* sysdeps/x86-64/dl-machine.h (elf_machine_load_address): Rewrite
to not use 32-bit pc relative relocations. (elf_machine_dynamic): Likewise.
This commit is contained in:
parent
05ae4d6ad9
commit
6c2b2a1987
|
@ -39,9 +39,12 @@ elf_machine_matches_host (const Elf64_Ehdr *ehdr)
|
||||||
static inline Elf64_Addr __attribute__ ((unused))
|
static inline Elf64_Addr __attribute__ ((unused))
|
||||||
elf_machine_dynamic (void)
|
elf_machine_dynamic (void)
|
||||||
{
|
{
|
||||||
register Elf64_Addr addr;
|
Elf64_Addr addr;
|
||||||
|
|
||||||
|
/* This works because we have our GOT address available in the small PIC
|
||||||
|
model. */
|
||||||
|
addr = (Elf64_Addr) &_DYNAMIC;
|
||||||
|
|
||||||
asm ("leaq _DYNAMIC, %0\n" : "=r" (addr));
|
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,10 +55,25 @@ elf_machine_load_address (void)
|
||||||
{
|
{
|
||||||
register Elf64_Addr addr, tmp;
|
register Elf64_Addr addr, tmp;
|
||||||
|
|
||||||
asm ("leaq _dl_start, %0\n"
|
/* The easy way is just the same as on x86:
|
||||||
"leaq _dl_start(%%rip), %1\n"
|
leaq _dl_start, %0
|
||||||
"subq %0, %1\n"
|
leaq _dl_start(%%rip), %1
|
||||||
: "=r" (tmp), "=r" (addr) : : "cc");
|
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 .L1(%%rip), %1\n"
|
||||||
|
"0:\tleaq _dl_start(%%rip), %0\n\t"
|
||||||
|
"subq %1, %0\n\t"
|
||||||
|
".section\t.data\n"
|
||||||
|
".L1:\t.quad _dl_start\n\t"
|
||||||
|
".previous\n\t"
|
||||||
|
: "=r" (addr), "=r" (tmp) : : "cc");
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,10 +385,33 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
|
||||||
break;
|
break;
|
||||||
case R_X86_64_32:
|
case R_X86_64_32:
|
||||||
*(unsigned int *) reloc_addr = value + reloc->r_addend;
|
*(unsigned int *) reloc_addr = value + reloc->r_addend;
|
||||||
|
if (value + reloc->r_addend > UINT_MAX)
|
||||||
|
{
|
||||||
|
const char *strtab;
|
||||||
|
|
||||||
|
strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
|
||||||
|
|
||||||
|
_dl_error_printf ("\
|
||||||
|
%s: Symbol `%s' causes overflow in R_X86_64_32 relocation\n",
|
||||||
|
rtld_progname ?: "<program name unknown>",
|
||||||
|
strtab + refsym->st_name);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case R_X86_64_PC32:
|
case R_X86_64_PC32:
|
||||||
*(unsigned int *) reloc_addr = value + reloc->r_addend
|
*(unsigned int *) reloc_addr = value + reloc->r_addend
|
||||||
- (Elf64_Addr) reloc_addr;
|
- (Elf64_Addr) reloc_addr;
|
||||||
|
if (value + reloc->r_addend - (Elf64_Addr) reloc_addr
|
||||||
|
!= (unsigned int)(value + reloc->r_addend - (Elf64_Addr) reloc_addr))
|
||||||
|
{
|
||||||
|
const char *strtab;
|
||||||
|
|
||||||
|
strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
|
||||||
|
|
||||||
|
_dl_error_printf ("\
|
||||||
|
%s: Symbol `%s' causes overflow in R_X86_64_PC32 relocation\n",
|
||||||
|
rtld_progname ?: "<program name unknown>",
|
||||||
|
strtab + refsym->st_name);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case R_X86_64_COPY:
|
case R_X86_64_COPY:
|
||||||
if (sym == NULL)
|
if (sym == NULL)
|
||||||
|
|
Loading…
Reference in New Issue