This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: bug: GOLD handling of Sparc PLTREL
From: Ian Lance Taylor <iant@google.com>
Date: Tue, 09 Feb 2010 07:04:13 -0800
> David Miller <davem@davemloft.net> writes:
>
>>> I see a few calls to add_local_relative and add_global_relative that
>>> are not passing down elfcpp::R_SPARC_RELATIVE as the reloc type. That
>>> is rather suspicious and seems like it could cause this sort of
>>> problem.
>>
>> It has nothing to do with these crashes.
>
> It is a problem, though, because it will cause DT_RELACOUNT to be
> incorrect.
How does this look?
gold/
2010-02-09 David S. Miller <davem@davemloft.net>
* sparc.cc (Target_sparc::Scan::local): Do not emit relocs other than
R_SPARC_RELATIVE using ->add_local_relative().
(Target_sparc::Scan::global): Likewise for ->add_global_relative().
diff --git a/gold/sparc.cc b/gold/sparc.cc
index d3c9435..234c5f5 100644
--- a/gold/sparc.cc
+++ b/gold/sparc.cc
@@ -1675,23 +1675,31 @@ Target_sparc<size, big_endian>::Scan::local(
if (parameters->options().output_is_position_independent())
{
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
check_non_pic(object, r_type);
if (lsym.get_st_type() != elfcpp::STT_SECTION)
{
- unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
rela_dyn->add_local(object, r_sym, orig_r_type, output_section,
data_shndx, reloc.get_r_offset(),
reloc.get_r_addend());
}
else
{
- unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+ unsigned int shndx = lsym.get_st_shndx();
+ bool is_ordinary;
+
gold_assert(lsym.get_st_value() == 0);
- rela_dyn->add_local_relative(object, r_sym, orig_r_type,
- output_section, data_shndx,
- reloc.get_r_offset(),
- reloc.get_r_addend());
+ shndx = object->adjust_sym_shndx(r_sym, shndx,
+ &is_ordinary);
+ if (!is_ordinary)
+ object->error(_("section symbol %u has bad shndx %u"),
+ r_sym, shndx);
+ else
+ rela_dyn->add_local_section(object, shndx,
+ r_type, output_section,
+ data_shndx, reloc.get_r_offset(),
+ reloc.get_r_addend());
}
}
break;
@@ -1839,15 +1847,13 @@ Target_sparc<size, big_endian>::Scan::local(
if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_OFFSET))
{
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- unsigned int off = got->add_constant(0);
-
- object->set_local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET,
- off);
- rela_dyn->add_local_relative(object, r_sym,
- (size == 64 ?
- elfcpp::R_SPARC_TLS_TPOFF64 :
- elfcpp::R_SPARC_TLS_TPOFF32),
- got, off, 0);
+
+ got->add_local_with_rela(object, r_sym,
+ GOT_TYPE_TLS_OFFSET,
+ rela_dyn,
+ (size == 64 ?
+ elfcpp::R_SPARC_TLS_TPOFF64 :
+ elfcpp::R_SPARC_TLS_TPOFF32));
}
}
else if (optimized_type != tls::TLSOPT_TO_LE)
@@ -1863,9 +1869,9 @@ Target_sparc<size, big_endian>::Scan::local(
gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- rela_dyn->add_local_relative(object, r_sym, r_type,
- output_section, data_shndx,
- reloc.get_r_offset(), 0);
+ rela_dyn->add_local(object, r_sym, r_type,
+ output_section, data_shndx,
+ reloc.get_r_offset(), 0);
}
break;
}
@@ -2060,19 +2066,10 @@ Target_sparc<size, big_endian>::Scan::global(
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
check_non_pic(object, r_type);
- if (gsym->is_from_dynobj()
- || gsym->is_undefined()
- || gsym->is_preemptible())
- rela_dyn->add_global(gsym, orig_r_type, output_section,
- object, data_shndx,
- reloc.get_r_offset(),
- reloc.get_r_addend());
- else
- rela_dyn->add_global_relative(gsym, orig_r_type,
- output_section, object,
- data_shndx,
- reloc.get_r_offset(),
- reloc.get_r_addend());
+ rela_dyn->add_global(gsym, orig_r_type, output_section,
+ object, data_shndx,
+ reloc.get_r_offset(),
+ reloc.get_r_addend());
}
}
}
@@ -2204,10 +2201,10 @@ Target_sparc<size, big_endian>::Scan::global(
if (parameters->options().shared())
{
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- rela_dyn->add_global_relative(gsym, orig_r_type,
- output_section, object,
- data_shndx, reloc.get_r_offset(),
- 0);
+ rela_dyn->add_global(gsym, orig_r_type,
+ output_section, object,
+ data_shndx, reloc.get_r_offset(),
+ 0);
}
break;