#include <string>
#include <utility>
#include <vector>
-#include <cassert>
#include "elfcpp.h"
#include "stringpool.h"
class Object;
class Relobj;
+template<int size, bool big_endian>
+class Sized_relobj;
class Dynobj;
+template<int size, bool big_endian>
+class Sized_dynobj;
class Output_data;
+class Output_section;
class Output_segment;
class Output_file;
class Target;
Object*
object() const
{
- assert(this->source_ == FROM_OBJECT);
+ gold_assert(this->source_ == FROM_OBJECT);
return this->u_.from_object.object;
}
// Return the index of the section in the input relocatable or
// dynamic object file.
unsigned int
- shnum() const
+ shndx() const
{
- assert(this->source_ == FROM_OBJECT);
- return this->u_.from_object.shnum;
+ gold_assert(this->source_ == FROM_OBJECT);
+ return this->u_.from_object.shndx;
}
// Return the output data section with which this symbol is
Output_data*
output_data() const
{
- assert(this->source_ == IN_OUTPUT_DATA);
+ gold_assert(this->source_ == IN_OUTPUT_DATA);
return this->u_.in_output_data.output_data;
}
bool
offset_is_from_end() const
{
- assert(this->source_ == IN_OUTPUT_DATA);
+ gold_assert(this->source_ == IN_OUTPUT_DATA);
return this->u_.in_output_data.offset_is_from_end;
}
Output_segment*
output_segment() const
{
- assert(this->source_ == IN_OUTPUT_SEGMENT);
+ gold_assert(this->source_ == IN_OUTPUT_SEGMENT);
return this->u_.in_output_segment.output_segment;
}
Segment_offset_base
offset_base() const
{
- assert(this->source_ == IN_OUTPUT_SEGMENT);
+ gold_assert(this->source_ == IN_OUTPUT_SEGMENT);
return this->u_.in_output_segment.offset_base;
}
set_forwarder()
{ this->is_forwarder_ = true; }
- // Return whether this symbol was ever seen in a dynamic object.
+ // Return whether this symbol needs an entry in the dynamic symbol
+ // table.
bool
- in_dyn() const
- { return this->in_dyn_; }
+ needs_dynsym_entry() const
+ { return this->needs_dynsym_entry_; }
+
+ // Mark this symbol as needing an entry in the dynamic symbol table.
+ void
+ set_needs_dynsym_entry()
+ { this->needs_dynsym_entry_ = true; }
// Mark this symbol as having been seen in a dynamic object.
void
set_in_dyn()
{ this->in_dyn_ = true; }
+ // Return the index of this symbol in the output file symbol table.
+ // A value of -1U means that this symbol is not going into the
+ // output file. This starts out as zero, and is set to a non-zero
+ // value by Symbol_table::finalize. It is an error to ask for the
+ // symbol table index before it has been set.
+ unsigned int
+ symtab_index() const
+ {
+ gold_assert(this->symtab_index_ != 0);
+ return this->symtab_index_;
+ }
+
+ // Set the index of the symbol in the output file symbol table.
+ void
+ set_symtab_index(unsigned int index)
+ {
+ gold_assert(index != 0);
+ this->symtab_index_ = index;
+ }
+
+ // Return whether this symbol already has an index in the output
+ // file symbol table.
+ bool
+ has_symtab_index() const
+ { return this->symtab_index_ != 0; }
+
+ // Return the index of this symbol in the dynamic symbol table. A
+ // value of -1U means that this symbol is not going into the dynamic
+ // symbol table. This starts out as zero, and is set to a non-zero
+ // during Layout::finalize. It is an error to ask for the dynamic
+ // symbol table index before it has been set.
+ unsigned int
+ dynsym_index() const
+ {
+ gold_assert(this->dynsym_index_ != 0);
+ return this->dynsym_index_;
+ }
+
+ // Set the index of the symbol in the dynamic symbol table.
+ void
+ set_dynsym_index(unsigned int index)
+ {
+ gold_assert(index != 0);
+ this->dynsym_index_ = index;
+ }
+
+ // Return whether this symbol already has an index in the dynamic
+ // symbol table.
+ bool
+ has_dynsym_index() const
+ { return this->dynsym_index_ != 0; }
+
// Return whether this symbol has an entry in the GOT section.
bool
has_got_offset() const
unsigned int
got_offset() const
{
- assert(this->has_got_offset());
+ gold_assert(this->has_got_offset());
return this->got_offset_;
}
this->got_offset_ = got_offset;
}
- // Return whether this symbol is resolved locally. This is always
- // true when linking statically. It is true for a symbol defined in
- // this object when using -Bsymbolic. It is true for a symbol
- // marked local in a version file. FIXME: This needs to be
- // completed.
+ // Return whether this symbol has an entry in the PLT section.
+ bool
+ has_plt_offset() const
+ { return this->has_plt_offset_; }
+
+ // Return the offset into the PLT section of this symbol.
+ unsigned int
+ plt_offset() const
+ {
+ gold_assert(this->has_plt_offset());
+ return this->plt_offset_;
+ }
+
+ // Set the PLT offset of this symbol.
+ void
+ set_plt_offset(unsigned int plt_offset)
+ {
+ this->has_plt_offset_ = true;
+ this->plt_offset_ = plt_offset;
+ }
+
+ // Return true if the final value of this symbol is known at link
+ // time.
bool
- is_resolved_locally() const
- { return !this->in_dyn_; }
+ final_value_is_known(const General_options* options) const
+ {
+ if (options->is_shared())
+ return false;
+ return this->source_ != FROM_OBJECT || !this->object()->is_dynamic();
+ }
// Return whether this is a defined symbol (not undefined or
// common).
is_defined() const
{
return (this->source_ != FROM_OBJECT
- || (this->u_.from_object.shnum != elfcpp::SHN_UNDEF
- && this->u_.from_object.shnum != elfcpp::SHN_COMMON));
+ || (this->shndx() != elfcpp::SHN_UNDEF
+ && this->shndx() != elfcpp::SHN_COMMON));
+ }
+
+ // Return whether this symbol is defined in a dynamic object.
+ bool
+ is_defined_in_dynobj() const
+ {
+ return (this->source_ == FROM_OBJECT
+ && this->object()->is_dynamic()
+ && this->is_defined());
}
// Return whether this is an undefined symbol.
bool
is_undefined() const
{
- return this->source_ == FROM_OBJECT && this->shnum() == elfcpp::SHN_UNDEF;
+ return this->source_ == FROM_OBJECT && this->shndx() == elfcpp::SHN_UNDEF;
}
// Return whether this is a common symbol.
is_common() const
{
return (this->source_ == FROM_OBJECT
- && (this->u_.from_object.shnum == elfcpp::SHN_COMMON
+ && (this->shndx() == elfcpp::SHN_COMMON
|| this->type_ == elfcpp::STT_COMMON));
}
// seen.
Object* object;
// Section number in object_ in which symbol is defined.
- unsigned int shnum;
+ unsigned int shndx;
} from_object;
// This struct is used if SOURCE_ == IN_OUTPUT_DATA.
} in_output_segment;
} u_;
+ // The index of this symbol in the output file. If the symbol is
+ // not going into the output file, this value is -1U. This field
+ // starts as always holding zero. It is set to a non-zero value by
+ // Symbol_table::finalize.
+ unsigned int symtab_index_;
+
+ // The index of this symbol in the dynamic symbol table. If the
+ // symbol is not going into the dynamic symbol table, this value is
+ // -1U. This field starts as always holding zero. It is set to a
+ // non-zero value during Layout::finalize.
+ unsigned int dynsym_index_;
+
// If this symbol has an entry in the GOT section (has_got_offset_
- // is true), this is the offset.
+ // is true), this is the offset from the start of the GOT section.
unsigned int got_offset_;
+
+ // If this symbol has an entry in the PLT section (has_plt_offset_
+ // is true), then this is the offset from the start of the PLT
+ // section.
+ unsigned int plt_offset_;
+
// Symbol type.
elfcpp::STT type_ : 4;
// Symbol binding.
// It forwards to the symbol found in the forwarders_ map of
// Symbol_table.
bool is_forwarder_ : 1;
+ // True if this symbol needs to be in the dynamic symbol table.
+ bool needs_dynsym_entry_ : 1;
// True if we've seen this symbol in a dynamic object.
bool in_dyn_ : 1;
// True if the symbol has an entry in the GOT section.
bool has_got_offset_ : 1;
+ // True if the symbol has an entry in the PLT section.
+ bool has_plt_offset_ : 1;
// True if there is a warning for this symbol.
bool has_warning_ : 1;
};
// Issue a warning for a reference to SYM at LOCATION.
void
- issue_warning(Symbol* sym, const std::string& location) const;
+ issue_warning(const Symbol* sym, const std::string& location) const;
private:
Warnings(const Warnings&);
~Symbol_table();
- // Add COUNT external symbols from the relocatable object OBJECT to
+ // Add COUNT external symbols from the relocatable object RELOBJ 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<int size, bool big_endian>
void
- add_from_object(Relobj* object, const unsigned char* syms,
- size_t count, const char* sym_names, size_t sym_name_size,
+ add_from_relobj(Sized_relobj<size, big_endian>* relobj,
+ const unsigned char* syms, size_t count,
+ const char* sym_names, size_t sym_name_size,
Symbol** sympointers);
+ // Add COUNT dynamic symbols from the dynamic object DYNOBJ to the
+ // symbol table. SYMS is the symbols. SYM_NAMES is their names.
+ // SYM_NAME_SIZE is the size of SYM_NAMES. The other parameters are
+ // symbol version data.
+ template<int size, bool big_endian>
+ void
+ add_from_dynobj(Sized_dynobj<size, big_endian>* dynobj,
+ const unsigned char* syms, size_t count,
+ const char* sym_names, size_t sym_name_size,
+ const unsigned char* versym, size_t versym_size,
+ const std::vector<const char*>*);
+
// Define a special symbol.
template<int size, bool big_endian>
Sized_symbol<size>*
// Return the real symbol associated with the forwarder symbol FROM.
Symbol*
- resolve_forwards(Symbol* from) const;
+ resolve_forwards(const Symbol* from) const;
- // Return the size of the symbols in the table.
+ // Return the bitsize (32 or 64) of the symbols in the table.
int
get_size() const
{ return this->size_; }
// Canonicalize a symbol name for use in the hash table.
const char*
canonicalize_name(const char* name)
- { return this->namepool_.add(name); }
+ { return this->namepool_.add(name, NULL); }
// Possibly issue a warning for a reference to SYM at LOCATION which
// is in OBJ.
void
- issue_warning(Symbol* sym, const std::string& location) const
+ issue_warning(const Symbol* sym, const std::string& location) const
{ this->warnings_.issue_warning(sym, location); }
+ // Set the dynamic symbol indexes. INDEX is the index of the first
+ // global dynamic symbol. Pointers to the symbols are stored into
+ // the vector. The names are stored into the Stringpool. This
+ // returns an updated dynamic symbol index.
+ unsigned int
+ set_dynsym_indexes(unsigned int index, std::vector<Symbol*>*,
+ Stringpool*);
+
// 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.
+ // of all the input sections. This sets the final symbol indexes,
+ // values and adds the names to *POOL. INDEX is the index of the
+ // first global symbol. OFF is the file offset of the global symbol
+ // table, DYNOFF is the offset of the globals in the dynamic symbol
+ // table, DYN_GLOBAL_INDEX is the index of the first global dynamic
+ // symbol, and DYNCOUNT is the number of global dynamic symbols.
+ // This records the parameters, and returns the new file offset.
off_t
- finalize(off_t, Stringpool*);
+ finalize(unsigned int index, off_t off, off_t dynoff,
+ size_t dyn_global_index, size_t dyncount, Stringpool* pool);
// Write out the global symbols.
void
- write_globals(const Target*, const Stringpool*, Output_file*) const;
+ write_globals(const Target*, const Stringpool*, const Stringpool*,
+ Output_file*) const;
+
+ // Write out a section symbol. Return the updated offset.
+ void
+ write_section_symbol(const Target*, const Output_section*, Output_file*,
+ off_t) const;
private:
Symbol_table(const Symbol_table&);
Symbol_table& operator=(const Symbol_table&);
- // Set the size of the symbols in the table.
+ // Set the size (32 or 64) of the symbols in the table.
void
set_size(int size)
{ this->size_ = size; }
// Add a symbol.
template<int size, bool big_endian>
Symbol*
- add_from_object(Object*, const char *name,
- const char *version, bool def,
- const elfcpp::Sym<size, big_endian>& sym);
+ add_from_object(Object*, const char *name, Stringpool::Key name_key,
+ const char *version, Stringpool::Key version_key,
+ bool def, const elfcpp::Sym<size, big_endian>& sym);
// Resolve symbols.
template<int size, bool big_endian>
// Finalize symbols specialized for size.
template<int size>
off_t
- sized_finalize(off_t, Stringpool*);
+ sized_finalize(unsigned int, off_t, Stringpool*);
// Write globals specialized for size and endianness.
template<int size, bool big_endian>
void
- sized_write_globals(const Target*, const Stringpool*, Output_file*) const;
+ sized_write_globals(const Target*, const Stringpool*, const Stringpool*,
+ Output_file*) const;
+
+ // Write out a symbol to P.
+ template<int size, bool big_endian>
+ void
+ sized_write_symbol(Sized_symbol<size>*, unsigned int shndx,
+ const Stringpool*, unsigned char* p
+ ACCEPT_SIZE_ENDIAN) const;
+
+ // Write out a section symbol, specialized for size and endianness.
+ template<int size, bool big_endian>
+ void
+ sized_write_section_symbol(const Output_section*, Output_file*, off_t) const;
// The type of the symbol hash table.
- typedef std::pair<const char*, const char*> Symbol_table_key;
+ typedef std::pair<Stringpool::Key, Stringpool::Key> Symbol_table_key;
struct Symbol_table_hash
{
// use in archive groups.
int saw_undefined_;
+ // The index of the first global symbol in the output file.
+ unsigned int first_global_index_;
+
// 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 file offset of the global dynamic symbols, or 0 if none.
+ off_t dynamic_offset_;
+
+ // The index of the first global dynamic symbol.
+ unsigned int first_dynamic_global_index_;
+
+ // The number of global dynamic symbols, or 0 if none.
+ off_t dynamic_count_;
+
// The symbol hash table.
Symbol_table_type table_;
Stringpool namepool_;
// Forwarding symbols.
- Unordered_map<Symbol*, Symbol*> forwarders_;
+ Unordered_map<const Symbol*, Symbol*> forwarders_;
// We don't expect there to be very many common symbols, so we keep
// a list of them. When we find a common symbol we add it to this
Sized_symbol<size>*
Symbol_table::get_sized_symbol(Symbol* sym ACCEPT_SIZE) const
{
- assert(size == this->get_size());
+ gold_assert(size == this->get_size());
return static_cast<Sized_symbol<size>*>(sym);
}
const Sized_symbol<size>*
Symbol_table::get_sized_symbol(const Symbol* sym ACCEPT_SIZE) const
{
- assert(size == this->get_size());
+ gold_assert(size == this->get_size());
return static_cast<const Sized_symbol<size>*>(sym);
}