diff options
Diffstat (limited to 'sysdeps/x86_64/dl-machine.h')
-rw-r--r-- | sysdeps/x86_64/dl-machine.h | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h index 934e0b0d6f..e3bab5f22d 100644 --- a/sysdeps/x86_64/dl-machine.h +++ b/sysdeps/x86_64/dl-machine.h @@ -283,6 +283,13 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, } else # endif +# if !defined RTLD_BOOTSTRAP + /* l_addr + r_addend may be > 0xffffffff and R_X86_64_RELATIVE64 + relocation updates the whole 64-bit entry. */ + if (__builtin_expect (r_type == R_X86_64_RELATIVE64, 0)) + *(Elf64_Addr *) reloc_addr = (Elf64_Addr) map->l_addr + reloc->r_addend; + else +# endif if (__builtin_expect (r_type == R_X86_64_NONE, 0)) return; else @@ -407,7 +414,9 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, # ifndef RTLD_BOOTSTRAP case R_X86_64_64: - *reloc_addr = value + reloc->r_addend; + /* value + r_addend may be > 0xffffffff and R_X86_64_64 + relocation updates the whole 64-bit entry. */ + *(Elf64_Addr *) reloc_addr = (Elf64_Addr) value + reloc->r_addend; break; case R_X86_64_32: value += reloc->r_addend; @@ -478,8 +487,15 @@ elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc, void *const reloc_addr_arg) { ElfW(Addr) *const reloc_addr = reloc_addr_arg; - assert (ELFW(R_TYPE) (reloc->r_info) == R_X86_64_RELATIVE); - *reloc_addr = l_addr + reloc->r_addend; + /* l_addr + r_addend may be > 0xffffffff and R_X86_64_RELATIVE64 + relocation updates the whole 64-bit entry. */ + if (__builtin_expect (ELFW(R_TYPE) (reloc->r_info) == R_X86_64_RELATIVE64, 0)) + *(Elf64_Addr *) reloc_addr = (Elf64_Addr) l_addr + reloc->r_addend; + else + { + assert (ELFW(R_TYPE) (reloc->r_info) == R_X86_64_RELATIVE); + *reloc_addr = l_addr + reloc->r_addend; + } } auto inline void |