This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
RE: [PATCH, MIPS] Support shared library debug with MIPS PIE (gdb)
- From: Matthew Fortune <Matthew dot Fortune at imgtec dot com>
- To: "gdb-patches at sourceware dot org" <gdb-patches at sourceware dot org>
- Cc: Joseph Myers <joseph at codesourcery dot com>
- Date: Fri, 26 Jun 2015 12:45:22 +0000
- Subject: RE: [PATCH, MIPS] Support shared library debug with MIPS PIE (gdb)
- Authentication-results: sourceware.org; auth=none
- References: <6D39441BF12EF246A7ABCE6654B02353211760FA at LEMAIL01 dot le dot imgtec dot org> <alpine dot DEB dot 2 dot 10 dot 1506231529530 dot 4489 at digraph dot polyomino dot org dot uk>
Joseph Myers <joseph@codesourcery.com> writes:
> On Tue, 23 Jun 2015, Matthew Fortune wrote:
>
> > Please note that the new DT_MIPS_RLD_MAP2 support will not be enabled
> > unless the host's elf.h header has the new tag defined in it. For
> > cross compiled GDB this may mean hacking the solib-svr4.c file to
> > define the macro until such time as distributions update glibc.
>
> That doesn't make any sense to me. Hosts (e.g. MinGW) may not have
> elf.h at all. GDB should get these definitions from the #include
> "elf/mips.h"
> already in solib-svr4.c (i.e. from toplevel's include/elf/mips.h). And
> so there should be no #ifdefs there.
Updated version below to match the name of the new tag as committed to
binutils and removed the #ifdefs from solib-svr4.c.
binutils commit: a5499fa Add support for DT_MIPS_RLD_MAP_REL.
OK to commit?
Thanks,
Matthew
This tag allows debugging of MIPS position independent executables
and provides access to shared library information.
gdb/gdbserver/
* linux-low.c (get_r_debug): Handle DT_MIPS_RLD_MAP_REL.
gdb/
* solib-svr4.c (read_program_header): Add base_addr argument to
report the runtime address of the segment.
(find_program_interpreter): Update read_program_header call to pass
a NULL pointer for the new argument.
(scan_dyntag): Add ptr_addr argument to report the runtime address
of the tag payload.
(scan_dyntag_auxv): Likewise and use thew new base_addr argument of
read_program_header to get the base address of the dynamic segment.
(elf_locate_base): Update uses of scan_dyntag, scan_dyntag_auxv and
read_program_header.
(elf_locate_base): Scan for and handle DT_MIPS_RLD_MAP_REL.
---
gdb/ChangeLog | 14 +++++++++++
gdb/gdbserver/ChangeLog | 4 +++
gdb/gdbserver/linux-low.c | 30 +++++++++++++++++++---
gdb/solib-svr4.c | 63 +++++++++++++++++++++++++++++++++++------------
4 files changed, 91 insertions(+), 20 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 659f9b7..766c02f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,17 @@
+2015-06-26 Matthew Fortune <matthew.fortune@imgtec.com>
+
+ * solib-svr4.c (read_program_header): Add base_addr argument to
+ report the runtime address of the segment.
+ (find_program_interpreter): Update read_program_header call to pass
+ a NULL pointer for the new argument.
+ (scan_dyntag): Add ptr_addr argument to report the runtime address
+ of the tag payload.
+ (scan_dyntag_auxv): Likewise and use thew new base_addr argument of
+ read_program_header to get the base address of the dynamic segment.
+ (elf_locate_base): Update uses of scan_dyntag, scan_dyntag_auxv and
+ read_program_header.
+ (elf_locate_base): Scan for and handle DT_MIPS_RLD_MAP_REL.
+
2015-06-25 Gary Benson <gbenson@redhat.com>
* solib.c (solib_find_1): Set local variable sysroot to NULL if
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 2528f0f..6e37863 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,7 @@
+2015-06-26 Matthew Fortune <matthew.fortune@imgtec.com>
+
+ * linux-low.c (get_r_debug): Handle DT_MIPS_RLD_MAP_REL.
+
2015-06-24 Gary Benson <gbenson@redhat.com>
* linux-i386-ipa.c (stdint.h): Do not include.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 3774d17..ed18e24 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -6102,14 +6102,15 @@ get_r_debug (const int pid, const int is_elf64)
if (is_elf64)
{
Elf64_Dyn *const dyn = (Elf64_Dyn *) buf;
-#ifdef DT_MIPS_RLD_MAP
+#if defined DT_MIPS_RLD_MAP || defined DT_MIPS_RLD_MAP_REL
union
{
Elf64_Xword map;
unsigned char buf[sizeof (Elf64_Xword)];
}
rld_map;
-
+#endif
+#ifdef DT_MIPS_RLD_MAP
if (dyn->d_tag == DT_MIPS_RLD_MAP)
{
if (linux_read_memory (dyn->d_un.d_val,
@@ -6119,6 +6120,16 @@ get_r_debug (const int pid, const int is_elf64)
break;
}
#endif /* DT_MIPS_RLD_MAP */
+#ifdef DT_MIPS_RLD_MAP_REL
+ if (dyn->d_tag == DT_MIPS_RLD_MAP_REL)
+ {
+ if (linux_read_memory (dyn->d_un.d_val + dynamic_memaddr,
+ rld_map.buf, sizeof (rld_map.buf)) == 0)
+ return rld_map.map;
+ else
+ break;
+ }
+#endif /* DT_MIPS_RLD_MAP_REL */
if (dyn->d_tag == DT_DEBUG && map == -1)
map = dyn->d_un.d_val;
@@ -6129,14 +6140,15 @@ get_r_debug (const int pid, const int is_elf64)
else
{
Elf32_Dyn *const dyn = (Elf32_Dyn *) buf;
-#ifdef DT_MIPS_RLD_MAP
+#if defined DT_MIPS_RLD_MAP || defined DT_MIPS_RLD_MAP_REL
union
{
Elf32_Word map;
unsigned char buf[sizeof (Elf32_Word)];
}
rld_map;
-
+#endif
+#ifdef DT_MIPS_RLD_MAP
if (dyn->d_tag == DT_MIPS_RLD_MAP)
{
if (linux_read_memory (dyn->d_un.d_val,
@@ -6146,6 +6158,16 @@ get_r_debug (const int pid, const int is_elf64)
break;
}
#endif /* DT_MIPS_RLD_MAP */
+#ifdef DT_MIPS_RLD_MAP_REL
+ if (dyn->d_tag == DT_MIPS_RLD_MAP_REL)
+ {
+ if (linux_read_memory (dyn->d_un.d_val + dynamic_memaddr,
+ rld_map.buf, sizeof (rld_map.buf)) == 0)
+ return rld_map.map;
+ else
+ break;
+ }
+#endif /* DT_MIPS_RLD_MAP_REL */
if (dyn->d_tag == DT_DEBUG && map == -1)
map = dyn->d_un.d_val;
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 909dfb7..a71fb82 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -443,10 +443,12 @@ static int match_main (const char *);
Return a pointer to allocated memory holding the program header contents,
or NULL on failure. If sucessful, and unless P_SECT_SIZE is NULL, the
size of those contents is returned to P_SECT_SIZE. Likewise, the target
- architecture size (32-bit or 64-bit) is returned to P_ARCH_SIZE. */
+ architecture size (32-bit or 64-bit) is returned to P_ARCH_SIZE and
+ the base address of the section is returned in BASE_ADDR. */
static gdb_byte *
-read_program_header (int type, int *p_sect_size, int *p_arch_size)
+read_program_header (int type, int *p_sect_size, int *p_arch_size,
+ CORE_ADDR *base_addr)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
CORE_ADDR at_phdr, at_phent, at_phnum, pt_phdr = 0;
@@ -576,6 +578,8 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size)
*p_arch_size = arch_size;
if (p_sect_size)
*p_sect_size = sect_size;
+ if (base_addr)
+ *base_addr = sect_addr;
return buf;
}
@@ -605,7 +609,7 @@ find_program_interpreter (void)
/* If we didn't find it, use the target auxillary vector. */
if (!buf)
- buf = read_program_header (PT_INTERP, NULL, NULL);
+ buf = read_program_header (PT_INTERP, NULL, NULL, NULL);
return (char *) buf;
}
@@ -615,7 +619,8 @@ find_program_interpreter (void)
found, 1 is returned and the corresponding PTR is set. */
static int
-scan_dyntag (const int desired_dyntag, bfd *abfd, CORE_ADDR *ptr)
+scan_dyntag (const int desired_dyntag, bfd *abfd, CORE_ADDR *ptr,
+ CORE_ADDR *ptr_addr)
{
int arch_size, step, sect_size;
long current_dyntag;
@@ -695,13 +700,15 @@ scan_dyntag (const int desired_dyntag, bfd *abfd, CORE_ADDR *ptr)
{
struct type *ptr_type;
gdb_byte ptr_buf[8];
- CORE_ADDR ptr_addr;
+ CORE_ADDR ptr_addr_1;
ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
- ptr_addr = dyn_addr + (buf - bufstart) + arch_size / 8;
- if (target_read_memory (ptr_addr, ptr_buf, arch_size / 8) == 0)
+ ptr_addr_1 = dyn_addr + (buf - bufstart) + arch_size / 8;
+ if (target_read_memory (ptr_addr_1, ptr_buf, arch_size / 8) == 0)
dyn_ptr = extract_typed_address (ptr_buf, ptr_type);
*ptr = dyn_ptr;
+ if (ptr_addr)
+ *ptr_addr = dyn_addr + (buf - bufstart);
}
return 1;
}
@@ -715,16 +722,19 @@ scan_dyntag (const int desired_dyntag, bfd *abfd, CORE_ADDR *ptr)
is returned and the corresponding PTR is set. */
static int
-scan_dyntag_auxv (const int desired_dyntag, CORE_ADDR *ptr)
+scan_dyntag_auxv (const int desired_dyntag, CORE_ADDR *ptr,
+ CORE_ADDR *ptr_addr)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
int sect_size, arch_size, step;
long current_dyntag;
CORE_ADDR dyn_ptr;
+ CORE_ADDR base_addr;
gdb_byte *bufend, *bufstart, *buf;
/* Read in .dynamic section. */
- buf = bufstart = read_program_header (PT_DYNAMIC, §_size, &arch_size);
+ buf = bufstart = read_program_header (PT_DYNAMIC, §_size, &arch_size,
+ &base_addr);
if (!buf)
return 0;
@@ -761,6 +771,9 @@ scan_dyntag_auxv (const int desired_dyntag, CORE_ADDR *ptr)
if (ptr)
*ptr = dyn_ptr;
+ if (ptr_addr)
+ *ptr_addr = base_addr + buf - bufstart;
+
xfree (bufstart);
return 1;
}
@@ -786,13 +799,13 @@ static CORE_ADDR
elf_locate_base (void)
{
struct bound_minimal_symbol msymbol;
- CORE_ADDR dyn_ptr;
+ CORE_ADDR dyn_ptr, dyn_ptr_addr;
/* Look for DT_MIPS_RLD_MAP first. MIPS executables use this
instead of DT_DEBUG, although they sometimes contain an unused
DT_DEBUG. */
- if (scan_dyntag (DT_MIPS_RLD_MAP, exec_bfd, &dyn_ptr)
- || scan_dyntag_auxv (DT_MIPS_RLD_MAP, &dyn_ptr))
+ if (scan_dyntag (DT_MIPS_RLD_MAP, exec_bfd, &dyn_ptr, NULL)
+ || scan_dyntag_auxv (DT_MIPS_RLD_MAP, &dyn_ptr, NULL))
{
struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
gdb_byte *pbuf;
@@ -806,9 +819,27 @@ elf_locate_base (void)
return extract_typed_address (pbuf, ptr_type);
}
+ /* Then check DT_MIPS_RLD_MAP_REL. MIPS executables now use this form
+ because of needing to support PIE. DT_MIPS_RLD_MAP will also exist
+ in non-PIE. */
+ if (scan_dyntag (DT_MIPS_RLD_MAP_REL, exec_bfd, &dyn_ptr, &dyn_ptr_addr)
+ || scan_dyntag_auxv (DT_MIPS_RLD_MAP_REL, &dyn_ptr, &dyn_ptr_addr))
+ {
+ struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
+ gdb_byte *pbuf;
+ int pbuf_size = TYPE_LENGTH (ptr_type);
+
+ pbuf = alloca (pbuf_size);
+ /* DT_MIPS_RLD_MAP_REL contains an offset from the address of the
+ DT slot to the address of the dynamic link structure. */
+ if (target_read_memory (dyn_ptr + dyn_ptr_addr, pbuf, pbuf_size))
+ return 0;
+ return extract_typed_address (pbuf, ptr_type);
+ }
+
/* Find DT_DEBUG. */
- if (scan_dyntag (DT_DEBUG, exec_bfd, &dyn_ptr)
- || scan_dyntag_auxv (DT_DEBUG, &dyn_ptr))
+ if (scan_dyntag (DT_DEBUG, exec_bfd, &dyn_ptr, NULL)
+ || scan_dyntag_auxv (DT_DEBUG, &dyn_ptr, NULL))
return dyn_ptr;
/* This may be a static executable. Look for the symbol
@@ -2607,7 +2638,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
gdb_byte *buf, *buf2;
int arch_size;
- buf = read_program_header (-1, &phdrs_size, &arch_size);
+ buf = read_program_header (-1, &phdrs_size, &arch_size, NULL);
buf2 = read_program_headers_from_bfd (exec_bfd, &phdrs2_size);
if (buf != NULL && buf2 != NULL)
{
@@ -3228,7 +3259,7 @@ elf_lookup_lib_symbol (struct objfile *objfile,
abfd = objfile->obfd;
}
- if (abfd == NULL || scan_dyntag (DT_SYMBOLIC, abfd, NULL) != 1)
+ if (abfd == NULL || scan_dyntag (DT_SYMBOLIC, abfd, NULL, NULL) != 1)
return NULL;
return lookup_global_symbol_from_objfile (objfile, name, domain);
--
2.2.1