}
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:
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:
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:
}
+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);
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)
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");
}