[PATCH] Add a fallback mechanism for undefined atom.

Rui Ueyama ruiu at google.com
Thu Aug 29 14:10:41 PDT 2013


Hi shankarke,

In COFF, an undefined symbol can have up to one alternative name. If a symbol
is resolved by its regular name, then it's linked normally. If a symbol is not
found in any input files, all references to the regular name are resolved using
the alternative name. If the alternative name is not found, it's a link error.
This mechanism is called "weak externals".

To support this mechanism, I added a new member function fallback() to undefined
atom. If an undefined atom has the second name, fallback() returns a new undefined
atom that should be used instead of the original one to resolve undefines. If it
does not have the second name, the function returns nullptr.

http://llvm-reviews.chandlerc.com/D1550

Files:
  include/lld/Core/SymbolTable.h
  include/lld/Core/UndefinedAtom.h
  lib/Core/Resolver.cpp
  lib/Core/SymbolTable.cpp

Index: include/lld/Core/SymbolTable.h
===================================================================
--- include/lld/Core/SymbolTable.h
+++ include/lld/Core/SymbolTable.h
@@ -67,6 +67,9 @@
   /// @brief count of by-name entries in symbol table
   unsigned int size();
 
+  /// @brief add atom to replacement table
+  void addReplacement(const Atom *replaced, const Atom *replacement);
+
   /// @brief if atom has been coalesced away, return replacement, else return atom
   const Atom *replacement(const Atom *);
 
Index: include/lld/Core/UndefinedAtom.h
===================================================================
--- include/lld/Core/UndefinedAtom.h
+++ include/lld/Core/UndefinedAtom.h
@@ -56,6 +56,14 @@
   }
   static inline bool classof(const UndefinedAtom *) { return true; }
 
+  /// Returns an undefined atom if this undefined symbol has a synonym.  This is
+  /// mainly used in COFF. In COFF, an unresolved external symbol can have up to
+  /// one optional name (sym2) in addition to its regular name (sym1). If a
+  /// definition of sym1 exists, sym1 is resolved normally. Otherwise, all
+  /// references to sym1 refer to sym2 instead. In that case sym2 must be
+  /// resolved, or link will fail.
+  virtual UndefinedAtom *fallback() const { return nullptr; }
+
 protected:
   UndefinedAtom() : Atom(definitionUndefined) {}
   virtual ~UndefinedAtom() {}
Index: lib/Core/Resolver.cpp
===================================================================
--- lib/Core/Resolver.cpp
+++ lib/Core/Resolver.cpp
@@ -198,7 +198,7 @@
     undefineGenCount = _symbolTable.size();
     std::vector<const UndefinedAtom *> undefines;
     _symbolTable.undefines(undefines);
-    for ( const Atom *undefAtom : undefines ) {
+    for (const UndefinedAtom *undefAtom : undefines) {
       StringRef undefName = undefAtom->name();
       // load for previous undefine may also have loaded this undefine
       if (!_symbolTable.isDefined(undefName)) {
@@ -208,6 +208,14 @@
                                     false,  // dataSymbolOnly
                                     *this);
       }
+      // If the undefined symbol has an alternative name, try to resolve the
+      // symbol with the name to give it a second chance. This feature is used
+      // for COFF "weak external" symbol.
+      const UndefinedAtom *fallbackUndefAtom = undefAtom->fallback();
+      if (fallbackUndefAtom) {
+        _symbolTable.addReplacement(undefAtom, fallbackUndefAtom);
+        _symbolTable.add(*fallbackUndefAtom);
+      }
     }
     // search libraries for overrides of common symbols
     if (searchArchives || searchSharedLibs) {
Index: lib/Core/SymbolTable.cpp
===================================================================
--- lib/Core/SymbolTable.cpp
+++ lib/Core/SymbolTable.cpp
@@ -311,6 +311,11 @@
   return true;
 }
 
+void SymbolTable::addReplacement(const Atom *replaced,
+                                 const Atom *replacement) {
+  _replacedAtoms[replaced] = replacement;
+}
+
 const Atom *SymbolTable::replacement(const Atom *atom) {
   AtomToAtom::iterator pos = _replacedAtoms.find(atom);
   if (pos == _replacedAtoms.end())
@@ -328,8 +333,12 @@
        end = _nameTable.end(); it != end; ++it) {
     const Atom *atom = it->second;
     assert(atom != nullptr);
-    if (const auto undef = dyn_cast<const UndefinedAtom>(atom))
+    if (const auto undef = dyn_cast<const UndefinedAtom>(atom)) {
+      AtomToAtom::iterator pos = _replacedAtoms.find(undef);
+      if (pos != _replacedAtoms.end())
+        continue;
       undefs.push_back(undef);
+    }
   }
 }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1550.1.patch
Type: text/x-patch
Size: 3596 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130829/a1442cb5/attachment.bin>


More information about the llvm-commits mailing list