[lld] r219384 - [PECOFF] Emit the delay-import table

Rui Ueyama ruiu at google.com
Wed Oct 8 19:48:15 PDT 2014


Author: ruiu
Date: Wed Oct  8 21:48:14 2014
New Revision: 219384

URL: http://llvm.org/viewvc/llvm-project?rev=219384&view=rev
Log:
[PECOFF] Emit the delay-import table

This is a partial patch to emit the delay-import table. With this,
LLD is now able to emit the table that llvm-readobj can read and
dump.

The table lacks a few fields, such as the address of HMODULE, the
import address table, etc. They'll be added in subsequent patches.

Added:
    lld/trunk/test/pecoff/Inputs/vars64.lib
Modified:
    lld/trunk/lib/Driver/WinLinkDriver.cpp
    lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.cpp
    lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.h
    lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
    lld/trunk/test/pecoff/delayimport.test

Modified: lld/trunk/lib/Driver/WinLinkDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=219384&r1=219383&r2=219384&view=diff
==============================================================================
--- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)
+++ lld/trunk/lib/Driver/WinLinkDriver.cpp Wed Oct  8 21:48:14 2014
@@ -1227,8 +1227,6 @@ bool WinLinkDriver::parse(int argc, cons
 
     case OPT_delayload:
       ctx.addDelayLoadDLL(inputArg->getValue());
-      ctx.addInitialUndefinedSymbol(
-          ctx.is64Bit() ? "__delayLoadHelper2" : "___delayLoadHelper2 at 8");
       break;
 
     case OPT_stub: {

Modified: lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.cpp?rev=219384&r1=219383&r2=219384&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.cpp Wed Oct  8 21:48:14 2014
@@ -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<
   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);
 }

Modified: lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.h?rev=219384&r1=219383&r2=219384&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.h (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/IdataPass.h Wed Oct  8 21:48:14 2014
@@ -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 {

Modified: lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp?rev=219384&r1=219383&r2=219384&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp Wed Oct  8 21:48:14 2014
@@ -1043,6 +1043,7 @@ void PECOFFWriter::build(const File &lin
         .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;

Added: lld/trunk/test/pecoff/Inputs/vars64.lib
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/vars64.lib?rev=219384&view=auto
==============================================================================
Binary files lld/trunk/test/pecoff/Inputs/vars64.lib (added) and lld/trunk/test/pecoff/Inputs/vars64.lib Wed Oct  8 21:48:14 2014 differ

Modified: lld/trunk/test/pecoff/delayimport.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/delayimport.test?rev=219384&r1=219383&r2=219384&view=diff
==============================================================================
--- lld/trunk/test/pecoff/delayimport.test (original)
+++ lld/trunk/test/pecoff/delayimport.test Wed Oct  8 21:48:14 2014
@@ -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 at 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: }





More information about the llvm-commits mailing list