]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
x86-64: tighten convert-load-reloc checking
authorJan Beulich <jbeulich@suse.com>
Fri, 24 Jan 2025 09:26:46 +0000 (10:26 +0100)
committerJan Beulich <jbeulich@suse.com>
Fri, 24 Jan 2025 09:26:46 +0000 (10:26 +0100)
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
ld/testsuite/ld-x86-64/load4.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/load4.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/x86-64.exp

index 93b9ae9b5bdccb58a1f988acf38d86232d6140ce..d1d02bd7b32f582a78a47c5c18e4d7f343a5c706 100644 (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.  */
diff --git a/ld/testsuite/ld-x86-64/load4.d b/ld/testsuite/ld-x86-64/load4.d
new file mode 100644 (file)
index 0000000..190205e
--- /dev/null
@@ -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 (file)
index 0000000..f3fa1b1
--- /dev/null
@@ -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
index 94cf9aa1a7dfeaaf0e8a77e63064dda7b72a8629..48a468814c135287c6a37b21e0a9f479d6362d83 100644 (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"