[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