summaryrefslogtreecommitdiffstats
path: root/lld
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2017-04-05 16:01:33 +0000
committerRui Ueyama <ruiu@google.com>2017-04-05 16:01:33 +0000
commit9c766d7a397b652b5a04c6acff16b1473a3c8838 (patch)
treeeb343629064f782053d9dcc5eaf5057e28fe721b /lld
parentaa65a2beb875e2bbe2c1b71ea3bf648d35101469 (diff)
downloadbcm5719-llvm-9c766d7a397b652b5a04c6acff16b1473a3c8838.tar.gz
bcm5719-llvm-9c766d7a397b652b5a04c6acff16b1473a3c8838.zip
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 llvm-svn: 299553
Diffstat (limited to 'lld')
-rw-r--r--lld/ELF/Target.cpp34
-rw-r--r--lld/test/ELF/plt-i686.s12
2 files changed, 28 insertions, 18 deletions
diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp
index 399c5da11fc..18f05d12a64 100644
--- a/lld/ELF/Target.cpp
+++ b/lld/ELF/Target.cpp
@@ -444,30 +444,33 @@ bool X86TargetInfo::isTlsInitialExecRel(uint32_t Type) const {
}
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 *Buf, uint64_t GotEntryAddr,
};
memcpy(Buf, Inst, sizeof(Inst));
- // jmp *foo@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@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);
}
diff --git a/lld/test/ELF/plt-i686.s b/lld/test/ELF/plt-i686.s
index e169bd4d70f..9a2c7f53dc5 100644
--- a/lld/test/ELF/plt-i686.s
+++ b/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
OpenPOWER on IntegriCloud