[lld] r299553 - Fix PLT and GOTPLT entries for 32-bit x86 PIC.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 5 09:01:33 PDT 2017


Author: ruiu
Date: Wed Apr  5 11:01:33 2017
New Revision: 299553

URL: http://llvm.org/viewvc/llvm-project?rev=299553&view=rev
Log:
Fix PLT and GOTPLT entries for 32-bit x86 PIC.

Previously, the code we set to our .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.

Differential Revision: https://reviews.llvm.org/D31682

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

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=299553&r1=299552&r2=299553&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Wed Apr  5 11:01:33 2017
@@ -444,30 +444,33 @@ bool X86TargetInfo::isTlsInitialExecRel(
 }
 
 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);
+  uint32_t GotPlt = In<ELF32LE>::GotPlt->getVA();
+  write32le(Buf + 2, GotPlt + 4);
+  write32le(Buf + 8, GotPlt + 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 @@ void X86TargetInfo::writePlt(uint8_t *Bu
   };
   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);
 }

Modified: lld/trunk/test/ELF/plt-i686.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/plt-i686.s?rev=299553&r1=299552&r2=299553&view=diff
==============================================================================
--- lld/trunk/test/ELF/plt-i686.s (original)
+++ lld/trunk/test/ELF/plt-i686.s Wed Apr  5 11:01:33 2017
@@ -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




More information about the llvm-commits mailing list