mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-18 08:38:10 +08:00
Add support for local GOT offsets.
This commit is contained in:
@ -147,7 +147,8 @@ Sized_relobj<size, big_endian>::Sized_relobj(
|
|||||||
output_local_symbol_count_(0),
|
output_local_symbol_count_(0),
|
||||||
symbols_(NULL),
|
symbols_(NULL),
|
||||||
local_symbol_offset_(0),
|
local_symbol_offset_(0),
|
||||||
local_values_()
|
local_values_(),
|
||||||
|
local_got_offsets_()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,6 +663,17 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the value of the local symbol symndx.
|
||||||
|
template<int size, bool big_endian>
|
||||||
|
typename elfcpp::Elf_types<size>::Elf_Addr
|
||||||
|
Sized_relobj<size, big_endian>::local_symbol_value(unsigned int symndx) const
|
||||||
|
{
|
||||||
|
gold_assert(symndx < this->local_symbol_count_);
|
||||||
|
gold_assert(symndx < this->local_values_.size());
|
||||||
|
const Symbol_value<size>& lv(this->local_values_[symndx]);
|
||||||
|
return lv.value(this, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Return the value of a local symbol defined in input section SHNDX,
|
// Return the value of a local symbol defined in input section SHNDX,
|
||||||
// with value VALUE, adding addend ADDEND. IS_SECTION_SYMBOL
|
// with value VALUE, adding addend ADDEND. IS_SECTION_SYMBOL
|
||||||
// indicates whether the symbol is a section symbol. This handles
|
// indicates whether the symbol is a section symbol. This handles
|
||||||
|
@ -612,6 +612,54 @@ class Sized_relobj : public Relobj
|
|||||||
return this->local_values_[sym].output_symtab_index();
|
return this->local_values_[sym].output_symtab_index();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the appropriate Sized_target structure.
|
||||||
|
Sized_target<size, big_endian>*
|
||||||
|
sized_target()
|
||||||
|
{
|
||||||
|
return this->Object::sized_target
|
||||||
|
SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
|
||||||
|
SELECT_SIZE_ENDIAN_ONLY(size, big_endian));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 whether the local symbol SYMNDX has a GOT offset.
|
||||||
|
bool
|
||||||
|
local_has_got_offset(unsigned int symndx) const
|
||||||
|
{
|
||||||
|
return (this->local_got_offsets_.find(symndx)
|
||||||
|
!= this->local_got_offsets_.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the GOT offset of the local symbol SYMNDX.
|
||||||
|
unsigned int
|
||||||
|
local_got_offset(unsigned int symndx) const
|
||||||
|
{
|
||||||
|
Local_got_offsets::const_iterator p =
|
||||||
|
this->local_got_offsets_.find(symndx);
|
||||||
|
gold_assert(p != this->local_got_offsets_.end());
|
||||||
|
return p->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
// Read the symbols.
|
// Read the symbols.
|
||||||
void
|
void
|
||||||
do_read_symbols(Read_symbols_data*);
|
do_read_symbols(Read_symbols_data*);
|
||||||
@ -658,23 +706,6 @@ class Sized_relobj : public Relobj
|
|||||||
do_section_flags(unsigned int shndx)
|
do_section_flags(unsigned int shndx)
|
||||||
{ return this->elf_file_.section_flags(shndx); }
|
{ return this->elf_file_.section_flags(shndx); }
|
||||||
|
|
||||||
// Return the appropriate Sized_target structure.
|
|
||||||
Sized_target<size, big_endian>*
|
|
||||||
sized_target()
|
|
||||||
{
|
|
||||||
return this->Object::sized_target
|
|
||||||
SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
|
|
||||||
SELECT_SIZE_ENDIAN_ONLY(size, big_endian));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the value of a local symbol define 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;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// For convenience.
|
// For convenience.
|
||||||
typedef Sized_relobj<size, big_endian> This;
|
typedef Sized_relobj<size, big_endian> This;
|
||||||
@ -724,6 +755,9 @@ class Sized_relobj : public Relobj
|
|||||||
write_local_symbols(Output_file*,
|
write_local_symbols(Output_file*,
|
||||||
const Stringpool_template<char>*);
|
const Stringpool_template<char>*);
|
||||||
|
|
||||||
|
// The GOT offsets of local symbols.
|
||||||
|
typedef Unordered_map<unsigned int, unsigned int> Local_got_offsets;
|
||||||
|
|
||||||
// General access to the ELF file.
|
// General access to the ELF file.
|
||||||
elfcpp::Elf_file<size, big_endian, Object> elf_file_;
|
elfcpp::Elf_file<size, big_endian, Object> elf_file_;
|
||||||
// Index of SHT_SYMTAB section.
|
// Index of SHT_SYMTAB section.
|
||||||
@ -738,6 +772,8 @@ class Sized_relobj : public Relobj
|
|||||||
off_t local_symbol_offset_;
|
off_t local_symbol_offset_;
|
||||||
// Values of local symbols.
|
// Values of local symbols.
|
||||||
Local_values local_values_;
|
Local_values local_values_;
|
||||||
|
// GOT offsets for local symbols, indexed by symbol number.
|
||||||
|
Local_got_offsets local_got_offsets_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A class to manage the list of all objects.
|
// A class to manage the list of all objects.
|
||||||
|
@ -679,7 +679,8 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
gold_unreachable();
|
val = this->u_.object->local_symbol_value(this->local_sym_index_);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
elfcpp::Swap<size, big_endian>::writeval(pov, val);
|
elfcpp::Swap<size, big_endian>::writeval(pov, val);
|
||||||
@ -704,6 +705,24 @@ Output_data_got<size, big_endian>::add_global(Symbol* gsym)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add an entry for a local symbol to the GOT. This returns true if
|
||||||
|
// this is a new GOT entry, false if the symbol already has a GOT
|
||||||
|
// entry.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
|
bool
|
||||||
|
Output_data_got<size, big_endian>::add_local(
|
||||||
|
Sized_relobj<size, big_endian>* object,
|
||||||
|
unsigned int symndx)
|
||||||
|
{
|
||||||
|
if (object->local_has_got_offset(symndx))
|
||||||
|
return false;
|
||||||
|
this->entries_.push_back(Got_entry(object, symndx));
|
||||||
|
this->set_got_size();
|
||||||
|
object->set_local_got_offset(symndx, this->last_got_offset());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Write out the GOT.
|
// Write out the GOT.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
|
@ -909,15 +909,11 @@ class Output_data_got : public Output_section_data
|
|||||||
bool
|
bool
|
||||||
add_global(Symbol* gsym);
|
add_global(Symbol* gsym);
|
||||||
|
|
||||||
// Add an entry for a local symbol to the GOT. This returns the
|
// Add an entry for a local symbol to the GOT. This returns true if
|
||||||
// offset of the new entry from the start of the GOT.
|
// this is a new GOT entry, false if the symbol already has a GOT
|
||||||
unsigned int
|
// entry.
|
||||||
add_local(Object* object, unsigned int sym_index)
|
bool
|
||||||
{
|
add_local(Sized_relobj<size, big_endian>* object, unsigned int sym_index);
|
||||||
this->entries_.push_back(Got_entry(object, sym_index));
|
|
||||||
this->set_got_size();
|
|
||||||
return this->last_got_offset();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a constant to the GOT. This returns the offset of the new
|
// Add a constant to the GOT. This returns the offset of the new
|
||||||
// entry from the start of the GOT.
|
// entry from the start of the GOT.
|
||||||
@ -949,7 +945,8 @@ class Output_data_got : public Output_section_data
|
|||||||
{ this->u_.gsym = gsym; }
|
{ this->u_.gsym = gsym; }
|
||||||
|
|
||||||
// Create a local symbol entry.
|
// Create a local symbol entry.
|
||||||
Got_entry(Object* object, unsigned int local_sym_index)
|
Got_entry(Sized_relobj<size, big_endian>* object,
|
||||||
|
unsigned int local_sym_index)
|
||||||
: local_sym_index_(local_sym_index)
|
: local_sym_index_(local_sym_index)
|
||||||
{
|
{
|
||||||
gold_assert(local_sym_index != GSYM_CODE
|
gold_assert(local_sym_index != GSYM_CODE
|
||||||
@ -977,7 +974,7 @@ class Output_data_got : public Output_section_data
|
|||||||
union
|
union
|
||||||
{
|
{
|
||||||
// For a local symbol, the object.
|
// For a local symbol, the object.
|
||||||
Object* object;
|
Sized_relobj<size, big_endian>* object;
|
||||||
// For a global symbol, the symbol.
|
// For a global symbol, the symbol.
|
||||||
Symbol* gsym;
|
Symbol* gsym;
|
||||||
// For a constant, the constant.
|
// For a constant, the constant.
|
||||||
|
Reference in New Issue
Block a user