aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-10-08 07:22:21 +0000
committerIan Lance Taylor <iant@google.com>2007-10-08 07:22:21 +0000
commite727fa71af6a46ff76ace26a73f8e17bb26559ec (patch)
tree9a6ff8e24154289d84963f376e3255a8e57a14f2 /gold
parentaf6359d59d84cdd70fd1f400b91bc2fdcbed7dfa (diff)
downloadfsf-binutils-gdb-e727fa71af6a46ff76ace26a73f8e17bb26559ec.zip
fsf-binutils-gdb-e727fa71af6a46ff76ace26a73f8e17bb26559ec.tar.gz
fsf-binutils-gdb-e727fa71af6a46ff76ace26a73f8e17bb26559ec.tar.bz2
Add support for local GOT offsets.
Diffstat (limited to 'gold')
-rw-r--r--gold/object.cc14
-rw-r--r--gold/object.h70
-rw-r--r--gold/output.cc21
-rw-r--r--gold/output.h19
4 files changed, 94 insertions, 30 deletions
diff --git a/gold/object.cc b/gold/object.cc
index 9986383..cfdb17c 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -147,7 +147,8 @@ Sized_relobj<size, big_endian>::Sized_relobj(
output_local_symbol_count_(0),
symbols_(NULL),
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 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,
// with value VALUE, adding addend ADDEND. IS_SECTION_SYMBOL
// indicates whether the symbol is a section symbol. This handles
diff --git a/gold/object.h b/gold/object.h
index e4359ac..2baf2da 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -612,6 +612,54 @@ class Sized_relobj : public Relobj
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.
void
do_read_symbols(Read_symbols_data*);
@@ -658,23 +706,6 @@ class Sized_relobj : public Relobj
do_section_flags(unsigned int 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:
// For convenience.
typedef Sized_relobj<size, big_endian> This;
@@ -724,6 +755,9 @@ class Sized_relobj : public Relobj
write_local_symbols(Output_file*,
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.
elfcpp::Elf_file<size, big_endian, Object> elf_file_;
// Index of SHT_SYMTAB section.
@@ -738,6 +772,8 @@ class Sized_relobj : public Relobj
off_t local_symbol_offset_;
// Values of local symbols.
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.
diff --git a/gold/output.cc b/gold/output.cc
index 34fdc67..f217b03 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -679,7 +679,8 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
break;
default:
- gold_unreachable();
+ val = this->u_.object->local_symbol_value(this->local_sym_index_);
+ break;
}
elfcpp::Swap<size, big_endian>::writeval(pov, val);
@@ -704,6 +705,24 @@ Output_data_got<size, big_endian>::add_global(Symbol* gsym)
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.
template<int size, bool big_endian>
diff --git a/gold/output.h b/gold/output.h
index 7f783d6..997a821 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -909,15 +909,11 @@ class Output_data_got : public Output_section_data
bool
add_global(Symbol* gsym);
- // Add an entry for a local symbol to the GOT. This returns the
- // offset of the new entry from the start of the GOT.
- unsigned int
- add_local(Object* object, unsigned int sym_index)
- {
- this->entries_.push_back(Got_entry(object, sym_index));
- this->set_got_size();
- return this->last_got_offset();
- }
+ // 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.
+ bool
+ add_local(Sized_relobj<size, big_endian>* object, unsigned int sym_index);
// Add a constant to the GOT. This returns the offset of the new
// entry from the start of the GOT.
@@ -949,7 +945,8 @@ class Output_data_got : public Output_section_data
{ this->u_.gsym = gsym; }
// 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)
{
gold_assert(local_sym_index != GSYM_CODE
@@ -977,7 +974,7 @@ class Output_data_got : public Output_section_data
union
{
// For a local symbol, the object.
- Object* object;
+ Sized_relobj<size, big_endian>* object;
// For a global symbol, the symbol.
Symbol* gsym;
// For a constant, the constant.