]> git.saurik.com Git - apple/ld64.git/blobdiff - ld64-134.9/src/ld/SymbolTable.cpp
ld64-136.tar.gz
[apple/ld64.git] / ld64-134.9 / src / ld / SymbolTable.cpp
diff --git a/ld64-134.9/src/ld/SymbolTable.cpp b/ld64-134.9/src/ld/SymbolTable.cpp
deleted file mode 100644 (file)
index 406556a..0000000
+++ /dev/null
@@ -1,780 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-*
- *
- * Copyright (c) 2009-2010 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <sys/sysctl.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <limits.h>
-#include <unistd.h>
-#include <assert.h>
-
-#include <iostream>
-#include <sstream>
-#include <string>
-#include <map>
-#include <set>
-#include <vector>
-#include <algorithm>
-#include <ext/hash_map>
-#include <ext/hash_set>
-
-#include "Options.h"
-
-#include "ld.hpp"
-#include "InputFiles.h"
-#include "SymbolTable.h"
-
-
-
-namespace ld {
-namespace tool {
-
-
-// HACK, I can't find a way to pass values in the compare classes (e.g. ContentFuncs)
-// so use global variable to pass info.
-static ld::IndirectBindingTable*       _s_indirectBindingTable = NULL;
-
-
-SymbolTable::SymbolTable(const Options& opts, std::vector<const ld::Atom*>& ibt) 
-       : _options(opts), _cstringTable(6151), _indirectBindingTable(ibt), _hasExternalTentativeDefinitions(false)
-{  
-       _s_indirectBindingTable = this;
-}
-
-
-size_t SymbolTable::ContentFuncs::operator()(const ld::Atom* atom) const
-{
-       return atom->contentHash(*_s_indirectBindingTable);
-}
-
-bool SymbolTable::ContentFuncs::operator()(const ld::Atom* left, const ld::Atom* right) const
-{
-       return (memcmp(left->rawContentPointer(), right->rawContentPointer(), left->size()) == 0);
-}
-
-
-
-size_t SymbolTable::CStringHashFuncs::operator()(const ld::Atom* atom) const
-{
-       return atom->contentHash(*_s_indirectBindingTable);
-}
-
-bool SymbolTable::CStringHashFuncs::operator()(const ld::Atom* left, const ld::Atom* right) const
-{
-       return (strcmp((char*)left->rawContentPointer(), (char*)right->rawContentPointer()) == 0);
-}
-
-
-size_t SymbolTable::UTF16StringHashFuncs::operator()(const ld::Atom* atom) const
-{
-       return atom->contentHash(*_s_indirectBindingTable);
-}
-
-bool SymbolTable::UTF16StringHashFuncs::operator()(const ld::Atom* left, const ld::Atom* right) const
-{
-       if ( left == right )
-               return true;
-       const void* leftContent = left->rawContentPointer();
-       const void* rightContent = right->rawContentPointer();
-       unsigned int amount = left->size()-2;
-       bool result = (memcmp(leftContent, rightContent, amount) == 0);
-       return result;
-}
-
-
-size_t SymbolTable::ReferencesHashFuncs::operator()(const ld::Atom* atom) const
-{
-       return atom->contentHash(*_s_indirectBindingTable);
-}
-
-bool SymbolTable::ReferencesHashFuncs::operator()(const ld::Atom* left, const ld::Atom* right) const
-{
-       return left->canCoalesceWith(*right, *_s_indirectBindingTable);
-}
-
-
-void SymbolTable::addDuplicateSymbol(const char *name, const ld::Atom *atom)
-{
-    // Look up or create the file list for name.
-    DuplicateSymbols::iterator symbolsIterator = _duplicateSymbols.find(name);
-    DuplicatedSymbolAtomList *atoms = NULL;
-    if (symbolsIterator != _duplicateSymbols.end()) {
-        atoms = symbolsIterator->second;
-    } else {
-        atoms = new std::vector<const ld::Atom *>;
-        _duplicateSymbols.insert(std::pair<const char *, DuplicatedSymbolAtomList *>(name, atoms));
-    }
-    
-    // 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)
-            found = true;
-    if (!found)
-        atoms->push_back(atom);
-}
-
-void SymbolTable::checkDuplicateSymbols() const
-{
-    bool foundDuplicate = false;
-    for (DuplicateSymbols::const_iterator symbolIt = _duplicateSymbols.begin(); symbolIt != _duplicateSymbols.end(); symbolIt++) {
-        DuplicatedSymbolAtomList *atoms = symbolIt->second;
-        bool reportDuplicate;
-        if (_options.deadCodeStrip()) {
-            // search for a live atom
-            reportDuplicate = false;
-            for (DuplicatedSymbolAtomList::iterator it = atoms->begin(); !reportDuplicate && it != atoms->end(); it++) {
-                if ((*it)->live())
-                    reportDuplicate = true;
-            }
-        } else {
-            reportDuplicate = true;
-        }
-        if (reportDuplicate) {
-            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());
-            }
-        }
-    }
-    if (foundDuplicate)
-        throwf("%d duplicate symbol%s", (int)_duplicateSymbols.size(), _duplicateSymbols.size()==1?"":"s");
-}
-
-// AtomPicker encapsulates the logic for picking which atom to use when adding an atom by name results in a collision
-class NameCollisionResolution {
-public:
-       NameCollisionResolution(const ld::Atom& a, const ld::Atom& b, bool ignoreDuplicates, const Options& options) : _atomA(a), _atomB(b), _options(options), _reportDuplicate(false), _ignoreDuplicates(ignoreDuplicates) {
-               pickAtom();
-       }
-       
-       // Returns which atom to use
-       const ld::Atom& chosen() { return *_chosen; }
-       bool choseAtom(const ld::Atom& atom) { return _chosen == &atom; }
-
-       // Returns true if the two atoms should be reported as a duplicate symbol
-       bool reportDuplicate()  { return _reportDuplicate; }
-       
-private:
-       const ld::Atom& _atomA;
-       const ld::Atom& _atomB;
-       const Options& _options;
-       const ld::Atom* _chosen;
-       bool _reportDuplicate;
-       bool _ignoreDuplicates;
-
-       void pickAtom(const ld::Atom& atom) { _chosen = &atom; } // primitive to set which atom is picked
-       void pickAtomA() { pickAtom(_atomA); }  // primitive to pick atom A
-       void pickAtomB() { pickAtom(_atomB); }  // primitive to pick atom B
-       
-       // use atom A if pickA, otherwise use atom B
-       void pickAOrB(bool pickA) { if (pickA) pickAtomA(); else pickAtomB(); }
-       
-       void pickHigherOrdinal() {
-               pickAOrB(_atomA.file()->ordinal() < _atomB.file()->ordinal());
-       }
-       
-       void pickLowerOrdinal() {
-               pickAOrB(_atomA.file()->ordinal() > _atomB.file()->ordinal());
-       }
-       
-       void pickLargerSize() {
-               if (_atomA.size() == _atomB.size())
-                       pickLowerOrdinal();
-               else
-                       pickAOrB(_atomA.size() > _atomB.size());
-       }
-       
-       void pickGreaterAlignment() {
-               pickAOrB(_atomA.alignment().trailingZeros() > _atomB.alignment().trailingZeros());
-       }
-       
-       void pickBetweenRegularAtoms() {
-               if ( _atomA.combine() == ld::Atom::combineByName ) {
-                       if ( _atomB.combine() == ld::Atom::combineByName ) {
-                               // <rdar://problem/9183821> always choose mach-o over llvm bit code, otherwise LTO may eliminate the llvm atom
-                               const bool aIsLTO = (_atomA.contentType() == ld::Atom::typeLTOtemporary);
-                               const bool bIsLTO = (_atomB.contentType() == ld::Atom::typeLTOtemporary);
-                               // <rdar://problem/9183821> always choose mach-o over llvm bit code, otherwise LTO may eliminate the llvm atom
-                               if ( aIsLTO != bIsLTO ) {
-                                       pickAOrB(!aIsLTO);
-                               }
-                               else {
-                                       // both weak, prefer non-auto-hide one
-                                       if ( _atomA.autoHide() != _atomB.autoHide() ) {
-                                               // <rdar://problem/6783167> support auto hidden weak symbols: .weak_def_can_be_hidden
-                                               pickAOrB(!_atomA.autoHide());
-                                       }
-                                       else if ( _atomA.autoHide() && _atomB.autoHide() ) {
-                                               // both have auto-hide, so use one with greater alignment
-                                               pickGreaterAlignment();
-                                       }
-                                       else {
-                                               // neither auto-hide, check visibility
-                                               if ( _atomA.scope() != _atomB.scope() ) {
-                                                       // <rdar://problem/8304984> use more visible weak def symbol
-                                                       pickAOrB(_atomA.scope() == ld::Atom::scopeGlobal);
-                                               }
-                                               else {
-                                                       // both have same visibility, use one with greater alignment
-                                                       pickGreaterAlignment();
-                                               }
-                                       }
-                               }
-                       }
-                       else {
-                               pickAtomB(); // pick not-weak
-
-                       }
-               }
-               else {
-                       if ( _atomB.combine() == ld::Atom::combineByName ) {
-                               pickAtomA(); // pick not-weak
-
-                       }
-                       else {
-                               // both are not-weak
-                               if ( _atomA.section().type() == ld::Section::typeMachHeader ) {
-                                       pickAtomA();
-                               } 
-                               else if ( _atomB.section().type() == ld::Section::typeMachHeader ) {
-                                       pickAtomB();
-                               } 
-                               else {
-                                       if ( _ignoreDuplicates ) {
-                                               pickLowerOrdinal();
-                                       }
-                                       else {
-                                               _reportDuplicate = true;
-                                       }
-                               }
-                       }
-               }
-       }
-       
-       void pickCommonsMode(const ld::Atom& dylib, const ld::Atom& proxy) {
-               assert(dylib.definition() == ld::Atom::definitionTentative);
-               assert(proxy.definition() == ld::Atom::definitionProxy);
-               switch ( _options.commonsMode() ) {
-                       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());
-                               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());
-                               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());
-               }
-       }
-       
-       void pickProxyAtom() {
-               // both atoms are definitionProxy
-               // <rdar://problem/5137732> ld should keep looking when it finds a weak definition in a dylib
-               if ( _atomA.combine() == ld::Atom::combineByName ) {
-                       pickAtomB();
-               } 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());
-               }
-       }
-       
-       void pickAtom() {
-               // First, discriminate by definition
-               switch (_atomA.definition()) {
-                       case ld::Atom::definitionRegular:
-                               switch (_atomB.definition()) {
-                                       case ld::Atom::definitionRegular:
-                                               pickBetweenRegularAtoms();
-                                               break;
-                                       case ld::Atom::definitionTentative:
-                                               pickAtomA();
-                                               break;
-                                       case ld::Atom::definitionAbsolute:
-                                               _reportDuplicate = true;
-                                               pickHigherOrdinal();
-                                               break;
-                                       case ld::Atom::definitionProxy:
-                                               pickAtomA();
-                                               break;
-                               }
-                               break;
-                       case ld::Atom::definitionTentative:
-                               switch (_atomB.definition()) {
-                                       case ld::Atom::definitionRegular:
-                                               pickAtomB();
-                                               break;
-                                       case ld::Atom::definitionTentative:
-                                               pickLargerSize();
-                                               break;
-                                       case ld::Atom::definitionAbsolute:
-                                               pickHigherOrdinal();
-                                               break;
-                                       case ld::Atom::definitionProxy:
-                                               pickCommonsMode(_atomA, _atomB);
-                                               break;
-                               }
-                               break;
-                       case ld::Atom::definitionAbsolute:
-                               switch (_atomB.definition()) {
-                                       case ld::Atom::definitionRegular:
-                                               _reportDuplicate = true;
-                                               pickHigherOrdinal();
-                                               break;
-                                       case ld::Atom::definitionTentative:
-                                               pickAtomA();
-                                               break;
-                                       case ld::Atom::definitionAbsolute:
-                                               _reportDuplicate = true;
-                                               pickHigherOrdinal();
-                                               break;
-                                       case ld::Atom::definitionProxy:
-                                               pickAtomA();
-                                               break;
-                               }
-                               break;
-                       case ld::Atom::definitionProxy:
-                               switch (_atomB.definition()) {
-                                       case ld::Atom::definitionRegular:
-                                               pickAtomB();
-                                               break;
-                                       case ld::Atom::definitionTentative:
-                                               pickCommonsMode(_atomB, _atomA);
-                                               break;
-                                       case ld::Atom::definitionAbsolute:
-                                               pickAtomB();
-                                               break;
-                                       case ld::Atom::definitionProxy:
-                                               pickProxyAtom();
-                                               break;
-                               }
-                               break;
-               }
-       }
-};
-
-bool SymbolTable::addByName(const ld::Atom& newAtom, bool ignoreDuplicates)
-{
-       bool useNew = true;
-       assert(newAtom.name() != NULL);
-       const char* name = newAtom.name();
-       IndirectBindingSlot slot = this->findSlotForName(name);
-       const ld::Atom* existingAtom = _indirectBindingTable[slot];
-       //fprintf(stderr, "addByName(%p) name=%s, slot=%u, existing=%p\n", &newAtom, newAtom.name(), slot, existingAtom);
-       if ( existingAtom != NULL ) {
-               assert(&newAtom != existingAtom);
-               NameCollisionResolution picker(newAtom, *existingAtom, ignoreDuplicates, _options);
-               if (picker.reportDuplicate()) {
-                       addDuplicateSymbol(name, existingAtom);
-                       addDuplicateSymbol(name, &newAtom);
-               }
-               useNew = picker.choseAtom(newAtom);
-       }
-       if ( useNew ) {
-               _indirectBindingTable[slot] = &newAtom;
-               if ( existingAtom != NULL ) {
-                       markCoalescedAway(existingAtom);
-               }
-               if ( newAtom.scope() == ld::Atom::scopeGlobal ) {
-                       if ( newAtom.definition() == ld::Atom::definitionTentative ) {
-                               _hasExternalTentativeDefinitions = true;
-                       }
-               }
-       }
-       else {
-               markCoalescedAway(&newAtom);
-       }
-       // return if existing atom in symbol table was replaced
-       return useNew && (existingAtom != NULL);
-}
-
-
-bool SymbolTable::addByContent(const ld::Atom& newAtom)
-{
-       bool useNew = true;
-       const ld::Atom* existingAtom;
-       IndirectBindingSlot slot = this->findSlotForContent(&newAtom, &existingAtom);
-       //fprintf(stderr, "addByContent(%p) name=%s, slot=%u, existing=%p\n", &newAtom, newAtom.name(), slot, existingAtom);
-       if ( existingAtom != NULL ) {
-               // use existing unless new one has greater alignment requirements
-               useNew = ( newAtom.alignment().trailingZeros() > existingAtom->alignment().trailingZeros() );
-       }
-       if ( useNew ) {
-               _indirectBindingTable[slot] = &newAtom;
-               if ( existingAtom != NULL ) 
-                       markCoalescedAway(existingAtom);
-       }
-       else {
-               _indirectBindingTable[slot] = existingAtom;
-               if ( existingAtom != &newAtom )
-                       markCoalescedAway(&newAtom);
-       }
-       // return if existing atom in symbol table was replaced
-       return useNew && (existingAtom != NULL);
-}
-
-bool SymbolTable::addByReferences(const ld::Atom& newAtom)
-{
-       bool useNew = true;
-       const ld::Atom* existingAtom;
-       IndirectBindingSlot slot = this->findSlotForReferences(&newAtom, &existingAtom);
-       //fprintf(stderr, "addByReferences(%p) name=%s, slot=%u, existing=%p\n", &newAtom, newAtom.name(), slot, existingAtom);
-       if ( existingAtom != NULL ) {
-               // use existing unless new one has greater alignment requirements
-               useNew = ( newAtom.alignment().trailingZeros() > existingAtom->alignment().trailingZeros() );
-       }
-       if ( useNew ) {
-               _indirectBindingTable[slot] = &newAtom;
-               if ( existingAtom != NULL ) 
-                       markCoalescedAway(existingAtom);
-       }
-       else {
-               if ( existingAtom != &newAtom )
-                       markCoalescedAway(&newAtom);
-       }
-       // return if existing atom in symbol table was replaced
-       return useNew && (existingAtom != NULL);
-}
-
-
-bool SymbolTable::add(const ld::Atom& atom, bool ignoreDuplicates)
-{
-       //fprintf(stderr, "SymbolTable::add(%p), name=%s\n", &atom, atom.name());
-       assert(atom.scope() != ld::Atom::scopeTranslationUnit);
-       switch ( atom.combine() ) {
-               case ld::Atom::combineNever:
-               case ld::Atom::combineByName:
-                       return this->addByName(atom, ignoreDuplicates);
-                       break;
-               case ld::Atom::combineByNameAndContent:
-                       return this->addByContent(atom);
-                       break;
-               case ld::Atom::combineByNameAndReferences:
-                       return this->addByReferences(atom);
-                       break;
-       }
-
-       return false;
-}
-
-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());
-       (const_cast<ld::Atom*>(atom))->setCoalescedAway();
-       
-       //
-       // The fixupNoneGroupSubordinate* fixup kind is used to model group comdat.  
-       // The "signature" atom in the group has a fixupNoneGroupSubordinate* fixup to
-       // all other members of the group.  So, if the signature atom is 
-       // coalesced away, all other atoms in the group should also be removed.  
-       //
-       for (ld::Fixup::iterator fit=atom->fixupsBegin(), fend=atom->fixupsEnd(); fit != fend; ++fit) { 
-               switch ( fit->kind ) {
-                       case ld::Fixup::kindNoneGroupSubordinate:
-                       case ld::Fixup::kindNoneGroupSubordinateFDE:
-                       case ld::Fixup::kindNoneGroupSubordinateLSDA:
-                               assert(fit->binding == ld::Fixup::bindingDirectlyBound);
-                               this->markCoalescedAway(fit->u.target);
-                               break;
-                       default:
-                               break;
-               }
-       }
-
-}
-
-
-struct StrcmpSorter {
-               bool operator() (const char* i,const char* j) {
-                       if (i==NULL)
-                               return true;
-                       if (j==NULL)
-                               return false;
-                       return strcmp(i, j)<0;}
-};
-
-void SymbolTable::undefines(std::vector<const char*>& undefs)
-{
-       // return all names in _byNameTable that have no associated atom
-       for (NameToSlot::iterator it=_byNameTable.begin(); it != _byNameTable.end(); ++it) {
-               //fprintf(stderr, "  _byNameTable[%s] = slot %d which has atom %p\n", it->first, it->second, _indirectBindingTable[it->second]);
-               if ( _indirectBindingTable[it->second] == NULL )
-                       undefs.push_back(it->first);
-       }
-       // sort so that undefines are in a stable order (not dependent on hashing functions)
-       struct StrcmpSorter strcmpSorter;
-       std::sort(undefs.begin(), undefs.end(), strcmpSorter);
-}
-
-
-void SymbolTable::tentativeDefs(std::vector<const char*>& tents)
-{
-       // return all names in _byNameTable that have no associated atom
-       for (NameToSlot::iterator it=_byNameTable.begin(); it != _byNameTable.end(); ++it) {
-               const char* name = it->first;
-               const ld::Atom* atom = _indirectBindingTable[it->second];
-               if ( (atom != NULL) && (atom->definition() == ld::Atom::definitionTentative) )
-                       tents.push_back(name);
-       }
-       std::sort(tents.begin(), tents.end());
-}
-
-
-bool SymbolTable::hasName(const char* name)                    
-{ 
-       NameToSlot::iterator pos = _byNameTable.find(name);
-       if ( pos == _byNameTable.end() ) 
-               return false;
-       return (_indirectBindingTable[pos->second] != NULL); 
-}
-
-// find existing or create new slot
-SymbolTable::IndirectBindingSlot SymbolTable::findSlotForName(const char* name)
-{
-       NameToSlot::iterator pos = _byNameTable.find(name);
-       if ( pos != _byNameTable.end() ) 
-               return pos->second;
-       // create new slot for this name
-       SymbolTable::IndirectBindingSlot slot = _indirectBindingTable.size();
-       _indirectBindingTable.push_back(NULL);
-       _byNameTable[name] = slot;
-       _byNameReverseTable[slot] = name;
-       return slot;
-}
-
-
-// find existing or create new slot
-SymbolTable::IndirectBindingSlot SymbolTable::findSlotForContent(const ld::Atom* atom, const ld::Atom** existingAtom)
-{
-       //fprintf(stderr, "findSlotForContent(%p)\n", atom);
-       SymbolTable::IndirectBindingSlot slot = 0;
-       UTF16StringToSlot::iterator upos;
-       CStringToSlot::iterator cspos;
-       ContentToSlot::iterator pos;
-       switch ( atom->section().type() ) {
-               case ld::Section::typeCString:
-                       cspos = _cstringTable.find(atom);
-                       if ( cspos != _cstringTable.end() ) {
-                               *existingAtom = _indirectBindingTable[cspos->second];
-                               return cspos->second;
-                       }
-                       slot = _indirectBindingTable.size();
-                       _cstringTable[atom] = slot;
-                       break;
-               case ld::Section::typeNonStdCString:
-                       {
-                               // use seg/sect name is key to map to avoid coalescing across segments and sections
-                               char segsect[64];
-                               sprintf(segsect, "%s/%s", atom->section().segmentName(), atom->section().sectionName());
-                               NameToMap::iterator mpos = _nonStdCStringSectionToMap.find(segsect);
-                               CStringToSlot* map = NULL;
-                               if ( mpos == _nonStdCStringSectionToMap.end() ) {
-                                       map = new CStringToSlot();
-                                       _nonStdCStringSectionToMap[strdup(segsect)] = map;
-                               }
-                               else {
-                                       map = mpos->second;
-                               }
-                               cspos = map->find(atom);
-                               if ( cspos != map->end() ) {
-                                       *existingAtom = _indirectBindingTable[cspos->second];
-                                       return cspos->second;
-                               }
-                               slot = _indirectBindingTable.size();
-                               map->operator[](atom) = slot;
-                       }
-                       break;
-               case ld::Section::typeUTF16Strings:
-                       upos = _utf16Table.find(atom);
-                       if ( upos != _utf16Table.end() ) {
-                               *existingAtom = _indirectBindingTable[upos->second];
-                               return upos->second;
-                       }
-                       slot = _indirectBindingTable.size();
-                       _utf16Table[atom] = slot;
-                       break;
-               case ld::Section::typeLiteral4:
-                       pos = _literal4Table.find(atom);
-                       if ( pos != _literal4Table.end() ) {
-                               *existingAtom = _indirectBindingTable[pos->second];
-                               return pos->second;
-                       }
-                       slot = _indirectBindingTable.size();
-                       _literal4Table[atom] = slot;
-                       break;
-               case ld::Section::typeLiteral8:
-                       pos = _literal8Table.find(atom);
-                       if ( pos != _literal8Table.end() ) {
-                               *existingAtom = _indirectBindingTable[pos->second];
-                               return pos->second;
-                       }
-                       slot = _indirectBindingTable.size();
-                       _literal8Table[atom] = slot;
-                       break;
-               case ld::Section::typeLiteral16:
-                       pos = _literal16Table.find(atom);
-                       if ( pos != _literal16Table.end() ) {
-                               *existingAtom = _indirectBindingTable[pos->second];
-                               return pos->second;
-                       }
-                       slot = _indirectBindingTable.size();
-                       _literal16Table[atom] = slot;
-                       break;
-               default:
-                       assert(0 && "section type does not support coalescing by content");
-       }
-       _indirectBindingTable.push_back(atom); 
-       *existingAtom = NULL;
-       return slot;
-}
-
-
-
-// find existing or create new slot
-SymbolTable::IndirectBindingSlot SymbolTable::findSlotForReferences(const ld::Atom* atom, const ld::Atom** existingAtom)
-{
-       //fprintf(stderr, "findSlotForReferences(%p)\n", atom);
-       
-       SymbolTable::IndirectBindingSlot slot = 0;
-       ReferencesToSlot::iterator pos;
-       switch ( atom->section().type() ) {
-               case ld::Section::typeNonLazyPointer:           
-                       pos = _nonLazyPointerTable.find(atom);
-                       if ( pos != _nonLazyPointerTable.end() ) {
-                               *existingAtom = _indirectBindingTable[pos->second];
-                               return pos->second;
-                       }
-                       slot = _indirectBindingTable.size();
-                       _nonLazyPointerTable[atom] = slot;
-                       break;
-               case ld::Section::typeCFString:
-                       pos = _cfStringTable.find(atom);
-                       if ( pos != _cfStringTable.end() ) {
-                               *existingAtom = _indirectBindingTable[pos->second];
-                               return pos->second;
-                       }
-                       slot = _indirectBindingTable.size();
-                       _cfStringTable[atom] = slot;
-                       break;
-               case ld::Section::typeObjCClassRefs:
-                       pos = _objc2ClassRefTable.find(atom);
-                       if ( pos != _objc2ClassRefTable.end() ) {
-                               *existingAtom = _indirectBindingTable[pos->second];
-                               return pos->second;
-                       }
-                       slot = _indirectBindingTable.size();
-                       _objc2ClassRefTable[atom] = slot;
-                       break;
-               case ld::Section::typeCStringPointer:
-                       pos = _pointerToCStringTable.find(atom);
-                       if ( pos != _pointerToCStringTable.end() ) {
-                               *existingAtom = _indirectBindingTable[pos->second];
-                               return pos->second;
-                       }
-                       slot = _indirectBindingTable.size();
-                       _pointerToCStringTable[atom] = slot;
-                       break;
-               default:
-                       assert(0 && "section type does not support coalescing by references");
-       }
-       _indirectBindingTable.push_back(atom);
-       *existingAtom = NULL;
-       return slot;
-}
-
-
-const char*    SymbolTable::indirectName(IndirectBindingSlot slot) const
-{
-       assert(slot < _indirectBindingTable.size());
-       const ld::Atom* target = _indirectBindingTable[slot];
-       if ( target != NULL )  {
-               return target->name();
-       }
-       // handle case when by-name reference is indirected and no atom yet in _byNameTable
-       SlotToName::const_iterator pos = _byNameReverseTable.find(slot);
-       if ( pos != _byNameReverseTable.end() )
-               return pos->second;
-       assert(0);
-       return NULL;
-}
-
-const ld::Atom* SymbolTable::indirectAtom(IndirectBindingSlot slot) const
-{
-       assert(slot < _indirectBindingTable.size());
-       return _indirectBindingTable[slot];
-}
-
-void SymbolTable::printStatistics()
-{
-//     fprintf(stderr, "cstring table size: %lu, bucket count: %lu, hash func called %u times\n", 
-//                             _cstringTable.size(), _cstringTable.bucket_count(), cstringHashCount);
-       int count[11];
-       for(unsigned int b=0; b < 11; ++b) {
-               count[b] = 0;
-       }
-       for(unsigned int i=0; i < _cstringTable.bucket_count(); ++i) {
-               unsigned int n = _cstringTable.elems_in_bucket(i);
-               if ( n < 10 ) 
-                       count[n] += 1;
-               else
-                       count[10] += 1;
-       }
-       fprintf(stderr, "cstring table distribution\n");
-       for(unsigned int b=0; b < 11; ++b) {
-               fprintf(stderr, "%u buckets have %u elements\n", count[b], b);
-       }
-       fprintf(stderr, "indirect table size: %lu\n", _indirectBindingTable.size());
-       fprintf(stderr, "by-name table size: %lu\n", _byNameTable.size());
-//     fprintf(stderr, "by-content table size: %lu, hash count: %u, equals count: %u, lookup count: %u\n", 
-//                                             _byContentTable.size(), contentHashCount, contentEqualCount, contentLookupCount);
-//     fprintf(stderr, "by-ref table size: %lu, hashed count: %u, equals count: %u, lookup count: %u, insert count: %u\n", 
-//                                             _byReferencesTable.size(), refHashCount, refEqualsCount, refLookupCount, refInsertCount);
-
-       //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());
-       //      
-       //      }
-       //}
-       
-}
-
-} // namespace tool 
-} // namespace ld 
-