diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2017-08-03 09:43:28 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2017-10-14 11:49:36 -0700 |
commit | c3d646723ce1b7d68270ae2b0f8163a9be434576 (patch) | |
tree | 4fcc568f0d2aeb66d5d1d7faf6d09b850694bebf /bfd/elfxx-x86.h | |
parent | 851b6fa13707d187e068c8773f21d376391387a9 (diff) | |
download | binutils-gdb-c3d646723ce1b7d68270ae2b0f8163a9be434576.tar.gz |
x86: Add R_X86_64_GPOFF/R_386_GPOFF relocationusers/hjl/gpoff/master
On x86, a segment register is used as thread pointer to access thread
local storage (TLS) with __thread. TLS is an OS-dependent, user-space
feature.
Here is a proposal to add R_X86_64_GPOFF/R_386_GPOFF relocation to
access symbol with an offset to global pointer, __gp. The assembly
syntax is
1. Load value of foo relative to __gp, pointed by %seg, into %reg:
op %seg:foo@GPOFF, %reg
2. Store value in %reg to foo relative to __gp, pointed by %seg:
op %reg, %seg:foo@GPOFF
3. Compute offset of foo to __gp:
lea foo@GPOFF, %reg
.long foo@GPOFF
Linker sets __gp to the middle of the section which contains definitions
of symbols with GPOFF relocations and the maximum offset is [-2G, 2G).
Run-time must initialize the segment register, %seg, with the address of
global pointer, __gp.
bfd/
* elf32-i386.c (elf_howto_table): Add R_386_GPOFF.
(R_386_ext2): Replace R_386_GOT32X with R_386_GPOFF.
(elf_i386_reloc_type_lookup): Support BFD_RELOC_GPREL32.
(elf_i386_check_relocs): Add a fake local symbol and set
has_gpoff_reloc for GPOFF relocation.
(elf_i386_allocate_local_dynrelocs): Skip local symbol with
GPOFF relocation.
(elf_i386_finish_local_dynamic_symbol): Likewise.
(elf_i386_relocate_section): Process GPOFF relocation.
* elf64-x86-64.c (elf_howto_table): Add R_X86_64_GPOFF.
(R_X86_64_standard): Replace R_X86_64_REX_GOTPCRELX with
R_X86_64_GPOFF.
(x86_64_reloc_map): Add BFD_RELOC_GPREL32.
(elf_x86_64_check_relocs): Add a fake local symbol and set
has_gpoff_reloc for GPOFF relocation.
(elf_x86_64_allocate_local_dynrelocs): Skip local symbol with
GPOFF relocation.
(elf_x86_64_finish_local_dynamic_symbol): Likewise.
(elf_x86_64_relocate_section): Process GPOFF relocation.
* elfxx-x86.c (_bfd_x86_elf_link_check_relocs): Cache and hide
__gp symbol.
(_bfd_x86_elf_copy_indirect_symbol): Also copy has_gpoff_reloc.
(elf_x86_setup_gp): New function.
(elf_x86_setup_gp_from_local_symbol): Likewise.
(_bfd_x86_elf_final_link): Likewise.
* elfxx-x86.h (elf_x86_link_hash_entry): Add has_gpoff_reloc.
(elf_x86_link_hash_table): Add gp.
(_bfd_x86_elf_final_link): New.
(bfd_elf64_bfd_final_link): Likewise.
(bfd_elf32_bfd_final_link): Likewise.
gas/
* config/tc-i386.c (GP_symbol): New.
(gotrel): Add "GPOFF".
(lex_got): Support BFD_RELOC_GPREL32.
(i386_displacement): Disallow BFD_RELOC_GPREL32 relocation
with base or index registers.
(md_undefined_symbol): Create GP_symbol if needed.
(tc_gen_reloc): Handle BFD_RELOC_GPREL32.
* config/tc-i386.h (GLOBAL_POINTER_NAME): New.
* testsuite/gas/i386/gpoff.d: New file.
* testsuite/gas/i386/gpoff.s: Likewise.
* testsuite/gas/i386/inval-gpoff.l: Likewise.
* testsuite/gas/i386/inval-gpoff.s: Likewise.
* testsuite/gas/i386/x86-64-gpoff.d: Likewise.
* testsuite/gas/i386/x86-64-gpoff.s: Likewise.
* testsuite/gas/i386/x86-64-inval-gpoff.l: Likewise.
* testsuite/gas/i386/x86-64-inval-gpoff.s: Likewise.
* testsuite/gas/i386/i386.exp: Run gpoff, inval-gpoff,
x86-64-gpoff and x86-64-inval-gpoff.
include/
* elf/i386.h (R_386_GPOFF): New relocation.
* elf/x86-64.h (R_X86_64_GPOFF): Likewise.
ld/
* testsuite/ld-i386/gpoff-1a.S: New file.
* testsuite/ld-i386/gpoff-1b.c: Likewise.
* testsuite/ld-i386/gpoff-2a.S: Likewise.
* testsuite/ld-i386/gpoff-2b.c: Likewise.
* testsuite/ld-i386/gpoff-3.d: Likewise.
* testsuite/ld-i386/gpoff-3.s: Likewise.
* testsuite/ld-i386/gpoff-4.d: Likewise.
* testsuite/ld-i386/gpoff-4.s: Likewise.
* testsuite/ld-i386/gpoff-5.d: Likewise.
* testsuite/ld-i386/gpoff-5.s: Likewise.
* testsuite/ld-i386/gpoff-6.d: Likewise.
* testsuite/ld-i386/gpoff-6.s: Likewise.
* testsuite/ld-i386/gpoff-7.d: Likewise.
* testsuite/ld-i386/gpoff-7.s: Likewise.
* testsuite/ld-i386/gpoff-8.s: Likewise.
* testsuite/ld-i386/gpoff-8.t: Likewise.
* testsuite/ld-i386/gpoff-8a.d: Likewise.
* testsuite/ld-i386/gpoff-8b.d: Likewise.
* testsuite/ld-i386/gpoff-8c.d: Likewise.
* testsuite/ld-i386/gpoff-8d.d: Likewise.
* testsuite/ld-i386/gpoff-8e.d: Likewise.
* testsuite/ld-i386/gpoff-8f.d: Likewise.
* testsuite/ld-x86-64/gpoff-1a.S: Likewise.
* testsuite/ld-x86-64/gpoff-1b.c: Likewise.
* testsuite/ld-x86-64/gpoff-2a.S: Likewise.
* testsuite/ld-x86-64/gpoff-2b.c: Likewise.
* testsuite/ld-x86-64/gpoff-3.d: Likewise.
* testsuite/ld-x86-64/gpoff-3.s: Likewise.
* testsuite/ld-x86-64/gpoff-4.d: Likewise.
* testsuite/ld-x86-64/gpoff-4.s: Likewise.
* testsuite/ld-x86-64/gpoff-5.d: Likewise.
* testsuite/ld-x86-64/gpoff-5.s: Likewise.
* testsuite/ld-x86-64/gpoff-6.d: Likewise.
* testsuite/ld-x86-64/gpoff-6.s: Likewise.
* testsuite/ld-x86-64/gpoff-7.d: Likewise.
* testsuite/ld-x86-64/gpoff-7.s: Likewise.
* testsuite/ld-x86-64/gpoff-8.s: Likewise.
* testsuite/ld-x86-64/gpoff-8.t: Likewise.
* testsuite/ld-x86-64/gpoff-8a.d: Likewise.
* testsuite/ld-x86-64/gpoff-8b.d: Likewise.
* testsuite/ld-x86-64/gpoff-8c.d: Likewise.
* testsuite/ld-x86-64/gpoff-8d.d: Likewise.
* testsuite/ld-x86-64/gpoff-8e.d: Likewise.
* testsuite/ld-x86-64/gpoff-8f.d: Likewise.
* testsuite/ld-i386/i386.exp: Run R_386_GPOFF tests.
* testsuite/ld-x86-64/x86-64.exp: Run R_X86_64_GPOFF tests.
Diffstat (limited to 'bfd/elfxx-x86.h')
-rw-r--r-- | bfd/elfxx-x86.h | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h index 8d2a7317eb3..a1bc3021b66 100644 --- a/bfd/elfxx-x86.h +++ b/bfd/elfxx-x86.h @@ -238,6 +238,9 @@ struct elf_x86_link_hash_entry should be resolved to 0 if zero_undefweak > 0. */ unsigned int zero_undefweak : 2; + /* TRUE if symbol has GPOFF relocations. */ + unsigned int has_gpoff_reloc : 1; + /* Don't call finish_dynamic_symbol on this symbol. */ unsigned int no_finish_dynamic_symbol : 1; @@ -433,6 +436,9 @@ struct elf_x86_link_hash_table /* Parameters describing non-lazy PLT generation. */ const struct elf_x86_non_lazy_plt_layout *non_lazy_plt; + /* Cache __gp symbol. */ + struct elf_link_hash_entry *gp; + union { bfd_signed_vma refcount; @@ -663,6 +669,9 @@ extern bfd_boolean _bfd_x86_elf_merge_gnu_properties extern bfd * _bfd_x86_elf_link_setup_gnu_properties (struct bfd_link_info *, struct elf_x86_init_table *); +extern bfd_boolean _bfd_x86_elf_final_link + (bfd *, struct bfd_link_info *); + #define bfd_elf64_mkobject \ _bfd_x86_elf_mkobject #define bfd_elf32_mkobject \ @@ -675,6 +684,10 @@ extern bfd * _bfd_x86_elf_link_setup_gnu_properties _bfd_x86_elf_link_check_relocs #define bfd_elf32_bfd_link_check_relocs \ _bfd_x86_elf_link_check_relocs +#define bfd_elf64_bfd_final_link \ + _bfd_x86_elf_final_link +#define bfd_elf32_bfd_final_link \ + _bfd_x86_elf_final_link #define elf_backend_size_dynamic_sections \ _bfd_x86_elf_size_dynamic_sections |