[lld] r220096 - [PECOFF] Emit x64 delay-import wrapper function

Rui Ueyama ruiu at google.com
Fri Oct 17 15:03:54 PDT 2014


Author: ruiu
Date: Fri Oct 17 17:03:54 2014
New Revision: 220096

URL: http://llvm.org/viewvc/llvm-project?rev=220096&view=rev
Log:
[PECOFF] Emit x64 delay-import wrapper function

Previously we supported x86 only. This patch is to support x64.

The array of pointers to delay-loaded functions points the
DLL delay loading function at start-up. When a function is called
for the first time, the delay loading function gets called and
then rewrite the function pointer array.

Modified:
    lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.cpp
    lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.h
    lld/trunk/lib/ReaderWriter/PECOFF/Pass.cpp
    lld/trunk/lib/ReaderWriter/PECOFF/Pass.h

Modified: lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.cpp?rev=220096&r1=220095&r2=220096&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.cpp Fri Oct 17 17:03:54 2014
@@ -187,17 +187,28 @@ void DelayImportDirectoryAtom::addReloca
   for (int i = 0, e = sharedAtoms.size(); i < e; ++i) {
     const DefinedAtom *loader = new (_alloc) DelayLoaderAtom(
         context, addrTable[i], this, delayLoadHelper);
-    addDir32Reloc(addrTable[i], loader, context.ctx.getMachineType(), 0);
+    addDir64Reloc(addrTable[i], loader, context.ctx.getMachineType(), 0);
   }
 }
 
 DelayLoaderAtom::DelayLoaderAtom(IdataContext &context, const Atom *impAtom,
                                  const Atom *descAtom, const Atom *delayLoadHelperAtom)
-    : IdataAtom(context, createContent()) {
+    : IdataAtom(context, createContent(context.ctx.getMachineType())) {
   MachineTypes machine = context.ctx.getMachineType();
-  addDir32Reloc(this, impAtom, machine, 3);
-  addDir32Reloc(this, descAtom, machine, 8);
-  addRel32Reloc(this, delayLoadHelperAtom, machine, 13);
+  switch (machine) {
+  case llvm::COFF::IMAGE_FILE_MACHINE_I386:
+    addDir32Reloc(this, impAtom, machine, 3);
+    addDir32Reloc(this, descAtom, machine, 8);
+    addRel32Reloc(this, delayLoadHelperAtom, machine, 13);
+    break;
+  case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
+    addRel32Reloc(this, impAtom, machine, 36);
+    addRel32Reloc(this, descAtom, machine, 43);
+    addRel32Reloc(this, delayLoadHelperAtom, machine, 48);
+    break;
+  default:
+    llvm::report_fatal_error("unsupported machine type");
+  }
 }
 
 // DelayLoaderAtom contains a wrapper function for __delayLoadHelper2.
@@ -213,9 +224,9 @@ DelayLoaderAtom::DelayLoaderAtom(IdataCo
 // function.
 //
 // __delayLoadHelper2 is defined in delayimp.lib.
-std::vector<uint8_t> DelayLoaderAtom::createContent() const {
-  // NB: x86 only for now. ECX and EDX are caller-save.
-  static const uint8_t array[] = {
+std::vector<uint8_t>
+DelayLoaderAtom::createContent(MachineTypes machine) const {
+  static const uint8_t x86[] = {
     0x51,              // push  ecx
     0x52,              // push  edx
     0x68, 0, 0, 0, 0,  // push  offset ___imp__<FUNCNAME>
@@ -225,7 +236,38 @@ std::vector<uint8_t> DelayLoaderAtom::cr
     0x59,              // pop   ecx
     0xFF, 0xE0,        // jmp   eax
   };
-  return std::vector<uint8_t>(array, array + sizeof(array));
+  static const uint8_t x64[] = {
+    0x51,                               // push    rcx
+    0x52,                               // push    rdx
+    0x41, 0x50,                         // push    r8
+    0x41, 0x51,                         // push    r9
+    0x48, 0x83, 0xEC, 0x48,             // sub     rsp, 48h
+    0x66, 0x0F, 0x7F, 0x04, 0x24,       // movdqa  xmmword ptr [rsp], xmm0
+    0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa  xmmword ptr [rsp+10h], xmm1
+    0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa  xmmword ptr [rsp+20h], xmm2
+    0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa  xmmword ptr [rsp+30h], xmm3
+    0x48, 0x8D, 0x15, 0, 0, 0, 0,       // lea     rdx, [__imp_<FUNCNAME>]
+    0x48, 0x8D, 0x0D, 0, 0, 0, 0,       // lea     rcx, [___DELAY_IMPORT_...]
+    0xE8, 0, 0, 0, 0,                   // call    __delayLoadHelper2
+    0x66, 0x0F, 0x6F, 0x04, 0x24,       // movdqa  xmm0, xmmword ptr [rsp]
+    0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa  xmm1, xmmword ptr [rsp+10h]
+    0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa  xmm2, xmmword ptr [rsp+20h]
+    0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa  xmm3, xmmword ptr [rsp+30h]
+    0x48, 0x83, 0xC4, 0x48,             // add     rsp, 48h
+    0x41, 0x59,                         // pop     r9
+    0x41, 0x58,                         // pop     r8
+    0x5A,                               // pop     rdx
+    0x59,                               // pop     rcx
+    0xFF, 0xE0,                         // jmp     rax
+  };
+  switch (machine) {
+  case llvm::COFF::IMAGE_FILE_MACHINE_I386:
+    return std::vector<uint8_t>(x86, x86 + sizeof(x86));
+  case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
+    return std::vector<uint8_t>(x64, x64 + sizeof(x64));
+  default:
+    llvm::report_fatal_error("unsupported machine type");
+  }
 }
 
 } // namespace idata

Modified: lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.h?rev=220096&r1=220095&r2=220096&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.h (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.h Fri Oct 17 17:03:54 2014
@@ -185,7 +185,7 @@ public:
   Alignment alignment() const override { return Alignment(0); }
 
 private:
-  std::vector<uint8_t> createContent() const;
+  std::vector<uint8_t> createContent(MachineTypes machine) const;
 };
 
 } // namespace idata

Modified: lld/trunk/lib/ReaderWriter/PECOFF/Pass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/Pass.cpp?rev=220096&r1=220095&r2=220096&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/Pass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/Pass.cpp Fri Oct 17 17:03:54 2014
@@ -23,6 +23,22 @@ static void addReloc(COFFBaseDefinedAtom
       target, offsetInAtom, relType, arch));
 }
 
+void addDir64Reloc(COFFBaseDefinedAtom *atom, const Atom *target,
+                   llvm::COFF::MachineTypes machine, size_t offsetInAtom) {
+  switch (machine) {
+  case llvm::COFF::IMAGE_FILE_MACHINE_I386:
+    addReloc(atom, target, offsetInAtom, Reference::KindArch::x86,
+             llvm::COFF::IMAGE_REL_I386_DIR32);
+    return;
+  case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
+    addReloc(atom, target, offsetInAtom, Reference::KindArch::x86_64,
+             llvm::COFF::IMAGE_REL_AMD64_ADDR64);
+    return;
+  default:
+    llvm_unreachable("unsupported machine type");
+  }
+}
+
 void addDir32Reloc(COFFBaseDefinedAtom *atom, const Atom *target,
                    llvm::COFF::MachineTypes machine, size_t offsetInAtom) {
   switch (machine) {

Modified: lld/trunk/lib/ReaderWriter/PECOFF/Pass.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/Pass.h?rev=220096&r1=220095&r2=220096&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/Pass.h (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/Pass.h Fri Oct 17 17:03:54 2014
@@ -16,6 +16,9 @@
 namespace lld {
 namespace pecoff {
 
+void addDir64Reloc(COFFBaseDefinedAtom *atom, const Atom *target,
+                   llvm::COFF::MachineTypes machine, size_t offsetInAtom);
+
 void addDir32Reloc(COFFBaseDefinedAtom *atom, const Atom *target,
                    llvm::COFF::MachineTypes machine, size_t offsetInAtom);
 





More information about the llvm-commits mailing list