x86: Add R_X86_64_GPOFF/R_386_GPOFF relocation

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.
61 files changed