[lld] r242343 - COFF: Implement x86 delay-load thunks.
Rui Ueyama
ruiu at google.com
Wed Jul 15 15:26:58 PDT 2015
Author: ruiu
Date: Wed Jul 15 17:26:57 2015
New Revision: 242343
URL: http://llvm.org/viewvc/llvm-project?rev=242343&view=rev
Log:
COFF: Implement x86 delay-load thunks.
Modified:
lld/trunk/COFF/DLL.cpp
lld/trunk/test/COFF/delayimports32.test
Modified: lld/trunk/COFF/DLL.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DLL.cpp?rev=242343&r1=242342&r2=242343&view=diff
==============================================================================
--- lld/trunk/COFF/DLL.cpp (original)
+++ lld/trunk/COFF/DLL.cpp Wed Jul 15 17:26:57 2015
@@ -249,7 +249,7 @@ public:
// This code calls __delayLoadHelper2 function to resolve a symbol
// and then overwrites its jump table slot with the result
// for subsequent function calls.
-static const uint8_t Thunk[] = {
+static const uint8_t ThunkX64[] = {
0x51, // push rcx
0x52, // push rdx
0x41, 0x50, // push r8
@@ -274,14 +274,27 @@ static const uint8_t Thunk[] = {
0xFF, 0xE0, // jmp rax
};
+static const uint8_t ThunkX86[] = {
+ 0x51, // push ecx
+ 0x52, // push edx
+ 0x68, 0, 0, 0, 0, // push offset ___imp__<FUNCNAME>
+ 0x68, 0, 0, 0, 0, // push offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_dll
+ 0xE8, 0, 0, 0, 0, // call ___delayLoadHelper2 at 8
+ 0x5A, // pop edx
+ 0x59, // pop ecx
+ 0xFF, 0xE0, // jmp eax
+};
+
// A chunk for the delay import thunk.
-class ThunkChunk : public Chunk {
+class ThunkChunkX64 : public Chunk {
public:
- ThunkChunk(Defined *I, Chunk *D, Defined *H) : Imp(I), Desc(D), Helper(H) {}
- size_t getSize() const override { return sizeof(Thunk); }
+ ThunkChunkX64(Defined *I, Chunk *D, Defined *H)
+ : Imp(I), Desc(D), Helper(H) {}
+
+ size_t getSize() const override { return sizeof(ThunkX64); }
void writeTo(uint8_t *Buf) override {
- memcpy(Buf + FileOff, Thunk, sizeof(Thunk));
+ memcpy(Buf + FileOff, ThunkX64, sizeof(ThunkX64));
write32le(Buf + FileOff + 36, Imp->getRVA() - RVA - 40);
write32le(Buf + FileOff + 43, Desc->getRVA() - RVA - 47);
write32le(Buf + FileOff + 48, Helper->getRVA() - RVA - 52);
@@ -292,6 +305,30 @@ public:
Defined *Helper = nullptr;
};
+class ThunkChunkX86 : public Chunk {
+public:
+ ThunkChunkX86(Defined *I, Chunk *D, Defined *H)
+ : Imp(I), Desc(D), Helper(H) {}
+
+ size_t getSize() const override { return sizeof(ThunkX86); }
+
+ void writeTo(uint8_t *Buf) override {
+ memcpy(Buf + FileOff, ThunkX86, sizeof(ThunkX86));
+ write32le(Buf + FileOff + 3, Imp->getRVA() + Config->ImageBase);
+ write32le(Buf + FileOff + 8, Desc->getRVA() + Config->ImageBase);
+ write32le(Buf + FileOff + 13, Helper->getRVA() - RVA + 17);
+ }
+
+ void getBaserels(std::vector<uint32_t> *Res, Defined *ImageBase) override {
+ Res->push_back(RVA + 3);
+ Res->push_back(RVA + 8);
+ }
+
+ Defined *Imp = nullptr;
+ Chunk *Desc = nullptr;
+ Defined *Helper = nullptr;
+};
+
std::vector<Chunk *> DelayLoadContents::getChunks() {
std::vector<Chunk *> V;
for (std::unique_ptr<Chunk> &C : Dirs)
@@ -354,10 +391,15 @@ void DelayLoadContents::create(Defined *
size_t Base = Addresses.size();
for (DefinedImportData *S : Syms) {
- auto T = make_unique<ThunkChunk>(S, Dir.get(), Helper);
- auto A = make_unique<DelayAddressChunk>(T.get());
+ Chunk *T;
+ if (Config->is64()) {
+ T = new ThunkChunkX64(S, Dir.get(), Helper);
+ } else {
+ T = new ThunkChunkX86(S, Dir.get(), Helper);
+ }
+ auto A = make_unique<DelayAddressChunk>(T);
Addresses.push_back(std::move(A));
- Thunks.push_back(std::move(T));
+ Thunks.push_back(std::unique_ptr<Chunk>(T));
StringRef ExtName = S->getExternalName();
if (ExtName.empty()) {
Names.push_back(make_unique<OrdinalOnlyChunk>(S->getOrdinal()));
Modified: lld/trunk/test/COFF/delayimports32.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/delayimports32.test?rev=242343&r1=242342&r2=242343&view=diff
==============================================================================
--- lld/trunk/test/COFF/delayimports32.test (original)
+++ lld/trunk/test/COFF/delayimports32.test Wed Jul 15 17:26:57 2015
@@ -1,15 +1,35 @@
# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj
# RUN: lld -flavor link2 %t.obj %p/Inputs/std32.lib /subsystem:console \
# RUN: /entry:main at 0 /alternatename:___delayLoadHelper2 at 8=main at 0 /out:%t.exe
-# RUN: llvm-readobj -coff-imports %t.exe | FileCheck %s
+# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s
+# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s
-CHECK: Format: COFF-i386
-CHECK: Arch: i386
-CHECK: AddressSize: 32bit
-CHECK: Import {
-CHECK: Name: std32.dll
-CHECK: ImportLookupTableRVA: 0x3028
-CHECK: ImportAddressTableRVA: 0x3034
-CHECK: Symbol: ExitProcess (0)
-CHECK: Symbol: MessageBoxA (1)
-CHECK: }
+IMPORT: Format: COFF-i386
+IMPORT: Arch: i386
+IMPORT: AddressSize: 32bit
+IMPORT: Import {
+IMPORT: Name: std32.dll
+IMPORT: ImportLookupTableRVA: 0x3028
+IMPORT: ImportAddressTableRVA: 0x3034
+IMPORT: Symbol: ExitProcess (0)
+IMPORT: Symbol: MessageBoxA (1)
+IMPORT: }
+
+BASEREL: BaseReloc [
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: DIR64
+BASEREL-NEXT: Address: 0x2005
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: DIR64
+BASEREL-NEXT: Address: 0x200C
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: DIR64
+BASEREL-NEXT: Address: 0x2022
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: DIR64
+BASEREL-NEXT: Address: 0x2032
+BASEREL-NEXT: }
+BASEREL-NEXT: ]
More information about the llvm-commits
mailing list