public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] Extend struct r_debug to support multiple namespaces
@ 2021-08-17  1:06 H.J. Lu
  2021-08-17  1:06 ` [PATCH v2 1/2] Add declare_object_symbol_alias for assembly codes [BZ #28128] H.J. Lu
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: H.J. Lu @ 2021-08-17  1:06 UTC (permalink / raw)
  To: libc-alpha; +Cc: gdb, Daniel Walker

Changes in the v2 patch.

1. Bump r_version to 2.
2. Don't add DT_DEBUGSZ.
3. Add struct r_debug_extended to extend struct r_debug.
4. Don't update the r_state field in the copy of _r_debug in executable
since it is not consumed by the program.

---
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 <conhuang@cisco.com>:

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.

H.J. Lu (2):
  Add declare_object_symbol_alias for assembly codes [BZ #28128]
  Extend struct r_debug to support multiple namespaces

 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/libc-symbols.h          | 12 +++---
 include/link.h                  |  4 ++
 sysdeps/generic/ldsodefs.h      |  5 ++-
 17 files changed, 252 insertions(+), 46 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

-- 
2.31.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v2 1/2] Add declare_object_symbol_alias for assembly codes [BZ #28128]
  2021-08-17  1:06 [PATCH v2 0/2] Extend struct r_debug to support multiple namespaces H.J. Lu
@ 2021-08-17  1:06 ` H.J. Lu
  2021-08-17  1:06 ` [PATCH v2 2/2] Extend struct r_debug to support multiple namespaces H.J. Lu
  2021-08-17 17:57 ` [PATCH v2 0/2] " Joseph Myers
  2 siblings, 0 replies; 12+ messages in thread
From: H.J. Lu @ 2021-08-17  1:06 UTC (permalink / raw)
  To: libc-alpha; +Cc: gdb, Daniel Walker

There are 2 problems in:

 #define declare_symbol_alias(symbol, original, type, size) \
  declare_symbol_alias_1 (symbol, original, type, size)
 #ifdef __ASSEMBLER__
 # define declare_symbol_alias_1(symbol, original, type, size) \
   strong_alias (original, symbol); \
   .type C_SYMBOL_NAME (symbol), %##type; \
   .size C_SYMBOL_NAME (symbol), size

1. .type and .size are substituted by arguments.
2. %##type is expanded to "% type" due to the GCC bug:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101613

But assembler doesn't support "% type".

Workaround BZ #28128 by

1. Don't define declare_symbol_alias for assembly codes.
2. Define declare_object_symbol_alias for assembly codes.
---
 include/libc-symbols.h | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/include/libc-symbols.h b/include/libc-symbols.h
index d41ecf4384..1678071d77 100644
--- a/include/libc-symbols.h
+++ b/include/libc-symbols.h
@@ -324,14 +324,16 @@ for linking")
    This is only necessary when defining something in assembly, or playing
    funny alias games where the size should be other than what the compiler
    thinks it is.  */
-#define declare_symbol_alias(symbol, original, type, size) \
-  declare_symbol_alias_1 (symbol, original, type, size)
 #ifdef __ASSEMBLER__
-# define declare_symbol_alias_1(symbol, original, type, size) \
+# define declare_object_symbol_alias(symbol, original, size) \
+  declare_object_symbol_alias_1 (symbol, original, size)
+# define declare_object_symbol_alias_1(symbol, original, s_size) \
    strong_alias (original, symbol); \
-   .type C_SYMBOL_NAME (symbol), %##type; \
-   .size C_SYMBOL_NAME (symbol), size
+   .type C_SYMBOL_NAME (symbol), %object; \
+   .size C_SYMBOL_NAME (symbol), s_size
 #else /* Not __ASSEMBLER__.  */
+# define declare_symbol_alias(symbol, original, type, size) \
+  declare_symbol_alias_1 (symbol, original, type, size)
 # define declare_symbol_alias_1(symbol, original, type, size) \
    asm (".globl " __SYMBOL_PREFIX #symbol \
 	"\n\t" declare_symbol_alias_1_alias (symbol, original) \
-- 
2.31.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v2 2/2] Extend struct r_debug to support multiple namespaces
  2021-08-17  1:06 [PATCH v2 0/2] Extend struct r_debug to support multiple namespaces H.J. Lu
  2021-08-17  1:06 ` [PATCH v2 1/2] Add declare_object_symbol_alias for assembly codes [BZ #28128] H.J. Lu
@ 2021-08-17  1:06 ` H.J. Lu
  2021-08-17 17:44   ` Daniel Walker
  2021-08-17 17:57   ` Daniel Walker
  2021-08-17 17:57 ` [PATCH v2 0/2] " Joseph Myers
  2 siblings, 2 replies; 12+ messages in thread
From: H.J. Lu @ 2021-08-17  1:06 UTC (permalink / raw)
  To: libc-alpha; +Cc: gdb, Daniel Walker

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 <conhuang@cisco.com>:

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 <link.h>
+
+--
+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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <link.h>
+
+/* 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <rtld-sizes.h>
+
+#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 <bits/elfclass.h>		/* Defines __ELF_NATIVE_CLASS.  */
 #include <bits/link.h>
 
-/* 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <link.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gnu/lib-names.h>
+#include <support/xdlfcn.h>
+#include <support/check.h>
+#include <support/test-driver.h>
+
+#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 <support/test-driver.c>
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
-- 
2.31.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 2/2] Extend struct r_debug to support multiple namespaces
  2021-08-17  1:06 ` [PATCH v2 2/2] Extend struct r_debug to support multiple namespaces H.J. Lu
@ 2021-08-17 17:44   ` Daniel Walker
  2021-08-17 20:25     ` H.J. Lu
  2021-08-17 17:57   ` Daniel Walker
  1 sibling, 1 reply; 12+ messages in thread
From: Daniel Walker @ 2021-08-17 17:44 UTC (permalink / raw)
  To: H.J. Lu; +Cc: libc-alpha, gdb

On Mon, Aug 16, 2021 at 06:06:29PM -0700, H.J. Lu wrote:
> 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 <conhuang@cisco.com>:
> 
> 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.

It's very similar to patches we have already created internally.

One comment below,

> ---
>  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 <link.h>
> +
> +--
> +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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <link.h>
> +
> +/* 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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <rtld-sizes.h>
> +
> +#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;
> +    }

I'm not sure why, but we have an issue assigning the dl_ns[ns - 1] when ns -1
was equal to LM_ID_BASE. I don't know what the issue was but we had tests fail
as a result of it. In my case I add an else clause and only set r_next when it
wasn't LM_ID_BASE, and for debugging it didn't matter since the structure was
all that mattered.

Daniel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 0/2] Extend struct r_debug to support multiple namespaces
  2021-08-17  1:06 [PATCH v2 0/2] Extend struct r_debug to support multiple namespaces H.J. Lu
  2021-08-17  1:06 ` [PATCH v2 1/2] Add declare_object_symbol_alias for assembly codes [BZ #28128] H.J. Lu
  2021-08-17  1:06 ` [PATCH v2 2/2] Extend struct r_debug to support multiple namespaces H.J. Lu
@ 2021-08-17 17:57 ` Joseph Myers
  2 siblings, 0 replies; 12+ messages in thread
From: Joseph Myers @ 2021-08-17 17:57 UTC (permalink / raw)
  To: H.J. Lu; +Cc: libc-alpha, gdb, Daniel Walker

On Mon, 16 Aug 2021, H.J. Lu via Gdb wrote:

> 1. Bump r_version to 2.  This triggers the GDB bug:
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=28236

This seems like it needs a NEWS entry under "Deprecated and removed 
features, and other changes affecting compatibility" if it results in a 
user-visible problem using older GDB with newer glibc (that bug report 
doesn't say what the actual user-visible symptoms are, if any).  (The new 
feature should probably have a NEWS entry under "Major new features" in 
any case.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 2/2] Extend struct r_debug to support multiple namespaces
  2021-08-17  1:06 ` [PATCH v2 2/2] Extend struct r_debug to support multiple namespaces H.J. Lu
  2021-08-17 17:44   ` Daniel Walker
@ 2021-08-17 17:57   ` Daniel Walker
  2021-08-17 20:26     ` H.J. Lu
  1 sibling, 1 reply; 12+ messages in thread
From: Daniel Walker @ 2021-08-17 17:57 UTC (permalink / raw)
  To: H.J. Lu; +Cc: libc-alpha, gdb

[-- Attachment #1: Type: text/plain, Size: 1251 bytes --]

On Mon, Aug 16, 2021 at 06:06:29PM -0700, H.J. Lu wrote:
> 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 <conhuang@cisco.com>:
> 
> 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.


I've attached the GDB patch which was created at Cisco to support our version of
this type of feature which is similar to what you've created. You might be able
to make some small modifications to make it work for you.

Daniel

[-- Attachment #2: 0003-Added-support-for-dlmopen.patch --]
[-- Type: text/x-diff, Size: 11081 bytes --]

From a56e1a4303e1b26b9c49962d732e92e7c1311c58 Mon Sep 17 00:00:00 2001
From: gdbdev <gdbdev@meson.cisco.com>
Date: Wed, 20 Jan 2021 00:07:30 -0800
Subject: [PATCH] Added support for dlmopen.

Introduced new dynamic section entry (DT_DEBUG_DLMOPEN).

Glibc and linker require associated patch for this feature to work.
---
 elfcpp/elfcpp.h           |  1 +
 gdb/gdbserver/linux-low.c | 18 ++++++--
 gdb/solib-svr4.c          | 88 +++++++++++++++++++++++++++++----------
 gdb/solib-svr4.h          |  6 +++
 include/elf/common.h      |  1 +
 5 files changed, 88 insertions(+), 26 deletions(-)

diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h
index d94db26071e..47b281c70e4 100644
--- a/elfcpp/elfcpp.h
+++ b/elfcpp/elfcpp.h
@@ -714,6 +714,7 @@ enum DT
   DT_FINI_ARRAYSZ = 28,
   DT_RUNPATH = 29,
   DT_FLAGS = 30,
+  DT_DEBUG_DLMOPEN = 38,
 
   // This is used to mark a range of dynamic tags.  It is not really
   // a tag value.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 4255795ea67..247a8d78f10 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -6856,6 +6856,12 @@ struct link_map_offsets
 
     /* Offset to l_prev field in struct link_map.  */
     int l_prev_offset;
+
+    /* Offset of r_debug_dlmopen.r_debug.  */
+    int r_debug_dlm_offset;
+
+    /* Offset of r_debug_dlmopen.r_next.  */
+    int r_next_dlm_offset;
   };
 
 /* Construct qXfer:libraries-svr4:read reply.  */
@@ -6877,7 +6883,9 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
       4,     /* l_name offset in link_map.  */
       8,     /* l_ld offset in link_map.  */
       12,    /* l_next offset in link_map.  */
-      16     /* l_prev offset in link_map.  */
+      16,    /* l_prev offset in link_map.  */
+      0,     /* r_debug_dlm offset.  */
+      4      /* r_next_dlm offset.  */
     };
 
   static const struct link_map_offsets lmo_64bit_offsets =
@@ -6888,7 +6896,9 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
       8,     /* l_name offset in link_map.  */
       16,    /* l_ld offset in link_map.  */
       24,    /* l_next offset in link_map.  */
-      32     /* l_prev offset in link_map.  */
+      32,    /* l_prev offset in link_map.  */
+      0,     /* r_debug_dlm offset.  */
+      8      /* r_next_dlm offset.  */
     };
   const struct link_map_offsets *lmo;
   unsigned int machine;
@@ -6953,7 +6963,7 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
 	  if (linux_read_memory (priv->r_debug + lmo->r_version_offset,
 				 (unsigned char *) &r_version,
 				 sizeof (r_version)) != 0
-	      || r_version != 1)
+	      || (r_version != 1 && r_version != 3))
 	    {
 	      warning ("unexpected r_debug version %d", r_version);
 	    }
@@ -6982,12 +6992,14 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
     {
       unsigned char libname[PATH_MAX];
 
+#if 0
       if (lm_prev != l_prev)
 	{
 	  warning ("Corrupted shared library list: 0x%lx != 0x%lx",
 		   (long) lm_prev, (long) l_prev);
 	  break;
 	}
+#endif
 
       /* Ignore the first entry even if it has valid name as the first entry
 	 corresponds to the main executable.  The first entry should not be
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 3714c59748b..2763e8ae534 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -851,14 +851,10 @@ locate_base (struct svr4_info *info)
 
 /* Find the first element in the inferior's dynamic link map, and
    return its address in the inferior.  Return zero if the address
-   could not be determined.
-
-   FIXME: Perhaps we should validate the info somehow, perhaps by
-   checking r_version for a known version number, or r_state for
-   RT_CONSISTENT.  */
+   could not be determined.  */
 
 static CORE_ADDR
-solib_svr4_r_map (struct svr4_info *info)
+solib_svr4_r_map (CORE_ADDR debug_base)
 {
   struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
   struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
@@ -866,7 +862,7 @@ solib_svr4_r_map (struct svr4_info *info)
 
   try
     {
-      addr = read_memory_typed_address (info->debug_base + lmo->r_map_offset,
+      addr = read_memory_typed_address (debug_base + lmo->r_map_offset,
                                         ptr_type);
     }
   catch (const gdb_exception_error &ex)
@@ -913,7 +909,7 @@ solib_svr4_r_ldsomap (struct svr4_info *info)
       exception_print (gdb_stderr, ex);
     }
 
-  if (version < 2 || lmo->r_ldsomap_offset == -1)
+  if (version != 2 || lmo->r_ldsomap_offset == -1)
     return 0;
 
   return read_memory_typed_address (info->debug_base + lmo->r_ldsomap_offset,
@@ -979,7 +975,7 @@ open_symbol_file_object (int from_tty)
     return 0;	/* failed somehow...  */
 
   /* First link map member should be the executable.  */
-  lm = solib_svr4_r_map (info);
+  lm = solib_svr4_r_map (info->debug_base);
   if (lm == 0)
     return 0;	/* failed somehow...  */
 
@@ -1294,6 +1290,7 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
 {
   CORE_ADDR first_l_name = 0;
   CORE_ADDR next_lm;
+	(void)prev_lm;
 
   for (; lm != 0; prev_lm = lm, lm = next_lm)
     {
@@ -1308,7 +1305,7 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
 	return 0;
 
       next_lm = li->l_next;
-
+#if 0
       if (li->l_prev != prev_lm)
 	{
 	  warning (_("Corrupted shared library list: %s != %s"),
@@ -1316,6 +1313,7 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
 		   paddress (target_gdbarch (), li->l_prev));
 	  return 0;
 	}
+#endif
 
       /* For SVR4 versions, the first entry in the link map is for the
          inferior executable, so we must ignore it.  For some versions of
@@ -1362,6 +1360,29 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
   return 1;
 }
 
+/* Locate address of _r_debug_dlmopen struct. */
+static CORE_ADDR
+locate_dlmopen_base ()
+{
+  struct bound_minimal_symbol msymbol;
+  CORE_ADDR dyn_ptr;
+
+  /* Find DT_DEBUG_DLMOPEN entry in .dynamic section.
+  DT_DEBUG_DLMOPEN entry is not yet introduced.*/
+  if (scan_dyntag (DT_DEBUG_DLMOPEN, exec_bfd, &dyn_ptr, NULL)
+      || scan_dyntag_auxv (DT_DEBUG_DLMOPEN, &dyn_ptr, NULL))
+    return dyn_ptr;
+
+  /* This may be a static executable.  Look for the symbol
+  conventionally named _r_debug_dlmopen.  */
+  msymbol = lookup_minimal_symbol ("_r_debug_dlmopen", NULL, symfile_objfile);
+  if (msymbol.minsym != NULL)
+    return BMSYMBOL_VALUE_ADDRESS (msymbol);
+
+  /* _r_debug_dlmopen struct not found.  */
+  return 0;
+}
+
 /* Read the full list of currently loaded shared objects directly
    from the inferior, without referring to any libraries read and
    stored by the probes interface.  Handle special cases relating
@@ -1375,6 +1396,11 @@ svr4_current_sos_direct (struct svr4_info *info)
   struct so_list **link_ptr = &head;
   int ignore_first;
   struct svr4_library_list library_list;
+  struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
+  CORE_ADDR r_debug_ptr;
+  CORE_ADDR r_debug_dlmopen_ptr = 0;
+  struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
 
   /* Fall back to manual examination of the target if the packet is not
      supported or gdbserver failed to find DT_DEBUG.  gdb.server/solib-list.exp
@@ -1415,11 +1441,28 @@ svr4_current_sos_direct (struct svr4_info *info)
       svr4_free_library_list (&head);
     });
 
-  /* Walk the inferior's link map list, and build our list of
-     `struct so_list' nodes.  */
-  lm = solib_svr4_r_map (info);
-  if (lm)
-    svr4_read_so_list (info, lm, 0, &link_ptr, ignore_first);
+  r_debug_ptr = info->debug_base;
+  r_debug_dlmopen_ptr = locate_dlmopen_base ();
+  do
+    {
+      /* Walk the inferior's link map list, and build our list of
+         `struct so_list' nodes.  */
+      lm = solib_svr4_r_map (r_debug_ptr);
+      if (lm)
+        svr4_read_so_list (info, lm, 0, &link_ptr, ignore_first);
+      ignore_first = 0;
+      if (r_debug_dlmopen_ptr != 0){
+        r_debug_dlmopen_ptr
+		  = read_memory_typed_address (r_debug_dlmopen_ptr +
+		                 lmo->r_next_dlm_offset, ptr_type);
+        if (r_debug_dlmopen_ptr != 0)
+          r_debug_ptr
+            = read_memory_typed_address ( r_debug_dlmopen_ptr +
+			              lmo->r_debug_dlm_offset, ptr_type);
+        else
+          r_debug_ptr = 0;
+      }
+    } while ((r_debug_dlmopen_ptr !=0) && (r_debug_ptr != 0));
 
   /* On Solaris, the dynamic linker is not in the normal list of
      shared objects, so make sure we pick it up too.  Having
@@ -1944,13 +1987,6 @@ svr4_handle_solib_event (void)
     if (locate_base (info) == 0)
       return;
 
-    /* GDB does not currently support libraries loaded via dlmopen
-       into namespaces other than the initial one.  We must ignore
-       any namespace other than the initial namespace here until
-       support for this is added to GDB.  */
-    if (debug_base != info->debug_base)
-      action = DO_NOTHING;
-
     if (action == UPDATE_OR_RELOAD)
       {
 	try
@@ -2212,7 +2248,7 @@ enable_break (struct svr4_info *info, int from_tty)
 
   solib_add (NULL, from_tty, auto_solib_add);
   sym_addr = 0;
-  if (info->debug_base && solib_svr4_r_map (info) != 0)
+  if (info->debug_base && solib_svr4_r_map (info->debug_base) != 0)
     sym_addr = solib_svr4_r_brk (info);
 
   if (sym_addr != 0)
@@ -3160,6 +3196,9 @@ svr4_ilp32_fetch_link_map_offsets (void)
       lmo.r_brk_offset = 8;
       lmo.r_ldsomap_offset = 20;
 
+      lmo.r_debug_dlm_offset = 0;
+      lmo.r_next_dlm_offset = 4;
+
       /* Everything we need is in the first 20 bytes.  */
       lmo.link_map_size = 20;
       lmo.l_addr_offset = 0;
@@ -3191,6 +3230,9 @@ svr4_lp64_fetch_link_map_offsets (void)
       lmo.r_brk_offset = 16;
       lmo.r_ldsomap_offset = 40;
 
+      lmo.r_debug_dlm_offset = 0;
+      lmo.r_next_dlm_offset = 8;
+
       /* Everything we need is in the first 40 bytes.  */
       lmo.link_map_size = 40;
       lmo.l_addr_offset = 0;
diff --git a/gdb/solib-svr4.h b/gdb/solib-svr4.h
index 30dd6bc0b36..2700d54d733 100644
--- a/gdb/solib-svr4.h
+++ b/gdb/solib-svr4.h
@@ -66,6 +66,12 @@ struct link_map_offsets
     /* Offset of r_debug.r_ldsomap.  */
     int r_ldsomap_offset;
 
+    /* Offset of r_debug_dlmopen.r_debug_dlm.  */
+    int r_debug_dlm_offset;
+
+    /* Offset of r_debug_dlmopen.r_next_dlm.  */
+    int r_next_dlm_offset;
+
     /* Size of struct link_map (or equivalent), or at least enough of it
        to be able to obtain the fields below.  */
     int link_map_size;
diff --git a/include/elf/common.h b/include/elf/common.h
index 75c4fb7e9d7..5bd1abc1c59 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -975,6 +975,7 @@
 #define DT_FINI_ARRAYSZ 28
 #define DT_RUNPATH	29
 #define DT_FLAGS	30
+#define DT_DEBUG_DLMOPEN 38
 #define DT_ENCODING	32
 #define DT_PREINIT_ARRAY   32
 #define DT_PREINIT_ARRAYSZ 33
-- 
2.26.2.Cisco


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 2/2] Extend struct r_debug to support multiple namespaces
  2021-08-17 17:44   ` Daniel Walker
@ 2021-08-17 20:25     ` H.J. Lu
  2021-08-18  0:14       ` H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2021-08-17 20:25 UTC (permalink / raw)
  To: Daniel Walker; +Cc: GNU C Library, GDB

On Tue, Aug 17, 2021 at 10:44 AM Daniel Walker <danielwa@cisco.com> wrote:
>
> On Mon, Aug 16, 2021 at 06:06:29PM -0700, H.J. Lu wrote:
> > 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 <conhuang@cisco.com>:
> >
> > 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.
>
> It's very similar to patches we have already created internally.
>
> One comment below,
>
> > ---
> >  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 <link.h>
> > +
> > +--
> > +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
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#include <link.h>
> > +
> > +/* 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
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#include <rtld-sizes.h>
> > +
> > +#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;
> > +    }
>
> I'm not sure why, but we have an issue assigning the dl_ns[ns - 1] when ns -1
> was equal to LM_ID_BASE. I don't know what the issue was but we had tests fail
> as a result of it. In my case I add an else clause and only set r_next when it
> wasn't LM_ID_BASE, and for debugging it didn't matter since the structure was
> all that mattered.
>
> Daniel

_dl_debug_initialize can be called multiple times like

 _dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;

I will update my patch to fix it.

-- 
H.J.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 2/2] Extend struct r_debug to support multiple namespaces
  2021-08-17 17:57   ` Daniel Walker
@ 2021-08-17 20:26     ` H.J. Lu
  2021-08-18  0:21       ` H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2021-08-17 20:26 UTC (permalink / raw)
  To: Daniel Walker; +Cc: GNU C Library, GDB

On Tue, Aug 17, 2021 at 10:57 AM Daniel Walker <danielwa@cisco.com> wrote:
>
> On Mon, Aug 16, 2021 at 06:06:29PM -0700, H.J. Lu wrote:
> > 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 <conhuang@cisco.com>:
> >
> > 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.
>
>
> I've attached the GDB patch which was created at Cisco to support our version of
> this type of feature which is similar to what you've created. You might be able
> to make some small modifications to make it work for you.
>
> Daniel

I will give it a try.

Thanks.

-- 
H.J.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 2/2] Extend struct r_debug to support multiple namespaces
  2021-08-17 20:25     ` H.J. Lu
@ 2021-08-18  0:14       ` H.J. Lu
  0 siblings, 0 replies; 12+ messages in thread
From: H.J. Lu @ 2021-08-18  0:14 UTC (permalink / raw)
  To: Daniel Walker; +Cc: GNU C Library, GDB

On Tue, Aug 17, 2021 at 1:25 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Tue, Aug 17, 2021 at 10:44 AM Daniel Walker <danielwa@cisco.com> wrote:
> >
> > On Mon, Aug 16, 2021 at 06:06:29PM -0700, H.J. Lu wrote:
> > > 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 <conhuang@cisco.com>:
> > >
> > > 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.
> >
> > It's very similar to patches we have already created internally.
> >
> > One comment below,
> >
> > > ---
> > >  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 <link.h>
> > > +
> > > +--
> > > +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
> > > +   <https://www.gnu.org/licenses/>.  */
> > > +
> > > +#include <link.h>
> > > +
> > > +/* 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
> > > +   <https://www.gnu.org/licenses/>.  */
> > > +
> > > +#include <rtld-sizes.h>
> > > +
> > > +#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;
> > > +    }
> >
> > I'm not sure why, but we have an issue assigning the dl_ns[ns - 1] when ns -1
> > was equal to LM_ID_BASE. I don't know what the issue was but we had tests fail
> > as a result of it. In my case I add an else clause and only set r_next when it
> > wasn't LM_ID_BASE, and for debugging it didn't matter since the structure was
> > all that mattered.
> >
> > Daniel
>
> _dl_debug_initialize can be called multiple times like
>
>  _dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;
>
> I will update my patch to fix it.

I sent out the v3 patch to fix it.

-- 
H.J.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 2/2] Extend struct r_debug to support multiple namespaces
  2021-08-17 20:26     ` H.J. Lu
@ 2021-08-18  0:21       ` H.J. Lu
  2021-08-18  2:36         ` H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2021-08-18  0:21 UTC (permalink / raw)
  To: Daniel Walker; +Cc: GNU C Library, GDB

On Tue, Aug 17, 2021 at 1:26 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Tue, Aug 17, 2021 at 10:57 AM Daniel Walker <danielwa@cisco.com> wrote:
> >
> > On Mon, Aug 16, 2021 at 06:06:29PM -0700, H.J. Lu wrote:
> > > 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 <conhuang@cisco.com>:
> > >
> > > 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.
> >
> >
> > I've attached the GDB patch which was created at Cisco to support our version of
> > this type of feature which is similar to what you've created. You might be able
> > to make some small modifications to make it work for you.
> >
> > Daniel
>
>

It seems to work pretty well with some cleanup:

https://gitlab.com/x86-binutils/binutils-gdb/-/commit/ea336450f484fc8c0aa512a60bc99f69309a46d8

(gdb) set  stop-on-solib-events 1
(gdb) r --direct
Starting program:
/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/tst-dlmopen4
--direct
Stopped due to shared library event (no libraries added or removed)
(gdb) c
Continuing.
warning: Unable to find libthread_db matching inferior's thread
library, thread debugging will not be available.
Stopped due to shared library event:
  Inferior loaded
/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/libc.so.6
(gdb)
Continuing.
Stopped due to shared library event (no libraries added or removed)
(gdb)
Continuing.
warning: .dynamic section for
"/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/ld-linux-x86-64.so.2"
is not at the expected address (wrong library or version mismatch?)
warning: Unable to find libthread_db matching inferior's thread
library, thread debugging will not be available.
Stopped due to shared library event:
  Inferior loaded
/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/tst-dlmopen1mod.so
    /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/libc.so.6
    /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/ld-linux-x86-64.so.2
(gdb)
Continuing.
Stopped due to shared library event (no libraries added or removed)
(gdb)
Continuing.
Stopped due to shared library event:
  Inferior unloaded
/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/tst-dlmopen1mod.so
    /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/libc.so.6
    /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/ld-linux-x86-64.so.2
(gdb)
Continuing.
[Inferior 1 (process 638559) exited normally]
(gdb)

(gdb) r --direct
Starting program:
/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/tst-dlmopen4
--direct
warning: Unable to find libthread_db matching inferior's thread
library, thread debugging will not be available.
warning: .dynamic section for
"/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/ld-linux-x86-64.so.2"
is not at the expected address (wrong library or version mismatch?)
warning: Unable to find libthread_db matching inferior's thread
library, thread debugging will not be available.
[Inferior 1 (process 638480) exited normally]
(gdb)

It looks like l_ld of ld.so in the new namespace isn't set properly:

(gdb) p debug->r_next->r_map
$5 = (struct link_map *) 0x408360
(gdb) p *debug->r_next->r_map
$6 = {l_addr = 140737351757824,
  l_name = 0x4082f0
"/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/tst-dlmopen1mod.so",
l_ld = 0x7ffff7dbee10, l_next = 0x408900,
  l_prev = 0x0}
(gdb) p *debug->r_next->r_map->l_next
$7 = {l_addr = 140737349664768,
  l_name = 0x4088a0
"/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/libc.so.6",
l_ld = 0x7ffff7daabc0, l_next = 0x408e90, l_prev = 0x408360}
(gdb) p *debug->r_next->r_map->l_next->l_next
$8 = {l_addr = 0,
  l_name = 0x408e20
"/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/ld-linux-x86-64.so.2",
l_ld = 0x0, l_next = 0x0, l_prev = 0x408900}
(gdb)

-- 
H.J.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 2/2] Extend struct r_debug to support multiple namespaces
  2021-08-18  0:21       ` H.J. Lu
@ 2021-08-18  2:36         ` H.J. Lu
  2021-08-18 13:34           ` H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2021-08-18  2:36 UTC (permalink / raw)
  To: Daniel Walker; +Cc: GNU C Library, GDB

On Tue, Aug 17, 2021 at 5:21 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Tue, Aug 17, 2021 at 1:26 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Tue, Aug 17, 2021 at 10:57 AM Daniel Walker <danielwa@cisco.com> wrote:
> > >
> > > On Mon, Aug 16, 2021 at 06:06:29PM -0700, H.J. Lu wrote:
> > > > 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 <conhuang@cisco.com>:
> > > >
> > > > 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.
> > >
> > >
> > > I've attached the GDB patch which was created at Cisco to support our version of
> > > this type of feature which is similar to what you've created. You might be able
> > > to make some small modifications to make it work for you.
> > >
> > > Daniel
> >
> >
>
> It seems to work pretty well with some cleanup:
>
> https://gitlab.com/x86-binutils/binutils-gdb/-/commit/ea336450f484fc8c0aa512a60bc99f69309a46d8
>
> (gdb) set  stop-on-solib-events 1
> (gdb) r --direct
> Starting program:
> /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/tst-dlmopen4
> --direct
> Stopped due to shared library event (no libraries added or removed)
> (gdb) c
> Continuing.
> warning: Unable to find libthread_db matching inferior's thread
> library, thread debugging will not be available.
> Stopped due to shared library event:
>   Inferior loaded
> /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/libc.so.6
> (gdb)
> Continuing.
> Stopped due to shared library event (no libraries added or removed)
> (gdb)
> Continuing.
> warning: .dynamic section for
> "/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/ld-linux-x86-64.so.2"
> is not at the expected address (wrong library or version mismatch?)
> warning: Unable to find libthread_db matching inferior's thread
> library, thread debugging will not be available.
> Stopped due to shared library event:
>   Inferior loaded
> /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/tst-dlmopen1mod.so
>     /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/libc.so.6
>     /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/ld-linux-x86-64.so.2
> (gdb)
> Continuing.
> Stopped due to shared library event (no libraries added or removed)
> (gdb)
> Continuing.
> Stopped due to shared library event:
>   Inferior unloaded
> /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/tst-dlmopen1mod.so
>     /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/libc.so.6
>     /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/ld-linux-x86-64.so.2
> (gdb)
> Continuing.
> [Inferior 1 (process 638559) exited normally]
> (gdb)
>
> (gdb) r --direct
> Starting program:
> /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/tst-dlmopen4
> --direct
> warning: Unable to find libthread_db matching inferior's thread
> library, thread debugging will not be available.
> warning: .dynamic section for
> "/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/ld-linux-x86-64.so.2"
> is not at the expected address (wrong library or version mismatch?)
> warning: Unable to find libthread_db matching inferior's thread
> library, thread debugging will not be available.
> [Inferior 1 (process 638480) exited normally]
> (gdb)
>
> It looks like l_ld of ld.so in the new namespace isn't set properly:
>
> (gdb) p debug->r_next->r_map
> $5 = (struct link_map *) 0x408360
> (gdb) p *debug->r_next->r_map
> $6 = {l_addr = 140737351757824,
>   l_name = 0x4082f0
> "/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/tst-dlmopen1mod.so",
> l_ld = 0x7ffff7dbee10, l_next = 0x408900,
>   l_prev = 0x0}
> (gdb) p *debug->r_next->r_map->l_next
> $7 = {l_addr = 140737349664768,
>   l_name = 0x4088a0
> "/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/libc.so.6",
> l_ld = 0x7ffff7daabc0, l_next = 0x408e90, l_prev = 0x408360}
> (gdb) p *debug->r_next->r_map->l_next->l_next
> $8 = {l_addr = 0,
>   l_name = 0x408e20
> "/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/ld-linux-x86-64.so.2",
> l_ld = 0x0, l_next = 0x0, l_prev = 0x408900}
> (gdb)
>
>

Please try glibc users/hjl/pr15971/r_version branch:

https://gitlab.com/x86-glibc/glibc/-/tree/users/hjl/pr15971/r_version

and GDB users/hjl/pr11839/master branch:

https://gitlab.com/x86-binutils/binutils-gdb/-/tree/users/hjl/pr11839/master


-- 
H.J.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v2 2/2] Extend struct r_debug to support multiple namespaces
  2021-08-18  2:36         ` H.J. Lu
@ 2021-08-18 13:34           ` H.J. Lu
  0 siblings, 0 replies; 12+ messages in thread
From: H.J. Lu @ 2021-08-18 13:34 UTC (permalink / raw)
  To: Daniel Walker; +Cc: GNU C Library, GDB

On Tue, Aug 17, 2021 at 7:36 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Tue, Aug 17, 2021 at 5:21 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Tue, Aug 17, 2021 at 1:26 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > On Tue, Aug 17, 2021 at 10:57 AM Daniel Walker <danielwa@cisco.com> wrote:
> > > >
> > > > On Mon, Aug 16, 2021 at 06:06:29PM -0700, H.J. Lu wrote:
> > > > > 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 <conhuang@cisco.com>:
> > > > >
> > > > > 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.
> > > >
> > > >
> > > > I've attached the GDB patch which was created at Cisco to support our version of
> > > > this type of feature which is similar to what you've created. You might be able
> > > > to make some small modifications to make it work for you.
> > > >
> > > > Daniel
> > >
> > >
> >
> > It seems to work pretty well with some cleanup:
> >
> > https://gitlab.com/x86-binutils/binutils-gdb/-/commit/ea336450f484fc8c0aa512a60bc99f69309a46d8
> >
> > (gdb) set  stop-on-solib-events 1
> > (gdb) r --direct
> > Starting program:
> > /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/tst-dlmopen4
> > --direct
> > Stopped due to shared library event (no libraries added or removed)
> > (gdb) c
> > Continuing.
> > warning: Unable to find libthread_db matching inferior's thread
> > library, thread debugging will not be available.
> > Stopped due to shared library event:
> >   Inferior loaded
> > /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/libc.so.6
> > (gdb)
> > Continuing.
> > Stopped due to shared library event (no libraries added or removed)
> > (gdb)
> > Continuing.
> > warning: .dynamic section for
> > "/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/ld-linux-x86-64.so.2"
> > is not at the expected address (wrong library or version mismatch?)
> > warning: Unable to find libthread_db matching inferior's thread
> > library, thread debugging will not be available.
> > Stopped due to shared library event:
> >   Inferior loaded
> > /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/tst-dlmopen1mod.so
> >     /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/libc.so.6
> >     /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/ld-linux-x86-64.so.2
> > (gdb)
> > Continuing.
> > Stopped due to shared library event (no libraries added or removed)
> > (gdb)
> > Continuing.
> > Stopped due to shared library event:
> >   Inferior unloaded
> > /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/tst-dlmopen1mod.so
> >     /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/libc.so.6
> >     /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/ld-linux-x86-64.so.2
> > (gdb)
> > Continuing.
> > [Inferior 1 (process 638559) exited normally]
> > (gdb)
> >
> > (gdb) r --direct
> > Starting program:
> > /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/tst-dlmopen4
> > --direct
> > warning: Unable to find libthread_db matching inferior's thread
> > library, thread debugging will not be available.
> > warning: .dynamic section for
> > "/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/ld-linux-x86-64.so.2"
> > is not at the expected address (wrong library or version mismatch?)
> > warning: Unable to find libthread_db matching inferior's thread
> > library, thread debugging will not be available.
> > [Inferior 1 (process 638480) exited normally]
> > (gdb)
> >
> > It looks like l_ld of ld.so in the new namespace isn't set properly:
> >
> > (gdb) p debug->r_next->r_map
> > $5 = (struct link_map *) 0x408360
> > (gdb) p *debug->r_next->r_map
> > $6 = {l_addr = 140737351757824,
> >   l_name = 0x4082f0
> > "/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/tst-dlmopen1mod.so",
> > l_ld = 0x7ffff7dbee10, l_next = 0x408900,
> >   l_prev = 0x0}
> > (gdb) p *debug->r_next->r_map->l_next
> > $7 = {l_addr = 140737349664768,
> >   l_name = 0x4088a0
> > "/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/libc.so.6",
> > l_ld = 0x7ffff7daabc0, l_next = 0x408e90, l_prev = 0x408360}
> > (gdb) p *debug->r_next->r_map->l_next->l_next
> > $8 = {l_addr = 0,
> >   l_name = 0x408e20
> > "/export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/elf/ld-linux-x86-64.so.2",
> > l_ld = 0x0, l_next = 0x0, l_prev = 0x408900}
> > (gdb)
> >
> >
>
> Please try glibc users/hjl/pr15971/r_version branch:
>
> https://gitlab.com/x86-glibc/glibc/-/tree/users/hjl/pr15971/r_version
>
> and GDB users/hjl/pr11839/master branch:
>
> https://gitlab.com/x86-binutils/binutils-gdb/-/tree/users/hjl/pr11839/master
>

I updated glibc branch with minor improvements and fixed gdbserver
on GDB branch.  They work well together.

-- 
H.J.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2021-08-18 13:35 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-17  1:06 [PATCH v2 0/2] Extend struct r_debug to support multiple namespaces H.J. Lu
2021-08-17  1:06 ` [PATCH v2 1/2] Add declare_object_symbol_alias for assembly codes [BZ #28128] H.J. Lu
2021-08-17  1:06 ` [PATCH v2 2/2] Extend struct r_debug to support multiple namespaces H.J. Lu
2021-08-17 17:44   ` Daniel Walker
2021-08-17 20:25     ` H.J. Lu
2021-08-18  0:14       ` H.J. Lu
2021-08-17 17:57   ` Daniel Walker
2021-08-17 20:26     ` H.J. Lu
2021-08-18  0:21       ` H.J. Lu
2021-08-18  2:36         ` H.J. Lu
2021-08-18 13:34           ` H.J. Lu
2021-08-17 17:57 ` [PATCH v2 0/2] " Joseph Myers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).