mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-24 12:35:55 +08:00
* 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.
This commit is contained in:
parent
403fe1979f
commit
0a65a3a740
@ -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.
|
||||
|
78
gold/i386.cc
78
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.
|
||||
|
163
gold/object.h
163
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)
|
||||
set_local_got_offset(unsigned int symndx, unsigned int got_type,
|
||||
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
|
||||
{
|
||||
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_;
|
||||
};
|
||||
|
287
gold/output.cc
287
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,19 +1096,77 @@ 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 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_global_pair_with_rel(
|
||||
Symbol* gsym,
|
||||
unsigned int got_type,
|
||||
Rel_dyn* rel_dyn,
|
||||
unsigned int r_type_1,
|
||||
unsigned int r_type_2)
|
||||
{
|
||||
if (gsym->has_got_offset(got_type))
|
||||
return;
|
||||
|
||||
this->entries_.push_back(Got_entry());
|
||||
unsigned int got_offset = this->last_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_global_pair_with_rela(
|
||||
Symbol* gsym,
|
||||
unsigned int got_type,
|
||||
Rela_dyn* rela_dyn,
|
||||
unsigned int r_type_1,
|
||||
unsigned int r_type_2)
|
||||
{
|
||||
if (gsym->has_got_offset(got_type))
|
||||
return;
|
||||
|
||||
this->entries_.push_back(Got_entry());
|
||||
unsigned int got_offset = this->last_got_offset();
|
||||
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 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.
|
||||
@ -1114,14 +1175,15 @@ template<int size, bool big_endian>
|
||||
bool
|
||||
Output_data_got<size, big_endian>::add_local(
|
||||
Sized_relobj<size, big_endian>* object,
|
||||
unsigned int symndx)
|
||||
unsigned int symndx,
|
||||
unsigned int got_type)
|
||||
{
|
||||
if (object->local_has_got_offset(symndx))
|
||||
if (object->local_has_got_offset(symndx, got_type))
|
||||
return false;
|
||||
|
||||
this->entries_.push_back(Got_entry(object, symndx));
|
||||
this->set_got_size();
|
||||
object->set_local_got_offset(symndx, this->last_got_offset());
|
||||
object->set_local_got_offset(symndx, got_type, this->last_got_offset());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1132,16 +1194,17 @@ void
|
||||
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 (object->local_has_got_offset(symndx))
|
||||
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();
|
||||
object->set_local_got_offset(symndx, got_offset);
|
||||
object->set_local_got_offset(symndx, got_type, got_offset);
|
||||
rel_dyn->add_local(object, symndx, r_type, this, got_offset);
|
||||
}
|
||||
|
||||
@ -1150,203 +1213,81 @@ void
|
||||
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 (object->local_has_got_offset(symndx))
|
||||
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();
|
||||
object->set_local_got_offset(symndx, got_offset);
|
||||
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 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.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
bool
|
||||
Output_data_got<size, big_endian>::add_global_tls(Symbol* gsym, bool need_pair)
|
||||
{
|
||||
if (gsym->has_tls_got_offset(need_pair))
|
||||
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->set_got_size();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add an entry for a global TLS symbol to the GOT, and add a dynamic
|
||||
// relocation of type R_TYPE.
|
||||
// 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_global_tls_with_rel(
|
||||
Symbol* gsym,
|
||||
Rel_dyn* rel_dyn,
|
||||
unsigned int r_type)
|
||||
{
|
||||
if (gsym->has_tls_got_offset(false))
|
||||
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);
|
||||
}
|
||||
|
||||
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 r_type)
|
||||
{
|
||||
if (gsym->has_tls_got_offset(false))
|
||||
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(
|
||||
Output_data_got<size, big_endian>::add_local_pair_with_rel(
|
||||
Sized_relobj<size, big_endian>* object,
|
||||
unsigned int symndx,
|
||||
bool need_pair)
|
||||
unsigned int shndx,
|
||||
unsigned int got_type,
|
||||
Rel_dyn* rel_dyn,
|
||||
unsigned int r_type_1,
|
||||
unsigned int r_type_2)
|
||||
{
|
||||
if (object->local_has_tls_got_offset(symndx, need_pair))
|
||||
return false;
|
||||
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_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_1, this, got_offset);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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.
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Output_data_got<size, big_endian>::add_local_tls_with_rel(
|
||||
Sized_relobj<size, big_endian>* object,
|
||||
unsigned int symndx,
|
||||
unsigned int shndx,
|
||||
bool need_pair,
|
||||
Rel_dyn* rel_dyn,
|
||||
unsigned int r_type)
|
||||
{
|
||||
if (object->local_has_tls_got_offset(symndx, need_pair))
|
||||
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);
|
||||
section_offset_type off;
|
||||
Output_section* os = object->output_section(shndx, &off);
|
||||
rel_dyn->add_output_section(os, r_type, 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));
|
||||
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();
|
||||
}
|
||||
|
@ -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);
|
||||
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 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.
|
||||
// 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_global_tls_with_rel(Symbol* gsym, 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_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);
|
||||
|
||||
// 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.
|
||||
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);
|
||||
|
||||
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.
|
||||
|
@ -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_);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user