* [PATCH 0/4] Support APX relocations
@ 2023-12-28 14:58 H.J. Lu
2023-12-28 14:58 ` [PATCH 1/4] x86-64: Add R_X86_64_CODE_4_GOTPCRELX H.J. Lu
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: H.J. Lu @ 2023-12-28 14:58 UTC (permalink / raw)
To: binutils
Implement 3 APX relocations in ld and gold:
#define R_X86_64_CODE_4_GOTPCRELX 43
#define R_X86_64_CODE_4_GOTTPOFF 44
#define R_X86_64_CODE_4_GOTPC32_TLSDESC 45
H.J. Lu (4):
x86-64: Add R_X86_64_CODE_4_GOTPCRELX
gold: Handle R_X86_64_CODE_4_GOTPCRELX
x86-64: Add R_X86_64_CODE_4_GOTTPOFF/R_X86_64_CODE_4_GOTPC32_TLSDESC
Gold: Handle R_X86_64_CODE_4_GOTPC32_TLSDESC/R_X86_64_CODE_4_GOTTPOFF
bfd/bfd-in2.h | 3 +
bfd/elf64-x86-64.c | 196 ++++++++++++++++--
bfd/libbfd.h | 3 +
bfd/reloc.c | 6 +
elfcpp/x86_64.h | 14 +-
gas/config/tc-i386.c | 38 +++-
gas/config/tc-i386.h | 6 +-
.../gas/i386/ilp32/x86-64-localpic.d | 4 +-
gas/testsuite/gas/i386/x86-64-gotpcrel.d | 12 ++
gas/testsuite/gas/i386/x86-64-gotpcrel.s | 19 ++
gas/testsuite/gas/i386/x86-64-gottpoff.d | 19 ++
gas/testsuite/gas/i386/x86-64-gottpoff.s | 15 ++
gas/testsuite/gas/i386/x86-64-localpic.d | 4 +-
gas/testsuite/gas/i386/x86-64-localpic.s | 2 +
gas/testsuite/gas/i386/x86-64-tlsdesc.d | 17 ++
gas/testsuite/gas/i386/x86-64-tlsdesc.s | 13 ++
gas/testsuite/gas/i386/x86-64.exp | 3 +
gas/write.h | 3 +-
gold/testsuite/Makefile.am | 11 +
gold/testsuite/Makefile.in | 17 ++
gold/testsuite/x86_64_gd_to_le.s | 1 +
gold/testsuite/x86_64_gd_to_le.sh | 1 +
gold/testsuite/x86_64_ie_to_le.s | 17 ++
gold/testsuite/x86_64_ie_to_le.sh | 29 +++
gold/testsuite/x86_64_mov_to_lea.sh | 16 ++
gold/testsuite/x86_64_mov_to_lea1.s | 1 +
gold/testsuite/x86_64_mov_to_lea2.s | 1 +
gold/testsuite/x86_64_mov_to_lea3.s | 1 +
gold/testsuite/x86_64_mov_to_lea4.s | 1 +
gold/testsuite/x86_64_mov_to_lea5.s | 1 +
gold/x86_64.cc | 193 +++++++++++++----
include/elf/x86-64.h | 12 +-
ld/testsuite/ld-x86-64/apx-load1.s | 51 +++++
ld/testsuite/ld-x86-64/apx-load1a.d | 54 +++++
ld/testsuite/ld-x86-64/apx-load1b.d | 55 +++++
ld/testsuite/ld-x86-64/apx-load1c.d | 47 +++++
ld/testsuite/ld-x86-64/apx-load1d.d | 47 +++++
ld/testsuite/ld-x86-64/tlsbindesc.dd | 49 +++++
ld/testsuite/ld-x86-64/tlsbindesc.rd | 36 ++--
ld/testsuite/ld-x86-64/tlsbindesc.s | 39 ++++
ld/testsuite/ld-x86-64/x86-64.exp | 4 +
41 files changed, 967 insertions(+), 94 deletions(-)
create mode 100644 gas/testsuite/gas/i386/x86-64-gottpoff.d
create mode 100644 gas/testsuite/gas/i386/x86-64-gottpoff.s
create mode 100644 gas/testsuite/gas/i386/x86-64-tlsdesc.d
create mode 100644 gas/testsuite/gas/i386/x86-64-tlsdesc.s
create mode 100644 gold/testsuite/x86_64_ie_to_le.s
create mode 100755 gold/testsuite/x86_64_ie_to_le.sh
create mode 100644 ld/testsuite/ld-x86-64/apx-load1.s
create mode 100644 ld/testsuite/ld-x86-64/apx-load1a.d
create mode 100644 ld/testsuite/ld-x86-64/apx-load1b.d
create mode 100644 ld/testsuite/ld-x86-64/apx-load1c.d
create mode 100644 ld/testsuite/ld-x86-64/apx-load1d.d
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/4] x86-64: Add R_X86_64_CODE_4_GOTPCRELX
2023-12-28 14:58 [PATCH 0/4] Support APX relocations H.J. Lu
@ 2023-12-28 14:58 ` H.J. Lu
2023-12-28 14:58 ` [PATCH 2/4] gold: Handle R_X86_64_CODE_4_GOTPCRELX H.J. Lu
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: H.J. Lu @ 2023-12-28 14:58 UTC (permalink / raw)
To: binutils
For
mov name@GOTPCREL(%rip), %reg
test %reg, name@GOTPCREL(%rip)
binop name@GOTPCREL(%rip), %reg
where binop is one of adc, add, add, cmp, or, sbb, sub, xor instructions,
add
# define R_X86_64_CODE_4_GOTPCRELX 43
if the instruction starts at 4 bytes before the relocation offset. It
similar to R_X86_64_GOTPCRELX. Linker can treat R_X86_64_CODE_4_GOTPCRELX
as R_X86_64_GOTPCREL or convert the above instructions to
lea name(%rip), %reg
mov $name, %reg
test $name, %reg
binop $name, %reg
if the instruction is encoded with the REX2 prefix when possible.
bfd/
* elf64-x86-64.c (x86_64_elf_howto_table): Add
R_X86_64_CODE_4_GOTPCRELX.
(R_X86_64_standard): Updated.
(x86_64_reloc_map): Add BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
(elf_x86_64_convert_load_reloc): Handle R_X86_64_CODE_4_GOTPCRELX.
(elf_x86_64_scan_relocs): Likewise.
(elf_x86_64_relocate_section): Likewise.
* reloc.c (bfd_reloc_code_real): Add
BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
* bfd-in2.h: Regenerated.
* libbfd.h: Likewise.
gas/
* write.h (fix): Add fx_tcbit3. Change fx_unused to 1 bit.
* config/tc-i386.c (tc_i386_fix_adjustable): Handle
BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
(tc_gen_reloc): Likewise.
(output_disp): Set fixP->fx_tcbit3 for REX2 prefix.
(i386_validate_fix): Generate BFD_RELOC_X86_64_CODE_4_GOTPCRELX
if fixp->fx_tcbit3 is set.
* config/tc-i386.h (TC_FORCE_RELOCATION_LOCAL): Add
BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
(TC_FORCE_RELOCATION_ABS): Likewise.
* testsuite/gas/i386/x86-64-gotpcrel.s: Add tests for
R_X86_64_CODE_4_GOTPCRELX.
* testsuite/gas/i386/x86-64-localpic.s: Likewise.
* testsuite/gas/i386/x86-64-gotpcrel.d: Updated.
* testsuite/gas/i386/x86-64-localpic.d: Likewise.
* testsuite/gas/i386/ilp32/x86-64-localpic.d: Likewise.
include/
* elf/x86-64.h (elf_x86_64_reloc_type): Add
R_X86_64_CODE_4_GOTPCRELX.
ld/
* testsuite/ld-x86-64/apx-load1.s: New file.
* testsuite/ld-x86-64/apx-load1a.d: Likewise.
* testsuite/ld-x86-64/apx-load1b.d: Likewise.
* testsuite/ld-x86-64/apx-load1c.d: Likewise.
* testsuite/ld-x86-64/apx-load1d.d: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Run apx-load1a, apx-load1b,
apx-load1c and apx-load1d.
---
bfd/bfd-in2.h | 1 +
bfd/elf64-x86-64.c | 73 ++++++++++++++-----
bfd/libbfd.h | 1 +
bfd/reloc.c | 2 +
gas/config/tc-i386.c | 18 ++++-
gas/config/tc-i386.h | 6 +-
.../gas/i386/ilp32/x86-64-localpic.d | 4 +-
gas/testsuite/gas/i386/x86-64-gotpcrel.d | 12 +++
gas/testsuite/gas/i386/x86-64-gotpcrel.s | 19 +++++
gas/testsuite/gas/i386/x86-64-localpic.d | 4 +-
gas/testsuite/gas/i386/x86-64-localpic.s | 2 +
gas/write.h | 3 +-
include/elf/x86-64.h | 6 +-
ld/testsuite/ld-x86-64/apx-load1.s | 51 +++++++++++++
ld/testsuite/ld-x86-64/apx-load1a.d | 54 ++++++++++++++
ld/testsuite/ld-x86-64/apx-load1b.d | 55 ++++++++++++++
ld/testsuite/ld-x86-64/apx-load1c.d | 47 ++++++++++++
ld/testsuite/ld-x86-64/apx-load1d.d | 47 ++++++++++++
ld/testsuite/ld-x86-64/x86-64.exp | 4 +
19 files changed, 382 insertions(+), 27 deletions(-)
create mode 100644 ld/testsuite/ld-x86-64/apx-load1.s
create mode 100644 ld/testsuite/ld-x86-64/apx-load1a.d
create mode 100644 ld/testsuite/ld-x86-64/apx-load1b.d
create mode 100644 ld/testsuite/ld-x86-64/apx-load1c.d
create mode 100644 ld/testsuite/ld-x86-64/apx-load1d.d
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 782845926ea..96709da9170 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -3891,6 +3891,7 @@ enum bfd_reloc_code_real
BFD_RELOC_X86_64_PLT32_BND,
BFD_RELOC_X86_64_GOTPCRELX,
BFD_RELOC_X86_64_REX_GOTPCRELX,
+ BFD_RELOC_X86_64_CODE_4_GOTPCRELX,
/* ns32k relocations. */
BFD_RELOC_NS32K_IMM_8,
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 3b7a8aeee11..a2d1b6f14b7 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -170,12 +170,15 @@ static reloc_howto_type x86_64_elf_howto_table[] =
HOWTO(R_X86_64_REX_GOTPCRELX, 0, 4, 32, true, 0, complain_overflow_signed,
bfd_elf_generic_reloc, "R_X86_64_REX_GOTPCRELX", false, 0, 0xffffffff,
true),
+ HOWTO(R_X86_64_CODE_4_GOTPCRELX, 0, 4, 32, true, 0, complain_overflow_signed,
+ bfd_elf_generic_reloc, "R_X86_64_CODE_4_GOTPCRELX", 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_REX_GOTPCRELX + 1)
+#define R_X86_64_standard (R_X86_64_CODE_4_GOTPCRELX + 1)
#define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard)
/* GNU extension to record C++ vtable hierarchy. */
@@ -244,6 +247,7 @@ static const struct elf_reloc_map x86_64_reloc_map[] =
{ BFD_RELOC_X86_64_PLT32_BND, R_X86_64_PLT32_BND, },
{ BFD_RELOC_X86_64_GOTPCRELX, R_X86_64_GOTPCRELX, },
{ BFD_RELOC_X86_64_REX_GOTPCRELX, R_X86_64_REX_GOTPCRELX, },
+ { BFD_RELOC_X86_64_CODE_4_GOTPCRELX, R_X86_64_CODE_4_GOTPCRELX, },
{ BFD_RELOC_VTABLE_INHERIT, R_X86_64_GNU_VTINHERIT, },
{ BFD_RELOC_VTABLE_ENTRY, R_X86_64_GNU_VTENTRY, },
};
@@ -1586,7 +1590,8 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
bfd_vma roff = irel->r_offset;
bfd_vma abs_relocation;
- if (roff < (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2))
+ if (roff < (r_type == R_X86_64_CODE_4_GOTPCRELX
+ ? 4 : (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2)))
return true;
raddend = irel->r_addend;
@@ -1597,8 +1602,18 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
htab = elf_x86_hash_table (link_info, X86_64_ELF_DATA);
is_pic = bfd_link_pic (link_info);
- relocx = (r_type == R_X86_64_GOTPCRELX
- || r_type == R_X86_64_REX_GOTPCRELX);
+ if (r_type == R_X86_64_CODE_4_GOTPCRELX)
+ {
+ /* Skip if this isn't a REX2 instruction. */
+ opcode = bfd_get_8 (abfd, contents + roff - 4);
+ if (opcode != 0xd5)
+ return true;
+
+ relocx = true;
+ }
+ else
+ relocx = (r_type == R_X86_64_GOTPCRELX
+ || r_type == R_X86_64_REX_GOTPCRELX);
/* TRUE if --no-relax is used. */
no_overflow = link_info->disable_target_specific_optimizations > 1;
@@ -1610,9 +1625,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
/* Convert mov to lea since it has been done for a while. */
if (opcode != 0x8b)
{
- /* Only convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX
- for call, jmp or one of adc, add, and, cmp, or, sbb, sub,
- test, xor instructions. */
+ /* Only convert R_X86_64_GOTPCRELX, R_X86_64_REX_GOTPCRELX
+ and R_X86_64_CODE_4_GOTPCRELX for call, jmp or one of adc,
+ add, and, cmp, or, sbb, sub, test, xor instructions. */
if (!relocx)
return true;
}
@@ -1797,13 +1812,22 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
}
else
{
- unsigned int rex;
+ unsigned int rex = 0;
unsigned int rex_mask = REX_R;
+ unsigned int rex2 = 0;
+ unsigned int rex2_mask = REX_R | REX_R << 4;
+ bool rex_w = false;
- if (r_type == R_X86_64_REX_GOTPCRELX)
- rex = bfd_get_8 (abfd, contents + roff - 3);
- else
- rex = 0;
+ if (r_type == R_X86_64_CODE_4_GOTPCRELX)
+ {
+ rex2 = bfd_get_8 (abfd, contents + roff - 3);
+ rex_w = (rex2 & REX_W) != 0;
+ }
+ else if (r_type == R_X86_64_REX_GOTPCRELX)
+ {
+ rex = bfd_get_8 (abfd, contents + roff - 3);
+ rex_w = (rex & REX_W) != 0;
+ }
if (opcode == 0x8b)
{
@@ -1824,8 +1848,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
opcode = 0xc7;
modrm = bfd_get_8 (abfd, contents + roff - 1);
modrm = 0xc0 | (modrm & 0x38) >> 3;
- if ((rex & REX_W) != 0
- && ABI_64_P (link_info->output_bfd))
+ if (rex_w && ABI_64_P (link_info->output_bfd))
{
/* Keep the REX_W bit in REX byte for LP64. */
r_type = R_X86_64_32S;
@@ -1837,8 +1860,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
use R_X86_64_32 and clear the W bit to avoid
sign-extend imm32 to imm64. */
r_type = R_X86_64_32;
- /* Clear the W bit in REX byte. */
+ /* Clear the W bit in REX byte and REX2 payload. */
rex_mask |= REX_W;
+ rex2_mask |= REX_W;
goto rewrite_modrm_rex;
}
}
@@ -1867,7 +1891,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
/* Use R_X86_64_32 with 32-bit operand to avoid relocation
overflow when sign-extending imm32 to imm64. */
- r_type = (rex & REX_W) != 0 ? R_X86_64_32S : R_X86_64_32;
+ r_type = rex_w ? R_X86_64_32S : R_X86_64_32;
rewrite_modrm_rex:
if (abs_relocation)
@@ -1893,6 +1917,13 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
rex = (rex & ~rex_mask) | (rex & REX_R) >> 2;
bfd_put_8 (abfd, rex, contents + roff - 3);
}
+ else if (rex2)
+ {
+ /* Move the R bits to the B bits in REX2 payload byte. */
+ rex2 = ((rex2 & ~rex2_mask)
+ | (rex2 & (REX_R | REX_R << 4)) >> 2);
+ bfd_put_8 (abfd, rex2, contents + roff - 3);
+ }
/* No addend for R_X86_64_32/R_X86_64_32S relocations. */
irel->r_addend = 0;
@@ -2058,7 +2089,8 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
converted_reloc = false;
if ((r_type == R_X86_64_GOTPCREL
|| r_type == R_X86_64_GOTPCRELX
- || r_type == R_X86_64_REX_GOTPCRELX)
+ || r_type == R_X86_64_REX_GOTPCRELX
+ || r_type == R_X86_64_CODE_4_GOTPCRELX)
&& (h == NULL || h->type != STT_GNU_IFUNC))
{
Elf_Internal_Rela *irel = (Elf_Internal_Rela *) rel;
@@ -2108,6 +2140,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
+ case R_X86_64_CODE_4_GOTPCRELX:
case R_X86_64_TLSGD:
case R_X86_64_GOT64:
case R_X86_64_GOTPCREL64:
@@ -2710,6 +2743,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
+ case R_X86_64_CODE_4_GOTPCRELX:
case R_X86_64_GOTPCREL64:
base_got = htab->elf.sgot;
off = h->got.offset;
@@ -2935,6 +2969,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
+ case R_X86_64_CODE_4_GOTPCRELX:
case R_X86_64_GOTPCREL64:
/* Use global offset table entry as symbol value. */
case R_X86_64_GOTPLT64:
@@ -3025,7 +3060,8 @@ elf_x86_64_relocate_section (bfd *output_bfd,
&& !(sym->st_shndx == SHN_ABS
&& (r_type == R_X86_64_GOTPCREL
|| r_type == R_X86_64_GOTPCRELX
- || r_type == R_X86_64_REX_GOTPCRELX)))
+ || r_type == R_X86_64_REX_GOTPCRELX
+ || r_type == R_X86_64_CODE_4_GOTPCRELX)))
relative_reloc = true;
}
}
@@ -3063,6 +3099,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
if (r_type != R_X86_64_GOTPCREL
&& r_type != R_X86_64_GOTPCRELX
&& r_type != R_X86_64_REX_GOTPCRELX
+ && r_type != R_X86_64_CODE_4_GOTPCRELX
&& r_type != R_X86_64_GOTPCREL64)
relocation -= htab->elf.sgotplt->output_section->vma
- htab->elf.sgotplt->output_offset;
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 8dab44110a6..8873fafdde9 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1460,6 +1460,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_X86_64_PLT32_BND",
"BFD_RELOC_X86_64_GOTPCRELX",
"BFD_RELOC_X86_64_REX_GOTPCRELX",
+ "BFD_RELOC_X86_64_CODE_4_GOTPCRELX",
"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 6fd0f1fb547..56d852d084f 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2475,6 +2475,8 @@ ENUMX
BFD_RELOC_X86_64_GOTPCRELX
ENUMX
BFD_RELOC_X86_64_REX_GOTPCRELX
+ENUMX
+ BFD_RELOC_X86_64_CODE_4_GOTPCRELX
ENUMDOC
x86-64/elf relocations.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index ee948a61b18..8d76446010b 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -3595,6 +3595,7 @@ tc_i386_fix_adjustable (fixS *fixP)
|| fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL
|| fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCRELX
|| fixP->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX
+ || fixP->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTPCRELX
|| fixP->fx_r_type == BFD_RELOC_X86_64_TLSGD
|| fixP->fx_r_type == BFD_RELOC_X86_64_TLSLD
|| fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32
@@ -10856,6 +10857,10 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
&& !i.prefix[ADDR_PREFIX])
fixP->fx_signed = 1;
+ /* Set fx_tcbit3 for REX2 prefix. */
+ if (is_apx_rex2_encoding ())
+ fixP->fx_tcbit3 = 1;
+
/* Check for "call/jmp *mem", "mov mem, %reg",
"test %reg, mem" and "binop mem, %reg" where binop
is one of adc, add, and, cmp, or, sbb, sub, xor
@@ -15936,9 +15941,14 @@ i386_validate_fix (fixS *fixp)
abort ();
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
if (fixp->fx_tcbit2)
- fixp->fx_r_type = (fixp->fx_tcbit
- ? BFD_RELOC_X86_64_REX_GOTPCRELX
- : BFD_RELOC_X86_64_GOTPCRELX);
+ {
+ 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);
+ }
else
#endif
fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL;
@@ -16042,6 +16052,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
case BFD_RELOC_X86_64_GOTPCREL:
case BFD_RELOC_X86_64_GOTPCRELX:
case BFD_RELOC_X86_64_REX_GOTPCRELX:
+ case BFD_RELOC_X86_64_CODE_4_GOTPCRELX:
case BFD_RELOC_386_PLT32:
case BFD_RELOC_386_GOT32:
case BFD_RELOC_386_GOT32X:
@@ -16200,6 +16211,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
case BFD_RELOC_X86_64_GOTPCREL:
case BFD_RELOC_X86_64_GOTPCRELX:
case BFD_RELOC_X86_64_REX_GOTPCRELX:
+ case BFD_RELOC_X86_64_CODE_4_GOTPCRELX:
case BFD_RELOC_X86_64_TLSGD:
case BFD_RELOC_X86_64_TLSLD:
case BFD_RELOC_X86_64_GOTTPOFF:
diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h
index 3cb0c784819..44227a8376c 100644
--- a/gas/config/tc-i386.h
+++ b/gas/config/tc-i386.h
@@ -171,7 +171,8 @@ extern int tc_i386_fix_adjustable (struct fix *);
|| (FIX)->fx_r_type == BFD_RELOC_386_GOTPC \
|| (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCREL \
|| (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCRELX \
- || (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX)
+ || (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX \
+ || (FIX)->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTPCRELX)
#define TC_FORCE_RELOCATION_ABS(FIX) \
(TC_FORCE_RELOCATION (FIX) \
@@ -179,7 +180,8 @@ extern int tc_i386_fix_adjustable (struct fix *);
|| (FIX)->fx_r_type == BFD_RELOC_386_GOT32X \
|| (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCREL \
|| (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCRELX \
- || (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX)
+ || (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX \
+ || (FIX)->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTPCRELX)
extern int i386_parse_name (char *, expressionS *, char *);
#define md_parse_name(s, e, m, c) i386_parse_name (s, e, c)
diff --git a/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d b/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d
index d0cc4e8efc9..57d4843a5b5 100644
--- a/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d
+++ b/gas/testsuite/gas/i386/ilp32/x86-64-localpic.d
@@ -3,10 +3,12 @@
#readelf: -rsW
#name: x86-64 (ILP32) local PIC
-Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 2 entries:
+Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 4 entries:
+Offset +Info +Type +Sym. Value +Symbol's Name \+ Addend
[0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +foo - 4
[0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +bar - 4
+[0-9a-f]+ +[0-9a-f]+ R_X86_64_CODE_4_GOTPCRELX +[0-9a-f]+ +foo - 4
+[0-9a-f]+ +[0-9a-f]+ R_X86_64_CODE_4_GOTPCRELX +[0-9a-f]+ +bar - 4
#...
+[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo
+[0-9]+: +fffffff0 +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +ABS +bar
diff --git a/gas/testsuite/gas/i386/x86-64-gotpcrel.d b/gas/testsuite/gas/i386/x86-64-gotpcrel.d
index 57792216e9a..12fadfbca4e 100644
--- a/gas/testsuite/gas/i386/x86-64-gotpcrel.d
+++ b/gas/testsuite/gas/i386/x86-64-gotpcrel.d
@@ -24,4 +24,16 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: ff 90 00 00 00 00 call \*0x0\(%rax\) 5a: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: ff 25 00 00 00 00 jmp \*0x0\(%rip\) # 64 <_start\+0x64> 60: R_X86_64_GOTPCRELX foo-0x4
[ ]*[a-f0-9]+: ff a1 00 00 00 00 jmp \*0x0\(%rcx\) 66: R_X86_64_GOTPCREL foo
+[ ]*[a-f0-9]+: d5 18 c7 c0 00 00 00 00 mov \$0x0,%r16 6e: R_X86_64_GOTPCREL foo
+[ ]*[a-f0-9]+: d5 48 8b 24 25 00 00 00 00 mov 0x0,%r20 77: R_X86_64_GOTPCREL foo
+[ ]*[a-f0-9]+: d5 48 8b 35 00 00 00 00 mov 0x0\(%rip\),%r22 # 83 <_start\+0x83> 7f: R_X86_64_CODE_4_GOTPCRELX foo-0x4
+[ ]*[a-f0-9]+: d5 59 8b b4 24 00 00 00 00 mov 0x0\(%r28\),%r22 88: R_X86_64_GOTPCREL foo
+[ ]*[a-f0-9]+: d5 10 ff 90 00 00 00 00 call \*0x0\(%r16\) 90: R_X86_64_GOTPCREL foo
+[ ]*[a-f0-9]+: d5 11 ff a4 24 00 00 00 00 jmp \*0x0\(%r28\) 99: R_X86_64_GOTPCREL foo
+[ ]*[a-f0-9]+: d5 18 c7 c0 00 00 00 00 mov \$0x0,%r16 a1: R_X86_64_GOTPCREL foo
+[ ]*[a-f0-9]+: d5 48 8b 24 25 00 00 00 00 mov 0x0,%r20 aa: R_X86_64_GOTPCREL foo
+[ ]*[a-f0-9]+: d5 48 8b 35 00 00 00 00 mov 0x0\(%rip\),%r22 # b6 <_start\+0xb6> b2: R_X86_64_CODE_4_GOTPCRELX foo-0x4
+[ ]*[a-f0-9]+: d5 59 8b b4 24 00 00 00 00 mov 0x0\(%r28\),%r22 bb: R_X86_64_GOTPCREL foo
+[ ]*[a-f0-9]+: d5 10 ff 90 00 00 00 00 call \*0x0\(%r16\) c3: R_X86_64_GOTPCREL foo
+[ ]*[a-f0-9]+: d5 11 ff a4 24 00 00 00 00 jmp \*0x0\(%r28\) cc: R_X86_64_GOTPCREL foo
#pass
diff --git a/gas/testsuite/gas/i386/x86-64-gotpcrel.s b/gas/testsuite/gas/i386/x86-64-gotpcrel.s
index 981b14ff4df..91b1ca204c8 100644
--- a/gas/testsuite/gas/i386/x86-64-gotpcrel.s
+++ b/gas/testsuite/gas/i386/x86-64-gotpcrel.s
@@ -21,3 +21,22 @@ _start:
call QWORD PTR [rax + foo@GOTPCREL]
jmp QWORD PTR [rip + foo@GOTPCREL]
jmp QWORD PTR [rcx + foo@GOTPCREL]
+
+ .att_syntax prefix
+ movq $foo@GOTPCREL, %r16
+ movq foo@GOTPCREL, %r20
+ movq foo@GOTPCREL(%rip), %r22
+ movq foo@GOTPCREL(%r28), %r22
+
+ call *foo@GOTPCREL(%r16)
+ jmp *foo@GOTPCREL(%r28)
+
+ .intel_syntax noprefix
+
+ mov r16, offset foo@gotpcrel
+ mov r20, QWORD PTR [foo@GOTPCREL]
+ mov r22, QWORD PTR [rip + foo@GOTPCREL]
+ mov r22, QWORD PTR [r28 + foo@GOTPCREL]
+
+ call QWORD PTR [r16 + foo@GOTPCREL]
+ jmp QWORD PTR [r28 + foo@GOTPCREL]
diff --git a/gas/testsuite/gas/i386/x86-64-localpic.d b/gas/testsuite/gas/i386/x86-64-localpic.d
index 62030d410ad..11eb57b30b7 100644
--- a/gas/testsuite/gas/i386/x86-64-localpic.d
+++ b/gas/testsuite/gas/i386/x86-64-localpic.d
@@ -2,10 +2,12 @@
#readelf: -rsW
#name: x86-64 local PIC
-Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 2 entries:
+Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 4 entries:
+Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
[0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +foo - 4
[0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +bar - 4
+[0-9a-f]+ +[0-9a-f]+ R_X86_64_CODE_4_GOTPCRELX +[0-9a-f]+ +foo - 4
+[0-9a-f]+ +[0-9a-f]+ R_X86_64_CODE_4_GOTPCRELX +[0-9a-f]+ +bar - 4
#...
+[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo
+[0-9]+: +0+fffffff0 +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +ABS +bar
diff --git a/gas/testsuite/gas/i386/x86-64-localpic.s b/gas/testsuite/gas/i386/x86-64-localpic.s
index beda94dc2f3..183dfb6293b 100644
--- a/gas/testsuite/gas/i386/x86-64-localpic.s
+++ b/gas/testsuite/gas/i386/x86-64-localpic.s
@@ -3,4 +3,6 @@ foo:
.quad 0
movq foo@GOTPCREL(%rip), %rax
movq bar@GOTPCREL(%rip), %rax
+ movq foo@GOTPCREL(%rip), %r26
+ movq bar@GOTPCREL(%rip), %r26
bar = 0xfffffff0
diff --git a/gas/write.h b/gas/write.h
index eb30a76bf85..fd0ab553b23 100644
--- a/gas/write.h
+++ b/gas/write.h
@@ -81,9 +81,10 @@ struct fix
/* Some bits for the CPU specific code. */
unsigned fx_tcbit : 1;
unsigned fx_tcbit2 : 1;
+ unsigned fx_tcbit3 : 1;
/* Spare bits. */
- unsigned fx_unused : 2;
+ unsigned fx_unused : 1;
bfd_reloc_code_real_type fx_r_type;
diff --git a/include/elf/x86-64.h b/include/elf/x86-64.h
index 1b87beef41a..30d1722cb73 100644
--- a/include/elf/x86-64.h
+++ b/include/elf/x86-64.h
@@ -77,11 +77,15 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_type)
RELOC_NUMBER (R_X86_64_PLT32_BND, 40) /* 32 bit PLT address with
BND prefix */
/* Load from 32 bit signed pc relative offset to GOT entry without
- REX prefix, relaxable. */
+ REX nor REX2 prefixes, relaxable. */
RELOC_NUMBER (R_X86_64_GOTPCRELX, 41)
/* Load from 32 bit signed pc relative offset to GOT entry with
REX prefix, relaxable. */
RELOC_NUMBER (R_X86_64_REX_GOTPCRELX, 42)
+ /* Load from 32 bit signed pc relative offset to GOT entry if the
+ instruction starts at 4 bytes before the relocation offset,
+ relaxable. */
+ RELOC_NUMBER (R_X86_64_CODE_4_GOTPCRELX, 43)
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)
diff --git a/ld/testsuite/ld-x86-64/apx-load1.s b/ld/testsuite/ld-x86-64/apx-load1.s
new file mode 100644
index 00000000000..f5eac57d82e
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/apx-load1.s
@@ -0,0 +1,51 @@
+ .data
+ .type bar, @object
+bar:
+ .byte 1
+ .size bar, .-bar
+ .globl foo
+ .type foo, @object
+foo:
+ .byte 1
+ .size foo, .-foo
+ .text
+ .globl _start
+ .type _start, @function
+_start:
+ adcl bar@GOTPCREL(%rip), %r16d
+ addl bar@GOTPCREL(%rip), %r17d
+ andl bar@GOTPCREL(%rip), %r18d
+ cmpl bar@GOTPCREL(%rip), %r19d
+ orl bar@GOTPCREL(%rip), %r20d
+ sbbl bar@GOTPCREL(%rip), %r21d
+ subl bar@GOTPCREL(%rip), %r22d
+ xorl bar@GOTPCREL(%rip), %r23d
+ testl %r24d, bar@GOTPCREL(%rip)
+ adcq bar@GOTPCREL(%rip), %r16
+ addq bar@GOTPCREL(%rip), %r17
+ andq bar@GOTPCREL(%rip), %r18
+ cmpq bar@GOTPCREL(%rip), %r19
+ orq bar@GOTPCREL(%rip), %r20
+ sbbq bar@GOTPCREL(%rip), %r21
+ subq bar@GOTPCREL(%rip), %r22
+ xorq bar@GOTPCREL(%rip), %r23
+ testq %r24, bar@GOTPCREL(%rip)
+ adcl foo@GOTPCREL(%rip), %r16d
+ addl foo@GOTPCREL(%rip), %r17d
+ andl foo@GOTPCREL(%rip), %r18d
+ cmpl foo@GOTPCREL(%rip), %r19d
+ orl foo@GOTPCREL(%rip), %r20d
+ sbbl foo@GOTPCREL(%rip), %r21d
+ subl foo@GOTPCREL(%rip), %r22d
+ xorl foo@GOTPCREL(%rip), %r23d
+ testl %r24d, foo@GOTPCREL(%rip)
+ adcq foo@GOTPCREL(%rip), %r16
+ addq foo@GOTPCREL(%rip), %r17
+ andq foo@GOTPCREL(%rip), %r18
+ cmpq foo@GOTPCREL(%rip), %r19
+ orq foo@GOTPCREL(%rip), %r20
+ sbbq foo@GOTPCREL(%rip), %r21
+ subq foo@GOTPCREL(%rip), %r22
+ xorq foo@GOTPCREL(%rip), %r23
+ testq %r24, foo@GOTPCREL(%rip)
+ .size _start, .-_start
diff --git a/ld/testsuite/ld-x86-64/apx-load1a.d b/ld/testsuite/ld-x86-64/apx-load1a.d
new file mode 100644
index 00000000000..162a2343ebe
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/apx-load1a.d
@@ -0,0 +1,54 @@
+#source: apx-load1.s
+#as: --64 -mrelax-relocations=yes
+#ld: -melf_x86_64 -z max-page-size=0x200000 -z noseparate-code
+#objdump: -dw --sym
+
+.*: +file format .*
+
+SYMBOL TABLE:
+#...
+0+6001d0 l O .data 0+1 bar
+#...
+0+6001d1 g O .data 0+1 foo
+#...
+
+Disassembly of section .text:
+
+0+4000b0 <_start>:
+ +[a-f0-9]+: d5 10 81 d0 d0 01 60 00 adc \$0x6001d0,%r16d
+ +[a-f0-9]+: d5 10 81 c1 d0 01 60 00 add \$0x6001d0,%r17d
+ +[a-f0-9]+: d5 10 81 e2 d0 01 60 00 and \$0x6001d0,%r18d
+ +[a-f0-9]+: d5 10 81 fb d0 01 60 00 cmp \$0x6001d0,%r19d
+ +[a-f0-9]+: d5 10 81 cc d0 01 60 00 or \$0x6001d0,%r20d
+ +[a-f0-9]+: d5 10 81 dd d0 01 60 00 sbb \$0x6001d0,%r21d
+ +[a-f0-9]+: d5 10 81 ee d0 01 60 00 sub \$0x6001d0,%r22d
+ +[a-f0-9]+: d5 10 81 f7 d0 01 60 00 xor \$0x6001d0,%r23d
+ +[a-f0-9]+: d5 11 f7 c0 d0 01 60 00 test \$0x6001d0,%r24d
+ +[a-f0-9]+: d5 18 81 d0 d0 01 60 00 adc \$0x6001d0,%r16
+ +[a-f0-9]+: d5 18 81 c1 d0 01 60 00 add \$0x6001d0,%r17
+ +[a-f0-9]+: d5 18 81 e2 d0 01 60 00 and \$0x6001d0,%r18
+ +[a-f0-9]+: d5 18 81 fb d0 01 60 00 cmp \$0x6001d0,%r19
+ +[a-f0-9]+: d5 18 81 cc d0 01 60 00 or \$0x6001d0,%r20
+ +[a-f0-9]+: d5 18 81 dd d0 01 60 00 sbb \$0x6001d0,%r21
+ +[a-f0-9]+: d5 18 81 ee d0 01 60 00 sub \$0x6001d0,%r22
+ +[a-f0-9]+: d5 18 81 f7 d0 01 60 00 xor \$0x6001d0,%r23
+ +[a-f0-9]+: d5 19 f7 c0 d0 01 60 00 test \$0x6001d0,%r24
+ +[a-f0-9]+: d5 10 81 d0 d1 01 60 00 adc \$0x6001d1,%r16d
+ +[a-f0-9]+: d5 10 81 c1 d1 01 60 00 add \$0x6001d1,%r17d
+ +[a-f0-9]+: d5 10 81 e2 d1 01 60 00 and \$0x6001d1,%r18d
+ +[a-f0-9]+: d5 10 81 fb d1 01 60 00 cmp \$0x6001d1,%r19d
+ +[a-f0-9]+: d5 10 81 cc d1 01 60 00 or \$0x6001d1,%r20d
+ +[a-f0-9]+: d5 10 81 dd d1 01 60 00 sbb \$0x6001d1,%r21d
+ +[a-f0-9]+: d5 10 81 ee d1 01 60 00 sub \$0x6001d1,%r22d
+ +[a-f0-9]+: d5 10 81 f7 d1 01 60 00 xor \$0x6001d1,%r23d
+ +[a-f0-9]+: d5 11 f7 c0 d1 01 60 00 test \$0x6001d1,%r24d
+ +[a-f0-9]+: d5 18 81 d0 d1 01 60 00 adc \$0x6001d1,%r16
+ +[a-f0-9]+: d5 18 81 c1 d1 01 60 00 add \$0x6001d1,%r17
+ +[a-f0-9]+: d5 18 81 e2 d1 01 60 00 and \$0x6001d1,%r18
+ +[a-f0-9]+: d5 18 81 fb d1 01 60 00 cmp \$0x6001d1,%r19
+ +[a-f0-9]+: d5 18 81 cc d1 01 60 00 or \$0x6001d1,%r20
+ +[a-f0-9]+: d5 18 81 dd d1 01 60 00 sbb \$0x6001d1,%r21
+ +[a-f0-9]+: d5 18 81 ee d1 01 60 00 sub \$0x6001d1,%r22
+ +[a-f0-9]+: d5 18 81 f7 d1 01 60 00 xor \$0x6001d1,%r23
+ +[a-f0-9]+: d5 19 f7 c0 d1 01 60 00 test \$0x6001d1,%r24
+#pass
diff --git a/ld/testsuite/ld-x86-64/apx-load1b.d b/ld/testsuite/ld-x86-64/apx-load1b.d
new file mode 100644
index 00000000000..8c8962cad2d
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/apx-load1b.d
@@ -0,0 +1,55 @@
+#source: apx-load1.s
+#as: --x32 -mrelax-relocations=yes
+#ld: -melf32_x86_64 -z max-page-size=0x200000 -z noseparate-code
+#objdump: -dw --sym
+
+.*: +file format .*
+
+SYMBOL TABLE:
+#...
+0+600194 l O .data 0+1 bar
+#...
+0+600195 g O .data 0+1 foo
+#...
+
+
+Disassembly of section .text:
+
+0+400074 <_start>:
+ +[a-f0-9]+: d5 10 81 d0 94 01 60 00 adc \$0x600194,%r16d
+ +[a-f0-9]+: d5 10 81 c1 94 01 60 00 add \$0x600194,%r17d
+ +[a-f0-9]+: d5 10 81 e2 94 01 60 00 and \$0x600194,%r18d
+ +[a-f0-9]+: d5 10 81 fb 94 01 60 00 cmp \$0x600194,%r19d
+ +[a-f0-9]+: d5 10 81 cc 94 01 60 00 or \$0x600194,%r20d
+ +[a-f0-9]+: d5 10 81 dd 94 01 60 00 sbb \$0x600194,%r21d
+ +[a-f0-9]+: d5 10 81 ee 94 01 60 00 sub \$0x600194,%r22d
+ +[a-f0-9]+: d5 10 81 f7 94 01 60 00 xor \$0x600194,%r23d
+ +[a-f0-9]+: d5 11 f7 c0 94 01 60 00 test \$0x600194,%r24d
+ +[a-f0-9]+: d5 18 81 d0 94 01 60 00 adc \$0x600194,%r16
+ +[a-f0-9]+: d5 18 81 c1 94 01 60 00 add \$0x600194,%r17
+ +[a-f0-9]+: d5 18 81 e2 94 01 60 00 and \$0x600194,%r18
+ +[a-f0-9]+: d5 18 81 fb 94 01 60 00 cmp \$0x600194,%r19
+ +[a-f0-9]+: d5 18 81 cc 94 01 60 00 or \$0x600194,%r20
+ +[a-f0-9]+: d5 18 81 dd 94 01 60 00 sbb \$0x600194,%r21
+ +[a-f0-9]+: d5 18 81 ee 94 01 60 00 sub \$0x600194,%r22
+ +[a-f0-9]+: d5 18 81 f7 94 01 60 00 xor \$0x600194,%r23
+ +[a-f0-9]+: d5 19 f7 c0 94 01 60 00 test \$0x600194,%r24
+ +[a-f0-9]+: d5 10 81 d0 95 01 60 00 adc \$0x600195,%r16d
+ +[a-f0-9]+: d5 10 81 c1 95 01 60 00 add \$0x600195,%r17d
+ +[a-f0-9]+: d5 10 81 e2 95 01 60 00 and \$0x600195,%r18d
+ +[a-f0-9]+: d5 10 81 fb 95 01 60 00 cmp \$0x600195,%r19d
+ +[a-f0-9]+: d5 10 81 cc 95 01 60 00 or \$0x600195,%r20d
+ +[a-f0-9]+: d5 10 81 dd 95 01 60 00 sbb \$0x600195,%r21d
+ +[a-f0-9]+: d5 10 81 ee 95 01 60 00 sub \$0x600195,%r22d
+ +[a-f0-9]+: d5 10 81 f7 95 01 60 00 xor \$0x600195,%r23d
+ +[a-f0-9]+: d5 11 f7 c0 95 01 60 00 test \$0x600195,%r24d
+ +[a-f0-9]+: d5 18 81 d0 95 01 60 00 adc \$0x600195,%r16
+ +[a-f0-9]+: d5 18 81 c1 95 01 60 00 add \$0x600195,%r17
+ +[a-f0-9]+: d5 18 81 e2 95 01 60 00 and \$0x600195,%r18
+ +[a-f0-9]+: d5 18 81 fb 95 01 60 00 cmp \$0x600195,%r19
+ +[a-f0-9]+: d5 18 81 cc 95 01 60 00 or \$0x600195,%r20
+ +[a-f0-9]+: d5 18 81 dd 95 01 60 00 sbb \$0x600195,%r21
+ +[a-f0-9]+: d5 18 81 ee 95 01 60 00 sub \$0x600195,%r22
+ +[a-f0-9]+: d5 18 81 f7 95 01 60 00 xor \$0x600195,%r23
+ +[a-f0-9]+: d5 19 f7 c0 95 01 60 00 test \$0x600195,%r24
+#pass
diff --git a/ld/testsuite/ld-x86-64/apx-load1c.d b/ld/testsuite/ld-x86-64/apx-load1c.d
new file mode 100644
index 00000000000..fdfe00cc61c
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/apx-load1c.d
@@ -0,0 +1,47 @@
+#source: apx-load1.s
+#as: --64
+#ld: -shared -melf_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
+#objdump: -dw
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+188 <_start>:
+ +[a-f0-9]+: d5 40 13 05 f8 01 20 00 adc 0x2001f8\(%rip\),%r16d # 200388 <.*>
+ +[a-f0-9]+: d5 40 03 0d f0 01 20 00 add 0x2001f0\(%rip\),%r17d # 200388 <.*>
+ +[a-f0-9]+: d5 40 23 15 e8 01 20 00 and 0x2001e8\(%rip\),%r18d # 200388 <.*>
+ +[a-f0-9]+: d5 40 3b 1d e0 01 20 00 cmp 0x2001e0\(%rip\),%r19d # 200388 <.*>
+ +[a-f0-9]+: d5 40 0b 25 d8 01 20 00 or 0x2001d8\(%rip\),%r20d # 200388 <.*>
+ +[a-f0-9]+: d5 40 1b 2d d0 01 20 00 sbb 0x2001d0\(%rip\),%r21d # 200388 <.*>
+ +[a-f0-9]+: d5 40 2b 35 c8 01 20 00 sub 0x2001c8\(%rip\),%r22d # 200388 <.*>
+ +[a-f0-9]+: d5 40 33 3d c0 01 20 00 xor 0x2001c0\(%rip\),%r23d # 200388 <.*>
+ +[a-f0-9]+: d5 44 85 05 b8 01 20 00 test %r24d,0x2001b8\(%rip\) # 200388 <.*>
+ +[a-f0-9]+: d5 48 13 05 b0 01 20 00 adc 0x2001b0\(%rip\),%r16 # 200388 <.*>
+ +[a-f0-9]+: d5 48 03 0d a8 01 20 00 add 0x2001a8\(%rip\),%r17 # 200388 <.*>
+ +[a-f0-9]+: d5 48 23 15 a0 01 20 00 and 0x2001a0\(%rip\),%r18 # 200388 <.*>
+ +[a-f0-9]+: d5 48 3b 1d 98 01 20 00 cmp 0x200198\(%rip\),%r19 # 200388 <.*>
+ +[a-f0-9]+: d5 48 0b 25 90 01 20 00 or 0x200190\(%rip\),%r20 # 200388 <.*>
+ +[a-f0-9]+: d5 48 1b 2d 88 01 20 00 sbb 0x200188\(%rip\),%r21 # 200388 <.*>
+ +[a-f0-9]+: d5 48 2b 35 80 01 20 00 sub 0x200180\(%rip\),%r22 # 200388 <.*>
+ +[a-f0-9]+: d5 48 33 3d 78 01 20 00 xor 0x200178\(%rip\),%r23 # 200388 <.*>
+ +[a-f0-9]+: d5 4c 85 05 70 01 20 00 test %r24,0x200170\(%rip\) # 200388 <.*>
+ +[a-f0-9]+: d5 40 13 05 70 01 20 00 adc 0x200170\(%rip\),%r16d # 200390 <.*>
+ +[a-f0-9]+: d5 40 03 0d 68 01 20 00 add 0x200168\(%rip\),%r17d # 200390 <.*>
+ +[a-f0-9]+: d5 40 23 15 60 01 20 00 and 0x200160\(%rip\),%r18d # 200390 <.*>
+ +[a-f0-9]+: d5 40 3b 1d 58 01 20 00 cmp 0x200158\(%rip\),%r19d # 200390 <.*>
+ +[a-f0-9]+: d5 40 0b 25 50 01 20 00 or 0x200150\(%rip\),%r20d # 200390 <.*>
+ +[a-f0-9]+: d5 40 1b 2d 48 01 20 00 sbb 0x200148\(%rip\),%r21d # 200390 <.*>
+ +[a-f0-9]+: d5 40 2b 35 40 01 20 00 sub 0x200140\(%rip\),%r22d # 200390 <.*>
+ +[a-f0-9]+: d5 40 33 3d 38 01 20 00 xor 0x200138\(%rip\),%r23d # 200390 <.*>
+ +[a-f0-9]+: d5 44 85 05 30 01 20 00 test %r24d,0x200130\(%rip\) # 200390 <.*>
+ +[a-f0-9]+: d5 48 13 05 28 01 20 00 adc 0x200128\(%rip\),%r16 # 200390 <.*>
+ +[a-f0-9]+: d5 48 03 0d 20 01 20 00 add 0x200120\(%rip\),%r17 # 200390 <.*>
+ +[a-f0-9]+: d5 48 23 15 18 01 20 00 and 0x200118\(%rip\),%r18 # 200390 <.*>
+ +[a-f0-9]+: d5 48 3b 1d 10 01 20 00 cmp 0x200110\(%rip\),%r19 # 200390 <.*>
+ +[a-f0-9]+: d5 48 0b 25 08 01 20 00 or 0x200108\(%rip\),%r20 # 200390 <.*>
+ +[a-f0-9]+: d5 48 1b 2d 00 01 20 00 sbb 0x200100\(%rip\),%r21 # 200390 <.*>
+ +[a-f0-9]+: d5 48 2b 35 f8 00 20 00 sub 0x2000f8\(%rip\),%r22 # 200390 <.*>
+ +[a-f0-9]+: d5 48 33 3d f0 00 20 00 xor 0x2000f0\(%rip\),%r23 # 200390 <.*>
+ +[a-f0-9]+: d5 4c 85 05 e8 00 20 00 test %r24,0x2000e8\(%rip\) # 200390 <.*>
+#pass
diff --git a/ld/testsuite/ld-x86-64/apx-load1d.d b/ld/testsuite/ld-x86-64/apx-load1d.d
new file mode 100644
index 00000000000..4da967822ea
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/apx-load1d.d
@@ -0,0 +1,47 @@
+#source: apx-load1.s
+#as: --x32
+#ld: -shared -melf32_x86_64 --hash-style=sysv -z max-page-size=0x200000 -z noseparate-code $NO_DT_RELR_LDFLAGS
+#objdump: -dw
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+100 <_start>:
+ +[a-f0-9]+: d5 40 13 05 88 01 20 00 adc 0x200188\(%rip\),%r16d # 200290 <.*>
+ +[a-f0-9]+: d5 40 03 0d 80 01 20 00 add 0x200180\(%rip\),%r17d # 200290 <.*>
+ +[a-f0-9]+: d5 40 23 15 78 01 20 00 and 0x200178\(%rip\),%r18d # 200290 <.*>
+ +[a-f0-9]+: d5 40 3b 1d 70 01 20 00 cmp 0x200170\(%rip\),%r19d # 200290 <.*>
+ +[a-f0-9]+: d5 40 0b 25 68 01 20 00 or 0x200168\(%rip\),%r20d # 200290 <.*>
+ +[a-f0-9]+: d5 40 1b 2d 60 01 20 00 sbb 0x200160\(%rip\),%r21d # 200290 <.*>
+ +[a-f0-9]+: d5 40 2b 35 58 01 20 00 sub 0x200158\(%rip\),%r22d # 200290 <.*>
+ +[a-f0-9]+: d5 40 33 3d 50 01 20 00 xor 0x200150\(%rip\),%r23d # 200290 <.*>
+ +[a-f0-9]+: d5 44 85 05 48 01 20 00 test %r24d,0x200148\(%rip\) # 200290 <.*>
+ +[a-f0-9]+: d5 48 13 05 40 01 20 00 adc 0x200140\(%rip\),%r16 # 200290 <.*>
+ +[a-f0-9]+: d5 48 03 0d 38 01 20 00 add 0x200138\(%rip\),%r17 # 200290 <.*>
+ +[a-f0-9]+: d5 48 23 15 30 01 20 00 and 0x200130\(%rip\),%r18 # 200290 <.*>
+ +[a-f0-9]+: d5 48 3b 1d 28 01 20 00 cmp 0x200128\(%rip\),%r19 # 200290 <.*>
+ +[a-f0-9]+: d5 48 0b 25 20 01 20 00 or 0x200120\(%rip\),%r20 # 200290 <.*>
+ +[a-f0-9]+: d5 48 1b 2d 18 01 20 00 sbb 0x200118\(%rip\),%r21 # 200290 <.*>
+ +[a-f0-9]+: d5 48 2b 35 10 01 20 00 sub 0x200110\(%rip\),%r22 # 200290 <.*>
+ +[a-f0-9]+: d5 48 33 3d 08 01 20 00 xor 0x200108\(%rip\),%r23 # 200290 <.*>
+ +[a-f0-9]+: d5 4c 85 05 00 01 20 00 test %r24,0x200100\(%rip\) # 200290 <.*>
+ +[a-f0-9]+: d5 40 13 05 00 01 20 00 adc 0x200100\(%rip\),%r16d # 200298 <.*>
+ +[a-f0-9]+: d5 40 03 0d f8 00 20 00 add 0x2000f8\(%rip\),%r17d # 200298 <.*>
+ +[a-f0-9]+: d5 40 23 15 f0 00 20 00 and 0x2000f0\(%rip\),%r18d # 200298 <.*>
+ +[a-f0-9]+: d5 40 3b 1d e8 00 20 00 cmp 0x2000e8\(%rip\),%r19d # 200298 <.*>
+ +[a-f0-9]+: d5 40 0b 25 e0 00 20 00 or 0x2000e0\(%rip\),%r20d # 200298 <.*>
+ +[a-f0-9]+: d5 40 1b 2d d8 00 20 00 sbb 0x2000d8\(%rip\),%r21d # 200298 <.*>
+ +[a-f0-9]+: d5 40 2b 35 d0 00 20 00 sub 0x2000d0\(%rip\),%r22d # 200298 <.*>
+ +[a-f0-9]+: d5 40 33 3d c8 00 20 00 xor 0x2000c8\(%rip\),%r23d # 200298 <.*>
+ +[a-f0-9]+: d5 44 85 05 c0 00 20 00 test %r24d,0x2000c0\(%rip\) # 200298 <.*>
+ +[a-f0-9]+: d5 48 13 05 b8 00 20 00 adc 0x2000b8\(%rip\),%r16 # 200298 <.*>
+ +[a-f0-9]+: d5 48 03 0d b0 00 20 00 add 0x2000b0\(%rip\),%r17 # 200298 <.*>
+ +[a-f0-9]+: d5 48 23 15 a8 00 20 00 and 0x2000a8\(%rip\),%r18 # 200298 <.*>
+ +[a-f0-9]+: d5 48 3b 1d a0 00 20 00 cmp 0x2000a0\(%rip\),%r19 # 200298 <.*>
+ +[a-f0-9]+: d5 48 0b 25 98 00 20 00 or 0x200098\(%rip\),%r20 # 200298 <.*>
+ +[a-f0-9]+: d5 48 1b 2d 90 00 20 00 sbb 0x200090\(%rip\),%r21 # 200298 <.*>
+ +[a-f0-9]+: d5 48 2b 35 88 00 20 00 sub 0x200088\(%rip\),%r22 # 200298 <.*>
+ +[a-f0-9]+: d5 48 33 3d 80 00 20 00 xor 0x200080\(%rip\),%r23 # 200298 <.*>
+ +[a-f0-9]+: d5 4c 85 05 78 00 20 00 test %r24,0x200078\(%rip\) # 200298 <.*>
+#pass
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 95a2986265b..d5c5219222c 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -605,6 +605,10 @@ run_dump_test "load1a"
run_dump_test "load1b"
run_dump_test "load1c"
run_dump_test "load1d"
+run_dump_test "apx-load1a"
+run_dump_test "apx-load1b"
+run_dump_test "apx-load1c"
+run_dump_test "apx-load1d"
run_dump_test "load2"
run_dump_test "call1a"
run_dump_test "call1b"
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/4] gold: Handle R_X86_64_CODE_4_GOTPCRELX
2023-12-28 14:58 [PATCH 0/4] Support APX relocations H.J. Lu
2023-12-28 14:58 ` [PATCH 1/4] x86-64: Add R_X86_64_CODE_4_GOTPCRELX H.J. Lu
@ 2023-12-28 14:58 ` H.J. Lu
2023-12-28 14:58 ` [PATCH 3/4] x86-64: Add R_X86_64_CODE_4_GOTTPOFF/R_X86_64_CODE_4_GOTPC32_TLSDESC H.J. Lu
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: H.J. Lu @ 2023-12-28 14:58 UTC (permalink / raw)
To: binutils
Handle R_X86_64_CODE_4_GOTPCRELX and convert
mov name@GOTPCREL(%rip), %r31
to
lea name@GOTPCREL(%rip), %r31
if the instruction is encoded with the REX2 prefix when possible.
elfcpp/
* x86_64.h (R_X86_64_CODE_4_GOTPCRELX): New.
gold/
* x86_64.cc (Target_x86_64::can_convert_mov_to_lea): Handle
R_X86_64_CODE_4_GOTPCRELX.
(Target_x86_64::Scan::get_reference_flags): Likewise.
(Target_x86_64::Scan::local): Likewise.
(Target_x86_64::Scan::possible_function_pointer_reloc): Likewise.
(Target_x86_64::Scan::global): Likewise.
(Target_x86_64::Relocate::relocate): Likewise.
* testsuite/x86_64_mov_to_lea1.s: Add a test for
R_X86_64_CODE_4_GOTPCRELX.
* testsuite/x86_64_mov_to_lea2.s: Likewise.
* testsuite/x86_64_mov_to_lea3.s: Likewise.
* testsuite/x86_64_mov_to_lea4.s: Likewise.
* testsuite/x86_64_mov_to_lea5.s: Likewise.
* testsuite/x86_64_mov_to_lea.sh: Updated.
---
elfcpp/x86_64.h | 6 ++++-
gold/testsuite/x86_64_mov_to_lea.sh | 16 +++++++++++++
gold/testsuite/x86_64_mov_to_lea1.s | 1 +
gold/testsuite/x86_64_mov_to_lea2.s | 1 +
gold/testsuite/x86_64_mov_to_lea3.s | 1 +
gold/testsuite/x86_64_mov_to_lea4.s | 1 +
gold/testsuite/x86_64_mov_to_lea5.s | 1 +
gold/x86_64.cc | 37 ++++++++++++++++++++++-------
8 files changed, 54 insertions(+), 10 deletions(-)
diff --git a/elfcpp/x86_64.h b/elfcpp/x86_64.h
index 0377e773071..97a87ae424d 100644
--- a/elfcpp/x86_64.h
+++ b/elfcpp/x86_64.h
@@ -95,9 +95,13 @@ enum
R_X86_64_PC32_BND = 39, // PC relative 32 bit signed with BND prefix
R_X86_64_PLT32_BND = 40, // 32 bit PLT address with BND prefix
R_X86_64_GOTPCRELX = 41, // 32 bit signed PC relative offset to GOT
- // without REX prefix, relaxable.
+ // without REX nor REX2 prefixes, relaxable.
R_X86_64_REX_GOTPCRELX = 42, // 32 bit signed PC relative offset to GOT
// with REX prefix, relaxable.
+ R_X86_64_CODE_4_GOTPCRELX = 43, // 32 bit signed PC relative offset to
+ // GOT if the instruction starts at 4
+ // bytes before the relocation offset,
+ // relaxable.
// GNU vtable garbage collection extensions.
R_X86_64_GNU_VTINHERIT = 250,
R_X86_64_GNU_VTENTRY = 251
diff --git a/gold/testsuite/x86_64_mov_to_lea.sh b/gold/testsuite/x86_64_mov_to_lea.sh
index 1b30e1aa048..3e248ebec3c 100755
--- a/gold/testsuite/x86_64_mov_to_lea.sh
+++ b/gold/testsuite/x86_64_mov_to_lea.sh
@@ -25,20 +25,36 @@
set -e
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea1.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea1.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea2.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea2.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea3.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea3.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea4.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea4.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea5.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea5.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea6.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea6.stdout
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea7.stdout
+grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea7.stdout
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea8.stdout
+grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea8.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea9.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea9.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea10.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea10.stdout
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea11.stdout
+grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea11.stdout
grep -q "mov 0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea12.stdout
+grep -q "mov 0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea12.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea13.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea13.stdout
grep -q "lea -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea14.stdout
+grep -q "lea -0x[a-f0-9]\+(%rip),%r26" x86_64_mov_to_lea14.stdout
grep -q "mov 0x[a-f0-9]\+(%rip),%eax" x86_64_mov_to_lea15.stdout
+grep -q "mov 0x[a-f0-9]\+(%rip),%r26d" x86_64_mov_to_lea15.stdout
grep -q "mov 0x[a-f0-9]\+(%rip),%eax" x86_64_mov_to_lea16.stdout
+grep -q "mov 0x[a-f0-9]\+(%rip),%r26d" x86_64_mov_to_lea16.stdout
exit 0
diff --git a/gold/testsuite/x86_64_mov_to_lea1.s b/gold/testsuite/x86_64_mov_to_lea1.s
index 4dce487c3fc..298ede12f80 100644
--- a/gold/testsuite/x86_64_mov_to_lea1.s
+++ b/gold/testsuite/x86_64_mov_to_lea1.s
@@ -8,4 +8,5 @@ foo:
.type _start, @function
_start:
movq foo@GOTPCREL(%rip), %rax
+ movq foo@GOTPCREL(%rip), %r26
.size _start, .-_start
diff --git a/gold/testsuite/x86_64_mov_to_lea2.s b/gold/testsuite/x86_64_mov_to_lea2.s
index 2a11b7a19f4..404f4c1dd48 100644
--- a/gold/testsuite/x86_64_mov_to_lea2.s
+++ b/gold/testsuite/x86_64_mov_to_lea2.s
@@ -3,4 +3,5 @@
.type _start, @function
_start:
movq _DYNAMIC@GOTPCREL(%rip), %rax
+ movq _DYNAMIC@GOTPCREL(%rip), %r26
.size _start, .-_start
diff --git a/gold/testsuite/x86_64_mov_to_lea3.s b/gold/testsuite/x86_64_mov_to_lea3.s
index ac43b783758..838c33edae0 100644
--- a/gold/testsuite/x86_64_mov_to_lea3.s
+++ b/gold/testsuite/x86_64_mov_to_lea3.s
@@ -7,4 +7,5 @@ foo:
.type _start, @function
_start:
movq foo@GOTPCREL(%rip), %rax
+ movq foo@GOTPCREL(%rip), %r26
.size _start, .-_start
diff --git a/gold/testsuite/x86_64_mov_to_lea4.s b/gold/testsuite/x86_64_mov_to_lea4.s
index 37bee32bb4e..a68a4cf0d19 100644
--- a/gold/testsuite/x86_64_mov_to_lea4.s
+++ b/gold/testsuite/x86_64_mov_to_lea4.s
@@ -9,4 +9,5 @@ foo:
.type _start, @function
_start:
movq foo@GOTPCREL(%rip), %rax
+ movq foo@GOTPCREL(%rip), %r26
.size _start, .-_start
diff --git a/gold/testsuite/x86_64_mov_to_lea5.s b/gold/testsuite/x86_64_mov_to_lea5.s
index e793a2b9b73..e818989deb7 100644
--- a/gold/testsuite/x86_64_mov_to_lea5.s
+++ b/gold/testsuite/x86_64_mov_to_lea5.s
@@ -9,4 +9,5 @@ foo:
.type _start, @function
_start:
movl foo@GOTPCREL+4(%rip), %eax
+ movl foo@GOTPCREL+4(%rip), %r26d
.size _start, .-_start
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 928dfa8ea34..b7be9bf0d48 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -1053,8 +1053,9 @@ class Target_x86_64 : public Sized_target<size, false>
gold_assert(gsym != NULL);
// We cannot do the conversion unless it's one of these relocations.
if (r_type != elfcpp::R_X86_64_GOTPCREL
- && r_type != elfcpp::R_X86_64_GOTPCRELX
- && r_type != elfcpp::R_X86_64_REX_GOTPCRELX)
+ && r_type != elfcpp::R_X86_64_GOTPCRELX
+ && r_type != elfcpp::R_X86_64_REX_GOTPCRELX
+ && r_type != elfcpp::R_X86_64_CODE_4_GOTPCRELX)
return false;
// We cannot convert references to IFUNC symbols, or to symbols that
// are not local to the current module.
@@ -2971,6 +2972,7 @@ Target_x86_64<size>::Scan::get_reference_flags(unsigned int r_type)
case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
+ case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
case elfcpp::R_X86_64_GOTPLT64:
// Absolute in GOT.
return Symbol::ABSOLUTE_REF;
@@ -3251,6 +3253,7 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
+ case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
case elfcpp::R_X86_64_GOTPLT64:
{
// The symbol requires a GOT section.
@@ -3261,21 +3264,30 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
// mov foo@GOTPCREL(%rip), %reg
// to lea foo(%rip), %reg.
// in Relocate::relocate.
+ size_t r_offset = reloc.get_r_offset();
if (!parameters->incremental()
- && (r_type == elfcpp::R_X86_64_GOTPCREL
- || r_type == elfcpp::R_X86_64_GOTPCRELX
- || r_type == elfcpp::R_X86_64_REX_GOTPCRELX)
+ && (((r_type == elfcpp::R_X86_64_GOTPCREL
+ || r_type == elfcpp::R_X86_64_GOTPCRELX
+ || r_type == elfcpp::R_X86_64_REX_GOTPCRELX)
+ && r_offset >= 2)
+ || (r_type == elfcpp::R_X86_64_CODE_4_GOTPCRELX
+ && r_offset >= 4))
&& reloc.get_r_addend() == -4
- && reloc.get_r_offset() >= 2
&& !is_ifunc)
{
section_size_type stype;
const unsigned char* view = object->section_contents(data_shndx,
&stype, true);
- if (view[reloc.get_r_offset() - 2] == 0x8b)
+ if (r_type == elfcpp::R_X86_64_CODE_4_GOTPCRELX
+ && view[r_offset - 4] != 0xd5)
+ goto need_got;
+
+ if (view[r_offset - 2] == 0x8b)
break;
}
+need_got:
+
// The symbol requires a GOT entry.
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
@@ -3498,6 +3510,7 @@ Target_x86_64<size>::Scan::possible_function_pointer_reloc(
case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
+ case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
case elfcpp::R_X86_64_GOTPLT64:
{
return true;
@@ -3714,6 +3727,7 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
+ case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
case elfcpp::R_X86_64_GOTPLT64:
{
// The symbol requires a GOT entry.
@@ -3736,8 +3750,12 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
size_t r_offset = reloc.get_r_offset();
if (!parameters->incremental()
&& reloc.get_r_addend() == -4
- && r_offset >= 2
- && Target_x86_64<size>::can_convert_mov_to_lea(gsym, r_type,
+ && ((r_type != elfcpp::R_X86_64_CODE_4_GOTPCRELX
+ && r_offset >= 2)
+ || (r_type == elfcpp::R_X86_64_CODE_4_GOTPCRELX
+ && r_offset >= 4
+ && view[r_offset - 4] == 0xd5))
+ && Target_x86_64<size>::can_convert_mov_to_lea(gsym, r_type,
r_offset, &view))
break;
@@ -4420,6 +4438,7 @@ Target_x86_64<size>::Relocate::relocate(
case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
+ case elfcpp::R_X86_64_CODE_4_GOTPCRELX:
{
bool converted_p = false;
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 3/4] x86-64: Add R_X86_64_CODE_4_GOTTPOFF/R_X86_64_CODE_4_GOTPC32_TLSDESC
2023-12-28 14:58 [PATCH 0/4] Support APX relocations H.J. Lu
2023-12-28 14:58 ` [PATCH 1/4] x86-64: Add R_X86_64_CODE_4_GOTPCRELX H.J. Lu
2023-12-28 14:58 ` [PATCH 2/4] gold: Handle R_X86_64_CODE_4_GOTPCRELX H.J. Lu
@ 2023-12-28 14:58 ` H.J. Lu
2023-12-28 14:58 ` [PATCH 4/4] Gold: Handle R_X86_64_CODE_4_GOTPC32_TLSDESC/R_X86_64_CODE_4_GOTTPOFF H.J. Lu
2023-12-28 16:57 ` [PATCH 0/4] Support APX relocations H.J. Lu
4 siblings, 0 replies; 6+ messages in thread
From: H.J. Lu @ 2023-12-28 14:58 UTC (permalink / raw)
To: binutils
For
add name@gottpoff(%rip), %reg
mov name@gottpoff(%rip), %reg
add
# define R_X86_64_CODE_4_GOTTPOFF 44
and for
lea name@tlsdesc(%rip), %reg
add
# define R_X86_64_CODE_4_GOTPC32_TLSDESC 45
if the instruction starts at 4 bytes before the relocation offset.
They are similar to R_X86_64_GOTTPOFF and R_X86_64_GOTPC32_TLSDESC,
respectively. Linker can covert GOTTPOFF to
add $name@tpoff, %reg
mov $name@tpoff, %reg
and GOTPC32_TLSDESC to
mov $name@tpoff, %reg
mov name@gottpoff(%rip), %reg
if the instruction is encoded with the REX2 prefix when possible.
bfd/
* elf64-x86-64.c (x86_64_elf_howto_table): Add
R_X86_64_CODE_4_GOTTPOFF and R_X86_64_CODE_4_GOTPC32_TLSDESC.
(R_X86_64_standard): Updated.
(x86_64_reloc_map): Add BFD_RELOC_X86_64_CODE_4_GOTTPOFF
and BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC.
(elf_x86_64_check_tls_transition): Handle R_X86_64_CODE_4_GOTTPOFF
and R_X86_64_CODE_4_GOTPC32_TLSDESC.
(elf_x86_64_tls_transition): Likewise.
(elf_x86_64_scan_relocs): Likewise.
(elf_x86_64_relocate_section): Likewise.
* reloc.c (bfd_reloc_code_real): Add
BFD_RELOC_X86_64_CODE_4_GOTTPOFF and
BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC.
* bfd-in2.h: Regenerated.
* libbfd.h: Likewise.
gas/
* config/tc-i386.c (tc_i386_fix_adjustable): Handle
BFD_RELOC_X86_64_CODE_4_GOTTPOFF and
BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC.
(md_assemble): Handle BFD_RELOC_X86_64_CODE_4_GOTTPOFF.
(output_insn): Don't add empty REX prefix with REX2 prefix.
(output_disp): Handle BFD_RELOC_X86_64_CODE_4_GOTTPOFF and
BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC.
(md_apply_fix): Likewise.
(i386_validate_fix): Generate BFD_RELOC_X86_64_CODE_4_GOTTPOFF or
BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC if ixp->fx_tcbit3 is set.
(tc_gen_reloc): Handle BFD_RELOC_X86_64_CODE_4_GOTTPOFF and
BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC.
* testsuite/gas/i386/x86-64-gottpoff.d: New file.
* testsuite/gas/i386/x86-64-gottpoff.s: Likewise.
* testsuite/gas/i386/x86-64-tlsdesc.d: Likewise.
* testsuite/gas/i386/x86-64-tlsdesc.s: Likewise.
include/
* elf/x86-64.h (elf_x86_64_reloc_type): Add
R_X86_64_CODE_4_GOTTPOFF and R_X86_64_CODE_4_GOTPC32_TLSDESC
ld/
* testsuite/ld-x86-64/tlsbindesc.d: Updated.
* testsuite/ld-x86-64/tlsbindesc.rd: Likewise.
* testsuite/ld-x86-64/tlsbindesc.s: Add R_X86_64_CODE_4_GOTTPOFF
and R_X86_64_CODE_4_GOTPC32_TLSDESC tests.
---
bfd/bfd-in2.h | 2 +
bfd/elf64-x86-64.c | 125 ++++++++++++++++++++++-
bfd/libbfd.h | 2 +
bfd/reloc.c | 4 +
gas/config/tc-i386.c | 20 ++++
gas/testsuite/gas/i386/x86-64-gottpoff.d | 19 ++++
gas/testsuite/gas/i386/x86-64-gottpoff.s | 15 +++
gas/testsuite/gas/i386/x86-64-tlsdesc.d | 17 +++
gas/testsuite/gas/i386/x86-64-tlsdesc.s | 13 +++
gas/testsuite/gas/i386/x86-64.exp | 3 +
include/elf/x86-64.h | 6 ++
ld/testsuite/ld-x86-64/tlsbindesc.dd | 49 +++++++++
ld/testsuite/ld-x86-64/tlsbindesc.rd | 36 +++----
ld/testsuite/ld-x86-64/tlsbindesc.s | 39 +++++++
14 files changed, 329 insertions(+), 21 deletions(-)
create mode 100644 gas/testsuite/gas/i386/x86-64-gottpoff.d
create mode 100644 gas/testsuite/gas/i386/x86-64-gottpoff.s
create mode 100644 gas/testsuite/gas/i386/x86-64-tlsdesc.d
create mode 100644 gas/testsuite/gas/i386/x86-64-tlsdesc.s
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 96709da9170..550704ae89f 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -3892,6 +3892,8 @@ enum bfd_reloc_code_real
BFD_RELOC_X86_64_GOTPCRELX,
BFD_RELOC_X86_64_REX_GOTPCRELX,
BFD_RELOC_X86_64_CODE_4_GOTPCRELX,
+ BFD_RELOC_X86_64_CODE_4_GOTTPOFF,
+ BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC,
/* ns32k relocations. */
BFD_RELOC_NS32K_IMM_8,
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index a2d1b6f14b7..3406bc86ec1 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -173,12 +173,18 @@ static reloc_howto_type x86_64_elf_howto_table[] =
HOWTO(R_X86_64_CODE_4_GOTPCRELX, 0, 4, 32, true, 0, complain_overflow_signed,
bfd_elf_generic_reloc, "R_X86_64_CODE_4_GOTPCRELX", false, 0, 0xffffffff,
true),
+ HOWTO(R_X86_64_CODE_4_GOTTPOFF, 0, 4, 32, true, 0, complain_overflow_signed,
+ bfd_elf_generic_reloc, "R_X86_64_CODE_4_GOTTPOFF", false, 0, 0xffffffff,
+ true),
+ 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),
/* 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_GOTPCRELX + 1)
+#define R_X86_64_standard (R_X86_64_CODE_4_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. */
@@ -248,6 +254,8 @@ static const struct elf_reloc_map x86_64_reloc_map[] =
{ BFD_RELOC_X86_64_GOTPCRELX, R_X86_64_GOTPCRELX, },
{ BFD_RELOC_X86_64_REX_GOTPCRELX, R_X86_64_REX_GOTPCRELX, },
{ 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_VTABLE_INHERIT, R_X86_64_GNU_VTINHERIT, },
{ BFD_RELOC_VTABLE_ENTRY, R_X86_64_GNU_VTENTRY, },
};
@@ -1262,6 +1270,19 @@ elf_x86_64_check_tls_transition (bfd *abfd,
return (r_type == R_X86_64_PC32 || r_type == R_X86_64_PLT32);
}
+ case R_X86_64_CODE_4_GOTTPOFF:
+ /* Check transition from IE access model:
+ mov foo@gottpoff(%rip), %reg
+ add foo@gottpoff(%rip), %reg
+ where reg is one of r16 to r31. */
+
+ if (offset < 4
+ || (offset + 4) > sec->size
+ || contents[offset - 4] != 0xd5)
+ return false;
+
+ goto check_gottpoff;
+
case R_X86_64_GOTTPOFF:
/* Check transition from IE access model:
mov foo@gottpoff(%rip), %reg
@@ -1288,6 +1309,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
return false;
}
+ check_gottpoff:
val = bfd_get_8 (abfd, contents + offset - 2);
if (val != 0x8b && val != 0x03)
return false;
@@ -1295,6 +1317,18 @@ elf_x86_64_check_tls_transition (bfd *abfd,
val = bfd_get_8 (abfd, contents + offset - 1);
return (val & 0xc7) == 5;
+ case R_X86_64_CODE_4_GOTPC32_TLSDESC:
+ /* Check transition from GDesc access model:
+ lea x@tlsdesc(%rip), %reg
+ where reg is one of r16 to r31. */
+
+ if (offset < 4
+ || (offset + 4) > sec->size
+ || contents[offset - 4] != 0xd5)
+ return false;
+
+ goto check_tlsdesc;
+
case R_X86_64_GOTPC32_TLSDESC:
/* Check transition from GDesc access model:
leaq x@tlsdesc(%rip), %rax <--- LP64 mode.
@@ -1312,6 +1346,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
if (val != 0x48 && (ABI_64_P (abfd) || val != 0x40))
return false;
+ check_tlsdesc:
if (bfd_get_8 (abfd, contents + offset - 2) != 0x8d)
return false;
@@ -1378,8 +1413,10 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
{
case R_X86_64_TLSGD:
case R_X86_64_GOTPC32_TLSDESC:
+ case R_X86_64_CODE_4_GOTPC32_TLSDESC:
case R_X86_64_TLSDESC_CALL:
case R_X86_64_GOTTPOFF:
+ case R_X86_64_CODE_4_GOTTPOFF:
if (bfd_link_executable (info))
{
if (h == NULL)
@@ -1399,6 +1436,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
if (to_type == R_X86_64_TLSGD
|| to_type == R_X86_64_GOTPC32_TLSDESC
+ || to_type == R_X86_64_CODE_4_GOTPC32_TLSDESC
|| to_type == R_X86_64_TLSDESC_CALL)
{
if (tls_type == GOT_TLS_IE)
@@ -1424,7 +1462,9 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
}
/* Return TRUE if there is no transition. */
- if (from_type == to_type)
+ if (from_type == to_type
+ || (from_type == R_X86_64_CODE_4_GOTTPOFF
+ && to_type == R_X86_64_GOTTPOFF))
return true;
/* Check if the transition can be performed. */
@@ -2132,6 +2172,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:
if (!bfd_link_executable (info))
info->flags |= DF_STATIC_TLS;
/* Fall through */
@@ -2146,6 +2187,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
case R_X86_64_GOTPCREL64:
case R_X86_64_GOTPLT64:
case R_X86_64_GOTPC32_TLSDESC:
+ case R_X86_64_CODE_4_GOTPC32_TLSDESC:
case R_X86_64_TLSDESC_CALL:
/* This symbol requires a global offset table entry. */
{
@@ -2167,9 +2209,11 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
tls_type = GOT_TLS_GD;
break;
case R_X86_64_GOTTPOFF:
+ case R_X86_64_CODE_4_GOTTPOFF:
tls_type = GOT_TLS_IE;
break;
case R_X86_64_GOTPC32_TLSDESC:
+ case R_X86_64_CODE_4_GOTPC32_TLSDESC:
case R_X86_64_TLSDESC_CALL:
tls_type = GOT_TLS_GDESC;
break;
@@ -3518,8 +3562,10 @@ elf_x86_64_relocate_section (bfd *output_bfd,
case R_X86_64_TLSGD:
case R_X86_64_GOTPC32_TLSDESC:
+ case R_X86_64_CODE_4_GOTPC32_TLSDESC:
case R_X86_64_TLSDESC_CALL:
case R_X86_64_GOTTPOFF:
+ case R_X86_64_CODE_4_GOTTPOFF:
tls_type = GOT_UNKNOWN;
if (h == NULL && local_got_offsets)
tls_type = elf_x86_local_got_tls_type (input_bfd) [r_symndx];
@@ -3660,6 +3706,37 @@ elf_x86_64_relocate_section (bfd *output_bfd,
contents + roff);
continue;
}
+ else if (r_type == R_X86_64_CODE_4_GOTPC32_TLSDESC)
+ {
+ /* GDesc -> LE transition.
+ It's originally something like:
+ lea x@tlsdesc(%rip), %reg
+
+ Change it to:
+ mov $x@tpoff, %reg
+ where reg is one of r16 to r31. */
+
+ unsigned int val, rex2;
+ unsigned int rex2_mask = REX_R | REX_R << 4;
+
+ if (roff < 4)
+ goto corrupt_input;
+ rex2 = bfd_get_8 (input_bfd, contents + roff - 3);
+ val = bfd_get_8 (input_bfd, contents + roff - 1);
+ /* Move the R bits to the B bits in REX2 payload
+ byte. */
+ bfd_put_8 (output_bfd,
+ ((rex2 & ~rex2_mask)
+ | (rex2 & rex2_mask) >> 2),
+ contents + roff - 3);
+ bfd_put_8 (output_bfd, 0xc7, contents + roff - 2);
+ bfd_put_8 (output_bfd, 0xc0 | ((val >> 3) & 7),
+ contents + roff - 1);
+ bfd_put_32 (output_bfd,
+ elf_x86_64_tpoff (info, relocation),
+ contents + roff);
+ continue;
+ }
else if (r_type == R_X86_64_TLSDESC_CALL)
{
/* GDesc -> LE transition.
@@ -3799,6 +3876,46 @@ elf_x86_64_relocate_section (bfd *output_bfd,
contents + roff);
continue;
}
+ else if (r_type == R_X86_64_CODE_4_GOTTPOFF)
+ {
+ /* IE->LE transition:
+ Originally it can be one of:
+ mov foo@gottpoff(%rip), %reg
+ add foo@gottpoff(%rip), %reg
+ We change it into:
+ mov $foo@tpoff, %reg
+ add $foo@tpoff, %reg
+ where reg is one of r16 to r31. */
+
+ unsigned int rex2, type, reg;
+ unsigned int rex2_mask = REX_R | REX_R << 4;
+
+ if (roff < 4)
+ goto corrupt_input;
+
+ rex2 = bfd_get_8 (input_bfd, contents + roff - 3);
+ type = bfd_get_8 (input_bfd, contents + roff - 2);
+ reg = bfd_get_8 (input_bfd, contents + roff - 1);
+ reg >>= 3;
+ /* Move the R bits to the B bits in REX2 payload
+ byte. */
+ if (type == 0x8b)
+ type = 0xc7;
+ else
+ type = 0x81;
+ bfd_put_8 (output_bfd,
+ ((rex2 & ~rex2_mask)
+ | (rex2 & rex2_mask) >> 2),
+ contents + roff - 3);
+ bfd_put_8 (output_bfd, type,
+ 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);
}
@@ -3905,6 +4022,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
if (r_type_tls == r_type)
{
if (r_type == R_X86_64_GOTPC32_TLSDESC
+ || r_type == R_X86_64_CODE_4_GOTPC32_TLSDESC
|| r_type == R_X86_64_TLSDESC_CALL)
relocation = htab->elf.sgotplt->output_section->vma
+ htab->elf.sgotplt->output_offset
@@ -4000,7 +4118,8 @@ elf_x86_64_relocate_section (bfd *output_bfd,
wrel++;
continue;
}
- else if (r_type == R_X86_64_GOTPC32_TLSDESC)
+ else if (r_type == R_X86_64_GOTPC32_TLSDESC
+ || r_type == R_X86_64_CODE_4_GOTPC32_TLSDESC)
{
/* GDesc -> IE transition.
It's originally something like:
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 8873fafdde9..196e7e55ea6 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1461,6 +1461,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_X86_64_GOTPCRELX",
"BFD_RELOC_X86_64_REX_GOTPCRELX",
"BFD_RELOC_X86_64_CODE_4_GOTPCRELX",
+ "BFD_RELOC_X86_64_CODE_4_GOTTPOFF",
+ "BFD_RELOC_X86_64_CODE_4_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 56d852d084f..30852b1422f 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2477,6 +2477,10 @@ ENUMX
BFD_RELOC_X86_64_REX_GOTPCRELX
ENUMX
BFD_RELOC_X86_64_CODE_4_GOTPCRELX
+ENUMX
+ BFD_RELOC_X86_64_CODE_4_GOTTPOFF
+ENUMX
+ BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC
ENUMDOC
x86-64/elf relocations.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 8d76446010b..694c494edec 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -3601,10 +3601,12 @@ tc_i386_fix_adjustable (fixS *fixP)
|| fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32
|| 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_TPOFF32
|| fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF64
|| fixP->fx_r_type == BFD_RELOC_X86_64_GOTOFF64
|| fixP->fx_r_type == BFD_RELOC_X86_64_GOTPC32_TLSDESC
+ || fixP->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC
|| fixP->fx_r_type == BFD_RELOC_X86_64_TLSDESC_CALL
|| fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
@@ -5632,6 +5634,7 @@ md_assemble (char *line)
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;
@@ -10477,6 +10480,7 @@ output_insn (const struct last_insn *last_insn)
is also needed for lea with R_X86_64_GOTPC32_TLSDESC
relocation for GDesc -> IE/LE optimization. */
if (x86_elf_abi == X86_64_X32_ABI
+ && !is_apx_rex2_encoding ()
&& i.operands == 2
&& (i.reloc[0] == BFD_RELOC_X86_64_GOTTPOFF
|| i.reloc[0] == BFD_RELOC_X86_64_GOTPC32_TLSDESC)
@@ -10842,7 +10846,9 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
case BFD_RELOC_X86_64_TLSGD:
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_GOTPC32_TLSDESC:
+ case BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC:
case BFD_RELOC_X86_64_TLSDESC_CALL:
i.has_gotpc_tls_reloc = true;
default:
@@ -14356,7 +14362,9 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
case BFD_RELOC_X86_64_TLSGD:
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_GOTPC32_TLSDESC:
+ case BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC:
value = 0; /* Fully resolved at runtime. No addend. */
/* Fallthrough */
case BFD_RELOC_386_TLS_LE:
@@ -15929,6 +15937,14 @@ i386_validate_fix (fixS *fixp)
return IS_ELF && fixp->fx_addsy
&& (!S_IS_DEFINED (fixp->fx_addsy)
|| S_IS_EXTERNAL (fixp->fx_addsy));
+
+ if (fixp->fx_tcbit3)
+ {
+ if (fixp->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF)
+ 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;
+ }
#endif
if (fixp->fx_subsy)
@@ -16073,6 +16089,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
case BFD_RELOC_X86_64_DTPOFF32:
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_TPOFF32:
case BFD_RELOC_X86_64_TPOFF64:
case BFD_RELOC_X86_64_GOTOFF64:
@@ -16083,6 +16100,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
case BFD_RELOC_X86_64_GOTPLT64:
case BFD_RELOC_X86_64_PLTOFF64:
case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
+ case BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC:
case BFD_RELOC_X86_64_TLSDESC_CALL:
case BFD_RELOC_RVA:
case BFD_RELOC_VTABLE_ENTRY:
@@ -16215,7 +16233,9 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
case BFD_RELOC_X86_64_TLSGD:
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_GOTPC32_TLSDESC:
+ case BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC:
case BFD_RELOC_X86_64_TLSDESC_CALL:
rel->addend = fixp->fx_offset - fixp->fx_size;
break;
diff --git a/gas/testsuite/gas/i386/x86-64-gottpoff.d b/gas/testsuite/gas/i386/x86-64-gottpoff.d
new file mode 100644
index 00000000000..d42abccc6d9
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-gottpoff.d
@@ -0,0 +1,19 @@
+#as:
+#objdump: -dwr
+#name: x86-64 gottpoff
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+ +[a-f0-9]+: 48 03 05 00 00 00 00 add 0x0\(%rip\),%rax # 7 <_start\+0x7> 3: R_X86_64_GOTTPOFF foo-0x4
+ +[a-f0-9]+: 48 8b 05 00 00 00 00 mov 0x0\(%rip\),%rax # e <_start\+0xe> a: R_X86_64_GOTTPOFF foo-0x4
+ +[a-f0-9]+: d5 48 03 05 00 00 00 00 add 0x0\(%rip\),%r16 # 16 <_start\+0x16> 12: R_X86_64_CODE_4_GOTTPOFF foo-0x4
+ +[a-f0-9]+: d5 48 8b 25 00 00 00 00 mov 0x0\(%rip\),%r20 # 1e <_start\+0x1e> 1a: R_X86_64_CODE_4_GOTTPOFF foo-0x4
+ +[a-f0-9]+: 48 03 05 00 00 00 00 add 0x0\(%rip\),%rax # 25 <_start\+0x25> 21: R_X86_64_GOTTPOFF foo-0x4
+ +[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
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-gottpoff.s b/gas/testsuite/gas/i386/x86-64-gottpoff.s
new file mode 100644
index 00000000000..6f8f9d1480c
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-gottpoff.s
@@ -0,0 +1,15 @@
+ .text
+_start:
+ addq foo@GOTTPOFF(%rip), %rax
+ movq foo@GOTTPOFF(%rip), %rax
+
+ addq foo@GOTTPOFF(%rip), %r16
+ movq foo@GOTTPOFF(%rip), %r20
+
+ .intel_syntax noprefix
+
+ addq rax, QWORD PTR [rip + foo@GOTTPOFF]
+ movq rax, QWORD PTR [rip + foo@GOTTPOFF]
+
+ addq r16, QWORD PTR [rip + foo@GOTTPOFF]
+ movq r20, QWORD PTR [rip + foo@GOTTPOFF]
diff --git a/gas/testsuite/gas/i386/x86-64-tlsdesc.d b/gas/testsuite/gas/i386/x86-64-tlsdesc.d
new file mode 100644
index 00000000000..50c04e1e6b9
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-tlsdesc.d
@@ -0,0 +1,17 @@
+#as:
+#objdump: -dwr
+#name: x86-64 tlsdesc
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <_start>:
+ +[a-f0-9]+: 48 8d 05 00 00 00 00 lea 0x0\(%rip\),%rax # 7 <_start\+0x7> 3: R_X86_64_GOTPC32_TLSDESC foo-0x4
+ +[a-f0-9]+: d5 48 8d 05 00 00 00 00 lea 0x0\(%rip\),%r16 # f <_start\+0xf> b: R_X86_64_CODE_4_GOTPC32_TLSDESC foo-0x4
+ +[a-f0-9]+: d5 48 8d 25 00 00 00 00 lea 0x0\(%rip\),%r20 # 17 <_start\+0x17> 13: R_X86_64_CODE_4_GOTPC32_TLSDESC foo-0x4
+ +[a-f0-9]+: 48 8d 05 00 00 00 00 lea 0x0\(%rip\),%rax # 1e <_start\+0x1e> 1a: R_X86_64_GOTPC32_TLSDESC foo-0x4
+ +[a-f0-9]+: d5 48 8d 05 00 00 00 00 lea 0x0\(%rip\),%r16 # 26 <_start\+0x26> 22: R_X86_64_CODE_4_GOTPC32_TLSDESC foo-0x4
+ +[a-f0-9]+: d5 48 8d 25 00 00 00 00 lea 0x0\(%rip\),%r20 # 2e <_start\+0x2e> 2a: R_X86_64_CODE_4_GOTPC32_TLSDESC foo-0x4
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-tlsdesc.s b/gas/testsuite/gas/i386/x86-64-tlsdesc.s
new file mode 100644
index 00000000000..91f8d23dca4
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-tlsdesc.s
@@ -0,0 +1,13 @@
+ .text
+_start:
+ leaq foo@TLSDESC(%rip), %rax
+
+ leaq foo@TLSDESC(%rip), %r16
+ leaq foo@TLSDESC(%rip), %r20
+
+ .intel_syntax noprefix
+
+ leaq rax, QWORD PTR [rip + foo@TLSDESC]
+
+ leaq r16, QWORD PTR [rip + foo@TLSDESC]
+ leaq r20, QWORD PTR [rip + foo@TLSDESC]
diff --git a/gas/testsuite/gas/i386/x86-64.exp b/gas/testsuite/gas/i386/x86-64.exp
index fa6a1c3c945..cd28846ca8f 100644
--- a/gas/testsuite/gas/i386/x86-64.exp
+++ b/gas/testsuite/gas/i386/x86-64.exp
@@ -665,6 +665,9 @@ if [is_elf_format] then {
run_dump_test "x86-64-gotpcrel-no-relax"
run_dump_test "x86-64-gotpcrel-2"
+ run_dump_test "x86-64-gottpoff"
+ run_dump_test "x86-64-tlsdesc"
+
run_dump_test "x86-64-no-got"
run_dump_test "x86-64-addend"
diff --git a/include/elf/x86-64.h b/include/elf/x86-64.h
index 30d1722cb73..bbcf190532e 100644
--- a/include/elf/x86-64.h
+++ b/include/elf/x86-64.h
@@ -86,6 +86,12 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_type)
instruction starts at 4 bytes before the relocation offset,
relaxable. */
RELOC_NUMBER (R_X86_64_CODE_4_GOTPCRELX, 43)
+ /* PC relative offset to IE GOT entry if the instruction starts at
+ 4 bytes before the relocation offset. */
+ RELOC_NUMBER (R_X86_64_CODE_4_GOTTPOFF, 44)
+ /* 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)
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)
diff --git a/ld/testsuite/ld-x86-64/tlsbindesc.dd b/ld/testsuite/ld-x86-64/tlsbindesc.dd
index 5bdb659555f..4587cc751b4 100644
--- a/ld/testsuite/ld-x86-64/tlsbindesc.dd
+++ b/ld/testsuite/ld-x86-64/tlsbindesc.dd
@@ -165,6 +165,55 @@ Disassembly of section .text:
+[0-9a-f]+: 90[ ]+nop *
+[0-9a-f]+: c9[ ]+leave *
+[0-9a-f]+: c3[ ]+ret *
+# IE against global var
+ +[0-9a-f]+: d5 48 03 05 ([0-9a-f]{2} ){3}[ ]+add 0x[0-9a-f]+\(%rip\),%r16 +# [0-9a-f]+ <sG2>
+# -> R_X86_64_TPOFF64 sG2
+ +[0-9a-f]+: 00 *
+# IE -> LE against global var defined in exec
+ +[0-9a-f]+: d5 18 81 c1 60 ff ff[ ]+add \$0xf+60,%r17
+# sg1
+ +[0-9a-f]+: ff *
+# IE -> LE against local var
+ +[0-9a-f]+: d5 18 81 c2 80 ff ff[ ]+add \$0xf+80,%r18
+# sl1
+ +[0-9a-f]+: ff *
+# IE -> LE against hidden var
+ +[0-9a-f]+: d5 18 81 c3 a0 ff ff[ ]+add \$0xf+a0,%r19
+# sh1
+ +[0-9a-f]+: ff *
+# Direct access through %fs
+# IE against global var
+ +[0-9a-f]+: d5 48 8b 25 ([0-9a-f]{2} ){3}[ ]+mov 0x[0-9a-f]+\(%rip\),%r20 +# [0-9a-f]+ <sG5>
+# -> R_X86_64_TPOFF64 sG5
+ +[0-9a-f]+: 00 *
+# IE->LE against local var
+ +[0-9a-f]+: d5 18 c7 c5 90 ff ff[ ]+mov \$0xf+90,%r21
+# sl5
+ +[0-9a-f]+: ff *
+# IE->LE against hidden var
+ +[0-9a-f]+: d5 18 c7 c6 b0 ff ff[ ]+mov \$0xf+b0,%r22
+ +[0-9a-f]+: ff *
+# GD -> IE because variable is not defined in executable
+ +[0-9a-f]+: d5 48 8b 05 ([0-9a-f]{2} ){3}[ ]+mov 0x[0-9a-f]+\(%rip\),%r16 +# [0-9a-f]+ <sG1>
+# -> R_X86_64_TPOFF64 sG1
+ +[0-9a-f]+: 00 *
+# GD -> IE because variable is not defined in executable where
+# the variable is referenced through IE too
+ +[0-9a-f]+: d5 48 8b 0d ([0-9a-f]{2} ){3}[ ]+mov 0x[0-9a-f]+\(%rip\),%r17 +# [0-9a-f]+ <sG2>
+# -> R_X86_64_TPOFF64 sG2
+ +[0-9a-f]+: 00 *
+# GD -> LE with global variable defined in executable
+ +[0-9a-f]+: d5 18 c7 c2 60 ff ff[ ]+mov \$0xf+60,%r18
+# sg1
+ +[0-9a-f]+: ff *
+# GD -> LE with local variable defined in executable
+ +[0-9a-f]+: d5 18 c7 c3 80 ff ff[ ]+mov \$0xf+80,%r19
+# sl1
+ +[0-9a-f]+: ff *
+# GD -> LE with hidden variable defined in executable
+ +[0-9a-f]+: d5 18 c7 c4 a0 ff ff[ ]+mov \$0xf+a0,%r20
+# sh1
+ +[0-9a-f]+: ff *
[0-9a-f]+ <_start>:
+[0-9a-f]+: 55[ ]+push %rbp
diff --git a/ld/testsuite/ld-x86-64/tlsbindesc.rd b/ld/testsuite/ld-x86-64/tlsbindesc.rd
index 682c4a066a2..daaea7a5371 100644
--- a/ld/testsuite/ld-x86-64/tlsbindesc.rd
+++ b/ld/testsuite/ld-x86-64/tlsbindesc.rd
@@ -15,12 +15,12 @@ Section Headers:
+\[[ 0-9]+\] .dynsym +.*
+\[[ 0-9]+\] .dynstr +.*
+\[[ 0-9]+\] .rela.dyn +.*
- +\[[ 0-9]+\] .text +PROGBITS +0+401000 0+1000 0+1fd 00 +AX +0 +0 +4096
- +\[[ 0-9]+\] .tdata +PROGBITS +0+6011fd 0+11fd 0+60 00 WAT +0 +0 +1
- +\[[ 0-9]+\] .tbss +NOBITS +0+60125d 0+125d 0+40 00 WAT +0 +0 +1
- +\[[ 0-9]+\] .dynamic +DYNAMIC +0+601260 0+1260 0+100 10 +WA +4 +0 +8
- +\[[ 0-9]+\] .got +PROGBITS +0+601360 0+1360 0+20 08 +WA +0 +0 +8
- +\[[ 0-9]+\] .got.plt +PROGBITS +0+601380 0+1380 0+18 08 +WA +0 +0 +8
+ +\[[ 0-9]+\] .text +PROGBITS +0+401000 0+1000 0+25d 00 +AX +0 +0 +4096
+ +\[[ 0-9]+\] .tdata +PROGBITS +0+60125d 0+125d 0+60 00 WAT +0 +0 +1
+ +\[[ 0-9]+\] .tbss +NOBITS +0+6012bd 0+12bd 0+40 00 WAT +0 +0 +1
+ +\[[ 0-9]+\] .dynamic +DYNAMIC +0+6012c0 0+12c0 0+100 10 +WA +4 +0 +8
+ +\[[ 0-9]+\] .got +PROGBITS +0+6013c0 0+13c0 0+20 08 +WA +0 +0 +8
+ +\[[ 0-9]+\] .got.plt +PROGBITS +0+6013e0 0+13e0 0+18 08 +WA +0 +0 +8
+\[[ 0-9]+\] .symtab +.*
+\[[ 0-9]+\] .strtab +.*
+\[[ 0-9]+\] .shstrtab +.*
@@ -28,7 +28,7 @@ Key to Flags:
#...
Elf file type is EXEC \(Executable file\)
-Entry point 0x401105
+Entry point 0x401165
There are [0-9]+ program headers, starting at offset [0-9]+
Program Headers:
@@ -36,10 +36,10 @@ Program Headers:
+PHDR.*
+INTERP.*
.*Requesting program interpreter.*
- +LOAD +0x0+ 0x0+400000 0x0+400000 0x0+11fd 0x0+11fd R E 0x200000
- +LOAD +0x0+11fd 0x0+6011fd 0x0+6011fd 0x0+19b 0x0+19b RW +0x200000
- +DYNAMIC +0x0+1260 0x0+601260 0x0+601260 0x0+100 0x0+100 RW +0x8
- +TLS +0x0+11fd 0x0+6011fd 0x0+6011fd 0x0+60 0x0+a0 R +0x1
+ +LOAD +0x0+ 0x0+400000 0x0+400000 0x0+125d 0x0+125d R E 0x200000
+ +LOAD +0x0+125d 0x0+60125d 0x0+60125d 0x0+19b 0x0+19b RW +0x200000
+ +DYNAMIC +0x0+12c0 0x0+6012c0 0x0+6012c0 0x0+100 0x0+100 RW +0x8
+ +TLS +0x0+125d 0x0+60125d 0x0+60125d 0x0+60 0x0+a0 R +0x1
Section to Segment mapping:
+Segment Sections...
@@ -52,10 +52,10 @@ Program Headers:
Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 4 entries:
+Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
-0+601360 +0+100000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0
-0+601368 +0+200000012 R_X86_64_TPOFF64 +0+ sG2 \+ 0
-0+601370 +0+300000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0
-0+601378 +0+400000012 R_X86_64_TPOFF64 +0+ sG1 \+ 0
+0+6013c0 +0+100000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0
+0+6013c8 +0+200000012 R_X86_64_TPOFF64 +0+ sG2 \+ 0
+0+6013d0 +0+300000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0
+0+6013d8 +0+400000012 R_X86_64_TPOFF64 +0+ sG1 \+ 0
Symbol table '\.dynsym' contains [0-9]+ entries:
+Num: +Value +Size +Type +Bind +Vis +Ndx +Name
@@ -88,8 +88,8 @@ Symbol table '\.symtab' contains [0-9]+ entries:
+[0-9]+: 0+9c +0 +TLS +LOCAL +DEFAULT +8 bl8
.* FILE +LOCAL +DEFAULT +ABS
+[0-9]+: 0+a0 +0 +TLS +LOCAL +DEFAULT +7 _TLS_MODULE_BASE_
- +[0-9]+: 0+601260 +0 +OBJECT +LOCAL +DEFAULT +9 _DYNAMIC
- +[0-9]+: 0+601380 +0 +OBJECT +LOCAL +DEFAULT +11 _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+6012c0 +0 +OBJECT +LOCAL +DEFAULT +9 _DYNAMIC
+ +[0-9]+: 0+6013e0 +0 +OBJECT +LOCAL +DEFAULT +11 _GLOBAL_OFFSET_TABLE_
+[0-9]+: 0+1c +0 +TLS +GLOBAL +DEFAULT +7 sg8
+[0-9]+: 0+7c +0 +TLS +GLOBAL +DEFAULT +8 bg8
+[0-9]+: 0+74 +0 +TLS +GLOBAL +DEFAULT +8 bg6
@@ -104,7 +104,7 @@ Symbol table '\.symtab' contains [0-9]+ entries:
+[0-9]+: 0+58 +0 +TLS +GLOBAL +HIDDEN +7 sh7
+[0-9]+: 0+5c +0 +TLS +GLOBAL +HIDDEN +7 sh8
+[0-9]+: 0+ +0 +TLS +GLOBAL +DEFAULT +7 sg1
- +[0-9]+: 0+401105 +0 +FUNC +GLOBAL +DEFAULT +6 _start
+ +[0-9]+: 0+401165 +0 +FUNC +GLOBAL +DEFAULT +6 _start
+[0-9]+: 0+4c +0 +TLS +GLOBAL +HIDDEN +7 sh4
+[0-9]+: 0+78 +0 +TLS +GLOBAL +DEFAULT +8 bg7
+[0-9]+: 0+50 +0 +TLS +GLOBAL +HIDDEN +7 sh5
diff --git a/ld/testsuite/ld-x86-64/tlsbindesc.s b/ld/testsuite/ld-x86-64/tlsbindesc.s
index cbebf02171d..b80e5f192c0 100644
--- a/ld/testsuite/ld-x86-64/tlsbindesc.s
+++ b/ld/testsuite/ld-x86-64/tlsbindesc.s
@@ -126,3 +126,42 @@ fn2:
leave
ret
+
+ /* IE against global var */
+ addq sG2@gottpoff(%rip), %r16
+
+ /* IE -> LE against global var defined in exec */
+ addq sg1@gottpoff(%rip), %r17
+
+ /* IE -> LE against local var */
+ addq sl1@gottpoff(%rip), %r18
+
+ /* IE -> LE against hidden var */
+ addq sh1@gottpoff(%rip), %r19
+
+ /* Direct access through %fs */
+
+ /* IE against global var */
+ movq sG5@gottpoff(%rip), %r20
+
+ /* IE->LE against local var */
+ movq sl5@gottpoff(%rip), %r21
+
+ /* IE->LE against hidden var */
+ movq sh5@gottpoff(%rip), %r22
+
+ /* GD -> IE because variable is not defined in executable */
+ leaq sG1@tlsdesc(%rip), %r16
+
+ /* GD -> IE because variable is not defined in executable where
+ the variable is referenced through IE too */
+ leaq sG2@tlsdesc(%rip), %r17
+
+ /* GD -> LE with global variable defined in executable */
+ leaq sg1@tlsdesc(%rip), %r18
+
+ /* GD -> LE with local variable defined in executable */
+ leaq sl1@tlsdesc(%rip), %r19
+
+ /* GD -> LE with hidden variable defined in executable */
+ leaq sh1@tlsdesc(%rip), %r20
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 4/4] Gold: Handle R_X86_64_CODE_4_GOTPC32_TLSDESC/R_X86_64_CODE_4_GOTTPOFF
2023-12-28 14:58 [PATCH 0/4] Support APX relocations H.J. Lu
` (2 preceding siblings ...)
2023-12-28 14:58 ` [PATCH 3/4] x86-64: Add R_X86_64_CODE_4_GOTTPOFF/R_X86_64_CODE_4_GOTPC32_TLSDESC H.J. Lu
@ 2023-12-28 14:58 ` H.J. Lu
2023-12-28 16:57 ` [PATCH 0/4] Support APX relocations H.J. Lu
4 siblings, 0 replies; 6+ messages in thread
From: H.J. Lu @ 2023-12-28 14:58 UTC (permalink / raw)
To: binutils
Handle R_X86_64_CODE_4_GOTTPOFF and R_X86_64_CODE_4_GOTPC32_TLSDESC.
Convert
add name@gottpoff(%rip), %reg
mov name@gottpoff(%rip), %reg
to
add $name@tpoff, %reg
mov $name@tpoff, %reg
and
lea name@tlsdesc(%rip), %reg
to
mov $name@tpoff, %reg
mov name@gottpoff(%rip), %reg
if the instruction is encoded with the REX2 prefix when possible.
elfcpp/
* x86_64.h (R_X86_64_CODE_4_GOTTPOFF): New.
(R_X86_64_CODE_4_GOTPC32_TLSDESC): Likewise.
gold/
* x86_64.cc (Target_x86_64::optimize_tls_reloc): Handle
R_X86_64_CODE_4_GOTPC32_TLSDESC and R_X86_64_CODE_4_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_desc_gd_to_ie): Handle
R_X86_64_CODE_4_GOTPC32_TLSDESC.
(Target_x86_64::Relocate::tls_desc_gd_to_le): Likewise.
(Target_x86_64::Relocate::tls_ie_to_le): Handle.
R_X86_64_CODE_4_GOTTPOFF.
* testsuite/Makefile.am: Add x86_64_ie_to_le test.
* testsuite/Makefile.in: Regenerated.
* testsuite/x86_64_gd_to_le.s: Add R_X86_64_CODE_4_GOTPC32_TLSDESC
test.
* testsuite/x86_64_gd_to_le.sh: Check GDesc to LE conversion.
* testsuite/x86_64_ie_to_le.s: New file.
* testsuite/x86_64_ie_to_le.sh: Likewise.
---
elfcpp/x86_64.h | 8 ++
gold/testsuite/Makefile.am | 11 +++
gold/testsuite/Makefile.in | 17 ++++
gold/testsuite/x86_64_gd_to_le.s | 1 +
gold/testsuite/x86_64_gd_to_le.sh | 1 +
gold/testsuite/x86_64_ie_to_le.s | 17 ++++
gold/testsuite/x86_64_ie_to_le.sh | 29 ++++++
gold/x86_64.cc | 156 +++++++++++++++++++++++-------
8 files changed, 203 insertions(+), 37 deletions(-)
create mode 100644 gold/testsuite/x86_64_ie_to_le.s
create mode 100755 gold/testsuite/x86_64_ie_to_le.sh
diff --git a/elfcpp/x86_64.h b/elfcpp/x86_64.h
index 97a87ae424d..da6ac191734 100644
--- a/elfcpp/x86_64.h
+++ b/elfcpp/x86_64.h
@@ -102,6 +102,14 @@ enum
// GOT if the instruction starts at 4
// bytes before the relocation offset,
// relaxable.
+ R_X86_64_CODE_4_GOTTPOFF = 44, // 32 bit signed PC relative offset to
+ // GOT entry for IE symbol if the
+ // instruction starts at 4 bytes before
+ // the relocation offset.
+ R_X86_64_CODE_4_GOTPC32_TLSDESC = 45, // 32-bit PC relative to TLS
+ // descriptor in GOT if the
+ // instruction starts at 4 bytes
+ // before the relocation offset.
// GNU vtable garbage collection extensions.
R_X86_64_GNU_VTINHERIT = 250,
R_X86_64_GNU_VTENTRY = 251
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
index df9405c1aac..0685e917d0e 100644
--- a/gold/testsuite/Makefile.am
+++ b/gold/testsuite/Makefile.am
@@ -1244,6 +1244,17 @@ x86_64_gd_to_le: x86_64_gd_to_le.o gcctestdir/ld
x86_64_gd_to_le.stdout: x86_64_gd_to_le
$(TEST_OBJDUMP) -dw $< > $@
+check_SCRIPTS += x86_64_ie_to_le.sh
+check_DATA += x86_64_ie_to_le.stdout
+MOSTLYCLEANFILES += x86_64_ie_to_le
+
+x86_64_ie_to_le.o: x86_64_ie_to_le.s
+ $(TEST_AS) --64 -o $@ $<
+x86_64_ie_to_le: x86_64_ie_to_le.o gcctestdir/ld
+ gcctestdir/ld -o $@ $<
+x86_64_ie_to_le.stdout: x86_64_ie_to_le
+ $(TEST_OBJDUMP) -dw $< > $@
+
check_SCRIPTS += x86_64_overflow_pc32.sh
check_DATA += x86_64_overflow_pc32.err
MOSTLYCLEANFILES += x86_64_overflow_pc32.err
diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in
index ab48f07bca4..ffd4821b875 100644
--- a/gold/testsuite/Makefile.in
+++ b/gold/testsuite/Makefile.in
@@ -296,6 +296,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_31 = x86_64_mov_to_lea.sh \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_indirect_call_to_direct.sh \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_gd_to_le.sh \
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_ie_to_le.sh \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_overflow_pc32.sh \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x32_overflow_pc32.sh \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ pr23016_1.sh \
@@ -319,6 +320,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_indirect_call_to_direct1.stdout \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_indirect_jump_to_direct1.stdout \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_gd_to_le.stdout \
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_ie_to_le.stdout \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_overflow_pc32.err \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x32_overflow_pc32.err \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ pr23016_1.stdout \
@@ -343,6 +345,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_indirect_call_to_direct1 \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_indirect_jump_to_direct1 \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_gd_to_le \
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_ie_to_le \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x86_64_overflow_pc32.err \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ x32_overflow_pc32.err
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_34 = pr17704a_test
@@ -5747,6 +5750,13 @@ x86_64_gd_to_le.sh.log: x86_64_gd_to_le.sh
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
+x86_64_ie_to_le.sh.log: x86_64_ie_to_le.sh
+ @p='x86_64_ie_to_le.sh'; \
+ b='x86_64_ie_to_le.sh'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
x86_64_overflow_pc32.sh.log: x86_64_overflow_pc32.sh
@p='x86_64_overflow_pc32.sh'; \
b='x86_64_overflow_pc32.sh'; \
@@ -8485,6 +8495,13 @@ uninstall-am:
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -o $@ $<
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@x86_64_gd_to_le.stdout: x86_64_gd_to_le
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_OBJDUMP) -dw $< > $@
+
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@x86_64_ie_to_le.o: x86_64_ie_to_le.s
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AS) --64 -o $@ $<
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@x86_64_ie_to_le: x86_64_ie_to_le.o gcctestdir/ld
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -o $@ $<
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@x86_64_ie_to_le.stdout: x86_64_ie_to_le
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_OBJDUMP) -dw $< > $@
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@x86_64_overflow_pc32.o: x86_64_overflow_pc32.s
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AS) -o $@ $<
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@x86_64_overflow_pc32.err: x86_64_overflow_pc32.o gcctestdir/ld
diff --git a/gold/testsuite/x86_64_gd_to_le.s b/gold/testsuite/x86_64_gd_to_le.s
index dcdd303184d..79f9c48f526 100644
--- a/gold/testsuite/x86_64_gd_to_le.s
+++ b/gold/testsuite/x86_64_gd_to_le.s
@@ -7,6 +7,7 @@ _start:
subq $8, %rsp
.cfi_def_cfa_offset 16
leaq foo@TLSDESC(%rip), %r9
+ leaq foo@TLSDESC(%rip), %r29
movq %r9, %rax
call *foo@TLSCALL(%rax)
addq %fs:0, %rax
diff --git a/gold/testsuite/x86_64_gd_to_le.sh b/gold/testsuite/x86_64_gd_to_le.sh
index 82a6f985b88..5b0a043e0a8 100755
--- a/gold/testsuite/x86_64_gd_to_le.sh
+++ b/gold/testsuite/x86_64_gd_to_le.sh
@@ -24,3 +24,4 @@
set -e
grep -q "mov[ \t]\+\$0x[a-f0-9]\+,%r9" x86_64_gd_to_le.stdout
+grep -q "mov[ \t]\+\$0x[a-f0-9]\+,%r29" x86_64_gd_to_le.stdout
diff --git a/gold/testsuite/x86_64_ie_to_le.s b/gold/testsuite/x86_64_ie_to_le.s
new file mode 100644
index 00000000000..c5752068866
--- /dev/null
+++ b/gold/testsuite/x86_64_ie_to_le.s
@@ -0,0 +1,17 @@
+ .text
+ .p2align 4
+ .globl _start
+ .type _start, @function
+_start:
+ addq foo@gottpoff(%rip), %r12
+ movq foo@gottpoff(%rip), %rax
+ addq foo@gottpoff(%rip), %r16
+ movq foo@gottpoff(%rip), %r20
+ .size _start, .-_start
+ .section .tdata,"awT",@progbits
+ .align 4
+ .type foo, @object
+ .size foo, 4
+foo:
+ .long 30
+ .section .note.GNU-stack,"",@progbits
diff --git a/gold/testsuite/x86_64_ie_to_le.sh b/gold/testsuite/x86_64_ie_to_le.sh
new file mode 100755
index 00000000000..417f0bfc636
--- /dev/null
+++ b/gold/testsuite/x86_64_ie_to_le.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# x86_64_ie_to_le.sh -- a test for IE -> LE conversion.
+
+# Copyright (C) 2023 Free Software Foundation, Inc.
+
+# This file is part of gold.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+set -e
+
+grep -q "add[ \t]\+\$0x[a-f0-9]\+,%r12" x86_64_ie_to_le.stdout
+grep -q "mov[ \t]\+\$0x[a-f0-9]\+,%rax" x86_64_ie_to_le.stdout
+grep -q "add[ \t]\+\$0x[a-f0-9]\+,%r16" x86_64_ie_to_le.stdout
+grep -q "mov[ \t]\+\$0x[a-f0-9]\+,%r20" x86_64_ie_to_le.stdout
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index b7be9bf0d48..bc4260db5f3 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -1110,7 +1110,8 @@ class Target_x86_64 : public Sized_target<size, false>
// Adjust TLS relocation type based on the options and whether this
// is a local symbol.
static tls::Tls_optimization
- optimize_tls_reloc(bool is_final, int r_type);
+ optimize_tls_reloc(bool is_final, int r_type, size_t r_offset,
+ const unsigned char* reloc_view);
// Get the GOT section, creating it if necessary.
Output_data_got<64, false>*
@@ -2878,11 +2879,13 @@ Target_x86_64<size>::got_mod_index_entry(Symbol_table* symtab, Layout* layout,
// Optimize the TLS relocation type based on what we know about the
// symbol. IS_FINAL is true if the final address of this symbol is
-// known at link time.
+// known at link time. RELOC_VIEW points to the relocation offset.
template<int size>
tls::Tls_optimization
-Target_x86_64<size>::optimize_tls_reloc(bool is_final, int r_type)
+Target_x86_64<size>::optimize_tls_reloc(bool is_final, int r_type,
+ size_t r_offset,
+ const unsigned char* reloc_view)
{
// If we are generating a shared library, then we can't do anything
// in the linker.
@@ -2891,6 +2894,10 @@ Target_x86_64<size>::optimize_tls_reloc(bool is_final, int r_type)
switch (r_type)
{
+ case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC:
+ if (r_offset <= 4 || *(reloc_view - 4) != 0xd5)
+ return tls::TLSOPT_NONE;
+ // Fall through.
case elfcpp::R_X86_64_TLSGD:
case elfcpp::R_X86_64_GOTPC32_TLSDESC:
case elfcpp::R_X86_64_TLSDESC_CALL:
@@ -2913,6 +2920,10 @@ Target_x86_64<size>::optimize_tls_reloc(bool is_final, int r_type)
// Another Local-Dynamic reloc.
return tls::TLSOPT_TO_LE;
+ case elfcpp::R_X86_64_CODE_4_GOTTPOFF:
+ if (r_offset <= 4 || *(reloc_view - 4) != 0xd5)
+ return tls::TLSOPT_NONE;
+ // Fall through.
case elfcpp::R_X86_64_GOTTPOFF:
// These are Initial-Exec relocs which get the thread offset
// from the GOT. If we know that we are linking against the
@@ -2979,11 +2990,13 @@ Target_x86_64<size>::Scan::get_reference_flags(unsigned int r_type)
case elfcpp::R_X86_64_TLSGD: // Global-dynamic
case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url)
+ case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC:
case elfcpp::R_X86_64_TLSDESC_CALL:
case elfcpp::R_X86_64_TLSLD: // Local-dynamic
case elfcpp::R_X86_64_DTPOFF32:
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_TPOFF32: // Local-exec
return Symbol::TLS_REF;
@@ -3148,6 +3161,8 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
target->make_local_ifunc_plt_entry(symtab, layout, object, r_sym);
}
+ const unsigned char* reloc_view = NULL;
+
switch (r_type)
{
case elfcpp::R_X86_64_NONE:
@@ -3345,6 +3360,13 @@ need_got:
break;
// 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:
+ {
+ section_size_type stype;
+ reloc_view = object->section_contents(data_shndx, &stype, true);
+ }
+ // Fall through.
case elfcpp::R_X86_64_TLSGD: // Global-dynamic
case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url)
case elfcpp::R_X86_64_TLSDESC_CALL:
@@ -3355,9 +3377,11 @@ need_got:
case elfcpp::R_X86_64_TPOFF32: // Local-exec
{
bool output_is_shared = parameters->options().shared();
+ size_t r_offset = reloc.get_r_offset();
const tls::Tls_optimization optimized_type
= Target_x86_64<size>::optimize_tls_reloc(!output_is_shared,
- r_type);
+ r_type, r_offset,
+ reloc_view + r_offset);
switch (r_type)
{
case elfcpp::R_X86_64_TLSGD: // General-dynamic
@@ -3386,6 +3410,7 @@ need_got:
break;
case elfcpp::R_X86_64_GOTPC32_TLSDESC:
+ case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC:
target->define_tls_base_symbol(symtab, layout);
if (optimized_type == tls::TLSOPT_NONE)
{
@@ -3438,6 +3463,7 @@ need_got:
break;
case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
+ case elfcpp::R_X86_64_CODE_4_GOTTPOFF:
layout->set_has_static_tls();
if (optimized_type == tls::TLSOPT_NONE)
{
@@ -3615,6 +3641,8 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
&& this->reloc_needs_plt_for_ifunc(object, r_type))
target->make_plt_entry(symtab, layout, gsym);
+ const unsigned char *reloc_view = NULL;
+
switch (r_type)
{
case elfcpp::R_X86_64_NONE:
@@ -3872,6 +3900,13 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
break;
// 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:
+ {
+ section_size_type stype;
+ reloc_view = object->section_contents(data_shndx, &stype, true);
+ }
+ // Fall through.
case elfcpp::R_X86_64_TLSGD: // Global-dynamic
case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url)
case elfcpp::R_X86_64_TLSDESC_CALL:
@@ -3884,11 +3919,15 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
// For the Initial-Exec model, we can treat undef symbols as final
// 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_GOTTPOFF ||
+ r_type == elfcpp::R_X86_64_CODE_4_GOTTPOFF) &&
gsym->is_undefined() &&
parameters->options().output_is_executable()));
+ size_t r_offset = reloc.get_r_offset();
const tls::Tls_optimization optimized_type
- = Target_x86_64<size>::optimize_tls_reloc(is_final, r_type);
+ = Target_x86_64<size>::optimize_tls_reloc(is_final, r_type,
+ r_offset,
+ reloc_view + r_offset);
switch (r_type)
{
case elfcpp::R_X86_64_TLSGD: // General-dynamic
@@ -3917,6 +3956,7 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
break;
case elfcpp::R_X86_64_GOTPC32_TLSDESC:
+ case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC:
target->define_tls_base_symbol(symtab, layout);
if (optimized_type == tls::TLSOPT_NONE)
{
@@ -3965,6 +4005,7 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
break;
case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
+ case elfcpp::R_X86_64_CODE_4_GOTTPOFF:
layout->set_has_static_tls();
if (optimized_type == tls::TLSOPT_NONE)
{
@@ -4560,11 +4601,13 @@ Target_x86_64<size>::Relocate::relocate(
// These are initial tls relocs, which are expected when linking
case elfcpp::R_X86_64_TLSGD: // Global-dynamic
case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url)
+ case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC:
case elfcpp::R_X86_64_TLSDESC_CALL:
case elfcpp::R_X86_64_TLSLD: // Local-dynamic
case elfcpp::R_X86_64_DTPOFF32:
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_TPOFF32: // Local-exec
this->relocate_tls(relinfo, target, relnum, rela, r_type, gsym, psymval,
view, address, view_size);
@@ -4636,8 +4679,10 @@ Target_x86_64<size>::Relocate::relocate_tls(
const bool is_final = (gsym == NULL
? !parameters->options().shared()
: gsym->final_value_is_known());
+ size_t r_offset = rela.get_r_offset();
tls::Tls_optimization optimized_type
- = Target_x86_64<size>::optimize_tls_reloc(is_final, r_type);
+ = Target_x86_64<size>::optimize_tls_reloc(is_final, r_type,
+ r_offset, view);
switch (r_type)
{
case elfcpp::R_X86_64_TLSGD: // Global-dynamic
@@ -4704,6 +4749,7 @@ Target_x86_64<size>::Relocate::relocate_tls(
break;
case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url)
+ case elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC:
case elfcpp::R_X86_64_TLSDESC_CALL:
if (!is_executable && optimized_type == tls::TLSOPT_TO_LE)
{
@@ -4729,7 +4775,8 @@ Target_x86_64<size>::Relocate::relocate_tls(
? GOT_TYPE_TLS_OFFSET
: GOT_TYPE_TLS_DESC);
unsigned int got_offset = 0;
- if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC
+ if ((r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC
+ || r_type == elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC)
&& optimized_type == tls::TLSOPT_NONE)
{
// We created GOT entries in the .got.tlsdesc portion of
@@ -4760,7 +4807,8 @@ Target_x86_64<size>::Relocate::relocate_tls(
}
else if (optimized_type == tls::TLSOPT_NONE)
{
- if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC)
+ if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC
+ || r_type == elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC)
{
// Relocate the field with the offset of the pair of GOT
// entries.
@@ -4845,6 +4893,7 @@ Target_x86_64<size>::Relocate::relocate_tls(
break;
case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
+ case elfcpp::R_X86_64_CODE_4_GOTTPOFF:
if (gsym != NULL
&& gsym->is_undefined()
&& parameters->options().output_is_executable())
@@ -5051,7 +5100,8 @@ Target_x86_64<size>::Relocate::tls_desc_gd_to_ie(
typename elfcpp::Elf_types<size>::Elf_Addr address,
section_size_type view_size)
{
- if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC)
+ if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC
+ || r_type == elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC)
{
// LP64: leaq foo@tlsdesc(%rip), %rax
// ==> movq foo@gottpoff(%rip), %rax
@@ -5060,7 +5110,8 @@ Target_x86_64<size>::Relocate::tls_desc_gd_to_ie(
tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3);
tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4);
tls::check_tls(relinfo, relnum, rela.get_r_offset(),
- (((view[-3] & 0xfb) == 0x48
+ ((r_type == elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC
+ || (view[-3] & 0xfb) == 0x48
|| (size == 32 && (view[-3] & 0xfb) == 0x40))
&& view[-2] == 0x8d
&& (view[-1] & 0xc7) == 0x05));
@@ -5132,6 +5183,22 @@ Target_x86_64<size>::Relocate::tls_desc_gd_to_le(
value -= tls_segment->memsz();
Relocate_functions<size, false>::rela32(view, value, 0);
}
+ else if (r_type == elfcpp::R_X86_64_CODE_4_GOTPC32_TLSDESC)
+ {
+ // REX2: lea foo@tlsdesc(%rip), %reg
+ // ==> mov foo@tpoff, %reg
+ tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3);
+ tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4);
+ tls::check_tls(relinfo, relnum, rela.get_r_offset(),
+ (view[-2] == 0x8d
+ && (view[-1] & 0xc7) == 0x05));
+ unsigned char rex2_mask = 4 | 4 << 4;
+ view[-3] = (view[-3] & ~rex2_mask) | ((view[-3] & rex2_mask) >> 2);
+ view[-2] = 0xc7;
+ view[-1] = 0xc0 | ((view[-1] >> 3) & 7);
+ value -= tls_segment->memsz();
+ Relocate_functions<size, false>::rela32(view, value, 0);
+ }
else
{
// LP64: call *foo@tlscall(%rax)
@@ -5231,7 +5298,7 @@ Target_x86_64<size>::Relocate::tls_ie_to_le(
size_t relnum,
Output_segment* tls_segment,
const elfcpp::Rela<size, false>& rela,
- unsigned int,
+ unsigned int r_type,
typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
section_size_type view_size)
@@ -5250,35 +5317,50 @@ Target_x86_64<size>::Relocate::tls_ie_to_le(
unsigned char op3 = view[-1];
unsigned char reg = op3 >> 3;
- if (op2 == 0x8b)
+ if (r_type == elfcpp::R_X86_64_GOTTPOFF)
{
- // movq
- if (op1 == 0x4c)
- view[-3] = 0x49;
- else if (size == 32 && op1 == 0x44)
- view[-3] = 0x41;
- view[-2] = 0xc7;
- view[-1] = 0xc0 | reg;
- }
- else if (reg == 4)
- {
- // Special handling for %rsp.
- if (op1 == 0x4c)
- view[-3] = 0x49;
- else if (size == 32 && op1 == 0x44)
- view[-3] = 0x41;
- view[-2] = 0x81;
- view[-1] = 0xc0 | reg;
+ if (op2 == 0x8b)
+ {
+ // movq
+ if (op1 == 0x4c)
+ view[-3] = 0x49;
+ else if (size == 32 && op1 == 0x44)
+ view[-3] = 0x41;
+ view[-2] = 0xc7;
+ view[-1] = 0xc0 | reg;
+ }
+ else if (reg == 4)
+ {
+ // Special handling for %rsp.
+ if (op1 == 0x4c)
+ view[-3] = 0x49;
+ else if (size == 32 && op1 == 0x44)
+ view[-3] = 0x41;
+ view[-2] = 0x81;
+ view[-1] = 0xc0 | reg;
+ }
+ else
+ {
+ // addq
+ if (op1 == 0x4c)
+ view[-3] = 0x4d;
+ else if (size == 32 && op1 == 0x44)
+ view[-3] = 0x45;
+ view[-2] = 0x8d;
+ view[-1] = 0x80 | reg | (reg << 3);
+ }
}
else
{
- // addq
- if (op1 == 0x4c)
- view[-3] = 0x4d;
- else if (size == 32 && op1 == 0x44)
- view[-3] = 0x45;
- view[-2] = 0x8d;
- view[-1] = 0x80 | reg | (reg << 3);
+ if (op2 == 0x8b)
+ op2 = 0xc7;
+ else
+ op2 = 0x81;
+
+ unsigned char rex2_mask = 4 | 4 << 4;
+ view[-3] = (view[-3] & ~rex2_mask) | ((view[-3] & rex2_mask) >> 2);
+ view[-2] = op2;
+ view[-1] = 0xc0 | reg;
}
if (tls_segment != NULL)
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 0/4] Support APX relocations
2023-12-28 14:58 [PATCH 0/4] Support APX relocations H.J. Lu
` (3 preceding siblings ...)
2023-12-28 14:58 ` [PATCH 4/4] Gold: Handle R_X86_64_CODE_4_GOTPC32_TLSDESC/R_X86_64_CODE_4_GOTTPOFF H.J. Lu
@ 2023-12-28 16:57 ` H.J. Lu
4 siblings, 0 replies; 6+ messages in thread
From: H.J. Lu @ 2023-12-28 16:57 UTC (permalink / raw)
To: binutils
On Thu, Dec 28, 2023 at 6:58 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> Implement 3 APX relocations in ld and gold:
>
> #define R_X86_64_CODE_4_GOTPCRELX 43
> #define R_X86_64_CODE_4_GOTTPOFF 44
> #define R_X86_64_CODE_4_GOTPC32_TLSDESC 45
>
> H.J. Lu (4):
> x86-64: Add R_X86_64_CODE_4_GOTPCRELX
> gold: Handle R_X86_64_CODE_4_GOTPCRELX
> x86-64: Add R_X86_64_CODE_4_GOTTPOFF/R_X86_64_CODE_4_GOTPC32_TLSDESC
> Gold: Handle R_X86_64_CODE_4_GOTPC32_TLSDESC/R_X86_64_CODE_4_GOTTPOFF
>
> bfd/bfd-in2.h | 3 +
> bfd/elf64-x86-64.c | 196 ++++++++++++++++--
> bfd/libbfd.h | 3 +
> bfd/reloc.c | 6 +
> elfcpp/x86_64.h | 14 +-
> gas/config/tc-i386.c | 38 +++-
> gas/config/tc-i386.h | 6 +-
> .../gas/i386/ilp32/x86-64-localpic.d | 4 +-
> gas/testsuite/gas/i386/x86-64-gotpcrel.d | 12 ++
> gas/testsuite/gas/i386/x86-64-gotpcrel.s | 19 ++
> gas/testsuite/gas/i386/x86-64-gottpoff.d | 19 ++
> gas/testsuite/gas/i386/x86-64-gottpoff.s | 15 ++
> gas/testsuite/gas/i386/x86-64-localpic.d | 4 +-
> gas/testsuite/gas/i386/x86-64-localpic.s | 2 +
> gas/testsuite/gas/i386/x86-64-tlsdesc.d | 17 ++
> gas/testsuite/gas/i386/x86-64-tlsdesc.s | 13 ++
> gas/testsuite/gas/i386/x86-64.exp | 3 +
> gas/write.h | 3 +-
> gold/testsuite/Makefile.am | 11 +
> gold/testsuite/Makefile.in | 17 ++
> gold/testsuite/x86_64_gd_to_le.s | 1 +
> gold/testsuite/x86_64_gd_to_le.sh | 1 +
> gold/testsuite/x86_64_ie_to_le.s | 17 ++
> gold/testsuite/x86_64_ie_to_le.sh | 29 +++
> gold/testsuite/x86_64_mov_to_lea.sh | 16 ++
> gold/testsuite/x86_64_mov_to_lea1.s | 1 +
> gold/testsuite/x86_64_mov_to_lea2.s | 1 +
> gold/testsuite/x86_64_mov_to_lea3.s | 1 +
> gold/testsuite/x86_64_mov_to_lea4.s | 1 +
> gold/testsuite/x86_64_mov_to_lea5.s | 1 +
> gold/x86_64.cc | 193 +++++++++++++----
> include/elf/x86-64.h | 12 +-
> ld/testsuite/ld-x86-64/apx-load1.s | 51 +++++
> ld/testsuite/ld-x86-64/apx-load1a.d | 54 +++++
> ld/testsuite/ld-x86-64/apx-load1b.d | 55 +++++
> ld/testsuite/ld-x86-64/apx-load1c.d | 47 +++++
> ld/testsuite/ld-x86-64/apx-load1d.d | 47 +++++
> ld/testsuite/ld-x86-64/tlsbindesc.dd | 49 +++++
> ld/testsuite/ld-x86-64/tlsbindesc.rd | 36 ++--
> ld/testsuite/ld-x86-64/tlsbindesc.s | 39 ++++
> ld/testsuite/ld-x86-64/x86-64.exp | 4 +
> 41 files changed, 967 insertions(+), 94 deletions(-)
> create mode 100644 gas/testsuite/gas/i386/x86-64-gottpoff.d
> create mode 100644 gas/testsuite/gas/i386/x86-64-gottpoff.s
> create mode 100644 gas/testsuite/gas/i386/x86-64-tlsdesc.d
> create mode 100644 gas/testsuite/gas/i386/x86-64-tlsdesc.s
> create mode 100644 gold/testsuite/x86_64_ie_to_le.s
> create mode 100755 gold/testsuite/x86_64_ie_to_le.sh
> create mode 100644 ld/testsuite/ld-x86-64/apx-load1.s
> create mode 100644 ld/testsuite/ld-x86-64/apx-load1a.d
> create mode 100644 ld/testsuite/ld-x86-64/apx-load1b.d
> create mode 100644 ld/testsuite/ld-x86-64/apx-load1c.d
> create mode 100644 ld/testsuite/ld-x86-64/apx-load1d.d
>
> --
> 2.43.0
>
I will check them in shortly.
--
H.J.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2023-12-28 16:58 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-28 14:58 [PATCH 0/4] Support APX relocations H.J. Lu
2023-12-28 14:58 ` [PATCH 1/4] x86-64: Add R_X86_64_CODE_4_GOTPCRELX H.J. Lu
2023-12-28 14:58 ` [PATCH 2/4] gold: Handle R_X86_64_CODE_4_GOTPCRELX H.J. Lu
2023-12-28 14:58 ` [PATCH 3/4] x86-64: Add R_X86_64_CODE_4_GOTTPOFF/R_X86_64_CODE_4_GOTPC32_TLSDESC H.J. Lu
2023-12-28 14:58 ` [PATCH 4/4] Gold: Handle R_X86_64_CODE_4_GOTPC32_TLSDESC/R_X86_64_CODE_4_GOTTPOFF H.J. Lu
2023-12-28 16:57 ` [PATCH 0/4] Support APX relocations H.J. Lu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).