x86-64: tighten convert-load-reloc checking

Even if the assembler avoids using relaxable relocations for
inapplicable insns, such relocations can still appear for other reasons.
Be more thorough in the opcode checking we do, to avoid bogusly altering
other insns.

Furthermore correct an opcode mask (even if with the added condition
that's now fully benign).
This commit is contained in:
Jan Beulich
2025-01-24 10:26:46 +01:00
parent 6a7a2387ad
commit 4998f9ea9d
4 changed files with 41 additions and 2 deletions

View File

@@ -2222,13 +2222,15 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
modrm = 0xc0 | (modrm & 0x38) >> 3;
opcode = 0xf7;
}
else
else if ((opcode | 0x38) == 0x3b)
{
/* Convert "binop foo@GOTPCREL(%rip), %reg" to
"binop $foo, %reg". */
modrm = 0xc0 | (modrm & 0x38) >> 3 | (opcode & 0x3c);
modrm = 0xc0 | ((modrm & 0x38) >> 3) | (opcode & 0x38);
opcode = 0x81;
}
else
return true;
/* Use R_X86_64_32 with 32-bit operand to avoid relocation
overflow when sign-extending imm32 to imm64. */

View File

@@ -0,0 +1,13 @@
#as: --64 -mrelax-relocations=yes
#ld: -melf_x86_64 -z max-page-size=0x200000 -z noseparate-code
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
0+4000b0 <_start>:
[ ]*[a-f0-9]+: 12 05 ([0-9a-f]{2} ){4} * adc 0x[a-f0-9]+\(%rip\),%al # 6000c8 <.*>
[ ]*[a-f0-9]+: 44 84 3d ([0-9a-f]{2} ){4} * test %r15b,0x[a-f0-9]+\(%rip\) # 6000c8 <.*>
[ ]*[a-f0-9]+: 48 87 05 ([0-9a-f]{2} ){4} * xchg %rax,0x[a-f0-9]+\(%rip\) # 6000c8 <.*>
#pass

View File

@@ -0,0 +1,23 @@
.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:
# Other insns must not be accidentally transformed.
adc 1f(%rip), %al
1: .reloc .-4, R_X86_64_GOTPCRELX, bar-4
test %r15b, 1f(%rip)
1: .reloc .-4, R_X86_64_REX_GOTPCRELX, bar-4
xchg 1f(%rip), %rax
1: .reloc .-4, R_X86_64_REX_GOTPCRELX, bar-4
.size _start, .-_start

View File

@@ -653,6 +653,7 @@ run_dump_test "apx-load1d"
run_dump_test "load2"
run_dump_test "load3a"
run_dump_test "load3b"
run_dump_test "load4"
run_dump_test "call1a"
run_dump_test "call1b"
run_dump_test "call1c"