Skip to content
  • H.J. Lu's avatar
    x86: Add R_X86_64_GPOFF/R_386_GPOFF relocation · 8a034336
    H.J. Lu authored
    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_link_hash_entry): Add has_gpoff_reloc.
    	(elf_i386_link_hash_table): Add gp.
    	(elf_i386_link_hash_newfunc): Initialize has_gpoff_reloc to 0.
    	(elf_i386_copy_indirect_symbol): Also copy has_gpoff_reloc.
    	(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.
    	(elf_i386_link_check_relocs): Cache and hide __gp symbol.
    	(elf_i386_setup_gp): New function.
    	(elf_i386_setup_gp_from_local_symbol): Likewise.
    	(elf_i386_final_link): Likewise.
    	(bfd_elf32_bfd_final_link): New.
    	* 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_link_hash_entry): Add has_gpoff_reloc.
    	(elf_x86_64_link_hash_table): Add gp.
    	(elf_x86_64_link_hash_newfunc): Initialize has_gpoff_reloc to 0.
    	(elf_x86_64_copy_indirect_symbol): Also copy has_gpoff_reloc.
    	(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.
    	(elf_x86_64_link_check_relocs): Cache and hide __gp symbol.
    	(elf_x86_64_setup_gp): New function.
    	(elf_x86_64_setup_gp_from_local_symbol): Likewise.
    	(elf_x86_64_final_link): Likewise.
    	(bfd_elf64_bfd_final_link): New.
    	(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.
    8a034336