Line 723... |
Line 723... |
bool
|
bool
|
section_is_compressed(unsigned int shndx,
|
section_is_compressed(unsigned int shndx,
|
section_size_type* uncompressed_size) const
|
section_size_type* uncompressed_size) const
|
{ return this->do_section_is_compressed(shndx, uncompressed_size); }
|
{ return this->do_section_is_compressed(shndx, uncompressed_size); }
|
|
|
|
// 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 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.
|
// Return the index of the first incremental relocation for symbol SYMNDX.
|
unsigned int
|
unsigned int
|
get_incremental_reloc_base(unsigned int symndx) const
|
get_incremental_reloc_base(unsigned int symndx) const
|
{ return this->do_get_incremental_reloc_base(symndx); }
|
{ return this->do_get_incremental_reloc_base(symndx); }
|
|
|
Line 890... |
Line 904... |
// *UNCOMPRESSED_SIZE to the size of the uncompressed data.
|
// *UNCOMPRESSED_SIZE to the size of the uncompressed data.
|
virtual bool
|
virtual bool
|
do_section_is_compressed(unsigned int, section_size_type*) const
|
do_section_is_compressed(unsigned int, section_size_type*) const
|
{ return false; }
|
{ 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->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--
|
// Return the index of the first incremental relocation for symbol SYMNDX--
|
// implemented by child class.
|
// implemented by child class.
|
virtual unsigned int
|
virtual unsigned int
|
do_get_incremental_reloc_base(unsigned int) const
|
do_get_incremental_reloc_base(unsigned int) const
|
{ gold_unreachable(); }
|
{ gold_unreachable(); }
|
Line 1007... |
Line 1042... |
// Scan the relocs and adjust the symbol table.
|
// Scan the relocs and adjust the symbol table.
|
void
|
void
|
scan_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd)
|
scan_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd)
|
{ return this->do_scan_relocs(symtab, layout, 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); }
|
|
|
// The number of local symbols in the input symbol table.
|
// The number of local symbols in the input symbol table.
|
virtual unsigned int
|
virtual unsigned int
|
local_symbol_count() const
|
local_symbol_count() const
|
{ return this->do_local_symbol_count(); }
|
{ return this->do_local_symbol_count(); }
|
|
|
Line 1165... |
Line 1233... |
|
|
// Scan the relocs--implemented by child class.
|
// Scan the relocs--implemented by child class.
|
virtual void
|
virtual void
|
do_scan_relocs(Symbol_table*, Layout*, Read_relocs_data*) = 0;
|
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 the number of local symbols--implemented by child class.
|
// Return the number of local symbols--implemented by child class.
|
virtual unsigned int
|
virtual unsigned int
|
do_local_symbol_count() const = 0;
|
do_local_symbol_count() const = 0;
|
|
|
// Return the number of output local symbols--implemented by child class.
|
// Return the number of output local symbols--implemented by child class.
|
Line 1718... |
Line 1808... |
|
|
private:
|
private:
|
std::vector<Symbol*> vec_;
|
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
|
// Abstract base class for a regular object file, either a real object file
|
// or an incremental (unchanged) object. This is size and endian specific.
|
// or an incremental (unchanged) object. This is size and endian specific.
|
|
|
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
Line 1773... |
Line 1868... |
{
|
{
|
gold_assert(shndx < this->section_offsets_.size());
|
gold_assert(shndx < this->section_offsets_.size());
|
return this->section_offsets_[shndx];
|
return this->section_offsets_[shndx];
|
}
|
}
|
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
// Iterate over local symbols, calling a visitor class V for each GOT offset
|
// Iterate over local symbols, calling a visitor class V for each GOT offset
|
// associated with a local symbol.
|
// associated with a local symbol.
|
void
|
void
|
do_for_all_local_got_entries(Got_offset_list::Visitor* v) const;
|
do_for_all_local_got_entries(Got_offset_list::Visitor* v) const;
|
|
|
Line 1853... |
Line 1907... |
(off == static_cast<uint64_t>(-1)
|
(off == static_cast<uint64_t>(-1)
|
? invalid_address
|
? invalid_address
|
: convert_types<Address, uint64_t>(off));
|
: 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);
|
|
}
|
|
}
|
|
|
private:
|
private:
|
// The GOT offsets of local symbols. This map also stores GOT offsets
|
// The GOT offsets of local symbols. This map also stores GOT offsets
|
// for tp-relative offsets for TLS symbols.
|
// for tp-relative offsets for TLS symbols.
|
typedef Unordered_map<unsigned int, Got_offset_list*> Local_got_offsets;
|
typedef Unordered_map<unsigned int, Got_offset_list*> Local_got_offsets;
|
|
|
Line 1998... |
Line 2095... |
|
|
// Return whether the local symbol SYMNDX has a PLT offset.
|
// Return whether the local symbol SYMNDX has a PLT offset.
|
bool
|
bool
|
local_has_plt_offset(unsigned int symndx) const;
|
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.
|
// Set the PLT offset of the local symbol SYMNDX.
|
void
|
void
|
set_local_plt_offset(unsigned int symndx, unsigned int plt_offset);
|
set_local_plt_offset(unsigned int symndx, unsigned int plt_offset);
|
|
|
// Return the name of the symbol that spans the given offset in the
|
// Return the name of the symbol that spans the given offset in the
|
Line 2048... |
Line 2140... |
|
|
// Read the symbols.
|
// Read the symbols.
|
void
|
void
|
do_read_symbols(Read_symbols_data*);
|
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 the number of local symbols.
|
// Return the number of local symbols.
|
unsigned int
|
unsigned int
|
do_local_symbol_count() const
|
do_local_symbol_count() const
|
{ return this->local_symbol_count_; }
|
{ return this->local_symbol_count_; }
|
|
|
Line 2252... |
Line 2357... |
Compressed_section_map::const_iterator p =
|
Compressed_section_map::const_iterator p =
|
this->compressed_sections_->find(shndx);
|
this->compressed_sections_->find(shndx);
|
if (p != this->compressed_sections_->end())
|
if (p != this->compressed_sections_->end())
|
{
|
{
|
if (uncompressed_size != NULL)
|
if (uncompressed_size != NULL)
|
*uncompressed_size = p->second;
|
*uncompressed_size = p->second.size;
|
return true;
|
return true;
|
}
|
}
|
return false;
|
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 uncompressed sections. This is done
|
|
// at the end of the Add_symbols task.
|
|
void
|
|
do_discard_decompressed_sections();
|
|
|
private:
|
private:
|
// For convenience.
|
// For convenience.
|
typedef Sized_relobj_file<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 ehdr_size = elfcpp::Elf_sizes<size>::ehdr_size;
|
static const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
|
static const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
|
Line 2542... |
Line 2660... |
unsigned int discarded_eh_frame_shndx_;
|
unsigned int discarded_eh_frame_shndx_;
|
// The list of sections whose layout was deferred.
|
// The list of sections whose layout was deferred.
|
std::vector<Deferred_layout> deferred_layout_;
|
std::vector<Deferred_layout> deferred_layout_;
|
// The list of relocation sections whose layout was deferred.
|
// The list of relocation sections whose layout was deferred.
|
std::vector<Deferred_layout> deferred_layout_relocs_;
|
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_;
|
Compressed_section_map* compressed_sections_;
|
};
|
};
|
|
|
// A class to manage the list of all objects.
|
// A class to manage the list of all objects.
|
|
|