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/libdwfl.h (dwfl_process_tracker_find_pid): New function.
* libdwfl/dwfl_process_tracker.h (dwfl_process_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 dwfl_process_tracker_find_pid.
---
libdw/libdw.map | 1 +
libdwfl/dwfl_process_tracker.c | 26 ++++++++++++++++++++++++++
libdwfl/libdwfl.h | 11 +++++++++++
3 files changed, 38 insertions(+)
diff --git a/libdw/libdw.map b/libdw/libdw.map
index a52d1b87..99fd9105 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -393,4 +393,5 @@ ELFUTILS_0.193 {
dwfl_begin_with_tracker;
dwfl_process_tracker_end;
dwfl_process_tracker_find_elf;
+ dwfl_process_tracker_find_pid;
} ELFUTILS_0.192;
diff --git a/libdwfl/dwfl_process_tracker.c b/libdwfl/dwfl_process_tracker.c
index dd93f16e..caf6a8ff 100644
--- a/libdwfl/dwfl_process_tracker.c
+++ b/libdwfl/dwfl_process_tracker.c
@@ -67,6 +67,32 @@ Dwfl *dwfl_begin_with_tracker (Dwfl_Process_Tracker *tracker)
return dwfl;
}
+Dwfl *dwfl_process_tracker_find_pid (Dwfl_Process_Tracker *tracker,
+ pid_t pid,
+ Dwfl *(*callback) (Dwfl_Process_Tracker *,
+ pid_t, void *),
+ void *arg)
+{
+ Dwfl *dwfl = NULL;
+
+ rwlock_rdlock (tracker->dwfltab_lock);
+ dwfltracker_dwfl_info *ent = dwfltracker_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 __libdwfl_add_dwfl_to_tracker (Dwfl *dwfl) {
Dwfl_Process_Tracker *tracker = dwfl->tracker;
assert (tracker != NULL);
diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h
index a4408a26..64b3ee82 100644
--- a/libdwfl/libdwfl.h
+++ b/libdwfl/libdwfl.h
@@ -133,6 +133,17 @@ extern Dwfl_Process_Tracker *dwfl_process_tracker_begin
(const Dwfl_Callbacks *c
extern Dwfl *dwfl_begin_with_tracker (Dwfl_Process_Tracker *tracker)
__nonnull_attribute__ (1);
+/* 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 *dwfl_process_tracker_find_pid (Dwfl_Process_Tracker *tracker,
+ pid_t pid,
+ Dwfl *(*callback)
(Dwfl_Process_Tracker *tracker,
+ pid_t pid,
+ void *arg),
+ void *arg)
+ __nonnull_attribute__ (1);
+
/* End a multi-process session. */
extern void dwfl_process_tracker_end (Dwfl_Process_Tracker *tracker);
--
2.47.0