summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@google.com>2008-03-25 18:37:16 +0000
committerCary Coutant <ccoutant@google.com>2008-03-25 18:37:16 +0000
commit0a65a3a7402d9b8523844366c638a0354f48dfa4 (patch)
tree38d2a9a2cbf1277091cd8de1f92c3e6871156407
parent403fe1979f7a9e128d3904731e709fadbf60ea81 (diff)
downloadppe42-binutils-0a65a3a7402d9b8523844366c638a0354f48dfa4.tar.gz
ppe42-binutils-0a65a3a7402d9b8523844366c638a0354f48dfa4.zip
* i386.cc (Target_i386::Got_type): New enum declaration.
(Target_i386::Scan::local): Updated callers of Output_data_got member functions. (Target_i386::Scan::global): Likewise. (Target_i386::Relocate::relocate): Likewise. (Target_i386::Relocate::relocate_tls): Likewise. * object.h (Got_offset_list): New class. (Sized_relobj::local_has_got_offset): Added got_type parameter. (Sized_relobj::local_got_offset): Likewise. (Sized_relobj::set_local_got_offset): Likewise. (Sized_relobj::local_has_tls_got_offset): Removed. (Sized_relobj::local_tls_got_offset): Removed. (Sized_relobj::set_local_tls_got_offset): Removed. (Sized_relobj::Local_got_offsets): Changed to store a list of offsets. * output.cc (Output_data_got::add_global): Added got_type parameter. (Output_data_got::add_global_with_rel): Likewise. (Output_data_got::add_global_with_rela): Likewise. (Output_data_got::add_global_pair_with_rel): New function. (Output_data_got::add_global_pair_with_rela): New function. (Output_data_got::add_local): Added got_type parameter. (Output_data_got::add_local_with_rel): Likewise. (Output_data_got::add_local_with_rela): Likewise. (Output_data_got::add_local_pair_with_rel): New function. (Output_data_got::add_local_pair_with_rela): New function. (Output_data_got::add_global_tls): Removed. (Output_data_got::add_global_tls_with_rel): Removed. (Output_data_got::add_global_tls_with_rela): Removed. (Output_data_got::add_local_tls): Removed. (Output_data_got::add_local_tls_with_rel): Removed. (Output_data_got::add_local_tls_with_rela): Removed. * output.h (Output_data_got::add_global): Added got_type parameter. (Output_data_got::add_global_with_rel): Likewise. (Output_data_got::add_global_with_rela): Likewise. (Output_data_got::add_global_pair_with_rel): New function. (Output_data_got::add_global_pair_with_rela): New function. (Output_data_got::add_local): Added got_type parameter. (Output_data_got::add_local_with_rel): Likewise. (Output_data_got::add_local_with_rela): Likewise. (Output_data_got::add_local_pair_with_rel): New function. (Output_data_got::add_local_pair_with_rela): New function. (Output_data_got::add_global_tls): Removed. (Output_data_got::add_global_tls_with_rel): Removed. (Output_data_got::add_global_tls_with_rela): Removed. (Output_data_got::add_local_tls): Removed. (Output_data_got::add_local_tls_with_rel): Removed. (Output_data_got::add_local_tls_with_rela): Removed. * resolve.cc (Symbol::override_base_with_special): Removed reference to has_got_offset_ field. * symtab.cc (Symbol::init_fields): Replaced initialization of got_offset_ with got_offsets_. Removed initialization of has_got_offset_ *symtab.h (Symbol::has_got_offset): Aded got_type parameter. (Symbol::got_offset): Likewise. (Symbol::set_got_offset): Likewise. (Symbol::has_tls_got_offset): Removed. (Symbol::tls_got_offset): Removed. (Symbol::set_tls_got_offset): Removed. (Symbol::got_offset_): Removed. (Symbol::tls_mod_got_offset_): Removed. (Symbol::tls_pair_got_offset_): Removed. (Symbol::got_offsets_): New field. (Symbol::has_got_offset): Removed. (Symbol::has_tls_mod_got_offset): Removed. (Symbol::has_tls_pair_got_offset): Removed. * x86_64.cc (Target_x86_64::Got_type): New enum declaration. (Target_x86_64::Scan::local): Updated callers of Output_data_got member functions. (Target_x86_64::Scan::global): Likewise. (Target_x86_64::Relocate::relocate): Likewise. (Target_x86_64::Relocate::relocate_tls): Likewise.
-rw-r--r--gold/ChangeLog73
-rw-r--r--gold/i386.cc78
-rw-r--r--gold/object.h163
-rw-r--r--gold/output.cc265
-rw-r--r--gold/output.h91
-rw-r--r--gold/resolve.cc1
-rw-r--r--gold/symtab.cc3
-rw-r--r--gold/symtab.h73
-rw-r--r--gold/x86_64.cc87
9 files changed, 418 insertions, 416 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 447712aabb..104646fe1a 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,76 @@
+2008-03-24 Cary Coutant <ccoutant@google.com>
+
+ * i386.cc (Target_i386::Got_type): New enum declaration.
+ (Target_i386::Scan::local): Updated callers of Output_data_got
+ member functions.
+ (Target_i386::Scan::global): Likewise.
+ (Target_i386::Relocate::relocate): Likewise.
+ (Target_i386::Relocate::relocate_tls): Likewise.
+ * object.h (Got_offset_list): New class.
+ (Sized_relobj::local_has_got_offset): Added got_type parameter.
+ (Sized_relobj::local_got_offset): Likewise.
+ (Sized_relobj::set_local_got_offset): Likewise.
+ (Sized_relobj::local_has_tls_got_offset): Removed.
+ (Sized_relobj::local_tls_got_offset): Removed.
+ (Sized_relobj::set_local_tls_got_offset): Removed.
+ (Sized_relobj::Local_got_offsets): Changed to store a list of offsets.
+ * output.cc (Output_data_got::add_global): Added got_type parameter.
+ (Output_data_got::add_global_with_rel): Likewise.
+ (Output_data_got::add_global_with_rela): Likewise.
+ (Output_data_got::add_global_pair_with_rel): New function.
+ (Output_data_got::add_global_pair_with_rela): New function.
+ (Output_data_got::add_local): Added got_type parameter.
+ (Output_data_got::add_local_with_rel): Likewise.
+ (Output_data_got::add_local_with_rela): Likewise.
+ (Output_data_got::add_local_pair_with_rel): New function.
+ (Output_data_got::add_local_pair_with_rela): New function.
+ (Output_data_got::add_global_tls): Removed.
+ (Output_data_got::add_global_tls_with_rel): Removed.
+ (Output_data_got::add_global_tls_with_rela): Removed.
+ (Output_data_got::add_local_tls): Removed.
+ (Output_data_got::add_local_tls_with_rel): Removed.
+ (Output_data_got::add_local_tls_with_rela): Removed.
+ * output.h (Output_data_got::add_global): Added got_type parameter.
+ (Output_data_got::add_global_with_rel): Likewise.
+ (Output_data_got::add_global_with_rela): Likewise.
+ (Output_data_got::add_global_pair_with_rel): New function.
+ (Output_data_got::add_global_pair_with_rela): New function.
+ (Output_data_got::add_local): Added got_type parameter.
+ (Output_data_got::add_local_with_rel): Likewise.
+ (Output_data_got::add_local_with_rela): Likewise.
+ (Output_data_got::add_local_pair_with_rel): New function.
+ (Output_data_got::add_local_pair_with_rela): New function.
+ (Output_data_got::add_global_tls): Removed.
+ (Output_data_got::add_global_tls_with_rel): Removed.
+ (Output_data_got::add_global_tls_with_rela): Removed.
+ (Output_data_got::add_local_tls): Removed.
+ (Output_data_got::add_local_tls_with_rel): Removed.
+ (Output_data_got::add_local_tls_with_rela): Removed.
+ * resolve.cc (Symbol::override_base_with_special): Removed
+ reference to has_got_offset_ field.
+ * symtab.cc (Symbol::init_fields): Replaced initialization
+ of got_offset_ with got_offsets_. Removed initialization
+ of has_got_offset_
+ *symtab.h (Symbol::has_got_offset): Aded got_type parameter.
+ (Symbol::got_offset): Likewise.
+ (Symbol::set_got_offset): Likewise.
+ (Symbol::has_tls_got_offset): Removed.
+ (Symbol::tls_got_offset): Removed.
+ (Symbol::set_tls_got_offset): Removed.
+ (Symbol::got_offset_): Removed.
+ (Symbol::tls_mod_got_offset_): Removed.
+ (Symbol::tls_pair_got_offset_): Removed.
+ (Symbol::got_offsets_): New field.
+ (Symbol::has_got_offset): Removed.
+ (Symbol::has_tls_mod_got_offset): Removed.
+ (Symbol::has_tls_pair_got_offset): Removed.
+ * x86_64.cc (Target_x86_64::Got_type): New enum declaration.
+ (Target_x86_64::Scan::local): Updated callers of Output_data_got
+ member functions.
+ (Target_x86_64::Scan::global): Likewise.
+ (Target_x86_64::Relocate::relocate): Likewise.
+ (Target_x86_64::Relocate::relocate_tls): Likewise.
+
2008-03-25 Ben Elliston <bje@au.ibm.com>
* yyscript.y: Fix spelling error in comment.
diff --git a/gold/i386.cc b/gold/i386.cc
index cc55249e9c..f12b6cdebf 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -339,6 +339,15 @@ class Target_i386 : public Sized_target<32, false>
// general Target structure.
static const Target::Target_info i386_info;
+ // The types of GOT entries needed for this platform.
+ enum Got_type
+ {
+ GOT_TYPE_STANDARD = 0, // GOT entry for a regular symbol
+ GOT_TYPE_TLS_OFFSET = 1, // GOT entry for TLS offset
+ GOT_TYPE_TLS_PAIR = 2, // GOT entry for TLS module/offset pair
+ GOT_TYPE_TLS_DESC = 3 // GOT entry for TLS_DESC pair
+ };
+
// The GOT section.
Output_data_got<32, false>* got_;
// The PLT section.
@@ -933,7 +942,7 @@ Target_i386::Scan::local(const General_options&,
// The symbol requires a GOT entry.
Output_data_got<32, false>* got = target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
- if (got->add_local(object, r_sym))
+ if (got->add_local(object, r_sym, GOT_TYPE_STANDARD))
{
// If we are generating a shared object, we need to add a
// dynamic RELATIVE relocation for this symbol's GOT entry.
@@ -941,10 +950,9 @@ Target_i386::Scan::local(const General_options&,
{
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
- rel_dyn->add_local_relative(object, r_sym,
- elfcpp::R_386_RELATIVE,
- got,
- object->local_got_offset(r_sym));
+ rel_dyn->add_local_relative(
+ object, r_sym, elfcpp::R_386_RELATIVE, got,
+ object->local_got_offset(r_sym, GOT_TYPE_STANDARD));
}
}
}
@@ -991,10 +999,11 @@ Target_i386::Scan::local(const General_options&,
Output_data_got<32, false>* got
= target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
- got->add_local_tls_with_rel(object, r_sym,
- lsym.get_st_shndx(), true,
- target->rel_dyn_section(layout),
- elfcpp::R_386_TLS_DTPMOD32);
+ got->add_local_pair_with_rel(object, r_sym,
+ lsym.get_st_shndx(),
+ GOT_TYPE_TLS_PAIR,
+ target->rel_dyn_section(layout),
+ elfcpp::R_386_TLS_DTPMOD32, 0);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_local(object, r_type);
@@ -1047,7 +1056,7 @@ Target_i386::Scan::local(const General_options&,
unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32
? elfcpp::R_386_TLS_TPOFF32
: elfcpp::R_386_TLS_TPOFF);
- got->add_local_with_rel(object, r_sym,
+ got->add_local_with_rel(object, r_sym, GOT_TYPE_TLS_OFFSET,
target->rel_dyn_section(layout),
dyn_r_type);
}
@@ -1210,7 +1219,7 @@ Target_i386::Scan::global(const General_options& options,
// The symbol requires a GOT entry.
Output_data_got<32, false>* got = target->got_section(symtab, layout);
if (gsym->final_value_is_known())
- got->add_global(gsym);
+ got->add_global(gsym, GOT_TYPE_STANDARD);
else
{
// If this symbol is not fully resolved, we need to add a
@@ -1219,12 +1228,14 @@ Target_i386::Scan::global(const General_options& options,
if (gsym->is_from_dynobj()
|| gsym->is_undefined()
|| gsym->is_preemptible())
- got->add_global_with_rel(gsym, rel_dyn, elfcpp::R_386_GLOB_DAT);
+ got->add_global_with_rel(gsym, GOT_TYPE_STANDARD,
+ rel_dyn, elfcpp::R_386_GLOB_DAT);
else
{
- if (got->add_global(gsym))
- rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
- got, gsym->got_offset());
+ if (got->add_global(gsym, GOT_TYPE_STANDARD))
+ rel_dyn->add_global_relative(
+ gsym, elfcpp::R_386_RELATIVE, got,
+ gsym->got_offset(GOT_TYPE_STANDARD));
}
}
}
@@ -1291,7 +1302,7 @@ Target_i386::Scan::global(const General_options& options,
// dtv-relative offset.
Output_data_got<32, false>* got
= target->got_section(symtab, layout);
- got->add_global_tls_with_rel(gsym,
+ got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
target->rel_dyn_section(layout),
elfcpp::R_386_TLS_DTPMOD32,
elfcpp::R_386_TLS_DTPOFF32);
@@ -1301,7 +1312,8 @@ Target_i386::Scan::global(const General_options& options,
// Create a GOT entry for the tp-relative offset.
Output_data_got<32, false>* got
= target->got_section(symtab, layout);
- got->add_global_with_rel(gsym, target->rel_dyn_section(layout),
+ got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
+ target->rel_dyn_section(layout),
elfcpp::R_386_TLS_TPOFF32);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
@@ -1353,7 +1365,7 @@ Target_i386::Scan::global(const General_options& options,
unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32
? elfcpp::R_386_TLS_TPOFF32
: elfcpp::R_386_TLS_TPOFF);
- got->add_global_with_rel(gsym,
+ got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
target->rel_dyn_section(layout),
dyn_r_type);
}
@@ -1576,14 +1588,16 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
case elfcpp::R_386_GOT32:
if (gsym != NULL)
{
- gold_assert(gsym->has_got_offset());
- got_offset = gsym->got_offset() - target->got_size();
+ gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+ got_offset = (gsym->got_offset(GOT_TYPE_STANDARD)
+ - target->got_size());
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym));
- got_offset = object->local_got_offset(r_sym) - target->got_size();
+ gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+ got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
+ - target->got_size());
}
have_got_offset = true;
break;
@@ -1770,14 +1784,16 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
unsigned int got_offset;
if (gsym != NULL)
{
- gold_assert(gsym->has_tls_got_offset(true));
- got_offset = gsym->tls_got_offset(true) - target->got_size();
+ gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_PAIR));
+ got_offset = (gsym->got_offset(GOT_TYPE_TLS_PAIR)
+ - target->got_size());
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
- gold_assert(object->local_has_tls_got_offset(r_sym, true));
- got_offset = (object->local_tls_got_offset(r_sym, true)
+ gold_assert(object->local_has_got_offset(r_sym,
+ GOT_TYPE_TLS_PAIR));
+ got_offset = (object->local_got_offset(r_sym, GOT_TYPE_TLS_PAIR)
- target->got_size());
}
if (optimized_type == tls::TLSOPT_TO_IE)
@@ -1868,14 +1884,16 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
unsigned int got_offset;
if (gsym != NULL)
{
- gold_assert(gsym->has_got_offset());
- got_offset = gsym->got_offset();
+ gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_OFFSET));
+ got_offset = gsym->got_offset(GOT_TYPE_TLS_OFFSET);
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym));
- got_offset = object->local_got_offset(r_sym);
+ gold_assert(object->local_has_got_offset(r_sym,
+ GOT_TYPE_TLS_OFFSET));
+ got_offset = object->local_got_offset(r_sym,
+ GOT_TYPE_TLS_OFFSET);
}
// For the R_386_TLS_IE relocation, we need to apply the
// absolute address of the GOT entry.
diff --git a/gold/object.h b/gold/object.h
index 3a74685943..4a2ad8a367 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -976,6 +976,83 @@ class 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.
template<int size, bool big_endian>
@@ -1067,84 +1144,40 @@ class Sized_relobj : public Relobj
// 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
+ set_local_got_offset(unsigned int symndx, unsigned int got_type,
+ unsigned int got_offset)
{
- 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)
- {
- 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);
}
}
@@ -1365,12 +1398,11 @@ class Sized_relobj : public Relobj
{
this->local_values_.clear();
this->local_got_offsets_.clear();
- this->local_tls_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
@@ -1409,9 +1441,6 @@ class Sized_relobj : public Relobj
// 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_;
};
diff --git a/gold/output.cc b/gold/output.cc
index 85cc2b257b..3a11aa48e8 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -1059,14 +1059,16 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
template<int size, bool big_endian>
bool
-Output_data_got<size, big_endian>::add_global(Symbol* gsym)
+Output_data_got<size, big_endian>::add_global(
+ Symbol* gsym,
+ unsigned int got_type)
{
- if (gsym->has_got_offset())
+ if (gsym->has_got_offset(got_type))
return false;
this->entries_.push_back(Got_entry(gsym));
this->set_got_size();
- gsym->set_got_offset(this->last_got_offset());
+ gsym->set_got_offset(got_type, this->last_got_offset());
return true;
}
@@ -1076,16 +1078,17 @@ template<int size, bool big_endian>
void
Output_data_got<size, big_endian>::add_global_with_rel(
Symbol* gsym,
+ unsigned int got_type,
Rel_dyn* rel_dyn,
unsigned int r_type)
{
- if (gsym->has_got_offset())
+ if (gsym->has_got_offset(got_type))
return;
this->entries_.push_back(Got_entry());
this->set_got_size();
unsigned int got_offset = this->last_got_offset();
- gsym->set_got_offset(got_offset);
+ gsym->set_got_offset(got_type, got_offset);
rel_dyn->add_global(gsym, r_type, this, got_offset);
}
@@ -1093,260 +1096,198 @@ template<int size, bool big_endian>
void
Output_data_got<size, big_endian>::add_global_with_rela(
Symbol* gsym,
+ unsigned int got_type,
Rela_dyn* rela_dyn,
unsigned int r_type)
{
- if (gsym->has_got_offset())
+ if (gsym->has_got_offset(got_type))
return;
this->entries_.push_back(Got_entry());
this->set_got_size();
unsigned int got_offset = this->last_got_offset();
- gsym->set_got_offset(got_offset);
+ gsym->set_got_offset(got_type, got_offset);
rela_dyn->add_global(gsym, r_type, this, got_offset, 0);
}
-// 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;
-}
-
-// Add an entry for a local symbol to the GOT, and add a dynamic
-// relocation of type R_TYPE for the GOT entry.
+// Add a pair of entries for a global symbol to the GOT, and add
+// dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively.
+// If R_TYPE_2 == 0, add the second entry with no relocation.
template<int size, bool big_endian>
void
-Output_data_got<size, big_endian>::add_local_with_rel(
- Sized_relobj<size, big_endian>* object,
- unsigned int symndx,
+Output_data_got<size, big_endian>::add_global_pair_with_rel(
+ Symbol* gsym,
+ unsigned int got_type,
Rel_dyn* rel_dyn,
- unsigned int r_type)
+ unsigned int r_type_1,
+ unsigned int r_type_2)
{
- if (object->local_has_got_offset(symndx))
+ if (gsym->has_got_offset(got_type))
return;
this->entries_.push_back(Got_entry());
- this->set_got_size();
unsigned int got_offset = this->last_got_offset();
- object->set_local_got_offset(symndx, got_offset);
- rel_dyn->add_local(object, symndx, r_type, this, got_offset);
+ gsym->set_got_offset(got_type, got_offset);
+ rel_dyn->add_global(gsym, r_type_1, this, got_offset);
+
+ this->entries_.push_back(Got_entry());
+ if (r_type_2 != 0)
+ {
+ got_offset = this->last_got_offset();
+ rel_dyn->add_global(gsym, r_type_2, this, got_offset);
+ }
+
+ this->set_got_size();
}
template<int size, bool big_endian>
void
-Output_data_got<size, big_endian>::add_local_with_rela(
- Sized_relobj<size, big_endian>* object,
- unsigned int symndx,
+Output_data_got<size, big_endian>::add_global_pair_with_rela(
+ Symbol* gsym,
+ unsigned int got_type,
Rela_dyn* rela_dyn,
- unsigned int r_type)
+ unsigned int r_type_1,
+ unsigned int r_type_2)
{
- if (object->local_has_got_offset(symndx))
+ if (gsym->has_got_offset(got_type))
return;
this->entries_.push_back(Got_entry());
- this->set_got_size();
unsigned int got_offset = this->last_got_offset();
- object->set_local_got_offset(symndx, got_offset);
- rela_dyn->add_local(object, symndx, r_type, this, got_offset, 0);
+ gsym->set_got_offset(got_type, got_offset);
+ rela_dyn->add_global(gsym, r_type_1, this, got_offset, 0);
+
+ this->entries_.push_back(Got_entry());
+ if (r_type_2 != 0)
+ {
+ got_offset = this->last_got_offset();
+ rela_dyn->add_global(gsym, r_type_2, this, got_offset, 0);
+ }
+
+ this->set_got_size();
}
-// Add an entry (or a pair of entries) for a global TLS symbol to the GOT.
-// In a pair of entries, the first value in the pair will be used for the
-// module index, and the second value will be used for the dtv-relative
-// offset. This returns true if this is a new GOT entry, false if the symbol
-// already has a GOT entry.
+// 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_global_tls(Symbol* gsym, bool need_pair)
+Output_data_got<size, big_endian>::add_local(
+ Sized_relobj<size, big_endian>* object,
+ unsigned int symndx,
+ unsigned int got_type)
{
- if (gsym->has_tls_got_offset(need_pair))
+ if (object->local_has_got_offset(symndx, got_type))
return false;
- this->entries_.push_back(Got_entry(gsym));
- gsym->set_tls_got_offset(this->last_got_offset(), need_pair);
- if (need_pair)
- this->entries_.push_back(Got_entry(gsym));
+ this->entries_.push_back(Got_entry(object, symndx));
this->set_got_size();
+ object->set_local_got_offset(symndx, got_type, this->last_got_offset());
return true;
}
-// Add an entry for a global TLS symbol to the GOT, and add a dynamic
-// relocation of type R_TYPE.
+// Add an entry for a local symbol to the GOT, and add a dynamic
+// relocation of type R_TYPE for the GOT entry.
template<int size, bool big_endian>
void
-Output_data_got<size, big_endian>::add_global_tls_with_rel(
- Symbol* gsym,
+Output_data_got<size, big_endian>::add_local_with_rel(
+ Sized_relobj<size, big_endian>* object,
+ unsigned int symndx,
+ unsigned int got_type,
Rel_dyn* rel_dyn,
unsigned int r_type)
{
- if (gsym->has_tls_got_offset(false))
+ if (object->local_has_got_offset(symndx, got_type))
return;
this->entries_.push_back(Got_entry());
this->set_got_size();
unsigned int got_offset = this->last_got_offset();
- gsym->set_tls_got_offset(got_offset, false);
- rel_dyn->add_global(gsym, r_type, this, got_offset);
+ object->set_local_got_offset(symndx, got_type, got_offset);
+ rel_dyn->add_local(object, symndx, r_type, this, got_offset);
}
template<int size, bool big_endian>
void
-Output_data_got<size, big_endian>::add_global_tls_with_rela(
- Symbol* gsym,
+Output_data_got<size, big_endian>::add_local_with_rela(
+ Sized_relobj<size, big_endian>* object,
+ unsigned int symndx,
+ unsigned int got_type,
Rela_dyn* rela_dyn,
unsigned int r_type)
{
- if (gsym->has_tls_got_offset(false))
+ if (object->local_has_got_offset(symndx, got_type))
return;
this->entries_.push_back(Got_entry());
this->set_got_size();
unsigned int got_offset = this->last_got_offset();
- gsym->set_tls_got_offset(got_offset, false);
- rela_dyn->add_global(gsym, r_type, this, got_offset, 0);
-}
-
-// Add a pair of entries for a global TLS symbol to the GOT, and add
-// dynamic relocations of type MOD_R_TYPE and DTV_R_TYPE, respectively.
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_global_tls_with_rel(
- Symbol* gsym,
- Rel_dyn* rel_dyn,
- unsigned int mod_r_type,
- unsigned int dtv_r_type)
-{
- if (gsym->has_tls_got_offset(true))
- return;
-
- this->entries_.push_back(Got_entry());
- unsigned int got_offset = this->last_got_offset();
- gsym->set_tls_got_offset(got_offset, true);
- rel_dyn->add_global(gsym, mod_r_type, this, got_offset);
-
- this->entries_.push_back(Got_entry());
- this->set_got_size();
- got_offset = this->last_got_offset();
- rel_dyn->add_global(gsym, dtv_r_type, this, got_offset);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_global_tls_with_rela(
- Symbol* gsym,
- Rela_dyn* rela_dyn,
- unsigned int mod_r_type,
- unsigned int dtv_r_type)
-{
- if (gsym->has_tls_got_offset(true))
- return;
-
- this->entries_.push_back(Got_entry());
- unsigned int got_offset = this->last_got_offset();
- gsym->set_tls_got_offset(got_offset, true);
- rela_dyn->add_global(gsym, mod_r_type, this, got_offset, 0);
-
- this->entries_.push_back(Got_entry());
- this->set_got_size();
- got_offset = this->last_got_offset();
- rela_dyn->add_global(gsym, dtv_r_type, this, got_offset, 0);
-}
-
-// Add an entry (or a pair of entries) for a local TLS symbol to the GOT.
-// In a pair of entries, the first value in the pair will be used for the
-// module index, and the second value will be used for the dtv-relative
-// offset. 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_tls(
- Sized_relobj<size, big_endian>* object,
- unsigned int symndx,
- bool need_pair)
-{
- if (object->local_has_tls_got_offset(symndx, need_pair))
- return false;
-
- this->entries_.push_back(Got_entry(object, symndx));
- object->set_local_tls_got_offset(symndx, this->last_got_offset(), need_pair);
- if (need_pair)
- this->entries_.push_back(Got_entry(object, symndx));
- this->set_got_size();
- return true;
+ object->set_local_got_offset(symndx, got_type, got_offset);
+ rela_dyn->add_local(object, symndx, r_type, this, got_offset, 0);
}
-// Add an entry (or pair of entries) for a local TLS symbol to the GOT,
-// and add a dynamic relocation of type R_TYPE for the first GOT entry.
-// Because this is a local symbol, the first GOT entry can be relocated
-// relative to a section symbol, and the second GOT entry will have an
-// dtv-relative value that can be computed at link time.
+// Add a pair of entries for a local symbol to the GOT, and add
+// dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively.
+// If R_TYPE_2 == 0, add the second entry with no relocation.
template<int size, bool big_endian>
void
-Output_data_got<size, big_endian>::add_local_tls_with_rel(
+Output_data_got<size, big_endian>::add_local_pair_with_rel(
Sized_relobj<size, big_endian>* object,
unsigned int symndx,
unsigned int shndx,
- bool need_pair,
+ unsigned int got_type,
Rel_dyn* rel_dyn,
- unsigned int r_type)
+ unsigned int r_type_1,
+ unsigned int r_type_2)
{
- if (object->local_has_tls_got_offset(symndx, need_pair))
+ if (object->local_has_got_offset(symndx, got_type))
return;
this->entries_.push_back(Got_entry());
unsigned int got_offset = this->last_got_offset();
- object->set_local_tls_got_offset(symndx, got_offset, need_pair);
+ object->set_local_got_offset(symndx, got_type, got_offset);
section_offset_type off;
Output_section* os = object->output_section(shndx, &off);
- rel_dyn->add_output_section(os, r_type, this, got_offset);
+ rel_dyn->add_output_section(os, r_type_1, this, got_offset);
- // The second entry of the pair will be statically initialized
- // with the TLS offset of the symbol.
- if (need_pair)
- this->entries_.push_back(Got_entry(object, symndx));
+ this->entries_.push_back(Got_entry(object, symndx));
+ if (r_type_2 != 0)
+ {
+ got_offset = this->last_got_offset();
+ rel_dyn->add_output_section(os, r_type_2, this, got_offset);
+ }
this->set_got_size();
}
template<int size, bool big_endian>
void
-Output_data_got<size, big_endian>::add_local_tls_with_rela(
+Output_data_got<size, big_endian>::add_local_pair_with_rela(
Sized_relobj<size, big_endian>* object,
unsigned int symndx,
unsigned int shndx,
- bool need_pair,
+ unsigned int got_type,
Rela_dyn* rela_dyn,
- unsigned int r_type)
+ unsigned int r_type_1,
+ unsigned int r_type_2)
{
- if (object->local_has_tls_got_offset(symndx, need_pair))
+ if (object->local_has_got_offset(symndx, got_type))
return;
this->entries_.push_back(Got_entry());
unsigned int got_offset = this->last_got_offset();
- object->set_local_tls_got_offset(symndx, got_offset, need_pair);
+ object->set_local_got_offset(symndx, got_type, got_offset);
section_offset_type off;
Output_section* os = object->output_section(shndx, &off);
- rela_dyn->add_output_section(os, r_type, this, got_offset, 0);
+ rela_dyn->add_output_section(os, r_type_1, this, got_offset, 0);
- // The second entry of the pair will be statically initialized
- // with the TLS offset of the symbol.
- if (need_pair)
- this->entries_.push_back(Got_entry(object, symndx));
+ this->entries_.push_back(Got_entry(object, symndx));
+ if (r_type_2 != 0)
+ {
+ got_offset = this->last_got_offset();
+ rela_dyn->add_output_section(os, r_type_2, this, got_offset, 0);
+ }
this->set_got_size();
}
diff --git a/gold/output.h b/gold/output.h
index e3945381c2..2b864f3756 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -1362,85 +1362,62 @@ class Output_data_got : public Output_section_data_build
// Add an entry for a global symbol to the GOT. Return true if this
// is a new GOT entry, false if the symbol was already in the GOT.
bool
- add_global(Symbol* gsym);
+ add_global(Symbol* gsym, unsigned int got_type);
// Add an entry for a global symbol to the GOT, and add a dynamic
// relocation of type R_TYPE for the GOT entry.
void
- add_global_with_rel(Symbol* gsym, Rel_dyn* rel_dyn, unsigned int r_type);
+ add_global_with_rel(Symbol* gsym, unsigned int got_type,
+ Rel_dyn* rel_dyn, unsigned int r_type);
void
- add_global_with_rela(Symbol* gsym, Rela_dyn* rela_dyn, unsigned int r_type);
+ add_global_with_rela(Symbol* gsym, unsigned int got_type,
+ Rela_dyn* rela_dyn, unsigned int r_type);
+
+ // Add a pair of entries for a global symbol to the GOT, and add
+ // dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively.
+ void
+ add_global_pair_with_rel(Symbol* gsym, unsigned int got_type,
+ Rel_dyn* rel_dyn, unsigned int r_type_1,
+ unsigned int r_type_2);
+
+ void
+ add_global_pair_with_rela(Symbol* gsym, unsigned int got_type,
+ Rela_dyn* rela_dyn, unsigned int r_type_1,
+ unsigned int r_type_2);
// 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_local(Sized_relobj<size, big_endian>* object, unsigned int sym_index,
+ unsigned int got_type);
- // Add an entry for a global symbol to the GOT, and add a dynamic
+ // Add an entry for a local symbol to the GOT, and add a dynamic
// relocation of type R_TYPE for the GOT entry.
void
add_local_with_rel(Sized_relobj<size, big_endian>* object,
- unsigned int sym_index, Rel_dyn* rel_dyn,
- unsigned int r_type);
+ unsigned int sym_index, unsigned int got_type,
+ Rel_dyn* rel_dyn, unsigned int r_type);
void
add_local_with_rela(Sized_relobj<size, big_endian>* object,
- unsigned int sym_index, Rela_dyn* rela_dyn,
- unsigned int r_type);
-
- // Add an entry (or pair of entries) for a global TLS symbol to the GOT.
- // Return true if this is a new GOT entry, false if the symbol was
- // already in the GOT.
- bool
- add_global_tls(Symbol* gsym, bool need_pair);
-
- // Add an entry for a global TLS symbol to the GOT, and add a dynamic
- // relocation of type R_TYPE.
- void
- add_global_tls_with_rel(Symbol* gsym, Rel_dyn* rel_dyn,
- unsigned int r_type);
-
- void
- add_global_tls_with_rela(Symbol* gsym, Rela_dyn* rela_dyn,
- unsigned int r_type);
-
- // Add a pair of entries for a global TLS symbol to the GOT, and add
- // dynamic relocations of type MOD_R_TYPE and DTV_R_TYPE, respectively.
- void
- add_global_tls_with_rel(Symbol* gsym, Rel_dyn* rel_dyn,
- unsigned int mod_r_type,
- unsigned int dtv_r_type);
-
- void
- add_global_tls_with_rela(Symbol* gsym, Rela_dyn* rela_dyn,
- unsigned int mod_r_type,
- unsigned int dtv_r_type);
-
- // Add an entry (or pair of entries) for a local TLS 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_tls(Sized_relobj<size, big_endian>* object,
- unsigned int sym_index, bool need_pair);
+ unsigned int sym_index, unsigned int got_type,
+ Rela_dyn* rela_dyn, unsigned int r_type);
- // Add an entry (or pair of entries) for a local TLS symbol to the GOT,
- // and add a dynamic relocation of type R_TYPE for the first GOT entry.
- // Because this is a local symbol, the first GOT entry can be relocated
- // relative to a section symbol, and the second GOT entry will have an
- // dtv-relative value that can be computed at link time.
+ // Add a pair of entries for a local symbol to the GOT, and add
+ // dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively.
void
- add_local_tls_with_rel(Sized_relobj<size, big_endian>* object,
- unsigned int sym_index, unsigned int shndx,
- bool need_pair, Rel_dyn* rel_dyn,
- unsigned int r_type);
+ add_local_pair_with_rel(Sized_relobj<size, big_endian>* object,
+ unsigned int sym_index, unsigned int shndx,
+ unsigned int got_type, Rel_dyn* rel_dyn,
+ unsigned int r_type_1, unsigned int r_type_2);
void
- add_local_tls_with_rela(Sized_relobj<size, big_endian>* object,
- unsigned int sym_index, unsigned int shndx,
- bool need_pair, Rela_dyn* rela_dyn,
- unsigned int r_type);
+ add_local_pair_with_rela(Sized_relobj<size, big_endian>* object,
+ unsigned int sym_index, unsigned int shndx,
+ unsigned int got_type, Rela_dyn* rela_dyn,
+ unsigned int r_type_1, unsigned int r_type_2);
// Add a constant to the GOT. This returns the offset of the new
// entry from the start of the GOT.
diff --git a/gold/resolve.cc b/gold/resolve.cc
index 330000099f..00e9278032 100644
--- a/gold/resolve.cc
+++ b/gold/resolve.cc
@@ -679,7 +679,6 @@ Symbol::override_base_with_special(const Symbol* from)
// somehow.
gold_assert(!from->is_target_special_ || this->is_target_special_);
gold_assert(!from->is_forwarder_);
- gold_assert(!from->has_got_offset_);
gold_assert(!from->has_plt_offset_);
gold_assert(!from->has_warning_);
gold_assert(!from->is_copied_from_dynobj_);
diff --git a/gold/symtab.cc b/gold/symtab.cc
index eef3a4b67d..3bd3833717 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -53,7 +53,7 @@ Symbol::init_fields(const char* name, const char* version,
this->version_ = version;
this->symtab_index_ = 0;
this->dynsym_index_ = 0;
- this->got_offset_ = 0;
+ this->got_offsets_.init();
this->plt_offset_ = 0;
this->type_ = type;
this->binding_ = binding;
@@ -66,7 +66,6 @@ Symbol::init_fields(const char* name, const char* version,
this->needs_dynsym_entry_ = false;
this->in_reg_ = false;
this->in_dyn_ = false;
- this->has_got_offset_ = false;
this->has_plt_offset_ = false;
this->has_warning_ = false;
this->is_copied_from_dynobj_ = false;
diff --git a/gold/symtab.h b/gold/symtab.h
index 8da9e6dcfb..bd417948cd 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -323,53 +323,22 @@ class Symbol
// Return whether this symbol has an entry in the GOT section.
// For a TLS symbol, this GOT entry will hold its tp-relative offset.
bool
- has_got_offset() const
- { return this->has_got_offset_; }
+ has_got_offset(unsigned int got_type) const
+ { return this->got_offsets_.get_offset(got_type) != -1U; }
// Return the offset into the GOT section of this symbol.
unsigned int
- got_offset() const
+ got_offset(unsigned int got_type) const
{
- gold_assert(this->has_got_offset());
- return this->got_offset_;
+ unsigned int got_offset = this->got_offsets_.get_offset(got_type);
+ gold_assert(got_offset != -1U);
+ return got_offset;
}
// Set the GOT offset of this symbol.
void
- set_got_offset(unsigned int got_offset)
- {
- this->has_got_offset_ = true;
- this->got_offset_ = got_offset;
- }
-
- // Return whether this TLS symbol has an entry in the GOT section for
- // its module index or, if NEED_PAIR is true, has a pair of entries
- // for its module index and dtv-relative offset.
- bool
- has_tls_got_offset(bool need_pair) const
- {
- return (this->has_tls_mod_got_offset_
- && (!need_pair || this->has_tls_pair_got_offset_));
- }
-
- // Return the offset into the GOT section for this symbol's TLS module
- // index or, if NEED_PAIR is true, for the pair of entries for the
- // module index and dtv-relative offset.
- unsigned int
- tls_got_offset(bool need_pair) const
- {
- gold_assert(this->has_tls_got_offset(need_pair));
- return this->tls_mod_got_offset_;
- }
-
- // Set the GOT offset of this symbol.
- void
- set_tls_got_offset(unsigned int got_offset, bool have_pair)
- {
- this->has_tls_mod_got_offset_ = true;
- this->has_tls_pair_got_offset_ = have_pair;
- this->tls_mod_got_offset_ = got_offset;
- }
+ set_got_offset(unsigned int got_type, unsigned int got_offset)
+ { this->got_offsets_.set_offset(got_type, got_offset); }
// Return whether this symbol has an entry in the PLT section.
bool
@@ -719,18 +688,11 @@ class Symbol
unsigned int dynsym_index_;
// If this symbol has an entry in the GOT section (has_got_offset_
- // is true), this is the offset from the start of the GOT section.
- // For a TLS symbol, if has_tls_tpoff_got_offset_ is true, this
- // serves as the GOT offset for the GOT entry that holds its
- // TP-relative offset.
- unsigned int got_offset_;
-
- // If this is a TLS symbol and has an entry in the GOT section
- // for a module index or a pair of entries (module index,
- // dtv-relative offset), these are the offsets from the start
- // of the GOT section.
- unsigned int tls_mod_got_offset_;
- unsigned int tls_pair_got_offset_;
+ // is true), this holds the offset from the start of the GOT section.
+ // 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_offset_list got_offsets_;
// If this symbol has an entry in the PLT section (has_plt_offset_
// is true), then this is the offset from the start of the PLT
@@ -769,15 +731,6 @@ class Symbol
bool in_reg_ : 1;
// True if we've seen this symbol in a dynamic object.
bool in_dyn_ : 1;
- // True if the symbol has an entry in the GOT section.
- // For a TLS symbol, this GOT entry will hold its tp-relative offset.
- bool has_got_offset_ : 1;
- // True if the symbol has an entry in the GOT section for its
- // module index.
- bool has_tls_mod_got_offset_ : 1;
- // True if the symbol has a pair of entries in the GOT section for its
- // module index and dtv-relative offset.
- bool has_tls_pair_got_offset_ : 1;
// True if the symbol has an entry in the PLT section.
bool has_plt_offset_ : 1;
// True if this is a dynamic symbol which needs a special value in
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index b64f6a8e9a..72c077970a 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -324,6 +324,14 @@ class Target_x86_64 : public Sized_target<64, false>
// general Target structure.
static const Target::Target_info x86_64_info;
+ enum Got_type
+ {
+ GOT_TYPE_STANDARD = 0, // GOT entry for a regular symbol
+ GOT_TYPE_TLS_OFFSET = 1, // GOT entry for TLS offset
+ GOT_TYPE_TLS_PAIR = 2, // GOT entry for TLS module/offset pair
+ GOT_TYPE_TLS_DESC = 3 // GOT entry for TLS_DESC pair
+ };
+
// The GOT section.
Output_data_got<64, false>* got_;
// The PLT section.
@@ -893,7 +901,7 @@ Target_x86_64::Scan::local(const General_options&,
// The symbol requires a GOT entry.
Output_data_got<64, false>* got = target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
- if (got->add_local(object, r_sym))
+ if (got->add_local(object, r_sym, GOT_TYPE_STANDARD))
{
// If we are generating a shared object, we need to add a
// dynamic relocation for this symbol's GOT entry.
@@ -902,16 +910,15 @@ Target_x86_64::Scan::local(const General_options&,
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
// R_X86_64_RELATIVE assumes a 64-bit relocation.
if (r_type != elfcpp::R_X86_64_GOT32)
- rela_dyn->add_local_relative(object, r_sym,
- elfcpp::R_X86_64_RELATIVE, got,
- object->local_got_offset(r_sym),
- 0);
+ rela_dyn->add_local_relative(
+ object, r_sym, elfcpp::R_X86_64_RELATIVE, got,
+ object->local_got_offset(r_sym, GOT_TYPE_STANDARD), 0);
else
{
gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
- rela_dyn->add_local(object, r_sym, r_type,
- got, object->local_got_offset(r_sym),
- 0);
+ rela_dyn->add_local(
+ object, r_sym, r_type, got,
+ object->local_got_offset(r_sym, GOT_TYPE_STANDARD), 0);
}
}
}
@@ -955,10 +962,11 @@ Target_x86_64::Scan::local(const General_options&,
Output_data_got<64, false>* got
= target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
- got->add_local_tls_with_rela(object, r_sym,
- lsym.get_st_shndx(), true,
- target->rela_dyn_section(layout),
- elfcpp::R_X86_64_DTPMOD64);
+ got->add_local_pair_with_rela(object, r_sym,
+ lsym.get_st_shndx(),
+ GOT_TYPE_TLS_PAIR,
+ target->rela_dyn_section(layout),
+ elfcpp::R_X86_64_DTPMOD64, 0);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_local(object, r_type);
@@ -994,7 +1002,7 @@ Target_x86_64::Scan::local(const General_options&,
Output_data_got<64, false>* got
= target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
- got->add_local_with_rela(object, r_sym,
+ got->add_local_with_rela(object, r_sym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_TPOFF64);
}
@@ -1140,7 +1148,7 @@ Target_x86_64::Scan::global(const General_options& options,
// The symbol requires a GOT entry.
Output_data_got<64, false>* got = target->got_section(symtab, layout);
if (gsym->final_value_is_known())
- got->add_global(gsym);
+ got->add_global(gsym, GOT_TYPE_STANDARD);
else
{
// If this symbol is not fully resolved, we need to add a
@@ -1149,14 +1157,14 @@ Target_x86_64::Scan::global(const General_options& options,
if (gsym->is_from_dynobj()
|| gsym->is_undefined()
|| gsym->is_preemptible())
- got->add_global_with_rela(gsym, rela_dyn,
+ got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn,
elfcpp::R_X86_64_GLOB_DAT);
else
{
- if (got->add_global(gsym))
- rela_dyn->add_global_relative(gsym,
- elfcpp::R_X86_64_RELATIVE,
- got, gsym->got_offset(), 0);
+ if (got->add_global(gsym, GOT_TYPE_STANDARD))
+ rela_dyn->add_global_relative(
+ gsym, elfcpp::R_X86_64_RELATIVE, got,
+ gsym->got_offset(GOT_TYPE_STANDARD), 0);
}
}
// For GOTPLT64, we also need a PLT entry (but only if the
@@ -1229,17 +1237,17 @@ Target_x86_64::Scan::global(const General_options& options,
// dtv-relative offset.
Output_data_got<64, false>* got
= target->got_section(symtab, layout);
- got->add_global_tls_with_rela(gsym,
- target->rela_dyn_section(layout),
- elfcpp::R_X86_64_DTPMOD64,
- elfcpp::R_X86_64_DTPOFF64);
+ got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_PAIR,
+ target->rela_dyn_section(layout),
+ elfcpp::R_X86_64_DTPMOD64,
+ elfcpp::R_X86_64_DTPOFF64);
}
else if (optimized_type == tls::TLSOPT_TO_IE)
{
// Create a GOT entry for the tp-relative offset.
Output_data_got<64, false>* got
= target->got_section(symtab, layout);
- got->add_global_with_rela(gsym,
+ got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_TPOFF64);
}
@@ -1276,7 +1284,7 @@ Target_x86_64::Scan::global(const General_options& options,
// Create a GOT entry for the tp-relative offset.
Output_data_got<64, false>* got
= target->got_section(symtab, layout);
- got->add_global_with_rela(gsym,
+ got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_TPOFF64);
}
@@ -1456,14 +1464,15 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
case elfcpp::R_X86_64_GOTPCREL64:
if (gsym != NULL)
{
- gold_assert(gsym->has_got_offset());
- got_offset = gsym->got_offset() - target->got_size();
+ gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+ got_offset = gsym->got_offset(GOT_TYPE_STANDARD) - target->got_size();
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym));
- got_offset = object->local_got_offset(r_sym) - target->got_size();
+ gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+ got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
+ - target->got_size());
}
have_got_offset = true;
break;
@@ -1691,14 +1700,16 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
unsigned int got_offset;
if (gsym != NULL)
{
- gold_assert(gsym->has_tls_got_offset(true));
- got_offset = gsym->tls_got_offset(true) - target->got_size();
+ gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_PAIR));
+ got_offset = (gsym->got_offset(GOT_TYPE_TLS_PAIR)
+ - target->got_size());
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
- gold_assert(object->local_has_tls_got_offset(r_sym, true));
- got_offset = (object->local_tls_got_offset(r_sym, true)
+ gold_assert(object->local_has_got_offset(r_sym,
+ GOT_TYPE_TLS_PAIR));
+ got_offset = (object->local_got_offset(r_sym, GOT_TYPE_TLS_PAIR)
- target->got_size());
}
if (optimized_type == tls::TLSOPT_TO_IE)
@@ -1776,14 +1787,16 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
unsigned int got_offset;
if (gsym != NULL)
{
- gold_assert(gsym->has_got_offset());
- got_offset = gsym->got_offset() - target->got_size();
+ gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_OFFSET));
+ got_offset = (gsym->got_offset(GOT_TYPE_TLS_OFFSET)
+ - target->got_size());
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym));
- got_offset = (object->local_got_offset(r_sym)
+ gold_assert(object->local_has_got_offset(r_sym,
+ GOT_TYPE_TLS_OFFSET));
+ got_offset = (object->local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET)
- target->got_size());
}
value = target->got_plt_section()->address() + got_offset;
OpenPOWER on IntegriCloud