diff options
author | Cary Coutant <ccoutant@google.com> | 2008-03-25 18:37:16 +0000 |
---|---|---|
committer | Cary Coutant <ccoutant@google.com> | 2008-03-25 18:37:16 +0000 |
commit | 0a65a3a7402d9b8523844366c638a0354f48dfa4 (patch) | |
tree | 38d2a9a2cbf1277091cd8de1f92c3e6871156407 /gold | |
parent | 403fe1979f7a9e128d3904731e709fadbf60ea81 (diff) | |
download | gdb-0a65a3a7402d9b8523844366c638a0354f48dfa4.zip gdb-0a65a3a7402d9b8523844366c638a0354f48dfa4.tar.gz gdb-0a65a3a7402d9b8523844366c638a0354f48dfa4.tar.bz2 |
* 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.
Diffstat (limited to 'gold')
-rw-r--r-- | gold/ChangeLog | 73 | ||||
-rw-r--r-- | gold/i386.cc | 78 | ||||
-rw-r--r-- | gold/object.h | 163 | ||||
-rw-r--r-- | gold/output.cc | 265 | ||||
-rw-r--r-- | gold/output.h | 91 | ||||
-rw-r--r-- | gold/resolve.cc | 1 | ||||
-rw-r--r-- | gold/symtab.cc | 3 | ||||
-rw-r--r-- | gold/symtab.h | 73 | ||||
-rw-r--r-- | gold/x86_64.cc | 87 |
9 files changed, 418 insertions, 416 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index 447712a..104646f 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 cc55249..f12b6cd 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 3a74685..4a2ad8a 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 85cc2b2..3a11aa4 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 e394538..2b864f3 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 3300000..00e9278 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 eef3a4b..3bd3833 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 8da9e6d..bd41794 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 b64f6a8..72c0779 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; |