summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/lib/Driver/WinLinkDriver.cpp2
-rw-r--r--lld/lib/ReaderWriter/PECOFF/IdataPass.cpp56
-rw-r--r--lld/lib/ReaderWriter/PECOFF/IdataPass.h35
-rw-r--r--lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp1
-rw-r--r--lld/test/pecoff/Inputs/vars64.libbin0 -> 2016 bytes
-rw-r--r--lld/test/pecoff/delayimport.test39
6 files changed, 120 insertions, 13 deletions
diff --git a/lld/lib/Driver/WinLinkDriver.cpp b/lld/lib/Driver/WinLinkDriver.cpp
index cbba4e43c6e..eb4c83ccc2d 100644
--- a/lld/lib/Driver/WinLinkDriver.cpp
+++ b/lld/lib/Driver/WinLinkDriver.cpp
@@ -1227,8 +1227,6 @@ bool WinLinkDriver::parse(int argc, const char *argv[],
case OPT_delayload:
ctx.addDelayLoadDLL(inputArg->getValue());
- ctx.addInitialUndefinedSymbol(
- ctx.is64Bit() ? "__delayLoadHelper2" : "___delayLoadHelper2@8");
break;
case OPT_stub: {
diff --git a/lld/lib/ReaderWriter/PECOFF/IdataPass.cpp b/lld/lib/ReaderWriter/PECOFF/IdataPass.cpp
index cab507d1352..f0e30b40364 100644
--- a/lld/lib/ReaderWriter/PECOFF/IdataPass.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/IdataPass.cpp
@@ -21,6 +21,9 @@
#include <cstddef>
#include <cstring>
#include <map>
+#include <vector>
+
+using llvm::object::delay_import_directory_table_entry;
namespace lld {
namespace pecoff {
@@ -119,6 +122,36 @@ void ImportDirectoryAtom::addRelocations(
offsetof(ImportDirectoryTableEntry, NameRVA));
}
+// Create the contents for the delay-import table.
+std::vector<uint8_t> DelayImportDirectoryAtom::createContent() {
+ std::vector<uint8_t> r(sizeof(delay_import_directory_table_entry), 0);
+ auto entry = reinterpret_cast<delay_import_directory_table_entry *>(&r[0]);
+ // link.exe seems to set 1 to Attributes field, so do we.
+ entry->Attributes = 1;
+ return r;
+}
+
+// Create the data referred by the delay-import table.
+void DelayImportDirectoryAtom::addRelocations(
+ IdataContext &context, StringRef loadName,
+ const std::vector<COFFSharedLibraryAtom *> &sharedAtoms) {
+ // "NameTable" field
+ std::vector<ImportTableEntryAtom *> nameTable =
+ createImportTableAtoms(context, sharedAtoms, true, ".didat", _alloc);
+ addDir32NBReloc(
+ this, nameTable[0], context.ctx.getMachineType(),
+ offsetof(delay_import_directory_table_entry, DelayImportNameTable));
+
+ // "Name" field
+ auto *atom = new (_alloc)
+ COFFStringAtom(context.dummyFile, context.dummyFile.getNextOrdinal(),
+ ".didat", loadName);
+ context.file.addAtom(*atom);
+ addDir32NBReloc(this, atom, context.ctx.getMachineType(),
+ offsetof(delay_import_directory_table_entry, Name));
+ // TODO: emit other fields
+}
+
} // namespace idata
void IdataPass::perform(std::unique_ptr<MutableFile> &file) {
@@ -128,15 +161,32 @@ void IdataPass::perform(std::unique_ptr<MutableFile> &file) {
idata::IdataContext context(*file, _dummyFile, _ctx);
std::map<StringRef, std::vector<COFFSharedLibraryAtom *>> sharedAtoms =
groupByLoadName(*file);
+ bool hasImports = false;
+ bool hasDelayImports = false;
+
+ // Create the import table and terminate it with the null entry.
for (auto i : sharedAtoms) {
StringRef loadName = i.first;
+ if (_ctx.isDelayLoadDLL(loadName))
+ continue;
+ hasImports = true;
std::vector<COFFSharedLibraryAtom *> &atoms = i.second;
new (_alloc) idata::ImportDirectoryAtom(context, loadName, atoms);
}
+ if (hasImports)
+ new (_alloc) idata::NullImportDirectoryAtom(context);
- // All atoms, including those of tyep NullImportDirectoryAtom, are added to
- // context.file in the IdataAtom's constructor.
- new (_alloc) idata::NullImportDirectoryAtom(context);
+ // Create the delay import table and terminate it with the null entry.
+ for (auto i : sharedAtoms) {
+ StringRef loadName = i.first;
+ if (!_ctx.isDelayLoadDLL(loadName))
+ continue;
+ hasDelayImports = true;
+ std::vector<COFFSharedLibraryAtom *> &atoms = i.second;
+ new (_alloc) idata::DelayImportDirectoryAtom(context, loadName, atoms);
+ }
+ if (hasDelayImports)
+ new (_alloc) idata::DelayNullImportDirectoryAtom(context);
replaceSharedLibraryAtoms(*file);
}
diff --git a/lld/lib/ReaderWriter/PECOFF/IdataPass.h b/lld/lib/ReaderWriter/PECOFF/IdataPass.h
index 0adf2dd881e..efba5835e1d 100644
--- a/lld/lib/ReaderWriter/PECOFF/IdataPass.h
+++ b/lld/lib/ReaderWriter/PECOFF/IdataPass.h
@@ -126,6 +126,41 @@ public:
StringRef customSectionName() const override { return ".idata.d"; }
};
+/// The class for the the delay-load import table.
+class DelayImportDirectoryAtom : public IdataAtom {
+public:
+ DelayImportDirectoryAtom(
+ IdataContext &context, StringRef loadName,
+ const std::vector<COFFSharedLibraryAtom *> &sharedAtoms)
+ : IdataAtom(context, createContent()) {
+ addRelocations(context, loadName, sharedAtoms);
+ }
+
+ StringRef customSectionName() const override { return ".didat.d"; }
+
+private:
+ std::vector<uint8_t> createContent();
+ void addRelocations(IdataContext &context, StringRef loadName,
+ const std::vector<COFFSharedLibraryAtom *> &sharedAtoms);
+
+ mutable llvm::BumpPtrAllocator _alloc;
+};
+
+/// Terminator of the delay-load import table. The content of this atom is all
+/// zero.
+class DelayNullImportDirectoryAtom : public IdataAtom {
+public:
+ explicit DelayNullImportDirectoryAtom(IdataContext &context)
+ : IdataAtom(context, createContent()) {}
+ StringRef customSectionName() const override { return ".didat.d"; }
+
+private:
+ std::vector<uint8_t> createContent() const {
+ return std::vector<uint8_t>(
+ sizeof(llvm::object::delay_import_directory_table_entry), 0);
+ }
+};
+
} // namespace idata
class IdataPass : public lld::Pass {
diff --git a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
index 313bcd5a737..6c241974741 100644
--- a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
@@ -1043,6 +1043,7 @@ void PECOFFWriter::build(const File &linkedFile) {
.Case(".idata.d", DataDirectoryIndex::IMPORT_TABLE)
.Case(".edata", DataDirectoryIndex::EXPORT_TABLE)
.Case(".loadcfg", DataDirectoryIndex::LOAD_CONFIG_TABLE)
+ .Case(".didat.d", DataDirectoryIndex::DELAY_IMPORT_DESCRIPTOR)
.Default(ignore);
if (idx == ignore)
continue;
diff --git a/lld/test/pecoff/Inputs/vars64.lib b/lld/test/pecoff/Inputs/vars64.lib
new file mode 100644
index 00000000000..fb48c9ab141
--- /dev/null
+++ b/lld/test/pecoff/Inputs/vars64.lib
Binary files differ
diff --git a/lld/test/pecoff/delayimport.test b/lld/test/pecoff/delayimport.test
index 1d8b5c3c218..d122178b914 100644
--- a/lld/test/pecoff/delayimport.test
+++ b/lld/test/pecoff/delayimport.test
@@ -1,13 +1,36 @@
# RUN: yaml2obj %p/Inputs/vars-main-x86.obj.yaml > %t-x86.obj
# RUN: yaml2obj %p/Inputs/vars-main-x64.obj.yaml > %t-x64.obj
#
-# RUN: not lld -flavor link /out:%t.exe /subsystem:console /entry:main \
-# RUN: /delayload:vars.dll -- %t-x86.obj %p/Inputs/vars.lib 2>&1 \
-# RUN: | FileCheck -check-prefix=X86 %s
+# RUN: lld -flavor link /out:%t1.exe /subsystem:console /entry:main \
+# RUN: /delayload:vars.dll -- %t-x86.obj %p/Inputs/vars.lib
+# RUN: llvm-readobj -coff-imports %t1.exe | FileCheck -check-prefix=X86 %s
#
-# RUN: not lld -flavor link /out:%t.exe /subsystem:console /entry:main \
-# RUN: /machine:x64 /delayload:vars.dll -- %t-x64.obj %p/Inputs/vars.lib 2>&1 \
-# RUN: | FileCheck -check-prefix=X64 %s
+# RUN: lld -flavor link /out:%t2.exe /subsystem:console /entry:main \
+# RUN: /machine:x64 /delayload:vars64.dll -- %t-x64.obj %p/Inputs/vars64.lib
+# RUN: llvm-readobj -coff-imports %t2.exe | FileCheck -check-prefix=X64 %s
-X86: Undefined symbol: {{.*}} ___delayLoadHelper2@8
-X64: Undefined symbol: {{.*}} __delayLoadHelper2
+X86: DelayImport {
+X86-NEXT: Name: vars.dll
+X86-NEXT: Attributes: 0x1
+X86-NEXT: ModuleHandle: 0x0
+X86-NEXT: ImportAddressTable: 0x0
+X86-NEXT: ImportNameTable: 0x1000
+X86-NEXT: BoundDelayImportTable: 0x0
+X86-NEXT: UnloadDelayImportTable: 0x0
+X86-NEXT: Symbol: _name_with_underscore (0)
+X86-NEXT: Symbol: fn (1)
+X86-NEXT: Symbol: (1)
+X86-NEXT: }
+
+X64: DelayImport {
+X64-NEXT: Name: vars64.dll
+X64-NEXT: Attributes: 0x1
+X64-NEXT: ModuleHandle: 0x0
+X64-NEXT: ImportAddressTable: 0x0
+X64-NEXT: ImportNameTable: 0x1000
+X64-NEXT: BoundDelayImportTable: 0x0
+X64-NEXT: UnloadDelayImportTable: 0x0
+X64-NEXT: Symbol: _name_with_underscore (0)
+X64-NEXT: Symbol: fn (1)
+X64-NEXT: Symbol: (1)
+X64-NEXT: }
OpenPOWER on IntegriCloud