From patchwork Tue Aug 17 01:06:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 44675 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 95F85395B833 for ; Tue, 17 Aug 2021 01:11:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 95F85395B833 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1629162699; bh=BMZjrrhAIJC3G0Zo2VL8TxxREXc+49C02z2NCl+8WUc=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=IC+IGcJqHE6pfhSYo5EkyadcLezawsy6yM2Rb7yVYaxvtBwGw5muuiIJVjRGp43ui dgXJmZzXqPvasN+v1F6hy1bkQLbgmtvwTn+ezQMkaZkJYoFskSz33zF+x5CMYhQ6mx 2R4igl78vU/Z5Zw0mOujhG8/AEF9Y45+SLBSmAzo= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com [IPv6:2607:f8b0:4864:20::102f]) by sourceware.org (Postfix) with ESMTPS id 0F0333844051; Tue, 17 Aug 2021 01:06:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 0F0333844051 Received: by mail-pj1-x102f.google.com with SMTP id j1so29279796pjv.3; Mon, 16 Aug 2021 18:06:32 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=BMZjrrhAIJC3G0Zo2VL8TxxREXc+49C02z2NCl+8WUc=; b=XdT/MPds/0jpPIx9g5bXaQO8gvrD6xntoF1C+iOxAIZexYs/Vi18/ehNZBeVV37uRE p+1iqxe+/E0SHy0XCc6Lzn2to51CByE2dwjhxCHI1UYoonwMwqJlgOUOLPXVEPOK2sdr GAI5lIw7rTSEM7MbTxrA7ZEewHhgxGE/Pf4ujSuNxTEfpO+W4sNtByc3yzvAALeGTIq4 AgDrAyYDVNI2aBhAG+IFpJIOTl2WlX0JPxcR2fwRQJ/tfSHLruMe8XX4wgENDjQf3Abr lj4GBCvFoe15611Bu410WRnDvc31GGMMiYDMNY+56JSgajAZYXCXvfqmpMzleYVHZrBe WQTw== X-Gm-Message-State: AOAM530dcI23fybJc86pXMvXqlynB0ExT2kiD1A+EEB+7CMWCJiRsRYy zUbV0+/WBfOmM9Gpp3lY+6Q= X-Google-Smtp-Source: ABdhPJykWWmH8c5ex2aZ76rJnd+aodkt23adQCORA1jf2RmMJ3BzXqtak0UTqAAeTWwLkd1JsN/XpQ== X-Received: by 2002:a65:67d8:: with SMTP id b24mr826013pgs.407.1629162391061; Mon, 16 Aug 2021 18:06:31 -0700 (PDT) Received: from gnu-cfl-2.localdomain ([172.58.38.240]) by smtp.gmail.com with ESMTPSA id y12sm357391pfa.25.2021.08.16.18.06.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Aug 2021 18:06:30 -0700 (PDT) Received: from gnu-cfl-2.. (localhost [IPv6:::1]) by gnu-cfl-2.localdomain (Postfix) with ESMTP id 35E85C0372; Mon, 16 Aug 2021 18:06:29 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v2 2/2] Extend struct r_debug to support multiple namespaces Date: Mon, 16 Aug 2021 18:06:29 -0700 Message-Id: <20210817010629.593479-3-hjl.tools@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210817010629.593479-1-hjl.tools@gmail.com> References: <20210817010629.593479-1-hjl.tools@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-3033.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "H.J. Lu via Libc-alpha" From: "H.J. Lu" Reply-To: "H.J. Lu" Cc: gdb@sourceware.org Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" Glibc does not provide an interface for debugger to access libraries loaded in multiple namespaces via dlmopen. The current rtld-debugger interface is described in the file: elf/rtld-debugger-interface.txt under the "Standard debugger interface" heading. This interface only provides access to the first link-map (LM_ID_BASE). Based on the patch from Conan C Huang : https://sourceware.org/pipermail/libc-alpha/2020-June/115448.html 1. Bump r_version to 2. This triggers the GDB bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28236 2. Add struct r_debug_extended to extend struct r_debug into a linked-list, where each element correlates to an unique namespace. 3. Add a hidden symbol, _r_debug_extended, for struct r_debug_extended. 4. Provide the compatibility symbol, _r_debug, with size of struct r_debug, as an alise of _r_debug_extended, for programs which reference _r_debug. --- csu/Makefile | 3 ++ csu/rtld-sizes.sym | 4 ++ elf/Makefile | 22 ++++++++++- elf/dl-close.c | 2 +- elf/dl-debug-symbols-gen.c | 24 +++++++++++ elf/dl-debug-symbols.S | 31 +++++++++++++++ elf/dl-debug.c | 29 +++++++------- elf/dl-load.c | 2 +- elf/dl-open.c | 2 +- elf/dl-reloc-static-pie.c | 2 +- elf/link.h | 70 +++++++++++++++++++++++++-------- elf/rtld-debugger-interface.txt | 14 +++++++ elf/rtld.c | 4 +- elf/tst-dlmopen4.c | 68 ++++++++++++++++++++++++++++++++ include/link.h | 4 ++ sysdeps/generic/ldsodefs.h | 5 ++- 16 files changed, 245 insertions(+), 41 deletions(-) create mode 100644 csu/rtld-sizes.sym create mode 100644 elf/dl-debug-symbols-gen.c create mode 100644 elf/dl-debug-symbols.S create mode 100644 elf/tst-dlmopen4.c diff --git a/csu/Makefile b/csu/Makefile index 3054329cea..e2390e4a7d 100644 --- a/csu/Makefile +++ b/csu/Makefile @@ -88,6 +88,9 @@ endif before-compile += $(objpfx)abi-tag.h generated += abi-tag.h +# Put it here to generate it earlier. +gen-as-const-headers += rtld-sizes.sym + # These are the special initializer/finalizer files. They are always the # first and last file in the link. crti.o ... crtn.o define the global # "functions" _init and _fini to run the .init and .fini sections. diff --git a/csu/rtld-sizes.sym b/csu/rtld-sizes.sym new file mode 100644 index 0000000000..40dd8edaec --- /dev/null +++ b/csu/rtld-sizes.sym @@ -0,0 +1,4 @@ +#include + +-- +COMPAT_R_DEBUG_SIZE sizeof (struct r_debug) diff --git a/elf/Makefile b/elf/Makefile index 725537c40b..1444a53405 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -35,7 +35,8 @@ dl-routines = $(addprefix dl-,load lookup object reloc deps \ execstack open close trampoline \ exception sort-maps lookup-direct \ call-libc-early-init write \ - thread_gscope_wait tls_init_tp) + thread_gscope_wait tls_init_tp \ + debug-symbols) ifeq (yes,$(use-ldconfig)) dl-routines += dl-cache endif @@ -203,7 +204,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ tst-tls16 tst-tls17 tst-tls18 tst-tls19 tst-tls-dlinfo \ tst-align tst-align2 \ tst-dlmodcount tst-dlopenrpath tst-deep1 \ - tst-dlmopen1 tst-dlmopen3 \ + tst-dlmopen1 tst-dlmopen3 tst-dlmopen4 \ unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \ tst-audit1 tst-audit2 tst-audit8 tst-audit9 \ tst-addr1 tst-thrlock \ @@ -672,6 +673,21 @@ LC_ALL=C sed $(ldd-rewrite) < $< \ endef endif +ifeq ($(build-shared),yes) +generated += dl-debug-compat-symbols.os dl-debug-compat-symbols.o + +libof-dl-debug-compat-symbols = rtld + +$(objpfx)dl-debug-compat-symbols.os: dl-debug-symbols-gen.c + $(compile-command.c) -S + +$(objpfx)dl-debug-compat-symbols.o: dl-debug-symbols-gen.c + $(compile-command.c) -S + +$(objpfx)dl-debug-symbols.os: $(objpfx)dl-debug-compat-symbols.os +$(objpfx)dl-debug-symbols.o: $(objpfx)dl-debug-compat-symbols.o +endif + $(objpfx)ldd: ldd.bash.in $(common-objpfx)soversions.mk \ $(common-objpfx)config.make $(gen-ldd) @@ -1242,6 +1258,8 @@ $(objpfx)tst-dlmopen2.out: $(objpfx)tst-dlmopen1mod.so $(objpfx)tst-dlmopen3.out: $(objpfx)tst-dlmopen1mod.so +$(objpfx)tst-dlmopen4.out: $(objpfx)tst-dlmopen1mod.so + $(objpfx)tst-audit1.out: $(objpfx)tst-auditmod1.so tst-audit1-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so diff --git a/elf/dl-close.c b/elf/dl-close.c index f39001cab9..f59ffdd666 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -500,7 +500,7 @@ _dl_close_worker (struct link_map *map, bool force) #endif /* Notify the debugger we are about to remove some loaded objects. */ - struct r_debug *r = _dl_debug_initialize (0, nsid); + struct r_debug_extended *r = _dl_debug_initialize (0, nsid); r->r_state = RT_DELETE; _dl_debug_state (); LIBC_PROBE (unmap_start, 2, nsid, r); diff --git a/elf/dl-debug-symbols-gen.c b/elf/dl-debug-symbols-gen.c new file mode 100644 index 0000000000..2406260bcb --- /dev/null +++ b/elf/dl-debug-symbols-gen.c @@ -0,0 +1,24 @@ +/* Generate the _r_debug_extended symbol used to communicate dynamic + linker state to the debugger at runtime. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +/* This structure communicates dl state to the debugger. The debugger + finds it via the DT_DEBUG entry in the dynamic section. */ +struct r_debug_extended _r_debug_extended; diff --git a/elf/dl-debug-symbols.S b/elf/dl-debug-symbols.S new file mode 100644 index 0000000000..0966b172ab --- /dev/null +++ b/elf/dl-debug-symbols.S @@ -0,0 +1,31 @@ +/* Define symbols used to communicate dynamic linker state to the + debugger at runtime. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +#ifdef SHARED +# include "dl-debug-compat-symbols.os" +#else +# include "dl-debug-compat-symbols.o" +#endif + +/* Define the compatibility symbol, _r_debug, with size of struct r_debug, + as an alias of _r_debug_extended. */ +declare_object_symbol_alias (_r_debug, _r_debug_extended, + COMPAT_R_DEBUG_SIZE); diff --git a/elf/dl-debug.c b/elf/dl-debug.c index 2cd5f09753..9e884a5648 100644 --- a/elf/dl-debug.c +++ b/elf/dl-debug.c @@ -30,34 +30,35 @@ extern const int verify_link_map_members[(VERIFY_MEMBER (l_addr) && VERIFY_MEMBER (l_prev)) ? 1 : -1]; -/* This structure communicates dl state to the debugger. The debugger - normally finds it via the DT_DEBUG entry in the dynamic section, but in - a statically-linked program there is no dynamic section for the debugger - to examine and it looks for this particular symbol name. */ -struct r_debug _r_debug; - - /* Initialize _r_debug if it has not already been done. The argument is the run-time load address of the dynamic linker, to be put in _r_debug.r_ldbase. Returns the address of _r_debug. */ -struct r_debug * +struct r_debug_extended * _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns) { - struct r_debug *r; + struct r_debug_extended *r, *rp; if (ns == LM_ID_BASE) - r = &_r_debug; + r = &_r_debug_extended; else - r = &GL(dl_ns)[ns]._ns_debug; + { + r = &GL(dl_ns)[ns]._ns_debug; + rp = &GL(dl_ns)[ns - 1]._ns_debug; + rp->r_next = r; + if (ns - 1 == LM_ID_BASE) + _r_debug_extended.r_next = r; + } if (r->r_map == NULL || ldbase != 0) { - /* Tell the debugger where to find the map of loaded objects. */ - r->r_version = 1 /* R_DEBUG_VERSION XXX */; - r->r_ldbase = ldbase ?: _r_debug.r_ldbase; + /* Tell the debugger where to find the map of loaded objects. + Bump r_version to 2 for the r_next field. */ + r->r_version = 2; + r->r_ldbase = ldbase ?: _r_debug_extended.r_ldbase; r->r_map = (void *) GL(dl_ns)[ns]._ns_loaded; r->r_brk = (ElfW(Addr)) &_dl_debug_state; + r->r_next = NULL; } return r; diff --git a/elf/dl-load.c b/elf/dl-load.c index 650e4edc35..cb0618b7fc 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -949,7 +949,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, /* Initialize to keep the compiler happy. */ const char *errstring = NULL; int errval = 0; - struct r_debug *r = _dl_debug_initialize (0, nsid); + struct r_debug_extended *r = _dl_debug_initialize (0, nsid); bool make_consistent = false; /* Get file information. To match the kernel behavior, do not fill diff --git a/elf/dl-open.c b/elf/dl-open.c index ec386626f9..e90287bc62 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -630,7 +630,7 @@ dl_open_worker (void *a) #endif /* Notify the debugger all new objects are now ready to go. */ - struct r_debug *r = _dl_debug_initialize (0, args->nsid); + struct r_debug_extended *r = _dl_debug_initialize (0, args->nsid); r->r_state = RT_CONSISTENT; _dl_debug_state (); LIBC_PROBE (map_complete, 3, args->nsid, r, new); diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c index d5bd2f31e9..b3016e1347 100644 --- a/elf/dl-reloc-static-pie.c +++ b/elf/dl-reloc-static-pie.c @@ -52,7 +52,7 @@ _dl_relocate_static_pie (void) main_map->l_relocated = 1; /* Initialize _r_debug. */ - struct r_debug *r = _dl_debug_initialize (0, LM_ID_BASE); + struct r_debug_extended *r = _dl_debug_initialize (0, LM_ID_BASE); r->r_state = RT_CONSISTENT; /* Set up debugging before the debugger is notified for the first diff --git a/elf/link.h b/elf/link.h index ff3a85c847..4c6391ff0b 100644 --- a/elf/link.h +++ b/elf/link.h @@ -34,14 +34,20 @@ #include /* Defines __ELF_NATIVE_CLASS. */ #include -/* Rendezvous structure used by the run-time dynamic linker to communicate - details of shared object loading to the debugger. If the executable's - dynamic section has a DT_DEBUG element, the run-time linker sets that - element's value to the address where this structure can be found. */ +enum r_debug_state + { + RT_CONSISTENT, /* Mapping change is complete. */ + RT_ADD, /* Beginning to add a new object. */ + RT_DELETE /* Beginning to remove an object mapping. */ + }; + +/* The legacy rendezvous structure used by the run-time dynamic linker to + communicate details of shared object loading to the debugger. */ struct r_debug { - int r_version; /* Version number for this protocol. */ + /* Version number for this protocol. It should be greater than 0. */ + int r_version; struct link_map *r_map; /* Head of the chain of loaded objects. */ @@ -51,28 +57,58 @@ struct r_debug The debugger can set a breakpoint at this address if it wants to notice shared object mapping changes. */ ElfW(Addr) r_brk; - enum - { - /* This state value describes the mapping change taking place when - the `r_brk' address is called. */ - RT_CONSISTENT, /* Mapping change is complete. */ - RT_ADD, /* Beginning to add a new object. */ - RT_DELETE /* Beginning to remove an object mapping. */ - } r_state; + /* This state value describes the mapping change taking place when + the `r_brk' address is called. */ + enum r_debug_state r_state; ElfW(Addr) r_ldbase; /* Base address the linker is loaded at. */ }; -/* This is the instance of that structure used by the dynamic linker. */ +/* This is the compatibility symbol of that structure provided by the + dynamic linker. Access to its fields beyond r_ldbase may be invalid. + */ extern struct r_debug _r_debug; +/* The extended rendezvous structure used by the run-time dynamic linker + to communicate details of shared object loading to the debugger. If + the executable's dynamic section has a DT_DEBUG element, the run-time + linker sets that element's value to the address where this structure + can be found. */ + +struct r_debug_extended + { + /* Version number for this protocol. It should be greater than 0. */ + int r_version; + + struct link_map *r_map; /* Head of the chain of loaded objects. */ + + /* This is the address of a function internal to the run-time linker, + that will always be called when the linker begins to map in a + library or unmap it, and again when the mapping change is complete. + The debugger can set a breakpoint at this address if it wants to + notice shared object mapping changes. */ + ElfW(Addr) r_brk; + /* This state value describes the mapping change taking place when + the `r_brk' address is called. */ + enum r_debug_state r_state; + + ElfW(Addr) r_ldbase; /* Base address the linker is loaded at. */ + + /* The following field is added by r_version == 2. */ + + /* Link to the next r_debug_extended structure. Each r_debug_extended + structure represents a different namespace. The first + r_debug_extended structure is for the default namespace. */ + struct r_debug_extended *r_next; + }; + /* This symbol refers to the "dynamic structure" in the `.dynamic' section of whatever module refers to `_DYNAMIC'. So, to find its own - `struct r_debug', a program could do: + `struct r_debug_extended', a program could do: for (dyn = _DYNAMIC; dyn->d_tag != DT_NULL; ++dyn) if (dyn->d_tag == DT_DEBUG) - r_debug = (struct r_debug *) dyn->d_un.d_ptr; - */ + r_debug_extended = (struct r_debug_extended *) dyn->d_un.d_ptr; + */ extern ElfW(Dyn) _DYNAMIC[]; /* Structure describing a loaded shared object. The `l_next' and `l_prev' diff --git a/elf/rtld-debugger-interface.txt b/elf/rtld-debugger-interface.txt index 61bc99e4b0..f6aaa28706 100644 --- a/elf/rtld-debugger-interface.txt +++ b/elf/rtld-debugger-interface.txt @@ -9,6 +9,9 @@ structure can be found. The r_debug structure contains (amongst others) the following fields: + int r_version: + Version number for this protocol. It should be greater than 0. + struct link_map *r_map: A linked list of loaded objects. @@ -32,6 +35,17 @@ but there is no way for the debugger to discover whether any of the objects in the link-map have been relocated or not. +Extension to the r_debug structure +================================== + +The r_debug_extended structure is an extension of the r_debug interface. +If r_version is 2, one additional field is available: + + struct r_debug_extended *r_next; + Link to the next r_debug_extended structure. Each r_debug_extended + structure represents a different namespace. The first r_debug_extended + structure is for the default namespace. + Probe-based debugger interface ============================== diff --git a/elf/rtld.c b/elf/rtld.c index 878e6480f4..6205dda3be 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -1661,8 +1661,8 @@ dl_main (const ElfW(Phdr) *phdr, call_init_paths (&state); /* Initialize _r_debug. */ - struct r_debug *r = _dl_debug_initialize (GL(dl_rtld_map).l_addr, - LM_ID_BASE); + struct r_debug_extended *r + = _dl_debug_initialize (GL(dl_rtld_map).l_addr, LM_ID_BASE); r->r_state = RT_CONSISTENT; /* Put the link_map for ourselves on the chain so it can be found by diff --git a/elf/tst-dlmopen4.c b/elf/tst-dlmopen4.c new file mode 100644 index 0000000000..40d94aec31 --- /dev/null +++ b/elf/tst-dlmopen4.c @@ -0,0 +1,68 @@ +/* Test struct r_debug_extended via DT_DEBUG and DT_DEBUGSZ. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef ELF_MACHINE_GET_R_DEBUG +# define ELF_MACHINE_GET_R_DEBUG(d) \ + (__extension__ ({ \ + struct r_debug_extended *debug; \ + if ((d)->d_tag == DT_DEBUG) \ + debug = (struct r_debug_extended *) (d)->d_un.d_ptr; \ + else \ + debug = NULL; \ + debug; })) +#endif + +static int +do_test (void) +{ + void *h = xdlmopen (LM_ID_NEWLM, "$ORIGIN/tst-dlmopen1mod.so", + RTLD_LAZY); + + int status = EXIT_FAILURE; + ElfW(Dyn) *d; + for (d = _DYNAMIC; d->d_tag != DT_NULL; ++d) + { + struct r_debug_extended *debug = ELF_MACHINE_GET_R_DEBUG (d); + if (debug != NULL) + { + TEST_VERIFY_EXIT (debug->r_version == 2); + TEST_VERIFY_EXIT (debug->r_next != NULL); + TEST_VERIFY_EXIT (debug->r_next->r_next == NULL); + TEST_VERIFY_EXIT (debug->r_next->r_map != NULL); + TEST_VERIFY_EXIT (debug->r_next->r_map->l_name != NULL); + const char *name = basename (debug->r_next->r_map->l_name); + TEST_VERIFY_EXIT (strcmp (name, "tst-dlmopen1mod.so") == 0); + status = EXIT_SUCCESS; + } + } + + xdlclose (h); + + return status; +} + +#include diff --git a/include/link.h b/include/link.h index 4af16cb596..7b8250db36 100644 --- a/include/link.h +++ b/include/link.h @@ -353,6 +353,10 @@ struct auditstate }; +/* This is the hidden instance of struct r_debug_extended used by the + dynamic linker. */ +extern struct r_debug_extended _r_debug_extended attribute_hidden; + #if __ELF_NATIVE_CLASS == 32 # define symbind symbind32 #elif __ELF_NATIVE_CLASS == 64 diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 9c15259236..a37b3fec82 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -355,7 +355,7 @@ struct rtld_global void (*free) (void *); } _ns_unique_sym_table; /* Keep track of changes to each namespace' list. */ - struct r_debug _ns_debug; + struct r_debug_extended _ns_debug; } _dl_ns[DL_NNS]; /* One higher than index of last used namespace. */ EXTERN size_t _dl_nns; @@ -1096,7 +1096,8 @@ rtld_hidden_proto (_dl_debug_state) /* Initialize `struct r_debug' if it has not already been done. The argument is the run-time load address of the dynamic linker, to be put in the `r_ldbase' member. Returns the address of the structure. */ -extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns) +extern struct r_debug_extended *_dl_debug_initialize (ElfW(Addr) ldbase, + Lmid_t ns) attribute_hidden; /* Initialize the basic data structure for the search paths. SOURCE