summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhei Makarov <[email protected]>2025-04-25 10:55:46 -0400
committerAaron Merey <[email protected]>2025-04-25 11:54:31 -0400
commit3ad7277b4163756f9d3fccd66df9576e3a5f8016 (patch)
treea7d972adfd4c20251ff989fd2a490e11960b3a7e
parentacb79d8a697bd572219d3aad1b12469b1c3e22a8 (diff)
libdwfl_stacktrace [4/12]: intro library, add dwflst_perf_sample_preferred_regs_mask
Subsequent patches in the series introduce a new library for tracking/caching Elf structs across multiple processes and wrapping the libebl perf register handling (since libebl is a private interface). In this patch, add the library and an interface to access the set of registers that libdwfl needs to allow proper unwinding of stack sample data. (Unwinding with a smaller set of registers can be attempted, but will yield a truncated call chain in most cases.) (Accessing the set of registers feels like an implementation detail, but the profiler invoking perf_event_open and elfutils unwinding code need to agree on the exact set of registers being requested. So it's best for the profiler to ask elfutils for this detail.) * libdwfl_stacktrace/Makefile.am: New file. * libdwfl_stacktrace/libdwfl_stacktrace.h: New file, library for tracking/caching Elf structs and unwinding across multiple processes. * libdwfl_stacktrace/libdwfl_stacktraceP.h: New file. * libdwfl_stacktrace/dwflst_perf_frame.c: New file. (dwflst_perf_sample_preferred_regs_mask): New function. * libdw/libdw.map: Add dwflst_perf_sample_preferred_regs_mask. * NEWS: Add NEWS item about libdwfl_stacktrace. * configure.ac: Add libdwfl_stacktrace/Makefile. * Makefile.am (SUBDIRS): Add libdwfl_stacktrace. * libdw/Makefile.am (libdw_so_LIBS): Add libdwfl_stacktrace. (libdwfl_stacktrace_objects): Add libdwfl_stacktrace.manifest. (libdw_a_LIBADD): Add libdwfl_stacktrace_objects. * config/elfutils.spec.in (%files devel): Add libdwfl_stacktrace.h. Signed-off-by: Serhei Makarov <[email protected]>
-rw-r--r--Makefile.am6
-rw-r--r--NEWS6
-rw-r--r--config/elfutils.spec.in1
-rw-r--r--configure.ac3
-rw-r--r--libdw/Makefile.am7
-rw-r--r--libdw/libdw.map6
-rw-r--r--libdwfl_stacktrace/Makefile.am63
-rw-r--r--libdwfl_stacktrace/dwflst_perf_frame.c63
-rw-r--r--libdwfl_stacktrace/libdwfl_stacktrace.h58
-rw-r--r--libdwfl_stacktrace/libdwfl_stacktraceP.h36
10 files changed, 244 insertions, 5 deletions
diff --git a/Makefile.am b/Makefile.am
index 3a181d75..76e98f60 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
## Process this file with automake to create Makefile.in
## Configure input file for elfutils.
##
-## Copyright (C) 1996-2006, 2008, 2009, 2015 Red Hat, Inc.
+## Copyright (C) 1996-2006, 2008, 2009, 2015, 2025 Red Hat, Inc.
##
## This file is part of elfutils.
##
@@ -28,8 +28,8 @@ AM_MAKEFLAGS = --no-print-directory
pkginclude_HEADERS = version.h
-SUBDIRS = config lib libelf libcpu backends libebl libdwelf libdwfl libdw \
- libasm debuginfod src po doc tests
+SUBDIRS = config lib libelf libcpu backends libebl libdwelf libdwfl \
+ libdwfl_stacktrace libdw libasm debuginfod src po doc tests
EXTRA_DIST = elfutils.spec GPG-KEY NOTES CONTRIBUTING SECURITY \
COPYING COPYING-GPLV2 COPYING-LGPLV3 CONDUCT
diff --git a/NEWS b/NEWS
index 664c125b..c3c611e3 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,12 @@ debuginfod: Add CORS (webapp access) support to webapi.
libdw: Add dwarf_language and dwarf_language_lower_bound functions.
+libdwfl_stacktrace: Experimental new library interface for unwinding
+ stack samples into call chains, and tracking and
+ caching Elf data for multiple processes, building
+ on libdwfl. Initially supports perf_events stack
+ sample data.
+
Version 0.192 "New rules, faster tools"
CONDUCT: A new code of conduct has been adopted. See the
diff --git a/config/elfutils.spec.in b/config/elfutils.spec.in
index 96934514..37077365 100644
--- a/config/elfutils.spec.in
+++ b/config/elfutils.spec.in
@@ -300,6 +300,7 @@ fi
#%%{_includedir}/elfutils/libasm.h
%{_includedir}/elfutils/libdw.h
%{_includedir}/elfutils/libdwfl.h
+%{_includedir}/elfutils/libdwfl_stacktrace.h
%{_includedir}/elfutils/libdwelf.h
%{_includedir}/elfutils/version.h
#%%{_libdir}/libasm.so
diff --git a/configure.ac b/configure.ac
index 27488e3f..92108b7f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -700,6 +700,9 @@ AC_CONFIG_FILES([libdw/Makefile])
dnl Higher-level DWARF support library.
AC_CONFIG_FILES([libdwfl/Makefile])
+dnl Higher-level DWARF stacktrace support library
+AC_CONFIG_FILES([libdwfl_stacktrace/Makefile])
+
dnl CPU handling library.
AC_CONFIG_FILES([libcpu/Makefile])
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 9dadc19b..f024d652 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -1,6 +1,6 @@
## Process this file with automake to create Makefile.in
##
-## Copyright (C) 2002-2010, 2012, 2014, 2016, 2018 Red Hat, Inc.
+## Copyright (C) 2002-2010, 2012, 2014, 2016, 2018, 2025 Red Hat, Inc.
## This file is part of elfutils.
##
## This file is free software; you can redistribute it and/or modify
@@ -107,7 +107,7 @@ am_libdw_pic_a_OBJECTS = $(libdw_a_SOURCES:.c=.os)
libdw_so_LIBS = ../libebl/libebl_pic.a ../backends/libebl_backends_pic.a \
../libcpu/libcpu_pic.a libdw_pic.a ../libdwelf/libdwelf_pic.a \
- ../libdwfl/libdwfl_pic.a
+ ../libdwfl/libdwfl_pic.a ../libdwfl_stacktrace/libdwfl_stacktrace_pic.a
libdw_so_DEPS = ../lib/libeu.a ../libelf/libelf.so
libdw_so_LDLIBS = $(libdw_so_DEPS) -ldl -lz $(argp_LDADD) $(fts_LIBS) $(obstack_LIBS) $(zip_LIBS) -pthread
libdw.so: $(srcdir)/libdw.map $(libdw_so_LIBS) $(libdw_so_DEPS)
@@ -135,6 +135,9 @@ uninstall: uninstall-am
libdwfl_objects = $(shell cat ../libdwfl/libdwfl.manifest)
libdw_a_LIBADD = $(addprefix ../libdwfl/,$(libdwfl_objects))
+libdwfl_stacktrace_objects = $(shell cat ../libdwfl_stacktrace/libdwfl_stacktrace.manifest)
+libdw_a_LIBADD += $(addprefix ../libdwfl_stacktrace/,$(libdwfl_stacktrace_objects))
+
libdwelf_objects = $(shell cat ../libdwelf/libdwelf.manifest)
libdw_a_LIBADD += $(addprefix ../libdwelf/,$(libdwelf_objects))
diff --git a/libdw/libdw.map b/libdw/libdw.map
index e7baf3c4..4f3fe6ba 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -391,3 +391,9 @@ ELFUTILS_0.193 {
dwarf_language;
dwarf_language_lower_bound;
} ELFUTILS_0.192;
+
+/* XXX Experimental libdwfl_stacktrace API. */
+ELFUTILS_0.193_EXPERIMENTAL {
+ global:
+ dwflst_perf_sample_preferred_regs_mask;
+};
diff --git a/libdwfl_stacktrace/Makefile.am b/libdwfl_stacktrace/Makefile.am
new file mode 100644
index 00000000..6364c292
--- /dev/null
+++ b/libdwfl_stacktrace/Makefile.am
@@ -0,0 +1,63 @@
+## Makefile.am for libdwfl_stacktrace library subdirectory in elfutils.
+##
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 2025 Red Hat, Inc.
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of either
+##
+## * the GNU Lesser General Public License as published by the Free
+## Software Foundation; either version 3 of the License, or (at
+## your option) any later version
+##
+## or
+##
+## * the GNU General Public License as published by the Free
+## Software Foundation; either version 2 of the License, or (at
+## your option) any later version
+##
+## or both in parallel, as here.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## General Public License for more details.
+##
+## You should have received copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program. If
+## not, see <http://www.gnu.org/licenses/>.
+##
+include $(top_srcdir)/config/eu.am
+AM_CPPFLAGS += -I$(srcdir) -I$(srcdir)/../libelf -I$(srcdir)/../libebl \
+ -I$(srcdir)/../libdw -I$(srcdir)/../libdwelf -I$(srcdir)/../libdwfl
+VERSION = 1
+
+noinst_LIBRARIES = libdwfl_stacktrace.a
+noinst_LIBRARIES += libdwfl_stacktrace_pic.a
+
+pkginclude_HEADERS = libdwfl_stacktrace.h
+
+
+libdwfl_stacktrace_a_SOURCES = dwflst_perf_frame.c
+
+libdwfl_stacktrace = $(libdw)
+libdw = ../libdw/libdw.so
+libelf = ../libelf/libelf.so
+libebl = ../libebl/libebl.a
+libeu = ../lib/libeu.a
+
+libdwfl_stacktrace_pic_a_SOURCES =
+am_libdwfl_stacktrace_pic_a_OBJECTS = $(libdwfl_stacktrace_a_SOURCES:.c=.os)
+
+noinst_HEADERS = libdwfl_stacktraceP.h
+
+EXTRA_libdwfl_stacktrace_a_DEPENDENCIES = libdwfl_stacktrace.manifest
+
+libdwfl_stacktrace.manifest: $(libdwfl_stacktrace_a_OBJECTS)
+ $(AM_V_GEN)echo $^ > $@
+
+MOSTLYCLEANFILES = $(am_libdwfl_stacktrace_a_OBJECTS) \
+ $(am_libdwfl_stacktrace_pic_a_OBJECTS)
+CLEANFILES = $(EXTRA_libdwfl_stacktrace_a_DEPENDENCIES)
diff --git a/libdwfl_stacktrace/dwflst_perf_frame.c b/libdwfl_stacktrace/dwflst_perf_frame.c
new file mode 100644
index 00000000..79e8e482
--- /dev/null
+++ b/libdwfl_stacktrace/dwflst_perf_frame.c
@@ -0,0 +1,63 @@
+/* Get Dwarf Frame state for perf stack sample data.
+ Copyright (C) 2025 Red Hat, Inc.
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if defined(__linux__)
+# include <linux/perf_event.h>
+#endif
+
+#include "libdwfl_stacktraceP.h"
+
+Ebl *default_ebl = NULL;
+GElf_Half default_ebl_machine = EM_NONE;
+
+uint64_t dwflst_perf_sample_preferred_regs_mask (GElf_Half machine)
+{
+ /* XXX The most likely case is that this will only be called once,
+ for the current architecture. So we keep one Ebl* around for
+ answering this query and replace it in the unlikely case of
+ getting called with different architectures. */
+ if (default_ebl != NULL && default_ebl_machine != machine)
+ {
+ ebl_closebackend(default_ebl);
+ default_ebl = NULL;
+ }
+ if (default_ebl == NULL)
+ {
+ default_ebl = ebl_openbackend_machine(machine);
+ default_ebl_machine = machine;
+ }
+ if (default_ebl != NULL)
+ return ebl_perf_frame_regs_mask (default_ebl);
+ return 0;
+}
+
+/* XXX dwflst_perf_sample_getframes to be added in subsequent patch */
diff --git a/libdwfl_stacktrace/libdwfl_stacktrace.h b/libdwfl_stacktrace/libdwfl_stacktrace.h
new file mode 100644
index 00000000..564f504a
--- /dev/null
+++ b/libdwfl_stacktrace/libdwfl_stacktrace.h
@@ -0,0 +1,58 @@
+/* Interfaces for libdwfl_stacktrace.
+
+ XXX: This is an experimental initial version of the API, and is
+ liable to change in future releases of elfutils, especially as
+ we figure out how to generalize the work to other sample data
+ formats in addition to perf_events.
+
+ Copyright (C) 2025 Red Hat, Inc.
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _LIBDWFL_STACKTRACE_H
+#define _LIBDWFL_STACKTRACE_H 1
+
+#include "libdwfl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* XXX dwflst_perf_sample_getframes to be added in subsequent patch */
+
+/* Returns the linux perf_events register mask describing a set of
+ registers sufficient for unwinding on MACHINE, or 0 if libdwfl does
+ not handle perf_events samples for MACHINE. Does not take a Dwfl*
+ or Elf* since this is meant to allow a profiling tool to configure
+ perf_events to produce meaningful data for a libdwfl session to be
+ opened later. */
+uint64_t dwflst_perf_sample_preferred_regs_mask (GElf_Half machine);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* libdwfl_stacktrace.h */
diff --git a/libdwfl_stacktrace/libdwfl_stacktraceP.h b/libdwfl_stacktrace/libdwfl_stacktraceP.h
new file mode 100644
index 00000000..fe6945fc
--- /dev/null
+++ b/libdwfl_stacktrace/libdwfl_stacktraceP.h
@@ -0,0 +1,36 @@
+/* Internal definitions for libdwfl_stacktrace.
+ Copyright (C) 2025 Red Hat, Inc.
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _LIBDWFL_STACKTRACEP_H
+#define _LIBDWFL_STACKTRACEP_H 1
+
+#include <libdwfl_stacktrace.h>
+
+#include "libdwflP.h"
+
+#endif /* libdwfl_stacktraceP.h */