[v5,09/12] libdwfl_stacktrace [9/12]: add dwflst_tracker_find_pid

Message ID 20250424214715.306147-10-serhei@serhei.io
State Superseded
Headers
Series [v5,01/12] libebl [1/12]: api for perf register handling, start with x86_64 |

Commit Message

Serhei Makarov April 24, 2025, 9:47 p.m. UTC
  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(+)
  

Comments

Aaron Merey April 25, 2025, 6 a.m. UTC | #1
On Thu, Apr 24, 2025 at 5:49 PM Serhei Makarov <serhei@serhei.io> wrote:
>
> 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. */

Should this information be incorporated into the libdw_stacktrace.h
doc comment for dwflst_process_tracker?

> +    }
> +
> +  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.  */

I would mention what a return value of NULL means (ex. callback failed).

> +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
>

Aaron
  

Patch

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);