@@ -119,37 +119,26 @@ extern unsigned __udivmodsi4(unsigned, unsigned) attribute_hidden;
| (((type) == R_ARC_COPY) * ELF_RTYPE_CLASS_COPY))
- * Get the runtime address of GOT
+ * Get build time address of .dynamic as setup in GOT
+ * This is called very early in _dl_start() so it has not been relocated to
+ * runtime value
static __always_inline Elf32_Addr elf_machine_dynamic(void)
- Elf32_Addr dyn;
- __asm__("ld %0,[pcl,_DYNAMIC@gotpc]\n\t" : "=r" (dyn));
- return dyn;
+ /* Declaring this hidden ensures that a PC-relative reference is used. */
+ extern const Elf32_Addr _GLOBAL_OFFSET_TABLE_ attribute_hidden;
+ return _GLOBAL_OFFSET_TABLE_;
/* Return the run-time load address of the shared object. */
static __always_inline Elf32_Addr elf_machine_load_address(void)
- /* To find the loadaddr we subtract the runtime addr of a non-local symbol
- * say _DYNAMIC from it's build-time addr.
- * N.B., gotpc loads get optimized by the linker if it finds the symbol
- * is resolved locally.
- * A more robust - and efficient - solution would be to use a symbol
- * set by the linker. To make it actually save space, we'd have to
- * suppress the unwanted text relocation in the linked dso, though.
- * (I.e. in ldso.so.*, though it's just another dso as far as bfd/ld
- * are concerned.)
- Elf32_Addr addr, tmp;
- __asm__ (
- "ld %1, [pcl, _DYNAMIC@gotpc] ;build addr of _DYNAMIC" "\n"
- "add %0, pcl, _DYNAMIC@pcl ;runtime addr of _DYNAMIC" "\n"
- "sub %0, %0, %1 ;delta" "\n"
- : "=&r" (addr), "=r"(tmp)
- return addr;
+ Elf32_Addr build_addr, run_addr;
+ build_addr = elf_machine_dynamic();
+ __asm__ ("add %0, pcl, _DYNAMIC@pcl \n" : "=r" (run_addr));
+ return run_addr - build_addr;
static __always_inline void