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::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::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::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::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::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::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::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::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::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::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::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)