X-Git-Url: https://git.saurik.com/apple/ld64.git/blobdiff_plain/d425e3882ca60fabae080ddb890789ef2e73a66b..7f09b9353af9897bf18933788d6a59c152c29edd:/src/ld/SymbolTable.cpp diff --git a/src/ld/SymbolTable.cpp b/src/ld/SymbolTable.cpp index 2ea690f..4be0c5e 100644 --- a/src/ld/SymbolTable.cpp +++ b/src/ld/SymbolTable.cpp @@ -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() : ""; + const char* atomBpath = (_atomB.file() != NULL) ? _atomB.file()->path() : ""; + 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() : ""; + const char* atomBpath = (_atomB.file() != NULL) ? _atomB.file()->path() : ""; + 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& tents) } +void SymbolTable::mustPreserveForBitcode(std::unordered_set& 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 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; + // 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::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"); }