// object.h -- support for an object file for linking in gold -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright (C) 2006-2014 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
class Dynobj;
class Object_merge_map;
class Relocatable_relocs;
-class Symbols_data;
+struct Symbols_data;
template<typename Stringpool_char>
class Stringpool_template;
{
std::string source_file;
std::string enclosing_symbol_name;
- int line_number;
+ elfcpp::STT enclosing_symbol_type;
};
// Data about a single relocation section. This is read in
: name_(name), input_file_(input_file), offset_(offset), shnum_(-1U),
is_dynamic_(is_dynamic), is_needed_(false), uses_split_stack_(false),
has_no_split_stack_(false), no_export_(false),
- is_in_system_directory_(false), xindex_(NULL)
+ is_in_system_directory_(false), as_needed_(false), xindex_(NULL)
{
if (input_file != NULL)
{
input_file->file().add_object();
this->is_in_system_directory_ = input_file->is_in_system_directory();
+ this->as_needed_ = input_file->options().as_needed();
}
}
this->input_file_->file().remove_object();
}
- // Return the name of the object as we would report it to the tuser.
+ // Return the name of the object as we would report it to the user.
const std::string&
name() const
{ return this->name_; }
has_no_split_stack() const
{ return this->has_no_split_stack_; }
+ // Returns NULL for Objects that are not dynamic objects. This method
+ // is overridden in the Dynobj class.
+ Dynobj*
+ dynobj()
+ { return this->do_dynobj(); }
+
// Returns NULL for Objects that are not plugin objects. This method
// is overridden in the Pluginobj class.
Pluginobj*
output_section(unsigned int shndx) const
{ return this->do_output_section(shndx); }
+ // Given a section index, return its address.
+ // The return value will be -1U if the section is specially mapped,
+ // such as a merge section.
+ uint64_t
+ output_section_address(unsigned int shndx)
+ { return this->do_output_section_address(shndx); }
+
// 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.
is_in_system_directory() const
{ return this->is_in_system_directory_; }
+ // Set flag that this object was linked with --as-needed.
+ void
+ set_as_needed()
+ { this->as_needed_ = true; }
+
+ // Return whether this object was linked with --as-needed.
+ bool
+ as_needed() const
+ { return this->as_needed_; }
+
// Return whether we found this object by searching a directory.
bool
searched_for() const
section_size_type* uncompressed_size) const
{ return this->do_section_is_compressed(shndx, uncompressed_size); }
+ // Return a view of the decompressed contents of a section. Set *PLEN
+ // to the size. Set *IS_NEW to true if the contents need to be freed
+ // by the caller.
+ const unsigned char*
+ decompressed_section_contents(unsigned int shndx, section_size_type* plen,
+ bool* is_cached)
+ { return this->do_decompressed_section_contents(shndx, plen, is_cached); }
+
+ // Discard any buffers of decompressed sections. This is done
+ // at the end of the Add_symbols task.
+ void
+ discard_decompressed_sections()
+ { this->do_discard_decompressed_sections(); }
+
// Return the index of the first incremental relocation for symbol SYMNDX.
unsigned int
get_incremental_reloc_base(unsigned int symndx) const
{ return this->do_get_incremental_reloc_count(symndx); }
protected:
+ // Returns NULL for Objects that are not dynamic objects. This method
+ // is overridden in the Dynobj class.
+ virtual Dynobj*
+ do_dynobj()
+ { return NULL; }
+
// Returns NULL for Objects that are not plugin objects. This method
// is overridden in the Pluginobj class.
virtual Pluginobj*
// Return the location of the contents of a section. Implemented by
// child class.
- virtual Location
- do_section_contents(unsigned int shndx) = 0;
+ virtual const unsigned char*
+ do_section_contents(unsigned int shndx, section_size_type* plen,
+ bool cache) = 0;
// Get the size of a section--implemented by child class.
virtual uint64_t
do_output_section(unsigned int) const
{ gold_unreachable(); }
+ // Get the address of a section--implemented by child class.
+ virtual uint64_t
+ do_output_section_address(unsigned int)
+ { gold_unreachable(); }
+
// Get the offset of a section--implemented by child class.
virtual uint64_t
do_output_section_offset(unsigned int) const
set_shnum(int shnum)
{ this->shnum_ = shnum; }
- // Functions used by both Sized_relobj and Sized_dynobj.
+ // Functions used by both Sized_relobj_file and Sized_dynobj.
// Read the section data into a Read_symbols_data object.
template<int size, bool big_endian>
read_section_data(elfcpp::Elf_file<size, big_endian, Object>*,
Read_symbols_data*);
+ // Find the section header with the given NAME. If HDR is non-NULL
+ // then it is a section header returned from a previous call to this
+ // function and the next section header with the same name will be
+ // returned.
+ template<int size, bool big_endian>
+ const unsigned char*
+ find_shdr(const unsigned char* pshdrs, const char* name,
+ const char* names, section_size_type names_size,
+ const unsigned char* hdr) const;
+
// Let the child class initialize the xindex object directly.
void
set_xindex(Xindex* xindex)
do_section_is_compressed(unsigned int, section_size_type*) const
{ return false; }
+ // Return a view of the decompressed contents of a section. Set *PLEN
+ // to the size. This default implementation simply returns the
+ // raw section contents and sets *IS_NEW to false to indicate
+ // that the contents do not need to be freed by the caller.
+ // This function must be overridden for any types of object files
+ // that might contain compressed sections.
+ virtual const unsigned char*
+ do_decompressed_section_contents(unsigned int shndx,
+ section_size_type* plen,
+ bool* is_new)
+ {
+ *is_new = false;
+ return this->do_section_contents(shndx, plen, false);
+ }
+
+ // Discard any buffers of decompressed sections. This is done
+ // at the end of the Add_symbols task.
+ virtual void
+ do_discard_decompressed_sections()
+ { }
+
// Return the index of the first incremental relocation for symbol SYMNDX--
// implemented by child class.
virtual unsigned int
bool no_export_ : 1;
// True if the object was found in a system directory.
bool is_in_system_directory_ : 1;
+ // True if the object was linked with --as-needed.
+ bool as_needed_ : 1;
// Many sections for objects with more than SHN_LORESERVE sections.
Xindex* xindex_;
};
// A regular object (ET_REL). This is an abstract base class itself.
-// The implementation is the template class Sized_relobj.
+// The implementation is the template class Sized_relobj_file.
class Relobj : public Object
{
relocs_must_follow_section_writes_(false),
sd_(NULL),
reloc_counts_(NULL),
- reloc_bases_(NULL)
+ reloc_bases_(NULL),
+ first_dyn_reloc_(0),
+ dyn_reloc_count_(0)
{ }
// During garbage collection, the Read_symbols_data pass for
scan_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd)
{ return this->do_scan_relocs(symtab, layout, rd); }
+ // Return the value of the local symbol whose index is SYMNDX, plus
+ // ADDEND. ADDEND is passed in so that we can correctly handle the
+ // section symbol for a merge section.
+ uint64_t
+ local_symbol_value(unsigned int symndx, uint64_t addend) const
+ { return this->do_local_symbol_value(symndx, addend); }
+
+ // Return the PLT offset for a local symbol. It is an error to call
+ // this if it doesn't have one.
+ unsigned int
+ local_plt_offset(unsigned int symndx) const
+ { return this->do_local_plt_offset(symndx); }
+
+ // Return whether the local symbol SYMNDX has a GOT offset of type
+ // GOT_TYPE.
+ bool
+ local_has_got_offset(unsigned int symndx, unsigned int got_type) const
+ { return this->do_local_has_got_offset(symndx, got_type); }
+
+ // Return the GOT offset of type GOT_TYPE of the local symbol
+ // SYMNDX. It is an error to call this if the symbol does not have
+ // a GOT offset of the specified type.
+ unsigned int
+ local_got_offset(unsigned int symndx, unsigned int got_type) const
+ { return this->do_local_got_offset(symndx, got_type); }
+
+ // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
+ // to GOT_OFFSET.
+ void
+ set_local_got_offset(unsigned int symndx, unsigned int got_type,
+ unsigned int got_offset)
+ { this->do_set_local_got_offset(symndx, got_type, got_offset); }
+
+ // Return whether the local symbol SYMNDX is a TLS symbol.
+ bool
+ local_is_tls(unsigned int symndx) const
+ { return this->do_local_is_tls(symndx); }
+
// The number of local symbols in the input symbol table.
virtual unsigned int
local_symbol_count() const
set_local_dynsym_offset(off_t off)
{ return this->do_set_local_dynsym_offset(off); }
+ // Record a dynamic relocation against an input section from this object.
+ void
+ add_dyn_reloc(unsigned int index)
+ {
+ if (this->dyn_reloc_count_ == 0)
+ this->first_dyn_reloc_ = index;
+ ++this->dyn_reloc_count_;
+ }
+
+ // Return the index of the first dynamic relocation.
+ unsigned int
+ first_dyn_reloc() const
+ { return this->first_dyn_reloc_; }
+
+ // Return the count of dynamic relocations.
+ unsigned int
+ dyn_reloc_count() const
+ { return this->dyn_reloc_count_; }
+
// Relocate the input sections and write out the local symbols.
void
relocate(const Symbol_table* symtab, const Layout* layout, Output_file* of)
return this->output_sections_[shndx] != NULL;
}
- // The the output section of the input section with index SHNDX.
+ // 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
do_get_incremental_reloc_count(unsigned int symndx) const
{ return this->reloc_counts_[symndx]; }
+ // Return the word size of the object file.
+ int
+ elfsize() const
+ { return this->do_elfsize(); }
+
+ // Return TRUE if this is a big-endian object file.
+ bool
+ is_big_endian() const
+ { return this->do_is_big_endian(); }
+
protected:
// The output section to be used for each input section, indexed by
// the input section number. The output section is NULL if the
virtual void
do_scan_relocs(Symbol_table*, Layout*, Read_relocs_data*) = 0;
+ // Return the value of a local symbol.
+ virtual uint64_t
+ do_local_symbol_value(unsigned int symndx, uint64_t addend) const = 0;
+
+ // Return the PLT offset of a local symbol.
+ virtual unsigned int
+ do_local_plt_offset(unsigned int symndx) const = 0;
+
+ // Return whether a local symbol has a GOT offset of a given type.
+ virtual bool
+ do_local_has_got_offset(unsigned int symndx,
+ unsigned int got_type) const = 0;
+
+ // Return the GOT offset of a given type of a local symbol.
+ virtual unsigned int
+ do_local_got_offset(unsigned int symndx, unsigned int got_type) const = 0;
+
+ // Set the GOT offset with a given type for a local symbol.
+ virtual void
+ do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
+ unsigned int got_offset) = 0;
+
+ // Return whether local symbol SYMNDX is a TLS symbol.
+ virtual bool
+ do_local_is_tls(unsigned int symndx) const = 0;
+
// Return the number of local symbols--implemented by child class.
virtual unsigned int
do_local_symbol_count() const = 0;
return this->reloc_bases_[symndx] + counter;
}
+ // Return the word size of the object file--
+ // implemented by child class.
+ virtual int
+ do_elfsize() const = 0;
+
+ // Return TRUE if this is a big-endian object file--
+ // implemented by child class.
+ virtual bool
+ do_is_big_endian() const = 0;
+
private:
// Mapping from input sections to output section.
Output_sections output_sections_;
unsigned int* reloc_counts_;
// Per-symbol base indexes of relocations, for incremental links.
unsigned int* reloc_bases_;
+ // Index of the first dynamic relocation for this object.
+ unsigned int first_dyn_reloc_;
+ // Count of dynamic relocations for this object.
+ unsigned int dyn_reloc_count_;
};
// This class is used to handle relocations against a section symbol
// symbol is defined, and ADDEND is an addend to add to the value.
template<bool big_endian>
Value
- value(const Sized_relobj<size, big_endian>* object, Value addend) const
+ value(const Sized_relobj_file<size, big_endian>* object, Value addend) const
{
if (this->has_output_value_)
return this->u_.value + addend;
std::vector<Symbol*> vec_;
};
-// Type for mapping section index to uncompressed size.
+// Type for mapping section index to uncompressed size and contents.
-typedef std::map<unsigned int, section_size_type> Compressed_section_map;
+struct Compressed_section_info
+{
+ section_size_type size;
+ const unsigned char* contents;
+};
+typedef std::map<unsigned int, Compressed_section_info> Compressed_section_map;
// Abstract base class for a regular object file, either a real object file
// or an incremental (unchanged) object. This is size and endian specific.
template<int size, bool big_endian>
-class Sized_relobj_base : public Relobj
+class Sized_relobj : public Relobj
{
public:
+ typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
typedef Relobj::Symbols Symbols;
- Sized_relobj_base(const std::string& name, Input_file* input_file)
- : Relobj(name, input_file)
+ static const Address invalid_address = static_cast<Address>(0) - 1;
+
+ Sized_relobj(const std::string& name, Input_file* input_file)
+ : Relobj(name, input_file), local_got_offsets_(), section_offsets_()
{ }
- Sized_relobj_base(const std::string& name, Input_file* input_file,
+ Sized_relobj(const std::string& name, Input_file* input_file,
off_t offset)
- : Relobj(name, input_file, offset)
+ : Relobj(name, input_file, offset), local_got_offsets_(), section_offsets_()
{ }
- ~Sized_relobj_base()
+ ~Sized_relobj()
{ }
+ // If this is a regular object, return a pointer to the Sized_relobj_file
+ // object. Otherwise, return NULL.
+ virtual Sized_relobj_file<size, big_endian>*
+ sized_relobj()
+ { return NULL; }
+
+ const virtual Sized_relobj_file<size, big_endian>*
+ sized_relobj() const
+ { return NULL; }
+
+ // Checks if the offset of input section SHNDX within its output
+ // section is invalid.
+ bool
+ is_output_section_offset_invalid(unsigned int shndx) const
+ { return this->get_output_section_offset(shndx) == invalid_address; }
+
+ // Get the offset of input section SHNDX within its output section.
+ // This is -1 if the input section requires a special mapping, such
+ // as a merge section. The output section can be found in the
+ // output_sections_ field of the parent class Relobj.
+ Address
+ get_output_section_offset(unsigned int shndx) const
+ {
+ gold_assert(shndx < this->section_offsets_.size());
+ return this->section_offsets_[shndx];
+ }
+
+ // Iterate over local symbols, calling a visitor class V for each GOT offset
+ // associated with a local symbol.
+ void
+ do_for_all_local_got_entries(Got_offset_list::Visitor* v) const;
+
protected:
typedef Relobj::Output_sections Output_sections;
+ // Clear the local symbol information.
+ void
+ clear_got_offsets()
+ { this->local_got_offsets_.clear(); }
+
+ // Return the vector of section offsets.
+ std::vector<Address>&
+ section_offsets()
+ { return this->section_offsets_; }
+
+ // Get the address of an output section.
+ uint64_t
+ do_output_section_address(unsigned int shndx);
+
+ // Get the offset of a section.
+ uint64_t
+ do_output_section_offset(unsigned int shndx) const
+ {
+ Address off = this->get_output_section_offset(shndx);
+ if (off == invalid_address)
+ return -1ULL;
+ return off;
+ }
+
+ // Set the offset of a section.
+ void
+ do_set_section_offset(unsigned int shndx, uint64_t off)
+ {
+ gold_assert(shndx < this->section_offsets_.size());
+ this->section_offsets_[shndx] =
+ (off == static_cast<uint64_t>(-1)
+ ? invalid_address
+ : convert_types<Address, uint64_t>(off));
+ }
+
+ // Return whether the local symbol SYMNDX has a GOT offset of type
+ // GOT_TYPE.
+ bool
+ do_local_has_got_offset(unsigned int symndx, unsigned int got_type) const
+ {
+ 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 type GOT_TYPE of the local symbol
+ // SYMNDX.
+ unsigned int
+ do_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());
+ unsigned int off = p->second->get_offset(got_type);
+ gold_assert(off != -1U);
+ return off;
+ }
+
+ // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
+ // to GOT_OFFSET.
+ void
+ do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
+ unsigned int got_offset)
+ {
+ 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
+ {
+ 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);
+ }
+ }
+
+ // Return the word size of the object file.
+ virtual int
+ do_elfsize() const
+ { return size; }
+
+ // Return TRUE if this is a big-endian object file.
+ virtual bool
+ do_is_big_endian() const
+ { return big_endian; }
+
private:
+ // The GOT offsets of local symbols. This map also stores GOT offsets
+ // for tp-relative offsets for TLS symbols.
+ typedef Unordered_map<unsigned int, Got_offset_list*> Local_got_offsets;
+
+ // GOT offsets for local non-TLS symbols, and tp-relative offsets
+ // for TLS symbols, indexed by symbol number.
+ Local_got_offsets local_got_offsets_;
+ // For each input section, the offset of the input section in its
+ // output section. This is INVALID_ADDRESS if the input section requires a
+ // special mapping.
+ std::vector<Address> section_offsets_;
};
// A regular object file. This is size and endian specific.
template<int size, bool big_endian>
-class Sized_relobj : public Sized_relobj_base<size, big_endian>
+class Sized_relobj_file : public Sized_relobj<size, big_endian>
{
public:
typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
- typedef typename Sized_relobj_base<size, big_endian>::Symbols Symbols;
+ typedef typename Sized_relobj<size, big_endian>::Symbols Symbols;
typedef std::vector<Symbol_value<size> > Local_values;
static const Address invalid_address = static_cast<Address>(0) - 1;
CFLV_DISCARDED
};
- Sized_relobj(const std::string& name, Input_file* input_file, off_t offset,
- const typename elfcpp::Ehdr<size, big_endian>&);
-
- ~Sized_relobj();
+ Sized_relobj_file(const std::string& name,
+ Input_file* input_file,
+ off_t offset,
+ const typename elfcpp::Ehdr<size, big_endian>&);
- // Checks if the offset of input section SHNDX within its output
- // section is invalid.
- bool
- is_output_section_offset_invalid(unsigned int shndx) const
- { return this->get_output_section_offset(shndx) == invalid_address; }
+ ~Sized_relobj_file();
// Set up the object file based on TARGET.
void
setup()
{ this->do_setup(); }
+ // Return a pointer to the Sized_relobj_file object.
+ Sized_relobj_file<size, big_endian>*
+ sized_relobj()
+ { return this; }
+
+ const Sized_relobj_file<size, big_endian>*
+ sized_relobj() const
+ { return this; }
+
+ // Return the ELF file type.
+ int
+ e_type() const
+ { return this->e_type_; }
+
// Return the number of symbols. This is only valid after
// Object::add_symbols has been called.
unsigned int
this->local_values_[sym].set_needs_output_dynsym_entry();
}
- // 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, unsigned int got_type) const
- {
- 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, 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());
- 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_type,
- unsigned int got_offset)
- {
- 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
- {
- 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);
- }
- }
-
// Return whether the local symbol SYMNDX has a PLT offset.
bool
local_has_plt_offset(unsigned int symndx) const;
- // Return the PLT offset for a local symbol. It is an error to call
- // this if it doesn't have one.
- unsigned int
- local_plt_offset(unsigned int symndx) const;
-
// Set the PLT offset of the local symbol SYMNDX.
void
set_local_plt_offset(unsigned int symndx, unsigned int plt_offset);
- // Get the offset of input section SHNDX within its output section.
- // This is -1 if the input section requires a special mapping, such
- // as a merge section. The output section can be found in the
- // output_sections_ field of the parent class Relobj.
- Address
- get_output_section_offset(unsigned int shndx) const
- {
- gold_assert(shndx < this->section_offsets_.size());
- return this->section_offsets_[shndx];
- }
+ // Adjust this local symbol value. Return false if the symbol
+ // should be discarded from the output file.
+ bool
+ adjust_local_symbol(Symbol_value<size>* lv) const
+ { return this->do_adjust_local_symbol(lv); }
// Return the name of the symbol that spans the given offset in the
// specified section in this object. This is used only for error
const Symbol_table* symtab);
protected:
- typedef typename Sized_relobj_base<size, big_endian>::Output_sections
+ typedef typename Sized_relobj<size, big_endian>::Output_sections
Output_sections;
// Set up.
void
do_read_symbols(Read_symbols_data*);
+ // Return the value of a local symbol.
+ uint64_t
+ do_local_symbol_value(unsigned int symndx, uint64_t addend) const
+ {
+ const Symbol_value<size>* symval = this->local_symbol(symndx);
+ return symval->value(this, addend);
+ }
+
+ // Return the PLT offset for a local symbol. It is an error to call
+ // this if it doesn't have one.
+ unsigned int
+ do_local_plt_offset(unsigned int symndx) const;
+
+ // Return whether local symbol SYMNDX is a TLS symbol.
+ bool
+ do_local_is_tls(unsigned int symndx) const
+ { return this->local_symbol(symndx)->is_tls_symbol(); }
+
// Return the number of local symbols.
unsigned int
do_local_symbol_count() const
do_for_all_global_symbols(Read_symbols_data* sd,
Library_base::Symbol_visitor_base* v);
- // Iterate over local symbols, calling a visitor class V for each GOT offset
- // associated with a local symbol.
- void
- do_for_all_local_got_entries(Got_offset_list::Visitor* v) const;
-
// Read the relocs.
void
do_read_relocs(Read_relocs_data*);
{ return this->elf_file_.section_name(shndx); }
// Return the location of the contents of a section.
- Object::Location
- do_section_contents(unsigned int shndx)
- { return this->elf_file_.section_contents(shndx); }
+ const unsigned char*
+ do_section_contents(unsigned int shndx, section_size_type* plen,
+ bool cache)
+ {
+ Object::Location loc(this->elf_file_.section_contents(shndx));
+ *plen = convert_to_section_size_type(loc.data_size);
+ if (*plen == 0)
+ {
+ static const unsigned char empty[1] = { '\0' };
+ return empty;
+ }
+ return this->get_view(loc.file_offset, *plen, true, cache);
+ }
// Return section flags.
uint64_t
do_get_global_symbols() const
{ return &this->symbols_; }
- // Get the offset of a section.
- uint64_t
- do_output_section_offset(unsigned int shndx) const
- {
- Address off = this->get_output_section_offset(shndx);
- if (off == invalid_address)
- return -1ULL;
- return off;
- }
-
- // Set the offset of a section.
- void
- do_set_section_offset(unsigned int shndx, uint64_t off)
- {
- gold_assert(shndx < this->section_offsets_.size());
- this->section_offsets_[shndx] =
- (off == static_cast<uint64_t>(-1)
- ? invalid_address
- : convert_types<Address, uint64_t>(off));
- }
-
// Adjust a section index if necessary.
unsigned int
adjust_shndx(unsigned int shndx)
section_size_type view_size;
bool is_input_output_view;
bool is_postprocessing_view;
+ bool is_ctors_reverse_view;
};
typedef std::vector<View_size> Views;
+ // Stash away info for a number of special sections.
+ // Return true if any of the sections found require local symbols to be read.
+ virtual bool
+ do_find_special_sections(Read_symbols_data* sd);
+
// This may be overriden by a child class.
virtual void
do_relocate_sections(const Symbol_table* symtab, const Layout* layout,
const unsigned char* pshdrs, Output_file* of,
Views* pviews);
+ // Adjust this local symbol value. Return false if the symbol
+ // should be discarded from the output file.
+ virtual bool
+ do_adjust_local_symbol(Symbol_value<size>*) const
+ { return true; }
+
// Allow a child to set output local symbol count.
void
set_output_local_symbol_count(unsigned int value)
if (p != this->compressed_sections_->end())
{
if (uncompressed_size != NULL)
- *uncompressed_size = p->second;
+ *uncompressed_size = p->second.size;
return true;
}
return false;
}
+ // Return a view of the uncompressed contents of a section. Set *PLEN
+ // to the size. Set *IS_NEW to true if the contents need to be deleted
+ // by the caller.
+ const unsigned char*
+ do_decompressed_section_contents(unsigned int shndx,
+ section_size_type* plen,
+ bool* is_new);
+
+ // Discard any buffers of decompressed sections. This is done
+ // at the end of the Add_symbols task.
+ void
+ do_discard_decompressed_sections();
+
private:
// For convenience.
- typedef Sized_relobj<size, big_endian> This;
+ typedef Sized_relobj_file<size, big_endian> This;
static const int ehdr_size = elfcpp::Elf_sizes<size>::ehdr_size;
static const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
static const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
// Layout an input section.
void
layout_section(Layout* layout, unsigned int shndx, const char* name,
- typename This::Shdr& shdr, unsigned int reloc_shndx,
+ const typename This::Shdr& shdr, unsigned int reloc_shndx,
unsigned int reloc_type);
+ // Layout an input .eh_frame section.
+ void
+ layout_eh_frame_section(Layout* layout, const unsigned char* symbols_data,
+ section_size_type symbols_size,
+ const unsigned char* symbol_names_data,
+ section_size_type symbol_names_size,
+ unsigned int shndx, const typename This::Shdr&,
+ unsigned int reloc_shndx, unsigned int reloc_type);
+
// Write section data to the output file. Record the views and
// sizes in VIEWS for use when relocating.
void
- write_sections(const unsigned char* pshdrs, Output_file*, Views*);
+ write_sections(const Layout*, const unsigned char* pshdrs, Output_file*,
+ Views*);
// Relocate the sections in the output file.
void
Views* pviews)
{ this->do_relocate_sections(symtab, layout, pshdrs, of, pviews); }
+ // Reverse the words in a section. Used for .ctors sections mapped
+ // to .init_array sections.
+ void
+ reverse_words(unsigned char*, section_size_type);
+
// Scan the input relocations for --emit-relocs.
void
emit_relocs_scan(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*, Address 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*, Address output_offset,
- unsigned char* view, Address address,
- section_size_type view_size,
- unsigned char* reloc_view,
- section_size_type reloc_view_size);
-
// Scan the input relocations for --incremental.
void
incremental_relocs_scan(const Read_relocs_data::Relocs_list::iterator&);
const std::vector<Address>& out_offsets,
const Symbol_table* symtab);
- // The GOT offsets of local symbols. This map also stores GOT offsets
- // for tp-relative offsets for TLS symbols.
- typedef Unordered_map<unsigned int, Got_offset_list*> Local_got_offsets;
-
// The PLT offsets of local symbols.
typedef Unordered_map<unsigned int, unsigned int> Local_plt_offsets;
// General access to the ELF file.
elfcpp::Elf_file<size, big_endian, Object> elf_file_;
+ // Type of ELF file (ET_REL or ET_EXEC). ET_EXEC files are allowed
+ // as input files only for the --just-symbols option.
+ int e_type_;
// Index of SHT_SYMTAB section.
unsigned int symtab_shndx_;
// The number of local symbols.
off_t local_dynsym_offset_;
// Values of local symbols.
Local_values local_values_;
- // GOT offsets for local non-TLS symbols, and tp-relative offsets
- // for TLS symbols, indexed by symbol number.
- Local_got_offsets local_got_offsets_;
// PLT offsets for local symbols.
Local_plt_offsets local_plt_offsets_;
- // For each input section, the offset of the input section in its
- // output section. This is INVALID_ADDRESS if the input section requires a
- // special mapping.
- std::vector<Address> section_offsets_;
// Table mapping discarded comdat sections to corresponding kept sections.
Kept_comdat_section_table kept_comdat_sections_;
// Whether this object has a GNU style .eh_frame section.
std::vector<Deferred_layout> deferred_layout_;
// The list of relocation sections whose layout was deferred.
std::vector<Deferred_layout> deferred_layout_relocs_;
- // For compressed debug sections, map section index to uncompressed size.
+ // For compressed debug sections, map section index to uncompressed size
+ // and contents.
Compressed_section_map* compressed_sections_;
};
// Layout.
const Layout* layout;
// Object being relocated.
- Sized_relobj<size, big_endian>* object;
+ Sized_relobj_file<size, big_endian>* object;
// Section index of relocation section.
unsigned int reloc_shndx;
// Section header of relocation section.