[PATCH] D20622: [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:57:45 PDT 2016


This revision was automatically updated to reflect the committed changes.
grimar marked 2 inline comments as done.
Closed by commit rL270721: [ELF] - Added support for jmp/call relaxations when… (authored by grimar).

Changed prior to commit:
  http://reviews.llvm.org/D20622?vs=58442&id=58446#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D20622

Files:
  lld/trunk/ELF/Target.cpp
  lld/trunk/test/ELF/gotpc-relax.s

Index: lld/trunk/ELF/Target.cpp
===================================================================
--- lld/trunk/ELF/Target.cpp
+++ lld/trunk/ELF/Target.cpp
@@ -740,14 +740,42 @@
                                    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);
 }
 
Index: lld/trunk/test/ELF/gotpc-relax.s
===================================================================
--- lld/trunk/test/ELF/gotpc-relax.s
+++ lld/trunk/test/ELF/gotpc-relax.s
@@ -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 @@
  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)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D20622.58446.patch
Type: text/x-patch
Size: 3701 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160525/a9ade02b/attachment.bin>


More information about the llvm-commits mailing list