[lld] r245201 - COFF: Fix the order of the DLL import entry.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 17 01:30:33 PDT 2015


Author: ruiu
Date: Mon Aug 17 03:30:31 2015
New Revision: 245201

URL: http://llvm.org/viewvc/llvm-project?rev=245201&view=rev
Log:
COFF: Fix the order of the DLL import entry.

There are some DLLs whose initializers depends on other DLLs'
initializers. The initialization order matters for them.

MSVC linker uses the order of the libraries from the command line.
LLD used ASCII-betical order. So they were incompatible.
This patch makes LLD compatible with MSVC.

Added:
    lld/trunk/test/COFF/dllorder.test
Modified:
    lld/trunk/COFF/Config.h
    lld/trunk/COFF/DLL.cpp
    lld/trunk/COFF/InputFiles.cpp
    lld/trunk/COFF/InputFiles.h
    lld/trunk/COFF/Writer.cpp

Modified: lld/trunk/COFF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Config.h?rev=245201&r1=245200&r2=245201&view=diff
==============================================================================
--- lld/trunk/COFF/Config.h (original)
+++ lld/trunk/COFF/Config.h Mon Aug 17 03:30:31 2015
@@ -78,6 +78,7 @@ struct Configuration {
   StringRef Implib;
   std::vector<Export> Exports;
   std::set<std::string> DelayLoads;
+  std::map<StringRef, int> DLLOrder;
   Undefined *DelayLoadHelper = nullptr;
 
   // Used for SafeSEH.

Modified: lld/trunk/COFF/DLL.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DLL.cpp?rev=245201&r1=245200&r2=245201&view=diff
==============================================================================
--- lld/trunk/COFF/DLL.cpp (original)
+++ lld/trunk/COFF/DLL.cpp Mon Aug 17 03:30:31 2015
@@ -124,14 +124,19 @@ private:
   size_t Size;
 };
 
-static std::map<StringRef, std::vector<DefinedImportData *>>
+static std::vector<std::vector<DefinedImportData *>>
 binImports(const std::vector<DefinedImportData *> &Imports) {
   // Group DLL-imported symbols by DLL name because that's how
   // symbols are layed out in the import descriptor table.
-  std::map<StringRef, std::vector<DefinedImportData *>> M;
+  auto Less = [](StringRef A, StringRef B) {
+    return Config->DLLOrder[A] < Config->DLLOrder[B];
+  };
+  std::map<StringRef, std::vector<DefinedImportData *>,
+           bool(*)(StringRef, StringRef)> M(Less);
   for (DefinedImportData *Sym : Imports)
     M[Sym->getDLLName()].push_back(Sym);
 
+  std::vector<std::vector<DefinedImportData *>> V;
   for (auto &P : M) {
     // Sort symbols by name for each group.
     std::vector<DefinedImportData *> &Syms = P.second;
@@ -139,8 +144,9 @@ binImports(const std::vector<DefinedImpo
               [](DefinedImportData *A, DefinedImportData *B) {
                 return A->getName() < B->getName();
               });
+    V.push_back(std::move(Syms));
   }
-  return M;
+  return V;
 }
 
 // Export table
@@ -393,13 +399,11 @@ std::vector<Chunk *> IdataContents::getC
 }
 
 void IdataContents::create() {
-  std::map<StringRef, std::vector<DefinedImportData *>> Map =
-      binImports(Imports);
+  std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
 
   // Create .idata contents for each DLL.
-  for (auto &P : Map) {
-    StringRef Name = P.first;
-    std::vector<DefinedImportData *> &Syms = P.second;
+  for (std::vector<DefinedImportData *> &Syms : V) {
+    StringRef Name = Syms[0]->getDLLName();
 
     // Create lookup and address tables. If they have external names,
     // we need to create HintName chunks to store the names.
@@ -467,13 +471,11 @@ uint64_t DelayLoadContents::getDirSize()
 
 void DelayLoadContents::create(Defined *H) {
   Helper = H;
-  std::map<StringRef, std::vector<DefinedImportData *>> Map =
-      binImports(Imports);
+  std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
 
   // Create .didat contents for each DLL.
-  for (auto &P : Map) {
-    StringRef Name = P.first;
-    std::vector<DefinedImportData *> &Syms = P.second;
+  for (std::vector<DefinedImportData *> &Syms : V) {
+    StringRef Name = Syms[0]->getDLLName();
 
     // Create the delay import table header.
     if (!DLLNames.count(Name))

Modified: lld/trunk/COFF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.cpp?rev=245201&r1=245200&r2=245201&view=diff
==============================================================================
--- lld/trunk/COFF/InputFiles.cpp (original)
+++ lld/trunk/COFF/InputFiles.cpp Mon Aug 17 03:30:31 2015
@@ -281,7 +281,8 @@ void ImportFile::parse() {
   // Read names and create an __imp_ symbol.
   StringRef Name = StringAlloc.save(StringRef(Buf + sizeof(*Hdr)));
   StringRef ImpName = StringAlloc.save(Twine("__imp_") + Name);
-  StringRef DLLName(Buf + sizeof(coff_import_header) + Name.size() + 1);
+  const char *NameStart = Buf + sizeof(coff_import_header) + Name.size() + 1;
+  DLLName = StringRef(NameStart).lower();
   StringRef ExtName;
   switch (Hdr->getNameType()) {
   case IMPORT_ORDINAL:

Modified: lld/trunk/COFF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.h?rev=245201&r1=245200&r2=245201&view=diff
==============================================================================
--- lld/trunk/COFF/InputFiles.h (original)
+++ lld/trunk/COFF/InputFiles.h Mon Aug 17 03:30:31 2015
@@ -186,6 +186,7 @@ public:
 
   DefinedImportData *ImpSym = nullptr;
   DefinedImportThunk *ThunkSym = nullptr;
+  std::string DLLName;
 
 private:
   void parse() override;

Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=245201&r1=245200&r2=245201&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Mon Aug 17 03:30:31 2015
@@ -365,15 +365,22 @@ void Writer::createMiscChunks() {
 void Writer::createImportTables() {
   if (Symtab->ImportFiles.empty())
     return;
+
+  // Initialize DLLOrder so that import entries are ordered in
+  // the same order as in the command line. (That affects DLL
+  // initialization order, and this ordering is MSVC-compatible.)
+  for (ImportFile *File : Symtab->ImportFiles)
+    if (Config->DLLOrder.count(File->DLLName) == 0)
+      Config->DLLOrder[File->DLLName] = Config->DLLOrder.size();
+
   OutputSection *Text = createSection(".text");
   for (ImportFile *File : Symtab->ImportFiles) {
     if (DefinedImportThunk *Thunk = File->ThunkSym)
       Text->addChunk(Thunk->getChunk());
-    DefinedImportData *Imp = File->ImpSym;
-    if (Config->DelayLoads.count(Imp->getDLLName().lower())) {
-      DelayIdata.add(Imp);
+    if (Config->DelayLoads.count(File->DLLName)) {
+      DelayIdata.add(File->ImpSym);
     } else {
-      Idata.add(Imp);
+      Idata.add(File->ImpSym);
     }
   }
   if (!Idata.empty()) {

Added: lld/trunk/test/COFF/dllorder.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/dllorder.test?rev=245201&view=auto
==============================================================================
--- lld/trunk/test/COFF/dllorder.test (added)
+++ lld/trunk/test/COFF/dllorder.test Mon Aug 17 03:30:31 2015
@@ -0,0 +1,64 @@
+# REQUIRES: winlib
+
+# RUN: yaml2obj < %s > %t.obj
+# RUN: mkdir -p %tlib
+
+# RUN: echo EXPORTS sym1 > %t1.def
+# RUN: lib /nologo /def:%t1.def /out:%tlib\\lib1.lib > /dev/null
+
+# RUN: echo EXPORTS sym2 > %t2.def
+# RUN: lib /nologo /def:%t2.def /out:%tlib\\lib2.lib > /dev/null
+
+# RUN: lld-link /out:%t1.exe /entry:main /libpath:%tlib %t.obj /defaultlib:lib1 /defaultlib:lib2
+# RUN: lld-link /out:%t2.exe /entry:main /libpath:%tlib %t.obj /defaultlib:lib2 /defaultlib:lib1
+
+# RUN: llvm-readobj -coff-imports %t1.exe | FileCheck -check-prefix=CHECK1 %s
+# RUN: llvm-readobj -coff-imports %t2.exe | FileCheck -check-prefix=CHECK2 %s
+
+# CHECK1: Name: dllorder.test.tmp1.dll
+# CHECK1: Name: dllorder.test.tmp2.dll
+
+# CHECK2: Name: dllorder.test.tmp2.dll
+# CHECK2: Name: dllorder.test.tmp1.dll
+
+---
+header:
+  Machine:         IMAGE_FILE_MACHINE_AMD64
+  Characteristics: []
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       4096
+    SectionData:     0000000000000000
+symbols:
+  - Name:            .text
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          8
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          0
+  - Name:            main
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            __imp_sym1
+    Value:           0
+    SectionNumber:   0
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            __imp_sym2
+    Value:           0
+    SectionNumber:   0
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+...




More information about the llvm-commits mailing list