From 4998f9ea9d351d546f317af80e054a5d615edaae Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 24 Jan 2025 10:26:46 +0100 Subject: [PATCH] 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). --- bfd/elf64-x86-64.c | 6 ++++-- ld/testsuite/ld-x86-64/load4.d | 13 +++++++++++++ ld/testsuite/ld-x86-64/load4.s | 23 +++++++++++++++++++++++ ld/testsuite/ld-x86-64/x86-64.exp | 1 + 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 ld/testsuite/ld-x86-64/load4.d create mode 100644 ld/testsuite/ld-x86-64/load4.s diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 93b9ae9b5bd..d1d02bd7b32 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -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. */ diff --git a/ld/testsuite/ld-x86-64/load4.d b/ld/testsuite/ld-x86-64/load4.d new file mode 100644 index 00000000000..190205e8167 --- /dev/null +++ b/ld/testsuite/ld-x86-64/load4.d @@ -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 diff --git a/ld/testsuite/ld-x86-64/load4.s b/ld/testsuite/ld-x86-64/load4.s new file mode 100644 index 00000000000..f3fa1b11b73 --- /dev/null +++ b/ld/testsuite/ld-x86-64/load4.s @@ -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 diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 94cf9aa1a7d..48a468814c1 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -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" -- 2.39.5