On Thu, Apr 24, 2025 at 5:50 PM Serhei Makarov <ser...@serhei.io> wrote: > > Changes for v5: > > - Separate ELFUTILS_0.193_EXPERIMENTAL namespace, mark library experimental. > > Changes for v4: > > - Separate out libdwfl_stacktrace, as requested. > > Changes for v2: > > - guard the linux/perf_events.h include properly with an #if defined __linux__ > > * * * > > 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. > --- > Makefile.am | 6 +-- > NEWS | 6 +++ > config/elfutils.spec.in | 1 + > configure.ac | 3 ++ > libdw/Makefile.am | 7 ++- > libdw/libdw.map | 6 +++ > libdwfl_stacktrace/Makefile.am | 63 ++++++++++++++++++++++++ > libdwfl_stacktrace/dwflst_perf_frame.c | 63 ++++++++++++++++++++++++ > libdwfl_stacktrace/libdwfl_stacktrace.h | 58 ++++++++++++++++++++++ > libdwfl_stacktrace/libdwfl_stacktraceP.h | 36 ++++++++++++++ > 10 files changed, 244 insertions(+), 5 deletions(-) > create mode 100644 libdwfl_stacktrace/Makefile.am > create mode 100644 libdwfl_stacktrace/dwflst_perf_frame.c > create mode 100644 libdwfl_stacktrace/libdwfl_stacktrace.h > create mode 100644 libdwfl_stacktrace/libdwfl_stacktraceP.h > > 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 */ > -- > 2.47.0 >
Thanks for separating the new API into its own "experimental" namespace in libdw.map. libdwfl_stacktraceP.h cannot be installed and it isn't included by any public header. libdw.map, NEWS and libdwfl_stacktrace.h all clearly mention the experimental nature of the new API. LGTM. Aaron