Changes for v4:

- Separate out libdwfl_stacktrace, as requested.

Changes for v2:

- Add locking for dwfltab.

* * *

New function that retrieves the Dwfl for a particular PID, or,
if the Dwfl is absent, creates it via a provided callback
and adds it to the table later, when the PID is confirmed
via dwfl_attach_state.

* libdwfl_stacktrace/libdwfl_stacktrace.h (dwflst_tracker_find_pid):
  New function.
* libdwfl_stacktrace/dwfl_process_tracker.c (dwflst_tracker_find_pid):
  New function; find a Dwfl in the dwfltab or create one using the
  provided callback.  The newly created Dwfl will be added to the
  dwfltab automatically when its pid is confirmed by a call to
  dwfl_attach_state.
* libdw/libdw.map: Add dwflst_tracker_find_pid.
---
 libdw/libdw.map                             |  1 +
 libdwfl_stacktrace/dwflst_process_tracker.c | 26 +++++++++++++++++++++
 libdwfl_stacktrace/libdwfl_stacktrace.h     | 11 +++++++++
 3 files changed, 38 insertions(+)

diff --git a/libdw/libdw.map b/libdw/libdw.map
index 46d0878a..688e415c 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -404,4 +404,5 @@ ELFUTILS_0.193_EXPERIMENTAL {
     dwflst_tracker_cache_elf;
     dwflst_module_gettracker;
     dwflst_tracker_linux_proc_find_elf;
+    dwflst_tracker_find_pid;
 };
diff --git a/libdwfl_stacktrace/dwflst_process_tracker.c 
b/libdwfl_stacktrace/dwflst_process_tracker.c
index f72b72b0..fc019b23 100644
--- a/libdwfl_stacktrace/dwflst_process_tracker.c
+++ b/libdwfl_stacktrace/dwflst_process_tracker.c
@@ -67,6 +67,32 @@ Dwfl *dwflst_tracker_dwfl_begin (Dwflst_Process_Tracker 
*tracker)
   return dwfl;
 }
 
+Dwfl *dwflst_tracker_find_pid (Dwflst_Process_Tracker *tracker,
+                              pid_t pid,
+                              Dwfl *(*callback) (Dwflst_Process_Tracker *,
+                                                 pid_t, void *),
+                              void *arg)
+{
+  Dwfl *dwfl = NULL;
+
+  rwlock_rdlock (tracker->dwfltab_lock);
+  dwflst_tracker_dwfl_info *ent
+    = dwflst_tracker_dwfltab_find(&tracker->dwfltab, pid);
+  rwlock_unlock (tracker->dwfltab_lock);
+
+  if (ent != NULL && !ent->invalid)
+    dwfl = ent->dwfl;
+  if (dwfl == NULL && callback != NULL)
+    dwfl = callback(tracker, pid, arg);
+  if (dwfl != NULL)
+    {
+      assert (dwfl->tracker == tracker);
+      /* XXX: dwfl added to dwfltab when dwfl->process set in 
dwfl_attach_state.
+         Prior to that, the pid is not confirmed. */
+    }
+
+  return dwfl;
+}
 
 void
 internal_function
diff --git a/libdwfl_stacktrace/libdwfl_stacktrace.h 
b/libdwfl_stacktrace/libdwfl_stacktrace.h
index d29dc640..ed6a6a5c 100644
--- a/libdwfl_stacktrace/libdwfl_stacktrace.h
+++ b/libdwfl_stacktrace/libdwfl_stacktrace.h
@@ -79,6 +79,17 @@ extern bool dwflst_tracker_cache_elf (Dwflst_Process_Tracker 
*tracker,
                                      Elf *elf, int fd)
   __nonnull_attribute__ (1, 2);
 
+/* Find the Dwfl corresponding to PID.  If CALLBACK is non-NULL and
+   the Dwfl has not been created, invoke CALLBACK to create the Dwfl
+   and then store it in the tracker.  */
+extern Dwfl *dwflst_tracker_find_pid (Dwflst_Process_Tracker *tracker,
+                                     pid_t pid,
+                                     Dwfl *(*callback) (Dwflst_Process_Tracker 
*tracker,
+                                                        pid_t pid,
+                                                        void *arg),
+                                     void *arg)
+  __nonnull_attribute__ (1);
+
 /* For implementing a find_elf callback based on the prior two functions.
    Returns the Dwflst_Process_Tracker corresponding to MOD.  */
 extern Dwflst_Process_Tracker *dwflst_module_gettracker (Dwfl_Module *mod);
-- 
2.47.0

Reply via email to