* RE: relocation of shared libs not based at 0
@ 2004-01-05 17:39 Paul Koning
2004-01-09 22:48 ` Kevin Buettner
0 siblings, 1 reply; 19+ messages in thread
From: Paul Koning @ 2004-01-05 17:39 UTC (permalink / raw)
To: gdb
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));
}
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: relocation of shared libs not based at 0
2004-01-05 17:39 relocation of shared libs not based at 0 Paul Koning
@ 2004-01-09 22:48 ` Kevin Buettner
0 siblings, 0 replies; 19+ messages in thread
From: Kevin Buettner @ 2004-01-09 22:48 UTC (permalink / raw)
To: Paul Koning, gdb
On Jan 5, 12:39pm, Paul Koning wrote:
> 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));
> }
I think something along these lines will be okay. It may even be okay
as is. I need to study the relationship between "vma" and "filepos"
to convince myself that it's okay.
I'll be very busy with other matters for the next couple of weeks. Would
you mind pinging me in a few weeks?
In the interim, I'd like to find out what the QNX folks think of this
patch. As I recall, QNX behaved in a similar fashion to NetBSD and
I'm wondering if Paul's patch would address those problems as well.
Kevin
^ permalink raw reply [flat|nested] 19+ messages in thread
* RE: relocation of shared libs not based at 0
@ 2003-02-12 18:37 Peter van der Veen
0 siblings, 0 replies; 19+ messages in thread
From: Peter van der Veen @ 2003-02-12 18:37 UTC (permalink / raw)
To: 'Kevin Buettner', 'Paul Koning'
Cc: Kris Warkentin, 'gdb@sources.redhat.com',
Peter van der Veen, Colin Burgess
> From: Kevin Buettner [mailto:kevinb@redhat.com]
>
> On Feb 10, 5:45pm, Paul Koning wrote:
>
> > >> 2. Hack gdb so it looks at the section headers in the shared
> > >> library file, to extract the start and length of the three
> > >> regions. Use that to identify the *ABS* symbols (i.e., p is bss
> > >> since it's within the vaddr range of the bss section in the
> > >> section headers), and then figure the correct relocation from
> > >> that.
> > >>
> > >> I can do (2), and that has the advantage of working with existing
> > >> binaries, but it seems ugly. (1) sounds right. There are two
> > >> issues there, though. One is that I don't know ld. The other is
> > >> that I'm guessing there must be SOME reason why *ABS* is used for
> > >> the mips case, though I can't imagine any reason.
> >
> > Kevin> (1) sounds right to me too, though I share your concern that
> > Kevin> there may be some reason that ABS must be used the way it is
> > Kevin> for mips. I think you ought to ask about this on the binutils
> > Kevin> list...
> >
> > Kevin> If you have to do (2), I strongly encourage you to create a
> > Kevin> new solib backend for it.
> >
> > I was looking at solib-svr4.c and found this interesting comment (in
> > svr4_relocate_main_executable):
> >
> > /* It is necessary to relocate the objfile. The amount to
> > relocate by is simply the address at which we are stopped
> > minus the starting address from the executable.
> >
> > We relocate all of the sections by the same amount. This
> > behavior is mandated by recent editions of the System V ABI.
> > According to the System V Application Binary Interface,
> > Edition 4.1, page 5-5:
> >
> > ... Though the system chooses virtual addresses for
> > individual processes, it maintains the segments' relative
> > positions. Because position-independent code uses relative
> > addressesing between segments, the difference between
> > virtual addresses in memory must match the difference
> > between virtual addresses in the file. The difference
> > between the virtual address of any segment in memory and
> > the corresponding virtual address in the file is thus a
> > single constant value for any one executable or shared
> > object in a given process. This difference is the base
> > address. One use of the base address is to relocate the
> > memory image of the program during dynamic linking.
> >
> > The same language also appears in Edition 4.0 of the System V
> > ABI and is left unspecified in some of the earlier editions. */
> >
> > So if I read that right, it sounds like the NetBSD practice of doing
> > separate mappings for the text, data, and bss sections (rather than
> > leaving them at the same relative offset they were in the library
> > file) violates the SVR4 spec.
>
> Yes, upon rereading that comment, I agree with you.
>
> If you haven't already done so, you may want to take a look at the ABI
> yourself to make sure that the comment quotes the ABI correctly and
> to understand the context of the quote. I wrote that comment, and
> I believe it to be accurate with sufficient context, but it doesn't
> hurt for someone else to double check.
>
> You should also take a look at the processor specific supplement. I
> don't think that the processor supplement will override the text
> quoted above from the generic part of the specification, but this
> possibility should be checked before declaring the NetBSD
> implementation wrong.
>
> > Very interesting. I'm not sure what to make of this. It doesn't feel
> > like a bug; the NetBSD behavior certainly makes sense.
> >
> > That suggests at least two other approaches:
> >
> > 3. Change NetBSD ld.elf_so to do what the ABI spec requires, which
> > means just one mapped region rather than three.
> >
> > 4. Change the linker so ld.elf_so can still use three regions, i.e.,
> > align the start of each region on a page boundary.
> >
> > Yikes. Now what? I may end up just doing (2) for the sake of
> > in-house expedience, and hope someone more skilled in the art will
> > tackle the "right" solution.
>
> If NetBSD wants to comply with the System V ABI (and if I've
> interpreted the text of the ABI correctly), then the dynamic linker
> needs fixing.
I'm not sure if this is what you are referring to, but here is what I have
observed. The System V ABI makes statements about base address, and relative
to that document base address is consistent. But the base address in the
l_addr field in link.h is not the same base address that the system V abi is
talking about. I think problems started when someone saw these both referred
to as "base address" and assumed they both where the same value. l_addr is
the address of the library at load time, but not the same value as the base
address in the ABI. I would think your comment that the NETBSD behaviour
does not feel like a bug is correct. I think the linux ld.so may treat both
base addresses as being the same thing, but I am not sure.
>
> I can understand wanting to do (2) for expediency's sake. If you do
> so, please create a new solib backend. Basically, this will consist
> of making a copy of solib-svr4.c and hacking on it 'til it works as
> desired. (Some small configury changes will also be needed.)
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: relocation of shared libs not based at 0
@ 2002-12-17 13:39 David Anderson
0 siblings, 0 replies; 19+ messages in thread
From: David Anderson @ 2002-12-17 13:39 UTC (permalink / raw)
To: gdb
"Kris Warkentin" <kewarken@qnx.com> writes:
>Can anyone with more knowledge than I enlighten me as to a) whether it is
>proper to allow shared objects to be non zero-based and b) a better way to
>do this. I looked at putting it in solib-svr4.c but I don't have access to
>the bfd in there, at least in svr4_relocate_section_addresses().
While I cannot speak for gdb requirements, I can say
that there is no requirement in generic-SYSV that shared
objects start at a zero address.
SGI IRIX (which is SYSV based) has never used zero as the base
address for shared objects, but always pre-assigns a non-zero
base address at static link time (intending that the shared
object will start up faster if it can run at that address).
Regards
David B. Anderson davea@sgi.com http://reality.sgiweb.org/davea
[ "What could go wrong?" -- Calvin ]
^ permalink raw reply [flat|nested] 19+ messages in thread
* relocation of shared libs not based at 0
@ 2002-12-17 12:23 Kris Warkentin
2002-12-17 12:31 ` Paul Koning
2002-12-17 16:28 ` Kevin Buettner
0 siblings, 2 replies; 19+ messages in thread
From: Kris Warkentin @ 2002-12-17 12:23 UTC (permalink / raw)
To: gdb
I recently came across a problem debugging a core file with some of our
older shared libs. Info shared showed the relocations of the shared libs to
be mangled (offset to 0x60... range rather than 0xb0... range). We had
recently changed our tools to always set the vaddr of shared libs to be zero
because of this but I was speaking to one of our architects and he says that
this shouldn't be.
One of the future optimizations we're looking at is pre-relocating shared
libs so that they can be executed in place (on flash for instance) and the
fact that the SysV stuff seems to assume that everything is based at zero is
not particularily compatable with that. I've attached an ugly patch that
shows a fix. This is for illustration only since solib.c is the wrong place
to put this but it makes it clear what the issue is.
Can anyone with more knowledge than I enlighten me as to a) whether it is
proper to allow shared objects to be non zero-based and b) a better way to
do this. I looked at putting it in solib-svr4.c but I don't have access to
the bfd in there, at least in svr4_relocate_section_addresses().
cheers,
Kris
Index: solib.c
===================================================================
RCS file: /product/tools/gdb/gdb/solib.c,v
retrieving revision 1.4
diff -c -r1.4 solib.c
*** solib.c 14 Nov 2002 20:57:23 -0000 1.4
--- solib.c 17 Dec 2002 20:10:14 -0000
***************
*** 26,31 ****
--- 26,34 ----
#include <fcntl.h>
#include "gdb_string.h"
#include "symtab.h"
+ #ifdef __QNXTARGET__
+ #include "elf-bfd.h"
+ #endif
#include "bfd.h"
#include "symfile.h"
#include "objfiles.h"
***************
*** 206,211 ****
--- 209,229 ----
expansion stuff?).
*/
+ #ifdef __QNXTARGET__
+ Elf_Internal_Phdr *find_load_phdr( bfd *abfd )
+ {
+ Elf32_Internal_Phdr *phdr;
+ unsigned int i;
+
+ phdr = elf_tdata (abfd)->phdr;
+ for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++) {
+ if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
+ return phdr;
+ }
+ return NULL;
+ }
+ #endif
+
static int
solib_map_sections (PTR arg)
{
***************
*** 263,268 ****
--- 281,296 ----
object's file by the base address to which the object was
actually
mapped. */
TARGET_SO_RELOCATE_SECTION_ADDRESSES (so, p);
+ #ifdef __QNXTARGET__
+ /* hack for solibs not based at 0 */
+ {
+ Elf32_Internal_Phdr *phdr = find_load_phdr(abfd);
+ if(phdr){
+ p->addr -= phdr->p_vaddr;
+ p->endaddr -= phdr->p_vaddr;
+ }
+ }
+ #endif
if (STREQ (p->the_bfd_section->name, ".text"))
{
so->textsection = p;
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: relocation of shared libs not based at 0
2002-12-17 12:23 Kris Warkentin
@ 2002-12-17 12:31 ` Paul Koning
2002-12-17 13:36 ` Kris Warkentin
2002-12-17 16:28 ` Kevin Buettner
1 sibling, 1 reply; 19+ messages in thread
From: Paul Koning @ 2002-12-17 12:31 UTC (permalink / raw)
To: kewarken; +Cc: gdb
>>>>> "Kris" == Kris Warkentin <kewarken@qnx.com> writes:
Kris> I recently came across a problem debugging a core file with
Kris> some of our older shared libs. Info shared showed the
Kris> relocations of the shared libs to be mangled (offset to
Kris> 0x60... range rather than 0xb0... range). We had recently
Kris> changed our tools to always set the vaddr of shared libs to be
Kris> zero because of this but I was speaking to one of our
Kris> architects and he says that this shouldn't be.
Kris> One of the future optimizations we're looking at is
Kris> pre-relocating shared libs so that they can be executed in
Kris> place (on flash for instance) and the fact that the SysV stuff
Kris> seems to assume that everything is based at zero is not
Kris> particularily compatable with that. I've attached an ugly
Kris> patch that shows a fix. This is for illustration only since
Kris> solib.c is the wrong place to put this but it makes it clear
Kris> what the issue is.
Kris> Can anyone with more knowledge than I enlighten me as to a)
Kris> whether it is proper to allow shared objects to be non
Kris> zero-based and b) a better way to do this. I looked at putting
Kris> it in solib-svr4.c but I don't have access to the bfd in there,
Kris> at least in svr4_relocate_section_addresses().
I ran into the same problem when trying to get gdb to deal correctly
with shared libs on NetBSD/MIPS. The following patch is my attempt at
dealing with it. I haven't tried to turn this into a patch submission
because I don't trust my gdb hacking skills yet. Also, I was
concentrating on "making it work" (for NetBSD/MIPS, the platform we
needed to get right) rather than "doing the right thing" for gdb
generally. BTW, this is a patch against a snapshot of 5.3 taken a few
months ago.
paul
diff -u -r1.1.1.2 -r1.2
--- console_gdb/gdb/solib-svr4.c 2002/10/03 19:50:00 1.1.1.2
+++ console_gdb/gdb/solib-svr4.c 2002/10/07 20:45:23 1.2
@@ -1259,8 +1259,24 @@
svr4_relocate_section_addresses (struct so_list *so,
struct section_table *sec)
{
+#if 0 /* wrong: LM_ADDR is the assigned address, not the offset */
sec->addr = svr4_truncate_ptr (sec->addr + LM_ADDR (so));
sec->endaddr = svr4_truncate_ptr (sec->endaddr + LM_ADDR (so));
+#else
+ /* The addresses are formed as follows:
+ LM_ADDR is the target address where the shared library file
+ is mapped.
+ So the actual section start address is LM_ADDR plus the section
+ offset within the shared library file. The end address is that
+ plus the section length. Note that we pay no attention to the
+ section start address as recorded in the library header.
+ */
+ sec->endaddr = svr4_truncate_ptr (sec->endaddr - sec->addr +
+ sec->the_bfd_section->filepos +
+ LM_ADDR (so));
+ sec->addr = svr4_truncate_ptr (sec->the_bfd_section->filepos +
+ LM_ADDR (so));
+#endif
}
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: relocation of shared libs not based at 0
2002-12-17 12:31 ` Paul Koning
@ 2002-12-17 13:36 ` Kris Warkentin
0 siblings, 0 replies; 19+ messages in thread
From: Kris Warkentin @ 2002-12-17 13:36 UTC (permalink / raw)
To: Paul Koning; +Cc: gdb
> I ran into the same problem when trying to get gdb to deal correctly
> with shared libs on NetBSD/MIPS. The following patch is my attempt at
> dealing with it. I haven't tried to turn this into a patch submission
> because I don't trust my gdb hacking skills yet. Also, I was
> concentrating on "making it work" (for NetBSD/MIPS, the platform we
> needed to get right) rather than "doing the right thing" for gdb
> generally. BTW, this is a patch against a snapshot of 5.3 taken a few
> months ago.
Thanks Paul. I like that fix a lot better and it seems to have the same
effect as mine. Can anyone else on the list make any comment about why gdb
assumes that relocations are based at zero?
cheers,
Kris
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: relocation of shared libs not based at 0
2002-12-17 12:23 Kris Warkentin
2002-12-17 12:31 ` Paul Koning
@ 2002-12-17 16:28 ` Kevin Buettner
2002-12-17 16:47 ` Paul Koning
1 sibling, 1 reply; 19+ messages in thread
From: Kevin Buettner @ 2002-12-17 16:28 UTC (permalink / raw)
To: Kris Warkentin, gdb
On Dec 17, 3:23pm, Kris Warkentin wrote:
> I recently came across a problem debugging a core file with some of our
> older shared libs. Info shared showed the relocations of the shared libs to
> be mangled (offset to 0x60... range rather than 0xb0... range). We had
> recently changed our tools to always set the vaddr of shared libs to be zero
> because of this but I was speaking to one of our architects and he says that
> this shouldn't be.
>
> One of the future optimizations we're looking at is pre-relocating shared
> libs so that they can be executed in place (on flash for instance) and the
> fact that the SysV stuff seems to assume that everything is based at zero is
> not particularily compatable with that. I've attached an ugly patch that
> shows a fix. This is for illustration only since solib.c is the wrong place
> to put this but it makes it clear what the issue is.
>
> Can anyone with more knowledge than I enlighten me as to a) whether it is
> proper to allow shared objects to be non zero-based and b) a better way to
> do this. I looked at putting it in solib-svr4.c but I don't have access to
> the bfd in there, at least in svr4_relocate_section_addresses().
With regard to a), it's okay for shared objects to be non-zero based.
We'll get to b) in a bit...
Let's first take a look at the existing code in GDB's solib-svr4.c:
static void
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));
}
This code is adjusting the start and end addresses by LM_ADDR (so) which
is simply the l_addr field obtained from struct link_map.
On my i386 GNU/Linux system, the comment in link.h says that l_addr is
the "base address shared object is loaded at." We must be very careful
with the term "base address" because it's quite possible that it means
something very different than what you think it does. (I certainly found
it counter-intuitive.)
Here is what chapter 5 of the "System V Application Binary Interface,
Edition 4.1" says about the term "Base Address":
As "Program Loading" in this chapter of the processor supplement
describes, the virtual addresses in the program headers might not
represent the actual virtual addresses of the program's memory
image. Executable files typically contain absolute code. To let
the process execute correctly, the segments must reside at the
virtual addresses used to build the executable file. On the other
hand, shared object segments typically contain
position-independent code. This lets a segment's virtual address
change from one process to another, without invalidating execu-
tion behavior. Though the system chooses virtual addresses for
individual processes, it maintains the segments' relative
positions. Because position- independent code uses relative
addressing between segments, the difference between virtual
addresses in memory must match the difference between virtual
addresses in the file. The difference between the virtual address
of any segment in memory and the corresponding virtual address in
the file is thus a single constant value for any one executable or
shared object in a given process. This difference is the base
address. One use of the base address is to relocate the memory
image of the program during dynamic linking.
An executable or shared object file's base address is calculated
during execution from three values: the virtual memory load
address, the maximum page size, and M the lowest virtual address
of a program's loadable segment. To compute the base address, one
determines the memory address associated with the lowest p_vaddr
value for a PT_LOAD segment. This address is truncated to the
nearest multiple of the maximum page size. The corresponding
p_vaddr value itself is also truncated to the nearest multiple of
the maximum page size. The base address is the difference between
the truncated memory address and the truncated p_vaddr value.
See this chapter in the processor supplement for more information
and examples. "Operating System Interface" of Chapter 3 in the
processor supplement contains more information about the virtual
address space and page size.
So, as I understand it, the "base address" is *not* an absolute
location, but is actually the difference between where the segment
ended up and the location assigned to it in the executable file.
Thus the "base address" is the proper value to use to relocate the
segment's start and end addresses.
Now, it's possible that my understanding is flawed. If so, I await
enlightenment. I think it's also possible that the shared library
implementation that you're using might not conform to the above
definition of "base address". If that's the case, then you can either
attempt to get it fixed in the code which implements the dynamic
loader, or, if that's not possible, create a new solib backend for gdb
which implements support for your shared library machinery. I suspect
it would be very similar to solib-svr4.c.
With regard to the two patches that have been posted for fixing this
problem, I don't think that either one is correct in light of the
above definition of "base address".
Kevin
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: relocation of shared libs not based at 0
2002-12-17 16:28 ` Kevin Buettner
@ 2002-12-17 16:47 ` Paul Koning
2003-01-08 21:52 ` Kris Warkentin
0 siblings, 1 reply; 19+ messages in thread
From: Paul Koning @ 2002-12-17 16:47 UTC (permalink / raw)
To: kevinb; +Cc: kewarken, gdb
>>>>> "Kevin" == Kevin Buettner <kevinb@redhat.com> writes:
Kevin> ...
Kevin> So, as I understand it, the "base address" is *not* an
Kevin> absolute location, but is actually the difference between
Kevin> where the segment ended up and the location assigned to it in
Kevin> the executable file. Thus the "base address" is the proper
Kevin> value to use to relocate the segment's start and end
Kevin> addresses.
That interpretation certainly matches the code. The document you
quoted is not all that clearly worded, but it seems to take the same
view of things.
On the other hand, the shared library loader in NetBSD doesn't. It
sets the "base address" in the link_map to the load address of the
section, not the bias from the link address to the load address.
That's why I changed solib-svr4.c in my copy of gdb.
Perhaps a better fix is to change the loader in NetBSD to set "base
address" to match gdb's expectations.
Kevin> Now, it's possible that my understanding is flawed. If so, I
Kevin> await enlightenment. I think it's also possible that the
Kevin> shared library implementation that you're using might not
Kevin> conform to the above definition of "base address". If that's
Kevin> the case, then you can either attempt to get it fixed in the
Kevin> code which implements the dynamic loader, or, if that's not
Kevin> possible, create a new solib backend for gdb which implements
Kevin> support for your shared library machinery. I suspect it would
Kevin> be very similar to solib-svr4.c.
Kevin> With regard to the two patches that have been posted for
Kevin> fixing this problem, I don't think that either one is correct
Kevin> in light of the above definition of "base address".
It would be interesting to hear from a NetBSD wizard. I'd be happy
with any fix that makes shared libs work in gdb for my platform.
Part of the reason why I patched gdb rather than ldd.elf_so is so I
could process coredumps from already shipped systems. Then again,
there are few enough of those that this isn't a big consideration.
paul
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: relocation of shared libs not based at 0
2002-12-17 16:47 ` Paul Koning
@ 2003-01-08 21:52 ` Kris Warkentin
2003-01-08 22:24 ` Kevin Buettner
2003-02-05 18:40 ` Paul Koning
0 siblings, 2 replies; 19+ messages in thread
From: Kris Warkentin @ 2003-01-08 21:52 UTC (permalink / raw)
To: Paul Koning, kevinb; +Cc: gdb, Peter van der Veen, Colin Burgess
I've been spending some time chasing this issue since it's fairly important
to us. It looks to me like Paul is correct in his assessment that the
shared library loader is the problem. Apparently, on NetBSD and QNX, the
loader uses the load address of the section as the base address. Linux (and
perhaps others) use the difference between the link address and the load
address.
What I had done to examine this was build shared libs with the normal 0
v_addr and also created some with an ld that had
"SHLIB_TEXT_START_ADDR=0xb0300000" (or some such) defined in its linker
script. This would give me a library with characteristics like so:
kewarken@stimpy:~/test$ objdump -p libodd.so
libodd.so: file format elf32-i386
Program Header:
LOAD off 0x00000000 vaddr 0xb0300000 paddr 0xb0300000 align 2**12
filesz 0x00000804 memsz 0x00000804 flags r-x
Now I wasn't able to get this test to work on Solaris - programs linked to a
lib built this way would always crash when the loader ran. On Linux,
however, I could link a program to one of these libs and check it out in the
debugger. Just as Paul suggested, the run-time linker had filled in the
l_addr field in the link_map with 0 so "info shared" would show something
like:
From To Syms Read Shared Object Library
0x00000640 0x000007e0 Yes ./libodd.so
0x40037f80 0x40119260 Yes /lib/libc.so.6
instead of:
From To Syms Read Shared Object Library
0xb0300640 0xb03007e0 Yes ./libodd.so
0x40037f80 0x40119260 Yes /lib/libc.so.6
This works fine on QNX and (I assume) NetBSD so it looks rather like we just
have a difference of opinion on how the shared object loader should fill
things in. We wanted to keep our linker's behaviour for some future
enhancements (pre-relocating shared objects on flash memory, etc.) so I was
hoping the fix below (Paul's code with some extra comments) might be
acceptable. That way Paul and I could just define LM_ADDR_IS_NOT_LOAD_BASE
in our tm-<host>.h and we'd be off to the races.
static void
svr4_relocate_section_addresses (struct so_list *so,
struct section_table *sec)
{
#if LM_ADDR_IS_NOT_LOAD_BASE
/* On some platforms, (ie. QNX, NetBSD) LM_ADDR is the assigned
address, not the offset.
The addresses are formed as follows:
LM_ADDR is the target address where the shared library file
is mapped, so the actual section start address is LM_ADDR plus
the section offset within the shared library file. The end
address is that plus the section length. Note that we pay no
attention to the section start address as recorded in the
library header.
*/
sec->endaddr = svr4_truncate_ptr (sec->endaddr - sec->addr +
sec->the_bfd_section->filepos +
LM_ADDR (so));
sec->addr = svr4_truncate_ptr (sec->the_bfd_section->filepos +
LM_ADDR (so));
#else
sec->addr = svr4_truncate_ptr (sec->addr + LM_ADDR (so));
sec->endaddr = svr4_truncate_ptr (sec->endaddr + LM_ADDR (so));
#endif
}
----- Original Message -----
From: "Paul Koning" <pkoning@equallogic.com>
To: <kevinb@redhat.com>
Cc: <kewarken@qnx.com>; <gdb@sources.redhat.com>
Sent: Tuesday, December 17, 2002 7:47 PM
Subject: Re: relocation of shared libs not based at 0
> >>>>> "Kevin" == Kevin Buettner <kevinb@redhat.com> writes:
>
> Kevin> ...
> Kevin> So, as I understand it, the "base address" is *not* an
> Kevin> absolute location, but is actually the difference between
> Kevin> where the segment ended up and the location assigned to it in
> Kevin> the executable file. Thus the "base address" is the proper
> Kevin> value to use to relocate the segment's start and end
> Kevin> addresses.
>
> That interpretation certainly matches the code. The document you
> quoted is not all that clearly worded, but it seems to take the same
> view of things.
>
> On the other hand, the shared library loader in NetBSD doesn't. It
> sets the "base address" in the link_map to the load address of the
> section, not the bias from the link address to the load address.
> That's why I changed solib-svr4.c in my copy of gdb.
>
> Perhaps a better fix is to change the loader in NetBSD to set "base
> address" to match gdb's expectations.
>
> Kevin> Now, it's possible that my understanding is flawed. If so, I
> Kevin> await enlightenment. I think it's also possible that the
> Kevin> shared library implementation that you're using might not
> Kevin> conform to the above definition of "base address". If that's
> Kevin> the case, then you can either attempt to get it fixed in the
> Kevin> code which implements the dynamic loader, or, if that's not
> Kevin> possible, create a new solib backend for gdb which implements
> Kevin> support for your shared library machinery. I suspect it would
> Kevin> be very similar to solib-svr4.c.
>
> Kevin> With regard to the two patches that have been posted for
> Kevin> fixing this problem, I don't think that either one is correct
> Kevin> in light of the above definition of "base address".
>
> It would be interesting to hear from a NetBSD wizard. I'd be happy
> with any fix that makes shared libs work in gdb for my platform.
>
> Part of the reason why I patched gdb rather than ldd.elf_so is so I
> could process coredumps from already shipped systems. Then again,
> there are few enough of those that this isn't a big consideration.
>
> paul
>
>
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: relocation of shared libs not based at 0
2003-01-08 21:52 ` Kris Warkentin
@ 2003-01-08 22:24 ` Kevin Buettner
2003-01-09 14:35 ` Colin Burgess
2003-02-05 18:40 ` Paul Koning
1 sibling, 1 reply; 19+ messages in thread
From: Kevin Buettner @ 2003-01-08 22:24 UTC (permalink / raw)
To: Kris Warkentin, Paul Koning, kevinb
Cc: gdb, Peter van der Veen, Colin Burgess
On Jan 8, 4:52pm, Kris Warkentin wrote:
> This works fine on QNX and (I assume) NetBSD so it looks rather like we just
> have a difference of opinion on how the shared object loader should fill
> things in. We wanted to keep our linker's behaviour for some future
> enhancements (pre-relocating shared objects on flash memory, etc.) so I was
> hoping the fix below (Paul's code with some extra comments) might be
> acceptable. That way Paul and I could just define LM_ADDR_IS_NOT_LOAD_BASE
> in our tm-<host>.h and we'd be off to the races.
>
> static void
> svr4_relocate_section_addresses (struct so_list *so,
> struct section_table *sec)
> {
> #if LM_ADDR_IS_NOT_LOAD_BASE
> /* On some platforms, (ie. QNX, NetBSD) LM_ADDR is the assigned
> address, not the offset.
> The addresses are formed as follows:
> LM_ADDR is the target address where the shared library file
> is mapped, so the actual section start address is LM_ADDR plus
> the section offset within the shared library file. The end
> address is that plus the section length. Note that we pay no
> attention to the section start address as recorded in the
> library header.
> */
> sec->endaddr = svr4_truncate_ptr (sec->endaddr - sec->addr +
> sec->the_bfd_section->filepos +
> LM_ADDR (so));
> sec->addr = svr4_truncate_ptr (sec->the_bfd_section->filepos +
> LM_ADDR (so));
> #else
> sec->addr = svr4_truncate_ptr (sec->addr + LM_ADDR (so));
> sec->endaddr = svr4_truncate_ptr (sec->endaddr + LM_ADDR (so));
> #endif
> }
The problem that I have with the above is that it's not possible to
build a cross debugger that'll have shared library support for both
Linux and NetBSD.
If we could somehow detect (perhaps via the osabi mechanism) that we
have one of the lm-addr-is-not-load-base platforms and enable that
code at runtime, I wouldn't mind...
Kevin
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: relocation of shared libs not based at 0
2003-01-08 22:24 ` Kevin Buettner
@ 2003-01-09 14:35 ` Colin Burgess
2003-01-09 15:06 ` Kris Warkentin
0 siblings, 1 reply; 19+ messages in thread
From: Colin Burgess @ 2003-01-09 14:35 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Kris Warkentin, Paul Koning, gdb, Peter van der Veen
You already have architecture dependant code in fetch_link_map_offsets, couldn't
you do something similar for relocate_section_addresses?
On Wed, 8 Jan 2003, Kevin Buettner wrote:
> On Jan 8, 4:52pm, Kris Warkentin wrote:
>
> > This works fine on QNX and (I assume) NetBSD so it looks rather like we just
> > have a difference of opinion on how the shared object loader should fill
> > things in. We wanted to keep our linker's behaviour for some future
> > enhancements (pre-relocating shared objects on flash memory, etc.) so I was
> > hoping the fix below (Paul's code with some extra comments) might be
> > acceptable. That way Paul and I could just define LM_ADDR_IS_NOT_LOAD_BASE
> > in our tm-<host>.h and we'd be off to the races.
> >
> > static void
> > svr4_relocate_section_addresses (struct so_list *so,
> > struct section_table *sec)
> > {
> > #if LM_ADDR_IS_NOT_LOAD_BASE
> > /* On some platforms, (ie. QNX, NetBSD) LM_ADDR is the assigned
> > address, not the offset.
> > The addresses are formed as follows:
> > LM_ADDR is the target address where the shared library file
> > is mapped, so the actual section start address is LM_ADDR plus
> > the section offset within the shared library file. The end
> > address is that plus the section length. Note that we pay no
> > attention to the section start address as recorded in the
> > library header.
> > */
> > sec->endaddr = svr4_truncate_ptr (sec->endaddr - sec->addr +
> > sec->the_bfd_section->filepos +
> > LM_ADDR (so));
> > sec->addr = svr4_truncate_ptr (sec->the_bfd_section->filepos +
> > LM_ADDR (so));
> > #else
> > sec->addr = svr4_truncate_ptr (sec->addr + LM_ADDR (so));
> > sec->endaddr = svr4_truncate_ptr (sec->endaddr + LM_ADDR (so));
> > #endif
> > }
>
> The problem that I have with the above is that it's not possible to
> build a cross debugger that'll have shared library support for both
> Linux and NetBSD.
>
> If we could somehow detect (perhaps via the osabi mechanism) that we
> have one of the lm-addr-is-not-load-base platforms and enable that
> code at runtime, I wouldn't mind...
>
> Kevin
>
--
cburgess@qnx.com
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: relocation of shared libs not based at 0
2003-01-09 14:35 ` Colin Burgess
@ 2003-01-09 15:06 ` Kris Warkentin
0 siblings, 0 replies; 19+ messages in thread
From: Kris Warkentin @ 2003-01-09 15:06 UTC (permalink / raw)
To: Colin Burgess, Kevin Buettner; +Cc: Paul Koning, gdb, Peter van der Veen
Well, there's certainly nothing to stop us from changing
current_target_so_ops->relocate_section_addresses to point to our own
function. The only issue with that is that initialization is then order
dependent. We would just have to make sure that _initialize_svr4_solib()
gets called before _initialize_some_qnx_specific_stuff(). I can certainly
see the point of not wanting to break cross compilation so perhaps I'll just
try to do it this way.
cheers,
Kris
----- Original Message -----
From: "Colin Burgess" <cburgess@qnx.com>
To: "Kevin Buettner" <kevinb@redhat.com>
Cc: "Kris Warkentin" <kewarken@qnx.com>; "Paul Koning"
<pkoning@equallogic.com>; <gdb@sources.redhat.com>; "Peter van der Veen"
<peterv@qnx.com>
Sent: Thursday, January 09, 2003 9:37 AM
Subject: Re: relocation of shared libs not based at 0
> You already have architecture dependant code in fetch_link_map_offsets,
couldn't
> you do something similar for relocate_section_addresses?
>
> On Wed, 8 Jan 2003, Kevin Buettner wrote:
>
> > On Jan 8, 4:52pm, Kris Warkentin wrote:
> >
> > > This works fine on QNX and (I assume) NetBSD so it looks rather like
we just
> > > have a difference of opinion on how the shared object loader should
fill
> > > things in. We wanted to keep our linker's behaviour for some future
> > > enhancements (pre-relocating shared objects on flash memory, etc.) so
I was
> > > hoping the fix below (Paul's code with some extra comments) might be
> > > acceptable. That way Paul and I could just define
LM_ADDR_IS_NOT_LOAD_BASE
> > > in our tm-<host>.h and we'd be off to the races.
> > >
> > > static void
> > > svr4_relocate_section_addresses (struct so_list *so,
> > > struct section_table *sec)
> > > {
> > > #if LM_ADDR_IS_NOT_LOAD_BASE
> > > /* On some platforms, (ie. QNX, NetBSD) LM_ADDR is the assigned
> > > address, not the offset.
> > > The addresses are formed as follows:
> > > LM_ADDR is the target address where the shared library file
> > > is mapped, so the actual section start address is LM_ADDR plus
> > > the section offset within the shared library file. The end
> > > address is that plus the section length. Note that we pay no
> > > attention to the section start address as recorded in the
> > > library header.
> > > */
> > > sec->endaddr = svr4_truncate_ptr (sec->endaddr - sec->addr +
> > > sec->the_bfd_section->filepos +
> > > LM_ADDR (so));
> > > sec->addr = svr4_truncate_ptr (sec->the_bfd_section->filepos +
> > > LM_ADDR (so));
> > > #else
> > > sec->addr = svr4_truncate_ptr (sec->addr + LM_ADDR (so));
> > > sec->endaddr = svr4_truncate_ptr (sec->endaddr + LM_ADDR (so));
> > > #endif
> > > }
> >
> > The problem that I have with the above is that it's not possible to
> > build a cross debugger that'll have shared library support for both
> > Linux and NetBSD.
> >
> > If we could somehow detect (perhaps via the osabi mechanism) that we
> > have one of the lm-addr-is-not-load-base platforms and enable that
> > code at runtime, I wouldn't mind...
> >
> > Kevin
> >
>
> --
> cburgess@qnx.com
>
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: relocation of shared libs not based at 0
2003-01-08 21:52 ` Kris Warkentin
2003-01-08 22:24 ` Kevin Buettner
@ 2003-02-05 18:40 ` Paul Koning
2003-02-05 19:08 ` Kris Warkentin
2003-02-05 19:11 ` Kevin Buettner
1 sibling, 2 replies; 19+ messages in thread
From: Paul Koning @ 2003-02-05 18:40 UTC (permalink / raw)
To: kewarken; +Cc: kevinb, gdb, peterv, cburgess
I'm resurrecting this thread to bring up a problem that's closely
related.
On mips-netbsd, even after fixing the relocation problem (e.g., by the
patch I proposed earlier) gdb still has problems. Specifically, it
computes the wrong address for data within the shared library.
After doing battle with various parts of gdb for quite some time, I
finally realized what the issue is. What puzzled me is that it works
just fine on netbsd-i386. That finally led me to the answer...
The reason can be seen by looking at the symbol table. Here are
(partial) objdump runs, first for i386, then for mips:
mainx86/libf3.so: file format elf32-i386
SYMBOL TABLE:
000006fc l F .text 0000002b _strrchr
00000000 F *UND* 00000000 __syscall
0000083c w F .text 00000033 dlerror
00000000 F *UND* 0000002b printf
00001b80 g O .bss 00000004 __mainprog_obj
00001b88 g O .bss 00000004 p
00000934 g F .text 00000041 f3
mainmips/libf3.so: file format elf32-littlemips
SYMBOL TABLE:
5ffe10f0 F *UND* 00000034 __syscall
5ffe0e20 w F *ABS* 00000000 dlerror
5ffe1100 F *UND* 00000068 printf
60021314 g O *ABS* 00000004 p
5ffe1040 g F *ABS* 000000ac f3
The difference is that the mips symbol table has all symbols as *ABS*,
whether they are text (functions) or data.
When the library is loaded, text and data are relocated separately
since they are two separate mmap regions. So the relocation bias is
different for the two. The i386 case works because the symbols are
correctly marked as to which region they belong to (text, data, bss).
But the mips case doesn't have that, so all symbol relocation is done
as if the symbols were text. The data and bss offsets are fine as
file offsets, but because the parts are mapped separately they are NOT
valid as memory address offsets.
I'm wondering what the right way to fix this is. Two ways come to
mind:
1. Fix ld so it puts the right section designations on the symbols,
just as in the i386 case.
2. Hack gdb so it looks at the section headers in the shared library
file, to extract the start and length of the three regions. Use
that to identify the *ABS* symbols (i.e., p is bss since it's
within the vaddr range of the bss section in the section headers),
and then figure the correct relocation from that.
I can do (2), and that has the advantage of working with existing
binaries, but it seems ugly. (1) sounds right. There are two issues
there, though. One is that I don't know ld. The other is that I'm
guessing there must be SOME reason why *ABS* is used for the mips
case, though I can't imagine any reason.
Suggestions would be much appreciated.
paul
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: relocation of shared libs not based at 0
2003-02-05 18:40 ` Paul Koning
@ 2003-02-05 19:08 ` Kris Warkentin
2003-02-05 19:11 ` Kevin Buettner
1 sibling, 0 replies; 19+ messages in thread
From: Kris Warkentin @ 2003-02-05 19:08 UTC (permalink / raw)
To: Paul Koning; +Cc: kevinb, gdb, peterv, cburgess
I ran into the same problem: GDB was calculating that data in a shared lib
was off by a page (1k hex) which was very annoying. The original patch that
I had submitted doesn't seem to have this problem though so I went back and
re-inserted it.
The following is the code that I put into our qnx specific files. All I did
then was set
current_target_so_ops->relocate_section_addresses =
qnx_relocate_section_addresses to override the System V behaviour and all my
problems went away.
cheers,
Kris
#include "solist.h"
#include "solib-svr4.h"
/* struct lm_info, LM_ADDR and qnx_truncate_ptr are copied from
solib-svr4.c to support qnx_relocate_section_addresses which is different
from the svr4 version. */
struct lm_info
{
/* Pointer to copy of link map from inferior. The type is char *
rather than void *, so that we may use byte offsets to find the
various fields without the need for a cast. */
char *lm;
};
static CORE_ADDR
LM_ADDR (struct so_list *so)
{
struct link_map_offsets *lmo = SVR4_FETCH_LINK_MAP_OFFSETS ();
return (CORE_ADDR) extract_signed_integer (so->lm_info->lm +
lmo->l_addr_offset,
lmo->l_addr_size);
}
static CORE_ADDR
qnx_truncate_ptr (CORE_ADDR addr)
{
if (TARGET_PTR_BIT == sizeof (CORE_ADDR) * 8)
/* We don't need to truncate anything, and the bit twiddling below
will fail due to overflow problems. */
return addr;
else
return addr & (((CORE_ADDR) 1 << TARGET_PTR_BIT) - 1);
}
#include "elf-bfd.h"
Elf_Internal_Phdr *find_load_phdr( bfd *abfd )
{
Elf32_Internal_Phdr *phdr;
unsigned int i;
phdr = elf_tdata (abfd)->phdr;
for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++) {
if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X))
return phdr;
}
return NULL;
}
static void
qnx_relocate_section_addresses (struct so_list *so,
struct section_table *sec)
{
Elf32_Internal_Phdr *phdr = find_load_phdr(sec->bfd);
unsigned vaddr = phdr?phdr->p_vaddr:0;
sec->addr = qnx_truncate_ptr (sec->addr + LM_ADDR (so) - vaddr);
sec->endaddr = qnx_truncate_ptr (sec->endaddr + LM_ADDR (so) - vaddr);
}
----- Original Message -----
From: "Paul Koning" <pkoning@equallogic.com>
To: <kewarken@qnx.com>
Cc: <kevinb@redhat.com>; <gdb@sources.redhat.com>; <peterv@qnx.com>;
<cburgess@qnx.com>
Sent: Wednesday, February 05, 2003 2:40 PM
Subject: Re: relocation of shared libs not based at 0
> I'm resurrecting this thread to bring up a problem that's closely
> related.
>
> On mips-netbsd, even after fixing the relocation problem (e.g., by the
> patch I proposed earlier) gdb still has problems. Specifically, it
> computes the wrong address for data within the shared library.
>
> After doing battle with various parts of gdb for quite some time, I
> finally realized what the issue is. What puzzled me is that it works
> just fine on netbsd-i386. That finally led me to the answer...
>
> The reason can be seen by looking at the symbol table. Here are
> (partial) objdump runs, first for i386, then for mips:
>
> mainx86/libf3.so: file format elf32-i386
>
> SYMBOL TABLE:
> 000006fc l F .text 0000002b _strrchr
> 00000000 F *UND* 00000000 __syscall
> 0000083c w F .text 00000033 dlerror
> 00000000 F *UND* 0000002b printf
> 00001b80 g O .bss 00000004 __mainprog_obj
> 00001b88 g O .bss 00000004 p
> 00000934 g F .text 00000041 f3
>
> mainmips/libf3.so: file format elf32-littlemips
>
> SYMBOL TABLE:
> 5ffe10f0 F *UND* 00000034 __syscall
> 5ffe0e20 w F *ABS* 00000000 dlerror
> 5ffe1100 F *UND* 00000068 printf
> 60021314 g O *ABS* 00000004 p
> 5ffe1040 g F *ABS* 000000ac f3
>
> The difference is that the mips symbol table has all symbols as *ABS*,
> whether they are text (functions) or data.
>
> When the library is loaded, text and data are relocated separately
> since they are two separate mmap regions. So the relocation bias is
> different for the two. The i386 case works because the symbols are
> correctly marked as to which region they belong to (text, data, bss).
> But the mips case doesn't have that, so all symbol relocation is done
> as if the symbols were text. The data and bss offsets are fine as
> file offsets, but because the parts are mapped separately they are NOT
> valid as memory address offsets.
>
> I'm wondering what the right way to fix this is. Two ways come to
> mind:
>
> 1. Fix ld so it puts the right section designations on the symbols,
> just as in the i386 case.
>
> 2. Hack gdb so it looks at the section headers in the shared library
> file, to extract the start and length of the three regions. Use
> that to identify the *ABS* symbols (i.e., p is bss since it's
> within the vaddr range of the bss section in the section headers),
> and then figure the correct relocation from that.
>
> I can do (2), and that has the advantage of working with existing
> binaries, but it seems ugly. (1) sounds right. There are two issues
> there, though. One is that I don't know ld. The other is that I'm
> guessing there must be SOME reason why *ABS* is used for the mips
> case, though I can't imagine any reason.
>
> Suggestions would be much appreciated.
>
> paul
>
>
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: relocation of shared libs not based at 0
2003-02-05 18:40 ` Paul Koning
2003-02-05 19:08 ` Kris Warkentin
@ 2003-02-05 19:11 ` Kevin Buettner
2003-02-10 21:45 ` Paul Koning
1 sibling, 1 reply; 19+ messages in thread
From: Kevin Buettner @ 2003-02-05 19:11 UTC (permalink / raw)
To: Paul Koning, kewarken; +Cc: kevinb, gdb, peterv, cburgess
On Feb 5, 2:40pm, Paul Koning wrote:
> I'm resurrecting this thread to bring up a problem that's closely
> related.
>
> On mips-netbsd, even after fixing the relocation problem (e.g., by the
> patch I proposed earlier) gdb still has problems. Specifically, it
> computes the wrong address for data within the shared library.
>
> After doing battle with various parts of gdb for quite some time, I
> finally realized what the issue is. What puzzled me is that it works
> just fine on netbsd-i386. That finally led me to the answer...
>
> The reason can be seen by looking at the symbol table. Here are
> (partial) objdump runs, first for i386, then for mips:
>
> mainx86/libf3.so: file format elf32-i386
>
> SYMBOL TABLE:
> 000006fc l F .text 0000002b _strrchr
> 00000000 F *UND* 00000000 __syscall
> 0000083c w F .text 00000033 dlerror
> 00000000 F *UND* 0000002b printf
> 00001b80 g O .bss 00000004 __mainprog_obj
> 00001b88 g O .bss 00000004 p
> 00000934 g F .text 00000041 f3
>
> mainmips/libf3.so: file format elf32-littlemips
>
> SYMBOL TABLE:
> 5ffe10f0 F *UND* 00000034 __syscall
> 5ffe0e20 w F *ABS* 00000000 dlerror
> 5ffe1100 F *UND* 00000068 printf
> 60021314 g O *ABS* 00000004 p
> 5ffe1040 g F *ABS* 000000ac f3
>
> The difference is that the mips symbol table has all symbols as *ABS*,
> whether they are text (functions) or data.
>
> When the library is loaded, text and data are relocated separately
> since they are two separate mmap regions. So the relocation bias is
> different for the two. The i386 case works because the symbols are
> correctly marked as to which region they belong to (text, data, bss).
> But the mips case doesn't have that, so all symbol relocation is done
> as if the symbols were text. The data and bss offsets are fine as
> file offsets, but because the parts are mapped separately they are NOT
> valid as memory address offsets.
>
> I'm wondering what the right way to fix this is. Two ways come to
> mind:
>
> 1. Fix ld so it puts the right section designations on the symbols,
> just as in the i386 case.
>
> 2. Hack gdb so it looks at the section headers in the shared library
> file, to extract the start and length of the three regions. Use
> that to identify the *ABS* symbols (i.e., p is bss since it's
> within the vaddr range of the bss section in the section headers),
> and then figure the correct relocation from that.
>
> I can do (2), and that has the advantage of working with existing
> binaries, but it seems ugly. (1) sounds right. There are two issues
> there, though. One is that I don't know ld. The other is that I'm
> guessing there must be SOME reason why *ABS* is used for the mips
> case, though I can't imagine any reason.
(1) sounds right to me too, though I share your concern that there may
be some reason that ABS must be used the way it is for mips. I think
you ought to ask about this on the binutils list...
If you have to do (2), I strongly encourage you to create a new solib
backend for it.
Kevin
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: relocation of shared libs not based at 0
2003-02-05 19:11 ` Kevin Buettner
@ 2003-02-10 21:45 ` Paul Koning
2003-02-12 18:06 ` Kevin Buettner
0 siblings, 1 reply; 19+ messages in thread
From: Paul Koning @ 2003-02-10 21:45 UTC (permalink / raw)
To: kevinb; +Cc: kewarken, gdb, peterv, cburgess
>>>>> "Kevin" == Kevin Buettner <kevinb@redhat.com> writes:
Kevin> On Feb 5, 2:40pm, Paul Koning wrote:
>> I'm resurrecting this thread to bring up a problem that's closely
>> related.
>>
>> On mips-netbsd, even after fixing the relocation problem (e.g., by
>> the patch I proposed earlier) gdb still has problems.
>> Specifically, it computes the wrong address for data within the
>> shared library....
>>
>> When the library is loaded, text and data are relocated separately
>> since they are two separate mmap regions. So the relocation bias
>> is different for the two. The i386 case works because the symbols
>> are correctly marked as to which region they belong to (text,
>> data, bss). But the mips case doesn't have that, so all symbol
>> relocation is done as if the symbols were text. The data and bss
>> offsets are fine as file offsets, but because the parts are mapped
>> separately they are NOT valid as memory address offsets.
>>
>> I'm wondering what the right way to fix this is. Two ways come to
>> mind:
>>
>> 1. Fix ld so it puts the right section designations on the
>> symbols, just as in the i386 case.
>>
>> 2. Hack gdb so it looks at the section headers in the shared
>> library file, to extract the start and length of the three
>> regions. Use that to identify the *ABS* symbols (i.e., p is bss
>> since it's within the vaddr range of the bss section in the
>> section headers), and then figure the correct relocation from
>> that.
>>
>> I can do (2), and that has the advantage of working with existing
>> binaries, but it seems ugly. (1) sounds right. There are two
>> issues there, though. One is that I don't know ld. The other is
>> that I'm guessing there must be SOME reason why *ABS* is used for
>> the mips case, though I can't imagine any reason.
Kevin> (1) sounds right to me too, though I share your concern that
Kevin> there may be some reason that ABS must be used the way it is
Kevin> for mips. I think you ought to ask about this on the binutils
Kevin> list...
Kevin> If you have to do (2), I strongly encourage you to create a
Kevin> new solib backend for it.
I was looking at solib-svr4.c and found this interesting comment (in
svr4_relocate_main_executable):
/* It is necessary to relocate the objfile. The amount to
relocate by is simply the address at which we are stopped
minus the starting address from the executable.
We relocate all of the sections by the same amount. This
behavior is mandated by recent editions of the System V ABI.
According to the System V Application Binary Interface,
Edition 4.1, page 5-5:
... Though the system chooses virtual addresses for
individual processes, it maintains the segments' relative
positions. Because position-independent code uses relative
addressesing between segments, the difference between
virtual addresses in memory must match the difference
between virtual addresses in the file. The difference
between the virtual address of any segment in memory and
the corresponding virtual address in the file is thus a
single constant value for any one executable or shared
object in a given process. This difference is the base
address. One use of the base address is to relocate the
memory image of the program during dynamic linking.
The same language also appears in Edition 4.0 of the System V
ABI and is left unspecified in some of the earlier editions. */
So if I read that right, it sounds like the NetBSD practice of doing
separate mappings for the text, data, and bss sections (rather than
leaving them at the same relative offset they were in the library
file) violates the SVR4 spec.
Very interesting. I'm not sure what to make of this. It doesn't feel
like a bug; the NetBSD behavior certainly makes sense.
That suggests at least two other approaches:
3. Change NetBSD ld.elf_so to do what the ABI spec requires, which
means just one mapped region rather than three.
4. Change the linker so ld.elf_so can still use three regions, i.e.,
align the start of each region on a page boundary.
Yikes. Now what? I may end up just doing (2) for the sake of
in-house expedience, and hope someone more skilled in the art will
tackle the "right" solution.
paul
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: relocation of shared libs not based at 0
2003-02-10 21:45 ` Paul Koning
@ 2003-02-12 18:06 ` Kevin Buettner
2003-02-12 18:19 ` Kris Warkentin
0 siblings, 1 reply; 19+ messages in thread
From: Kevin Buettner @ 2003-02-12 18:06 UTC (permalink / raw)
To: Paul Koning, kevinb; +Cc: kewarken, gdb, peterv, cburgess
On Feb 10, 5:45pm, Paul Koning wrote:
> >> 2. Hack gdb so it looks at the section headers in the shared
> >> library file, to extract the start and length of the three
> >> regions. Use that to identify the *ABS* symbols (i.e., p is bss
> >> since it's within the vaddr range of the bss section in the
> >> section headers), and then figure the correct relocation from
> >> that.
> >>
> >> I can do (2), and that has the advantage of working with existing
> >> binaries, but it seems ugly. (1) sounds right. There are two
> >> issues there, though. One is that I don't know ld. The other is
> >> that I'm guessing there must be SOME reason why *ABS* is used for
> >> the mips case, though I can't imagine any reason.
>
> Kevin> (1) sounds right to me too, though I share your concern that
> Kevin> there may be some reason that ABS must be used the way it is
> Kevin> for mips. I think you ought to ask about this on the binutils
> Kevin> list...
>
> Kevin> If you have to do (2), I strongly encourage you to create a
> Kevin> new solib backend for it.
>
> I was looking at solib-svr4.c and found this interesting comment (in
> svr4_relocate_main_executable):
>
> /* It is necessary to relocate the objfile. The amount to
> relocate by is simply the address at which we are stopped
> minus the starting address from the executable.
>
> We relocate all of the sections by the same amount. This
> behavior is mandated by recent editions of the System V ABI.
> According to the System V Application Binary Interface,
> Edition 4.1, page 5-5:
>
> ... Though the system chooses virtual addresses for
> individual processes, it maintains the segments' relative
> positions. Because position-independent code uses relative
> addressesing between segments, the difference between
> virtual addresses in memory must match the difference
> between virtual addresses in the file. The difference
> between the virtual address of any segment in memory and
> the corresponding virtual address in the file is thus a
> single constant value for any one executable or shared
> object in a given process. This difference is the base
> address. One use of the base address is to relocate the
> memory image of the program during dynamic linking.
>
> The same language also appears in Edition 4.0 of the System V
> ABI and is left unspecified in some of the earlier editions. */
>
> So if I read that right, it sounds like the NetBSD practice of doing
> separate mappings for the text, data, and bss sections (rather than
> leaving them at the same relative offset they were in the library
> file) violates the SVR4 spec.
Yes, upon rereading that comment, I agree with you.
If you haven't already done so, you may want to take a look at the ABI
yourself to make sure that the comment quotes the ABI correctly and
to understand the context of the quote. I wrote that comment, and
I believe it to be accurate with sufficient context, but it doesn't
hurt for someone else to double check.
You should also take a look at the processor specific supplement. I
don't think that the processor supplement will override the text
quoted above from the generic part of the specification, but this
possibility should be checked before declaring the NetBSD
implementation wrong.
> Very interesting. I'm not sure what to make of this. It doesn't feel
> like a bug; the NetBSD behavior certainly makes sense.
>
> That suggests at least two other approaches:
>
> 3. Change NetBSD ld.elf_so to do what the ABI spec requires, which
> means just one mapped region rather than three.
>
> 4. Change the linker so ld.elf_so can still use three regions, i.e.,
> align the start of each region on a page boundary.
>
> Yikes. Now what? I may end up just doing (2) for the sake of
> in-house expedience, and hope someone more skilled in the art will
> tackle the "right" solution.
If NetBSD wants to comply with the System V ABI (and if I've
interpreted the text of the ABI correctly), then the dynamic linker
needs fixing.
I can understand wanting to do (2) for expediency's sake. If you do
so, please create a new solib backend. Basically, this will consist
of making a copy of solib-svr4.c and hacking on it 'til it works as
desired. (Some small configury changes will also be needed.)
Kevin
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: relocation of shared libs not based at 0
2003-02-12 18:06 ` Kevin Buettner
@ 2003-02-12 18:19 ` Kris Warkentin
0 siblings, 0 replies; 19+ messages in thread
From: Kris Warkentin @ 2003-02-12 18:19 UTC (permalink / raw)
To: Kevin Buettner, Paul Koning; +Cc: gdb, peterv, cburgess
> I can understand wanting to do (2) for expediency's sake. If you do
> so, please create a new solib backend. Basically, this will consist
> of making a copy of solib-svr4.c and hacking on it 'til it works as
> desired. (Some small configury changes will also be needed.)
I was actually able to cheat without creating a whole new backend just by
overriding svr4_relocate_section_addresses in one of my backend files. That
way I only had to grab a couple support functions from solib-svr4.c
cheers,
Kris
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2004-01-09 22:48 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-01-05 17:39 relocation of shared libs not based at 0 Paul Koning
2004-01-09 22:48 ` Kevin Buettner
-- strict thread matches above, loose matches on Subject: below --
2003-02-12 18:37 Peter van der Veen
2002-12-17 13:39 David Anderson
2002-12-17 12:23 Kris Warkentin
2002-12-17 12:31 ` Paul Koning
2002-12-17 13:36 ` Kris Warkentin
2002-12-17 16:28 ` Kevin Buettner
2002-12-17 16:47 ` Paul Koning
2003-01-08 21:52 ` Kris Warkentin
2003-01-08 22:24 ` Kevin Buettner
2003-01-09 14:35 ` Colin Burgess
2003-01-09 15:06 ` Kris Warkentin
2003-02-05 18:40 ` Paul Koning
2003-02-05 19:08 ` Kris Warkentin
2003-02-05 19:11 ` Kevin Buettner
2003-02-10 21:45 ` Paul Koning
2003-02-12 18:06 ` Kevin Buettner
2003-02-12 18:19 ` Kris Warkentin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox