| Message ID | 563157f631271f15cefd89297dbe48cd6cd1a0e8.camel@kernkonzept.com |
|---|---|
| State | Accepted |
| Headers | show |
| Series | [uclibc-ng-devel] Re: use __ehdr_start to compute load address | expand |
Hi Marcus, applied and pushed, after intensive testing with Qemu and uClibc-ng-test. thanks Waldemar Marcus Hähnel wrote, > ... and here is the attachment ... > > > > > On Thu, 2025-03-20 at 09:39 +0100, Marcus Hähnel wrote: > > Dear List > > > > So far, uclibc relied on the informal behaviour of GNU ld to put the link address of the _DYNAMIC symbol in the first GOT > > entry. This does not work with LLVM lld which does not follow this convention. Consequently, glibc has abandoned its usage > > in favour of using __ehdr_start as magic symbol to infer the load address [1]. > > > > Note that this implies that the link time address of __ehdr_start is *always* 0! So far, this seems to be the case on all > > platforms. > > > > We implemented this change only for the platforms which we actively support and test at Kernkonzept (arm64, arm, i386, > > x86_64 and and riscv). The riscv64 dl-sysdep.h already used the method we converted the others to. For the other platforms > > we do not have the capacity to port this, but as long as noone wants to build them using lld this should not be an issue. > > > > Please feel free to test this on the relevant platforms before merging, to be sure it works as intended with the upstream > > version of the lib. > > > > Best regards, > > > > - Marcus > > > > > > [1] https://sourceware.org/bugzilla/show_bug.cgi?id=28203 > > > > > > > > > > -- > +++++++++++++++++++ > > > Register now for our workshop "Get to know L4Re in 3 days" on April 8-10. Learn to design and deploy secure system > architectures for your product with L4Re: https://www.kernkonzept.com/workshop-getting-started-with-l4re/ > > +++++++++++++++++++ > > Kernkonzept GmbH > Sitz: Dresden > HRB 31129 > Geschäftsführer: Dr.-Ing. Michael Hohmuth > > > From 9a4929ce522d34bed13c24e88c58ae48f1c538c5 Mon Sep 17 00:00:00 2001 > From: =?UTF-8?q?Jan=20Kl=C3=B6tzke?= <jan.kloetzke@kernkonzept.com> > Date: Tue, 18 Mar 2025 07:41:47 +0100 > Subject: [PATCH] Use __ehdr_start to compute load address > > So far, uclibc relied on the informal behaviour of GNU ld to put the > link address of the _DYNAMIC symbol in the first GOT entry. This does > not work with LLVM lld which does not follow this convention. > Consequently, glibc has abandoned its usage in favour of using > __ehdr_start as magic symbol to infer the load address [1]. > > Note that this implies that the link time address of __ehdr_start is > *always* 0! So far, this seems to be the case on all platforms. > > [1] https://sourceware.org/bugzilla/show_bug.cgi?id=28203 > > Signed-off-by: Marcus Haehnel <marcus.haehnel@kernkonzept.com> > --- > ldso/ldso/aarch64/dl-sysdep.h | 25 +++++-------- > ldso/ldso/arm/dl-sysdep.h | 69 +++++------------------------------ > ldso/ldso/i386/dl-sysdep.h | 27 +++++--------- > ldso/ldso/riscv32/dl-sysdep.h | 22 +++++------ > ldso/ldso/x86_64/dl-sysdep.h | 45 +++++------------------ > 5 files changed, 48 insertions(+), 140 deletions(-) > > diff --git a/ldso/ldso/aarch64/dl-sysdep.h b/ldso/ldso/aarch64/dl-sysdep.h > index 6d9d2c1fb..3466920d9 100644 > --- a/ldso/ldso/aarch64/dl-sysdep.h > +++ b/ldso/ldso/aarch64/dl-sysdep.h > @@ -54,28 +54,21 @@ unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); > || (type) == R_AARCH64_TLSDESC) * ELF_RTYPE_CLASS_PLT) \ > | (((type) == R_AARCH64_COPY) * ELF_RTYPE_CLASS_COPY)) > > -/* Return the link-time address of _DYNAMIC. Conveniently, this is the > - first element of the GOT. */ > -extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden; > -static __always_inline ElfW(Addr) __attribute__ ((unused)) > -elf_machine_dynamic (void) > -{ > - return _GLOBAL_OFFSET_TABLE_[0]; > -} > - > /* Return the run-time load address of the shared object. */ > > static __always_inline ElfW(Addr) __attribute__ ((unused)) > elf_machine_load_address (void) > { > - /* To figure out the load address we use the definition that for any symbol: > - dynamic_addr(symbol) = static_addr(symbol) + load_addr > - > - _DYNAMIC sysmbol is used here as its link-time address stored in > - the special unrelocated first GOT entry. */ > + extern const ElfW(Ehdr) __ehdr_start attribute_hidden; > + return (ElfW(Addr)) &__ehdr_start; > +} > > - extern ElfW(Dyn) _DYNAMIC[] attribute_hidden; > - return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic (); > +/* Return the link-time address of _DYNAMIC. */ > +static __always_inline ElfW(Addr) __attribute__ ((unused)) > +elf_machine_dynamic (void) > +{ > + extern ElfW(Dyn) _DYNAMIC[] attribute_hidden; > + return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address (); > } > > static __always_inline void > diff --git a/ldso/ldso/arm/dl-sysdep.h b/ldso/ldso/arm/dl-sysdep.h > index 0f783e1c4..93e36b694 100644 > --- a/ldso/ldso/arm/dl-sysdep.h > +++ b/ldso/ldso/arm/dl-sysdep.h > @@ -96,43 +96,6 @@ unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); > | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY)) > #endif /* __FDPIC__ */ > > -/* Return the link-time address of _DYNAMIC. Conveniently, this is the > - first element of the GOT. We used to use the PIC register to do this > - without a constant pool reference, but GCC 4.2 will use a pseudo-register > - for the PIC base, so it may not be in r10. */ > -static __always_inline Elf32_Addr __attribute__ ((unused)) > -elf_machine_dynamic (void) > -{ > - Elf32_Addr dynamic; > -#if !defined __thumb__ > - __asm__ ("ldr %0, 2f\n" > - "1: ldr %0, [pc, %0]\n" > - "b 3f\n" > - "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n" > - "3:" : "=r" (dynamic)); > -#else > - int tmp; > - __asm__ (".align 2\n" > - "bx pc\n" > - "nop\n" > - ".arm\n" > - "ldr %0, 2f\n" > - "1: ldr %0, [pc, %0]\n" > - "b 3f\n" > - "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n" > - "3:" > - ".align 2\n" > - "orr %1, pc, #1\n" > - "bx %1\n" > - ".force_thumb\n" > - : "=r" (dynamic), "=&r" (tmp)); > -#endif > - > - return dynamic; > -} > - > -extern char __dl_start[] __asm__("_dl_start"); > - > #ifdef __FDPIC__ > /* We must force strings used early in the bootstrap into the data > segment. */ > @@ -148,28 +111,16 @@ extern char __dl_start[] __asm__("_dl_start"); > static __always_inline Elf32_Addr __attribute__ ((unused)) > elf_machine_load_address (void) > { > -#if defined(__FDPIC__) > - return 0; > -#else > - Elf32_Addr got_addr = (Elf32_Addr) &__dl_start; > - Elf32_Addr pcrel_addr; > -#if defined __OPTIMIZE__ && !defined __thumb__ > - __asm__ ("adr %0, _dl_start" : "=r" (pcrel_addr)); > -#else > - /* A simple adr does not work in Thumb mode because the offset is > - negative, and for debug builds may be too large. */ > - int tmp; > - __asm__ ("adr %1, 1f\n\t" > - "ldr %0, [%1]\n\t" > - "add %0, %0, %1\n\t" > - "b 2f\n\t" > - ".align 2\n\t" > - "1: .word _dl_start - 1b\n\t" > - "2:" > - : "=r" (pcrel_addr), "=r" (tmp)); > -#endif > - return pcrel_addr - got_addr; > -#endif > + extern const Elf32_Ehdr __ehdr_start attribute_hidden; > + return (Elf32_Addr) &__ehdr_start; > +} > + > +/* Return the link-time address of _DYNAMIC. */ > +static __always_inline Elf32_Addr __attribute__ ((unused)) > +elf_machine_dynamic (void) > +{ > + extern Elf32_Dyn _DYNAMIC[] attribute_hidden; > + return (Elf32_Addr) _DYNAMIC - elf_machine_load_address (); > } > > static __always_inline void > diff --git a/ldso/ldso/i386/dl-sysdep.h b/ldso/ldso/i386/dl-sysdep.h > index b95328df4..8fc80a145 100644 > --- a/ldso/ldso/i386/dl-sysdep.h > +++ b/ldso/ldso/i386/dl-sysdep.h > @@ -35,28 +35,21 @@ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_ent > || (type) == R_386_TLS_TPOFF) * ELF_RTYPE_CLASS_PLT) \ > | (((type) == R_386_COPY) * ELF_RTYPE_CLASS_COPY)) > > -/* Return the link-time address of _DYNAMIC. Conveniently, this is the > - first element of the GOT, a special entry that is never relocated. */ > -extern const Elf32_Addr _GLOBAL_OFFSET_TABLE_[] attribute_hidden; > -static __always_inline Elf32_Addr __attribute__ ((unused, const)) > -elf_machine_dynamic (void) > -{ > - /* This produces a GOTOFF reloc that resolves to zero at link time, so in > - fact just loads from the GOT register directly. By doing it without > - an asm we can let the compiler choose any register. */ > - return _GLOBAL_OFFSET_TABLE_[0]; > -} > - > > -extern Elf32_Dyn bygotoff[] __asm__ ("_DYNAMIC") attribute_hidden; > /* Return the run-time load address of the shared object. */ > static __always_inline Elf32_Addr attribute_unused > elf_machine_load_address (void) > { > - /* Compute the difference between the runtime address of _DYNAMIC as seen > - by a GOTOFF reference, and the link-time address found in the special > - unrelocated first GOT entry. */ > - return (Elf32_Addr) &bygotoff - elf_machine_dynamic (); > + extern const Elf32_Ehdr __ehdr_start attribute_hidden; > + return (Elf32_Addr) &__ehdr_start; > +} > + > +/* Return the link-time address of _DYNAMIC. */ > +static __always_inline Elf32_Addr __attribute__ ((unused, const)) > +elf_machine_dynamic (void) > +{ > + extern Elf32_Dyn _DYNAMIC[] attribute_hidden; > + return (Elf32_Addr) _DYNAMIC - elf_machine_load_address (); > } > > static __always_inline void > diff --git a/ldso/ldso/riscv32/dl-sysdep.h b/ldso/ldso/riscv32/dl-sysdep.h > index e0a59fddd..02296b148 100644 > --- a/ldso/ldso/riscv32/dl-sysdep.h > +++ b/ldso/ldso/riscv32/dl-sysdep.h > @@ -59,22 +59,20 @@ unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); > | (ELF_RTYPE_CLASS_COPY * ((type) == R_RISCV_COPY))) > > > -/* Return the link-time address of _DYNAMIC. */ > -static inline ElfW(Addr) > -elf_machine_dynamic (void) > -{ > - extern ElfW(Addr) _GLOBAL_OFFSET_TABLE_ __attribute__ ((visibility ("hidden"))); > - return _GLOBAL_OFFSET_TABLE_; > -} > - > - > /* Return the run-time load address of the shared object. */ > static __always_inline ElfW(Addr) __attribute__ ((unused)) > elf_machine_load_address (void) > { > - ElfW(Addr) load_addr; > - __asm__ ("lla %0, _DYNAMIC" : "=r" (load_addr)); > - return load_addr - elf_machine_dynamic (); > + extern const ElfW(Ehdr) __ehdr_start attribute_hidden; > + return (ElfW(Addr)) &__ehdr_start; > +} > + > +/* Return the link-time address of _DYNAMIC. */ > +static inline ElfW(Addr) > +elf_machine_dynamic (void) > +{ > + extern ElfW(Dyn) _DYNAMIC[] attribute_hidden; > + return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address (); > } > > static __always_inline void > diff --git a/ldso/ldso/x86_64/dl-sysdep.h b/ldso/ldso/x86_64/dl-sysdep.h > index ccf9a8851..58447a951 100644 > --- a/ldso/ldso/x86_64/dl-sysdep.h > +++ b/ldso/ldso/x86_64/dl-sysdep.h > @@ -52,48 +52,21 @@ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_ent > * ELF_RTYPE_CLASS_PLT) \ > | (((type) == R_X86_64_COPY) * ELF_RTYPE_CLASS_COPY)) > > -/* Return the link-time address of _DYNAMIC. Conveniently, this is the > - first element of the GOT. This must be inlined in a function which > - uses global data. */ > -static __always_inline Elf64_Addr __attribute__ ((unused)) > -elf_machine_dynamic (void) > -{ > - Elf64_Addr addr; > - > - /* This works because we have our GOT address available in the small PIC > - model. */ > - addr = (Elf64_Addr) &_DYNAMIC; > - > - return addr; > -} > - > > /* Return the run-time load address of the shared object. */ > static __always_inline Elf64_Addr __attribute__ ((unused)) > elf_machine_load_address (void) > { > - register Elf64_Addr addr, tmp; > - > - /* The easy way is just the same as on x86: > - leaq _dl_start, %0 > - leaq _dl_start(%%rip), %1 > - subq %0, %1 > - but this does not work with binutils since we then have > - a R_X86_64_32S relocation in a shared lib. > - > - Instead we store the address of _dl_start in the data section > - and compare it with the current value that we can get via > - an RIP relative addressing mode. */ > - > - __asm__ ("movq 1f(%%rip), %1\n" > - "0:\tleaq _dl_start(%%rip), %0\n\t" > - "subq %1, %0\n\t" > - ".section\t.data\n" > - "1:\t.quad _dl_start\n\t" > - ".previous\n\t" > - : "=r" (addr), "=r" (tmp) : : "cc"); > + extern const Elf64_Ehdr __ehdr_start attribute_hidden; > + return (Elf64_Addr) &__ehdr_start; > +} > > - return addr; > +/* Return the link-time address of _DYNAMIC. */ > +static __always_inline Elf64_Addr __attribute__ ((unused)) > +elf_machine_dynamic (void) > +{ > + extern Elf64_Dyn _DYNAMIC[] attribute_hidden; > + return (Elf64_Addr) _DYNAMIC - elf_machine_load_address (); > } > > static __always_inline void > -- > 2.47.1 > > _______________________________________________ > devel mailing list -- devel@uclibc-ng.org > To unsubscribe send an email to devel-leave@uclibc-ng.org
From 9a4929ce522d34bed13c24e88c58ae48f1c538c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kl=C3=B6tzke?= <jan.kloetzke@kernkonzept.com> Date: Tue, 18 Mar 2025 07:41:47 +0100 Subject: [PATCH] Use __ehdr_start to compute load address So far, uclibc relied on the informal behaviour of GNU ld to put the link address of the _DYNAMIC symbol in the first GOT entry. This does not work with LLVM lld which does not follow this convention. Consequently, glibc has abandoned its usage in favour of using __ehdr_start as magic symbol to infer the load address [1]. Note that this implies that the link time address of __ehdr_start is *always* 0! So far, this seems to be the case on all platforms. [1] https://sourceware.org/bugzilla/show_bug.cgi?id=28203 Signed-off-by: Marcus Haehnel <marcus.haehnel@kernkonzept.com> --- ldso/ldso/aarch64/dl-sysdep.h | 25 +++++-------- ldso/ldso/arm/dl-sysdep.h | 69 +++++------------------------------ ldso/ldso/i386/dl-sysdep.h | 27 +++++--------- ldso/ldso/riscv32/dl-sysdep.h | 22 +++++------ ldso/ldso/x86_64/dl-sysdep.h | 45 +++++------------------ 5 files changed, 48 insertions(+), 140 deletions(-) diff --git a/ldso/ldso/aarch64/dl-sysdep.h b/ldso/ldso/aarch64/dl-sysdep.h index 6d9d2c1fb..3466920d9 100644 --- a/ldso/ldso/aarch64/dl-sysdep.h +++ b/ldso/ldso/aarch64/dl-sysdep.h @@ -54,28 +54,21 @@ unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); || (type) == R_AARCH64_TLSDESC) * ELF_RTYPE_CLASS_PLT) \ | (((type) == R_AARCH64_COPY) * ELF_RTYPE_CLASS_COPY)) -/* Return the link-time address of _DYNAMIC. Conveniently, this is the - first element of the GOT. */ -extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden; -static __always_inline ElfW(Addr) __attribute__ ((unused)) -elf_machine_dynamic (void) -{ - return _GLOBAL_OFFSET_TABLE_[0]; -} - /* Return the run-time load address of the shared object. */ static __always_inline ElfW(Addr) __attribute__ ((unused)) elf_machine_load_address (void) { - /* To figure out the load address we use the definition that for any symbol: - dynamic_addr(symbol) = static_addr(symbol) + load_addr - - _DYNAMIC sysmbol is used here as its link-time address stored in - the special unrelocated first GOT entry. */ + extern const ElfW(Ehdr) __ehdr_start attribute_hidden; + return (ElfW(Addr)) &__ehdr_start; +} - extern ElfW(Dyn) _DYNAMIC[] attribute_hidden; - return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic (); +/* Return the link-time address of _DYNAMIC. */ +static __always_inline ElfW(Addr) __attribute__ ((unused)) +elf_machine_dynamic (void) +{ + extern ElfW(Dyn) _DYNAMIC[] attribute_hidden; + return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address (); } static __always_inline void diff --git a/ldso/ldso/arm/dl-sysdep.h b/ldso/ldso/arm/dl-sysdep.h index 0f783e1c4..93e36b694 100644 --- a/ldso/ldso/arm/dl-sysdep.h +++ b/ldso/ldso/arm/dl-sysdep.h @@ -96,43 +96,6 @@ unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY)) #endif /* __FDPIC__ */ -/* Return the link-time address of _DYNAMIC. Conveniently, this is the - first element of the GOT. We used to use the PIC register to do this - without a constant pool reference, but GCC 4.2 will use a pseudo-register - for the PIC base, so it may not be in r10. */ -static __always_inline Elf32_Addr __attribute__ ((unused)) -elf_machine_dynamic (void) -{ - Elf32_Addr dynamic; -#if !defined __thumb__ - __asm__ ("ldr %0, 2f\n" - "1: ldr %0, [pc, %0]\n" - "b 3f\n" - "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n" - "3:" : "=r" (dynamic)); -#else - int tmp; - __asm__ (".align 2\n" - "bx pc\n" - "nop\n" - ".arm\n" - "ldr %0, 2f\n" - "1: ldr %0, [pc, %0]\n" - "b 3f\n" - "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n" - "3:" - ".align 2\n" - "orr %1, pc, #1\n" - "bx %1\n" - ".force_thumb\n" - : "=r" (dynamic), "=&r" (tmp)); -#endif - - return dynamic; -} - -extern char __dl_start[] __asm__("_dl_start"); - #ifdef __FDPIC__ /* We must force strings used early in the bootstrap into the data segment. */ @@ -148,28 +111,16 @@ extern char __dl_start[] __asm__("_dl_start"); static __always_inline Elf32_Addr __attribute__ ((unused)) elf_machine_load_address (void) { -#if defined(__FDPIC__) - return 0; -#else - Elf32_Addr got_addr = (Elf32_Addr) &__dl_start; - Elf32_Addr pcrel_addr; -#if defined __OPTIMIZE__ && !defined __thumb__ - __asm__ ("adr %0, _dl_start" : "=r" (pcrel_addr)); -#else - /* A simple adr does not work in Thumb mode because the offset is - negative, and for debug builds may be too large. */ - int tmp; - __asm__ ("adr %1, 1f\n\t" - "ldr %0, [%1]\n\t" - "add %0, %0, %1\n\t" - "b 2f\n\t" - ".align 2\n\t" - "1: .word _dl_start - 1b\n\t" - "2:" - : "=r" (pcrel_addr), "=r" (tmp)); -#endif - return pcrel_addr - got_addr; -#endif + extern const Elf32_Ehdr __ehdr_start attribute_hidden; + return (Elf32_Addr) &__ehdr_start; +} + +/* Return the link-time address of _DYNAMIC. */ +static __always_inline Elf32_Addr __attribute__ ((unused)) +elf_machine_dynamic (void) +{ + extern Elf32_Dyn _DYNAMIC[] attribute_hidden; + return (Elf32_Addr) _DYNAMIC - elf_machine_load_address (); } static __always_inline void diff --git a/ldso/ldso/i386/dl-sysdep.h b/ldso/ldso/i386/dl-sysdep.h index b95328df4..8fc80a145 100644 --- a/ldso/ldso/i386/dl-sysdep.h +++ b/ldso/ldso/i386/dl-sysdep.h @@ -35,28 +35,21 @@ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_ent || (type) == R_386_TLS_TPOFF) * ELF_RTYPE_CLASS_PLT) \ | (((type) == R_386_COPY) * ELF_RTYPE_CLASS_COPY)) -/* Return the link-time address of _DYNAMIC. Conveniently, this is the - first element of the GOT, a special entry that is never relocated. */ -extern const Elf32_Addr _GLOBAL_OFFSET_TABLE_[] attribute_hidden; -static __always_inline Elf32_Addr __attribute__ ((unused, const)) -elf_machine_dynamic (void) -{ - /* This produces a GOTOFF reloc that resolves to zero at link time, so in - fact just loads from the GOT register directly. By doing it without - an asm we can let the compiler choose any register. */ - return _GLOBAL_OFFSET_TABLE_[0]; -} - -extern Elf32_Dyn bygotoff[] __asm__ ("_DYNAMIC") attribute_hidden; /* Return the run-time load address of the shared object. */ static __always_inline Elf32_Addr attribute_unused elf_machine_load_address (void) { - /* Compute the difference between the runtime address of _DYNAMIC as seen - by a GOTOFF reference, and the link-time address found in the special - unrelocated first GOT entry. */ - return (Elf32_Addr) &bygotoff - elf_machine_dynamic (); + extern const Elf32_Ehdr __ehdr_start attribute_hidden; + return (Elf32_Addr) &__ehdr_start; +} + +/* Return the link-time address of _DYNAMIC. */ +static __always_inline Elf32_Addr __attribute__ ((unused, const)) +elf_machine_dynamic (void) +{ + extern Elf32_Dyn _DYNAMIC[] attribute_hidden; + return (Elf32_Addr) _DYNAMIC - elf_machine_load_address (); } static __always_inline void diff --git a/ldso/ldso/riscv32/dl-sysdep.h b/ldso/ldso/riscv32/dl-sysdep.h index e0a59fddd..02296b148 100644 --- a/ldso/ldso/riscv32/dl-sysdep.h +++ b/ldso/ldso/riscv32/dl-sysdep.h @@ -59,22 +59,20 @@ unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); | (ELF_RTYPE_CLASS_COPY * ((type) == R_RISCV_COPY))) -/* Return the link-time address of _DYNAMIC. */ -static inline ElfW(Addr) -elf_machine_dynamic (void) -{ - extern ElfW(Addr) _GLOBAL_OFFSET_TABLE_ __attribute__ ((visibility ("hidden"))); - return _GLOBAL_OFFSET_TABLE_; -} - - /* Return the run-time load address of the shared object. */ static __always_inline ElfW(Addr) __attribute__ ((unused)) elf_machine_load_address (void) { - ElfW(Addr) load_addr; - __asm__ ("lla %0, _DYNAMIC" : "=r" (load_addr)); - return load_addr - elf_machine_dynamic (); + extern const ElfW(Ehdr) __ehdr_start attribute_hidden; + return (ElfW(Addr)) &__ehdr_start; +} + +/* Return the link-time address of _DYNAMIC. */ +static inline ElfW(Addr) +elf_machine_dynamic (void) +{ + extern ElfW(Dyn) _DYNAMIC[] attribute_hidden; + return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address (); } static __always_inline void diff --git a/ldso/ldso/x86_64/dl-sysdep.h b/ldso/ldso/x86_64/dl-sysdep.h index ccf9a8851..58447a951 100644 --- a/ldso/ldso/x86_64/dl-sysdep.h +++ b/ldso/ldso/x86_64/dl-sysdep.h @@ -52,48 +52,21 @@ extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_ent * ELF_RTYPE_CLASS_PLT) \ | (((type) == R_X86_64_COPY) * ELF_RTYPE_CLASS_COPY)) -/* Return the link-time address of _DYNAMIC. Conveniently, this is the - first element of the GOT. This must be inlined in a function which - uses global data. */ -static __always_inline Elf64_Addr __attribute__ ((unused)) -elf_machine_dynamic (void) -{ - Elf64_Addr addr; - - /* This works because we have our GOT address available in the small PIC - model. */ - addr = (Elf64_Addr) &_DYNAMIC; - - return addr; -} - /* Return the run-time load address of the shared object. */ static __always_inline Elf64_Addr __attribute__ ((unused)) elf_machine_load_address (void) { - register Elf64_Addr addr, tmp; - - /* The easy way is just the same as on x86: - leaq _dl_start, %0 - leaq _dl_start(%%rip), %1 - subq %0, %1 - but this does not work with binutils since we then have - a R_X86_64_32S relocation in a shared lib. - - Instead we store the address of _dl_start in the data section - and compare it with the current value that we can get via - an RIP relative addressing mode. */ - - __asm__ ("movq 1f(%%rip), %1\n" - "0:\tleaq _dl_start(%%rip), %0\n\t" - "subq %1, %0\n\t" - ".section\t.data\n" - "1:\t.quad _dl_start\n\t" - ".previous\n\t" - : "=r" (addr), "=r" (tmp) : : "cc"); + extern const Elf64_Ehdr __ehdr_start attribute_hidden; + return (Elf64_Addr) &__ehdr_start; +} - return addr; +/* Return the link-time address of _DYNAMIC. */ +static __always_inline Elf64_Addr __attribute__ ((unused)) +elf_machine_dynamic (void) +{ + extern Elf64_Dyn _DYNAMIC[] attribute_hidden; + return (Elf64_Addr) _DYNAMIC - elf_machine_load_address (); } static __always_inline void -- 2.47.1