This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[patch] Relocate phdr in read_program_header
- From: Aleksandar Ristovski <aristovski at qnx dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: Fri, 30 Sep 2011 15:31:33 -0400
- Subject: [patch] Relocate phdr in read_program_header
Hello,
When attaching to a process without the executable file, gdb reads
pheaders from the target (solib-svr4.c: read_program_header).
However, it does not take into account possibility of having PIE
executable on the other end, resulting in trying to read from
unrelocated phdr address.
This patch addresses the issue by looking for PT_PHDR; if found, uses it
to determine relocation and adjusts address before reading it from
target memory.
Testsuite on x86_64-unknown-linux-gnu did not show any regressions.
Thanks,
Aleksandar Ristovski
QNX Software Systems
... Aleksandar Ristovski <aristovski@qnx.com>
* solib-svr4.c (read_program_header): If PT_PHDR is present, use it
to calculate correct address in case of PIE.
Index: gdb/solib-svr4.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-svr4.c,v
retrieving revision 1.154
diff -u -p -r1.154 solib-svr4.c
--- gdb/solib-svr4.c 30 Aug 2011 02:48:05 -0000 1.154
+++ gdb/solib-svr4.c 30 Sep 2011 17:47:13 -0000
@@ -385,7 +385,7 @@ static gdb_byte *
read_program_header (int type, int *p_sect_size, int *p_arch_size)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
- CORE_ADDR at_phdr, at_phent, at_phnum;
+ CORE_ADDR at_phdr, at_phent, at_phnum, pt_phdr;
int arch_size, sect_size;
CORE_ADDR sect_addr;
gdb_byte *buf;
@@ -408,6 +408,10 @@ read_program_header (int type, int *p_se
else
return 0;
+ pt_phdr = (CORE_ADDR)-1; /* Address of the first entry. If not PIE,
+ this will be zero.
+ For PIE, it will be unrelocated at_phdr. */
+
/* Find the requested segment. */
if (type == -1)
{
@@ -427,6 +431,11 @@ read_program_header (int type, int *p_se
return 0;
if (extract_unsigned_integer ((gdb_byte *)phdr.p_type,
+ 4, byte_order) == PT_PHDR)
+ pt_phdr = extract_unsigned_integer ((gdb_byte *)phdr.p_vaddr,
+ 4, byte_order);
+
+ if (extract_unsigned_integer ((gdb_byte *)phdr.p_type,
4, byte_order) == type)
break;
}
@@ -453,6 +462,11 @@ read_program_header (int type, int *p_se
return 0;
if (extract_unsigned_integer ((gdb_byte *)phdr.p_type,
+ 4, byte_order) == PT_PHDR)
+ pt_phdr = extract_unsigned_integer ((gdb_byte *)phdr.p_vaddr,
+ 8, byte_order);
+
+ if (extract_unsigned_integer ((gdb_byte *)phdr.p_type,
4, byte_order) == type)
break;
}
@@ -467,6 +481,16 @@ read_program_header (int type, int *p_se
8, byte_order);
}
+ /* at_phdr is real address in memory. pt_phdr is what pheader says it is.
+ Relocation offset is the difference between the two. */
+ if (pt_phdr != (CORE_ADDR)-1)
+ {
+ /* PT_PHDR is optional in the execution view, but we really need it
+ for PIE to make this work in general. However, if not found,
+ work with what you have. */
+ sect_addr = sect_addr + (at_phdr - pt_phdr);
+ }
+
/* Read in requested program header. */
buf = xmalloc (sect_size);
if (target_read_memory (sect_addr, buf, sect_size))