[PATCH v8 2/3] elf: Introduce _dl_debug_change_state
H.J. Lu
hjl.tools@gmail.com
Fri Jul 4 20:34:54 GMT 2025
On Sat, Jul 5, 2025 at 3:47 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> It combines updating r_state with the debugger notification.
>
> The second change to _dl_open introduces an additional debugger
> notification for dlmopen, but debuggers are expected to ignore it.
> ---
> elf/dl-close.c | 6 ++----
> elf/dl-debug.c | 7 +++++++
> elf/dl-load.c | 3 +--
> elf/dl-open.c | 5 ++---
> elf/rtld.c | 6 ++----
> sysdeps/generic/ldsodefs.h | 14 ++++++++++++--
> 6 files changed, 26 insertions(+), 15 deletions(-)
>
> diff --git a/elf/dl-close.c b/elf/dl-close.c
> index 47bd3dab81..83e4f012b2 100644
> --- a/elf/dl-close.c
> +++ b/elf/dl-close.c
> @@ -433,8 +433,7 @@ _dl_close_worker (struct link_map *map, bool force)
> /* Notify the debugger we are about to remove some loaded objects.
> LA_ACT_DELETE has already been signalled above for !unload_any. */
> struct r_debug *r = _dl_debug_update (nsid);
> - r->r_state = RT_DELETE;
> - _dl_debug_state ();
> + _dl_debug_change_state (r, RT_DELETE);
> LIBC_PROBE (unmap_start, 2, nsid, r);
>
> if (unload_global)
> @@ -726,8 +725,7 @@ _dl_close_worker (struct link_map *map, bool force)
> __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
>
> /* Notify the debugger those objects are finalized and gone. */
> - r->r_state = RT_CONSISTENT;
> - _dl_debug_state ();
> + _dl_debug_change_state (r, RT_CONSISTENT);
> LIBC_PROBE (unmap_complete, 2, nsid, r);
>
> #ifdef SHARED
> diff --git a/elf/dl-debug.c b/elf/dl-debug.c
> index 09624eae9c..b033723679 100644
> --- a/elf/dl-debug.c
> +++ b/elf/dl-debug.c
> @@ -67,6 +67,13 @@ _dl_debug_update (Lmid_t ns)
> return &r->base;
> }
>
> +void
> +_dl_debug_change_state (struct r_debug *r, int state)
> +{
> + atomic_store_release (&r->r_state, state);
> + _dl_debug_state ();
> +}
> +
> /* Initialize _r_debug_extended for the namespace NS. LDBASE is the
> run-time load address of the dynamic linker, to be put in
> _r_debug_extended.r_ldbase. Return the address of _r_debug. */
> diff --git a/elf/dl-load.c b/elf/dl-load.c
> index 6e26ef0583..00b9da9ec7 100644
> --- a/elf/dl-load.c
> +++ b/elf/dl-load.c
> @@ -921,8 +921,7 @@ _dl_notify_new_object (int mode, Lmid_t nsid, struct link_map *l)
> /* Notify the debugger we have added some objects. We need to
> call _dl_debug_initialize in a static program in case dynamic
> linking has not been used before. */
> - r->r_state = RT_ADD;
> - _dl_debug_state ();
> + _dl_debug_change_state (r, RT_ADD);
> LIBC_PROBE (map_start, 2, nsid, r);
> }
> else
> diff --git a/elf/dl-open.c b/elf/dl-open.c
> index f6227bdfd6..5526065352 100644
> --- a/elf/dl-open.c
> +++ b/elf/dl-open.c
> @@ -772,8 +772,7 @@ dl_open_worker (void *a)
> #ifdef SHARED
> bool was_not_consistent = r->r_state != RT_CONSISTENT;
> #endif
> - r->r_state = RT_CONSISTENT;
> - _dl_debug_state ();
> + _dl_debug_change_state (r, RT_CONSISTENT);
> LIBC_PROBE (map_complete, 3, nsid, r, args->map);
>
> #ifdef SHARED
> @@ -842,7 +841,7 @@ no more namespaces available for dlmopen()"));
> }
>
> GL(dl_ns)[nsid].libc_map = NULL;
> - _dl_debug_update (nsid)->r_state = RT_CONSISTENT;
> + _dl_debug_change_state (_dl_debug_update (nsid), RT_CONSISTENT);
> }
> /* Never allow loading a DSO in a namespace which is empty. Such
> direct placements is only causing problems. Also don't allow
> diff --git a/elf/rtld.c b/elf/rtld.c
> index 9038a50799..eec11bf790 100644
> --- a/elf/rtld.c
> +++ b/elf/rtld.c
> @@ -1778,8 +1778,7 @@ dl_main (const ElfW(Phdr) *phdr,
> elf_setup_debug_entry (main_map, r);
>
> /* We start adding objects. */
> - r->r_state = RT_ADD;
> - _dl_debug_state ();
> + _dl_debug_change_state (r, RT_ADD);
> LIBC_PROBE (init_start, 2, LM_ID_BASE, r);
>
> /* Auditing checkpoint: we are ready to signal that the initial map
> @@ -2334,8 +2333,7 @@ dl_main (const ElfW(Phdr) *phdr,
> /* Notify the debugger all new objects are now ready to go. We must re-get
> the address since by now the variable might be in another object. */
> r = _dl_debug_update (LM_ID_BASE);
> - r->r_state = RT_CONSISTENT;
> - _dl_debug_state ();
> + _dl_debug_change_state (r, RT_CONSISTENT);
> LIBC_PROBE (init_complete, 2, LM_ID_BASE, r);
>
> /* Auditing checkpoint: we have added all objects. */
> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
> index 528c80e2e0..74931fec25 100644
> --- a/sysdeps/generic/ldsodefs.h
> +++ b/sysdeps/generic/ldsodefs.h
> @@ -1087,8 +1087,14 @@ extern void _dl_debug_state (void);
> rtld_hidden_proto (_dl_debug_state)
>
> /* Initialize `struct r_debug_extended' for the namespace NS. LDBASE
> - is the run-time load address of the dynamic linker, to be put in the
> - `r_ldbase' member. Return the address of the structure. */
> + is the run-time load address of the dynamic linker, to be put in
> + the `r_ldbase' member.
> +
> + Return the address of the r_debug structure for the namespace.
> + This is not merely a convenience or optimization, but it is
> + necessary for the LIBC_PROBE Systemtap/debugger probes to work
> + reliably: direct variable access can create probes that tools
> + cannot consume. */
> extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
> attribute_hidden;
>
> @@ -1096,6 +1102,10 @@ extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
> of the namespace NS. */
> extern struct r_debug *_dl_debug_update (Lmid_t ns) attribute_hidden;
>
> +/* Update R->r_state to STATE and notify the debugger by calling
> + _dl_debug_state. */
> +void _dl_debug_change_state (struct r_debug *r, int state) attribute_hidden;
> +
> /* Initialize the basic data structure for the search paths. SOURCE
> is either "LD_LIBRARY_PATH" or "--library-path".
> GLIBC_HWCAPS_PREPEND adds additional glibc-hwcaps subdirectories to
> --
> 2.50.0
>
>
LGTM.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Thanks.
--
H.J.
More information about the Libc-alpha
mailing list