[lld] r270721 - [ELF] - Added support for jmp/call relaxations when R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX are used.
George Rimar via llvm-commits
llvm-commits at lists.llvm.org
Wed May 25 09:51:12 PDT 2016
Author: grimar
Date: Wed May 25 11:51:08 2016
New Revision: 270721
URL: http://llvm.org/viewvc/llvm-project?rev=270721&view=rev
Log:
[ELF] - Added support for jmp/call relaxations when R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX are used.
D15779 introduced basic approach to support new relaxations.
This patch implements relaxations for jmp and call instructions,
described in System V Application Binary Interface AMD64 Architecture Processor
Supplement Draft Version 0.99.8 (https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-r249.pdf,
B.2 "B.2 Optimize GOTPCRELX Relocations")
Differential revision: http://reviews.llvm.org/D20622
Modified:
lld/trunk/ELF/Target.cpp
lld/trunk/test/ELF/gotpc-relax.s
Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=270721&r1=270720&r2=270721&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Wed May 25 11:51:08 2016
@@ -740,14 +740,42 @@ bool X86_64TargetInfo::canRelaxGot(uint3
uint64_t Offset) const {
if (Type != R_X86_64_GOTPCRELX && Type != R_X86_64_REX_GOTPCRELX)
return false;
-
- // Converting mov foo at GOTPCREL(%rip), %reg to lea foo(%rip), %reg
- // is the only supported relaxation for now.
- return (Offset >= 2 && Data[Offset - 2] == 0x8b);
+ const uint8_t Op = Data[Offset - 2];
+ const uint8_t ModRm = Data[Offset - 1];
+ // Relax mov.
+ if (Op == 0x8b)
+ return true;
+ // Relax call and jmp.
+ return Op == 0xff && (ModRm == 0x15 || ModRm == 0x25);
}
void X86_64TargetInfo::relaxGot(uint8_t *Loc, uint64_t Val) const {
- Loc[-2] = 0x8d;
+ const uint8_t Op = Loc[-2];
+ const uint8_t ModRm = Loc[-1];
+
+ // Convert mov foo at GOTPCREL(%rip), %reg to lea foo(%rip), %reg.
+ if (Op == 0x8b) {
+ *(Loc - 2) = 0x8d;
+ relocateOne(Loc, R_X86_64_PC32, Val);
+ return;
+ }
+
+ assert(Op == 0xff);
+ if (ModRm == 0x15) {
+ // ABI says we can convert call *foo at GOTPCREL(%rip) to nop call foo.
+ // Instead we convert to addr32 call foo, where addr32 is instruction
+ // prefix. That makes result expression to be a single instruction.
+ *(Loc - 2) = 0x67; // addr32 prefix
+ *(Loc - 1) = 0xe8; // call
+ } else {
+ assert(ModRm == 0x25);
+ // Convert jmp *foo at GOTPCREL(%rip) to jmp foo nop.
+ // jmp doesn't return, so it is fine to use nop here, it is just a stub.
+ *(Loc - 2) = 0xe9; // jmp
+ *(Loc + 3) = 0x90; // nop
+ Loc -= 1;
+ Val += 1;
+ }
relocateOne(Loc, R_X86_64_PC32, Val);
}
Modified: lld/trunk/test/ELF/gotpc-relax.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/gotpc-relax.s?rev=270721&r1=270720&r2=270721&view=diff
==============================================================================
--- lld/trunk/test/ELF/gotpc-relax.s (original)
+++ lld/trunk/test/ELF/gotpc-relax.s Wed May 25 11:51:08 2016
@@ -32,8 +32,22 @@
# DISASM-NEXT: 1103f: 8d 05 bc ff ff ff leal -68(%rip), %eax
# DISASM-NEXT: 11045: 8b 05 b5 0f 00 00 movl 4021(%rip), %eax
# DISASM-NEXT: 1104b: 8b 05 af 0f 00 00 movl 4015(%rip), %eax
-# DISASM-NEXT: 11051: ff 15 b1 0f 00 00 callq *4017(%rip)
-# DISASM-NEXT: 11057: ff 25 a3 0f 00 00 jmpq *4003(%rip)
+# DISASM-NEXT: 11051: 67 e8 a9 ff ff ff callq -87 <foo>
+# DISASM-NEXT: 11057: 67 e8 a3 ff ff ff callq -93 <foo>
+# DISASM-NEXT: 1105d: 67 e8 9e ff ff ff callq -98 <hid>
+# DISASM-NEXT: 11063: 67 e8 98 ff ff ff callq -104 <hid>
+# DISASM-NEXT: 11069: ff 15 91 0f 00 00 callq *3985(%rip)
+# DISASM-NEXT: 1106f: ff 15 8b 0f 00 00 callq *3979(%rip)
+# DISASM-NEXT: 11075: e9 86 ff ff ff jmp -122 <foo>
+# DISASM-NEXT: 1107a: 90 nop
+# DISASM-NEXT: 1107b: e9 80 ff ff ff jmp -128 <foo>
+# DISASM-NEXT: 11080: 90 nop
+# DISASM-NEXT: 11081: e9 7b ff ff ff jmp -133 <hid>
+# DISASM-NEXT: 11086: 90 nop
+# DISASM-NEXT: 11087: e9 75 ff ff ff jmp -139 <hid>
+# DISASM-NEXT: 1108c: 90 nop
+# DISASM-NEXT: 1108d: ff 25 6d 0f 00 00 jmpq *3949(%rip)
+# DISASM-NEXT: 11093: ff 25 67 0f 00 00 jmpq *3943(%rip)
.text
.globl foo
@@ -70,7 +84,15 @@ _start:
movl ifunc at GOTPCREL(%rip), %eax
movl ifunc at GOTPCREL(%rip), %eax
-## We check few other possible instructions
-## to see that they are not "relaxed" by mistake to lea.
call *foo at GOTPCREL(%rip)
+ call *foo at GOTPCREL(%rip)
+ call *hid at GOTPCREL(%rip)
+ call *hid at GOTPCREL(%rip)
+ call *ifunc at GOTPCREL(%rip)
+ call *ifunc at GOTPCREL(%rip)
+ jmp *foo at GOTPCREL(%rip)
+ jmp *foo at GOTPCREL(%rip)
+ jmp *hid at GOTPCREL(%rip)
+ jmp *hid at GOTPCREL(%rip)
+ jmp *ifunc at GOTPCREL(%rip)
jmp *ifunc at GOTPCREL(%rip)
More information about the llvm-commits
mailing list