[binutils-gdb] ix86: tighten convert-load-reloc checking

Jan Beulich jbeulich@sourceware.org
Fri Feb 21 09:27:02 GMT 2025


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

commit e6dc09203871c81f83e15f59640e865bcee4f760
Author: Jan Beulich <jbeulich@suse.com>
Date:   Fri Feb 21 10:22:50 2025 +0100

    ix86: tighten convert-load-reloc checking
    
    Just like was done recently for x86-64 (commit 4998f9ea9d35): Even if
    the assembler avoids using the relaxable relocation for inapplicable
    insns, the relocation type 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/elf32-i386.c              |  9 +++++----
 ld/testsuite/ld-i386/i386.exp |  1 +
 ld/testsuite/ld-i386/load8.d  | 14 ++++++++++++++
 ld/testsuite/ld-i386/load8.s  | 21 +++++++++++++++++++++
 4 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 78ca74e2472..ca82016fafc 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1453,15 +1453,16 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
 		  modrm = 0xc0 | (modrm & 0x38) >> 3;
 		  opcode = 0xf7;
 		}
-	      else
+	      else if ((opcode | 0x38) == 0x3b)
 		{
 		  /* Convert "binop foo@GOT(%reg1), %reg2" to
 		     "binop $foo, %reg2".  */
-		  modrm = (0xc0
-			   | (modrm & 0x38) >> 3
-			   | (opcode & 0x3c));
+		  modrm = 0xc0 | ((modrm & 0x38) >> 3) | (opcode & 0x38);
 		  opcode = 0x81;
 		}
+	      else
+		return true;
+
 	      bfd_put_8 (abfd, modrm, contents + roff - 1);
 	      r_type = R_386_32;
 	    }
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index 16b9fb87e21..f84b4d4fe59 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -373,6 +373,7 @@ run_dump_test "load5a"
 run_dump_test "load5b"
 run_dump_test "load6"
 run_dump_test "load7"
+run_dump_test "load8"
 run_dump_test "pr19175"
 run_dump_test "pr19615"
 run_dump_test "pr19636-1a"
diff --git a/ld/testsuite/ld-i386/load8.d b/ld/testsuite/ld-i386/load8.d
new file mode 100644
index 00000000000..c114721c5ab
--- /dev/null
+++ b/ld/testsuite/ld-i386/load8.d
@@ -0,0 +1,14 @@
+#as: --32 -mrelax-relocations=yes
+#ld: -melf_i386 -z noseparate-code
+#objdump: -dw
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+8048074 <_start>:
+[ 	]*[a-f0-9]+:	12 05 90 90 04 08    	adc    0x8049090,%al
+[ 	]*[a-f0-9]+:	6b 05 90 90 04 08 01 	imul   \$(0x)?1,0x8049090,%eax
+[ 	]*[a-f0-9]+:	84 35 90 90 04 08    	test   %dh,0x8049090
+[ 	]*[a-f0-9]+:	87 05 90 90 04 08    	xchg   %eax,0x8049090
+#pass
diff --git a/ld/testsuite/ld-i386/load8.s b/ld/testsuite/ld-i386/load8.s
new file mode 100644
index 00000000000..87131f9156a
--- /dev/null
+++ b/ld/testsuite/ld-i386/load8.s
@@ -0,0 +1,21 @@
+	.data
+	.type	bar, @object
+bar:
+	.byte	1
+	.size	bar, .-bar
+
+	.text
+	.globl	_start
+	.type	_start, @function
+_start:
+	# Other insns must not be accidentally transformed.
+	adc	0, %al
+	.reloc .-4, R_386_GOT32X, bar
+	imul	$1, 0, %eax
+	.reloc .-5, R_386_GOT32X, bar
+	test	%dh, 0
+	.reloc .-4, R_386_GOT32X, bar
+	xchg	0, %eax
+	.reloc .-4, R_386_GOT32X, bar
+
+	.size	_start, .-_start


More information about the Binutils-cvs mailing list