return 0;
}
+/* We have to do this because elf_machine_{dynamic,load_address} can be
+ invoked from functions that have no GOT references, and thus the compiler
+ has no obligation to load the PIC register. */
+#define LOAD_PIC_REG(PIC_REG) \
+do { register Elf32_Addr pc __asm("o7"); \
+ __asm("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \
+ "call 1f\n\t" \
+ "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n" \
+ "1:\tadd %1, %0, %1" \
+ : "=r" (pc), "=r" (PIC_REG)); \
+} while (0)
/* Return the link-time address of _DYNAMIC. Conveniently, this is the
first element of the GOT. This must be inlined in a function which
elf_machine_dynamic (void)
{
register Elf32_Addr *got asm ("%l7");
+
+ LOAD_PIC_REG (got);
+
return *got;
}
{
register Elf32_Addr pc __asm("%o7"), pic __asm("%l7"), got;
+ LOAD_PIC_REG (pic);
+
/* Utilize the fact that a local .got entry will be partially
initialized at startup awaiting its RELATIVE fixup. */
return ehdr->e_machine == EM_SPARCV9;
}
+/* We have to do this because elf_machine_{dynamic,load_address} can be
+ invoked from functions that have no GOT references, and thus the compiler
+ has no obligation to load the PIC register. */
+#define LOAD_PIC_REG(PIC_REG) \
+do { Elf64_Addr tmp; \
+ __asm("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \
+ "rd %%pc, %0\n\t" \
+ "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t" \
+ "add %0, %1, %0" \
+ : "=r" (PIC_REG), "=r" (tmp)); \
+} while (0)
+
/* 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. */
{
register Elf64_Addr *elf_pic_register __asm__("%l7");
+ LOAD_PIC_REG (elf_pic_register);
+
return *elf_pic_register;
}
{
register Elf64_Addr *elf_pic_register __asm__("%l7");
+ LOAD_PIC_REG (elf_pic_register);
+
/* We used to utilize the fact that a local .got entry will
be partially initialized at startup awaiting its RELATIVE
fixup: