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]

[rfc] Fix problem with (maybe) non-relocated .opd section on powerpc64-linux


Hello,

I've been running into problems when using the new_objfile observer to
set a breakpoint on a newly loaded library on powerpc64-linux.

The observer gets called when ld.so hits the _dl_debug_state breakpoint.
At this point, my code was retrieving a symbol from the new library and
setting a breakpoint.  As this is powerpc64-linux, this involves resolving
function descriptors, i.e. reading the target address from the .opd section.

Now the current ppc64_linux_convert_from_func_ptr_addr simply reads the
.opd contents from target memory.  However, there may in fact be relocations
that need to be applied to .opd.  Usually, this is not a problem, because
the _dl_debug_state breakpoint is hit only after ld.so has applied those
relocations to target memory.

However, this is not the case if the library is loaded via dlopen.  In this
case, the _dl_debug_state breakpoint is hit *before* relocations are applied.
(I guess this might be considered a bug in glibc.  But we have to live with
existing glibc's in the field anyway ...)

This is somewhat unfortunate, as I now cannot even manually apply the 
relocation (because it might already have been applied, and I cannot
find out whether or not this has actually happened).

So to solve this I'm now completely ignoring contents of .opd in target
memory, and instead always retrieve the contents from the BFD.  Those
will certainly be non-relocated, so applying the relocation offset by
hand will always result in the correct target address.

Is this a reasonable thing to do?


Tested on powerpc64-linux.

Bye,
Ulrich

ChangeLog:

	* ppc-linux-tdep.c (ppc64_linux_convert_from_func_ptr_addr): Read
	and manually relocate .opd contents from BFD instead of reading
	them from target memory.


diff -urNp gdb-orig/gdb/ppc-linux-tdep.c gdb-head/gdb/ppc-linux-tdep.c
--- gdb-orig/gdb/ppc-linux-tdep.c	2008-05-14 20:28:48.244451000 +0200
+++ gdb-head/gdb/ppc-linux-tdep.c	2008-05-14 21:11:35.672042314 +0200
@@ -591,7 +591,31 @@ ppc64_linux_convert_from_func_ptr_addr (
 
   /* Check if ADDR points to a function descriptor.  */
   if (s && strcmp (s->the_bfd_section->name, ".opd") == 0)
-    return get_target_memory_unsigned (targ, addr, 8);
+    {
+      /* There may be relocations that need to be applied to the .opd 
+	 section.  Unfortunately, this function may be called at a time
+	 where these relocations have not yet been performed -- this can
+	 happen for example shortly after a library has been loaded with
+	 dlopen, but ld.so has not yet applied the relocations.
+
+	 To cope with both the case where the relocation has been applied,
+	 and the case where it has not yet been applied, we do *not* read
+	 the (maybe) relocated value from target memory, but we instead
+	 read the non-relocated value from the BFD, and apply the relocation
+	 offset manually.
+
+	 This makes the assumption that all .opd entries are always relocated
+	 by the same offset the section itself was relocated.  */
+
+      gdb_byte buf[8];
+      int res;
+
+      res = bfd_get_section_contents (s->bfd, s->the_bfd_section,
+				      &buf, addr - s->addr, 8);
+      if (res != 0)
+	return extract_unsigned_integer (buf, 8)
+		- bfd_section_vma (s->bfd, s->the_bfd_section) + s->addr;
+   }
 
   return addr;
 }
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


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