summaryrefslogtreecommitdiff
path: root/bfd/elfxx-x86.h
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2017-08-03 09:43:28 -0700
committerH.J. Lu <hjl.tools@gmail.com>2017-10-14 11:49:36 -0700
commitc3d646723ce1b7d68270ae2b0f8163a9be434576 (patch)
tree4fcc568f0d2aeb66d5d1d7faf6d09b850694bebf /bfd/elfxx-x86.h
parent851b6fa13707d187e068c8773f21d376391387a9 (diff)
downloadbinutils-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.h13
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