]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/SymbolTable.cpp
ld64-274.2.tar.gz
[apple/ld64.git] / src / ld / SymbolTable.cpp
index 2ea690fa2eb1aea3dd2387f00dc404f0e5858ccb..4be0c5e264a1b10903b7cc1ff09aeb896540422e 100644 (file)
@@ -312,6 +312,7 @@ private:
        }
        
        void pickAtom() {
+               //fprintf(stderr, "pickAtom(), a=%p, def=%d, b=%p, def=%d\n", &_atomA, _atomA.definition(), &_atomB, _atomB.definition());
                // First, discriminate by definition
                switch (_atomA.definition()) {
                        case ld::Atom::definitionRegular:
@@ -320,6 +321,12 @@ private:
                                                pickBetweenRegularAtoms();
                                                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);
+                                               }
                                                pickAtomA();
                                                break;
                                        case ld::Atom::definitionAbsolute:
@@ -334,6 +341,12 @@ private:
                        case ld::Atom::definitionTentative:
                                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);
+                                               }
                                                pickAtomB();
                                                break;
                                        case ld::Atom::definitionTentative:
@@ -553,6 +566,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);
@@ -575,6 +600,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)
@@ -707,6 +825,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");
        }