This is the mail archive of the gdb@sources.redhat.com 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]

RE: relocation of shared libs not based at 0


Continuing a thread from a long time ago...

On NetBSD/MIPS I was having trouble with shared library references,
which is caused by wrong relocation processing in solib-svr4.c.

Back in February 2003, I proposed a patch for this, but the reaction
wasn't really encouraging and I wasn't happy with the diagnosis I had
made at that time, anyway.

Recently I went back to this and analyzed the problem better.

The issue is very simple: solib-svr4.c assumes that the LM_ADDR
entries in the library file headers are offsets from the start VMA of
the library to the start VMA of that section.  In fact, they are not;
they are the start VMA of the section before relocation.

If the library VMA (as linked) is zero, as is the case on many targets
such as x86, then these two interpretations are identical.  On MIPS,
the as-linked base VMA is 0x5ffe0000, so the existing code produces
the wrong answer.

At the end of the earlier discussion it was pointed out that the SysV
ABI requires all sections of a library to be relocated by the same
amount, and it seemed that NetBSD wasn't obeying that.

It turns out that it is; I was confused about this and muddled the
picture.  And that's what was wrong with my earlier patch.

So the real answer is simple: the LM_ADDR entries have to be adjusted
by the as-linked start VMA of the library.  The only problem I ran
into is that I couldn't find a clean way to obtain that value in gdb.
I did come up with something that worked; if there are better ways to
do this I would be interested.

My fix is in a modified 5.3, but the relevant source is unchanged from
5.3 to 6.0.  So attached is a diff for 6.0 that shows the fix I
described.  

	    paul

--- gdb/solib-svr4.c.orig	Fri Jun 13 17:56:27 2003
+++ gdb/solib-svr4.c	Mon Jan  5 12:29:49 2004
@@ -1375,8 +1375,29 @@
 svr4_relocate_section_addresses (struct so_list *so,
                                  struct section_table *sec)
 {
-  sec->addr    = svr4_truncate_ptr (sec->addr    + LM_ADDR (so));
-  sec->endaddr = svr4_truncate_ptr (sec->endaddr + LM_ADDR (so));
+  CORE_ADDR reloc;
+  
+  /* On NetBSD/MIPS at least, the library is mapped in two pieces.
+     The section headers describe this: each shows the unrelocated
+     virtual address of the section.  To figure out the relocated
+     address, we have to adjust these by the base VMA of the library.
+     
+     There isn't a really clean way to figure out the offset of each
+     section.  "filepos" doesn't do it, because that is the 
+     file-relative offset, not the VMA offset.
+
+     So what we do is this: 
+     Pick up the VMA (given by the header) of the first section,
+     and subtract from that its filepos.  That's the unrelocated VMA
+     of the library.  Subtract that from the unrelocated VMA
+     of each section to get its relocation bias; add that to the
+     library load address to get the relocated address.
+  */
+  reloc = so->sections->the_bfd_section->vma -
+          so->sections->the_bfd_section->filepos;
+
+  sec->endaddr = svr4_truncate_ptr (sec->endaddr - reloc + LM_ADDR (so));
+  sec->addr    = svr4_truncate_ptr (sec->addr - reloc + LM_ADDR (so));
 }
 
 


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