]> git.ipfire.org Git - thirdparty/elfutils.git/commit
libdwfl_stacktrace [6/12]: Elf* caching via dwflst_process_tracker
authorSerhei Makarov <serhei@serhei.io>
Fri, 25 Apr 2025 14:55:48 +0000 (10:55 -0400)
committerAaron Merey <amerey@redhat.com>
Fri, 25 Apr 2025 15:54:55 +0000 (11:54 -0400)
commit13e02ced0edd954e1e9ad7135d96cb746a0192f7
treea1c7ed4e80433a20de63f1afd2aede117e0bbbd7
parent4d17ddf0864110150cfea484edba0f4f68489f9f
libdwfl_stacktrace [6/12]: Elf* caching via dwflst_process_tracker

The Dwflst_Process_Tracker includes a dynamicsizehash cache which maps
file paths to Elf * (or rather, dwflst_tracker_elf_info * storing fd
and Elf *).  We provide a dwflst_tracker_linux_proc_find_elf callback
which checks the cache for an already-loaded Elf * and, if missing,
populates the cache with the fd returned by dwfl_linux_proc_find_elf.

Later, open_elf updates the cache with the Elf * for that fd.  The
commented asserts in dwflst_tracker_cache_elf still catch some cases
where a redundant Elf * is being created without checking the cache.

Since the Elf * outlasts the Dwfl that created it, we use the
(convenient, already-existing) reference count field in Elf * to
retain the data in the table.  Then dwfl_end calling elf_end will
decrement the refcount cleanly, and dwflst_tracker_end will issue
another elf_end call.

* libdwfl_stacktrace/libdwfl_stacktrace.h
  (dwflst_tracker_find_cached_elf): New function.
  (dwflst_tracker_cache_elf): New function.
  (dwflst_module_gettracker): New function, gives external users
  a way to access Dwflst_Process_Tracker given a Dwfl_Module.
  (dwflst_tracker_linux_proc_find_elf): New function, serves as a
  cached version of the dwfl_linux_proc_find_elf callback.
* libdwfl_stacktrace/libdwfl_stacktraceP.h (dwflst_tracker_elf_info):
  New struct typedef.
  (struct Dwflst_Process_Tracker): Add dynamicsizehash table of
  dwflst_tracker_elf_info structs + associated rwlock.
  (INTDECLs): Add INTDECL for dwflst_tracker_find_cached_elf,
  dwflst_tracker_cache_elf, dwflst_module_gettracker.
* libdwfl_stacktrace/dwflst_tracker_elftab.c: New file, instantiates
  lib/dynamicsizehash_concurrent.c to store dwflst_tracker_elf_info
  structs.
* libdwfl_stacktrace/dwflst_tracker_elftab.h: New file, ditto.
* libdwfl_stacktrace/libdwfl_stacktrace_next_prime.c: New file.
* libdwfl_stacktrace/dwflst_process_tracker.c (dwflst_tracker_begin):
  Init elftab.
  (dwflst_tracker_end): Clean up elftab.  Lock and iterate the hash to
  free tracker->elftab.table items.
* libdwfl_stacktrace/dwflst_tracker_find_elf.c: New file, implements a
  find_elf callback that wraps dwfl_linux_proc_find_elf with
  additional caching logic, and an API to access the
  Dwflst_Process_Tracker Elf cache when implementing a custom find_elf
  callback.
* libdwfl_stacktrace/Makefile.am (libdwfl_stacktrace_a_SOURCES): Add
  dwflst_tracker_find_elf.c, dwflst_tracker_elftab.c,
  libdwfl_stacktrace_next_prime.c.
  (noinst_HEADERS): Add dwflst_tracker_elftab.h.
* libdw/libdw.map: Add dwflst_tracker_find_cached_elf,
  dwflst_tracker_cache_elf,
  dwflst_module_gettracker,
  dwflst_tracker_linux_proc_find_elf.
* libdwfl/Makefile.am (AM_CPPFLAGS): Include headers from
  ../libdwfl_stacktrace.
* libdwfl/dwfl_module_getdwarf.c (open_elf): Cache file->elf in
  Dwflst_Process_Tracker. Must be done here as
  dwfl_linux_proc_find_elf opens an fd but does not yet create the
  Elf *.

Signed-off-by: Serhei Makarov <serhei@serhei.io>
libdw/libdw.map
libdwfl/Makefile.am
libdwfl/dwfl_module_getdwarf.c
libdwfl_stacktrace/Makefile.am
libdwfl_stacktrace/dwflst_process_tracker.c
libdwfl_stacktrace/dwflst_tracker_elftab.c [new file with mode: 0644]
libdwfl_stacktrace/dwflst_tracker_elftab.h [new file with mode: 0644]
libdwfl_stacktrace/dwflst_tracker_find_elf.c [new file with mode: 0644]
libdwfl_stacktrace/libdwfl_stacktrace.h
libdwfl_stacktrace/libdwfl_stacktraceP.h
libdwfl_stacktrace/libdwfl_stacktrace_next_prime.c [new file with mode: 0644]