]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdwfl: introduce Dwfl_Process_Tracker
authorSerhei Makarov <serhei@serhei.io>
Mon, 20 Jan 2025 21:38:42 +0000 (16:38 -0500)
committerSerhei Makarov <serhei@serhei.io>
Tue, 28 Jan 2025 17:30:50 +0000 (12:30 -0500)
New data structure to coordinate caching Elf data among multiple Dwfl
structs attached to different processes. Meant to reduce the overhead
for profilers that use elfutils for unwinding.

The caching is well-justified, as the current approach (e.g. in
eu-stacktrace, sysprof-live-unwinder) of creating a separate Dwfl per
process

Initial patch just introduces the struct, to be filled in by the rest
of the patch series.

* libdwfl/libdwfl.h (Dwfl_Process_Tracker): New struct.
  (dwfl_process_tracker_begin): New function.
  (dwfl_begin_with_tracker): New function.
  (dwfl_process_tracker_end): New function.
* libdw/libdw.map: Add new functions.
* libdwfl/libdwflP.h (struct Dwfl_Process_Tracker): New struct.
  (struct Dwfl): Add 'tracker' field.
* libdwfl/Makefile.am (libdwfl_a_SOURCES): Add dwfl_process_tracker.c.
* libdwfl/dwfl_process_tracker.c: New file.
  (dwfl_process_tracker_begin): Initialize the tracker.
  (dwfl_begin_with_tracker): Initialize Dwfl * with specified tracker.
  (dwfl_process_tracker_end): Deallocate the tracker.

libdw/libdw.map
libdwfl/Makefile.am
libdwfl/dwfl_process_tracker.c [new file with mode: 0644]
libdwfl/libdwfl.h
libdwfl/libdwflP.h

index bc53385f61a698a4c6e5212d699512ae7c734330..47bad5f4e9874d119ecdd4bf5ee441e0c700cb27 100644 (file)
@@ -385,3 +385,10 @@ ELFUTILS_0.192 {
     dwfl_frame_unwound_source;
     dwfl_unwound_source_str;
 } ELFUTILS_0.191;
+
+ELFUTILS_0.193 {
+  global:
+    dwfl_process_tracker_begin;
+    dwfl_begin_with_tracker;
+    dwfl_process_tracker_end;
+} ELFUTILS_0.192;
index 57c89604cd07fd9cfbbfca7a02c6ea132aa80290..7221a3d7214ea871a8f72c7219aab67d4995e9d4 100644 (file)
@@ -71,6 +71,7 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c dwfl_version.c \
                    link_map.c core-file.c open.c image-header.c \
                    dwfl_frame.c frame_unwind.c dwfl_frame_pc.c \
                    linux-pid-attach.c linux-core-attach.c dwfl_frame_regs.c \
+                   dwfl_process_tracker.c \
                    gzip.c debuginfod-client.c
 
 if BZLIB
diff --git a/libdwfl/dwfl_process_tracker.c b/libdwfl/dwfl_process_tracker.c
new file mode 100644 (file)
index 0000000..a66bcac
--- /dev/null
@@ -0,0 +1,66 @@
+/* Track multiple Dwfl structs for multiple processes.
+   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
+
+#include "libdwflP.h"
+
+Dwfl_Process_Tracker *dwfl_process_tracker_begin (const Dwfl_Callbacks *callbacks)
+{
+  Dwfl_Process_Tracker *tracker = calloc (1, sizeof *tracker);
+  if (tracker == NULL)
+    {
+      __libdwfl_seterrno (DWFL_E_NOMEM);
+      return tracker;
+    }
+
+  tracker->callbacks = callbacks;
+  return tracker;
+}
+
+Dwfl *dwfl_begin_with_tracker (Dwfl_Process_Tracker *tracker)
+{
+  Dwfl *dwfl = dwfl_begin (tracker->callbacks);
+  if (dwfl == NULL)
+    return dwfl;
+
+  /* TODO: Could also share dwfl->debuginfod, but thead-safely? */
+  dwfl->tracker = tracker;
+  return dwfl;
+}
+
+void dwfl_process_tracker_end (Dwfl_Process_Tracker *tracker)
+{
+  if (tracker == NULL)
+    return;
+
+  /* TODO: Call dwfl_end for each Dwfl connected to this tracker. */
+  free (tracker);
+}
index 90523283c9359b09a16709a8422917a44257932f..4ba68cc289d252852c5659a983f41be13aa64e04 100644 (file)
 #include "libdw.h"
 #include <stdio.h>
 
-/* Handle for a session using the library.  */
+/* Handle for a session using the library to attach to a single target process.  */
 typedef struct Dwfl Dwfl;
 
+/* Handle for a session using the library to attach to more than one process.  */
+typedef struct Dwfl_Process_Tracker Dwfl_Process_Tracker;
+
 /* Handle for a module.  */
 typedef struct Dwfl_Module Dwfl_Module;
 
@@ -122,6 +125,18 @@ extern int dwfl_errno (void);
 extern const char *dwfl_errmsg (int err);
 
 
+/* Start a new multi-process session with the library.  */
+extern Dwfl_Process_Tracker *dwfl_process_tracker_begin (const Dwfl_Callbacks *callbacks)
+  __nonnull_attribute__ (1);
+
+/* Create a new Dwfl within a multi-process session.  */
+extern Dwfl *dwfl_begin_with_tracker (Dwfl_Process_Tracker *tracker)
+  __nonnull_attribute__ (1);
+
+/* End a multi-process session.  */
+extern void dwfl_process_tracker_end (Dwfl_Process_Tracker *tracker);
+
+
 /* Start reporting the current set of segments and modules to the library.
    All existing segments are wiped.  Existing modules are marked to be
    deleted, and will not be found via dwfl_addrmodule et al if they are not
index 6ec5c96643a9c2265a48e2329b94632d816081d5..9bcfea6c77c493fb03e908412dd261bbb142b2c2 100644 (file)
@@ -101,6 +101,12 @@ typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
 extern int __libdwfl_canon_error (Dwfl_Error) internal_function;
 extern void __libdwfl_seterrno (Dwfl_Error) internal_function;
 
+struct Dwfl_Process_Tracker
+{
+  const Dwfl_Callbacks *callbacks;
+  /* ... */
+};
+
 /* Resources we might keep for the user about the core file that the
    Dwfl might have been created from.  Can currently only be set
    through std-argp.  */
@@ -114,6 +120,7 @@ struct Dwfl_User_Core
 struct Dwfl
 {
   const Dwfl_Callbacks *callbacks;
+  Dwfl_Process_Tracker *tracker;
 #ifdef ENABLE_LIBDEBUGINFOD
   debuginfod_client *debuginfod;
 #endif