diff options
Diffstat (limited to 'sysdeps/x86_64')
-rw-r--r-- | sysdeps/x86_64/dl-irel.h | 44 | ||||
-rw-r--r-- | sysdeps/x86_64/dl-machine.h | 12 |
2 files changed, 56 insertions, 0 deletions
diff --git a/sysdeps/x86_64/dl-irel.h b/sysdeps/x86_64/dl-irel.h new file mode 100644 index 0000000000..442ab71d26 --- /dev/null +++ b/sysdeps/x86_64/dl-irel.h @@ -0,0 +1,44 @@ +/* Machine-dependent ELF indirect relocation inline functions. + x86-64 version. + Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DL_IREL_H +#define _DL_IREL_H + +#include <unistd.h> + +#define ELF_MACHINE_IRELA 1 + +static inline void +__attribute ((always_inline)) +elf_irela (const Elf64_Rela *reloc) +{ + Elf64_Addr *const reloc_addr = (void *) reloc->r_offset; + const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info); + + if (__builtin_expect (r_type == R_X86_64_IRELATIVE, 1)) + { + Elf64_Addr value = ((Elf64_Addr (*) (void)) reloc->r_addend) (); + *reloc_addr = value; + } + else + _exit (-1); +} + +#endif /* dl-irel.h */ diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h index 4444ae0a71..1b5ce8e981 100644 --- a/sysdeps/x86_64/dl-machine.h +++ b/sysdeps/x86_64/dl-machine.h @@ -297,6 +297,7 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, : (Elf64_Addr) sym_map->l_addr + sym->st_value); if (sym != NULL + && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1) && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)) value = ((Elf64_Addr (*) (void)) value) (); @@ -442,6 +443,11 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, } break; # endif + case R_X86_64_IRELATIVE: + value = map->l_addr + reloc->r_addend; + value = ((Elf64_Addr (*) (void)) value) (); + *reloc_addr = value; + break; default: _dl_reloc_bad_type (map, r_type, 0); break; @@ -488,6 +494,12 @@ elf_machine_lazy_rel (struct link_map *map, td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)]) + map->l_addr); } + else if (__builtin_expect (r_type == R_X86_64_IRELATIVE, 0)) + { + Elf64_Addr value = map->l_addr + reloc->r_addend; + value = ((Elf64_Addr (*) (void)) value) (); + *reloc_addr = value; + } else _dl_reloc_bad_type (map, r_type, 1); } |