forked from Imagelibrary/binutils-gdb
2010-09-08 Doug Kwan <dougkwan@google.com>
* arm.cc (Arm_exidx_cantunwind::do_print_to_mapfile): New method. (Arm_relobj::do_relocate_sections): Add new parameter for output file to match the parent. (Target_arm::scan_reloc_section_for_stubs): Use would-be final values of local symbols instead of input values. Update code to track changes in gold::relocate_section. * object.cc (Sized_relobj::compute_final_local_value): New methods. (Sized_relobj::compute_final_local_value_internal): New methods. (Sized_relobj::do_finalize_local_symbols): Move code from loop body into private version of Sized_relobj::compute_final_local_value. Call the inline method. * object.h (Symbol_value::Symbol_value): Define destructor. Free merged symbol value if there is one. (Symbol_value::has_output_value): New method defintiion. (Sized_relobj::Compute_final_local_value_status): New enum type. (Sized_relobj::compute_final_local_value): New methods. (Sized_relobj::compute_final_local_value_internal): New methods. * Makefile.am (check_SCRIPTS): Add arm_branch_out_of_range.sh and arm_cortex_a8.sh. (thumb_bl_out_of_range_local, arm_cortex_a8_b_cond, arm_cortex_a8_bl, arm_cortex_a8_blx, arm_cortex_a8_local, arm_corte_a8_local_reloc): New tests. * Makefile.in: Regenerate. * testsuite/arm_bl_out_of_range.s: Update test. * testsuite/thumb_bl_out_of_range.s: Ditto. * testsuite/thumb_blx_out_of_range.s: Ditto. * testsuite/arm_branch_out_of_range.sh: New file. * testsuite/arm_cortex_a8.sh: Ditto. * testsuite/arm_cortex_a8_b.s: Ditto. * testsuite/arm_cortex_a8_b_cond.s: Ditto. * testsuite/arm_cortex_a8_b_local.s: Ditto. * testsuite/arm_cortex_a8_bl.s: Ditto. * testsuite/arm_cortex_a8_blx.s: Ditto. * testsuite/arm_cortex_a8_local.s: Ditto. * testsuite/arm_cortex_a8_local_reloc.s: Ditto. * testsuite/thumb_bl_out_of_range_local.s: Ditto.
This commit is contained in:
122
gold/arm.cc
122
gold/arm.cc
@@ -1064,6 +1064,11 @@ class Arm_exidx_cantunwind : public Output_section_data
|
||||
this->do_fixed_endian_write<false>(of);
|
||||
}
|
||||
|
||||
// Write to a map file.
|
||||
void
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _("** ARM cantunwind")); }
|
||||
|
||||
private:
|
||||
// Implement do_write for a given endianness.
|
||||
template<bool big_endian>
|
||||
@@ -1636,7 +1641,7 @@ class Arm_relobj : public Sized_relobj<32, big_endian>
|
||||
|
||||
void
|
||||
do_relocate_sections(const Symbol_table* symtab, const Layout* layout,
|
||||
const unsigned char* pshdrs,
|
||||
const unsigned char* pshdrs, Output_file* of,
|
||||
typename Sized_relobj<32, big_endian>::Views* pivews);
|
||||
|
||||
// Read the symbol information.
|
||||
@@ -6351,11 +6356,12 @@ Arm_relobj<big_endian>::do_relocate_sections(
|
||||
const Symbol_table* symtab,
|
||||
const Layout* layout,
|
||||
const unsigned char* pshdrs,
|
||||
Output_file* of,
|
||||
typename Sized_relobj<32, big_endian>::Views* pviews)
|
||||
{
|
||||
// Call parent to relocate sections.
|
||||
Sized_relobj<32, big_endian>::do_relocate_sections(symtab, layout, pshdrs,
|
||||
pviews);
|
||||
of, pviews);
|
||||
|
||||
// We do not generate stubs if doing a relocatable link.
|
||||
if (parameters->options().relocatable())
|
||||
@@ -10944,6 +10950,8 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
|
||||
|
||||
Symbol_value<32> symval;
|
||||
const Symbol_value<32> *psymval;
|
||||
bool is_defined_in_discarded_section;
|
||||
unsigned int shndx;
|
||||
if (r_sym < local_count)
|
||||
{
|
||||
sym = NULL;
|
||||
@@ -10955,45 +10963,53 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
|
||||
// counterpart in the kept section. The symbol must not
|
||||
// correspond to a section we are folding.
|
||||
bool is_ordinary;
|
||||
unsigned int shndx = psymval->input_shndx(&is_ordinary);
|
||||
if (is_ordinary
|
||||
&& shndx != elfcpp::SHN_UNDEF
|
||||
&& !arm_object->is_section_included(shndx)
|
||||
&& !(relinfo->symtab->is_section_folded(arm_object, shndx)))
|
||||
shndx = psymval->input_shndx(&is_ordinary);
|
||||
is_defined_in_discarded_section =
|
||||
(is_ordinary
|
||||
&& shndx != elfcpp::SHN_UNDEF
|
||||
&& !arm_object->is_section_included(shndx)
|
||||
&& !relinfo->symtab->is_section_folded(arm_object, shndx));
|
||||
|
||||
// We need to compute the would-be final value of this local
|
||||
// symbol.
|
||||
if (!is_defined_in_discarded_section)
|
||||
{
|
||||
if (comdat_behavior == CB_UNDETERMINED)
|
||||
{
|
||||
std::string name =
|
||||
arm_object->section_name(relinfo->data_shndx);
|
||||
comdat_behavior = get_comdat_behavior(name.c_str());
|
||||
}
|
||||
if (comdat_behavior == CB_PRETEND)
|
||||
{
|
||||
bool found;
|
||||
typename elfcpp::Elf_types<32>::Elf_Addr value =
|
||||
arm_object->map_to_kept_section(shndx, &found);
|
||||
if (found)
|
||||
symval.set_output_value(value + psymval->input_value());
|
||||
else
|
||||
symval.set_output_value(0);
|
||||
}
|
||||
typedef Sized_relobj<32, big_endian> ObjType;
|
||||
typename ObjType::Compute_final_local_value_status status =
|
||||
arm_object->compute_final_local_value(r_sym, psymval, &symval,
|
||||
relinfo->symtab);
|
||||
if (status == ObjType::CFLV_OK)
|
||||
{
|
||||
// Currently we cannot handle a branch to a target in
|
||||
// a merged section. If this is the case, issue an error
|
||||
// and also free the merge symbol value.
|
||||
if (!symval.has_output_value())
|
||||
{
|
||||
const std::string& section_name =
|
||||
arm_object->section_name(shndx);
|
||||
arm_object->error(_("cannot handle branch to local %u "
|
||||
"in a merged section %s"),
|
||||
r_sym, section_name.c_str());
|
||||
}
|
||||
psymval = &symval;
|
||||
}
|
||||
else
|
||||
{
|
||||
symval.set_output_value(0);
|
||||
}
|
||||
symval.set_no_output_symtab_entry();
|
||||
psymval = &symval;
|
||||
{
|
||||
// We cannot determine the final value.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const Symbol* gsym = arm_object->global_symbol(r_sym);
|
||||
const Symbol* gsym;
|
||||
gsym = arm_object->global_symbol(r_sym);
|
||||
gold_assert(gsym != NULL);
|
||||
if (gsym->is_forwarder())
|
||||
gsym = relinfo->symtab->resolve_forwards(gsym);
|
||||
|
||||
sym = static_cast<const Sized_symbol<32>*>(gsym);
|
||||
if (sym->has_symtab_index())
|
||||
if (sym->has_symtab_index() && sym->symtab_index() != -1U)
|
||||
symval.set_output_symtab_index(sym->symtab_index());
|
||||
else
|
||||
symval.set_no_output_symtab_entry();
|
||||
@@ -11010,9 +11026,53 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
|
||||
// Skip this if the symbol has not output section.
|
||||
if (status == Symbol_table::CFVS_NO_OUTPUT_SECTION)
|
||||
continue;
|
||||
|
||||
symval.set_output_value(value);
|
||||
|
||||
if (gsym->type() == elfcpp::STT_TLS)
|
||||
symval.set_is_tls_symbol();
|
||||
else if (gsym->type() == elfcpp::STT_GNU_IFUNC)
|
||||
symval.set_is_ifunc_symbol();
|
||||
psymval = &symval;
|
||||
|
||||
is_defined_in_discarded_section =
|
||||
(gsym->is_defined_in_discarded_section()
|
||||
&& gsym->is_undefined());
|
||||
shndx = 0;
|
||||
}
|
||||
|
||||
Symbol_value<32> symval2;
|
||||
if (is_defined_in_discarded_section)
|
||||
{
|
||||
if (comdat_behavior == CB_UNDETERMINED)
|
||||
{
|
||||
std::string name = arm_object->section_name(relinfo->data_shndx);
|
||||
comdat_behavior = get_comdat_behavior(name.c_str());
|
||||
}
|
||||
if (comdat_behavior == CB_PRETEND)
|
||||
{
|
||||
// FIXME: This case does not work for global symbols.
|
||||
// We have no place to store the original section index.
|
||||
// Fortunately this does not matter for comdat sections,
|
||||
// only for sections explicitly discarded by a linker
|
||||
// script.
|
||||
bool found;
|
||||
typename elfcpp::Elf_types<32>::Elf_Addr value =
|
||||
arm_object->map_to_kept_section(shndx, &found);
|
||||
if (found)
|
||||
symval2.set_output_value(value + psymval->input_value());
|
||||
else
|
||||
symval2.set_output_value(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (comdat_behavior == CB_WARNING)
|
||||
gold_warning_at_location(relinfo, i, offset,
|
||||
_("relocation refers to discarded "
|
||||
"section"));
|
||||
symval2.set_output_value(0);
|
||||
}
|
||||
symval2.set_no_output_symtab_entry();
|
||||
psymval = &symval2;
|
||||
}
|
||||
|
||||
// If symbol is a section symbol, we don't know the actual type of
|
||||
|
||||
Reference in New Issue
Block a user