diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2024-02-03 14:32:17 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2024-02-10 08:23:26 -0800 |
commit | 3c1f1c35784f4062455690329a0e7eaa61dd7c79 (patch) | |
tree | 94f9a23ab507e0fe8791b158ed74158ed5f2f3e7 /bfd | |
parent | ba864c35f5856cd75dc75e5415f74fa13d05a9ce (diff) | |
download | fsf-binutils-gdb-3c1f1c35784f4062455690329a0e7eaa61dd7c79.zip fsf-binutils-gdb-3c1f1c35784f4062455690329a0e7eaa61dd7c79.tar.gz fsf-binutils-gdb-3c1f1c35784f4062455690329a0e7eaa61dd7c79.tar.bz2 |
x86-64: Add R_X86_64_CODE_6_GOTTPOFF
For
add %reg1, name@gottpoff(%rip), %reg2
and
add name@gottpoff(%rip), %reg1, %reg2
add
#define R_X86_64_CODE_6_GOTTPOFF 50
if the instruction starts at 6 bytes before the relocation offset.
They are similar to R_X86_64_GOTTPOFF. Linker can covert GOTTPOFF to
add $name@tpoff, %reg1, %reg2
Rewrite fx_tcbit, fx_tcbit2 and fx_tcbit3 usage to generate
R_X86_64_GOTPCRELX, R_X86_64_REX_GOTPCRELX, R_X86_64_CODE_4_GOTPCRELX,
R_X86_64_CODE_4_GOTTPOFF, R_X86_64_CODE_4_GOTPC32_TLSDESC and
R_X86_64_CODE_6_GOTTPOFF.
NB: There is no need to check BFD_RELOC_X86_64_CODE_4_GOTTPOFF in
md_assemble since there is only BFD_RELOC_X86_64_GOTTPOFF at this
stage, which will be converted to BFD_RELOC_X86_64_CODE_4_GOTTPOFF
or BFD_RELOC_X86_64_CODE_6_GOTTPOFF in i386_validate_fix.
5 relocations:
#define R_X86_64_CODE_5_GOTPCRELX 46
#define R_X86_64_CODE_5_GOTTPOFF 47
#define R_X86_64_CODE_5_GOTPC32_TLSDESC 48
#define R_X86_64_CODE_6_GOTPCRELX 49
#define R_X86_64_CODE_6_GOTPC32_TLSDESC 51
are added for completeness and they are unused.
bfd/
* elf64-x86-64.c (x86_64_elf_howto_table): Add
R_X86_64_CODE_5_GOTPCRELX, R_X86_64_CODE_5_GOTTPOFF,
R_X86_64_CODE_5_GOTPC32_TLSDESC, R_X86_64_CODE_6_GOTPCRELX,
R_X86_64_CODE_6_GOTTPOFF and R_X86_64_CODE_6_GOTPC32_TLSDESC.
(R_X86_64_standard): Updated.
(x86_64_reloc_map): Add R_X86_64_CODE_5_GOTPCRELX,
R_X86_64_CODE_5_GOTTPOFF, R_X86_64_CODE_5_GOTPC32_TLSDESC,
R_X86_64_CODE_6_GOTPCRELX, R_X86_64_CODE_6_GOTTPOFF and
R_X86_64_CODE_6_GOTPC32_TLSDESC.
(elf_x86_64_check_tls_transition): Handle
R_X86_64_CODE_6_GOTTPOFF.
(elf_x86_64_tls_transition): Likewise.
(elf_x86_64_scan_relocs): Handle R_X86_64_CODE_6_GOTTPOFF.
Issue an error for R_X86_64_CODE_5_GOTPCRELX,
R_X86_64_CODE_5_GOTTPOFF, R_X86_64_CODE_5_GOTPC32_TLSDESC,
R_X86_64_CODE_6_GOTPCRELX and R_X86_64_CODE_6_GOTPC32_TLSDESC.
(elf_x86_64_relocate_section): Handle R_X86_64_CODE_6_GOTTPOFF.
* reloc.c (bfd_reloc_code_real): Add
BFD_RELOC_X86_64_CODE_5_GOTPCRELX,
BFD_RELOC_X86_64_CODE_5_GOTTPOFF,
BFD_RELOC_X86_64_CODE_5_GOTPC32_TLSDESC,
BFD_RELOC_X86_64_CODE_6_GOTPCRELX,
BFD_RELOC_X86_64_CODE_6_GOTTPOFF and
BFD_RELOC_X86_64_CODE_6_GOTPC32_TLSDESC.
* bfd-in2.h: Regenerated.
* libbfd.h: Likewise.
elfcpp/
* x86_64.h (R_X86_64_CODE_5_GOTPCRELX): New.
(R_X86_64_CODE_5_GOTTPOFF): Likewise.
(R_X86_64_CODE_5_GOTPC32_TLSDESC): Likewise.
(R_X86_64_CODE_6_GOTPCRELX): Likewise.
(R_X86_64_CODE_6_GOTTPOFF): Likewise.
(R_X86_64_CODE_6_GOTPC32_TLSDESC): Likewise.
gas/
* config/tc-i386.c (tc_i386_fix_adjustable): Handle
BFD_RELOC_X86_64_CODE_6_GOTTPOFF.
(md_assemble): Don't check BFD_RELOC_X86_64_CODE_4_GOTTPOFF.
Allow "add %reg1, foo@gottpoff(%rip), %reg2".
(output_disp): Handle BFD_RELOC_X86_64_CODE_6_GOTTPOFF. Rewrite
setting fx_tcbitX bits for BFD_RELOC_X86_64_GOTTPOFF,
BFD_RELOC_X86_64_GOTPC32_TLSDESC and BFD_RELOC_32_PCREL.
(md_apply_fix): Handle BFD_RELOC_X86_64_CODE_6_GOTTPOFF.
(i386_validate_fix): Rewrite fx_tcbitX bit checking for
BFD_RELOC_X86_64_GOTTPOFF, BFD_RELOC_X86_64_GOTPC32_TLSDESC and
BFD_RELOC_32_PCREL.
(tc_gen_reloc): Handle BFD_RELOC_X86_64_CODE_6_GOTTPOFF.
* testsuite/gas/i386/x86-64-gottpoff.d: Updated.
* testsuite/gas/i386/x86-64-gottpoff.s: Add tests for
"add %reg1, foo@gottpoff(%rip), %reg2" and
"add foo@gottpoff(%rip), %reg, %reg2".
gold/
* x86_64.cc (Target_x86_64::optimize_tls_reloc): Handle
R_X86_64_CODE_6_GOTTPOFF.
(Target_x86_64::Scan::get_reference_flags): Likewise.
(Target_x86_64::Scan::local): Likewise.
(Target_x86_64::Scan::global): Likewise.
(Target_x86_64::Relocate::relocate): Likewise.
(Target_x86_64::Relocate::relocate_tls): Likewise.
(Target_x86_64::Relocate::tls_ie_to_le): Handle.
R_X86_64_CODE_6_GOTTPOFF.
* testsuite/x86_64_ie_to_le.s: Add tests for
"add %reg1, foo@gottpoff(%rip), %reg2" and
"add foo@gottpoff(%rip), %reg, %reg2".
* testsuite/x86_64_ie_to_le.sh: Updated.
include/
* elf/x86-64.h (elf_x86_64_reloc_type): Add
R_X86_64_CODE_5_GOTPCRELX, R_X86_64_CODE_5_GOTTPOFF,
R_X86_64_CODE_5_GOTPC32_TLSDESC, R_X86_64_CODE_6_GOTPCRELX,
R_X86_64_CODE_6_GOTTPOFF and R_X86_64_CODE_6_GOTPC32_TLSDESC.
ld/
* testsuite/ld-x86-64/tlsbindesc.s: Add R_X86_64_CODE_6_GOTTPOFF
tests.
* testsuite/ld-x86-64/tlsbindesc.d: Updated.
* testsuite/ld-x86-64/tlsbindesc.rd: Likewise.
(cherry picked from commit 5bc71c2a6b8efb27089baa1fecded82be4f550a7)
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/bfd-in2.h | 6 | ||||
-rw-r--r-- | bfd/elf64-x86-64.c | 113 | ||||
-rw-r--r-- | bfd/libbfd.h | 6 | ||||
-rw-r--r-- | bfd/reloc.c | 12 |
4 files changed, 136 insertions, 1 deletions
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 581d8fe..dbafcf8 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -3894,6 +3894,12 @@ enum bfd_reloc_code_real BFD_RELOC_X86_64_CODE_4_GOTPCRELX, BFD_RELOC_X86_64_CODE_4_GOTTPOFF, BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC, + BFD_RELOC_X86_64_CODE_5_GOTPCRELX, + BFD_RELOC_X86_64_CODE_5_GOTTPOFF, + BFD_RELOC_X86_64_CODE_5_GOTPC32_TLSDESC, + BFD_RELOC_X86_64_CODE_6_GOTPCRELX, + BFD_RELOC_X86_64_CODE_6_GOTTPOFF, + BFD_RELOC_X86_64_CODE_6_GOTPC32_TLSDESC, /* ns32k relocations. */ BFD_RELOC_NS32K_IMM_8, diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index f125375..2ed120a 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -179,12 +179,30 @@ static reloc_howto_type x86_64_elf_howto_table[] = HOWTO(R_X86_64_CODE_4_GOTPC32_TLSDESC, 0, 4, 32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_X86_64_CODE_4_GOTPC32_TLSDESC", false, 0, 0xffffffff, true), + HOWTO(R_X86_64_CODE_5_GOTPCRELX, 0, 4, 32, true, 0, + complain_overflow_signed, bfd_elf_generic_reloc, + "R_X86_64_CODE_5_GOTPCRELX", false, 0, 0xffffffff, true), + HOWTO(R_X86_64_CODE_5_GOTTPOFF, 0, 4, 32, true, 0, + complain_overflow_signed, bfd_elf_generic_reloc, + "R_X86_64_CODE_5_GOTTPOFF", false, 0, 0xffffffff, true), + HOWTO(R_X86_64_CODE_5_GOTPC32_TLSDESC, 0, 4, 32, true, 0, + complain_overflow_bitfield, bfd_elf_generic_reloc, + "R_X86_64_CODE_5_GOTPC32_TLSDESC", false, 0, 0xffffffff, true), + HOWTO(R_X86_64_CODE_6_GOTPCRELX, 0, 4, 32, true, 0, + complain_overflow_signed, bfd_elf_generic_reloc, + "R_X86_64_CODE_6_GOTPCRELX", false, 0, 0xffffffff, true), + HOWTO(R_X86_64_CODE_6_GOTTPOFF, 0, 4, 32, true, 0, + complain_overflow_signed, bfd_elf_generic_reloc, + "R_X86_64_CODE_6_GOTTPOFF", false, 0, 0xffffffff, true), + HOWTO(R_X86_64_CODE_6_GOTPC32_TLSDESC, 0, 4, 32, true, 0, + complain_overflow_bitfield, bfd_elf_generic_reloc, + "R_X86_64_CODE_6_GOTPC32_TLSDESC", false, 0, 0xffffffff, true), /* We have a gap in the reloc numbers here. R_X86_64_standard counts the number up to this point, and R_X86_64_vt_offset is the value to subtract from a reloc type of R_X86_64_GNU_VT* to form an index into this table. */ -#define R_X86_64_standard (R_X86_64_CODE_4_GOTPC32_TLSDESC + 1) +#define R_X86_64_standard (R_X86_64_CODE_6_GOTPC32_TLSDESC + 1) #define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard) /* GNU extension to record C++ vtable hierarchy. */ @@ -256,6 +274,12 @@ static const struct elf_reloc_map x86_64_reloc_map[] = { BFD_RELOC_X86_64_CODE_4_GOTPCRELX, R_X86_64_CODE_4_GOTPCRELX, }, { BFD_RELOC_X86_64_CODE_4_GOTTPOFF, R_X86_64_CODE_4_GOTTPOFF, }, { BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC, R_X86_64_CODE_4_GOTPC32_TLSDESC, }, + { BFD_RELOC_X86_64_CODE_5_GOTPCRELX, R_X86_64_CODE_5_GOTPCRELX, }, + { BFD_RELOC_X86_64_CODE_5_GOTTPOFF, R_X86_64_CODE_5_GOTTPOFF, }, + { BFD_RELOC_X86_64_CODE_5_GOTPC32_TLSDESC, R_X86_64_CODE_5_GOTPC32_TLSDESC, }, + { BFD_RELOC_X86_64_CODE_6_GOTPCRELX, R_X86_64_CODE_6_GOTPCRELX, }, + { BFD_RELOC_X86_64_CODE_6_GOTTPOFF, R_X86_64_CODE_6_GOTTPOFF, }, + { BFD_RELOC_X86_64_CODE_6_GOTPC32_TLSDESC, R_X86_64_CODE_6_GOTPC32_TLSDESC, }, { BFD_RELOC_VTABLE_INHERIT, R_X86_64_GNU_VTINHERIT, }, { BFD_RELOC_VTABLE_ENTRY, R_X86_64_GNU_VTENTRY, }, }; @@ -1283,6 +1307,23 @@ elf_x86_64_check_tls_transition (bfd *abfd, goto check_gottpoff; + case R_X86_64_CODE_6_GOTTPOFF: + /* Check transition from IE access model: + add %reg1, foo@gottpoff(%rip), %reg2 + where reg1/reg2 are one of r16 to r31. */ + + if (offset < 6 + || (offset + 4) > sec->size + || contents[offset - 6] != 0x62) + return false; + + val = bfd_get_8 (abfd, contents + offset - 2); + if (val != 0x01 && val != 0x03) + return false; + + val = bfd_get_8 (abfd, contents + offset - 1); + return (val & 0xc7) == 5; + case R_X86_64_GOTTPOFF: /* Check transition from IE access model: mov foo@gottpoff(%rip), %reg @@ -1417,6 +1458,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, case R_X86_64_TLSDESC_CALL: case R_X86_64_GOTTPOFF: case R_X86_64_CODE_4_GOTTPOFF: + case R_X86_64_CODE_6_GOTTPOFF: if (bfd_link_executable (info)) { if (h == NULL) @@ -1464,6 +1506,8 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd, /* Return TRUE if there is no transition. */ if (from_type == to_type || (from_type == R_X86_64_CODE_4_GOTTPOFF + && to_type == R_X86_64_GOTTPOFF) + || (from_type == R_X86_64_CODE_6_GOTTPOFF && to_type == R_X86_64_GOTTPOFF)) return true; @@ -2177,6 +2221,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, case R_X86_64_GOTTPOFF: case R_X86_64_CODE_4_GOTTPOFF: + case R_X86_64_CODE_6_GOTTPOFF: if (!bfd_link_executable (info)) info->flags |= DF_STATIC_TLS; /* Fall through */ @@ -2214,6 +2259,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, break; case R_X86_64_GOTTPOFF: case R_X86_64_CODE_4_GOTTPOFF: + case R_X86_64_CODE_6_GOTTPOFF: tls_type = GOT_TLS_IE; break; case R_X86_64_GOTPC32_TLSDESC: @@ -2503,6 +2549,26 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info, } break; + case R_X86_64_CODE_5_GOTPCRELX: + case R_X86_64_CODE_5_GOTTPOFF: + case R_X86_64_CODE_5_GOTPC32_TLSDESC: + case R_X86_64_CODE_6_GOTPCRELX: + case R_X86_64_CODE_6_GOTPC32_TLSDESC: + { + /* These relocations are added only for completeness and + aren't be used. */ + if (h) + name = h->root.root.string; + else + name = bfd_elf_sym_name (abfd, symtab_hdr, isym, + NULL); + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: unsupported relocation %s against symbol `%s'"), + abfd, x86_64_elf_howto_table[r_type].name, name); + } + break; + /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_X86_64_GNU_VTINHERIT: @@ -3570,6 +3636,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, case R_X86_64_TLSDESC_CALL: case R_X86_64_GOTTPOFF: case R_X86_64_CODE_4_GOTTPOFF: + case R_X86_64_CODE_6_GOTTPOFF: tls_type = GOT_UNKNOWN; if (h == NULL && local_got_offsets) tls_type = elf_x86_local_got_tls_type (input_bfd) [r_symndx]; @@ -3920,6 +3987,50 @@ elf_x86_64_relocate_section (bfd *output_bfd, contents + roff); continue; } + else if (r_type == R_X86_64_CODE_6_GOTTPOFF) + { + /* IE->LE transition: + Originally it is + add %reg1, foo@gottpoff(%rip), %reg2 + or + add foo@gottpoff(%rip), %reg1, %reg2 + We change it into: + add $foo@tpoff, %reg1, %reg2 + */ + unsigned int reg, byte1; + unsigned int updated_byte1; + + if (roff < 6) + goto corrupt_input; + + /* Move the R bits to the B bits in EVEX payload + byte 1. */ + byte1 = bfd_get_8 (input_bfd, contents + roff - 5); + updated_byte1 = byte1; + + /* Set the R bits since they is inverted. */ + updated_byte1 |= 1 << 7 | 1 << 4; + + /* Update the B bits from the R bits. */ + if ((byte1 & (1 << 7)) == 0) + updated_byte1 &= ~(1 << 5); + if ((byte1 & (1 << 4)) == 0) + updated_byte1 |= 1 << 3; + + reg = bfd_get_8 (input_bfd, contents + roff - 1); + reg >>= 3; + + bfd_put_8 (output_bfd, updated_byte1, + contents + roff - 5); + bfd_put_8 (output_bfd, 0x81, + contents + roff - 2); + bfd_put_8 (output_bfd, 0xc0 | reg, + contents + roff - 1); + bfd_put_32 (output_bfd, + elf_x86_64_tpoff (info, relocation), + contents + roff); + continue; + } else BFD_ASSERT (false); } diff --git a/bfd/libbfd.h b/bfd/libbfd.h index ebd4f24..40bbe6a 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1463,6 +1463,12 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_X86_64_CODE_4_GOTPCRELX", "BFD_RELOC_X86_64_CODE_4_GOTTPOFF", "BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC", + "BFD_RELOC_X86_64_CODE_5_GOTPCRELX", + "BFD_RELOC_X86_64_CODE_5_GOTTPOFF", + "BFD_RELOC_X86_64_CODE_5_GOTPC32_TLSDESC", + "BFD_RELOC_X86_64_CODE_6_GOTPCRELX", + "BFD_RELOC_X86_64_CODE_6_GOTTPOFF", + "BFD_RELOC_X86_64_CODE_6_GOTPC32_TLSDESC", "BFD_RELOC_NS32K_IMM_8", "BFD_RELOC_NS32K_IMM_16", "BFD_RELOC_NS32K_IMM_32", diff --git a/bfd/reloc.c b/bfd/reloc.c index e74cbd7..7583b7f 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2481,6 +2481,18 @@ ENUMX BFD_RELOC_X86_64_CODE_4_GOTTPOFF ENUMX BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC +ENUMX + BFD_RELOC_X86_64_CODE_5_GOTPCRELX +ENUMX + BFD_RELOC_X86_64_CODE_5_GOTTPOFF +ENUMX + BFD_RELOC_X86_64_CODE_5_GOTPC32_TLSDESC +ENUMX + BFD_RELOC_X86_64_CODE_6_GOTPCRELX +ENUMX + BFD_RELOC_X86_64_CODE_6_GOTTPOFF +ENUMX + BFD_RELOC_X86_64_CODE_6_GOTPC32_TLSDESC ENUMDOC x86-64/elf relocations. |