[lld] r240757 - COFF: Change symbol resolution order for entry and /include.

Rui Ueyama ruiu at google.com
Thu Jun 25 20:44:00 PDT 2015


Author: ruiu
Date: Thu Jun 25 22:44:00 2015
New Revision: 240757

URL: http://llvm.org/viewvc/llvm-project?rev=240757&view=rev
Log:
COFF: Change symbol resolution order for entry and /include.

We were resolving entry symbols and /include'd symbols after all other
symbols are resolved. But looks like it's too late. I found that it
causes some program to fail to link.

Let's say we have an object file A which defines symbols X and Y in an
archive. We also have another file B after A which defines X, Y and
_DLLMainCRTStartup in another archive. They conflict each other, so
either A or B can be linked.

If we have _DLLMainCRTStartup as an undefined symbol, file B is always
chosen. If not, there's a chance that A is chosen. If the linker
find it needs _DllMainCRTStartup after that, it's too late.

This patch adds undefined symbols to the symbol table as soon as
possible to fix the issue.

Modified:
    lld/trunk/COFF/Config.h
    lld/trunk/COFF/Driver.cpp
    lld/trunk/COFF/Driver.h
    lld/trunk/COFF/SymbolTable.cpp
    lld/trunk/test/COFF/include2.test
    lld/trunk/test/COFF/order.test

Modified: lld/trunk/COFF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Config.h?rev=240757&r1=240756&r2=240757&view=diff
==============================================================================
--- lld/trunk/COFF/Config.h (original)
+++ lld/trunk/COFF/Config.h Thu Jun 25 22:44:00 2015
@@ -53,9 +53,6 @@ struct Configuration {
   std::set<StringRef> NoDefaultLibs;
   bool NoDefaultLibAll = false;
 
-  // Used for /include.
-  std::set<StringRef> Includes;
-
   // True if we are creating a DLL.
   bool DLL = false;
   StringRef Implib;

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=240757&r1=240756&r2=240757&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Thu Jun 25 22:44:00 2015
@@ -117,7 +117,7 @@ LinkerDriver::parseDirectives(StringRef
         return EC;
       break;
     case OPT_incl:
-      Config->Includes.insert(Arg->getValue());
+      addUndefined(Arg->getValue());
       break;
     case OPT_merge:
       // Ignore /merge for now.
@@ -201,6 +201,11 @@ void LinkerDriver::addLibSearchPaths() {
   }
 }
 
+void LinkerDriver::addUndefined(StringRef Sym) {
+  Symtab.addUndefined(Sym);
+  Config->GCRoots.insert(Sym);
+}
+
 static WindowsSubsystem inferSubsystem() {
   if (Config->DLL)
     return IMAGE_SUBSYSTEM_WINDOWS_GUI;
@@ -259,16 +264,22 @@ bool LinkerDriver::link(llvm::ArrayRef<c
   if (Args.hasArg(OPT_verbose))
     Config->Verbose = true;
 
+  // Handle /entry
+  if (auto *Arg = Args.getLastArg(OPT_entry)) {
+    Config->EntryName = Arg->getValue();
+    addUndefined(Config->EntryName);
+  }
+
   // Handle /dll
   if (Args.hasArg(OPT_dll)) {
     Config->DLL = true;
     Config->ManifestID = 2;
+    if (Config->EntryName.empty()) {
+      Config->EntryName = "_DllMainCRTStartup";
+      addUndefined("_DllMainCRTStartup");
+    }
   }
 
-  // Handle /entry
-  if (auto *Arg = Args.getLastArg(OPT_entry))
-    Config->EntryName = Arg->getValue();
-
   // Handle /fixed
   if (Args.hasArg(OPT_fixed)) {
     if (Args.hasArg(OPT_dynamicbase)) {
@@ -347,7 +358,7 @@ bool LinkerDriver::link(llvm::ArrayRef<c
 
   // Handle /include
   for (auto *Arg : Args.filtered(OPT_incl))
-    Config->Includes.insert(Arg->getValue());
+    addUndefined(Arg->getValue());
 
   // Handle /implib
   if (auto *Arg = Args.getLastArg(OPT_implib))
@@ -383,7 +394,7 @@ bool LinkerDriver::link(llvm::ArrayRef<c
   // Handle /delayload
   for (auto *Arg : Args.filtered(OPT_delayload)) {
     Config->DelayLoads.insert(Arg->getValue());
-    Config->Includes.insert("__delayLoadHelper2");
+    addUndefined("__delayLoadHelper2");
   }
 
   // Handle /failifmismatch
@@ -504,13 +515,9 @@ bool LinkerDriver::link(llvm::ArrayRef<c
   for (;;) {
     size_t Ver = Symtab.getVersion();
 
-    // Add undefined symbols specified by /include.
-    for (StringRef Sym : Config->Includes)
-      Symtab.addUndefined(Sym);
-
     // Windows specific -- Make sure we resolve all dllexported symbols.
     for (Export &E : Config->Exports)
-      Symtab.addUndefined(E.Name);
+      addUndefined(E.Name);
 
     // Add weak aliases. Weak aliases is a mechanism to give remaining
     // undefined symbols final chance to be resolved successfully.
@@ -535,7 +542,7 @@ bool LinkerDriver::link(llvm::ArrayRef<c
       }
       Config->EntryName = EntryOrErr.get();
     }
-    Symtab.addUndefined(Config->EntryName);
+    addUndefined(Config->EntryName);
 
     if (auto EC = Symtab.run()) {
       llvm::errs() << EC.message() << "\n";
@@ -549,13 +556,6 @@ bool LinkerDriver::link(llvm::ArrayRef<c
   if (Symtab.reportRemainingUndefines())
     return false;
 
-  // Initialize a list of GC root.
-  for (StringRef Sym : Config->Includes)
-    Config->GCRoots.insert(Sym);
-  for (Export &E : Config->Exports)
-    Config->GCRoots.insert(E.Name);
-  Config->GCRoots.insert(Config->EntryName);
-
   // Do LTO by compiling bitcode input files to a native COFF file
   // then link that file.
   if (auto EC = Symtab.addCombinedLTOObject()) {

Modified: lld/trunk/COFF/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.h?rev=240757&r1=240756&r2=240757&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.h (original)
+++ lld/trunk/COFF/Driver.h Thu Jun 25 22:44:00 2015
@@ -88,9 +88,10 @@ private:
 
   // Library search path. The first element is always "" (current directory).
   std::vector<StringRef> SearchPaths;
-
   std::set<std::string> VisitedFiles;
 
+  void addUndefined(StringRef Sym);
+
   // Driver is the owner of all opened files.
   // InputFiles have MemoryBufferRefs to them.
   std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;

Modified: lld/trunk/COFF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.cpp?rev=240757&r1=240756&r2=240757&view=diff
==============================================================================
--- lld/trunk/COFF/SymbolTable.cpp (original)
+++ lld/trunk/COFF/SymbolTable.cpp Thu Jun 25 22:44:00 2015
@@ -184,14 +184,6 @@ std::error_code SymbolTable::resolveLazy
 
 // Windows specific -- Link default entry point name.
 ErrorOr<StringRef> SymbolTable::findDefaultEntry() {
-  // If it's DLL, the rule is easy.
-  if (Config->DLL) {
-    StringRef Sym = "_DllMainCRTStartup";
-    if (auto EC = resolve(new (Alloc) Undefined(Sym)))
-      return EC;
-    return Sym;
-  }
-
   // User-defined main functions and their corresponding entry points.
   static const char *Entries[][2] = {
       {"main", "mainCRTStartup"},

Modified: lld/trunk/test/COFF/include2.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/include2.test?rev=240757&r1=240756&r2=240757&view=diff
==============================================================================
--- lld/trunk/test/COFF/include2.test (original)
+++ lld/trunk/test/COFF/include2.test Thu Jun 25 22:44:00 2015
@@ -9,6 +9,6 @@
 
 CHECK: include2.test.tmp1.obj
 CHECK: include2.test.tmp2.lib
-CHECK: include2.test.tmp3.lib
 CHECK: include2.test.tmp2.lib(include2.test.tmp2.obj) for foo
+CHECK: include2.test.tmp3.lib
 CHECK: include2.test.tmp3.lib(include2.test.tmp3.obj) for bar

Modified: lld/trunk/test/COFF/order.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/order.test?rev=240757&r1=240756&r2=240757&view=diff
==============================================================================
--- lld/trunk/test/COFF/order.test (original)
+++ lld/trunk/test/COFF/order.test Thu Jun 25 22:44:00 2015
@@ -9,6 +9,6 @@
 
 CHECK: order.test.tmp1.obj
 CHECK: order.test.tmp2.lib
+CHECK: order.test.tmp2.lib(order.test.tmp2.obj) for foo
 CHECK: order.test.tmp3.obj
 CHECK: order.test.tmp3.lib
-CHECK: order.test.tmp2.lib(order.test.tmp2.obj) for foo





More information about the llvm-commits mailing list