ld64-302.3.1.tar.gz
[apple/ld64.git] / src / ld / SymbolTable.cpp
index 309de8b6835fa155c00733903cdb9d79d60cdac3..3c12a777d930e6e38915dca081c034d30a3b3cf1 100644 (file)
@@ -132,7 +132,7 @@ void SymbolTable::addDuplicateSymbol(const char *name, const ld::Atom *atom)
     // check if file is already in the list, add it if not
     bool found = false;
     for (DuplicatedSymbolAtomList::iterator it = atoms->begin(); !found && it != atoms->end(); it++)
-        if (strcmp((*it)->file()->path(), atom->file()->path()) == 0)
+        if (strcmp((*it)->safeFilePath(), atom->safeFilePath()) == 0)
             found = true;
     if (!found)
         atoms->push_back(atom);
@@ -158,7 +158,7 @@ void SymbolTable::checkDuplicateSymbols() const
             foundDuplicate = true;
             fprintf(stderr, "duplicate symbol %s in:\n", symbolIt->first);
             for (DuplicatedSymbolAtomList::iterator atomIt = atoms->begin(); atomIt != atoms->end(); atomIt++) {
-                fprintf(stderr, "    %s\n", (*atomIt)->file()->path());
+                fprintf(stderr, "    %s\n", (*atomIt)->safeFilePath());
             }
         }
     }
@@ -284,18 +284,18 @@ private:
                        case Options::kCommonsIgnoreDylibs:
                                if ( _options.warnCommons() )
                                        warning("using common symbol %s from %s and ignoring defintion from dylib %s",
-                                                       proxy.name(), proxy.file()->path(), dylib.file()->path());
+                                                       proxy.name(), proxy.safeFilePath(), dylib.safeFilePath());
                                pickAtom(dylib);
                                break;
                        case Options::kCommonsOverriddenByDylibs:
                                if ( _options.warnCommons() )
                                        warning("replacing common symbol %s from %s with true definition from dylib %s",
-                                                       proxy.name(), proxy.file()->path(), dylib.file()->path());
+                                                       proxy.name(), proxy.safeFilePath(), dylib.safeFilePath());
                                pickAtom(proxy);
                                break;
                        case Options::kCommonsConflictsDylibsError:
                                throwf("common symbol %s from %s conflicts with defintion from dylib %s",
-                                          proxy.name(), proxy.file()->path(), dylib.file()->path());
+                                          proxy.name(), proxy.safeFilePath(), dylib.safeFilePath());
                }
        }
        
@@ -307,7 +307,7 @@ private:
                } else if ( _atomB.combine() == ld::Atom::combineByName ) {
                        pickAtomA();
                } else {
-                               throwf("symbol %s exported from both %s and %s\n", _atomA.name(), _atomA.file()->path(), _atomB.file()->path());
+                               throwf("symbol %s exported from both %s and %s\n", _atomA.name(), _atomA.safeFilePath(), _atomB.safeFilePath());
                }
        }
        
@@ -322,10 +322,8 @@ private:
                                                break;
                                        case ld::Atom::definitionTentative:
                                                if ( _atomB.size() > _atomA.size() ) {
-                                                       const char* atomApath = (_atomA.file() != NULL) ? _atomA.file()->path() : "<internal>";
-                                                       const char* atomBpath = (_atomB.file() != NULL) ? _atomB.file()->path() : "<internal>";
                                                        warning("tentative definition of '%s' with size %llu from '%s' is being replaced by real definition of smaller size %llu from '%s'",
-                                                                       _atomA.name(), _atomB.size(), atomBpath, _atomA.size(), atomApath);
+                                                                       _atomA.name(), _atomB.size(), _atomB.safeFilePath(), _atomA.size(), _atomA.safeFilePath());
                                                }
                                                pickAtomA();
                                                break;
@@ -342,10 +340,8 @@ private:
                                switch (_atomB.definition()) {
                                        case ld::Atom::definitionRegular:
                                                if ( _atomA.size() > _atomB.size() ) {
-                                                       const char* atomApath = (_atomA.file() != NULL) ? _atomA.file()->path() : "<internal>";
-                                                       const char* atomBpath = (_atomB.file() != NULL) ? _atomB.file()->path() : "<internal>";
                                                        warning("tentative definition of '%s' with size %llu from '%s' is being replaced by real definition of smaller size %llu from '%s'",
-                                                                       _atomA.name(), _atomA.size(),atomApath, _atomB.size(), atomBpath);
+                                                                       _atomA.name(), _atomA.size(),_atomA.safeFilePath(), _atomB.size(), _atomB.safeFilePath());
                                                }
                                                pickAtomB();
                                                break;
@@ -505,7 +501,7 @@ bool SymbolTable::add(const ld::Atom& atom, bool ignoreDuplicates)
 void SymbolTable::markCoalescedAway(const ld::Atom* atom)
 {
        // remove this from list of all atoms used
-       //fprintf(stderr, "markCoalescedAway(%p) from %s\n", atom, atom->file()->path());
+       //fprintf(stderr, "markCoalescedAway(%p) from %s\n", atom, atom->safeFilePath());
        (const_cast<ld::Atom*>(atom))->setCoalescedAway();
        
        //
@@ -566,6 +562,18 @@ void SymbolTable::tentativeDefs(std::vector<const char*>& tents)
 }
 
 
+void SymbolTable::mustPreserveForBitcode(std::unordered_set<const char*>& syms)
+{
+       // return all names in _byNameTable that have no associated atom
+       for (const auto &entry: _byNameTable) {
+               const char* name = entry.first;
+               const ld::Atom* atom = _indirectBindingTable[entry.second];
+               if ( (atom == NULL) || (atom->definition() == ld::Atom::definitionProxy) )
+                       syms.insert(name);
+       }
+}
+
+
 bool SymbolTable::hasName(const char* name)                    
 { 
        NameToSlot::iterator pos = _byNameTable.find(name);
@@ -588,6 +596,99 @@ SymbolTable::IndirectBindingSlot SymbolTable::findSlotForName(const char* name)
        return slot;
 }
 
+void SymbolTable::removeDeadAtoms()
+{
+       // remove dead atoms from: _byNameTable, _byNameReverseTable, and _indirectBindingTable
+       std::vector<const char*> namesToRemove;
+       for (NameToSlot::iterator it=_byNameTable.begin(); it != _byNameTable.end(); ++it) {
+               IndirectBindingSlot slot = it->second;
+               const ld::Atom* atom = _indirectBindingTable[slot];
+               if ( atom != NULL ) {
+                       if ( !atom->live() && !atom->dontDeadStrip() ) {
+                               //fprintf(stderr, "removing from symbolTable[%u] %s\n", slot, atom->name());
+                               _indirectBindingTable[slot] = NULL;
+                               // <rdar://problem/16025786> need to completely remove dead atoms from symbol table
+                               _byNameReverseTable.erase(slot);
+                               // can't remove while iterating, do it after iteration
+                               namesToRemove.push_back(it->first);
+                       }
+               }
+       }
+       for (std::vector<const char*>::iterator it = namesToRemove.begin(); it != namesToRemove.end(); ++it) {
+               _byNameTable.erase(*it);
+       }
+
+       // remove dead atoms from _nonLazyPointerTable
+       for (ReferencesToSlot::iterator it=_nonLazyPointerTable.begin(); it != _nonLazyPointerTable.end(); ) {
+               const ld::Atom* atom = it->first;
+               assert(atom != NULL);
+               if ( !atom->live() && !atom->dontDeadStrip() )
+                       it = _nonLazyPointerTable.erase(it);
+               else
+                       ++it;
+       }
+
+       // remove dead atoms from _cstringTable
+       for (CStringToSlot::iterator it=_cstringTable.begin(); it != _cstringTable.end(); ) {
+               const ld::Atom* atom = it->first;
+               assert(atom != NULL);
+               if ( !atom->live() && !atom->dontDeadStrip() )
+                       it = _cstringTable.erase(it);
+               else
+                       ++it;
+       }
+
+       // remove dead atoms from _utf16Table
+       for (UTF16StringToSlot::iterator it=_utf16Table.begin(); it != _utf16Table.end(); ) {
+               const ld::Atom* atom = it->first;
+               assert(atom != NULL);
+               if ( !atom->live() && !atom->dontDeadStrip() )
+                       it = _utf16Table.erase(it);
+               else
+                       ++it;
+       }
+
+       // remove dead atoms from _cfStringTable
+       for (ReferencesToSlot::iterator it=_cfStringTable.begin(); it != _cfStringTable.end(); ) {
+               const ld::Atom* atom = it->first;
+               assert(atom != NULL);
+               if ( !atom->live() && !atom->dontDeadStrip() )
+                       it = _cfStringTable.erase(it);
+               else
+                       ++it;
+       }
+
+       // remove dead atoms from _literal4Table
+       for (ContentToSlot::iterator it=_literal4Table.begin(); it != _literal4Table.end(); ) {
+               const ld::Atom* atom = it->first;
+               assert(atom != NULL);
+               if ( !atom->live() && !atom->dontDeadStrip() )
+                       it = _literal4Table.erase(it);
+               else
+                       ++it;
+       }
+
+       // remove dead atoms from _literal8Table
+       for (ContentToSlot::iterator it=_literal8Table.begin(); it != _literal8Table.end(); ) {
+               const ld::Atom* atom = it->first;
+               assert(atom != NULL);
+               if ( !atom->live() && !atom->dontDeadStrip() )
+                       it = _literal8Table.erase(it);
+               else
+                       ++it;
+       }
+
+       // remove dead atoms from _literal16Table
+       for (ContentToSlot::iterator it=_literal16Table.begin(); it != _literal16Table.end(); ) {
+               const ld::Atom* atom = it->first;
+               assert(atom != NULL);
+               if ( !atom->live() && !atom->dontDeadStrip() )
+                       it = _literal16Table.erase(it);
+               else
+                       ++it;
+       }
+}
+
 
 // find existing or create new slot
 SymbolTable::IndirectBindingSlot SymbolTable::findSlotForContent(const ld::Atom* atom, const ld::Atom** existingAtom)
@@ -720,6 +821,15 @@ SymbolTable::IndirectBindingSlot SymbolTable::findSlotForReferences(const ld::At
                        slot = _indirectBindingTable.size();
                        _pointerToCStringTable[atom] = slot;
                        break;
+               case ld::Section::typeTLVPointers:
+                       pos = _threadPointerTable.find(atom);
+                       if ( pos != _threadPointerTable.end() ) {
+                               *existingAtom = _indirectBindingTable[pos->second];
+                               return pos->second;
+                       }
+                       slot = _indirectBindingTable.size();
+                       _threadPointerTable[atom] = slot;
+                       break;
                default:
                        assert(0 && "section type does not support coalescing by references");
        }
@@ -779,7 +889,7 @@ void SymbolTable::printStatistics()
        //ReferencesHash obj;
        //for(ReferencesHashToSlot::iterator it=_byReferencesTable.begin(); it != _byReferencesTable.end(); ++it) {
        //      if ( obj.operator()(it->first) == 0x2F3AC0EAC744EA70 ) {
-       //              fprintf(stderr, "hash=0x2F3AC0EAC744EA70 for %p %s from %s\n", it->first, it->first->name(), it->first->file()->path());
+       //              fprintf(stderr, "hash=0x2F3AC0EAC744EA70 for %p %s from %s\n", it->first, it->first->name(), it->first->safeFilePath());
        //      
        //      }
        //}