This is the mail archive of the
libc-alpha@sourceware.cygnus.com
mailing list for the glibc project.
Re: Problem in rtld.c with gcc-2.95pre
- To: Geoff Keating <geoffk@ozemail.com.au>
- Subject: Re: Problem in rtld.c with gcc-2.95pre
- From: Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
- Date: Sat, 12 Jun 1999 11:23:10 +0200
- Cc: libc-alpha@sourceware.cygnus.com
- References: <199906110731.RAA08204@geoffk.wattle.id.au>
Am Fri, 11 Jun 1999 schrieb Geoff Keating:
>> Mailing-List: contact libc-alpha-help@sourceware.cygnus.com; run by ezmlm
>> From: Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
>> Date: Thu, 10 Jun 1999 22:07:28 +0200
>>
>> Hi,
>>
>> in rtld.c is the following code:
>>
>> /* Relocate ourselves so we can do normal function calls and
>> data access using the global offset table. */
>>
>> ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0);
>>
>> /* Please note that we don't allow profiling of this object and
>> therefore need not test whether we have to allocate the array
>> for the relocation results (as done in dl-reloc.c). */
>>
>> /* Now life is sane; we can call functions and access global data.
>> Set up to use the operating system facilities, and find out from
>> the operating system's program loader where to find the program
>> header table in core. */
>>
>> if (HP_TIMING_AVAIL)
>> {
>> /* If it hasn't happen yet record the startup time. */
>> if (! HP_TIMING_INLINE)
>> HP_TIMING_NOW (start_time);
>>
>> /* Initialize the timing functions. */
>> HP_TIMING_DIFF_INIT ();
>> }
>>
>> /* Transfer data about ourselves to the permanent link_map structure. */
>> _dl_rtld_map.l_addr = bootstrap_map.l_addr;
>>
>>
>> With gcc-2.95pre the loading of the address of _dl_rtld_map into a register is
>> moved _before_ the call to ELF_DYNAMIC_RELOCATE()! This lets ld.so crash
>> immediately when it tries to access _dl_rtld_map.l_addr, because it still uses
>> the address loaded out of GOT before the relocation.
>> I tried to surround ELF_DYNAMIC_RELOCATE() with
>>
>> asm volatile ("" : : : "memory");
>>
>> but this had no effect, maybe because gcc doesn't consider the GOT as normal
>> memory?
>>
>> My platform is as usual powerpc-linux-gnu with glibc-2.1.1.
>
>Aha! I've been waiting for that to cause trouble for years now.
>
>Indeed, gcc doesn't consider a reference through the GOT as a memory
>reference.
>
>I think the change that is needed is something like switching, in
>rs6000.md, from:
>
>(define_expand "movsi_got"
> [(set (match_operand:SI 0 "register_operand" "")
> (unspec [(match_operand:SI 1 "got_operand" "")
> (match_dup 2)] 8))]
>
>(or whatever it now is in gcc)
>
>to:
>
>(define_expand "movsi_got"
> [(set (match_operand:SI 0 "register_operand" "")
> (mem (plus (unspec [(match_operand:SI 1 "got_operand" "")] 8)
> (match_dup 2))))]
>
>in all the places where an 'unspec 8' appears. This will inform gcc
>of what is going on, in particular that this is a memory reference,
>and then the `asm volatile' will work. At least, I hope so. Tell me
>how it goes.
Hmm, so is this a bug in gcc or in glibc? Or in both? Wouldn't it be better to
just split out the end of _dl_start into a separate function/file? This should
be a portable solution for all platforms.
FYI, both splitting out the end of _dl_start and using asm volatile("" : : :
"r30") solves the problem and the resulting gcc-2.95pre built library passes
all tests.
Franz.