This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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))

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]