aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2024-02-03 14:32:17 -0800
committerH.J. Lu <hjl.tools@gmail.com>2024-02-10 08:23:26 -0800
commit3c1f1c35784f4062455690329a0e7eaa61dd7c79 (patch)
tree94f9a23ab507e0fe8791b158ed74158ed5f2f3e7 /bfd
parentba864c35f5856cd75dc75e5415f74fa13d05a9ce (diff)
downloadfsf-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.h6
-rw-r--r--bfd/elf64-x86-64.c113
-rw-r--r--bfd/libbfd.h6
-rw-r--r--bfd/reloc.c12
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.