// object.h -- support for an object file for linking in gold -*- C++ -*-
-// Copyright 2006, 2007 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
{
class General_options;
+class Task;
class Layout;
class Output_section;
class Output_file;
class Dynobj;
class Object_merge_map;
+class Relocatable_relocs;
template<typename Stringpool_char>
class Stringpool_template;
// Section names.
File_view* section_names;
// Size of section name data in bytes.
- off_t section_names_size;
+ section_size_type section_names_size;
// Symbol data.
File_view* symbols;
// Size of symbol data in bytes.
- off_t symbols_size;
+ section_size_type symbols_size;
// Offset of external symbols within symbol data. This structure
// sometimes contains only external symbols, in which case this will
// be zero. Sometimes it contains all symbols.
- off_t external_symbols_offset;
+ section_offset_type external_symbols_offset;
// Symbol names.
File_view* symbol_names;
// Size of symbol name data in bytes.
- off_t symbol_names_size;
+ section_size_type symbol_names_size;
// Version information. This is only used on dynamic objects.
// Version symbol data (from SHT_GNU_versym section).
File_view* versym;
- off_t versym_size;
+ section_size_type versym_size;
// Version definition data (from SHT_GNU_verdef section).
File_view* verdef;
- off_t verdef_size;
+ section_size_type verdef_size;
unsigned int verdef_info;
// Needed version data (from SHT_GNU_verneed section).
File_view* verneed;
- off_t verneed_size;
+ section_size_type verneed_size;
unsigned int verneed_info;
};
Output_section* output_section;
// Whether this section has special handling for offsets.
bool needs_special_offset_handling;
+ // Whether the data section is allocated (has the SHF_ALLOC flag set).
+ bool is_data_section_allocated;
};
// Relocations in an object file. This is read in read_relocs and
off_t offset = 0)
: name_(name), input_file_(input_file), offset_(offset), shnum_(-1U),
is_dynamic_(is_dynamic), target_(NULL)
- { }
+ { input_file->file().add_object(); }
virtual ~Object()
- { }
+ { this->input_file_->file().remove_object(); }
// Return the name of the object as we would report it to the tuser.
const std::string&
// Lock the underlying file.
void
- lock()
- { this->input_file_->file().lock(); }
+ lock(const Task* t)
+ { this->input_file()->file().lock(t); }
// Unlock the underlying file.
void
- unlock()
- { this->input_file_->file().unlock(); }
+ unlock(const Task* t)
+ { this->input_file()->file().unlock(t); }
// Return whether the underlying file is locked.
bool
is_locked() const
- { return this->input_file_->file().is_locked(); }
+ { return this->input_file()->file().is_locked(); }
+
+ // Return the token, so that the task can be queued.
+ Task_token*
+ token()
+ { return this->input_file()->file().token(); }
+
+ // Release the underlying file.
+ void
+ release()
+ { this->input_file_->file().release(); }
+
+ // Return whether we should just read symbols from this file.
+ bool
+ just_symbols() const
+ { return this->input_file()->just_symbols(); }
// Return the sized target structure associated with this object.
// This is like the target method but it returns a pointer of
// appropriate checked type.
template<int size, bool big_endian>
Sized_target<size, big_endian>*
- sized_target(ACCEPT_SIZE_ENDIAN_ONLY);
+ sized_target() const;
// Get the number of sections.
unsigned int
// Return a view of the contents of a section. Set *PLEN to the
// size. CACHE is a hint as in File_read::get_view.
const unsigned char*
- section_contents(unsigned int shndx, off_t* plen, bool cache);
+ section_contents(unsigned int shndx, section_size_type* plen, bool cache);
- // Return the name of a section given a section index. This is only
- // used for error messages.
+ // Return the size of a section given a section index.
+ uint64_t
+ section_size(unsigned int shndx)
+ { return this->do_section_size(shndx); }
+
+ // Return the name of a section given a section index.
std::string
section_name(unsigned int shndx)
{ return this->do_section_name(shndx); }
section_flags(unsigned int shndx)
{ return this->do_section_flags(shndx); }
+ // Return the section address given a section index.
+ uint64_t
+ section_address(unsigned int shndx)
+ { return this->do_section_address(shndx); }
+
// Return the section type given a section index.
unsigned int
section_type(unsigned int shndx)
section_info(unsigned int shndx)
{ return this->do_section_info(shndx); }
+ // Return the required section alignment given a section index.
+ uint64_t
+ section_addralign(unsigned int shndx)
+ { return this->do_section_addralign(shndx); }
+
// Read the symbol information.
void
read_symbols(Read_symbols_data* sd)
// Return a View.
View
- view(off_t file_offset, off_t data_size)
+ view(off_t file_offset, section_size_type data_size)
{ return View(this->get_view(file_offset, data_size, true)); }
// Report an error.
off_t file_offset;
off_t data_size;
- Location(off_t fo, off_t ds)
+ Location(off_t fo, section_size_type ds)
: file_offset(fo), data_size(ds)
{ }
};
View view(Location loc)
{ return View(this->get_view(loc.file_offset, loc.data_size, true)); }
+ // Get a view into the underlying file.
+ const unsigned char*
+ get_view(off_t start, section_size_type size, bool cache)
+ {
+ return this->input_file()->file().get_view(start + this->offset_, size,
+ cache);
+ }
+
+ // Get a lasting view into the underlying file.
+ File_view*
+ get_lasting_view(off_t start, section_size_type size, bool cache)
+ {
+ return this->input_file()->file().get_lasting_view(start + this->offset_,
+ size, cache);
+ }
+
+ // Read data from the underlying file.
+ void
+ read(off_t start, section_size_type size, void* p) const
+ { this->input_file()->file().read(start + this->offset_, size, p); }
+
+ // Read multiple data from the underlying file.
+ void
+ read_multiple(const File_read::Read_multiple& rm)
+ { this->input_file()->file().read_multiple(this->offset_, rm); }
+
+ // Stop caching views in the underlying file.
+ void
+ clear_view_cache_marks()
+ { this->input_file()->file().clear_view_cache_marks(); }
+
protected:
// Read the symbols--implemented by child class.
virtual void
virtual Location
do_section_contents(unsigned int shndx) = 0;
+ // Get the size of a section--implemented by child class.
+ virtual uint64_t
+ do_section_size(unsigned int shndx) = 0;
+
// Get the name of a section--implemented by child class.
virtual std::string
do_section_name(unsigned int shndx) = 0;
virtual uint64_t
do_section_flags(unsigned int shndx) = 0;
+ // Get section address--implemented by child class.
+ virtual uint64_t
+ do_section_address(unsigned int shndx) = 0;
+
// Get section type--implemented by child class.
virtual unsigned int
do_section_type(unsigned int shndx) = 0;
virtual unsigned int
do_section_info(unsigned int shndx) = 0;
- // Get the file.
+ // Get section alignment--implemented by child class.
+ virtual uint64_t
+ do_section_addralign(unsigned int shndx) = 0;
+
+ // Get the file. We pass on const-ness.
Input_file*
- input_file() const
+ input_file()
{ return this->input_file_; }
- // Get a view into the underlying file.
- const unsigned char*
- get_view(off_t start, off_t size, bool cache)
- {
- return this->input_file_->file().get_view(start + this->offset_, size,
- cache);
- }
-
- // Get a lasting view into the underlying file.
- File_view*
- get_lasting_view(off_t start, off_t size, bool cache)
- {
- return this->input_file_->file().get_lasting_view(start + this->offset_,
- size, cache);
- }
-
- // Read data from the underlying file.
- void
- read(off_t start, off_t size, void* p)
- { this->input_file_->file().read(start + this->offset_, size, p); }
+ const Input_file*
+ input_file() const
+ { return this->input_file_; }
// Set the target.
void
template<int size, bool big_endian>
inline Sized_target<size, big_endian>*
-Object::sized_target(ACCEPT_SIZE_ENDIAN_ONLY)
+Object::sized_target() const
{
gold_assert(this->target_->get_size() == size);
gold_assert(this->target_->is_big_endian() ? big_endian : !big_endian);
Relobj(const std::string& name, Input_file* input_file, off_t offset = 0)
: Object(name, input_file, false, offset),
map_to_output_(),
+ map_to_relocatable_relocs_(NULL),
object_merge_map_(NULL),
relocs_must_follow_section_writes_(false)
{ }
Layout* layout, Read_relocs_data* rd)
{ return this->do_scan_relocs(options, symtab, layout, rd); }
+ // The number of local symbols in the input symbol table.
+ virtual unsigned int
+ local_symbol_count() const
+ { return this->do_local_symbol_count(); }
+
// Initial local symbol processing: count the number of local symbols
// in the output symbol table and dynamic symbol table; add local symbol
// names to *POOL and *DYNPOOL.
// and set *POFF to the offset within that section. *POFF will be
// set to -1 if the section requires special handling.
inline Output_section*
- output_section(unsigned int shndx, off_t* poff) const;
+ output_section(unsigned int shndx, section_offset_type* poff) const;
// Set the offset of an input section within its output section.
void
- set_section_offset(unsigned int shndx, off_t off)
+ set_section_offset(unsigned int shndx, section_offset_type off)
{
gold_assert(shndx < this->map_to_output_.size());
this->map_to_output_[shndx].offset = off;
// any relocations for sections which require special handling, such
// as the exception frame section.
bool
- relocs_must_follow_section_writes()
+ relocs_must_follow_section_writes() const
{ return this->relocs_must_follow_section_writes_; }
// Return the object merge map.
this->object_merge_map_ = object_merge_map;
}
+ // Record the relocatable reloc info for an input reloc section.
+ void
+ set_relocatable_relocs(unsigned int reloc_shndx, Relocatable_relocs* rr)
+ {
+ gold_assert(reloc_shndx < this->shnum());
+ (*this->map_to_relocatable_relocs_)[reloc_shndx] = rr;
+ }
+
+ // Get the relocatable reloc info for an input reloc section.
+ Relocatable_relocs*
+ relocatable_relocs(unsigned int reloc_shndx)
+ {
+ gold_assert(reloc_shndx < this->shnum());
+ return (*this->map_to_relocatable_relocs_)[reloc_shndx];
+ }
+
protected:
// What we need to know to map an input section to an output
// section. We keep an array of these, one for each input section,
Output_section* output_section;
// The offset within the output section. This is -1 if the
// section requires special handling.
- off_t offset;
+ section_offset_type offset;
};
// Read the relocs--implemented by child class.
do_scan_relocs(const General_options&, Symbol_table*, Layout*,
Read_relocs_data*) = 0;
+ // Return the number of local symbols--implemented by child class.
+ virtual unsigned int
+ do_local_symbol_count() const = 0;
+
// Count local symbols--implemented by child class.
virtual void
do_count_local_symbols(Stringpool_template<char>*,
- Stringpool_template<char>*) = 0;
+ Stringpool_template<char>*) = 0;
- // Finalize the local symbols. Set the output symbol table indexes for the local variables, and set the
- // offset where local symbol information will be stored.
+ // Finalize the local symbols. Set the output symbol table indexes
+ // for the local variables, and set the offset where local symbol
+ // information will be stored.
virtual unsigned int
do_finalize_local_symbols(unsigned int, off_t) = 0;
map_to_output() const
{ return this->map_to_output_; }
+ // Set the size of the relocatable relocs array.
+ void
+ size_relocatable_relocs()
+ {
+ this->map_to_relocatable_relocs_ =
+ new std::vector<Relocatable_relocs*>(this->shnum());
+ }
+
// Record that we must wait for the output sections to be written
// before applying relocations.
void
private:
// Mapping from input sections to output section.
std::vector<Map_to_output> map_to_output_;
+ // Mapping from input section index to the information recorded for
+ // the relocations. This is only used for a relocatable link.
+ std::vector<Relocatable_relocs*>* map_to_relocatable_relocs_;
// Mappings for merge sections. This is managed by the code in the
// Merge_map class.
Object_merge_map* object_merge_map_;
// Implement Object::output_section inline for efficiency.
inline Output_section*
-Relobj::output_section(unsigned int shndx, off_t* poff) const
+Relobj::output_section(unsigned int shndx, section_offset_type* poff) const
{
gold_assert(shndx < this->map_to_output_.size());
const Map_to_output& mo(this->map_to_output_[shndx]);
return mo.output_section;
}
+// This class is used to handle relocations against a section symbol
+// in an SHF_MERGE section. For such a symbol, we need to know the
+// addend of the relocation before we can determine the final value.
+// The addend gives us the location in the input section, and we can
+// determine how it is mapped to the output section. For a
+// non-section symbol, we apply the addend to the final value of the
+// symbol; that is done in finalize_local_symbols, and does not use
+// this class.
+
+template<int size>
+class Merged_symbol_value
+{
+ public:
+ typedef typename elfcpp::Elf_types<size>::Elf_Addr Value;
+
+ // We use a hash table to map offsets in the input section to output
+ // addresses.
+ typedef Unordered_map<section_offset_type, Value> Output_addresses;
+
+ Merged_symbol_value(Value input_value, Value output_start_address)
+ : input_value_(input_value), output_start_address_(output_start_address),
+ output_addresses_()
+ { }
+
+ // Initialize the hash table.
+ void
+ initialize_input_to_output_map(const Relobj*, unsigned int input_shndx);
+
+ // Release the hash table to save space.
+ void
+ free_input_to_output_map()
+ { this->output_addresses_.clear(); }
+
+ // Get the output value corresponding to an addend. The object and
+ // input section index are passed in because the caller will have
+ // them; otherwise we could store them here.
+ Value
+ value(const Relobj* object, unsigned int input_shndx, Value addend) const
+ {
+ Value input_offset = this->input_value_ + addend;
+ typename Output_addresses::const_iterator p =
+ this->output_addresses_.find(input_offset);
+ if (p != this->output_addresses_.end())
+ return p->second;
+
+ return this->value_from_output_section(object, input_shndx, input_offset);
+ }
+
+ private:
+ // Get the output value for an input offset if we couldn't find it
+ // in the hash table.
+ Value
+ value_from_output_section(const Relobj*, unsigned int input_shndx,
+ Value input_offset) const;
+
+ // The value of the section symbol in the input file. This is
+ // normally zero, but could in principle be something else.
+ Value input_value_;
+ // The start address of this merged section in the output file.
+ Value output_start_address_;
+ // A hash table which maps offsets in the input section to output
+ // addresses. This only maps specific offsets, not all offsets.
+ Output_addresses output_addresses_;
+};
+
// This POD class is holds the value of a symbol. This is used for
// local symbols, and for all symbols during relocation processing.
// For special sections, such as SHF_MERGE sections, this calls a
Symbol_value()
: output_symtab_index_(0), output_dynsym_index_(-1U), input_shndx_(0),
is_section_symbol_(false), is_tls_symbol_(false),
- needs_output_address_(false), value_(0)
- { }
+ has_output_value_(true)
+ { this->u_.value = 0; }
// Get the value of this symbol. OBJECT is the object in which this
// symbol is defined, and ADDEND is an addend to add to the value.
Value
value(const Sized_relobj<size, big_endian>* object, Value addend) const
{
- if (!this->needs_output_address_)
- return this->value_ + addend;
- return object->local_value(this->input_shndx_, this->value_,
- this->is_section_symbol_, addend);
+ if (this->has_output_value_)
+ return this->u_.value + addend;
+ else
+ return this->u_.merged_symbol_value->value(object, this->input_shndx_,
+ addend);
}
// Set the value of this symbol in the output symbol table.
void
set_output_value(Value value)
+ { this->u_.value = value; }
+
+ // For a section symbol in a merged section, we need more
+ // information.
+ void
+ set_merged_symbol_value(Merged_symbol_value<size>* msv)
{
- this->value_ = value;
- this->needs_output_address_ = false;
+ gold_assert(this->is_section_symbol_);
+ this->has_output_value_ = false;
+ this->u_.merged_symbol_value = msv;
}
- // Set the value of the symbol from the input file. This value
- // will usually be replaced during finalization with the output
- // value, but if the symbol is mapped to an output section which
- // requires special handling to determine the output value, we
- // leave the input value in place until later. This is used for
- // SHF_MERGE sections.
+ // Initialize the input to output map for a section symbol in a
+ // merged section. We also initialize the value of a non-section
+ // symbol in a merged section.
void
- set_input_value(Value value)
+ initialize_input_to_output_map(const Relobj* object)
{
- this->value_ = value;
- this->needs_output_address_ = true;
+ if (!this->has_output_value_)
+ {
+ gold_assert(this->is_section_symbol_);
+ Merged_symbol_value<size>* msv = this->u_.merged_symbol_value;
+ msv->initialize_input_to_output_map(object, this->input_shndx_);
+ }
}
- // Return the input value.
- Value
- input_value() const
+ // Free the input to output map for a section symbol in a merged
+ // section.
+ void
+ free_input_to_output_map()
{
- gold_assert(this->needs_output_address_);
- return this->value_;
+ if (!this->has_output_value_)
+ this->u_.merged_symbol_value->free_input_to_output_map();
}
+ // Set the value of the symbol from the input file. This is only
+ // called by count_local_symbols, to communicate the value to
+ // finalize_local_symbols.
+ void
+ set_input_value(Value value)
+ { this->u_.value = value; }
+
+ // Return the input value. This is only called by
+ // finalize_local_symbols.
+ Value
+ input_value() const
+ { return this->u_.value; }
+
// Return whether this symbol should go into the output symbol
// table.
bool
needs_output_symtab_entry() const
- {
- // gold_assert(this->output_symtab_index_ != 0);
- return this->output_symtab_index_ != -1U;
- }
+ { return this->output_symtab_index_ != -1U; }
// Return the index in the output symbol table.
unsigned int
void
set_needs_output_dynsym_entry()
{
+ gold_assert(!this->is_section_symbol());
this->output_dynsym_index_ = 0;
}
unsigned int
output_dynsym_index() const
{
- gold_assert(this->output_dynsym_index_ != 0);
+ gold_assert(this->output_dynsym_index_ != 0
+ && this->output_dynsym_index_ != -1U);
return this->output_dynsym_index_;
}
set_input_shndx(unsigned int i)
{
this->input_shndx_ = i;
+ // input_shndx_ field is a bitfield, so make sure that the value
+ // fits.
gold_assert(this->input_shndx_ == i);
}
input_shndx() const
{ return this->input_shndx_; }
+ // Whether this is a section symbol.
+ bool
+ is_section_symbol() const
+ { return this->is_section_symbol_; }
+
// Record that this is a section symbol.
void
set_is_section_symbol()
- { this->is_section_symbol_ = true; }
+ {
+ gold_assert(!this->needs_output_dynsym_entry());
+ this->is_section_symbol_ = true;
+ }
// Record that this is a TLS symbol.
void
bool is_section_symbol_ : 1;
// Whether this is a STT_TLS symbol.
bool is_tls_symbol_ : 1;
- // Whether getting the value of this symbol requires calling an
- // Output_section method. For example, this will be true of a
- // symbol in a SHF_MERGE section.
- bool needs_output_address_ : 1;
- // The value of the symbol. If !needs_output_address_, this is the
- // value in the output file. If needs_output_address_, this is the
- // value in the input file.
- Value value_;
+ // Whether this symbol has a value for the output file. This is
+ // normally set to true during Layout::finalize, by
+ // finalize_local_symbols. It will be false for a section symbol in
+ // a merge section, as for such symbols we can not determine the
+ // value to use in a relocation until we see the addend.
+ bool has_output_value_ : 1;
+ union
+ {
+ // This is used if has_output_value_ is true. Between
+ // count_local_symbols and finalize_local_symbols, this is the
+ // value in the input file. After finalize_local_symbols, it is
+ // the value in the output file.
+ Value value;
+ // This is used if has_output_value_ is false. It points to the
+ // information we need to get the value for a merge section.
+ Merged_symbol_value<size>* merged_symbol_value;
+ } u_;
+};
+
+// A GOT offset list. A symbol may have more than one GOT offset
+// (e.g., when mixing modules compiled with two different TLS models),
+// but will usually have at most one. GOT_TYPE identifies the type of
+// GOT entry; its values are specific to each target.
+
+class Got_offset_list
+{
+ public:
+ Got_offset_list()
+ : got_type_(-1U), got_offset_(0), got_next_(NULL)
+ { }
+
+ Got_offset_list(unsigned int got_type, unsigned int got_offset)
+ : got_type_(got_type), got_offset_(got_offset), got_next_(NULL)
+ { }
+
+ ~Got_offset_list()
+ {
+ if (this->got_next_ != NULL)
+ {
+ delete this->got_next_;
+ this->got_next_ = NULL;
+ }
+ }
+
+ // Initialize the fields to their default values.
+ void
+ init()
+ {
+ this->got_type_ = -1U;
+ this->got_offset_ = 0;
+ this->got_next_ = NULL;
+ }
+
+ // Set the offset for the GOT entry of type GOT_TYPE.
+ void
+ set_offset(unsigned int got_type, unsigned int got_offset)
+ {
+ if (this->got_type_ == -1U)
+ {
+ this->got_type_ = got_type;
+ this->got_offset_ = got_offset;
+ }
+ else
+ {
+ for (Got_offset_list* g = this; g != NULL; g = g->got_next_)
+ {
+ if (g->got_type_ == got_type)
+ {
+ g->got_offset_ = got_offset;
+ return;
+ }
+ }
+ Got_offset_list* g = new Got_offset_list(got_type, got_offset);
+ g->got_next_ = this->got_next_;
+ this->got_next_ = g;
+ }
+ }
+
+ // Return the offset for a GOT entry of type GOT_TYPE.
+ unsigned int
+ get_offset(unsigned int got_type) const
+ {
+ for (const Got_offset_list* g = this; g != NULL; g = g->got_next_)
+ {
+ if (g->got_type_ == got_type)
+ return g->got_offset_;
+ }
+ return -1U;
+ }
+
+ private:
+ unsigned int got_type_;
+ unsigned int got_offset_;
+ Got_offset_list* got_next_;
};
// A regular object file. This is size and endian specific.
void
setup(const typename elfcpp::Ehdr<size, big_endian>&);
- // Return the number of local symbols.
- unsigned int
- local_symbol_count() const
- { return this->local_symbol_count_; }
-
// If SYM is the index of a global symbol in the object file's
// symbol table, return the Symbol object. Otherwise, return NULL.
Symbol*
return this->local_values_[sym].output_dynsym_index();
}
- // Return the appropriate Sized_target structure.
- Sized_target<size, big_endian>*
- sized_target()
+ // Return the input section index of local symbol SYM.
+ unsigned int
+ local_symbol_input_shndx(unsigned int sym) const
{
- return this->Object::sized_target
- SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
- SELECT_SIZE_ENDIAN_ONLY(size, big_endian));
+ gold_assert(sym < this->local_values_.size());
+ return this->local_values_[sym].input_shndx();
}
- // Return the value of the local symbol symndx.
- Address
- local_symbol_value(unsigned int symndx) const;
-
- // Return the value of a local symbol defined in input section
- // SHNDX, with value VALUE, adding addend ADDEND. IS_SECTION_SYMBOL
- // indicates whether the symbol is a section symbol. This handles
- // SHF_MERGE sections.
- Address
- local_value(unsigned int shndx, Address value, bool is_section_symbol,
- Address addend) const;
+ // Return the appropriate Sized_target structure.
+ Sized_target<size, big_endian>*
+ sized_target()
+ { return this->Object::sized_target<size, big_endian>(); }
+ // Record that local symbol SYM needs a dynamic symbol entry.
void
set_needs_output_dynsym_entry(unsigned int sym)
{
// Return whether the local symbol SYMNDX has a GOT offset.
// For TLS symbols, the GOT entry will hold its tp-relative offset.
bool
- local_has_got_offset(unsigned int symndx) const
+ local_has_got_offset(unsigned int symndx, unsigned int got_type) const
{
- return (this->local_got_offsets_.find(symndx)
- != this->local_got_offsets_.end());
+ Local_got_offsets::const_iterator p =
+ this->local_got_offsets_.find(symndx);
+ return (p != this->local_got_offsets_.end()
+ && p->second->get_offset(got_type) != -1U);
}
// Return the GOT offset of the local symbol SYMNDX.
unsigned int
- local_got_offset(unsigned int symndx) const
+ local_got_offset(unsigned int symndx, unsigned int got_type) const
{
Local_got_offsets::const_iterator p =
this->local_got_offsets_.find(symndx);
gold_assert(p != this->local_got_offsets_.end());
- return p->second;
+ unsigned int off = p->second->get_offset(got_type);
+ gold_assert(off != -1U);
+ return off;
}
// Set the GOT offset of the local symbol SYMNDX to GOT_OFFSET.
void
- set_local_got_offset(unsigned int symndx, unsigned int got_offset)
- {
- std::pair<Local_got_offsets::iterator, bool> ins =
- this->local_got_offsets_.insert(std::make_pair(symndx, got_offset));
- gold_assert(ins.second);
- }
-
- // Return whether the local TLS symbol SYMNDX has a GOT offset.
- // The GOT entry at this offset will contain a module index. If
- // NEED_PAIR is true, a second entry immediately following the first
- // will contain the dtv-relative offset.
- bool
- local_has_tls_got_offset(unsigned int symndx, bool need_pair) const
- {
- typename Local_tls_got_offsets::const_iterator p =
- this->local_tls_got_offsets_.find(symndx);
- if (p == this->local_tls_got_offsets_.end()
- || (need_pair && !p->second.have_pair_))
- return false;
- return true;
- }
-
- // Return the offset of the GOT entry for the local TLS symbol SYMNDX.
- // If NEED_PAIR is true, we need the offset of a pair of GOT entries;
- // otherwise we need the offset of the GOT entry for the module index.
- unsigned int
- local_tls_got_offset(unsigned int symndx, bool need_pair) const
- {
- typename Local_tls_got_offsets::const_iterator p =
- this->local_tls_got_offsets_.find(symndx);
- gold_assert(p != this->local_tls_got_offsets_.end());
- gold_assert(!need_pair || p->second.have_pair_);
- return p->second.got_offset_;
- }
-
- // Set the offset of the GOT entry for the local TLS symbol SYMNDX
- // to GOT_OFFSET. If HAVE_PAIR is true, we have a pair of GOT entries;
- // otherwise, we have just a single entry for the module index.
- void
- set_local_tls_got_offset(unsigned int symndx, unsigned int got_offset,
- bool have_pair)
+ set_local_got_offset(unsigned int symndx, unsigned int got_type,
+ unsigned int got_offset)
{
- typename Local_tls_got_offsets::iterator p =
- this->local_tls_got_offsets_.find(symndx);
- if (p != this->local_tls_got_offsets_.end())
- {
- // An entry already existed for this symbol. This can happen
- // if we see a relocation asking for the module index before
- // a relocation asking for the pair. In that case, the original
- // GOT entry will remain, but won't get used by any further
- // relocations.
- p->second.got_offset_ = got_offset;
- gold_assert(have_pair);
- p->second.have_pair_ = true;
- }
+ Local_got_offsets::const_iterator p =
+ this->local_got_offsets_.find(symndx);
+ if (p != this->local_got_offsets_.end())
+ p->second->set_offset(got_type, got_offset);
else
{
- std::pair<typename Local_tls_got_offsets::iterator, bool> ins =
- this->local_tls_got_offsets_.insert(
- std::make_pair(symndx, Tls_got_entry(got_offset, have_pair)));
+ Got_offset_list* g = new Got_offset_list(got_type, got_offset);
+ std::pair<Local_got_offsets::iterator, bool> ins =
+ this->local_got_offsets_.insert(std::make_pair(symndx, g));
gold_assert(ins.second);
}
}
get_symbol_location_info(unsigned int shndx, off_t offset,
Symbol_location_info* info);
+ protected:
// Read the symbols.
void
do_read_symbols(Read_symbols_data*);
+ // Return the number of local symbols.
+ unsigned int
+ do_local_symbol_count() const
+ { return this->local_symbol_count_; }
+
// Lay out the input sections.
void
do_layout(Symbol_table*, Layout*, Read_symbols_data*);
do_relocate(const General_options& options, const Symbol_table* symtab,
const Layout*, Output_file* of);
+ // Get the size of a section.
+ uint64_t
+ do_section_size(unsigned int shndx)
+ { return this->elf_file_.section_size(shndx); }
+
// Get the name of a section.
std::string
do_section_name(unsigned int shndx)
do_section_flags(unsigned int shndx)
{ return this->elf_file_.section_flags(shndx); }
+ // Return section address.
+ uint64_t
+ do_section_address(unsigned int shndx)
+ { return this->elf_file_.section_addr(shndx); }
+
// Return section type.
unsigned int
do_section_type(unsigned int shndx)
do_section_info(unsigned int shndx)
{ return this->elf_file_.section_info(shndx); }
+ // Return the section alignment.
+ uint64_t
+ do_section_addralign(unsigned int shndx)
+ { return this->elf_file_.section_addralign(shndx); }
+
private:
// For convenience.
typedef Sized_relobj<size, big_endian> This;
// a GNU style exception frame section.
bool
find_eh_frame(const unsigned char* pshdrs, const char* names,
- off_t names_size) const;
+ section_size_type names_size) const;
// Whether to include a section group in the link.
bool
- include_section_group(Layout*, unsigned int,
+ include_section_group(Symbol_table*, Layout*, unsigned int, const char*,
const elfcpp::Shdr<size, big_endian>&,
std::vector<bool>*);
unsigned char* view;
typename elfcpp::Elf_types<size>::Elf_Addr address;
off_t offset;
- off_t view_size;
+ section_size_type view_size;
bool is_input_output_view;
bool is_postprocessing_view;
};
relocate_sections(const General_options& options, const Symbol_table*,
const Layout*, const unsigned char* pshdrs, Views*);
+ // Scan the input relocations for --emit-relocs.
+ void
+ emit_relocs_scan(const General_options&, Symbol_table*, Layout*,
+ const unsigned char* plocal_syms,
+ const Read_relocs_data::Relocs_list::iterator&);
+
+ // Scan the input relocations for --emit-relocs, templatized on the
+ // type of the relocation section.
+ template<int sh_type>
+ void
+ emit_relocs_scan_reltype(const General_options&, Symbol_table*, Layout*,
+ const unsigned char* plocal_syms,
+ const Read_relocs_data::Relocs_list::iterator&,
+ Relocatable_relocs*);
+
+ // Emit the relocs for --emit-relocs.
+ void
+ emit_relocs(const Relocate_info<size, big_endian>*, unsigned int,
+ unsigned int sh_type, const unsigned char* prelocs,
+ size_t reloc_count, Output_section*, off_t output_offset,
+ unsigned char* view, Address address,
+ section_size_type view_size,
+ unsigned char* reloc_view, section_size_type reloc_view_size);
+
+ // Emit the relocs for --emit-relocs, templatized on the type of the
+ // relocation section.
+ template<int sh_type>
+ void
+ emit_relocs_reltype(const Relocate_info<size, big_endian>*, unsigned int,
+ const unsigned char* prelocs, size_t reloc_count,
+ Output_section*, off_t output_offset,
+ unsigned char* view, Address address,
+ section_size_type view_size,
+ unsigned char* reloc_view,
+ section_size_type reloc_view_size);
+
+ // Initialize input to output maps for section symbols in merged
+ // sections.
+ void
+ initialize_input_to_output_maps();
+
+ // Free the input to output maps for section symbols in merged
+ // sections.
+ void
+ free_input_to_output_maps();
+
// Write out the local symbols.
void
write_local_symbols(Output_file*,
const Stringpool_template<char>*,
const Stringpool_template<char>*);
+ // Clear the local symbol information.
+ void
+ clear_local_symbols()
+ {
+ this->local_values_.clear();
+ this->local_got_offsets_.clear();
+ }
+
// The GOT offsets of local symbols. This map also stores GOT offsets
// for tp-relative offsets for TLS symbols.
- typedef Unordered_map<unsigned int, unsigned int> Local_got_offsets;
+ typedef Unordered_map<unsigned int, Got_offset_list*> Local_got_offsets;
// The TLS GOT offsets of local symbols. The map stores the offsets
// for either a single GOT entry that holds the module index of a TLS
// GOT offsets for local non-TLS symbols, and tp-relative offsets
// for TLS symbols, indexed by symbol number.
Local_got_offsets local_got_offsets_;
- // GOT offsets for local TLS symbols, indexed by symbol number
- // and GOT entry type.
- Local_tls_got_offsets local_tls_got_offsets_;
// Whether this object has a GNU style .eh_frame section.
bool has_eh_frame_;
};
{
public:
Input_objects()
- : relobj_list_(), dynobj_list_(), target_(NULL), sonames_(),
- system_library_directory_()
+ : relobj_list_(), dynobj_list_(), sonames_(), system_library_directory_()
{ }
// The type of the list of input relocateable objects.
bool
add_object(Object*);
- // Get the target we should use for the output file.
- Target*
- target() const
- { return this->target_; }
-
// For each dynamic object, check whether we've seen all of its
// explicit dependencies.
void
Relobj_list relobj_list_;
// The list of dynamic objects included in the link.
Dynobj_list dynobj_list_;
- // The target.
- Target* target_;
// SONAMEs that we have seen.
Unordered_set<std::string> sonames_;
// The directory in which we find the libc.so.
extern Object*
make_elf_object(const std::string& name, Input_file*,
off_t offset, const unsigned char* p,
- off_t bytes);
+ section_offset_type bytes);
} // end namespace gold