[lld] r240177 - COFF: Continue reading object files until converge.

Rui Ueyama ruiu at google.com
Fri Jun 19 14:12:49 PDT 2015


Author: ruiu
Date: Fri Jun 19 16:12:48 2015
New Revision: 240177

URL: http://llvm.org/viewvc/llvm-project?rev=240177&view=rev
Log:
COFF: Continue reading object files until converge.

In this linker model, adding an undefined symbol may trigger chain
reactions. It may trigger a Lazy symbol to read a new file.
A new file may contain a directive section, which may contain various
command line options.

Previously, we didn't handle chain reactions well. We visited /include'd
symbols only once, so newly-added /include symbols were ignored.
This patch fixes that bug.

Now, the symbol table is versioned; every time the symbol table is
updated, the version number is incremented. We repeat adding undefined
symbols until the version number does not change. It is guaranteed to
converge -- the number of undefined symbol in the system is finite,
and adding the same undefined symbol more than once is basically no-op.

Added:
    lld/trunk/test/COFF/Inputs/include1a.yaml
    lld/trunk/test/COFF/Inputs/include1b.yaml
    lld/trunk/test/COFF/Inputs/include1c.yaml
    lld/trunk/test/COFF/include2.test
Modified:
    lld/trunk/COFF/Driver.cpp
    lld/trunk/COFF/SymbolTable.cpp
    lld/trunk/COFF/SymbolTable.h

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=240177&r1=240176&r2=240177&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Fri Jun 19 16:12:48 2015
@@ -454,11 +454,6 @@ bool LinkerDriver::link(int Argc, const
   // Create a symbol table.
   SymbolTable Symtab;
 
-  // Add undefined symbols given via the command line.
-  // (/include is equivalent to Unix linker's -u option.)
-  for (StringRef Sym : Config->Includes)
-    Symtab.addUndefined(Sym);
-
   // Windows specific -- Create a resource file containing a manifest file.
   if (Config->Manifest == Configuration::Embed) {
     auto MBOrErr = createManifestRes();
@@ -499,36 +494,46 @@ bool LinkerDriver::link(int Argc, const
     }
   }
 
-  // Windows specific -- Make sure we resolve all dllexported symbols.
-  // (We don't cache the size here because Symtab.resolve() may add
-  // new entries to Config->Exports.)
-  for (size_t I = 0; I < Config->Exports.size(); ++I) {
-    StringRef Sym = Config->Exports[I].Name;
-    Symtab.addUndefined(Sym);
-  }
-
-  // Windows specific -- If entry point name is not given, we need to
-  // infer that from user-defined entry name. The symbol table takes
-  // care of details.
-  if (Config->EntryName.empty()) {
-    auto EntryOrErr = Symtab.findDefaultEntry();
-    if (auto EC = EntryOrErr.getError()) {
-      llvm::errs() << EC.message() << "\n";
-      return false;
+  // Resolve auxiliary symbols until converge.
+  // (Trying to resolve a symbol may trigger a Lazy symbol to load a new file.
+  // A new file may contain a directive section to add new command line options.
+  // That's why we have to repeat until converge.)
+  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);
+
+    // Add weak aliases. Weak aliases is a mechanism to give remaining
+    // undefined symbols final chance to be resolved successfully.
+    // This is symbol renaming.
+    for (auto &P : Config->AlternateNames) {
+      StringRef From = P.first;
+      StringRef To = P.second;
+      if (auto EC = Symtab.rename(From, To)) {
+        llvm::errs() << EC.message() << "\n";
+        return false;
+      }
     }
-    Config->EntryName = EntryOrErr.get();
-  }
 
-  // Add weak aliases. Weak aliases is a mechanism to give remaining
-  // undefined symbols final chance to be resolved successfully.
-  // This is symbol renaming.
-  for (auto &P : Config->AlternateNames) {
-    StringRef From = P.first;
-    StringRef To = P.second;
-    if (auto EC = Symtab.rename(From, To)) {
-      llvm::errs() << EC.message() << "\n";
-      return false;
+    // Windows specific -- If entry point name is not given, we need to
+    // infer that from user-defined entry name. The symbol table takes
+    // care of details.
+    if (Config->EntryName.empty()) {
+      auto EntryOrErr = Symtab.findDefaultEntry();
+      if (auto EC = EntryOrErr.getError()) {
+        llvm::errs() << EC.message() << "\n";
+        return false;
+      }
+      Config->EntryName = EntryOrErr.get();
     }
+    if (Ver == Symtab.getVersion())
+      break;
   }
 
   // Make sure we have resolved all symbols.

Modified: lld/trunk/COFF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.cpp?rev=240177&r1=240176&r2=240177&view=diff
==============================================================================
--- lld/trunk/COFF/SymbolTable.cpp (original)
+++ lld/trunk/COFF/SymbolTable.cpp Fri Jun 19 16:12:48 2015
@@ -128,6 +128,7 @@ std::error_code SymbolTable::resolve(Sym
   if (!Sym) {
     Sym = new (Alloc) Symbol(New);
     New->setBackref(Sym);
+    ++Version;
     return std::error_code();
   }
   New->setBackref(Sym);
@@ -136,8 +137,10 @@ std::error_code SymbolTable::resolve(Sym
   // equivalent (conflicting), or more preferable, respectively.
   SymbolBody *Existing = Sym->Body;
   int comp = Existing->compare(New);
-  if (comp < 0)
+  if (comp < 0) {
     Sym->Body = New;
+    ++Version;
+  }
   if (comp == 0) {
     llvm::errs() << "duplicate symbol: " << Name << "\n";
     return make_error_code(LLDError::DuplicateSymbols);
@@ -245,6 +248,7 @@ std::error_code SymbolTable::rename(Stri
     return EC;
   Sym->Body = Body->getReplacement();
   Body->setBackref(Sym);
+  ++Version;
   return std::error_code();
 }
 

Modified: lld/trunk/COFF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.h?rev=240177&r1=240176&r2=240177&view=diff
==============================================================================
--- lld/trunk/COFF/SymbolTable.h (original)
+++ lld/trunk/COFF/SymbolTable.h Fri Jun 19 16:12:48 2015
@@ -34,8 +34,8 @@ namespace coff {
 class SymbolTable {
 public:
   SymbolTable();
-
   std::error_code addFile(std::unique_ptr<InputFile> File);
+  size_t getVersion() { return Version; }
 
   // Print an error message on undefined symbols.
   bool reportRemainingUndefines();
@@ -97,6 +97,9 @@ private:
   std::vector<std::unique_ptr<BitcodeFile>> BitcodeFiles;
   std::unique_ptr<MemoryBuffer> LTOMB;
   llvm::BumpPtrAllocator Alloc;
+
+  // This variable is incremented every time Symtab is updated.
+  size_t Version = 0;
 };
 
 } // namespace coff

Added: lld/trunk/test/COFF/Inputs/include1a.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/include1a.yaml?rev=240177&view=auto
==============================================================================
--- lld/trunk/test/COFF/Inputs/include1a.yaml (added)
+++ lld/trunk/test/COFF/Inputs/include1a.yaml Fri Jun 19 16:12:48 2015
@@ -0,0 +1,33 @@
+---
+header:
+  Machine:         IMAGE_FILE_MACHINE_AMD64
+  Characteristics: []
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     B800000000506800000000680000000050E80000000050E800000000
+  - Name:            .drectve
+    Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+    Alignment:       2147483648
+    SectionData:     2f696e636c7564653a666f6f00  # /include:foo
+symbols:
+  - Name:            .text
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          28
+      NumberOfRelocations: 4
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          0
+  - Name:            mainCRTStartup
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+...

Added: lld/trunk/test/COFF/Inputs/include1b.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/include1b.yaml?rev=240177&view=auto
==============================================================================
--- lld/trunk/test/COFF/Inputs/include1b.yaml (added)
+++ lld/trunk/test/COFF/Inputs/include1b.yaml Fri Jun 19 16:12:48 2015
@@ -0,0 +1,33 @@
+---
+header:
+  Machine:         IMAGE_FILE_MACHINE_AMD64
+  Characteristics: []
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     B800000000506800000000680000000050E80000000050E800000000
+  - Name:            .drectve
+    Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+    Alignment:       2147483648
+    SectionData:     2f696e636c7564653a62617200  # /include:bar
+symbols:
+  - Name:            .text
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          28
+      NumberOfRelocations: 4
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          0
+  - Name:            foo
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+...

Added: lld/trunk/test/COFF/Inputs/include1c.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/include1c.yaml?rev=240177&view=auto
==============================================================================
--- lld/trunk/test/COFF/Inputs/include1c.yaml (added)
+++ lld/trunk/test/COFF/Inputs/include1c.yaml Fri Jun 19 16:12:48 2015
@@ -0,0 +1,29 @@
+---
+header:
+  Machine:         IMAGE_FILE_MACHINE_AMD64
+  Characteristics: []
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     B800000000506800000000680000000050E80000000050E800000000
+symbols:
+  - Name:            .text
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          28
+      NumberOfRelocations: 4
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          0
+  - Name:            bar
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+...

Added: lld/trunk/test/COFF/include2.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/include2.test?rev=240177&view=auto
==============================================================================
--- lld/trunk/test/COFF/include2.test (added)
+++ lld/trunk/test/COFF/include2.test Fri Jun 19 16:12:48 2015
@@ -0,0 +1,14 @@
+# RUN: yaml2obj < %p/Inputs/include1a.yaml > %t1.obj
+# RUN: yaml2obj < %p/Inputs/include1b.yaml > %t2.obj
+# RUN: yaml2obj < %p/Inputs/include1c.yaml > %t3.obj
+# RUN: rm -f %t2.lib %t3.lib
+# RUN: llvm-ar cru %t2.lib %t2.obj
+# RUN: llvm-ar cru %t3.lib %t3.obj
+# RUN: lld -flavor link2 /out:%t.exe %t1.obj %t2.lib %t3.lib /verbose >& %t.log
+# RUN: FileCheck %s < %t.log
+
+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(include2.test.tmp3.obj) for bar





More information about the llvm-commits mailing list