// symtab.h -- the gold symbol table -*- C++ -*- // Symbol_table // The symbol table. #include #include #include #include "elfcpp.h" #include "stringpool.h" #ifndef GOLD_SYMTAB_H #define GOLD_SYMTAB_H namespace gold { class Object; class Output_file; class Target; template class Sized_object; // The base class of an entry in the symbol table. The symbol table // can have a lot of entries, so we don't want this class to big. // Size dependent fields can be found in the template class // Sized_symbol. Targets may support their own derived classes. class Symbol { public: // Return the symbol name. const char* name() const { return this->name_; } // Return the symbol version. This will return NULL for an // unversioned symbol. const char* version() const { return this->version_; } // Return the object with which this symbol is associated. Object* object() const { return this->object_; } // Return the symbol binding. elfcpp::STB binding() const { return this->binding_; } // Return the symbol type. elfcpp::STT type() const { return this->type_; } // Return the symbol visibility. elfcpp::STV visibility() const { return this->visibility_; } // Return the non-visibility part of the st_other field. unsigned char other() const { return this->other_; } // Return the section index. unsigned int shnum() const { return this->shnum_; } // Return whether this symbol is a forwarder. This will never be // true of a symbol found in the hash table, but may be true of // symbol pointers attached to object files. bool is_forwarder() const { return this->is_forwarder_; } // Mark this symbol as a forwarder. void set_forwarder() { this->is_forwarder_ = true; } // Return whether this symbol was seen in a dynamic object. bool in_dyn() const { return this->in_dyn_; } // Mark this symbol as seen in a dynamic object. void set_in_dyn() { this->in_dyn_ = true; } protected: // Instances of this class should always be created at a specific // size. Symbol() { } // Initialize fields from an ELF symbol in OBJECT. template void init_base(const char *name, const char* version, Object* object, const elfcpp::Sym&); // Override existing symbol. template void override_base(const elfcpp::Sym&, Object* object); private: Symbol(const Symbol&); Symbol& operator=(const Symbol&); // Symbol name (expected to point into a Stringpool). const char* name_; // Symbol version (expected to point into a Stringpool). This may // be NULL. const char* version_; // Object in which symbol is defined, or in which it was first seen. Object* object_; // Section number in object_ in which symbol is defined. unsigned int shnum_; // Symbol type. elfcpp::STT type_ : 4; // Symbol binding. elfcpp::STB binding_ : 4; // Symbol visibility. elfcpp::STV visibility_ : 2; // Rest of symbol st_other field. unsigned int other_ : 6; // True if this symbol always requires special target-specific // handling. bool is_special_ : 1; // True if this is the default version of the symbol. bool is_def_ : 1; // True if this symbol really forwards to another symbol. This is // used when we discover after the fact that two different entries // in the hash table really refer to the same symbol. This will // never be set for a symbol found in the hash table, but may be set // for a symbol found in the list of symbols attached to an Object. // It forwards to the symbol found in the forwarders_ map of // Symbol_table. bool is_forwarder_ : 1; // True if we've seen this symbol in a dynamic object. bool in_dyn_ : 1; }; // The parts of a symbol which are size specific. Using a template // derived class like this helps us use less space on a 32-bit system. template class Sized_symbol : public Symbol { public: typedef typename elfcpp::Elf_types::Elf_Addr Value_type; typedef typename elfcpp::Elf_types::Elf_WXword Size_type; Sized_symbol() { } // Initialize fields from an ELF symbol in OBJECT. template void init(const char *name, const char* version, Object* object, const elfcpp::Sym&); // Override existing symbol. template void override(const elfcpp::Sym&, Object* object); // Return the symbol's value. Value_type value() const { return this->value_; } // Return the symbol's size (we can't call this 'size' because that // is a template parameter). Size_type symsize() const { return this->size_; } // Set the symbol value. This is called when we store the final // values of the symbols into the symbol table. void set_value(Value_type value) { this->value_ = value; } private: Sized_symbol(const Sized_symbol&); Sized_symbol& operator=(const Sized_symbol&); // Symbol value. Value_type value_; // Symbol size. Size_type size_; }; // The main linker symbol table. class Symbol_table { public: Symbol_table(); ~Symbol_table(); // Add COUNT external symbols from OBJECT to the symbol table. SYMS // is the symbols, SYM_NAMES is their names, SYM_NAME_SIZE is the // size of SYM_NAMES. This sets SYMPOINTERS to point to the symbols // in the symbol table. template void add_from_object(Sized_object* object, const elfcpp::Sym* syms, size_t count, const char* sym_names, size_t sym_name_size, Symbol** sympointers); // Look up a symbol. Symbol* lookup(const char*, const char* version = NULL) const; // Return the real symbol associated with the forwarder symbol FROM. Symbol* resolve_forwards(Symbol* from) const; // Return the size of the symbols in the table. int get_size() const { return this->size_; } // Return the sized version of a symbol in this table. template Sized_symbol* get_sized_symbol(Symbol* ACCEPT_SIZE) const; template const Sized_symbol* get_sized_symbol(const Symbol* ACCEPT_SIZE) const; // Finalize the symbol table after we have set the final addresses // of all the input sections. This sets the final symbol values and // adds the names to *POOL. It records the file offset OFF, and // returns the new file offset. off_t finalize(off_t, Stringpool*); // Write out the global symbols. void write_globals(const Target*, const Stringpool*, Output_file*) const; private: Symbol_table(const Symbol_table&); Symbol_table& operator=(const Symbol_table&); // Set the size of the symbols in the table. void set_size(int size) { this->size_ = size; } // Make FROM a forwarder symbol to TO. void make_forwarder(Symbol* from, Symbol* to); // Add a symbol. template Symbol* add_from_object(Sized_object*, const char *name, const char *version, bool def, const elfcpp::Sym& sym); // Resolve symbols. template static void resolve(Sized_symbol* to, const elfcpp::Sym& sym, Object*); template static void resolve(Sized_symbol* to, const Sized_symbol* from ACCEPT_SIZE_ENDIAN); // Finalize symbols specialized for size. template off_t sized_finalize(off_t, Stringpool*); // Write globals specialized for size and endianness. template void sized_write_globals(const Target*, const Stringpool*, Output_file*) const; // The type of the symbol hash table. typedef std::pair Symbol_table_key; struct Symbol_table_hash { size_t operator()(const Symbol_table_key&) const; }; struct Symbol_table_eq { bool operator()(const Symbol_table_key&, const Symbol_table_key&) const; }; typedef Unordered_map Symbol_table_type; // The size of the symbols in the symbol table (32 or 64). int size_; // The file offset within the output symtab section where we should // write the table. off_t offset_; // The number of global symbols we want to write out. size_t output_count_; // The symbol hash table. Symbol_table_type table_; // A pool of symbol names. This is used for all global symbols. // Entries in the hash table point into this pool. Stringpool namepool_; // Forwarding symbols. Unordered_map forwarders_; }; // We inline get_sized_symbol for efficiency. template Sized_symbol* Symbol_table::get_sized_symbol(Symbol* sym ACCEPT_SIZE) const { assert(size == this->get_size()); return static_cast*>(sym); } template const Sized_symbol* Symbol_table::get_sized_symbol(const Symbol* sym ACCEPT_SIZE) const { assert(size == this->get_size()); return static_cast*>(sym); } } // End namespace gold. #endif // !defined(GOLD_SYMTAB_H)