<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Jun 21, 2015 at 3:31 PM, Rui Ueyama <span dir="ltr"><<a href="mailto:ruiu@google.com" target="_blank">ruiu@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: ruiu<br>
Date: Sun Jun 21 17:31:52 2015<br>
New Revision: 240250<br>
<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject-3Frev-3D240250-26view-3Drev&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=kmqwAf84zRl78Izt4ryTywWQYidpp2NkfCw4KBf5TjI&s=YPPO3uTHEfyQyokums6j47kpAOA36144fmWUaym0X8U&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=240250&view=rev</a><br>
Log:<br>
COFF: Support delay-load import tables.<br>
<br>
DLLs are usually resolved at process startup, but you can<br>
delay-load them by passing /delayload option to the linker.<br>
<br>
If a /delayload is specified, the linker has to create data<br>
which is similar to regular import table.<br>
One notable difference is that the pointers in a delay-load<br>
import table are originally pointing to thunks that resolves<br>
themselves. Each thunk loads a DLL, resolve its name, and then<br>
overwrites the pointer with the result so that subsequent<br>
function calls directly call a desired function. The linker<br>
has to emit thunks.<br>
<br>
Added:<br>
    lld/trunk/test/COFF/delayimports.test<br>
Modified:<br>
    lld/trunk/COFF/Config.h<br>
    lld/trunk/COFF/DLL.cpp<br>
    lld/trunk/COFF/DLL.h<br>
    lld/trunk/COFF/Driver.cpp<br>
    lld/trunk/COFF/Writer.cpp<br>
    lld/trunk/COFF/Writer.h<br>
<br>
Modified: lld/trunk/COFF/Config.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_COFF_Config.h-3Frev-3D240250-26r1-3D240249-26r2-3D240250-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=kmqwAf84zRl78Izt4ryTywWQYidpp2NkfCw4KBf5TjI&s=QMrFJpAIyJJNcMhEg1ukhb_47qJM6slFjd6POzKU3-k&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Config.h?rev=240250&r1=240249&r2=240250&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/COFF/Config.h (original)<br>
+++ lld/trunk/COFF/Config.h Sun Jun 21 17:31:52 2015<br>
@@ -60,6 +60,7 @@ struct Configuration {<br>
   bool DLL = false;<br>
   StringRef Implib;<br>
   std::vector<Export> Exports;<br>
+  std::set<StringRef> DelayLoads;<br>
<br>
   // Options for manifest files.<br>
   ManifestKind Manifest = SideBySide;<br>
<br>
Modified: lld/trunk/COFF/DLL.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_COFF_DLL.cpp-3Frev-3D240250-26r1-3D240249-26r2-3D240250-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=kmqwAf84zRl78Izt4ryTywWQYidpp2NkfCw4KBf5TjI&s=Rn-UUG0Ra3a1H1Gw8sw713RpKgzUZOCfpKENmAypxTE&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DLL.cpp?rev=240250&r1=240249&r2=240250&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/COFF/DLL.cpp (original)<br>
+++ lld/trunk/COFF/DLL.cpp Sun Jun 21 17:31:52 2015<br>
@@ -7,8 +7,8 @@<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
 //<br>
-// This file defines various types of chunks for the DLL import<br>
-// descriptor table. They are inherently Windows-specific.<br>
+// This file defines various types of chunks for the DLL import or export<br>
+// descriptor tables. They are inherently Windows-specific.<br>
 // You need to read Microsoft PE/COFF spec to understand details<br>
 // about the data structures.<br>
 //<br>
@@ -114,6 +114,7 @@ public:<br>
   explicit NullChunk(size_t N) : Size(N) {}<br>
   bool hasData() const override { return false; }<br>
   size_t getSize() const override { return Size; }<br>
+  void setAlign(size_t N) { Align = N; }<br>
<br>
 private:<br>
   size_t Size;<br>
@@ -149,23 +150,33 @@ std::vector<Chunk *> IdataContents::getC<br>
   return V;<br>
 }<br>
<br>
-void IdataContents::create() {<br>
+static std::map<StringRef, std::vector<DefinedImportData *>><br>
+binImports(const std::vector<DefinedImportData *> &Imports) {<br>
   // Group DLL-imported symbols by DLL name because that's how<br>
   // symbols are layed out in the import descriptor table.<br>
-  std::map<StringRef, std::vector<DefinedImportData *>> Map;<br>
+  std::map<StringRef, std::vector<DefinedImportData *>> M;<br>
   for (DefinedImportData *Sym : Imports)<br>
-    Map[Sym->getDLLName()].push_back(Sym);<br>
-<br>
-  // Create .idata contents for each DLL.<br>
-  for (auto &P : Map) {<br>
-    StringRef Name = P.first;<br>
-    std::vector<DefinedImportData *> &Syms = P.second;<br>
+    M[Sym->getDLLName()].push_back(Sym);<br>
<br>
+  for (auto &P : M) {<br>
     // Sort symbols by name for each group.<br>
+    std::vector<DefinedImportData *> &Syms = P.second;<br>
     std::sort(Syms.begin(), Syms.end(),<br>
               [](DefinedImportData *A, DefinedImportData *B) {<br>
                 return A->getName() < B->getName();<br>
               });<br>
+  }<br>
+  return M;<br>
+}<br>
+<br>
+void IdataContents::create() {<br>
+  std::map<StringRef, std::vector<DefinedImportData *>> Map =<br>
+      binImports(Imports);<br>
+<br>
+  // Create .idata contents for each DLL.<br>
+  for (auto &P : Map) {<br>
+    StringRef Name = P.first;<br>
+    std::vector<DefinedImportData *> &Syms = P.second;<br>
<br>
     // Create lookup and address tables. If they have external names,<br>
     // we need to create HintName chunks to store the names.<br>
@@ -204,6 +215,148 @@ void IdataContents::create() {<br>
 }<br>
<br>
 // Export table<br>
+// See Microsoft PE/COFF spec 4.3 for details.<br>
+<br>
+// A chunk for the delay import descriptor table etnry.<br>
+class DelayDirectoryChunk : public Chunk {<br>
+public:<br>
+  explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {}<br>
+<br>
+  size_t getSize() const override {<br>
+    return sizeof(delay_import_directory_table_entry);<br>
+  }<br>
+<br>
+  void writeTo(uint8_t *Buf) override {<br>
+    auto *E = (delay_import_directory_table_entry *)(Buf + FileOff);<br>
+    E->Name = DLLName->getRVA();<br>
+    E->ModuleHandle = ModuleHandle->getRVA();<br>
+    E->DelayImportAddressTable = AddressTab->getRVA();<br>
+    E->DelayImportNameTable = NameTab->getRVA();<br>
+  }<br>
+<br>
+  Chunk *DLLName;<br>
+  Chunk *ModuleHandle;<br>
+  Chunk *AddressTab;<br>
+  Chunk *NameTab;<br>
+};<br>
+<br>
+// Initial contents for delay-loaded functions.<br>
+// This code calls __delayLoadHerper2 function to resolve a symbol<br></blockquote><div><br></div><div>Looks like a typo, should probably be __delayLoadHelper2?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+// and then overwrites its jump table slot with the result<br>
+// for subsequent function calls.<br>
+static const uint8_t Thunk[] = {<br>
+    0x51,                               // push    rcx<br>
+    0x52,                               // push    rdx<br>
+    0x41, 0x50,                         // push    r8<br>
+    0x41, 0x51,                         // push    r9<br>
+    0x48, 0x83, 0xEC, 0x48,             // sub     rsp, 48h<br>
+    0x66, 0x0F, 0x7F, 0x04, 0x24,       // movdqa  xmmword ptr [rsp], xmm0<br>
+    0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa  xmmword ptr [rsp+10h], xmm1<br>
+    0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa  xmmword ptr [rsp+20h], xmm2<br>
+    0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa  xmmword ptr [rsp+30h], xmm3<br>
+    0x48, 0x8D, 0x15, 0, 0, 0, 0,       // lea     rdx, [__imp_<FUNCNAME>]<br>
+    0x48, 0x8D, 0x0D, 0, 0, 0, 0,       // lea     rcx, [___DELAY_IMPORT_...]<br>
+    0xE8, 0, 0, 0, 0,                   // call    __delayLoadHelper2<br>
+    0x66, 0x0F, 0x6F, 0x04, 0x24,       // movdqa  xmm0, xmmword ptr [rsp]<br>
+    0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa  xmm1, xmmword ptr [rsp+10h]<br>
+    0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa  xmm2, xmmword ptr [rsp+20h]<br>
+    0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa  xmm3, xmmword ptr [rsp+30h]<br>
+    0x48, 0x83, 0xC4, 0x48,             // add     rsp, 48h<br>
+    0x41, 0x59,                         // pop     r9<br>
+    0x41, 0x58,                         // pop     r8<br>
+    0x5A,                               // pop     rdx<br>
+    0x59,                               // pop     rcx<br>
+    0xFF, 0xE0,                         // jmp     rax<br>
+};<br>
+<br>
+// A chunk for the delay import thunk.<br>
+class ThunkChunk : public Chunk {<br>
+public:<br>
+  ThunkChunk(Defined *I, Defined *H) : Imp(I), Helper(H) {}<br>
+<br>
+  size_t getSize() const override { return sizeof(Thunk); }<br>
+<br>
+  void writeTo(uint8_t *Buf) override {<br>
+    memcpy(Buf + FileOff, Thunk, sizeof(Thunk));<br>
+    write32le(Buf + FileOff + 36, Imp->getRVA());<br>
+    write32le(Buf + FileOff + 43, Desc->getRVA());<br>
+    write32le(Buf + FileOff + 48, Helper->getRVA());<br>
+  }<br>
+<br>
+  Defined *Imp = nullptr;<br>
+  Chunk *Desc = nullptr;<br>
+  Defined *Helper = nullptr;<br>
+};<br>
+<br>
+std::vector<Chunk *> DelayLoadContents::getChunks(Defined *H) {<br>
+  Helper = H;<br>
+  create();<br>
+  std::vector<Chunk *> V;<br>
+  for (std::unique_ptr<Chunk> &C : Dirs)<br>
+    V.push_back(C.get());<br>
+  for (std::unique_ptr<Chunk> &C : Addresses)<br>
+    V.push_back(C.get());<br>
+  for (std::unique_ptr<Chunk> &C : Names)<br>
+    V.push_back(C.get());<br>
+  for (std::unique_ptr<Chunk> &C : HintNames)<br>
+    V.push_back(C.get());<br>
+  for (auto &P : DLLNames) {<br>
+    std::unique_ptr<Chunk> &C = P.second;<br>
+    V.push_back(C.get());<br>
+  }<br>
+  return V;<br>
+}<br>
+<br>
+uint64_t DelayLoadContents::getDirSize() {<br>
+  return Dirs.size() * sizeof(delay_import_directory_table_entry);<br>
+}<br>
+<br>
+void DelayLoadContents::create() {<br>
+  std::map<StringRef, std::vector<DefinedImportData *>> Map =<br>
+      binImports(Imports);<br>
+<br>
+  // Create .didat contents for each DLL.<br>
+  for (auto &P : Map) {<br>
+    StringRef Name = P.first;<br>
+    std::vector<DefinedImportData *> &Syms = P.second;<br>
+<br>
+    size_t Base = Addresses.size();<br>
+    for (DefinedImportData *S : Syms) {<br>
+      auto T = make_unique<ThunkChunk>(S, Helper);<br>
+      auto A = make_unique<LookupChunk>(T.get());<br>
+      T->Desc = A.get();<br>
+      Addresses.push_back(std::move(A));<br>
+      Thunks.push_back(std::move(T));<br>
+      auto C =<br>
+          make_unique<HintNameChunk>(S->getExternalName(), S->getOrdinal());<br>
+      Names.push_back(make_unique<LookupChunk>(C.get()));<br>
+      HintNames.push_back(std::move(C));<br>
+    }<br>
+    // Terminate with null values.<br>
+    Addresses.push_back(make_unique<NullChunk>(LookupChunkSize));<br>
+    Names.push_back(make_unique<NullChunk>(LookupChunkSize));<br>
+<br>
+    for (int I = 0, E = Syms.size(); I < E; ++I)<br>
+      Syms[I]->setLocation(Addresses[Base + I].get());<br>
+    auto *MH = new NullChunk(8);<br>
+    MH->setAlign(8);<br>
+    ModuleHandles.push_back(std::unique_ptr<Chunk>(MH));<br>
+<br>
+    // Create the delay import table header.<br>
+    if (!DLLNames.count(Name))<br>
+      DLLNames[Name] = make_unique<StringChunk>(Name);<br>
+    auto Dir = make_unique<DelayDirectoryChunk>(DLLNames[Name].get());<br>
+    Dir->ModuleHandle = MH;<br>
+    Dir->AddressTab = Addresses[Base].get();<br>
+    Dir->NameTab = Names[Base].get();<br>
+    Dirs.push_back(std::move(Dir));<br>
+  }<br>
+  // Add null terminator.<br>
+  Dirs.push_back(<br>
+      make_unique<NullChunk>(sizeof(delay_import_directory_table_entry)));<br>
+}<br>
+<br>
+// Export table<br>
 // Read Microsoft PE/COFF spec 5.3 for details.<br>
<br>
 // A chunk for the export descriptor table.<br>
<br>
Modified: lld/trunk/COFF/DLL.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_COFF_DLL.h-3Frev-3D240250-26r1-3D240249-26r2-3D240250-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=kmqwAf84zRl78Izt4ryTywWQYidpp2NkfCw4KBf5TjI&s=f5IUf2hC7HGx4ljszmmfShBk5Fu31skw-dJdHQQ5_jA&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DLL.h?rev=240250&r1=240249&r2=240250&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/COFF/DLL.h (original)<br>
+++ lld/trunk/COFF/DLL.h Sun Jun 21 17:31:52 2015<br>
@@ -23,6 +23,7 @@ namespace coff {<br>
 class IdataContents {<br>
 public:<br>
   void add(DefinedImportData *Sym) { Imports.push_back(Sym); }<br>
+  bool empty() { return Imports.empty(); }<br>
   std::vector<Chunk *> getChunks();<br>
<br>
   uint64_t getDirRVA() { return Dirs[0]->getRVA(); }<br>
@@ -41,6 +42,32 @@ private:<br>
   std::map<StringRef, std::unique_ptr<Chunk>> DLLNames;<br>
 };<br>
<br>
+// Windows-specific.<br>
+// DelayLoadContents creates all chunks for the delay-load DLL import table.<br>
+class DelayLoadContents {<br>
+public:<br>
+  void add(DefinedImportData *Sym) { Imports.push_back(Sym); }<br>
+  bool empty() { return Imports.empty(); }<br>
+  std::vector<Chunk *> getChunks(Defined *Helper);<br>
+  std::vector<std::unique_ptr<Chunk>> &getDataChunks() { return ModuleHandles; }<br>
+  std::vector<std::unique_ptr<Chunk>> &getCodeChunks() { return Thunks; }<br>
+<br>
+  uint64_t getDirRVA() { return Dirs[0]->getRVA(); }<br>
+  uint64_t getDirSize();<br>
+<br>
+private:<br>
+  void create();<br>
+  Defined *Helper;<br>
+  std::vector<DefinedImportData *> Imports;<br>
+  std::vector<std::unique_ptr<Chunk>> Dirs;<br>
+  std::vector<std::unique_ptr<Chunk>> ModuleHandles;<br>
+  std::vector<std::unique_ptr<Chunk>> Addresses;<br>
+  std::vector<std::unique_ptr<Chunk>> Names;<br>
+  std::vector<std::unique_ptr<Chunk>> HintNames;<br>
+  std::vector<std::unique_ptr<Chunk>> Thunks;<br>
+  std::map<StringRef, std::unique_ptr<Chunk>> DLLNames;<br>
+};<br>
+<br>
 // Windows-specific.<br>
 // EdataContents creates all chunks for the DLL export table.<br>
 class EdataContents {<br>
<br>
Modified: lld/trunk/COFF/Driver.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_COFF_Driver.cpp-3Frev-3D240250-26r1-3D240249-26r2-3D240250-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=kmqwAf84zRl78Izt4ryTywWQYidpp2NkfCw4KBf5TjI&s=8L0jPkLhCLuE3NznmaYcZAnyqNX1mS39zm-wM8KYoKY&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=240250&r1=240249&r2=240250&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/COFF/Driver.cpp (original)<br>
+++ lld/trunk/COFF/Driver.cpp Sun Jun 21 17:31:52 2015<br>
@@ -378,6 +378,12 @@ bool LinkerDriver::link(llvm::ArrayRef<c<br>
     Config->Exports.push_back(E.get());<br>
   }<br>
<br>
+  // Handle /delayload<br>
+  for (auto *Arg : Args->filtered(OPT_delayload)) {<br>
+    Config->DelayLoads.insert(Arg->getValue());<br>
+    Config->Includes.insert("__delayLoadHelper2");<br>
+  }<br>
+<br>
   // Handle /failifmismatch<br>
   for (auto *Arg : Args->filtered(OPT_failifmismatch))<br>
     if (checkFailIfMismatch(Arg->getValue()))<br>
<br>
Modified: lld/trunk/COFF/Writer.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_COFF_Writer.cpp-3Frev-3D240250-26r1-3D240249-26r2-3D240250-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=kmqwAf84zRl78Izt4ryTywWQYidpp2NkfCw4KBf5TjI&s=GWEaCy1bQn9xdgAI6JGlu78EUq8hqpeTP6iOh0XpxkU&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=240250&r1=240249&r2=240250&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/COFF/Writer.cpp (original)<br>
+++ lld/trunk/COFF/Writer.cpp Sun Jun 21 17:31:52 2015<br>
@@ -159,29 +159,45 @@ void Writer::createImportTables() {<br>
   if (Symtab->ImportFiles.empty())<br>
     return;<br>
   OutputSection *Text = createSection(".text");<br>
-  Idata.reset(new IdataContents());<br>
   for (std::unique_ptr<ImportFile> &File : Symtab->ImportFiles) {<br>
-    for (SymbolBody *Body : File->getSymbols()) {<br>
-      if (auto *Import = dyn_cast<DefinedImportData>(Body)) {<br>
-        Idata->add(Import);<br>
+    for (SymbolBody *B : File->getSymbols()) {<br>
+      auto *Import = dyn_cast<DefinedImportData>(B);<br>
+      if (!Import) {<br>
+        // Linker-created function thunks for DLL symbols are added to<br>
+        // .text section.<br>
+        Text->addChunk(cast<DefinedImportThunk>(B)->getChunk());<br>
         continue;<br>
       }<br>
-      // Linker-created function thunks for DLL symbols are added to<br>
-      // .text section.<br>
-      Text->addChunk(cast<DefinedImportThunk>(Body)->getChunk());<br>
+      if (Config->DelayLoads.count(Import->getDLLName())) {<br>
+        DelayIdata.add(Import);<br>
+      } else {<br>
+        Idata.add(Import);<br>
+      }<br>
     }<br>
   }<br>
-  OutputSection *Sec = createSection(".idata");<br>
-  for (Chunk *C : Idata->getChunks())<br>
-    Sec->addChunk(C);<br>
+  if (!Idata.empty()) {<br>
+    OutputSection *Sec = createSection(".idata");<br>
+    for (Chunk *C : Idata.getChunks())<br>
+      Sec->addChunk(C);<br>
+  }<br>
+  if (!DelayIdata.empty()) {<br>
+    OutputSection *Sec = createSection(".didat");<br>
+    for (Chunk *C : DelayIdata.getChunks(Symtab->find("__delayLoadHelper2")))<br>
+      Sec->addChunk(C);<br>
+    Sec = createSection(".text");<br>
+    for (std::unique_ptr<Chunk> &C : DelayIdata.getCodeChunks())<br>
+      Sec->addChunk(C.get());<br>
+    Sec = createSection(".data");<br>
+    for (std::unique_ptr<Chunk> &C : DelayIdata.getDataChunks())<br>
+      Sec->addChunk(C.get());<br>
+  }<br>
 }<br>
<br>
 void Writer::createExportTable() {<br>
   if (Config->Exports.empty())<br>
     return;<br>
-  Edata.reset(new EdataContents());<br>
   OutputSection *Sec = createSection(".edata");<br>
-  for (std::unique_ptr<Chunk> &C : Edata->Chunks)<br>
+  for (std::unique_ptr<Chunk> &C : Edata.Chunks)<br>
     Sec->addChunk(C.get());<br>
 }<br>
<br>
@@ -309,11 +325,16 @@ void Writer::writeHeader() {<br>
     Dir[EXPORT_TABLE].RelativeVirtualAddress = Sec->getRVA();<br>
     Dir[EXPORT_TABLE].Size = Sec->getVirtualSize();<br>
   }<br>
-  if (Idata) {<br>
-    Dir[IMPORT_TABLE].RelativeVirtualAddress = Idata->getDirRVA();<br>
-    Dir[IMPORT_TABLE].Size = Idata->getDirSize();<br>
-    Dir[IAT].RelativeVirtualAddress = Idata->getIATRVA();<br>
-    Dir[IAT].Size = Idata->getIATSize();<br>
+  if (!Idata.empty()) {<br>
+    Dir[IMPORT_TABLE].RelativeVirtualAddress = Idata.getDirRVA();<br>
+    Dir[IMPORT_TABLE].Size = Idata.getDirSize();<br>
+    Dir[IAT].RelativeVirtualAddress = Idata.getIATRVA();<br>
+    Dir[IAT].Size = Idata.getIATSize();<br>
+  }<br>
+  if (!DelayIdata.empty()) {<br>
+    Dir[DELAY_IMPORT_DESCRIPTOR].RelativeVirtualAddress =<br>
+        DelayIdata.getDirRVA();<br>
+    Dir[DELAY_IMPORT_DESCRIPTOR].Size = DelayIdata.getDirSize();<br>
   }<br>
   if (OutputSection *Sec = findSection(".rsrc")) {<br>
     Dir[RESOURCE_TABLE].RelativeVirtualAddress = Sec->getRVA();<br>
<br>
Modified: lld/trunk/COFF/Writer.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_COFF_Writer.h-3Frev-3D240250-26r1-3D240249-26r2-3D240250-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=kmqwAf84zRl78Izt4ryTywWQYidpp2NkfCw4KBf5TjI&s=ofklI9WY1Oc0_mddrFtHzxFRGM0WxB_wPomlWzTpT2U&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.h?rev=240250&r1=240249&r2=240250&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/COFF/Writer.h (original)<br>
+++ lld/trunk/COFF/Writer.h Sun Jun 21 17:31:52 2015<br>
@@ -100,8 +100,9 @@ private:<br>
   llvm::SpecificBumpPtrAllocator<OutputSection> CAlloc;<br>
   llvm::SpecificBumpPtrAllocator<BaserelChunk> BAlloc;<br>
   std::vector<OutputSection *> OutputSections;<br>
-  std::unique_ptr<IdataContents> Idata;<br>
-  std::unique_ptr<EdataContents> Edata;<br>
+  IdataContents Idata;<br>
+  DelayLoadContents DelayIdata;<br>
+  EdataContents Edata;<br>
<br>
   uint64_t FileSize;<br>
   uint64_t SizeOfImage;<br>
<br>
Added: lld/trunk/test/COFF/delayimports.test<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_test_COFF_delayimports.test-3Frev-3D240250-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=kmqwAf84zRl78Izt4ryTywWQYidpp2NkfCw4KBf5TjI&s=GLzRZXbzoREljZgeMKFcyLNmCzjyOI9llppFgDCujD0&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/delayimports.test?rev=240250&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/COFF/delayimports.test (added)<br>
+++ lld/trunk/test/COFF/delayimports.test Sun Jun 21 17:31:52 2015<br>
@@ -0,0 +1,26 @@<br>
+# RUN: lld -flavor link2 /out:%t.exe /entry:main /subsystem:console \<br>
+# RUN:   %p/Inputs/hello64.obj %p/Inputs/std64.lib /delayload:std64.dll \<br>
+# RUN:   /alternatename:__delayLoadHelper2=main<br>
+# RUN: llvm-readobj -coff-imports %t.exe | FileCheck %s<br>
+<br>
+CHECK:      DelayImport {<br>
+CHECK-NEXT:   Name: std64.dll<br>
+CHECK-NEXT:   Attributes: 0x0<br>
+CHECK-NEXT:   ModuleHandle: 0x1018<br>
+CHECK-NEXT:   ImportAddressTable: 0x3040<br>
+CHECK-NEXT:   ImportNameTable: 0x3060<br>
+CHECK-NEXT:   BoundDelayImportTable: 0x0<br>
+CHECK-NEXT:   UnloadDelayImportTable: 0x0<br>
+CHECK-NEXT:   Import {<br>
+CHECK-NEXT:     Symbol: ExitProcess (0)<br>
+CHECK-NEXT:     Address: 0x2045<br>
+CHECK-NEXT:   }<br>
+CHECK-NEXT:   Import {<br>
+CHECK-NEXT:     Symbol:  (50)<br>
+CHECK-NEXT:     Address: 0x209C<br>
+CHECK-NEXT:   }<br>
+CHECK-NEXT:   Import {<br>
+CHECK-NEXT:     Symbol: MessageBoxA (1)<br>
+CHECK-NEXT:     Address: 0x20F3<br>
+CHECK-NEXT:   }<br>
+CHECK-NEXT: }<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>