This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH] gdbserver: Handle DT_MIPS_RLD_MAP dynamic tag
- From: "Maciej W. Rozycki" <macro at codesourcery dot com>
- To: <gdb-patches at sourceware dot org>
- Date: Tue, 3 Apr 2012 21:47:28 +0100
- Subject: [PATCH] gdbserver: Handle DT_MIPS_RLD_MAP dynamic tag
Hi,
While working on a test case for an unrelated issue I have noticed
single-stepping over system library calls is broken on the MIPS/Linux
target when `gdbserver' is used. On closer inspection I have observed
`gdbserver' reports no shared libraries loaded. Further investigation has
revealed that the newly-added support for the `qXfer:libraries-svr4:read'
packet does not handle the DT_MIPS_RLD_MAP dynamic tag and therefore
cannot locate the link map on the MIPS target.
Such support has been long present in gdb/solib-svr4.c, hence a fix
turned out rather mechanical; here's a piece of code ported from there
over to linux-low.c, likewise making no special exception just for the
MIPS platform and applying to generic code instead. This change has fixed
the single-stepping problem observed for me.
Just to be safe I have regression-tested this change for the
mips-linux-gnu remote target, o32/big-endian multilib (using an x86 Linux
host) with 139 failures removed starting from:
(gdb) PASS: gdb.base/break.exp: backtrace from factorial(5.1)
break exit
Function "exit" not defined.
(gdb) FAIL: gdb.base/break.exp: setting breakpoint at exit
and no new ones. I didn't test the change for any other target, but then
DT_MIPS_RLD_MAP tags are not expected to appear on non-MIPS binaries,
hence the "dyn->d_tag == DT_MIPS_RLD_MAP" conditional is not expected to
trigger there.
OK to apply?
2012-04-03 Maciej W. Rozycki <macro@codesourcery.com>
gdb/gdbserver/
* linux-low.c (get_r_debug): Handle DT_MIPS_RLD_MAP.
Maciej
gdb-gdbserver-rld-map.diff
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-low.c 2012-04-03 13:38:58.575561428 +0100
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-low.c 2012-04-03 13:39:17.315624148 +0100
@@ -5419,7 +5419,9 @@ get_dynamic (const int pid, const int is
}
/* Return &_r_debug in the inferior, or -1 if not present. Return value
- can be 0 if the inferior does not yet have the library list initialized. */
+ can be 0 if the inferior does not yet have the library list initialized.
+ We look for DT_MIPS_RLD_MAP first. MIPS executables use this instead of
+ DT_DEBUG, although they sometimes contain an unused DT_DEBUG entry too. */
static CORE_ADDR
get_r_debug (const int pid, const int is_elf64)
@@ -5437,6 +5439,21 @@ get_r_debug (const int pid, const int is
if (is_elf64)
{
Elf64_Dyn *const dyn = (Elf64_Dyn *) buf;
+ union
+ {
+ Elf64_Xword map;
+ unsigned char buf[sizeof (Elf64_Xword)];
+ }
+ rld_map;
+
+ if (dyn->d_tag == DT_MIPS_RLD_MAP)
+ {
+ if (linux_read_memory (dyn->d_un.d_val,
+ rld_map.buf, sizeof (rld_map.buf)) == 0)
+ return rld_map.map;
+ else
+ break;
+ }
if (dyn->d_tag == DT_DEBUG)
return dyn->d_un.d_val;
@@ -5447,6 +5464,21 @@ get_r_debug (const int pid, const int is
else
{
Elf32_Dyn *const dyn = (Elf32_Dyn *) buf;
+ union
+ {
+ Elf32_Word map;
+ unsigned char buf[sizeof (Elf32_Word)];
+ }
+ rld_map;
+
+ if (dyn->d_tag == DT_MIPS_RLD_MAP)
+ {
+ if (linux_read_memory (dyn->d_un.d_val,
+ rld_map.buf, sizeof (rld_map.buf)) == 0)
+ return rld_map.map;
+ else
+ break;
+ }
if (dyn->d_tag == DT_DEBUG)
return dyn->d_un.d_val;