[2/2] x86-64: tighten convert-load-reloc checking
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_binutils_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_binutils_check--master-arm |
success
|
Test passed
|
Commit Message
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).
---
The use of "abs_relocation" as an if() condition (just outside of lower
patch context) is highly questionable: The value of a symbol doesn't
express whether a symbol is absolute. In fact this way non-absolute
symbols also undergo the respective range check. Whereas at the same
time absolute symbols coming from the linker script or the --defsym
command line option aren't checked (because of what ABS_SYMBOL_P()
expands to). However, changing this breaks the pr19609-6a linker
testcase, as the way ABS_SYMBOL_P() works the range checking would then
be skipped, while later on when the relocation is processed it would
overflow.
@@ -2223,13 +2223,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. */
@@ -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
@@ -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
@@ -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"