+2011-07-08 Ian Lance Taylor <iant@google.com>
+
+ PR gold/12279
+ * resolve.cc (Symbol_table::should_override): Add fromtype
+ parameter. Change all callers. Give error when linking together
+ TLS and non-TLS symbol.
+ (Symbol_table::should_override_with_special): Add fromtype
+ parameter. Change all callers.
+ * i386.cc (Target_i386::Relocate::relocate_tls): Don't crash if
+ there is no TLS segment if we have reported some errors.
+ * x86_64.cc (Target_x86_64::relocate_tls): Likewise.
+
2011-07-08 Ian Lance Taylor <iant@google.com>
PR gold/12372
case elfcpp::R_386_TLS_GD: // Global-dynamic
if (optimized_type == tls::TLSOPT_TO_LE)
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
this->tls_gd_to_le(relinfo, relnum, tls_segment,
rel, r_type, value, view,
view_size);
}
if (optimized_type == tls::TLSOPT_TO_IE)
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
this->tls_gd_to_ie(relinfo, relnum, tls_segment, rel, r_type,
got_offset, view, view_size);
break;
this->local_dynamic_type_ = LOCAL_DYNAMIC_GNU;
if (optimized_type == tls::TLSOPT_TO_LE)
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
this->tls_desc_gd_to_le(relinfo, relnum, tls_segment,
rel, r_type, value, view,
view_size);
}
if (optimized_type == tls::TLSOPT_TO_IE)
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
this->tls_desc_gd_to_ie(relinfo, relnum, tls_segment, rel, r_type,
got_offset, view, view_size);
break;
this->local_dynamic_type_ = LOCAL_DYNAMIC_GNU;
if (optimized_type == tls::TLSOPT_TO_LE)
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
this->tls_ld_to_le(relinfo, relnum, tls_segment, rel, r_type,
value, view, view_size);
break;
elfcpp::Shdr<32, false> shdr(relinfo->data_shdr);
if ((shdr.get_sh_flags() & elfcpp::SHF_EXECINSTR) != 0)
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
value -= tls_segment->memsz();
}
}
case elfcpp::R_386_TLS_IE_32:
if (optimized_type == tls::TLSOPT_TO_LE)
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
Target_i386::Relocate::tls_ie_to_le(relinfo, relnum, tls_segment,
rel, r_type, value, view,
view_size);
// have been created for this location, so do not apply it now.
if (!parameters->options().shared())
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
value -= tls_segment->memsz();
Relocate_functions<32, false>::rel32(view, value);
}
// have been created for this location, so do not apply it now.
if (!parameters->options().shared())
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
value = tls_segment->memsz() - value;
Relocate_functions<32, false>::rel32(view, value);
}
bool adjust_common_sizes;
bool adjust_dyndef;
typename Sized_symbol<size>::Size_type tosize = to->symsize();
- if (Symbol_table::should_override(to, frombits, OBJECT, object,
- &adjust_common_sizes,
+ if (Symbol_table::should_override(to, frombits, sym.get_st_type(), OBJECT,
+ object, &adjust_common_sizes,
&adjust_dyndef))
{
elfcpp::STB tobinding = to->binding();
bool
Symbol_table::should_override(const Symbol* to, unsigned int frombits,
- Defined defined, Object* object,
- bool* adjust_common_sizes,
+ elfcpp::STT fromtype, Defined defined,
+ Object* object, bool* adjust_common_sizes,
bool* adjust_dyndef)
{
*adjust_common_sizes = false;
to->type());
}
- // FIXME: Warn if either but not both of TO and SYM are STT_TLS.
+ if (to->type() == elfcpp::STT_TLS
+ ? fromtype != elfcpp::STT_TLS
+ : fromtype == elfcpp::STT_TLS)
+ Symbol_table::report_resolve_problem(true,
+ _("symbol '%s' used as both __thread "
+ "and non-__thread"),
+ to, defined, object);
// We use a giant switch table for symbol resolution. This code is
// unwieldy, but: 1) it is efficient; 2) we definitely handle all
// defining special symbols.
bool
-Symbol_table::should_override_with_special(const Symbol* to, Defined defined)
+Symbol_table::should_override_with_special(const Symbol* to,
+ elfcpp::STT fromtype,
+ Defined defined)
{
bool adjust_common_sizes;
bool adjust_dyn_def;
unsigned int frombits = global_flag | regular_flag | def_flag;
- bool ret = Symbol_table::should_override(to, frombits, defined, NULL,
- &adjust_common_sizes,
+ bool ret = Symbol_table::should_override(to, frombits, fromtype, defined,
+ NULL, &adjust_common_sizes,
&adjust_dyn_def);
gold_assert(!adjust_common_sizes && !adjust_dyn_def);
return ret;
return sym;
}
- if (Symbol_table::should_override_with_special(oldsym, defined))
+ if (Symbol_table::should_override_with_special(oldsym, type, defined))
this->override_with_special(oldsym, sym);
if (resolve_oldsym)
return sym;
}
- if (Symbol_table::should_override_with_special(oldsym, defined))
+ if (Symbol_table::should_override_with_special(oldsym, type, defined))
this->override_with_special(oldsym, sym);
if (resolve_oldsym)
}
if (force_override
- || Symbol_table::should_override_with_special(oldsym, defined))
+ || Symbol_table::should_override_with_special(oldsym, type, defined))
this->override_with_special(oldsym, sym);
if (resolve_oldsym)
// Whether we should override a symbol, based on flags in
// resolve.cc.
static bool
- should_override(const Symbol*, unsigned int, Defined, Object*, bool*, bool*);
+ should_override(const Symbol*, unsigned int, elfcpp::STT, Defined,
+ Object*, bool*, bool*);
// Report a problem in symbol resolution.
static void
// Whether we should override a symbol with a special symbol which
// is automatically defined by the linker.
static bool
- should_override_with_special(const Symbol*, Defined);
+ should_override_with_special(const Symbol*, elfcpp::STT, Defined);
// Override a symbol with a special symbol.
template<int size>
}
if (optimized_type == tls::TLSOPT_TO_LE)
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
this->tls_gd_to_le(relinfo, relnum, tls_segment,
rela, r_type, value, view,
view_size);
}
if (optimized_type == tls::TLSOPT_TO_IE)
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
value = target->got_plt_section()->address() + got_offset;
this->tls_gd_to_ie(relinfo, relnum, tls_segment, rela, r_type,
value, view, address, view_size);
}
if (optimized_type == tls::TLSOPT_TO_LE)
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
this->tls_desc_gd_to_le(relinfo, relnum, tls_segment,
rela, r_type, value, view,
view_size);
}
if (optimized_type == tls::TLSOPT_TO_IE)
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
value = target->got_plt_section()->address() + got_offset;
this->tls_desc_gd_to_ie(relinfo, relnum, tls_segment,
rela, r_type, value, view, address,
}
if (optimized_type == tls::TLSOPT_TO_LE)
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
this->tls_ld_to_le(relinfo, relnum, tls_segment, rela, r_type,
value, view, view_size);
break;
// R_X86_64_TLSLD.
if (optimized_type == tls::TLSOPT_TO_LE && is_executable)
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
value -= tls_segment->memsz();
}
Relocate_functions<64, false>::rela32(view, value, addend);
// See R_X86_64_DTPOFF32, just above, for why we check for is_executable.
if (optimized_type == tls::TLSOPT_TO_LE && is_executable)
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
value -= tls_segment->memsz();
}
Relocate_functions<64, false>::rela64(view, value, addend);
case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
if (optimized_type == tls::TLSOPT_TO_LE)
{
- gold_assert(tls_segment != NULL);
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
Target_x86_64::Relocate::tls_ie_to_le(relinfo, relnum, tls_segment,
rela, r_type, value, view,
view_size);
break;
case elfcpp::R_X86_64_TPOFF32: // Local-exec
+ if (tls_segment == NULL)
+ {
+ gold_assert(parameters->errors()->error_count() > 0);
+ return;
+ }
value -= tls_segment->memsz();
Relocate_functions<64, false>::rela32(view, value, addend);
break;