// object.h -- support for an object file for linking in gold -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
#include "elfcpp_file.h"
#include "fileread.h"
#include "target.h"
+#include "archive.h"
namespace gold
{
class General_options;
class Task;
class Cref;
-class Archive;
class Layout;
class Output_section;
class Output_file;
struct Read_symbols_data
{
+ Read_symbols_data()
+ : section_headers(NULL), section_names(NULL), symbols(NULL),
+ symbol_names(NULL), versym(NULL), verdef(NULL), verneed(NULL)
+ { }
+
+ ~Read_symbols_data();
+
// Section headers.
File_view* section_headers;
// Section names.
struct Section_relocs
{
+ Section_relocs()
+ : contents(NULL)
+ { }
+
+ ~Section_relocs()
+ { delete this->contents; }
+
// Index of reloc section.
unsigned int reloc_shndx;
// Index of section that relocs apply to.
struct Read_relocs_data
{
+ Read_relocs_data()
+ : local_symbols(NULL)
+ { }
+
+ ~Read_relocs_data()
+ { delete this->local_symbols; }
+
typedef std::vector<Section_relocs> Relocs_list;
// The relocations.
Relocs_list relocs;
class Object
{
public:
+ typedef std::vector<Symbol*> Symbols;
+
// NAME is the name of the object as we would report it to the user
// (e.g., libfoo.a(bar.o) if this is in an archive. INPUT_FILE is
// used to read the file. OFFSET is the offset within the input
add_symbols(Symbol_table* symtab, Read_symbols_data* sd, Layout *layout)
{ this->do_add_symbols(symtab, sd, layout); }
+ // Add symbol information to the global symbol table.
+ Archive::Should_include
+ should_include_member(Symbol_table* symtab, Read_symbols_data* sd,
+ std::string* why)
+ { return this->do_should_include_member(symtab, sd, why); }
+
// Functions and types for the elfcpp::Elf_file interface. This
// permit us to use Object as the File template parameter for
// elfcpp::Elf_file.
size_t* used) const
{ this->do_get_global_symbol_counts(symtab, defined, used); }
+ // Get the symbols defined in this object.
+ const Symbols*
+ get_global_symbols() const
+ { return this->do_get_global_symbols(); }
+
// Return whether this object was found in a system directory.
bool
is_in_system_directory() const
virtual void
do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*) = 0;
+ virtual Archive::Should_include
+ do_should_include_member(Symbol_table* symtab, Read_symbols_data*,
+ std::string* why) = 0;
+
// Return the location of the contents of a section. Implemented by
// child class.
virtual Location
virtual void
do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const = 0;
+ virtual const Symbols*
+ do_get_global_symbols() const = 0;
+
// Set the number of sections.
void
set_shnum(int shnum)
return this->output_sections_[shndx];
}
+ // The the output section of the input section with index SHNDX.
+ // This is only used currently to remove a section from the link in
+ // relaxation.
+ void
+ set_output_section(unsigned int shndx, Output_section* os)
+ {
+ gold_assert(shndx < this->output_sections_.size());
+ this->output_sections_[shndx] = os;
+ }
+
// Given a section index, return the offset in the Output_section.
// The return value will be -1U if the section is specially mapped,
// such as a merge section.
input_value() const
{ return this->u_.value; }
- // Return whether this symbol should go into the output symbol
+ // Return whether we have set the index in the output symbol table
+ // yet.
+ bool
+ is_output_symtab_index_set() const
+ {
+ return (this->output_symtab_index_ != 0
+ && this->output_symtab_index_ != -2U);
+ }
+
+ // Return whether this symbol may be discarded from the normal
+ // symbol table.
+ bool
+ may_be_discarded_from_output_symtab() const
+ {
+ gold_assert(!this->is_output_symtab_index_set());
+ return this->output_symtab_index_ != -2U;
+ }
+
+ // Return whether this symbol has an entry in the output symbol
// table.
bool
- needs_output_symtab_entry() const
- { return this->output_symtab_index_ != -1U; }
+ has_output_symtab_entry() const
+ {
+ gold_assert(this->is_output_symtab_index_set());
+ return this->output_symtab_index_ != -1U;
+ }
// Return the index in the output symbol table.
unsigned int
output_symtab_index() const
{
- gold_assert(this->output_symtab_index_ != 0);
+ gold_assert(this->is_output_symtab_index_set()
+ && this->output_symtab_index_ != -1U);
return this->output_symtab_index_;
}
void
set_output_symtab_index(unsigned int i)
{
- gold_assert(this->output_symtab_index_ == 0);
+ gold_assert(!this->is_output_symtab_index_set());
+ gold_assert(i != 0 && i != -1U && i != -2U);
this->output_symtab_index_ = i;
}
this->output_symtab_index_ = -1U;
}
+ // Record that this symbol must go into the output symbol table,
+ // because it there is a relocation that uses it.
+ void
+ set_must_have_output_symtab_entry()
+ {
+ gold_assert(!this->is_output_symtab_index_set());
+ this->output_symtab_index_ = -2U;
+ }
+
// Set the index in the output dynamic symbol table.
void
set_needs_output_dynsym_entry()
this->output_dynsym_index_ = 0;
}
- // Return whether this symbol should go into the output symbol
+ // Return whether this symbol should go into the dynamic symbol
// table.
bool
needs_output_dynsym_entry() const
return this->output_dynsym_index_ != -1U;
}
+ // Return whether this symbol has an entry in the dynamic symbol
+ // table.
+ bool
+ has_output_dynsym_entry() const
+ {
+ gold_assert(this->output_dynsym_index_ != 0);
+ return this->output_dynsym_index_ != -1U;
+ }
+
// Record that this symbol should go into the dynamic symbol table.
void
set_output_dynsym_index(unsigned int i)
{
gold_assert(this->output_dynsym_index_ == 0);
+ gold_assert(i != 0 && i != -1U);
this->output_dynsym_index_ = i;
}
private:
// The index of this local symbol in the output symbol table. This
- // will be -1 if the symbol should not go into the symbol table.
+ // will be 0 if no value has been assigned yet, and the symbol may
+ // be omitted. This will be -1U if the symbol should not go into
+ // the symbol table. This will be -2U if the symbol must go into
+ // the symbol table, but no index has been assigned yet.
unsigned int output_symtab_index_;
// The index of this local symbol in the dynamic symbol table. This
- // will be -1 if the symbol should not go into the symbol table.
+ // will be -1U if the symbol should not go into the symbol table.
unsigned int output_dynsym_index_;
// The section index in the input file in which this symbol is
// defined.
return this->local_values_[sym].input_shndx(is_ordinary);
}
+ // Record that local symbol SYM must be in the output symbol table.
+ void
+ set_must_have_output_symtab_entry(unsigned int sym)
+ {
+ gold_assert(sym < this->local_values_.size());
+ this->local_values_[sym].set_must_have_output_symtab_entry();
+ }
+
// Record that local symbol SYM needs a dynamic symbol entry.
void
set_needs_output_dynsym_entry(unsigned int sym)
Address
map_to_kept_section(unsigned int shndx, bool* found) const;
- // Make section offset invalid. This is needed for relaxation.
- void
- invalidate_section_offset(unsigned int shndx)
- { this->do_invalidate_section_offset(shndx); }
-
protected:
// Set up.
virtual void
void
do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);
+ Archive::Should_include
+ do_should_include_member(Symbol_table* symtab, Read_symbols_data*,
+ std::string* why);
+
// Read the relocs.
void
do_read_relocs(Read_relocs_data*);
void
do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const;
+ // Get the global symbols.
+ const Symbols*
+ do_get_global_symbols() const
+ { return &this->symbols_; }
+
// Get the offset of a section.
uint64_t
do_output_section_offset(unsigned int shndx) const
do_set_section_offset(unsigned int shndx, uint64_t off)
{
gold_assert(shndx < this->section_offsets_.size());
- this->section_offsets_[shndx] = convert_types<Address, uint64_t>(off);
- }
-
- // Set the offset of a section to invalid_address.
- virtual void
- do_invalidate_section_offset(unsigned int shndx)
- {
- gold_assert(shndx < this->section_offsets_.size());
- this->section_offsets_[shndx] = invalid_address;
+ this->section_offsets_[shndx] =
+ (off == static_cast<uint64_t>(-1)
+ ? invalid_address
+ : convert_types<Address, uint64_t>(off));
}
// Adjust a section index if necessary.
do_relocate_sections(const Symbol_table* symtab, const Layout* layout,
const unsigned char* pshdrs, Views* pviews);
+ // Allow a child to set output local symbol count.
+ void
+ set_output_local_symbol_count(unsigned int value)
+ { this->output_local_symbol_count_ = value; }
+
private:
// For convenience.
typedef Sized_relobj<size, big_endian> This;
void
print_symbol_counts(const Symbol_table*) const;
+ // Print a cross reference table.
+ void
+ print_cref(const Symbol_table*, FILE*) const;
+
// Iterate over all regular objects.
Relobj_iterator
any_dynamic() const
{ return !this->dynobj_list_.empty(); }
+ // Return the number of non dynamic objects.
+ int
+ number_of_relobjs() const
+ { return this->relobj_list_.size(); }
+
// Return the number of input objects.
int
number_of_input_objects() const
location(size_t relnum, off_t reloffset) const;
};
+// This is used to represent a section in an object and is used as the
+// key type for various section maps.
+typedef std::pair<Object*, unsigned int> Section_id;
+
+// This is similar to Section_id but is used when the section
+// pointers are const.
+typedef std::pair<const Object*, unsigned int> Const_section_id;
+
+// The hash value is based on the address of an object in memory during
+// linking. It is okay to use this for looking up sections but never use
+// this in an unordered container that we want to traverse in a repeatable
+// manner.
+
+struct Section_id_hash
+{
+ size_t operator()(const Section_id& loc) const
+ { return reinterpret_cast<uintptr_t>(loc.first) ^ loc.second; }
+};
+
+struct Const_section_id_hash
+{
+ size_t operator()(const Const_section_id& loc) const
+ { return reinterpret_cast<uintptr_t>(loc.first) ^ loc.second; }
+};
+
// Return whether INPUT_FILE contains an ELF object start at file
// offset OFFSET. This sets *START to point to a view of the start of
// the file. It sets *READ_SIZE to the number of bytes in the view.