This is the mail archive of the binutils@sourceware.cygnus.com mailing list for the binutils project.


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

Re: A glibc dynamic linker or gld bug?


> Date: 7 Jul 1999 14:21:41 -0400
> From: Ian Lance Taylor <ian@zembu.com>
> CC: rth@twiddle.net, hjl@lucon.org, drepper@cygnus.com,
>         binutils@sourceware.cygnus.com, jgg@ualberta.ca
> 
>    Date: Wed, 7 Jul 1999 18:23:19 +1000
>    From: Geoff Keating <geoffk@ozemail.com.au>
> 
>    These cases are not fixable under the usual non-pic-executable model, in
>    which all addresses referenced by the executable are fixed at link
>    time.
> 
> No, they are fixable.  We just need to generate the appropriate
> dynamic relocations.  At present we do not do that, but there is
> nothing preventing us from doing it.

To be precise:

These cases, if fixed by outputting all relevant relocations, would
lead to incredibly inefficient program loading because it would be
necessary to have run-time relocs for any weak symbol referenced by the
executable.  It would also cost large amounts of memory because the
text segment of executables would no longer be sharable between
invocations.


For instance, consider the following tiny bit of code, which we assume
goes in an executable:

extern int foo(void);
int main(void) { if (foo) return foo(); else return 42; }


This compiles to an object file with the following relocs: 

RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE 
0000000e R_PPC_ADDR16_HA   foo
00000012 R_PPC_ADDR16_LO   foo
00000024 R_PPC_REL24       foo

The first two are from the 'if (foo)', the third is the call in
'return foo()'.

Suppose we have a DSO like this:

#pragma weak foo
int foo(void) { return 2; }

Now, at present, a PLT entry is generated for foo() in the executable,
and all the relocs in the object file are pointed at it.  The relocs
generated are in the executable are:

DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE 
01840650 R_PPC_JMP_SLOT    __libc_start_main
01840658 R_PPC_JMP_SLOT    foo

I think these are correct, and haven't changed recently.

Now, suppose foo() goes away in a future version of the DSO.  Now we
have a weak symbol which isn't defined anywhere, so it has address 0.

In that case, the test `if (foo)' will still pass, because it was
decided at link time where the ADDR16 relocs were bound (they get
bound to address 01840658, to the PLT entry).  The PLT entry will
branch to location 0, so the program will crash.  The only way to fix
this would be export the ADDR16 (and, to be completely correct, the
REL24) relocs; it would be like a DSO which had been compiled without
-fpic.

This will happen a lot.  For instance, in current glibc 'open()' is
weak.  open() is not likely to go away, but the linker doesn't know
that.


On some old systems, this implies that the .text section in the
executable must be put in a read-write segment, because you can't
change memory permissions on executable segments.

-- 
Geoffrey Keating <geoffk@ozemail.com.au>

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