summaryrefslogtreecommitdiff
path: root/gold/i386.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/i386.cc')
-rw-r--r--gold/i386.cc78
1 files changed, 48 insertions, 30 deletions
diff --git a/gold/i386.cc b/gold/i386.cc
index cc55249e9c..f12b6cdebf 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -339,6 +339,15 @@ class Target_i386 : public Sized_target<32, false>
// general Target structure.
static const Target::Target_info i386_info;
+ // The types of GOT entries needed for this platform.
+ enum Got_type
+ {
+ GOT_TYPE_STANDARD = 0, // GOT entry for a regular symbol
+ GOT_TYPE_TLS_OFFSET = 1, // GOT entry for TLS offset
+ GOT_TYPE_TLS_PAIR = 2, // GOT entry for TLS module/offset pair
+ GOT_TYPE_TLS_DESC = 3 // GOT entry for TLS_DESC pair
+ };
+
// The GOT section.
Output_data_got<32, false>* got_;
// The PLT section.
@@ -933,7 +942,7 @@ Target_i386::Scan::local(const General_options&,
// The symbol requires a GOT entry.
Output_data_got<32, false>* got = target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
- if (got->add_local(object, r_sym))
+ if (got->add_local(object, r_sym, GOT_TYPE_STANDARD))
{
// If we are generating a shared object, we need to add a
// dynamic RELATIVE relocation for this symbol's GOT entry.
@@ -941,10 +950,9 @@ Target_i386::Scan::local(const General_options&,
{
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
- rel_dyn->add_local_relative(object, r_sym,
- elfcpp::R_386_RELATIVE,
- got,
- object->local_got_offset(r_sym));
+ rel_dyn->add_local_relative(
+ object, r_sym, elfcpp::R_386_RELATIVE, got,
+ object->local_got_offset(r_sym, GOT_TYPE_STANDARD));
}
}
}
@@ -991,10 +999,11 @@ Target_i386::Scan::local(const General_options&,
Output_data_got<32, false>* got
= target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
- got->add_local_tls_with_rel(object, r_sym,
- lsym.get_st_shndx(), true,
- target->rel_dyn_section(layout),
- elfcpp::R_386_TLS_DTPMOD32);
+ got->add_local_pair_with_rel(object, r_sym,
+ lsym.get_st_shndx(),
+ GOT_TYPE_TLS_PAIR,
+ target->rel_dyn_section(layout),
+ elfcpp::R_386_TLS_DTPMOD32, 0);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_local(object, r_type);
@@ -1047,7 +1056,7 @@ Target_i386::Scan::local(const General_options&,
unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32
? elfcpp::R_386_TLS_TPOFF32
: elfcpp::R_386_TLS_TPOFF);
- got->add_local_with_rel(object, r_sym,
+ got->add_local_with_rel(object, r_sym, GOT_TYPE_TLS_OFFSET,
target->rel_dyn_section(layout),
dyn_r_type);
}
@@ -1210,7 +1219,7 @@ Target_i386::Scan::global(const General_options& options,
// The symbol requires a GOT entry.
Output_data_got<32, false>* got = target->got_section(symtab, layout);
if (gsym->final_value_is_known())
- got->add_global(gsym);
+ got->add_global(gsym, GOT_TYPE_STANDARD);
else
{
// If this symbol is not fully resolved, we need to add a
@@ -1219,12 +1228,14 @@ Target_i386::Scan::global(const General_options& options,
if (gsym->is_from_dynobj()
|| gsym->is_undefined()
|| gsym->is_preemptible())
- got->add_global_with_rel(gsym, rel_dyn, elfcpp::R_386_GLOB_DAT);
+ got->add_global_with_rel(gsym, GOT_TYPE_STANDARD,
+ rel_dyn, elfcpp::R_386_GLOB_DAT);
else
{
- if (got->add_global(gsym))
- rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
- got, gsym->got_offset());
+ if (got->add_global(gsym, GOT_TYPE_STANDARD))
+ rel_dyn->add_global_relative(
+ gsym, elfcpp::R_386_RELATIVE, got,
+ gsym->got_offset(GOT_TYPE_STANDARD));
}
}
}
@@ -1291,7 +1302,7 @@ Target_i386::Scan::global(const General_options& options,
// dtv-relative offset.
Output_data_got<32, false>* got
= target->got_section(symtab, layout);
- got->add_global_tls_with_rel(gsym,
+ got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
target->rel_dyn_section(layout),
elfcpp::R_386_TLS_DTPMOD32,
elfcpp::R_386_TLS_DTPOFF32);
@@ -1301,7 +1312,8 @@ Target_i386::Scan::global(const General_options& options,
// Create a GOT entry for the tp-relative offset.
Output_data_got<32, false>* got
= target->got_section(symtab, layout);
- got->add_global_with_rel(gsym, target->rel_dyn_section(layout),
+ got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
+ target->rel_dyn_section(layout),
elfcpp::R_386_TLS_TPOFF32);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
@@ -1353,7 +1365,7 @@ Target_i386::Scan::global(const General_options& options,
unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32
? elfcpp::R_386_TLS_TPOFF32
: elfcpp::R_386_TLS_TPOFF);
- got->add_global_with_rel(gsym,
+ got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
target->rel_dyn_section(layout),
dyn_r_type);
}
@@ -1576,14 +1588,16 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
case elfcpp::R_386_GOT32:
if (gsym != NULL)
{
- gold_assert(gsym->has_got_offset());
- got_offset = gsym->got_offset() - target->got_size();
+ gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+ got_offset = (gsym->got_offset(GOT_TYPE_STANDARD)
+ - target->got_size());
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym));
- got_offset = object->local_got_offset(r_sym) - target->got_size();
+ gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+ got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
+ - target->got_size());
}
have_got_offset = true;
break;
@@ -1770,14 +1784,16 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
unsigned int got_offset;
if (gsym != NULL)
{
- gold_assert(gsym->has_tls_got_offset(true));
- got_offset = gsym->tls_got_offset(true) - target->got_size();
+ gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_PAIR));
+ got_offset = (gsym->got_offset(GOT_TYPE_TLS_PAIR)
+ - target->got_size());
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
- gold_assert(object->local_has_tls_got_offset(r_sym, true));
- got_offset = (object->local_tls_got_offset(r_sym, true)
+ gold_assert(object->local_has_got_offset(r_sym,
+ GOT_TYPE_TLS_PAIR));
+ got_offset = (object->local_got_offset(r_sym, GOT_TYPE_TLS_PAIR)
- target->got_size());
}
if (optimized_type == tls::TLSOPT_TO_IE)
@@ -1868,14 +1884,16 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
unsigned int got_offset;
if (gsym != NULL)
{
- gold_assert(gsym->has_got_offset());
- got_offset = gsym->got_offset();
+ gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_OFFSET));
+ got_offset = gsym->got_offset(GOT_TYPE_TLS_OFFSET);
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym));
- got_offset = object->local_got_offset(r_sym);
+ gold_assert(object->local_has_got_offset(r_sym,
+ GOT_TYPE_TLS_OFFSET));
+ got_offset = object->local_got_offset(r_sym,
+ GOT_TYPE_TLS_OFFSET);
}
// For the R_386_TLS_IE relocation, we need to apply the
// absolute address of the GOT entry.