aboutsummaryrefslogtreecommitdiff
path: root/gold/i386.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/i386.cc')
-rw-r--r--gold/i386.cc151
1 files changed, 74 insertions, 77 deletions
diff --git a/gold/i386.cc b/gold/i386.cc
index 693ae4c..0a3931a 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -335,6 +335,10 @@ class Target_i386 : public Target_freebsd<32, false>
// The class which scans relocations.
struct Scan
{
+ static inline int
+
+ get_reference_flags(unsigned int r_type);
+
inline void
local(Symbol_table* symtab, Layout* layout, Target_i386* target,
Sized_relobj<32, false>* object,
@@ -406,7 +410,7 @@ class Target_i386 : public Target_freebsd<32, false>
// Return whether the static relocation needs to be applied.
inline bool
should_apply_static_reloc(const Sized_symbol<32>* gsym,
- int ref_flags,
+ unsigned int r_type,
bool is_32bit,
Output_section* output_section);
@@ -1191,41 +1195,49 @@ Target_i386::optimize_tls_reloc(bool is_final, int r_type)
}
}
-// Report an unsupported relocation against a local symbol.
+// Get the Reference_flags for a particular relocation.
-void
-Target_i386::Scan::unsupported_reloc_local(Sized_relobj<32, false>* object,
- unsigned int r_type)
-{
- gold_error(_("%s: unsupported reloc %u against local symbol"),
- object->name().c_str(), r_type);
-}
-
-// Return whether we need to make a PLT entry for a relocation of a
-// given type against a STT_GNU_IFUNC symbol.
-
-bool
-Target_i386::Scan::reloc_needs_plt_for_ifunc(Sized_relobj<32, false>* object,
- unsigned int r_type)
+int
+Target_i386::Scan::get_reference_flags(unsigned int r_type)
{
switch (r_type)
{
case elfcpp::R_386_NONE:
case elfcpp::R_386_GNU_VTINHERIT:
case elfcpp::R_386_GNU_VTENTRY:
- return false;
+ case elfcpp::R_386_GOTPC:
+ // No symbol reference.
+ return 0;
case elfcpp::R_386_32:
case elfcpp::R_386_16:
case elfcpp::R_386_8:
+ return Symbol::ABSOLUTE_REF;
+
case elfcpp::R_386_PC32:
case elfcpp::R_386_PC16:
case elfcpp::R_386_PC8:
- case elfcpp::R_386_PLT32:
case elfcpp::R_386_GOTOFF:
- case elfcpp::R_386_GOTPC:
+ return Symbol::RELATIVE_REF;
+
+ case elfcpp::R_386_PLT32:
+ return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
+
case elfcpp::R_386_GOT32:
- return true;
+ // Absolute in GOT.
+ return Symbol::ABSOLUTE_REF;
+
+ case elfcpp::R_386_TLS_GD: // Global-dynamic
+ case elfcpp::R_386_TLS_GOTDESC: // Global-dynamic (from ~oliva url)
+ case elfcpp::R_386_TLS_DESC_CALL:
+ case elfcpp::R_386_TLS_LDM: // Local-dynamic
+ case elfcpp::R_386_TLS_LDO_32: // Alternate local-dynamic
+ case elfcpp::R_386_TLS_IE: // Initial-exec
+ case elfcpp::R_386_TLS_IE_32:
+ case elfcpp::R_386_TLS_GOTIE:
+ case elfcpp::R_386_TLS_LE: // Local-exec
+ case elfcpp::R_386_TLS_LE_32:
+ return Symbol::TLS_REF;
case elfcpp::R_386_COPY:
case elfcpp::R_386_GLOB_DAT:
@@ -1237,23 +1249,6 @@ Target_i386::Scan::reloc_needs_plt_for_ifunc(Sized_relobj<32, false>* object,
case elfcpp::R_386_TLS_DTPOFF32:
case elfcpp::R_386_TLS_TPOFF32:
case elfcpp::R_386_TLS_DESC:
- // We will give an error later.
- return false;
-
- case elfcpp::R_386_TLS_GD:
- case elfcpp::R_386_TLS_GOTDESC:
- case elfcpp::R_386_TLS_DESC_CALL:
- case elfcpp::R_386_TLS_LDM:
- case elfcpp::R_386_TLS_LDO_32:
- case elfcpp::R_386_TLS_IE:
- case elfcpp::R_386_TLS_IE_32:
- case elfcpp::R_386_TLS_GOTIE:
- case elfcpp::R_386_TLS_LE:
- case elfcpp::R_386_TLS_LE_32:
- gold_error(_("%s: unsupported TLS reloc %u for IFUNC symbol"),
- object->name().c_str(), r_type);
- return false;
-
case elfcpp::R_386_32PLT:
case elfcpp::R_386_TLS_GD_32:
case elfcpp::R_386_TLS_GD_PUSH:
@@ -1265,11 +1260,35 @@ Target_i386::Scan::reloc_needs_plt_for_ifunc(Sized_relobj<32, false>* object,
case elfcpp::R_386_TLS_LDM_POP:
case elfcpp::R_386_USED_BY_INTEL_200:
default:
- // We will give an error later.
- return false;
+ // Not expected. We will give an error later.
+ return 0;
}
}
+// Report an unsupported relocation against a local symbol.
+
+void
+Target_i386::Scan::unsupported_reloc_local(Sized_relobj<32, false>* object,
+ unsigned int r_type)
+{
+ gold_error(_("%s: unsupported reloc %u against local symbol"),
+ object->name().c_str(), r_type);
+}
+
+// Return whether we need to make a PLT entry for a relocation of a
+// given type against a STT_GNU_IFUNC symbol.
+
+bool
+Target_i386::Scan::reloc_needs_plt_for_ifunc(Sized_relobj<32, false>* object,
+ unsigned int r_type)
+{
+ int flags = Scan::get_reference_flags(r_type);
+ if (flags & Symbol::TLS_REF)
+ gold_error(_("%s: unsupported TLS reloc %u for IFUNC symbol"),
+ object->name().c_str(), r_type);
+ return flags != 0;
+}
+
// Scan a relocation for a local symbol.
inline void
@@ -1676,7 +1695,7 @@ Target_i386::Scan::global(Symbol_table* symtab,
gsym->set_needs_dynsym_value();
}
// Make a dynamic relocation if necessary.
- if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF))
+ if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
{
if (gsym->may_need_copy_reloc())
{
@@ -1737,10 +1756,7 @@ Target_i386::Scan::global(Symbol_table* symtab,
target->make_plt_entry(symtab, layout, gsym);
}
// Make a dynamic relocation if necessary.
- int flags = Symbol::NON_PIC_REF;
- if (gsym->is_func())
- flags |= Symbol::FUNCTION_CALL;
- if (gsym->needs_dynamic_reloc(flags))
+ if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
{
if (gsym->may_need_copy_reloc())
{
@@ -2109,7 +2125,7 @@ Target_i386::do_finalize_sections(
inline bool
Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym,
- int ref_flags,
+ unsigned int r_type,
bool is_32bit,
Output_section* output_section)
{
@@ -2119,6 +2135,8 @@ Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym,
if ((output_section->flags() & elfcpp::SHF_ALLOC) == 0)
return true;
+ int ref_flags = Scan::get_reference_flags(r_type);
+
// For local symbols, we will have created a non-RELATIVE dynamic
// relocation only if (a) the output is position independent,
// (b) the relocation is absolute (not pc- or segment-relative), and
@@ -2176,7 +2194,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
if (gsym != NULL
&& gsym->type() == elfcpp::STT_GNU_IFUNC
&& r_type == elfcpp::R_386_32
- && gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF)
+ && gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type))
&& gsym->can_use_relative_reloc(false)
&& !gsym->is_from_dynobj()
&& !gsym->is_undefined()
@@ -2186,9 +2204,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
// want to use the real value of the symbol, not the PLT offset.
}
else if (gsym != NULL
- && gsym->use_plt_offset(r_type == elfcpp::R_386_PC8
- || r_type == elfcpp::R_386_PC16
- || r_type == elfcpp::R_386_PC32))
+ && gsym->use_plt_offset(Scan::get_reference_flags(r_type)))
{
symval.set_output_value(target->plt_section()->address()
+ gsym->plt_offset());
@@ -2242,52 +2258,33 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
break;
case elfcpp::R_386_32:
- if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true,
- output_section))
+ if (should_apply_static_reloc(gsym, r_type, true, output_section))
Relocate_functions<32, false>::rel32(view, object, psymval);
break;
case elfcpp::R_386_PC32:
- {
- int ref_flags = Symbol::NON_PIC_REF;
- if (gsym != NULL && gsym->is_func())
- ref_flags |= Symbol::FUNCTION_CALL;
- if (should_apply_static_reloc(gsym, ref_flags, true, output_section))
- Relocate_functions<32, false>::pcrel32(view, object, psymval, address);
- }
+ if (should_apply_static_reloc(gsym, r_type, true, output_section))
+ Relocate_functions<32, false>::pcrel32(view, object, psymval, address);
break;
case elfcpp::R_386_16:
- if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
- output_section))
+ if (should_apply_static_reloc(gsym, r_type, false, output_section))
Relocate_functions<32, false>::rel16(view, object, psymval);
break;
case elfcpp::R_386_PC16:
- {
- int ref_flags = Symbol::NON_PIC_REF;
- if (gsym != NULL && gsym->is_func())
- ref_flags |= Symbol::FUNCTION_CALL;
- if (should_apply_static_reloc(gsym, ref_flags, false, output_section))
- Relocate_functions<32, false>::pcrel16(view, object, psymval, address);
- }
+ if (should_apply_static_reloc(gsym, r_type, false, output_section))
+ Relocate_functions<32, false>::pcrel16(view, object, psymval, address);
break;
case elfcpp::R_386_8:
- if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
- output_section))
+ if (should_apply_static_reloc(gsym, r_type, false, output_section))
Relocate_functions<32, false>::rel8(view, object, psymval);
break;
case elfcpp::R_386_PC8:
- {
- int ref_flags = Symbol::NON_PIC_REF;
- if (gsym != NULL && gsym->is_func())
- ref_flags |= Symbol::FUNCTION_CALL;
- if (should_apply_static_reloc(gsym, ref_flags, false,
- output_section))
- Relocate_functions<32, false>::pcrel8(view, object, psymval, address);
- }
+ if (should_apply_static_reloc(gsym, r_type, false, output_section))
+ Relocate_functions<32, false>::pcrel8(view, object, psymval, address);
break;
case elfcpp::R_386_PLT32: