663 lines
26 KiB
Diff
663 lines
26 KiB
Diff
|
diff -rup binutils.orig/bfd/bfd-in2.h binutils-2.41/bfd/bfd-in2.h
|
||
|
--- binutils.orig/bfd/bfd-in2.h 2024-04-05 10:34:23.956241281 +0100
|
||
|
+++ binutils-2.41/bfd/bfd-in2.h 2024-04-05 10:59:44.555106927 +0100
|
||
|
@@ -3840,6 +3840,12 @@ instruction. */
|
||
|
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 -rup binutils.orig/bfd/elf64-x86-64.c binutils-2.41/bfd/elf64-x86-64.c
|
||
|
--- binutils.orig/bfd/elf64-x86-64.c 2024-04-05 10:34:23.956241281 +0100
|
||
|
+++ binutils-2.41/bfd/elf64-x86-64.c 2024-04-05 10:59:44.557106930 +0100
|
||
|
@@ -179,12 +179,30 @@ static reloc_howto_type x86_64_elf_howto
|
||
|
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
|
||
|
{ 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 *ab
|
||
|
|
||
|
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_li
|
||
|
case R_X86_64_GOTTPOFF:
|
||
|
case R_X86_64_CODE_4_GOTPC32_TLSDESC:
|
||
|
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_li
|
||
|
/* 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, struc
|
||
|
|
||
|
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, struc
|
||
|
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, struc
|
||
|
}
|
||
|
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
|
||
|
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];
|
||
|
@@ -3915,6 +3982,50 @@ elf_x86_64_relocate_section (bfd *output
|
||
|
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 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);
|
||
|
diff -rup binutils.orig/bfd/libbfd.h binutils-2.41/bfd/libbfd.h
|
||
|
--- binutils.orig/bfd/libbfd.h 2024-04-05 10:34:23.956241281 +0100
|
||
|
+++ binutils-2.41/bfd/libbfd.h 2024-04-05 10:59:44.559106933 +0100
|
||
|
@@ -1470,6 +1470,12 @@ static const char *const bfd_reloc_code_
|
||
|
"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 -rup binutils.orig/bfd/reloc.c binutils-2.41/bfd/reloc.c
|
||
|
--- binutils.orig/bfd/reloc.c 2024-04-05 10:34:23.956241281 +0100
|
||
|
+++ binutils-2.41/bfd/reloc.c 2024-04-05 10:59:44.561106936 +0100
|
||
|
@@ -2487,6 +2487,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
|
||
|
|
||
|
diff -rup binutils.orig/elfcpp/x86_64.h binutils-2.41/elfcpp/x86_64.h
|
||
|
--- binutils.orig/elfcpp/x86_64.h 2024-04-05 10:34:23.969241295 +0100
|
||
|
+++ binutils-2.41/elfcpp/x86_64.h 2024-04-05 10:59:44.561106936 +0100
|
||
|
@@ -110,6 +110,30 @@ enum
|
||
|
// descriptor in GOT if the
|
||
|
// instruction starts at 4 bytes
|
||
|
// before the relocation offset.
|
||
|
+ R_X86_64_CODE_5_GOTPCRELX = 46, // 32 bit signed PC relative offset to
|
||
|
+ // GOT if the instruction starts at 5
|
||
|
+ // bytes before the relocation offset,
|
||
|
+ // relaxable.
|
||
|
+ R_X86_64_CODE_5_GOTTPOFF = 47, // 32 bit signed PC relative offset to
|
||
|
+ // GOT entry for IE symbol if the
|
||
|
+ // instruction starts at 5 bytes before
|
||
|
+ // the relocation offset.
|
||
|
+ R_X86_64_CODE_5_GOTPC32_TLSDESC = 48, // 32-bit PC relative to TLS
|
||
|
+ // descriptor in GOT if the
|
||
|
+ // instruction starts at 5 bytes
|
||
|
+ // before the relocation offset.
|
||
|
+ R_X86_64_CODE_6_GOTPCRELX = 49, // 32 bit signed PC relative offset to
|
||
|
+ // GOT if the instruction starts at 6
|
||
|
+ // bytes before the relocation offset,
|
||
|
+ // relaxable.
|
||
|
+ R_X86_64_CODE_6_GOTTPOFF = 50, // 32 bit signed PC relative offset to
|
||
|
+ // GOT entry for IE symbol if the
|
||
|
+ // instruction starts at 6 bytes before
|
||
|
+ // the relocation offset.
|
||
|
+ R_X86_64_CODE_6_GOTPC32_TLSDESC = 51, // 32-bit PC relative to TLS
|
||
|
+ // descriptor in GOT if the
|
||
|
+ // instruction starts at 6 bytes
|
||
|
+ // before the relocation offset.
|
||
|
// GNU vtable garbage collection extensions.
|
||
|
R_X86_64_GNU_VTINHERIT = 250,
|
||
|
R_X86_64_GNU_VTENTRY = 251
|
||
|
diff -rup binutils.orig/gas/config/tc-i386.c binutils-2.41/gas/config/tc-i386.c
|
||
|
--- binutils.orig/gas/config/tc-i386.c 2024-04-05 10:34:23.973241300 +0100
|
||
|
+++ binutils-2.41/gas/config/tc-i386.c 2024-04-05 10:59:44.561106936 +0100
|
||
|
@@ -3640,6 +3640,7 @@ tc_i386_fix_adjustable (fixS *fixP)
|
||
|
|| fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF64
|
||
|
|| fixP->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF
|
||
|
|| fixP->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTTPOFF
|
||
|
+ || fixP->fx_r_type == BFD_RELOC_X86_64_CODE_6_GOTTPOFF
|
||
|
|| fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32
|
||
|
|| fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF64
|
||
|
|| fixP->fx_r_type == BFD_RELOC_X86_64_GOTOFF64
|
||
|
@@ -5671,10 +5672,19 @@ md_assemble (char *line)
|
||
|
for (j = i.imm_operands; j < i.operands; ++j)
|
||
|
switch (i.reloc[j])
|
||
|
{
|
||
|
+ case BFD_RELOC_X86_64_GOTTPOFF:
|
||
|
+ if (i.tm.mnem_off == MN_add
|
||
|
+ && i.tm.opcode_space == SPACE_EVEXMAP4
|
||
|
+ && i.mem_operands == 1
|
||
|
+ && i.base_reg
|
||
|
+ && i.base_reg->reg_num == RegIP
|
||
|
+ && i.tm.operand_types[0].bitfield.class == Reg
|
||
|
+ && i.tm.operand_types[2].bitfield.class == Reg)
|
||
|
+ /* Allow APX: add %reg1, foo@gottpoff(%rip), %reg2. */
|
||
|
+ break;
|
||
|
+ /* Fall through. */
|
||
|
case BFD_RELOC_386_TLS_GOTIE:
|
||
|
case BFD_RELOC_386_TLS_LE_32:
|
||
|
- case BFD_RELOC_X86_64_GOTTPOFF:
|
||
|
- case BFD_RELOC_X86_64_CODE_4_GOTTPOFF:
|
||
|
case BFD_RELOC_X86_64_TLSLD:
|
||
|
as_bad (_("TLS relocation cannot be used with `%s'"), insn_name (&i.tm));
|
||
|
return;
|
||
|
@@ -10889,6 +10899,7 @@ output_disp (fragS *insn_start_frag, off
|
||
|
case BFD_RELOC_X86_64_TLSLD:
|
||
|
case BFD_RELOC_X86_64_GOTTPOFF:
|
||
|
case BFD_RELOC_X86_64_CODE_4_GOTTPOFF:
|
||
|
+ case BFD_RELOC_X86_64_CODE_6_GOTTPOFF:
|
||
|
case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
|
||
|
case BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC:
|
||
|
case BFD_RELOC_X86_64_TLSDESC_CALL:
|
||
|
@@ -10905,9 +10916,30 @@ output_disp (fragS *insn_start_frag, off
|
||
|
&& !i.prefix[ADDR_PREFIX])
|
||
|
fixP->fx_signed = 1;
|
||
|
|
||
|
- /* Set fx_tcbit3 for REX2 prefix. */
|
||
|
- if (is_apx_rex2_encoding ())
|
||
|
- fixP->fx_tcbit3 = 1;
|
||
|
+ if (reloc_type == BFD_RELOC_X86_64_GOTTPOFF
|
||
|
+ && i.tm.opcode_space == SPACE_EVEXMAP4)
|
||
|
+ {
|
||
|
+ /* Only "add %reg1, foo@gottpoff(%rip), %reg2" is
|
||
|
+ allowed in md_assemble. Set fx_tcbit2 for EVEX
|
||
|
+ prefix. */
|
||
|
+ fixP->fx_tcbit2 = 1;
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (i.base_reg && i.base_reg->reg_num == RegIP)
|
||
|
+ {
|
||
|
+ if (reloc_type == BFD_RELOC_X86_64_GOTPC32_TLSDESC)
|
||
|
+ {
|
||
|
+ /* Set fx_tcbit for REX2 prefix. */
|
||
|
+ if (is_apx_rex2_encoding ())
|
||
|
+ fixP->fx_tcbit = 1;
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ /* In 64-bit, i386_validate_fix updates only (%rip)
|
||
|
+ relocations. */
|
||
|
+ else if (object_64bit)
|
||
|
+ continue;
|
||
|
|
||
|
/* Check for "call/jmp *mem", "mov mem, %reg",
|
||
|
"test %reg, mem" and "binop mem, %reg" where binop
|
||
|
@@ -10932,10 +10964,22 @@ output_disp (fragS *insn_start_frag, off
|
||
|
{
|
||
|
if (object_64bit)
|
||
|
{
|
||
|
- fixP->fx_tcbit = i.rex != 0;
|
||
|
- if (i.base_reg
|
||
|
- && (i.base_reg->reg_num == RegIP))
|
||
|
- fixP->fx_tcbit2 = 1;
|
||
|
+ if (reloc_type == BFD_RELOC_X86_64_GOTTPOFF)
|
||
|
+ {
|
||
|
+ /* Set fx_tcbit for REX2 prefix. */
|
||
|
+ if (is_apx_rex2_encoding ())
|
||
|
+ fixP->fx_tcbit = 1;
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ /* Set fx_tcbit3 for REX2 prefix. */
|
||
|
+ if (is_apx_rex2_encoding ())
|
||
|
+ fixP->fx_tcbit3 = 1;
|
||
|
+ else if (i.rex)
|
||
|
+ fixP->fx_tcbit2 = 1;
|
||
|
+ else
|
||
|
+ fixP->fx_tcbit = 1;
|
||
|
+ }
|
||
|
}
|
||
|
else
|
||
|
fixP->fx_tcbit2 = 1;
|
||
|
@@ -14405,6 +14449,7 @@ md_apply_fix (fixS *fixP, valueT *valP,
|
||
|
case BFD_RELOC_X86_64_TLSLD:
|
||
|
case BFD_RELOC_X86_64_GOTTPOFF:
|
||
|
case BFD_RELOC_X86_64_CODE_4_GOTTPOFF:
|
||
|
+ case BFD_RELOC_X86_64_CODE_6_GOTTPOFF:
|
||
|
case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
|
||
|
case BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC:
|
||
|
value = 0; /* Fully resolved at runtime. No addend. */
|
||
|
@@ -15980,13 +16025,27 @@ i386_validate_fix (fixS *fixp)
|
||
|
&& (!S_IS_DEFINED (fixp->fx_addsy)
|
||
|
|| S_IS_EXTERNAL (fixp->fx_addsy));
|
||
|
|
||
|
- if (fixp->fx_tcbit3)
|
||
|
+ /* BFD_RELOC_X86_64_GOTTPOFF:
|
||
|
+ 1. fx_tcbit -> BFD_RELOC_X86_64_CODE_4_GOTTPOFF
|
||
|
+ 2. fx_tcbit2 -> BFD_RELOC_X86_64_CODE_6_GOTTPOFF
|
||
|
+ BFD_RELOC_X86_64_GOTPC32_TLSDESC:
|
||
|
+ 1. fx_tcbit -> BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC
|
||
|
+ BFD_RELOC_32_PCREL:
|
||
|
+ 1. fx_tcbit -> BFD_RELOC_X86_64_GOTPCRELX
|
||
|
+ 2. fx_tcbit2 -> BFD_RELOC_X86_64_REX_GOTPCRELX
|
||
|
+ 3. fx_tcbit3 -> BFD_RELOC_X86_64_CODE_4_GOTPCRELX
|
||
|
+ 4. else -> BFD_RELOC_X86_64_GOTPCREL
|
||
|
+ */
|
||
|
+ if (fixp->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF)
|
||
|
{
|
||
|
- if (fixp->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF)
|
||
|
+ if (fixp->fx_tcbit)
|
||
|
fixp->fx_r_type = BFD_RELOC_X86_64_CODE_4_GOTTPOFF;
|
||
|
- else if (fixp->fx_r_type == BFD_RELOC_X86_64_GOTPC32_TLSDESC)
|
||
|
- fixp->fx_r_type = BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC;
|
||
|
+ else if (fixp->fx_tcbit2)
|
||
|
+ fixp->fx_r_type = BFD_RELOC_X86_64_CODE_6_GOTTPOFF;
|
||
|
}
|
||
|
+ else if (fixp->fx_r_type == BFD_RELOC_X86_64_GOTPC32_TLSDESC
|
||
|
+ && fixp->fx_tcbit)
|
||
|
+ fixp->fx_r_type = BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC;
|
||
|
#endif
|
||
|
|
||
|
if (fixp->fx_subsy)
|
||
|
@@ -15998,15 +16057,12 @@ i386_validate_fix (fixS *fixp)
|
||
|
if (!object_64bit)
|
||
|
abort ();
|
||
|
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
|
||
|
- if (fixp->fx_tcbit2)
|
||
|
- {
|
||
|
- if (fixp->fx_tcbit3)
|
||
|
- fixp->fx_r_type = BFD_RELOC_X86_64_CODE_4_GOTPCRELX;
|
||
|
- else
|
||
|
- fixp->fx_r_type = (fixp->fx_tcbit
|
||
|
- ? BFD_RELOC_X86_64_REX_GOTPCRELX
|
||
|
- : BFD_RELOC_X86_64_GOTPCRELX);
|
||
|
- }
|
||
|
+ if (fixp->fx_tcbit)
|
||
|
+ fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCRELX;
|
||
|
+ else if (fixp->fx_tcbit2)
|
||
|
+ fixp->fx_r_type = BFD_RELOC_X86_64_REX_GOTPCRELX;
|
||
|
+ else if (fixp->fx_tcbit3)
|
||
|
+ fixp->fx_r_type = BFD_RELOC_X86_64_CODE_4_GOTPCRELX;
|
||
|
else
|
||
|
#endif
|
||
|
fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL;
|
||
|
@@ -16132,6 +16188,7 @@ tc_gen_reloc (asection *section ATTRIBUT
|
||
|
case BFD_RELOC_X86_64_DTPOFF64:
|
||
|
case BFD_RELOC_X86_64_GOTTPOFF:
|
||
|
case BFD_RELOC_X86_64_CODE_4_GOTTPOFF:
|
||
|
+ case BFD_RELOC_X86_64_CODE_6_GOTTPOFF:
|
||
|
case BFD_RELOC_X86_64_TPOFF32:
|
||
|
case BFD_RELOC_X86_64_TPOFF64:
|
||
|
case BFD_RELOC_X86_64_GOTOFF64:
|
||
|
@@ -16276,6 +16333,7 @@ tc_gen_reloc (asection *section ATTRIBUT
|
||
|
case BFD_RELOC_X86_64_TLSLD:
|
||
|
case BFD_RELOC_X86_64_GOTTPOFF:
|
||
|
case BFD_RELOC_X86_64_CODE_4_GOTTPOFF:
|
||
|
+ case BFD_RELOC_X86_64_CODE_6_GOTTPOFF:
|
||
|
case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
|
||
|
case BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC:
|
||
|
case BFD_RELOC_X86_64_TLSDESC_CALL:
|
||
|
diff -rup binutils.orig/gas/testsuite/gas/i386/x86-64-gottpoff.d binutils-2.41/gas/testsuite/gas/i386/x86-64-gottpoff.d
|
||
|
--- binutils.orig/gas/testsuite/gas/i386/x86-64-gottpoff.d 2024-04-05 10:34:24.078241418 +0100
|
||
|
+++ binutils-2.41/gas/testsuite/gas/i386/x86-64-gottpoff.d 2024-04-05 10:59:44.561106936 +0100
|
||
|
@@ -16,4 +16,8 @@ Disassembly of section .text:
|
||
|
+[a-f0-9]+: 48 8b 05 00 00 00 00 mov 0x0\(%rip\),%rax # 2c <_start\+0x2c> 28: R_X86_64_GOTTPOFF foo-0x4
|
||
|
+[a-f0-9]+: d5 48 03 05 00 00 00 00 add 0x0\(%rip\),%r16 # 34 <_start\+0x34> 30: R_X86_64_CODE_4_GOTTPOFF foo-0x4
|
||
|
+[a-f0-9]+: d5 48 8b 25 00 00 00 00 mov 0x0\(%rip\),%r20 # 3c <_start\+0x3c> 38: R_X86_64_CODE_4_GOTTPOFF foo-0x4
|
||
|
+ +[a-f0-9]+: 62 74 fc 10 01 05 00 00 00 00 add %r8,0x0\(%rip\),%r16 # 46 <_start\+0x46> 42: R_X86_64_CODE_6_GOTTPOFF foo-0x4
|
||
|
+ +[a-f0-9]+: 62 f4 9c 18 03 05 00 00 00 00 add 0x0\(%rip\),%rax,%r12 # 50 <_start\+0x50> 4c: R_X86_64_CODE_6_GOTTPOFF foo-0x4
|
||
|
+ +[a-f0-9]+: 62 74 fc 10 01 05 00 00 00 00 add %r8,0x0\(%rip\),%r16 # 5a <_start\+0x5a> 56: R_X86_64_CODE_6_GOTTPOFF foo-0x4
|
||
|
+ +[a-f0-9]+: 62 f4 9c 18 03 05 00 00 00 00 add 0x0\(%rip\),%rax,%r12 # 64 <_start\+0x64> 60: R_X86_64_CODE_6_GOTTPOFF foo-0x4
|
||
|
#pass
|
||
|
diff -rup binutils.orig/gas/testsuite/gas/i386/x86-64-gottpoff.s binutils-2.41/gas/testsuite/gas/i386/x86-64-gottpoff.s
|
||
|
--- binutils.orig/gas/testsuite/gas/i386/x86-64-gottpoff.s 2024-04-05 10:34:24.078241418 +0100
|
||
|
+++ binutils-2.41/gas/testsuite/gas/i386/x86-64-gottpoff.s 2024-04-05 10:59:44.561106936 +0100
|
||
|
@@ -13,3 +13,13 @@ _start:
|
||
|
|
||
|
addq r16, QWORD PTR [rip + foo@GOTTPOFF]
|
||
|
movq r20, QWORD PTR [rip + foo@GOTTPOFF]
|
||
|
+
|
||
|
+ .att_syntax prefix
|
||
|
+
|
||
|
+ addq %r8, foo@GOTTPOFF(%rip), %r16
|
||
|
+ addq foo@GOTTPOFF(%rip), %rax, %r12
|
||
|
+
|
||
|
+ .intel_syntax noprefix
|
||
|
+
|
||
|
+ addq r16, QWORD PTR [rip + foo@GOTTPOFF], r8
|
||
|
+ addq r12, rax, QWORD PTR [rip + foo@GOTTPOFF]
|
||
|
diff -rup binutils.orig/gold/x86_64.cc binutils-2.41/gold/x86_64.cc
|
||
|
--- binutils.orig/gold/x86_64.cc 2024-04-05 10:34:24.166241517 +0100
|
||
|
+++ binutils-2.41/gold/x86_64.cc 2024-04-05 10:59:44.563106939 +0100
|
||
|
@@ -2920,6 +2920,11 @@ Target_x86_64<size>::optimize_tls_reloc(
|
||
|
// Another Local-Dynamic reloc.
|
||
|
return tls::TLSOPT_TO_LE;
|
||
|
|
||
|
+ case elfcpp::R_X86_64_CODE_6_GOTTPOFF:
|
||
|
+ if (r_offset <= 6 || *(reloc_view - 6) != 0x62)
|
||
|
+ return tls::TLSOPT_NONE;
|
||
|
+ goto handle_gottpoff;
|
||
|
+
|
||
|
case elfcpp::R_X86_64_CODE_4_GOTTPOFF:
|
||
|
if (r_offset <= 4 || *(reloc_view - 4) != 0xd5)
|
||
|
return tls::TLSOPT_NONE;
|
||
|
@@ -2929,6 +2934,7 @@ Target_x86_64<size>::optimize_tls_reloc(
|
||
|
// from the GOT. If we know that we are linking against the
|
||
|
// local symbol, we can switch to Local-Exec, which links the
|
||
|
// thread offset into the instruction.
|
||
|
+handle_gottpoff:
|
||
|
if (is_final)
|
||
|
return tls::TLSOPT_TO_LE;
|
||
|
return tls::TLSOPT_NONE;
|
||
|
@@ -2997,6 +3003,7 @@ Target_x86_64<size>::Scan::get_reference
|
||
|
case elfcpp::R_X86_64_DTPOFF64:
|
||
|
case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
|
||
|
case elfcpp::R_X86_64_CODE_4_GOTTPOFF:
|
||
|
+ case elfcpp::R_X86_64_CODE_6_GOTTPOFF:
|
||
|
case elfcpp::R_X86_64_TPOFF32: // Local-exec
|
||
|
return Symbol::TLS_REF;
|
||
|
|
||
|
@@ -3362,6 +3369,7 @@ need_got:
|
||
|
// These are initial tls relocs, which are expected when linking
|
||
|
case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC:
|
||
|
case elfcpp::R_X86_64_CODE_4_GOTTPOFF:
|
||
|
+ case elfcpp::R_X86_64_CODE_6_GOTTPOFF:
|
||
|
{
|
||
|
section_size_type stype;
|
||
|
reloc_view = object->section_contents(data_shndx, &stype, true);
|
||
|
@@ -3464,6 +3472,7 @@ need_got:
|
||
|
|
||
|
case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
|
||
|
case elfcpp::R_X86_64_CODE_4_GOTTPOFF:
|
||
|
+ case elfcpp::R_X86_64_CODE_6_GOTTPOFF:
|
||
|
layout->set_has_static_tls();
|
||
|
if (optimized_type == tls::TLSOPT_NONE)
|
||
|
{
|
||
|
@@ -3902,6 +3911,7 @@ Target_x86_64<size>::Scan::global(Symbol
|
||
|
// These are initial tls relocs, which are expected for global()
|
||
|
case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC:
|
||
|
case elfcpp::R_X86_64_CODE_4_GOTTPOFF:
|
||
|
+ case elfcpp::R_X86_64_CODE_6_GOTTPOFF:
|
||
|
{
|
||
|
section_size_type stype;
|
||
|
reloc_view = object->section_contents(data_shndx, &stype, true);
|
||
|
@@ -3920,7 +3930,8 @@ Target_x86_64<size>::Scan::global(Symbol
|
||
|
// when building an executable.
|
||
|
const bool is_final = (gsym->final_value_is_known() ||
|
||
|
((r_type == elfcpp::R_X86_64_GOTTPOFF ||
|
||
|
- r_type == elfcpp::R_X86_64_CODE_4_GOTTPOFF) &&
|
||
|
+ r_type == elfcpp::R_X86_64_CODE_4_GOTTPOFF||
|
||
|
+ r_type == elfcpp::R_X86_64_CODE_6_GOTTPOFF) &&
|
||
|
gsym->is_undefined() &&
|
||
|
parameters->options().output_is_executable()));
|
||
|
size_t r_offset = reloc.get_r_offset();
|
||
|
@@ -4006,6 +4017,7 @@ Target_x86_64<size>::Scan::global(Symbol
|
||
|
|
||
|
case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
|
||
|
case elfcpp::R_X86_64_CODE_4_GOTTPOFF:
|
||
|
+ case elfcpp::R_X86_64_CODE_6_GOTTPOFF:
|
||
|
layout->set_has_static_tls();
|
||
|
if (optimized_type == tls::TLSOPT_NONE)
|
||
|
{
|
||
|
@@ -4608,6 +4620,7 @@ Target_x86_64<size>::Relocate::relocate(
|
||
|
case elfcpp::R_X86_64_DTPOFF64:
|
||
|
case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
|
||
|
case elfcpp::R_X86_64_CODE_4_GOTTPOFF:
|
||
|
+ case elfcpp::R_X86_64_CODE_6_GOTTPOFF:
|
||
|
case elfcpp::R_X86_64_TPOFF32: // Local-exec
|
||
|
this->relocate_tls(relinfo, target, relnum, rela, r_type, gsym, psymval,
|
||
|
view, address, view_size);
|
||
|
@@ -4894,6 +4907,7 @@ Target_x86_64<size>::Relocate::relocate_
|
||
|
|
||
|
case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
|
||
|
case elfcpp::R_X86_64_CODE_4_GOTTPOFF:
|
||
|
+ case elfcpp::R_X86_64_CODE_6_GOTTPOFF:
|
||
|
if (gsym != NULL
|
||
|
&& gsym->is_undefined()
|
||
|
&& parameters->options().output_is_executable())
|
||
|
@@ -5308,11 +5322,19 @@ Target_x86_64<size>::Relocate::tls_ie_to
|
||
|
|
||
|
// movq foo@gottpoff(%rip),%reg ==> movq $YY,%reg
|
||
|
// addq foo@gottpoff(%rip),%reg ==> addq $YY,%reg
|
||
|
+ // addq %reg1,foo@gottpoff(%rip),%reg2 ==> addq $YY,%reg1,%reg2
|
||
|
+ // addq foo@gottpoff(%rip),%reg1,%reg2 ==> addq $YY,%reg1,%reg2
|
||
|
|
||
|
- tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3);
|
||
|
+ int off1;
|
||
|
+ if (r_type == elfcpp::R_X86_64_CODE_6_GOTTPOFF)
|
||
|
+ off1 = -5;
|
||
|
+ else
|
||
|
+ off1 = -3;
|
||
|
+
|
||
|
+ tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, off1);
|
||
|
tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4);
|
||
|
|
||
|
- unsigned char op1 = view[-3];
|
||
|
+ unsigned char op1 = view[off1];
|
||
|
unsigned char op2 = view[-2];
|
||
|
unsigned char op3 = view[-1];
|
||
|
unsigned char reg = op3 >> 3;
|
||
|
@@ -5350,7 +5372,7 @@ Target_x86_64<size>::Relocate::tls_ie_to
|
||
|
view[-1] = 0x80 | reg | (reg << 3);
|
||
|
}
|
||
|
}
|
||
|
- else
|
||
|
+ else if (r_type == elfcpp::R_X86_64_CODE_4_GOTTPOFF)
|
||
|
{
|
||
|
if (op2 == 0x8b)
|
||
|
op2 = 0xc7;
|
||
|
@@ -5362,6 +5384,23 @@ Target_x86_64<size>::Relocate::tls_ie_to
|
||
|
view[-2] = op2;
|
||
|
view[-1] = 0xc0 | reg;
|
||
|
}
|
||
|
+ else
|
||
|
+ {
|
||
|
+ unsigned char updated_op1 = op1;
|
||
|
+
|
||
|
+ // Set the R bits since they is inverted.
|
||
|
+ updated_op1 |= 1 << 7 | 1 << 4;
|
||
|
+
|
||
|
+ // Update the B bits from the R bits.
|
||
|
+ if ((op1 & (1 << 7)) == 0)
|
||
|
+ updated_op1 &= ~(1 << 5);
|
||
|
+ if ((op1 & (1 << 4)) == 0)
|
||
|
+ updated_op1 |= 1 << 3;
|
||
|
+
|
||
|
+ view[-5] = updated_op1;
|
||
|
+ view[-2] = 0x81;
|
||
|
+ view[-1] = 0xc0 | reg;
|
||
|
+ }
|
||
|
|
||
|
if (tls_segment != NULL)
|
||
|
value -= tls_segment->memsz();
|
||
|
diff -rup binutils.orig/include/elf/x86-64.h binutils-2.41/include/elf/x86-64.h
|
||
|
--- binutils.orig/include/elf/x86-64.h 2024-04-05 10:34:24.174241526 +0100
|
||
|
+++ binutils-2.41/include/elf/x86-64.h 2024-04-05 10:59:44.563106939 +0100
|
||
|
@@ -92,6 +92,26 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_ty
|
||
|
/* 32 bit signed pc relative offset to TLS descriptor in the GOT if
|
||
|
instruction starts at 4 bytes before the relocation offset. */
|
||
|
RELOC_NUMBER (R_X86_64_CODE_4_GOTPC32_TLSDESC, 45)
|
||
|
+ /* Load from 32 bit signed pc relative offset to GOT entry if the
|
||
|
+ instruction starts at 5 bytes before the relocation offset,
|
||
|
+ relaxable. */
|
||
|
+ RELOC_NUMBER (R_X86_64_CODE_5_GOTPCRELX, 46)
|
||
|
+ /* 32 bit signed pc relative offset to TLS descriptor in the GOT if
|
||
|
+ instruction starts at 5 bytes before the relocation offset. */
|
||
|
+ RELOC_NUMBER (R_X86_64_CODE_5_GOTPC32_TLSDESC, 47)
|
||
|
+ /* PC relative offset to IE GOT entry if the instruction starts at
|
||
|
+ 5 bytes before the relocation offset. */
|
||
|
+ RELOC_NUMBER (R_X86_64_CODE_5_GOTTPOFF, 48)
|
||
|
+ /* Load from 32 bit signed pc relative offset to GOT entry if the
|
||
|
+ instruction starts at 6 bytes before the relocation offset,
|
||
|
+ relaxable. */
|
||
|
+ RELOC_NUMBER (R_X86_64_CODE_6_GOTPCRELX, 49)
|
||
|
+ /* PC relative offset to IE GOT entry if the instruction starts at
|
||
|
+ 6 bytes before the relocation offset. */
|
||
|
+ RELOC_NUMBER (R_X86_64_CODE_6_GOTTPOFF, 50)
|
||
|
+ /* 32 bit signed pc relative offset to TLS descriptor in the GOT if
|
||
|
+ instruction starts at 6 bytes before the relocation offset. */
|
||
|
+ RELOC_NUMBER (R_X86_64_CODE_6_GOTPC32_TLSDESC, 51)
|
||
|
RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250) /* GNU C++ hack */
|
||
|
RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251) /* GNU C++ hack */
|
||
|
END_RELOC_NUMBERS (R_X86_64_max)
|