[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 08:01:43 PDT 2016


grimar created this revision.
grimar added reviewers: rafael, ruiu.
grimar added subscribers: llvm-commits, grimar.

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")



http://reviews.llvm.org/D20622

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

Index: test/ELF/gotpc-relax.s
===================================================================
--- test/ELF/gotpc-relax.s
+++ 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)
Index: ELF/Target.cpp
===================================================================
--- ELF/Target.cpp
+++ ELF/Target.cpp
@@ -740,14 +740,39 @@
                                    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];
+
+  if (Op == 0x8b) {
+    // Convert mov foo at GOTPCREL(%rip), %reg to lea foo(%rip), %reg.
+    *(Loc - 2) = 0x8d;
+  } else if (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 {
+      // ModRm == 0x25.
+      // Convert jmp *foo at GOTPCREL(%rip) to jmp foo nop.
+      *(Loc - 2) = 0xe9; // jmp
+      *(Loc + 3) = 0x90; // nop
+      Loc -= 1;
+      Val += 1;
+    }
+  }
+
   relocateOne(Loc, R_X86_64_PC32, Val);
 }
 


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


More information about the llvm-commits mailing list