[PATCH] D31682: Fix PLT and GOTPLT entries for x86 PIC.
Rafael EspĂndola via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 5 07:24:59 PDT 2017
LGTM
On 4 April 2017 at 18:21, Rui Ueyama via Phabricator via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> 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);
> }
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
More information about the llvm-commits
mailing list