Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: "Metzger, Markus T via Gdb-patches" <gdb-patches@sourceware.org>
To: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
Subject: RE: [PATCH v4] gdb, gdbserver: support dlmopen()
Date: Fri, 21 Jan 2022 11:42:46 +0000	[thread overview]
Message-ID: <DM8PR11MB5749D144899C9D7DA82A7A21DE5B9@DM8PR11MB5749.namprd11.prod.outlook.com> (raw)
In-Reply-To: <20211117142812.3685162-1-markus.t.metzger@intel.com>

Kindly pinging,
Markus.

>-----Original Message-----
>From: Metzger, Markus T <markus.t.metzger@intel.com>
>Sent: Wednesday, November 17, 2021 3:28 PM
>To: gdb-patches@sourceware.org
>Subject: [PATCH v4] gdb, gdbserver: support dlmopen()
>
>This patch was originally developed by H.J.  Last version:
>https://sourceware.org/pipermail/gdb-patches/2021-October/182353.html
>
>Changes in v4:
>
>1. add gdb.base/dlmopen.exp
>2. extend svr4_same() to compare the load offset in addition to the name
>3. supply l_addr_inferior for default DSO to make it work with #2
>4. fix bugs in gdbserver/linux-low.cc
>
>Changes in v3:
>
>1. Fix gdbserver support.
>
>Changes in v2:
>
>1. Don't check shared libraries in other namespaces when updating shared
>libraries in a new namespace.
>
>Regression-tested on x86-64 linux.
>
>---
>
>In glibc, the r_debug structure contains (amongst others) the following
>fields:
>
>  int r_version:
>    Version number for this protocol.  It should be greater than 0.
>
>If r_version is 2, struct r_debug is extended to struct r_debug_extended
>with one additional field:
>
>  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.
>
>1. Change solib_svr4_r_map argument to take the debug base.
>2. Add solib_svr4_r_next to find the link map in the next namespace from
>the r_next field.
>3. Update svr4_current_sos_direct to get the link map in the next namespace
>from the r_next field.
>4. Don't check shared libraries in other namespaces when updating shared
>libraries in a new namespace.
>5. Update svr4_same to check the load offset in addition to the name
>6. Update svr4_default_sos to also set l_addr_inferior
>
>Add gdb.base/dlmopen.exp to test this.
>
>This fixes PR 11839.
>---
> gdb/linux-tdep.c                     |   2 +
> gdb/mips-fbsd-tdep.c                 |   2 +
> gdb/mips-netbsd-tdep.c               |   2 +
> gdb/solib-svr4.c                     |  89 ++++++++--
> gdb/solib-svr4.h                     |   3 +
> gdb/testsuite/gdb.base/dlmopen-lib.c |  25 +++
> gdb/testsuite/gdb.base/dlmopen.c     |  56 +++++++
> gdb/testsuite/gdb.base/dlmopen.exp   | 141 ++++++++++++++++
> gdbserver/linux-low.cc               | 242 ++++++++++++++++-----------
> 9 files changed, 450 insertions(+), 112 deletions(-)
> create mode 100644 gdb/testsuite/gdb.base/dlmopen-lib.c
> create mode 100644 gdb/testsuite/gdb.base/dlmopen.c
> create mode 100644 gdb/testsuite/gdb.base/dlmopen.exp
>
>diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
>index e2cff83086a..cb8e52d760a 100644
>--- a/gdb/linux-tdep.c
>+++ b/gdb/linux-tdep.c
>@@ -2739,6 +2739,7 @@ linux_ilp32_fetch_link_map_offsets ()
>       lmo.r_map_offset = 4;
>       lmo.r_brk_offset = 8;
>       lmo.r_ldsomap_offset = -1;
>+      lmo.r_next_offset = 20;
>
>       /* Everything we need is in the first 20 bytes.  */
>       lmo.link_map_size = 20;
>@@ -2767,6 +2768,7 @@ linux_lp64_fetch_link_map_offsets ()
>       lmo.r_map_offset = 8;
>       lmo.r_brk_offset = 16;
>       lmo.r_ldsomap_offset = -1;
>+      lmo.r_next_offset = 40;
>
>       /* Everything we need is in the first 40 bytes.  */
>       lmo.link_map_size = 40;
>diff --git a/gdb/mips-fbsd-tdep.c b/gdb/mips-fbsd-tdep.c
>index 0b7c97c445f..00e38a8f1c4 100644
>--- a/gdb/mips-fbsd-tdep.c
>+++ b/gdb/mips-fbsd-tdep.c
>@@ -495,6 +495,7 @@ mips_fbsd_ilp32_fetch_link_map_offsets (void)
>       lmo.r_map_offset = 4;
>       lmo.r_brk_offset = 8;
>       lmo.r_ldsomap_offset = -1;
>+      lmo.r_next_offset = -1;
>
>       lmo.link_map_size = 24;
>       lmo.l_addr_offset = 0;
>@@ -522,6 +523,7 @@ mips_fbsd_lp64_fetch_link_map_offsets (void)
>       lmo.r_map_offset = 8;
>       lmo.r_brk_offset = 16;
>       lmo.r_ldsomap_offset = -1;
>+      lmo.r_next_offset = -1;
>
>       lmo.link_map_size = 48;
>       lmo.l_addr_offset = 0;
>diff --git a/gdb/mips-netbsd-tdep.c b/gdb/mips-netbsd-tdep.c
>index a32ae5e3a29..12d702ef359 100644
>--- a/gdb/mips-netbsd-tdep.c
>+++ b/gdb/mips-netbsd-tdep.c
>@@ -308,6 +308,7 @@ mipsnbsd_ilp32_fetch_link_map_offsets (void)
>       lmo.r_map_offset = 4;
>       lmo.r_brk_offset = 8;
>       lmo.r_ldsomap_offset = -1;
>+      lmo.r_next_offset = -1;
>
>       /* Everything we need is in the first 24 bytes.  */
>       lmo.link_map_size = 24;
>@@ -336,6 +337,7 @@ mipsnbsd_lp64_fetch_link_map_offsets (void)
>       lmo.r_map_offset = 8;
>       lmo.r_brk_offset = 16;
>       lmo.r_ldsomap_offset = -1;
>+      lmo.r_next_offset = -1;
>
>       /* Everything we need is in the first 40 bytes.  */
>       lmo.link_map_size = 48;
>diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
>index 3de1bb9c7f7..d57a3c1ffdb 100644
>--- a/gdb/solib-svr4.c
>+++ b/gdb/solib-svr4.c
>@@ -174,7 +174,16 @@ svr4_same_1 (const char *gdb_so_name, const char
>*inferior_so_name)
> static int
> svr4_same (struct so_list *gdb, struct so_list *inferior)
> {
>-  return (svr4_same_1 (gdb->so_original_name, inferior->so_original_name));
>+  if (!svr4_same_1 (gdb->so_original_name, inferior->so_original_name))
>+    return false;
>+
>+  /* There may be different instances of the same library, in different
>+     namespaces.  Each instance, however, must have been loaded at a
>+     different address so its relocation offset would be different.  */
>+  const lm_info_svr4 *lmg = (const lm_info_svr4 *) gdb->lm_info;
>+  const lm_info_svr4 *lmi = (const lm_info_svr4 *) inferior->lm_info;
>+
>+  return (lmg->l_addr_inferior == lmi->l_addr_inferior);
> }
>
> static std::unique_ptr<lm_info_svr4>
>@@ -767,7 +776,7 @@ locate_base (struct svr4_info *info)
>    RT_CONSISTENT.  */
>
> 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;
>@@ -775,7 +784,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)
>@@ -829,6 +838,35 @@ solib_svr4_r_ldsomap (struct svr4_info *info)
> 				    ptr_type);
> }
>
>+/* Find the next namespace from the r_next field.  */
>+
>+static CORE_ADDR
>+solib_svr4_r_next (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;
>+  enum bfd_endian byte_order = type_byte_order (ptr_type);
>+  ULONGEST version = 0;
>+
>+  try
>+    {
>+      version
>+	= read_memory_unsigned_integer (debug_base + lmo->r_version_offset,
>+					lmo->r_version_size, byte_order);
>+    }
>+  catch (const gdb_exception_error &ex)
>+    {
>+      exception_print (gdb_stderr, ex);
>+    }
>+
>+  /* The r_next field is added with r_version == 2.  */
>+  if (version < 2 || lmo->r_next_offset == -1)
>+    return 0;
>+
>+  return read_memory_typed_address (debug_base + lmo->r_next_offset,
>+				    ptr_type);
>+}
>+
> /* On Solaris systems with some versions of the dynamic linker,
>    ld.so's l_name pointer points to the SONAME in the string table
>    rather than into writable memory.  So that GDB can find shared
>@@ -886,7 +924,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...  */
>
>@@ -1178,7 +1216,7 @@ svr4_default_sos (svr4_info *info)
>   newobj->lm_info = li;
>
>   /* Nothing will ever check the other fields if we set l_addr_p.  */
>-  li->l_addr = info->debug_loader_offset;
>+  li->l_addr = li->l_addr_inferior = info->debug_loader_offset;
>   li->l_addr_p = 1;
>
>   strncpy (newobj->so_name, info->debug_loader_name,
>SO_NAME_MAX_PATH_SIZE - 1);
>@@ -1323,7 +1361,7 @@ svr4_current_sos_direct (struct svr4_info *info)
>
>   /* Walk the inferior's link map list, and build our list of
>      `struct so_list' nodes.  */
>-  lm = solib_svr4_r_map (info);
>+  lm = solib_svr4_r_map (info->debug_base);
>   if (lm)
>     svr4_read_so_list (info, lm, 0, &link_ptr, ignore_first);
>
>@@ -1335,6 +1373,18 @@ svr4_current_sos_direct (struct svr4_info *info)
>   if (lm)
>     svr4_read_so_list (info, lm, 0, &link_ptr, 0);
>
>+  /* Get the next namespace from the r_next field.  */
>+  lm = solib_svr4_r_next (info->debug_base);
>+  while (lm != 0)
>+    {
>+      /* Get the link map in this namespace.  */
>+      CORE_ADDR link_map = solib_svr4_r_map (lm);
>+      if (link_map != 0)
>+	svr4_read_so_list (info, link_map, 0, &link_ptr, 0);
>+      /* Go to the next namespace.  */
>+      lm = solib_svr4_r_next (lm);
>+    }
>+
>   cleanup.release ();
>
>   if (head == NULL)
>@@ -1706,7 +1756,8 @@ solist_update_full (struct svr4_info *info)
>    failure.  */
>
> static int
>-solist_update_incremental (struct svr4_info *info, CORE_ADDR lm)
>+solist_update_incremental (struct svr4_info *info, CORE_ADDR debug_base,
>+			   CORE_ADDR lm)
> {
>   struct so_list *tail;
>   CORE_ADDR prev_lm;
>@@ -1727,8 +1778,15 @@ solist_update_incremental (struct svr4_info *info,
>CORE_ADDR lm)
>   for (tail = info->solib_list; tail->next != NULL; tail = tail->next)
>     /* Nothing.  */;
>
>-  lm_info_svr4 *li = (lm_info_svr4 *) tail->lm_info;
>-  prev_lm = li->lm_addr;
>+  /* Don't check shared libraries in other namespaces when updating
>+     shared libraries in a new namespace.  */
>+  if (debug_base == info->debug_base)
>+    {
>+      lm_info_svr4 *li = (lm_info_svr4 *) tail->lm_info;
>+      prev_lm = li->lm_addr;
>+    }
>+  else
>+    prev_lm = 0;
>
>   /* Read the new objects.  */
>   if (info->using_xfer)
>@@ -1869,13 +1927,6 @@ svr4_handle_solib_event (void)
> 	  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
>@@ -1901,7 +1952,7 @@ svr4_handle_solib_event (void)
>
>   if (action == UPDATE_OR_RELOAD)
>     {
>-      if (!solist_update_incremental (info, lm))
>+      if (!solist_update_incremental (info, debug_base, lm))
> 	action = FULL_RELOAD;
>     }
>
>@@ -2136,7 +2187,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)
>@@ -3087,6 +3138,7 @@ svr4_ilp32_fetch_link_map_offsets (void)
>       lmo.r_map_offset = 4;
>       lmo.r_brk_offset = 8;
>       lmo.r_ldsomap_offset = 20;
>+      lmo.r_next_offset = -1;
>
>       /* Everything we need is in the first 20 bytes.  */
>       lmo.link_map_size = 20;
>@@ -3118,6 +3170,7 @@ svr4_lp64_fetch_link_map_offsets (void)
>       lmo.r_map_offset = 8;
>       lmo.r_brk_offset = 16;
>       lmo.r_ldsomap_offset = 40;
>+      lmo.r_next_offset = -1;
>
>       /* Everything we need is in the first 40 bytes.  */
>       lmo.link_map_size = 40;
>diff --git a/gdb/solib-svr4.h b/gdb/solib-svr4.h
>index 8d94d9cb26e..64854e2edd9 100644
>--- a/gdb/solib-svr4.h
>+++ b/gdb/solib-svr4.h
>@@ -66,6 +66,9 @@ struct link_map_offsets
>     /* Offset of r_debug.r_ldsomap.  */
>     int r_ldsomap_offset;
>
>+    /* Offset of r_debug_extended.r_next.  */
>+    int r_next_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/gdb/testsuite/gdb.base/dlmopen-lib.c
>b/gdb/testsuite/gdb.base/dlmopen-lib.c
>new file mode 100644
>index 00000000000..264659ec9de
>--- /dev/null
>+++ b/gdb/testsuite/gdb.base/dlmopen-lib.c
>@@ -0,0 +1,25 @@
>+/* This testcase is part of GDB, the GNU debugger.
>+
>+   Copyright 2021 Free Software Foundation, Inc.
>+
>+   This program is free software; you can redistribute it and/or modify
>+   it under the terms of the GNU General Public License as published by
>+   the Free Software Foundation; either version 3 of the License, or
>+   (at your option) any later version.
>+
>+   This program 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 General Public License for more details.
>+
>+   You should have received a copy of the GNU General Public License
>+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
>+
>+*/
>+
>+__attribute__((visibility ("default")))
>+int
>+inc (int n)
>+{
>+  return n + 1;  /* bp.inc.  */
>+}
>diff --git a/gdb/testsuite/gdb.base/dlmopen.c
>b/gdb/testsuite/gdb.base/dlmopen.c
>new file mode 100644
>index 00000000000..49040dc8738
>--- /dev/null
>+++ b/gdb/testsuite/gdb.base/dlmopen.c
>@@ -0,0 +1,56 @@
>+/* This testcase is part of GDB, the GNU debugger.
>+
>+   Copyright 2021 Free Software Foundation, Inc.
>+
>+   This program is free software; you can redistribute it and/or modify
>+   it under the terms of the GNU General Public License as published by
>+   the Free Software Foundation; either version 3 of the License, or
>+   (at your option) any later version.
>+
>+   This program 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 General Public License for more details.
>+
>+   You should have received a copy of the GNU General Public License
>+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
>+
>+*/
>+
>+#define _GNU_SOURCE
>+#include <dlfcn.h>
>+#include <stddef.h>
>+#include <assert.h>
>+
>+volatile int pause = 1;
>+
>+int
>+main (void)
>+{
>+  void *handle[2];
>+  int (*fun) (int);
>+
>+  handle[0] = dlmopen (LM_ID_NEWLM, DSO_NAME, RTLD_LAZY | RTLD_LOCAL);
>+  assert (handle[0] != NULL);
>+
>+  handle[1] = dlmopen (LM_ID_NEWLM, DSO_NAME, RTLD_LAZY | RTLD_LOCAL);
>+  assert (handle[1] != NULL);
>+
>+  fun = dlsym (handle[0], "inc");
>+  assert (fun != NULL);
>+
>+  while (pause != 0)
>+    ;
>+
>+  fun (42);
>+
>+  dlclose (handle[0]);
>+
>+  fun = dlsym (handle[1], "inc");
>+  assert (fun != NULL);
>+
>+  fun (42);
>+
>+  dlclose (handle[1]);
>+  return 0;  /* bp.main  */
>+}
>diff --git a/gdb/testsuite/gdb.base/dlmopen.exp
>b/gdb/testsuite/gdb.base/dlmopen.exp
>new file mode 100644
>index 00000000000..fbf6fcb6b42
>--- /dev/null
>+++ b/gdb/testsuite/gdb.base/dlmopen.exp
>@@ -0,0 +1,141 @@
>+# This testcase is part of GDB, the GNU debugger.
>+#
>+# Copyright 2021 Free Software Foundation, Inc.
>+#
>+# This program is free software; you can redistribute it and/or modify
>+# it under the terms of the GNU General Public License as published by
>+# the Free Software Foundation; either version 3 of the License, or
>+# (at your option) any later version.
>+#
>+# This program 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 General Public License for more details.
>+#
>+# You should have received a copy of the GNU General Public License
>+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
>+
>+if { [skip_shlib_tests] } {
>+    unsupported "target does not support dynamic libraries"
>+    return -1
>+}
>+
>+standard_testfile
>+
>+set basename_lib dlmopen-lib
>+set srcfile_lib $srcdir/$subdir/$basename_lib.c
>+set binfile_lib [standard_output_file $basename_lib.so]
>+
>+if { [gdb_compile_shlib $srcfile_lib $binfile_lib {debug}] != "" } {
>+    untested "failed to prepare shlib"
>+    return -1
>+}
>+
>+if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
>+	  [list additional_flags=-DDSO_NAME=\"$binfile_lib\" \
>+	       libs=-ldl debug]] } {
>+    return -1
>+}
>+
>+if { ![runto_main] } {
>+    return -1
>+}
>+
>+# Check that 'info shared' show NUM occurrences of DSO.
>+proc check_dso_count { dso num } {
>+    global gdb_prompt
>+
>+    set count 0
>+    gdb_test_multiple "info shared" "info shared" {
>+	-re "$dso" {
>+	    set count [expr $count + 1]
>+	    exp_continue
>+	}
>+	-re "$gdb_prompt " {
>+	    gdb_assert {$count == $num} $gdb_test_name
>+	}
>+    }
>+}
>+
>+# The actual test.  We run it twice.
>+proc test_dlmopen {} {
>+    global srcfile srcfile_lib binfile_lib bp_main bp_inc
>+
>+    with_test_prefix "dso 1" {
>+	# Try to reach the breakpoint in the dynamically loaded library.
>+	gdb_continue_to_breakpoint "cont to bp.inc" \
>+	    ".*$srcfile_lib:$bp_inc\r\n.*"
>+
>+	# The library should be listed twice.
>+	check_dso_count $binfile_lib 2
>+
>+	# This might help debugging.
>+	gdb_test "info breakpoints" ".*"
>+	gdb_test "print \$pc" ".*"
>+    }
>+
>+    with_test_prefix "dso 2" {
>+	# Try to reach the breakpoint in the dynamically loaded library.
>+	gdb_continue_to_breakpoint "cont to bp.inc" \
>+	    ".*$srcfile_lib:$bp_inc\r\n.*"
>+
>+	# The library should be listed once.
>+	check_dso_count $binfile_lib 1
>+
>+	# This might help debugging.
>+	gdb_test "info breakpoints" ".*"
>+	gdb_test "print \$pc" ".*"
>+    }
>+
>+    with_test_prefix "main" {
>+	# Try to reach the breakpoint in the dynamically loaded library.
>+	gdb_continue_to_breakpoint "cont to bp.main" \
>+	    ".*$srcfile:$bp_main\r\n.*"
>+
>+	# The library should not be listed.
>+	check_dso_count $binfile_lib 0
>+    }
>+}
>+
>+# Remove the pause.  We only need it for the attach test.
>+gdb_test "print pause = 0" "\\\$1 = 0"
>+
>+# The library is not yet loaded.  We need breakpoints to be pending.
>+gdb_test_no_output "set breakpoint pending on"
>+
>+# Break in the to-be-loaded library and at the end of main.
>+set bp_inc [gdb_get_line_number "bp.inc" $srcfile_lib]
>+set bp_main [gdb_get_line_number "bp.main" $srcfile]
>+
>+delete_breakpoints
>+gdb_breakpoint $srcfile_lib:$bp_inc allow-pending
>+gdb_breakpoint $srcfile:$bp_main
>+
>+test_dlmopen
>+
>+# Try the same again when attaching after dlmopen().
>+if { ![can_spawn_for_attach] } {
>+    unsupported "target does not support attach"
>+    return -1
>+}
>+
>+clean_restart $binfile
>+
>+# Start the test program.
>+set test_spawn_id [spawn_wait_for_attach $binfile]
>+set testpid [spawn_id_get_pid $test_spawn_id]
>+
>+# Attach.
>+gdb_test "attach $testpid" "Attaching to program.*, process $testpid.*"
>+
>+with_test_prefix "attach" {
>+    # Remove the pause.  We no longer need it.
>+    gdb_test "print pause = 0" "\\\$1 = 0"
>+
>+    # Set the same breakpoints again.  This time, however, we do not allow the
>+    # breakpoint to be pending since the library has already been loaded.
>+    gdb_breakpoint $srcfile_lib:$bp_inc
>+    gdb_breakpoint $srcfile:$bp_main
>+
>+    test_dlmopen
>+}
>diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc
>index 34ede238d19..4ad0f94526d 100644
>--- a/gdbserver/linux-low.cc
>+++ b/gdbserver/linux-low.cc
>@@ -6727,6 +6727,9 @@ struct link_map_offsets
>     /* Offset and size of r_debug.r_map.  */
>     int r_map_offset;
>
>+    /* Offset of r_debug_extended.r_next.  */
>+    int r_next_offset;
>+
>     /* Offset to l_addr field in struct link_map.  */
>     int l_addr_offset;
>
>@@ -6743,6 +6746,98 @@ struct link_map_offsets
>     int l_prev_offset;
>   };
>
>+static const struct link_map_offsets lmo_32bit_offsets =
>+  {
>+    0,     /* r_version offset. */
>+    4,     /* r_debug.r_map offset.  */
>+    20,    /* r_debug_extended.r_next.  */
>+    0,     /* l_addr offset in link_map.  */
>+    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.  */
>+  };
>+
>+static const struct link_map_offsets lmo_64bit_offsets =
>+  {
>+    0,     /* r_version offset. */
>+    8,     /* r_debug.r_map offset.  */
>+    40,    /* r_debug_extended.r_next.  */
>+    0,     /* l_addr offset in link_map.  */
>+    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.  */
>+  };
>+
>+/* Get the loaded shared libraries from one namespace.  */
>+
>+static void
>+read_link_map (std::string &document, CORE_ADDR lm_addr, CORE_ADDR
>lm_prev,
>+	       int ptr_size, const struct link_map_offsets *lmo,
>+	       bool ignore_first, int &header_done)
>+{
>+  CORE_ADDR l_name, l_addr, l_ld, l_next, l_prev;
>+
>+  while (lm_addr
>+	 && read_one_ptr (lm_addr + lmo->l_name_offset,
>+			  &l_name, ptr_size) == 0
>+	 && read_one_ptr (lm_addr + lmo->l_addr_offset,
>+			  &l_addr, ptr_size) == 0
>+	 && read_one_ptr (lm_addr + lmo->l_ld_offset,
>+			  &l_ld, ptr_size) == 0
>+	 && read_one_ptr (lm_addr + lmo->l_prev_offset,
>+			  &l_prev, ptr_size) == 0
>+	 && read_one_ptr (lm_addr + lmo->l_next_offset,
>+			  &l_next, ptr_size) == 0)
>+    {
>+      unsigned char libname[PATH_MAX];
>+
>+      if (lm_prev != l_prev)
>+	{
>+	  warning ("Corrupted shared library list: 0x%lx != 0x%lx",
>+		   (long) lm_prev, (long) l_prev);
>+	  break;
>+	}
>+
>+      /* 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
>+	 skipped if the dynamic loader was loaded late by a static executable
>+	 (see solib-svr4.c parameter ignore_first).  But in such case the main
>+	 executable does not have PT_DYNAMIC present and this function already
>+	 exited above due to failed get_r_debug.  */
>+      if (ignore_first && lm_prev == 0)
>+	string_appendf (document, " main-lm=\"0x%lx\"", (unsigned long)
>lm_addr);
>+      else
>+	{
>+	  /* Not checking for error because reading may stop before
>+	     we've got PATH_MAX worth of characters.  */
>+	  libname[0] = '\0';
>+	  linux_read_memory (l_name, libname, sizeof (libname) - 1);
>+	  libname[sizeof (libname) - 1] = '\0';
>+	  if (libname[0] != '\0')
>+	    {
>+	      if (!header_done)
>+		{
>+		  /* Terminate `<library-list-svr4'.  */
>+		  document += '>';
>+		  header_done = 1;
>+		}
>+
>+	      string_appendf (document, "<library name=\"");
>+	      xml_escape_text_append (&document, (char *) libname);
>+	      string_appendf (document, "\" lm=\"0x%lx\" "
>+			      "l_addr=\"0x%lx\" l_ld=\"0x%lx\"/>",
>+			      (unsigned long) lm_addr, (unsigned long) l_addr,
>+			      (unsigned long) l_ld);
>+	    }
>+	}
>+
>+      lm_prev = lm_addr;
>+      lm_addr = l_next;
>+    }
>+}
>+
> /* Construct qXfer:libraries-svr4:read reply.  */
>
> int
>@@ -6754,33 +6849,8 @@ linux_process_target::qxfer_libraries_svr4 (const char
>*annex,
>   struct process_info_private *const priv = current_process ()->priv;
>   char filename[PATH_MAX];
>   int pid, is_elf64;
>-
>-  static const struct link_map_offsets lmo_32bit_offsets =
>-    {
>-      0,     /* r_version offset. */
>-      4,     /* r_debug.r_map offset.  */
>-      0,     /* l_addr offset in link_map.  */
>-      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.  */
>-    };
>-
>-  static const struct link_map_offsets lmo_64bit_offsets =
>-    {
>-      0,     /* r_version offset. */
>-      8,     /* r_debug.r_map offset.  */
>-      0,     /* l_addr offset in link_map.  */
>-      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.  */
>-    };
>-  const struct link_map_offsets *lmo;
>   unsigned int machine;
>-  int ptr_size;
>   CORE_ADDR lm_addr = 0, lm_prev = 0;
>-  CORE_ADDR l_name, l_addr, l_ld, l_next, l_prev;
>   int header_done = 0;
>
>   if (writebuf != NULL)
>@@ -6791,8 +6861,18 @@ linux_process_target::qxfer_libraries_svr4 (const char
>*annex,
>   pid = lwpid_of (current_thread);
>   xsnprintf (filename, sizeof filename, "/proc/%d/exe", pid);
>   is_elf64 = elf_64_file_p (filename, &machine);
>-  lmo = is_elf64 ? &lmo_64bit_offsets : &lmo_32bit_offsets;
>-  ptr_size = is_elf64 ? 8 : 4;
>+  const struct link_map_offsets *lmo;
>+  int ptr_size;
>+  if (is_elf64)
>+    {
>+      lmo = &lmo_64bit_offsets;
>+      ptr_size = 8;
>+    }
>+  else
>+    {
>+      lmo = &lmo_32bit_offsets;
>+      ptr_size = 4;
>+    }
>
>   while (annex[0] != '\0')
>     {
>@@ -6821,95 +6901,69 @@ linux_process_target::qxfer_libraries_svr4 (const char
>*annex,
>       annex = decode_address_to_semicolon (addrp, sep + 1);
>     }
>
>-  if (lm_addr == 0)
>-    {
>-      int r_version = 0;
>+  std::string document = "<library-list-svr4 version=\"1.0\"";
>
>-      if (priv->r_debug == 0)
>-	priv->r_debug = get_r_debug (pid, is_elf64);
>+  /* When the starting LM_ADDR is passed in the annex, only traverse that
>+     namespace.
>+
>+     Otherwise, start with R_DEBUG and traverse all namespaces we find.  */
>+  if (lm_addr != 0)
>+    read_link_map (document, lm_addr, lm_prev, ptr_size, lmo, false,
>+		   header_done);
>+  else
>+    {
>+      CORE_ADDR lm = priv->r_debug;
>+      if (lm == 0)
>+	lm = priv->r_debug = get_r_debug (pid, is_elf64);
>
>       /* We failed to find DT_DEBUG.  Such situation will not change
> 	 for this inferior - do not retry it.  Report it to GDB as
> 	 E01, see for the reasons at the GDB solib-svr4.c side.  */
>-      if (priv->r_debug == (CORE_ADDR) -1)
>+      if (lm == (CORE_ADDR) -1)
> 	return -1;
>
>-      if (priv->r_debug != 0)
>+      bool ignore_first = true;
>+      while (lm != 0)
> 	{
>-	  if (linux_read_memory (priv->r_debug + lmo->r_version_offset,
>+	  int r_version = 0;
>+	  if (linux_read_memory (lm + lmo->r_version_offset,
> 				 (unsigned char *) &r_version,
>-				 sizeof (r_version)) != 0
>-	      || r_version < 1)
>+				 sizeof (r_version)) != 0)
>+	    {
>+	      warning ("unable to read r_version from 0x%lx",
>+		       (long) lm + lmo->r_version_offset);
>+	      break;
>+	    }
>+
>+	  if (r_version < 1)
> 	    {
> 	      warning ("unexpected r_debug version %d", r_version);
>+	      break;
> 	    }
>-	  else if (read_one_ptr (priv->r_debug + lmo->r_map_offset,
>-				 &lm_addr, ptr_size) != 0)
>+
>+	  if (read_one_ptr (lm + lmo->r_map_offset, &lm_addr, ptr_size) != 0)
> 	    {
> 	      warning ("unable to read r_map from 0x%lx",
>-		       (long) priv->r_debug + lmo->r_map_offset);
>+		       (long) lm + lmo->r_map_offset);
>+	      break;
> 	    }
>-	}
>-    }
>
>-  std::string document = "<library-list-svr4 version=\"1.0\"";
>+	  read_link_map (document, lm_addr, lm_prev, ptr_size, lmo,
>+			 ignore_first, header_done);
>
>-  while (lm_addr
>-	 && read_one_ptr (lm_addr + lmo->l_name_offset,
>-			  &l_name, ptr_size) == 0
>-	 && read_one_ptr (lm_addr + lmo->l_addr_offset,
>-			  &l_addr, ptr_size) == 0
>-	 && read_one_ptr (lm_addr + lmo->l_ld_offset,
>-			  &l_ld, ptr_size) == 0
>-	 && read_one_ptr (lm_addr + lmo->l_prev_offset,
>-			  &l_prev, ptr_size) == 0
>-	 && read_one_ptr (lm_addr + lmo->l_next_offset,
>-			  &l_next, ptr_size) == 0)
>-    {
>-      unsigned char libname[PATH_MAX];
>+	  if (r_version < 2)
>+	    break;
>
>-      if (lm_prev != l_prev)
>-	{
>-	  warning ("Corrupted shared library list: 0x%lx != 0x%lx",
>-		   (long) lm_prev, (long) l_prev);
>-	  break;
>-	}
>+	  /* Only applies to the default namespace.  */
>+	  ignore_first = false;
>
>-      /* 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
>-	 skipped if the dynamic loader was loaded late by a static executable
>-	 (see solib-svr4.c parameter ignore_first).  But in such case the main
>-	 executable does not have PT_DYNAMIC present and this function already
>-	 exited above due to failed get_r_debug.  */
>-      if (lm_prev == 0)
>-	string_appendf (document, " main-lm=\"0x%lx\"", (unsigned long)
>lm_addr);
>-      else
>-	{
>-	  /* Not checking for error because reading may stop before
>-	     we've got PATH_MAX worth of characters.  */
>-	  libname[0] = '\0';
>-	  linux_read_memory (l_name, libname, sizeof (libname) - 1);
>-	  libname[sizeof (libname) - 1] = '\0';
>-	  if (libname[0] != '\0')
>+	  if (read_one_ptr (lm + lmo->r_next_offset, &lm, ptr_size) != 0)
> 	    {
>-	      if (!header_done)
>-		{
>-		  /* Terminate `<library-list-svr4'.  */
>-		  document += '>';
>-		  header_done = 1;
>-		}
>-
>-	      string_appendf (document, "<library name=\"");
>-	      xml_escape_text_append (&document, (char *) libname);
>-	      string_appendf (document, "\" lm=\"0x%lx\" "
>-			      "l_addr=\"0x%lx\" l_ld=\"0x%lx\"/>",
>-			      (unsigned long) lm_addr, (unsigned long) l_addr,
>-			      (unsigned long) l_ld);
>+	      warning ("unable to read r_next from 0x%lx",
>+		       (long) lm + lmo->r_next_offset);
>+	      break;
> 	    }
> 	}
>-
>-      lm_prev = lm_addr;
>-      lm_addr = l_next;
>     }
>
>   if (!header_done)
>--
>2.31.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


  reply	other threads:[~2022-01-21 11:43 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-17 14:28 Markus Metzger via Gdb-patches
2022-01-21 11:42 ` Metzger, Markus T via Gdb-patches [this message]
2022-03-01 19:10 ` Tom Tromey
2022-03-09 12:23   ` Metzger, Markus T via Gdb-patches
2022-03-03 18:32 ` Pedro Alves
2022-03-09 12:24   ` Metzger, Markus T via Gdb-patches
2022-03-09 14:15     ` Pedro Alves
2022-03-29 16:13       ` Metzger, Markus T via Gdb-patches
2022-04-08 12:40         ` Metzger, Markus T via Gdb-patches
2022-05-25 17:12 ` Kevin Buettner via Gdb-patches
2022-05-31  9:29   ` Metzger, Markus T via Gdb-patches
2022-05-31 18:44     ` Ben Woodard via Gdb-patches
2022-05-24 18:40 Ben Woodard via Gdb-patches

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DM8PR11MB5749D144899C9D7DA82A7A21DE5B9@DM8PR11MB5749.namprd11.prod.outlook.com \
    --to=gdb-patches@sourceware.org \
    --cc=markus.t.metzger@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox