* aarch64 prelink issue
@ 2013-06-24 16:41 Mark Salter
2013-06-24 17:18 ` Richard Henderson
0 siblings, 1 reply; 5+ messages in thread
From: Mark Salter @ 2013-06-24 16:41 UTC (permalink / raw)
To: marcus.shawcroft; +Cc: libc-ports
I'm trying to get prelink working for aarch64 and ran into a problem
in the aarch64 elf_machine_dynamic() function which is simply:
/* Return the link-time address of _DYNAMIC. Conveniently, this is the
first element of the GOT. */
static inline ElfW(Addr) __attribute__ ((unused))
elf_machine_dynamic (void)
{
ElfW(Addr) addr = (ElfW(Addr)) &_DYNAMIC;
return addr;
}
This routine is only used early before rtld has relocated itself and is
expected to return the static link address of the .dynamic section. The
problem is that the above code generates a got entry + reloc for the
reference to &_DYNAMIC. When the rtld is prelinked, the early startup
code in rtld adds the load address to an already relocated value and
then segfaults as soon as it uses the bogus result.
I worked around this with:
diff --git a/ports/sysdeps/aarch64/dl-machine.h b/ports/sysdeps/aarch64/dl-machine.h
index 94f1108..f69c618 100644
--- a/ports/sysdeps/aarch64/dl-machine.h
+++ b/ports/sysdeps/aarch64/dl-machine.h
@@ -36,7 +36,14 @@ elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
static inline ElfW(Addr) __attribute__ ((unused))
elf_machine_dynamic (void)
{
- ElfW(Addr) addr = (ElfW(Addr)) &_DYNAMIC;
+ ElfW(Addr) addr;
+
+ asm (" \n\
+ ldr %w0, 1f \n\
+ b 2f \n\
+1: .word _DYNAMIC \n\
+2: \n\
+ " : "=r" (addr));
return addr;
}
I suppose the prelink tool could work around this itself which would
allow it to work on all versions of glibc. Even in that case, the
above patch still saves an unnecessary got+reloc.
--Mark
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: aarch64 prelink issue
2013-06-24 16:41 aarch64 prelink issue Mark Salter
@ 2013-06-24 17:18 ` Richard Henderson
2013-06-26 12:43 ` Mark Salter
0 siblings, 1 reply; 5+ messages in thread
From: Richard Henderson @ 2013-06-24 17:18 UTC (permalink / raw)
To: Mark Salter; +Cc: marcus.shawcroft, libc-ports
On 06/24/2013 09:41 AM, Mark Salter wrote:
> I worked around this with:
>
> diff --git a/ports/sysdeps/aarch64/dl-machine.h b/ports/sysdeps/aarch64/dl-machine.h
> index 94f1108..f69c618 100644
> --- a/ports/sysdeps/aarch64/dl-machine.h
> +++ b/ports/sysdeps/aarch64/dl-machine.h
> @@ -36,7 +36,14 @@ elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
> static inline ElfW(Addr) __attribute__ ((unused))
> elf_machine_dynamic (void)
> {
> - ElfW(Addr) addr = (ElfW(Addr)) &_DYNAMIC;
> + ElfW(Addr) addr;
> +
> + asm (" \n\
> + ldr %w0, 1f \n\
> + b 2f \n\
> +1: .word _DYNAMIC \n\
> +2: \n\
> + " : "=r" (addr));
> return addr;
> }
>
> I suppose the prelink tool could work around this itself which would
> allow it to work on all versions of glibc. Even in that case, the
> above patch still saves an unnecessary got+reloc.
Try the x86_64 solution:
/* This produces an IP-relative reloc which is resolved at link time. */
extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden;
return _GLOBAL_OFFSET_TABLE_[0];
with the extra hidden attribute, this should result in an ADR(P)
reference to the _G_O_T_.
r~
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: aarch64 prelink issue
2013-06-24 17:18 ` Richard Henderson
@ 2013-06-26 12:43 ` Mark Salter
2013-06-26 15:36 ` Marcus Shawcroft
0 siblings, 1 reply; 5+ messages in thread
From: Mark Salter @ 2013-06-26 12:43 UTC (permalink / raw)
To: Richard Henderson; +Cc: marcus.shawcroft, libc-ports
On Mon, 2013-06-24 at 10:18 -0700, Richard Henderson wrote:
> Try the x86_64 solution:
>
> /* This produces an IP-relative reloc which is resolved at link time. */
> extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden;
> return _GLOBAL_OFFSET_TABLE_[0];
>
> with the extra hidden attribute, this should result in an ADR(P)
> reference to the _G_O_T_.
>
This isn't working for aarch64. It doesn't use a PC-relative reference
and it tries reading from the GOT at the link time absolute address.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: aarch64 prelink issue
2013-06-26 12:43 ` Mark Salter
@ 2013-06-26 15:36 ` Marcus Shawcroft
2013-06-26 16:48 ` Richard Henderson
0 siblings, 1 reply; 5+ messages in thread
From: Marcus Shawcroft @ 2013-06-26 15:36 UTC (permalink / raw)
To: Mark Salter; +Cc: Richard Henderson, libc-ports
On 26 June 2013 13:42, Mark Salter <msalter@redhat.com> wrote:
> On Mon, 2013-06-24 at 10:18 -0700, Richard Henderson wrote:
>> Try the x86_64 solution:
>>
>> /* This produces an IP-relative reloc which is resolved at link time. */
>> extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden;
>> return _GLOBAL_OFFSET_TABLE_[0];
>>
>> with the extra hidden attribute, this should result in an ADR(P)
>> reference to the _G_O_T_.
>>
>
> This isn't working for aarch64. It doesn't use a PC-relative reference
> and it tries reading from the GOT at the link time absolute address.
It looks to me that Richard's proposal gives the correct sequence in
elf_machine_dynamic():
adrp x0, _GLOBAL_OFFSET_TABLE_
ldr x0, [x0,#:lo12:_GLOBAL_OFFSET_TABLE_]
ret
... but, this exposes an issue in the static linker:
Currently the static linker produces:
.got
<-_GLOBAL_OFFSET_TABLE_
...
.gotplt[0] &_DYNAMIC <--DT_PLTGOT
.gotplt[1] reserved for ld.so (&linkmap)
.gotplt[2] reserved fpr ld.so (resolver)
...
This layout is broken wrt the placement of &_DYNAMIC. The correct
layout should be:
.got[0] &_DYNAMIC <-_GLOBAL_OFFSET_TABLE_
...
.gotplt[0] reserved for ld.so (&linkmap) <--DT_PLTGOT
.gotplt[1] reserved fpr ld.so (resolver)
...
Hence when we use Richard's suggestion we end up picking junk out of .got[0]
I'm still looking at this, but at the moment I think we can fix the
static linker to emit:
.got[0] &_DYNAMIC <-_GLOBAL_OFFSET_TABLE_
...
.gotplt[0] reserved for ld.so (&linkmap) <--DT_PLTGOT
.gotplt[1] reserved for ld.so (resolver)
.gotplt[2] reserved
With this change, I believe that we do not introduce an
incompatibility between existing binaries / .so's and the modified
ld.so because the code within elf_machine_dynamic() is only
instantiated within ld.so and is only used to inspect ld.so's own
image.
The .gotplt[2] entry remains reserved in the new layout to ensure that
an unmodified ld.so can load a binary built using a modified static ld
without clobbering the first real PLT entry.
I'd really appreciate some feedback on the sanity of this proposal.
Thanks
/Marcus
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: aarch64 prelink issue
2013-06-26 15:36 ` Marcus Shawcroft
@ 2013-06-26 16:48 ` Richard Henderson
0 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2013-06-26 16:48 UTC (permalink / raw)
To: Marcus Shawcroft; +Cc: Mark Salter, libc-ports
On 06/26/2013 08:36 AM, Marcus Shawcroft wrote:
> I'd really appreciate some feedback on the sanity of this proposal.
Seems sane to me.
r~
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-06-26 16:48 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-24 16:41 aarch64 prelink issue Mark Salter
2013-06-24 17:18 ` Richard Henderson
2013-06-26 12:43 ` Mark Salter
2013-06-26 15:36 ` Marcus Shawcroft
2013-06-26 16:48 ` Richard Henderson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).