#ifndef __SYMBOL_TABLE_H__
#define __SYMBOL_TABLE_H__
#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 <mach/mach_time.h>
#include <mach/vm_statistics.h>
#include <mach/mach_init.h>
#include <mach/mach_host.h>
#include <dlfcn.h>
#include <mach-o/dyld.h>
#include <vector>
#include <unordered_map>
#include "Options.h"
#include "ld.hpp"
namespace ld {
namespace tool {
class SymbolTable : public ld::IndirectBindingTable
{
public:
typedef uint32_t IndirectBindingSlot;
private:
typedef std::unordered_map<const char*, IndirectBindingSlot, CStringHash, CStringEquals> NameToSlot;
class ContentFuncs {
public:
size_t operator()(const ld::Atom*) const;
bool operator()(const ld::Atom* left, const ld::Atom* right) const;
};
typedef std::unordered_map<const ld::Atom*, IndirectBindingSlot, ContentFuncs, ContentFuncs> ContentToSlot;
class ReferencesHashFuncs {
public:
size_t operator()(const ld::Atom*) const;
bool operator()(const ld::Atom* left, const ld::Atom* right) const;
};
typedef std::unordered_map<const ld::Atom*, IndirectBindingSlot, ReferencesHashFuncs, ReferencesHashFuncs> ReferencesToSlot;
class CStringHashFuncs {
public:
size_t operator()(const ld::Atom*) const;
bool operator()(const ld::Atom* left, const ld::Atom* right) const;
};
typedef std::unordered_map<const ld::Atom*, IndirectBindingSlot, CStringHashFuncs, CStringHashFuncs> CStringToSlot;
class UTF16StringHashFuncs {
public:
size_t operator()(const ld::Atom*) const;
bool operator()(const ld::Atom* left, const ld::Atom* right) const;
};
typedef std::unordered_map<const ld::Atom*, IndirectBindingSlot, UTF16StringHashFuncs, UTF16StringHashFuncs> UTF16StringToSlot;
typedef std::map<IndirectBindingSlot, const char*> SlotToName;
typedef std::unordered_map<const char*, CStringToSlot*, CStringHash, CStringEquals> NameToMap;
typedef std::vector<const ld::Atom *> DuplicatedSymbolAtomList;
typedef std::map<const char *, DuplicatedSymbolAtomList * > DuplicateSymbols;
public:
class byNameIterator {
public:
byNameIterator& operator++(int) { ++_nameTableIterator; return *this; }
const ld::Atom* operator*() { return _slotTable[_nameTableIterator->second]; }
bool operator!=(const byNameIterator& lhs) { return _nameTableIterator != lhs._nameTableIterator; }
private:
friend class SymbolTable;
byNameIterator(NameToSlot::iterator it, std::vector<const ld::Atom*>& indirectTable)
: _nameTableIterator(it), _slotTable(indirectTable) {}
NameToSlot::iterator _nameTableIterator;
std::vector<const ld::Atom*>& _slotTable;
};
SymbolTable(const Options& opts, std::vector<const ld::Atom*>& ibt);
bool add(const ld::Atom& atom, bool ignoreDuplicates);
IndirectBindingSlot findSlotForName(const char* name);
IndirectBindingSlot findSlotForContent(const ld::Atom* atom, const ld::Atom** existingAtom);
IndirectBindingSlot findSlotForReferences(const ld::Atom* atom, const ld::Atom** existingAtom);
const ld::Atom* atomForSlot(IndirectBindingSlot s) { return _indirectBindingTable[s]; }
unsigned int updateCount() { return _indirectBindingTable.size(); }
void undefines(std::vector<const char*>& undefines);
void tentativeDefs(std::vector<const char*>& undefines);
void mustPreserveForBitcode(std::unordered_set<const char*>& syms);
void removeDeadAtoms();
bool hasName(const char* name);
bool hasExternalTentativeDefinitions() { return _hasExternalTentativeDefinitions; }
byNameIterator begin() { return byNameIterator(_byNameTable.begin(),_indirectBindingTable); }
byNameIterator end() { return byNameIterator(_byNameTable.end(),_indirectBindingTable); }
void printStatistics();
virtual const char* indirectName(IndirectBindingSlot slot) const;
virtual const ld::Atom* indirectAtom(IndirectBindingSlot slot) const;
void checkDuplicateSymbols() const;
private:
bool addByName(const ld::Atom& atom, bool ignoreDuplicates);
bool addByContent(const ld::Atom& atom);
bool addByReferences(const ld::Atom& atom);
void markCoalescedAway(const ld::Atom* atom);
void addDuplicateSymbol(const char *symbol, const ld::Atom* atom);
const Options& _options;
NameToSlot _byNameTable;
SlotToName _byNameReverseTable;
ContentToSlot _literal4Table;
ContentToSlot _literal8Table;
ContentToSlot _literal16Table;
UTF16StringToSlot _utf16Table;
CStringToSlot _cstringTable;
NameToMap _nonStdCStringSectionToMap;
ReferencesToSlot _nonLazyPointerTable;
ReferencesToSlot _threadPointerTable;
ReferencesToSlot _cfStringTable;
ReferencesToSlot _objc2ClassRefTable;
ReferencesToSlot _pointerToCStringTable;
std::vector<const ld::Atom*>& _indirectBindingTable;
bool _hasExternalTentativeDefinitions;
DuplicateSymbols _duplicateSymbols;
};
} }
#endif // __SYMBOL_TABLE_H__