<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>