[PATCH] D31682: Fix PLT and GOTPLT entries for x86 PIC.

Rui Ueyama via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 4 15:21:25 PDT 2017


ruiu created this revision.
Herald added a subscriber: emaste.

Previously, the code we set to our .got.plt entries expected that
.got and .got.plt are consecutive in the virtual address space.
Since %ebx points to the last entry of .got for position-independent
code, it assumed that .got is accessible with small negative
displacements and .got.plt are accessible with small positive
displacements.

That assumption was simply wrong. We don't impose any restrictions on
relative layout of .got and .got.plt. As a result, the control is
transferred to a bogus address from .plt at runtime, which resulted in
segfaults.

This patch removes that wrong assumption. We still assume that .got.plt
has a fixed relative address to .got, but we no longer assume that they
are consecutive in memory.

With this change, a "hello world" program compiled with -fPIC works.

Fixes https://bugs.llvm.org/show_bug.cgi?id=31332.


https://reviews.llvm.org/D31682

Files:
  lld/ELF/Target.cpp
  lld/test/ELF/plt-i686.s


Index: lld/test/ELF/plt-i686.s
===================================================================
--- lld/test/ELF/plt-i686.s
+++ lld/test/ELF/plt-i686.s
@@ -135,23 +135,23 @@
 // DISASMSHARED-NEXT:  1013: e9 e8 ff ff ff jmp -24
 // DISASMSHARED-NEXT:  Disassembly of section .plt:
 // DISASMSHARED-NEXT:  .plt:
-// DISASMSHARED-NEXT:  1020: ff b3 04 00 00 00  pushl 4(%ebx)
-// DISASMSHARED-NEXT:  1026: ff a3 08 00 00 00  jmpl *8(%ebx)
+// DISASMSHARED-NEXT:  1020: ff b3 04 20 00 00 pushl 8196(%ebx)
+// DISASMSHARED-NEXT:  1026: ff a3 08 20 00 00 jmpl *8200(%ebx)
 // DISASMSHARED-NEXT:  102c: 90 nop
 // DISASMSHARED-NEXT:  102d: 90 nop
 // DISASMSHARED-NEXT:  102e: 90 nop
 // DISASMSHARED-NEXT:  102f: 90 nop
-// DISASMSHARED-NEXT:  1030: ff a3 0c 00 00 00  jmpl *12(%ebx)
+// DISASMSHARED-NEXT:  1030: ff a3 0c 20 00 00 jmpl *8204(%ebx)
 // DISASMSHARED-NEXT:  1036: 68 00 00 00 00     pushl $0
 // DISASMSHARED-NEXT:  103b: e9 e0 ff ff ff     jmp -32 <.plt>
-// DISASMSHARED-NEXT:  1040: ff a3 10 00 00 00  jmpl *16(%ebx)
+// DISASMSHARED-NEXT:  1040: ff a3 10 20 00 00 jmpl *8208(%ebx)
 // DISASMSHARED-NEXT:  1046: 68 08 00 00 00     pushl $8
 // DISASMSHARED-NEXT:  104b: e9 d0 ff ff ff     jmp -48 <.plt>
 
 // DISASMPIE:      Disassembly of section .plt:
 // DISASMPIE-NEXT: .plt:
-// DISASMPIE-NEXT:   1020:	ff b3 04 00 00 00 pushl 4(%ebx)
-// DISASMPIE-NEXT:   1026:	ff a3 08 00 00 00 jmpl *8(%ebx)
+// DISASMPIE-NEXT:   1020:	ff b3 04 20 00 00 pushl 8196(%ebx)
+// DISASMPIE-NEXT:   1026:	ff a3 08 20 00 00 jmpl *8200(%ebx)
 // DISASMPIE-NEXT:   102c:	90 nop
 // DISASMPIE-NEXT:   102d:	90 nop
 // DISASMPIE-NEXT:   102e:	90 nop
Index: lld/ELF/Target.cpp
===================================================================
--- lld/ELF/Target.cpp
+++ lld/ELF/Target.cpp
@@ -444,30 +444,33 @@
 }
 
 void X86TargetInfo::writePltHeader(uint8_t *Buf) const {
-  // Executable files and shared object files have
-  // separate procedure linkage tables.
   if (Config->Pic) {
     const uint8_t V[] = {
         0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl 4(%ebx)
         0xff, 0xa3, 0x08, 0x00, 0x00, 0x00, // jmp   *8(%ebx)
-        0x90, 0x90, 0x90, 0x90              // nop; nop; nop; nop
+        0x90, 0x90, 0x90, 0x90              // nop
     };
     memcpy(Buf, V, sizeof(V));
+
+    uint32_t Ebx = In<ELF32LE>::Got->getVA() + In<ELF32LE>::Got->getSize();
+    uint32_t GotPlt = In<ELF32LE>::GotPlt->getVA() - Ebx;
+    write32le(Buf + 2, GotPlt + 4);
+    write32le(Buf + 8, GotPlt + 8);
     return;
   }
 
   const uint8_t PltData[] = {
       0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushl (GOT+4)
       0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp   *(GOT+8)
-      0x90, 0x90, 0x90, 0x90              // nop; nop; nop; nop
+      0x90, 0x90, 0x90, 0x90              // nop
   };
   memcpy(Buf, PltData, sizeof(PltData));
   uint32_t Got = In<ELF32LE>::GotPlt->getVA();
   write32le(Buf + 2, Got + 4);
   write32le(Buf + 8, Got + 8);
 }
 
-void X86TargetInfo::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
+void X86TargetInfo::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
                              uint64_t PltEntryAddr, int32_t Index,
                              unsigned RelOff) const {
   const uint8_t Inst[] = {
@@ -477,10 +480,17 @@
   };
   memcpy(Buf, Inst, sizeof(Inst));
 
-  // jmp *foo at GOT(%ebx) or jmp *foo_in_GOT
-  Buf[1] = Config->Pic ? 0xa3 : 0x25;
-  uint32_t Got = In<ELF32LE>::GotPlt->getVA();
-  write32le(Buf + 2, Config->Shared ? GotEntryAddr - Got : GotEntryAddr);
+  if (Config->Pic) {
+    // jmp *foo at GOT(%ebx)
+    uint32_t Ebx = In<ELF32LE>::Got->getVA() + In<ELF32LE>::Got->getSize();
+    Buf[1] = 0xa3;
+    write32le(Buf + 2, GotPltEntryAddr - Ebx);
+  } else {
+    // jmp *foo_in_GOT
+    Buf[1] = 0x25;
+    write32le(Buf + 2, GotPltEntryAddr);
+  }
+
   write32le(Buf + 7, RelOff);
   write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16);
 }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D31682.94130.patch
Type: text/x-patch
Size: 3923 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170404/3bd07bcc/attachment.bin>


More information about the llvm-commits mailing list