[binutils-gdb] x86-64: tighten convert-load-reloc checking

Jan Beulich jbeulich@sourceware.org
Fri Jan 24 09:27:57 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=4998f9ea9d351d546f317af80e054a5d615edaae

commit 4998f9ea9d351d546f317af80e054a5d615edaae
Author: Jan Beulich <jbeulich@suse.com>
Date:   Fri Jan 24 10:26:46 2025 +0100

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

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

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"


More information about the Binutils-cvs mailing list