[lld] r240837 - COFF: Fix delay-import tables.

Rui Ueyama ruiu at google.com
Fri Jun 26 14:40:16 PDT 2015


Author: ruiu
Date: Fri Jun 26 16:40:15 2015
New Revision: 240837

URL: http://llvm.org/viewvc/llvm-project?rev=240837&view=rev
Log:
COFF: Fix delay-import tables.

There were a few issues with the previous delay-import tables.

 - "Attribute" field should have been 1 instead of 0.
   (I don't know the meaning of this field, though.)
 - LEA and CALL operands had wrong addresses.
 - Address tables are in .didat (which is read-only).
   They should have been in .data.

Modified:
    lld/trunk/COFF/DLL.cpp
    lld/trunk/COFF/DLL.h
    lld/trunk/COFF/Writer.cpp
    lld/trunk/test/COFF/delayimports.test

Modified: lld/trunk/COFF/DLL.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DLL.cpp?rev=240837&r1=240836&r2=240837&view=diff
==============================================================================
--- lld/trunk/COFF/DLL.cpp (original)
+++ lld/trunk/COFF/DLL.cpp Fri Jun 26 16:40:15 2015
@@ -228,6 +228,7 @@ public:
 
   void writeTo(uint8_t *Buf) override {
     auto *E = (delay_import_directory_table_entry *)(Buf + FileOff);
+    E->Attributes = 1;
     E->Name = DLLName->getRVA();
     E->ModuleHandle = ModuleHandle->getRVA();
     E->DelayImportAddressTable = AddressTab->getRVA();
@@ -272,15 +273,14 @@ static const uint8_t Thunk[] = {
 // A chunk for the delay import thunk.
 class ThunkChunk : public Chunk {
 public:
-  ThunkChunk(Defined *I, Defined *H) : Imp(I), Helper(H) {}
-
+  ThunkChunk(Defined *I, Chunk *D, Defined *H) : Imp(I), Desc(D), Helper(H) {}
   size_t getSize() const override { return sizeof(Thunk); }
 
   void writeTo(uint8_t *Buf) override {
     memcpy(Buf + FileOff, Thunk, sizeof(Thunk));
-    write32le(Buf + FileOff + 36, Imp->getRVA());
-    write32le(Buf + FileOff + 43, Desc->getRVA());
-    write32le(Buf + FileOff + 48, Helper->getRVA());
+    write32le(Buf + FileOff + 36, Imp->getRVA() - RVA - 40);
+    write32le(Buf + FileOff + 43, Desc->getRVA() - RVA - 47);
+    write32le(Buf + FileOff + 48, Helper->getRVA() - RVA - 52);
   }
 
   Defined *Imp = nullptr;
@@ -288,14 +288,10 @@ public:
   Defined *Helper = nullptr;
 };
 
-std::vector<Chunk *> DelayLoadContents::getChunks(Defined *H) {
-  Helper = H;
-  create();
+std::vector<Chunk *> DelayLoadContents::getChunks() {
   std::vector<Chunk *> V;
   for (std::unique_ptr<Chunk> &C : Dirs)
     V.push_back(C.get());
-  for (std::unique_ptr<Chunk> &C : Addresses)
-    V.push_back(C.get());
   for (std::unique_ptr<Chunk> &C : Names)
     V.push_back(C.get());
   for (std::unique_ptr<Chunk> &C : HintNames)
@@ -307,11 +303,34 @@ std::vector<Chunk *> DelayLoadContents::
   return V;
 }
 
+std::vector<Chunk *> DelayLoadContents::getDataChunks() {
+  std::vector<Chunk *> V;
+  for (std::unique_ptr<Chunk> &C : ModuleHandles)
+    V.push_back(C.get());
+  for (std::unique_ptr<Chunk> &C : Addresses)
+    V.push_back(C.get());
+  return V;
+}
+
 uint64_t DelayLoadContents::getDirSize() {
   return Dirs.size() * sizeof(delay_import_directory_table_entry);
 }
 
-void DelayLoadContents::create() {
+// A chunk for the import descriptor table.
+class DelayAddressChunk : public Chunk {
+public:
+  explicit DelayAddressChunk(Chunk *C) : Thunk(C) {}
+  size_t getSize() const override { return 8; }
+
+  void writeTo(uint8_t *Buf) override {
+    write64le(Buf + FileOff, Thunk->getRVA() + Config->ImageBase);
+  }
+
+  Chunk *Thunk;
+};
+
+void DelayLoadContents::create(Defined *H) {
+  Helper = H;
   std::map<StringRef, std::vector<DefinedImportData *>> Map =
       binImports(Imports);
 
@@ -320,11 +339,15 @@ void DelayLoadContents::create() {
     StringRef Name = P.first;
     std::vector<DefinedImportData *> &Syms = P.second;
 
+    // Create the delay import table header.
+    if (!DLLNames.count(Name))
+      DLLNames[Name] = make_unique<StringChunk>(Name);
+    auto Dir = make_unique<DelayDirectoryChunk>(DLLNames[Name].get());
+
     size_t Base = Addresses.size();
     for (DefinedImportData *S : Syms) {
-      auto T = make_unique<ThunkChunk>(S, Helper);
-      auto A = make_unique<LookupChunk>(T.get());
-      T->Desc = A.get();
+      auto T = make_unique<ThunkChunk>(S, Dir.get(), Helper);
+      auto A = make_unique<DelayAddressChunk>(T.get());
       Addresses.push_back(std::move(A));
       Thunks.push_back(std::move(T));
       auto C =
@@ -333,8 +356,8 @@ void DelayLoadContents::create() {
       HintNames.push_back(std::move(C));
     }
     // Terminate with null values.
-    Addresses.push_back(make_unique<NullChunk>(LookupChunkSize));
-    Names.push_back(make_unique<NullChunk>(LookupChunkSize));
+    Addresses.push_back(make_unique<NullChunk>(8));
+    Names.push_back(make_unique<NullChunk>(8));
 
     for (int I = 0, E = Syms.size(); I < E; ++I)
       Syms[I]->setLocation(Addresses[Base + I].get());
@@ -342,10 +365,7 @@ void DelayLoadContents::create() {
     MH->setAlign(8);
     ModuleHandles.push_back(std::unique_ptr<Chunk>(MH));
 
-    // Create the delay import table header.
-    if (!DLLNames.count(Name))
-      DLLNames[Name] = make_unique<StringChunk>(Name);
-    auto Dir = make_unique<DelayDirectoryChunk>(DLLNames[Name].get());
+    // Fill the delay import table header fields.
     Dir->ModuleHandle = MH;
     Dir->AddressTab = Addresses[Base].get();
     Dir->NameTab = Names[Base].get();

Modified: lld/trunk/COFF/DLL.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DLL.h?rev=240837&r1=240836&r2=240837&view=diff
==============================================================================
--- lld/trunk/COFF/DLL.h (original)
+++ lld/trunk/COFF/DLL.h Fri Jun 26 16:40:15 2015
@@ -48,15 +48,15 @@ class DelayLoadContents {
 public:
   void add(DefinedImportData *Sym) { Imports.push_back(Sym); }
   bool empty() { return Imports.empty(); }
-  std::vector<Chunk *> getChunks(Defined *Helper);
-  std::vector<std::unique_ptr<Chunk>> &getDataChunks() { return ModuleHandles; }
+  void create(Defined *Helper);
+  std::vector<Chunk *> getChunks();
+  std::vector<Chunk *> getDataChunks();
   std::vector<std::unique_ptr<Chunk>> &getCodeChunks() { return Thunks; }
 
   uint64_t getDirRVA() { return Dirs[0]->getRVA(); }
   uint64_t getDirSize();
 
 private:
-  void create();
   Defined *Helper;
   std::vector<DefinedImportData *> Imports;
   std::vector<std::unique_ptr<Chunk>> Dirs;

Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=240837&r1=240836&r2=240837&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Fri Jun 26 16:40:15 2015
@@ -203,15 +203,16 @@ void Writer::createImportTables() {
       Sec->addChunk(C);
   }
   if (!DelayIdata.empty()) {
+    DelayIdata.create(Symtab->find("__delayLoadHelper2"));
     OutputSection *Sec = createSection(".didat");
-    for (Chunk *C : DelayIdata.getChunks(Symtab->find("__delayLoadHelper2")))
+    for (Chunk *C : DelayIdata.getChunks())
+      Sec->addChunk(C);
+    Sec = createSection(".data");
+    for (Chunk *C : DelayIdata.getDataChunks())
       Sec->addChunk(C);
     Sec = createSection(".text");
     for (std::unique_ptr<Chunk> &C : DelayIdata.getCodeChunks())
       Sec->addChunk(C.get());
-    Sec = createSection(".data");
-    for (std::unique_ptr<Chunk> &C : DelayIdata.getDataChunks())
-      Sec->addChunk(C.get());
   }
 }
 

Modified: lld/trunk/test/COFF/delayimports.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/delayimports.test?rev=240837&r1=240836&r2=240837&view=diff
==============================================================================
--- lld/trunk/test/COFF/delayimports.test (original)
+++ lld/trunk/test/COFF/delayimports.test Fri Jun 26 16:40:15 2015
@@ -5,22 +5,22 @@
 
 CHECK:      DelayImport {
 CHECK-NEXT:   Name: std64.dll
-CHECK-NEXT:   Attributes: 0x0
+CHECK-NEXT:   Attributes: 0x1
 CHECK-NEXT:   ModuleHandle: 0x1018
-CHECK-NEXT:   ImportAddressTable: 0x3040
-CHECK-NEXT:   ImportNameTable: 0x3060
+CHECK-NEXT:   ImportAddressTable: 0x1020
+CHECK-NEXT:   ImportNameTable: 0x3040
 CHECK-NEXT:   BoundDelayImportTable: 0x0
 CHECK-NEXT:   UnloadDelayImportTable: 0x0
 CHECK-NEXT:   Import {
 CHECK-NEXT:     Symbol: ExitProcess (0)
-CHECK-NEXT:     Address: 0x2066
+CHECK-NEXT:     Address: 0x140002066
 CHECK-NEXT:   }
 CHECK-NEXT:   Import {
 CHECK-NEXT:     Symbol:  (50)
-CHECK-NEXT:     Address: 0x20BD
+CHECK-NEXT:     Address: 0x1400020BD
 CHECK-NEXT:   }
 CHECK-NEXT:   Import {
 CHECK-NEXT:     Symbol: MessageBoxA (1)
-CHECK-NEXT:     Address: 0x2114
+CHECK-NEXT:     Address: 0x140002114
 CHECK-NEXT:   }
 CHECK-NEXT: }





More information about the llvm-commits mailing list