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:
parent
5e1617b13f
commit
aa98ff75dd
@ -1,3 +1,42 @@
|
||||
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.
|
||||
|
||||
2010-09-08 Rafael Espindola <espindola@google.com>
|
||||
|
||||
* script-sections.cc (Script_sections::add_memory_region): Convert
|
||||
|
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
|
||||
|
316
gold/object.cc
316
gold/object.cc
@ -1878,6 +1878,178 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool,
|
||||
this->output_local_dynsym_count_ = dyncount;
|
||||
}
|
||||
|
||||
// Compute the final value of a local symbol.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
typename Sized_relobj<size, big_endian>::Compute_final_local_value_status
|
||||
Sized_relobj<size, big_endian>::compute_final_local_value_internal(
|
||||
unsigned int r_sym,
|
||||
const Symbol_value<size>* lv_in,
|
||||
Symbol_value<size>* lv_out,
|
||||
bool relocatable,
|
||||
const Output_sections& out_sections,
|
||||
const std::vector<Address>& out_offsets,
|
||||
const Symbol_table* symtab)
|
||||
{
|
||||
// We are going to overwrite *LV_OUT, if it has a merged symbol value,
|
||||
// we may have a memory leak.
|
||||
gold_assert(lv_out->has_output_value());
|
||||
|
||||
bool is_ordinary;
|
||||
unsigned int shndx = lv_in->input_shndx(&is_ordinary);
|
||||
|
||||
// Set the output symbol value.
|
||||
|
||||
if (!is_ordinary)
|
||||
{
|
||||
if (shndx == elfcpp::SHN_ABS || Symbol::is_common_shndx(shndx))
|
||||
lv_out->set_output_value(lv_in->input_value());
|
||||
else
|
||||
{
|
||||
this->error(_("unknown section index %u for local symbol %u"),
|
||||
shndx, r_sym);
|
||||
lv_out->set_output_value(0);
|
||||
return This::CFLV_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shndx >= this->shnum())
|
||||
{
|
||||
this->error(_("local symbol %u section index %u out of range"),
|
||||
r_sym, shndx);
|
||||
lv_out->set_output_value(0);
|
||||
return This::CFLV_ERROR;
|
||||
}
|
||||
|
||||
Output_section* os = out_sections[shndx];
|
||||
Address secoffset = out_offsets[shndx];
|
||||
if (symtab->is_section_folded(this, shndx))
|
||||
{
|
||||
gold_assert(os == NULL && secoffset == invalid_address);
|
||||
// Get the os of the section it is folded onto.
|
||||
Section_id folded = symtab->icf()->get_folded_section(this,
|
||||
shndx);
|
||||
gold_assert(folded.first != NULL);
|
||||
Sized_relobj<size, big_endian>* folded_obj = reinterpret_cast
|
||||
<Sized_relobj<size, big_endian>*>(folded.first);
|
||||
os = folded_obj->output_section(folded.second);
|
||||
gold_assert(os != NULL);
|
||||
secoffset = folded_obj->get_output_section_offset(folded.second);
|
||||
|
||||
// This could be a relaxed input section.
|
||||
if (secoffset == invalid_address)
|
||||
{
|
||||
const Output_relaxed_input_section* relaxed_section =
|
||||
os->find_relaxed_input_section(folded_obj, folded.second);
|
||||
gold_assert(relaxed_section != NULL);
|
||||
secoffset = relaxed_section->address() - os->address();
|
||||
}
|
||||
}
|
||||
|
||||
if (os == NULL)
|
||||
{
|
||||
// This local symbol belongs to a section we are discarding.
|
||||
// In some cases when applying relocations later, we will
|
||||
// attempt to match it to the corresponding kept section,
|
||||
// so we leave the input value unchanged here.
|
||||
return This::CFLV_DISCARDED;
|
||||
}
|
||||
else if (secoffset == invalid_address)
|
||||
{
|
||||
uint64_t start;
|
||||
|
||||
// This is a SHF_MERGE section or one which otherwise
|
||||
// requires special handling.
|
||||
if (shndx == this->discarded_eh_frame_shndx_)
|
||||
{
|
||||
// This local symbol belongs to a discarded .eh_frame
|
||||
// section. Just treat it like the case in which
|
||||
// os == NULL above.
|
||||
gold_assert(this->has_eh_frame_);
|
||||
return This::CFLV_DISCARDED;
|
||||
}
|
||||
else if (!lv_in->is_section_symbol())
|
||||
{
|
||||
// This is not a section symbol. We can determine
|
||||
// the final value now.
|
||||
lv_out->set_output_value(
|
||||
os->output_address(this, shndx, lv_in->input_value()));
|
||||
}
|
||||
else if (!os->find_starting_output_address(this, shndx, &start))
|
||||
{
|
||||
// This is a section symbol, but apparently not one in a
|
||||
// merged section. First check to see if this is a relaxed
|
||||
// input section. If so, use its address. Otherwise just
|
||||
// use the start of the output section. This happens with
|
||||
// relocatable links when the input object has section
|
||||
// symbols for arbitrary non-merge sections.
|
||||
const Output_section_data* posd =
|
||||
os->find_relaxed_input_section(this, shndx);
|
||||
if (posd != NULL)
|
||||
{
|
||||
Address relocatable_link_adjustment =
|
||||
relocatable ? os->address() : 0;
|
||||
lv_out->set_output_value(posd->address()
|
||||
- relocatable_link_adjustment);
|
||||
}
|
||||
else
|
||||
lv_out->set_output_value(os->address());
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have to consider the addend to determine the
|
||||
// value to use in a relocation. START is the start
|
||||
// of this input section. If we are doing a relocatable
|
||||
// link, use offset from start output section instead of
|
||||
// address.
|
||||
Address adjusted_start =
|
||||
relocatable ? start - os->address() : start;
|
||||
Merged_symbol_value<size>* msv =
|
||||
new Merged_symbol_value<size>(lv_in->input_value(),
|
||||
adjusted_start);
|
||||
lv_out->set_merged_symbol_value(msv);
|
||||
}
|
||||
}
|
||||
else if (lv_in->is_tls_symbol())
|
||||
lv_out->set_output_value(os->tls_offset()
|
||||
+ secoffset
|
||||
+ lv_in->input_value());
|
||||
else
|
||||
lv_out->set_output_value((relocatable ? 0 : os->address())
|
||||
+ secoffset
|
||||
+ lv_in->input_value());
|
||||
}
|
||||
return This::CFLV_OK;
|
||||
}
|
||||
|
||||
// Compute final local symbol value. R_SYM is the index of a local
|
||||
// symbol in symbol table. LV points to a symbol value, which is
|
||||
// expected to hold the input value and to be over-written by the
|
||||
// final value. SYMTAB points to a symbol table. Some targets may want
|
||||
// to know would-be-finalized local symbol values in relaxation.
|
||||
// Hence we provide this method. Since this method updates *LV, a
|
||||
// callee should make a copy of the original local symbol value and
|
||||
// use the copy instead of modifying an object's local symbols before
|
||||
// everything is finalized. The caller should also free up any allocated
|
||||
// memory in the return value in *LV.
|
||||
template<int size, bool big_endian>
|
||||
typename Sized_relobj<size, big_endian>::Compute_final_local_value_status
|
||||
Sized_relobj<size, big_endian>::compute_final_local_value(
|
||||
unsigned int r_sym,
|
||||
const Symbol_value<size>* lv_in,
|
||||
Symbol_value<size>* lv_out,
|
||||
const Symbol_table* symtab)
|
||||
{
|
||||
// This is just a wrapper of compute_final_local_value_internal.
|
||||
const bool relocatable = parameters->options().relocatable();
|
||||
const Output_sections& out_sections(this->output_sections());
|
||||
const std::vector<Address>& out_offsets(this->section_offsets_);
|
||||
return this->compute_final_local_value_internal(r_sym, lv_in, lv_out,
|
||||
relocatable, out_sections,
|
||||
out_offsets, symtab);
|
||||
}
|
||||
|
||||
// Finalize the local symbols. Here we set the final value in
|
||||
// THIS->LOCAL_VALUES_ and set their output symbol table indexes.
|
||||
// This function is always called from a singleton thread. The actual
|
||||
@ -1897,141 +2069,31 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
|
||||
const bool relocatable = parameters->options().relocatable();
|
||||
const Output_sections& out_sections(this->output_sections());
|
||||
const std::vector<Address>& out_offsets(this->section_offsets_);
|
||||
unsigned int shnum = this->shnum();
|
||||
|
||||
for (unsigned int i = 1; i < loccount; ++i)
|
||||
{
|
||||
Symbol_value<size>& lv(this->local_values_[i]);
|
||||
Symbol_value<size>* lv = &this->local_values_[i];
|
||||
|
||||
bool is_ordinary;
|
||||
unsigned int shndx = lv.input_shndx(&is_ordinary);
|
||||
|
||||
// Set the output symbol value.
|
||||
|
||||
if (!is_ordinary)
|
||||
This::Compute_final_local_value_status cflv_status =
|
||||
this->compute_final_local_value_internal(i, lv, lv, relocatable,
|
||||
out_sections, out_offsets,
|
||||
symtab);
|
||||
switch (cflv_status)
|
||||
{
|
||||
if (shndx == elfcpp::SHN_ABS || Symbol::is_common_shndx(shndx))
|
||||
lv.set_output_value(lv.input_value());
|
||||
else
|
||||
case CFLV_OK:
|
||||
if (!lv->is_output_symtab_index_set())
|
||||
{
|
||||
this->error(_("unknown section index %u for local symbol %u"),
|
||||
shndx, i);
|
||||
lv.set_output_value(0);
|
||||
lv->set_output_symtab_index(index);
|
||||
++index;
|
||||
}
|
||||
break;
|
||||
case CFLV_DISCARDED:
|
||||
case CFLV_ERROR:
|
||||
// Do nothing.
|
||||
break;
|
||||
default:
|
||||
gold_unreachable();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shndx >= shnum)
|
||||
{
|
||||
this->error(_("local symbol %u section index %u out of range"),
|
||||
i, shndx);
|
||||
shndx = 0;
|
||||
}
|
||||
|
||||
Output_section* os = out_sections[shndx];
|
||||
Address secoffset = out_offsets[shndx];
|
||||
if (symtab->is_section_folded(this, shndx))
|
||||
{
|
||||
gold_assert(os == NULL && secoffset == invalid_address);
|
||||
// Get the os of the section it is folded onto.
|
||||
Section_id folded = symtab->icf()->get_folded_section(this,
|
||||
shndx);
|
||||
gold_assert(folded.first != NULL);
|
||||
Sized_relobj<size, big_endian>* folded_obj = reinterpret_cast
|
||||
<Sized_relobj<size, big_endian>*>(folded.first);
|
||||
os = folded_obj->output_section(folded.second);
|
||||
gold_assert(os != NULL);
|
||||
secoffset = folded_obj->get_output_section_offset(folded.second);
|
||||
|
||||
// This could be a relaxed input section.
|
||||
if (secoffset == invalid_address)
|
||||
{
|
||||
const Output_relaxed_input_section* relaxed_section =
|
||||
os->find_relaxed_input_section(folded_obj, folded.second);
|
||||
gold_assert(relaxed_section != NULL);
|
||||
secoffset = relaxed_section->address() - os->address();
|
||||
}
|
||||
}
|
||||
|
||||
if (os == NULL)
|
||||
{
|
||||
// This local symbol belongs to a section we are discarding.
|
||||
// In some cases when applying relocations later, we will
|
||||
// attempt to match it to the corresponding kept section,
|
||||
// so we leave the input value unchanged here.
|
||||
continue;
|
||||
}
|
||||
else if (secoffset == invalid_address)
|
||||
{
|
||||
uint64_t start;
|
||||
|
||||
// This is a SHF_MERGE section or one which otherwise
|
||||
// requires special handling.
|
||||
if (shndx == this->discarded_eh_frame_shndx_)
|
||||
{
|
||||
// This local symbol belongs to a discarded .eh_frame
|
||||
// section. Just treat it like the case in which
|
||||
// os == NULL above.
|
||||
gold_assert(this->has_eh_frame_);
|
||||
continue;
|
||||
}
|
||||
else if (!lv.is_section_symbol())
|
||||
{
|
||||
// This is not a section symbol. We can determine
|
||||
// the final value now.
|
||||
lv.set_output_value(os->output_address(this, shndx,
|
||||
lv.input_value()));
|
||||
}
|
||||
else if (!os->find_starting_output_address(this, shndx, &start))
|
||||
{
|
||||
// This is a section symbol, but apparently not one in a
|
||||
// merged section. First check to see if this is a relaxed
|
||||
// input section. If so, use its address. Otherwise just
|
||||
// use the start of the output section. This happens with
|
||||
// relocatable links when the input object has section
|
||||
// symbols for arbitrary non-merge sections.
|
||||
const Output_section_data* posd =
|
||||
os->find_relaxed_input_section(this, shndx);
|
||||
if (posd != NULL)
|
||||
{
|
||||
Address relocatable_link_adjustment =
|
||||
relocatable ? os->address() : 0;
|
||||
lv.set_output_value(posd->address()
|
||||
- relocatable_link_adjustment);
|
||||
}
|
||||
else
|
||||
lv.set_output_value(os->address());
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have to consider the addend to determine the
|
||||
// value to use in a relocation. START is the start
|
||||
// of this input section. If we are doing a relocatable
|
||||
// link, use offset from start output section instead of
|
||||
// address.
|
||||
Address adjusted_start =
|
||||
relocatable ? start - os->address() : start;
|
||||
Merged_symbol_value<size>* msv =
|
||||
new Merged_symbol_value<size>(lv.input_value(),
|
||||
adjusted_start);
|
||||
lv.set_merged_symbol_value(msv);
|
||||
}
|
||||
}
|
||||
else if (lv.is_tls_symbol())
|
||||
lv.set_output_value(os->tls_offset()
|
||||
+ secoffset
|
||||
+ lv.input_value());
|
||||
else
|
||||
lv.set_output_value((relocatable ? 0 : os->address())
|
||||
+ secoffset
|
||||
+ lv.input_value());
|
||||
}
|
||||
|
||||
if (!lv.is_output_symtab_index_set())
|
||||
{
|
||||
lv.set_output_symtab_index(index);
|
||||
++index;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
@ -1155,6 +1155,12 @@ class Symbol_value
|
||||
is_tls_symbol_(false), is_ifunc_symbol_(false), has_output_value_(true)
|
||||
{ this->u_.value = 0; }
|
||||
|
||||
~Symbol_value()
|
||||
{
|
||||
if (!this->has_output_value_)
|
||||
delete this->u_.merged_symbol_value;
|
||||
}
|
||||
|
||||
// Get the value of this symbol. OBJECT is the object in which this
|
||||
// symbol is defined, and ADDEND is an addend to add to the value.
|
||||
template<bool big_endian>
|
||||
@ -1380,6 +1386,11 @@ class Symbol_value
|
||||
is_ifunc_symbol() const
|
||||
{ return this->is_ifunc_symbol_; }
|
||||
|
||||
// Return true if this has output value.
|
||||
bool
|
||||
has_output_value() const
|
||||
{ return this->has_output_value_; }
|
||||
|
||||
private:
|
||||
// The index of this local symbol in the output symbol table. This
|
||||
// will be 0 if no value has been assigned yet, and the symbol may
|
||||
@ -1558,6 +1569,16 @@ class Sized_relobj : public Relobj
|
||||
|
||||
static const Address invalid_address = static_cast<Address>(0) - 1;
|
||||
|
||||
enum Compute_final_local_value_status
|
||||
{
|
||||
// No error.
|
||||
CFLV_OK,
|
||||
// An error occurred.
|
||||
CFLV_ERROR,
|
||||
// The local symbol has no output section.
|
||||
CFLV_DISCARDED
|
||||
};
|
||||
|
||||
Sized_relobj(const std::string& name, Input_file* input_file, off_t offset,
|
||||
const typename elfcpp::Ehdr<size, big_endian>&);
|
||||
|
||||
@ -1742,6 +1763,22 @@ class Sized_relobj : public Relobj
|
||||
Address
|
||||
map_to_kept_section(unsigned int shndx, bool* found) const;
|
||||
|
||||
// Compute final local symbol value. R_SYM is the local symbol index.
|
||||
// LV_IN points to a local symbol value containing the input value.
|
||||
// LV_OUT points to a local symbol value storing the final output value,
|
||||
// which must not be a merged symbol value since before calling this
|
||||
// method to avoid memory leak. SYMTAB points to a symbol table.
|
||||
//
|
||||
// The method returns a status code at return. If the return status is
|
||||
// CFLV_OK, *LV_OUT contains the final value. If the return status is
|
||||
// CFLV_ERROR, *LV_OUT is 0. If the return status is CFLV_DISCARDED,
|
||||
// *LV_OUT is not modified.
|
||||
Compute_final_local_value_status
|
||||
compute_final_local_value(unsigned int r_sym,
|
||||
const Symbol_value<size>* lv_in,
|
||||
Symbol_value<size>* lv_out,
|
||||
const Symbol_table* symtab);
|
||||
|
||||
protected:
|
||||
// Set up.
|
||||
virtual void
|
||||
@ -2162,6 +2199,28 @@ class Sized_relobj : public Relobj
|
||||
return true;
|
||||
}
|
||||
|
||||
// Compute final local symbol value. R_SYM is the local symbol index.
|
||||
// LV_IN points to a local symbol value containing the input value.
|
||||
// LV_OUT points to a local symbol value storing the final output value,
|
||||
// which must not be a merged symbol value since before calling this
|
||||
// method to avoid memory leak. RELOCATABLE indicates whether we are
|
||||
// linking a relocatable output. OUT_SECTIONS is an array of output
|
||||
// sections. OUT_OFFSETS is an array of offsets of the sections. SYMTAB
|
||||
// points to a symbol table.
|
||||
//
|
||||
// The method returns a status code at return. If the return status is
|
||||
// CFLV_OK, *LV_OUT contains the final value. If the return status is
|
||||
// CFLV_ERROR, *LV_OUT is 0. If the return status is CFLV_DISCARDED,
|
||||
// *LV_OUT is not modified.
|
||||
inline Compute_final_local_value_status
|
||||
compute_final_local_value_internal(unsigned int r_sym,
|
||||
const Symbol_value<size>* lv_in,
|
||||
Symbol_value<size>* lv_out,
|
||||
bool relocatable,
|
||||
const Output_sections& out_sections,
|
||||
const std::vector<Address>& out_offsets,
|
||||
const Symbol_table* symtab);
|
||||
|
||||
// The GOT offsets of local symbols. This map also stores GOT offsets
|
||||
// for tp-relative offsets for TLS symbols.
|
||||
typedef Unordered_map<unsigned int, Got_offset_list*> Local_got_offsets;
|
||||
|
@ -1885,12 +1885,13 @@ arm_abs_global.stdout: arm_abs_global
|
||||
|
||||
MOSTLYCLEANFILES += arm_abs_global
|
||||
|
||||
check_SCRIPTS += arm_branch_in_range.sh
|
||||
check_SCRIPTS += arm_branch_in_range.sh arm_branch_out_of_range.sh
|
||||
check_DATA += arm_bl_in_range.stdout arm_bl_out_of_range.stdout \
|
||||
thumb_bl_in_range.stdout thumb_bl_out_of_range.stdout \
|
||||
thumb2_bl_in_range.stdout thumb2_bl_out_of_range.stdout \
|
||||
thumb_blx_in_range.stdout thumb_blx_out_of_range.stdout \
|
||||
thumb2_blx_in_range.stdout thumb2_blx_out_of_range.stdout
|
||||
thumb2_blx_in_range.stdout thumb2_blx_out_of_range.stdout \
|
||||
thumb_bl_out_of_range_local.stdout
|
||||
|
||||
arm_bl_in_range.stdout: arm_bl_in_range
|
||||
$(TEST_OBJDUMP) -D $< > $@
|
||||
@ -1982,10 +1983,19 @@ thumb2_blx_out_of_range: thumb2_blx_out_of_range.o ../ld-new
|
||||
thumb2_blx_out_of_range.o: thumb_blx_out_of_range.s
|
||||
$(TEST_AS) -o $@ -march=armv7-a $<
|
||||
|
||||
thumb_bl_out_of_range_local.stdout: thumb_bl_out_of_range_local
|
||||
$(TEST_OBJDUMP) -D $< > $@
|
||||
|
||||
thumb_bl_out_of_range_local: thumb_bl_out_of_range_local.o ../ld-new
|
||||
../ld-new -T $(srcdir)/thumb_branch_range.t -o $@ $<
|
||||
|
||||
thumb_bl_out_of_range_local.o: thumb_bl_out_of_range_local.s
|
||||
$(TEST_AS) -o $@ -march=armv5te $<
|
||||
|
||||
MOSTLYCLEANFILES += arm_bl_in_range arm_bl_out_of_range thumb_bl_in_range \
|
||||
thumb_bl_out_of_range thumb2_bl_in_range thumb2_bl_out_of_range \
|
||||
thumb_blx_in_range thumb_blx_out_of_range thumb2_blx_in_range \
|
||||
thumb2_blx_out_of_range
|
||||
thumb2_blx_out_of_range thumb_bl_out_of_range_local
|
||||
|
||||
check_SCRIPTS += arm_fix_v4bx.sh
|
||||
check_DATA += arm_fix_v4bx.stdout arm_fix_v4bx_interworking.stdout \
|
||||
@ -2050,4 +2060,68 @@ arm_attr_merge_7b.o: arm_attr_merge_7b.s
|
||||
|
||||
MOSTLYCLEANFILES += arm_attr_merge_6 arm_attr_merge_6r arm_attr_merge_7
|
||||
|
||||
# Cortex-A8 workaround test.
|
||||
|
||||
check_SCRIPTS += arm_cortex_a8.sh
|
||||
check_DATA += arm_cortex_a8_b_cond.stdout arm_cortex_a8_b.stdout \
|
||||
arm_cortex_a8_bl.stdout arm_cortex_a8_blx.stdout \
|
||||
arm_cortex_a8_local.stdout arm_cortex_a8_local_reloc.stdout
|
||||
|
||||
arm_cortex_a8_b_cond.stdout: arm_cortex_a8_b_cond
|
||||
$(TEST_OBJDUMP) -D -j.text $< > $@
|
||||
|
||||
arm_cortex_a8_b_cond: arm_cortex_a8_b_cond.o ../ld-new
|
||||
../ld-new -o $@ $<
|
||||
|
||||
arm_cortex_a8_b_cond.o: arm_cortex_a8_b_cond.s
|
||||
$(TEST_AS) -o $@ $<
|
||||
|
||||
arm_cortex_a8_b.stdout: arm_cortex_a8_b
|
||||
$(TEST_OBJDUMP) -D -j.text $< > $@
|
||||
|
||||
arm_cortex_a8_b: arm_cortex_a8_b.o ../ld-new
|
||||
../ld-new --fix-cortex-a8 -o $@ $<
|
||||
|
||||
arm_cortex_a8_b.o: arm_cortex_a8_b.s
|
||||
$(TEST_AS) -o $@ $<
|
||||
|
||||
arm_cortex_a8_bl.stdout: arm_cortex_a8_bl
|
||||
$(TEST_OBJDUMP) -D -j.text $< > $@
|
||||
|
||||
arm_cortex_a8_bl: arm_cortex_a8_bl.o ../ld-new
|
||||
../ld-new -o $@ $<
|
||||
|
||||
arm_cortex_a8_bl.o: arm_cortex_a8_bl.s
|
||||
$(TEST_AS) -o $@ $<
|
||||
|
||||
arm_cortex_a8_blx.stdout: arm_cortex_a8_blx
|
||||
$(TEST_OBJDUMP) -D -j.text $< > $@
|
||||
|
||||
arm_cortex_a8_blx: arm_cortex_a8_blx.o ../ld-new
|
||||
../ld-new -o $@ $<
|
||||
|
||||
arm_cortex_a8_blx.o: arm_cortex_a8_blx.s
|
||||
$(TEST_AS) -o $@ $<
|
||||
|
||||
arm_cortex_a8_local.stdout: arm_cortex_a8_local
|
||||
$(TEST_OBJDUMP) -D -j.text $< > $@
|
||||
|
||||
arm_cortex_a8_local: arm_cortex_a8_local.o ../ld-new
|
||||
../ld-new -o $@ $<
|
||||
|
||||
arm_cortex_a8_local.o: arm_cortex_a8_local.s
|
||||
$(TEST_AS) -o $@ $<
|
||||
|
||||
arm_cortex_a8_local_reloc.stdout: arm_cortex_a8_local_reloc
|
||||
$(TEST_OBJDUMP) -D -j.text $< > $@
|
||||
|
||||
arm_cortex_a8_local_reloc: arm_cortex_a8_local_reloc.o ../ld-new
|
||||
../ld-new -o $@ $<
|
||||
|
||||
arm_cortex_a8_local_reloc.o: arm_cortex_a8_local_reloc.s
|
||||
$(TEST_AS) -o $@ $<
|
||||
|
||||
MOSTLYCLEANFILES += arm_cortex_a8_b_cond arm_cortex_a8_b arm_cortex_a8_bl \
|
||||
arm_cortex_a8_blx arm_cortex_a8_local arm_cortex_a8_local_reloc
|
||||
|
||||
endif DEFAULT_TARGET_ARM
|
||||
|
@ -492,9 +492,13 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
|
||||
@DEFAULT_TARGET_X86_64_TRUE@am__append_39 = split_x86_64_1 split_x86_64_2 split_x86_64_3 \
|
||||
@DEFAULT_TARGET_X86_64_TRUE@ split_x86_64_4 split_x86_64_r
|
||||
|
||||
|
||||
# Cortex-A8 workaround test.
|
||||
@DEFAULT_TARGET_ARM_TRUE@am__append_40 = arm_abs_global.sh \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_branch_in_range.sh \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_fix_v4bx.sh arm_attr_merge.sh
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_branch_out_of_range.sh \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_fix_v4bx.sh arm_attr_merge.sh \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_cortex_a8.sh
|
||||
@DEFAULT_TARGET_ARM_TRUE@am__append_41 = arm_abs_global.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_bl_in_range.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_bl_out_of_range.stdout \
|
||||
@ -506,12 +510,19 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ thumb_blx_out_of_range.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ thumb2_blx_in_range.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ thumb2_blx_out_of_range.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ thumb_bl_out_of_range_local.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_fix_v4bx.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_fix_v4bx_interworking.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_no_fix_v4bx.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_attr_merge_6.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_attr_merge_6r.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_attr_merge_7.stdout
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_attr_merge_7.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_cortex_a8_b_cond.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_cortex_a8_b.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_cortex_a8_bl.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_cortex_a8_blx.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_cortex_a8_local.stdout \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_cortex_a8_local_reloc.stdout
|
||||
@DEFAULT_TARGET_ARM_TRUE@am__append_42 = arm_abs_global \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_bl_in_range arm_bl_out_of_range \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ thumb_bl_in_range \
|
||||
@ -521,10 +532,16 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ thumb_blx_in_range \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ thumb_blx_out_of_range \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ thumb2_blx_in_range \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ thumb2_blx_out_of_range arm_fix_v4bx \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ thumb2_blx_out_of_range \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ thumb_bl_out_of_range_local \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_fix_v4bx \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_fix_v4bx_interworking \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_no_fix_v4bx arm_attr_merge_6 \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_attr_merge_6r arm_attr_merge_7
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_attr_merge_6r arm_attr_merge_7 \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_cortex_a8_b_cond arm_cortex_a8_b \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_cortex_a8_bl arm_cortex_a8_blx \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_cortex_a8_local \
|
||||
@DEFAULT_TARGET_ARM_TRUE@ arm_cortex_a8_local_reloc
|
||||
subdir = testsuite
|
||||
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
@ -3297,10 +3314,14 @@ arm_abs_global.sh.log: arm_abs_global.sh
|
||||
@p='arm_abs_global.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
|
||||
arm_branch_in_range.sh.log: arm_branch_in_range.sh
|
||||
@p='arm_branch_in_range.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
|
||||
arm_branch_out_of_range.sh.log: arm_branch_out_of_range.sh
|
||||
@p='arm_branch_out_of_range.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
|
||||
arm_fix_v4bx.sh.log: arm_fix_v4bx.sh
|
||||
@p='arm_fix_v4bx.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
|
||||
arm_attr_merge.sh.log: arm_attr_merge.sh
|
||||
@p='arm_attr_merge.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
|
||||
arm_cortex_a8.sh.log: arm_cortex_a8.sh
|
||||
@p='arm_cortex_a8.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
|
||||
object_unittest.log: object_unittest$(EXEEXT)
|
||||
@p='object_unittest$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
|
||||
binary_unittest.log: binary_unittest$(EXEEXT)
|
||||
@ -4641,6 +4662,15 @@ uninstall-am:
|
||||
@DEFAULT_TARGET_ARM_TRUE@thumb2_blx_out_of_range.o: thumb_blx_out_of_range.s
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ -march=armv7-a $<
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@thumb_bl_out_of_range_local.stdout: thumb_bl_out_of_range_local
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D $< > $@
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@thumb_bl_out_of_range_local: thumb_bl_out_of_range_local.o ../ld-new
|
||||
@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -T $(srcdir)/thumb_branch_range.t -o $@ $<
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@thumb_bl_out_of_range_local.o: thumb_bl_out_of_range_local.s
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ -march=armv5te $<
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_fix_v4bx.stdout: arm_fix_v4bx
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D -j.text $< > $@
|
||||
|
||||
@ -4692,6 +4722,60 @@ uninstall-am:
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_attr_merge_7b.o: arm_attr_merge_7b.s
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ $<
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_b_cond.stdout: arm_cortex_a8_b_cond
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D -j.text $< > $@
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_b_cond: arm_cortex_a8_b_cond.o ../ld-new
|
||||
@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -o $@ $<
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_b_cond.o: arm_cortex_a8_b_cond.s
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ $<
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_b.stdout: arm_cortex_a8_b
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D -j.text $< > $@
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_b: arm_cortex_a8_b.o ../ld-new
|
||||
@DEFAULT_TARGET_ARM_TRUE@ ../ld-new --fix-cortex-a8 -o $@ $<
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_b.o: arm_cortex_a8_b.s
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ $<
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_bl.stdout: arm_cortex_a8_bl
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D -j.text $< > $@
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_bl: arm_cortex_a8_bl.o ../ld-new
|
||||
@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -o $@ $<
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_bl.o: arm_cortex_a8_bl.s
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ $<
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_blx.stdout: arm_cortex_a8_blx
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D -j.text $< > $@
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_blx: arm_cortex_a8_blx.o ../ld-new
|
||||
@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -o $@ $<
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_blx.o: arm_cortex_a8_blx.s
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ $<
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_local.stdout: arm_cortex_a8_local
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D -j.text $< > $@
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_local: arm_cortex_a8_local.o ../ld-new
|
||||
@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -o $@ $<
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_local.o: arm_cortex_a8_local.s
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ $<
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_local_reloc.stdout: arm_cortex_a8_local_reloc
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D -j.text $< > $@
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_local_reloc: arm_cortex_a8_local_reloc.o ../ld-new
|
||||
@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -o $@ $<
|
||||
|
||||
@DEFAULT_TARGET_ARM_TRUE@arm_cortex_a8_local_reloc.o: arm_cortex_a8_local_reloc.s
|
||||
@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ $<
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
|
@ -15,7 +15,8 @@ _backward_target:
|
||||
.size _backward_target, .-_backward_target
|
||||
|
||||
.text
|
||||
.align 2
|
||||
# Use 256-byte alignment so that we know where the stubs start.
|
||||
.align 8
|
||||
|
||||
# Define _start so that linker does not complain.
|
||||
.global _start
|
||||
|
123
gold/testsuite/arm_branch_out_of_range.sh
Executable file
123
gold/testsuite/arm_branch_out_of_range.sh
Executable file
@ -0,0 +1,123 @@
|
||||
#!/bin/sh
|
||||
|
||||
# arm_branch_out_of_range.sh -- test ARM/THUMB/THUMB branch instructions whose
|
||||
# targets are just out of the branch range limits.
|
||||
|
||||
# Copyright 2010 Free Software Foundation, Inc.
|
||||
# Written by Doug Kwan <dougkwan@google.com>
|
||||
|
||||
# This file is part of gold.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
|
||||
# This file goes with the assembler source files arm_bl_out_of_range.s,
|
||||
# thumb_bl_out_of_range.s and thumb_bl_out_of_range_local.s that are assembled
|
||||
# and linked to check that branches whose target are just out of the branch
|
||||
# range limits are handle correctly.
|
||||
|
||||
check()
|
||||
{
|
||||
file=$1
|
||||
pattern=$2
|
||||
|
||||
found=`grep "$pattern" $file`
|
||||
if test -z "$found"; then
|
||||
echo "pattern \"$pattern\" not found in file $file."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# This is a bit crude. Also, there are tabs in the grep patterns.
|
||||
|
||||
check arm_bl_out_of_range.stdout \
|
||||
" 4000004: eb00003d bl 4000100 <.*>"
|
||||
check arm_bl_out_of_range.stdout \
|
||||
" 4000008: eb00003e bl 4000108 <.*>"
|
||||
check arm_bl_out_of_range.stdout \
|
||||
" 4000100: e51ff004 ldr pc, \[pc, #-4\]"
|
||||
check arm_bl_out_of_range.stdout \
|
||||
" 4000104: 02000008 "
|
||||
check arm_bl_out_of_range.stdout \
|
||||
" 4000108: e51ff004 ldr pc, \[pc, #-4\]"
|
||||
check arm_bl_out_of_range.stdout \
|
||||
" 400010c: 06000010 "
|
||||
|
||||
check thumb_bl_out_of_range.stdout \
|
||||
" 800004: f000 e87c blx 800100 <.*>"
|
||||
check thumb_bl_out_of_range.stdout \
|
||||
" 800008: f000 e87e blx 800108 <.*>"
|
||||
check thumb_bl_out_of_range.stdout \
|
||||
" 800100: e51ff004 ldr pc, \[pc, #-4\]"
|
||||
check thumb_bl_out_of_range.stdout \
|
||||
" 800104: 00400007 "
|
||||
check thumb_bl_out_of_range.stdout \
|
||||
" 800108: e51ff004 ldr pc, \[pc, #-4\]"
|
||||
check thumb_bl_out_of_range.stdout \
|
||||
" 80010c: 00c0000d "
|
||||
|
||||
check thumb_blx_out_of_range.stdout \
|
||||
" 800004: f000 e87c blx 800100 <.*>"
|
||||
check thumb_blx_out_of_range.stdout \
|
||||
" 80000a: f000 e87e blx 800108 <.*>"
|
||||
check thumb_blx_out_of_range.stdout \
|
||||
" 800100: e51ff004 ldr pc, \[pc, #-4\]"
|
||||
check thumb_blx_out_of_range.stdout \
|
||||
" 800104: 00400006 "
|
||||
check thumb_blx_out_of_range.stdout \
|
||||
" 800108: e51ff004 ldr pc, \[pc, #-4\]"
|
||||
check thumb_blx_out_of_range.stdout \
|
||||
" 80010c: 00c0000c "
|
||||
|
||||
check thumb_bl_out_of_range_local.stdout \
|
||||
" 800004: f000 e87c blx 800100 <.*>"
|
||||
check thumb_bl_out_of_range_local.stdout \
|
||||
" 800008: f000 e87e blx 800108 <.*>"
|
||||
check thumb_bl_out_of_range_local.stdout \
|
||||
" 800100: e51ff004 ldr pc, \[pc, #-4\]"
|
||||
check thumb_bl_out_of_range_local.stdout \
|
||||
" 800104: 00400007 "
|
||||
check thumb_bl_out_of_range_local.stdout \
|
||||
" 800108: e51ff004 ldr pc, \[pc, #-4\]"
|
||||
check thumb_bl_out_of_range_local.stdout \
|
||||
" 80010c: 00c0000d "
|
||||
|
||||
check thumb2_bl_out_of_range.stdout \
|
||||
" 2000004: f000 e87c blx 2000100 <.*>"
|
||||
check thumb2_bl_out_of_range.stdout \
|
||||
" 2000008: f000 e87e blx 2000108 <.*>"
|
||||
check thumb2_bl_out_of_range.stdout \
|
||||
" 2000100: e51ff004 ldr pc, \[pc, #-4\]"
|
||||
check thumb2_bl_out_of_range.stdout \
|
||||
" 2000104: 01000007 "
|
||||
check thumb2_bl_out_of_range.stdout \
|
||||
" 2000108: e51ff004 ldr pc, \[pc, #-4\]"
|
||||
check thumb2_bl_out_of_range.stdout \
|
||||
" 200010c: 0300000d "
|
||||
|
||||
check thumb2_blx_out_of_range.stdout \
|
||||
" 2000004: f000 e87c blx 2000100 <.*>"
|
||||
check thumb2_blx_out_of_range.stdout \
|
||||
" 200000a: f000 e87e blx 2000108 <.*>"
|
||||
check thumb2_blx_out_of_range.stdout \
|
||||
" 2000100: e51ff004 ldr pc, \[pc, #-4\]"
|
||||
check thumb2_blx_out_of_range.stdout \
|
||||
" 2000104: 01000006 "
|
||||
check thumb2_blx_out_of_range.stdout \
|
||||
" 2000108: e51ff004 ldr pc, \[pc, #-4\]"
|
||||
check thumb2_blx_out_of_range.stdout \
|
||||
" 200010c: 0300000c "
|
||||
|
||||
exit 0
|
65
gold/testsuite/arm_cortex_a8.sh
Executable file
65
gold/testsuite/arm_cortex_a8.sh
Executable file
@ -0,0 +1,65 @@
|
||||
#!/bin/sh
|
||||
|
||||
# arm_cortex_a8.sh -- a test case for the Cortex-A8 workaround.
|
||||
|
||||
# Copyright 2010 Free Software Foundation, Inc.
|
||||
# Written by Doug Kwan <dougkwan@google.com>.
|
||||
|
||||
# This file is part of gold.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
|
||||
# This file goes with arm_v4bx.s, an ARM assembly source file constructed to
|
||||
# have test the handling of R_ARM_V4BX relocation.
|
||||
|
||||
check()
|
||||
{
|
||||
if ! grep -q "$2" "$1"
|
||||
then
|
||||
echo "Did not find expected instruction in $1:"
|
||||
echo " $2"
|
||||
echo ""
|
||||
echo "Actual instructions below:"
|
||||
cat "$1"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Test branch.
|
||||
check arm_cortex_a8_b.stdout ".*ffe: .* b.w .*000 <.*>"
|
||||
check arm_cortex_a8_b.stdout ".000: .* b.w .*100 <_func>"
|
||||
|
||||
# Test conditional branch.
|
||||
check arm_cortex_a8_b_cond.stdout ".*ffe: .* b.w .*000 <.*>"
|
||||
check arm_cortex_a8_b_cond.stdout ".000: .* beq.n .*006 <.*>"
|
||||
check arm_cortex_a8_b_cond.stdout ".002: .* b.w .*002 <.*>"
|
||||
check arm_cortex_a8_b_cond.stdout ".006: .* b.w .*100 <_func>"
|
||||
|
||||
# Test branch and link.
|
||||
check arm_cortex_a8_bl.stdout ".*ffe: .* bl .*000 <.*>"
|
||||
check arm_cortex_a8_bl.stdout ".000: .* b.w .*100 <_func>"
|
||||
|
||||
# Test blx
|
||||
check arm_cortex_a8_blx.stdout ".*ffe: .* blx .*000 <.*>"
|
||||
check arm_cortex_a8_blx.stdout ".000: .* b .*100 <_func>"
|
||||
|
||||
# Test a local branch without relocation.
|
||||
check arm_cortex_a8_local.stdout ".*ffe: .* b.w .*000 <.*>"
|
||||
check arm_cortex_a8_local.stdout ".000: .* bpl.n .*006 <.*>"
|
||||
check arm_cortex_a8_local.stdout ".002: .* b.w .*002 <.*>"
|
||||
check arm_cortex_a8_local.stdout ".006: .* b.w .*100 <.*>"
|
||||
|
||||
exit 0
|
30
gold/testsuite/arm_cortex_a8_b.s
Normal file
30
gold/testsuite/arm_cortex_a8_b.s
Normal file
@ -0,0 +1,30 @@
|
||||
.syntax unified
|
||||
.cpu cortex-a8
|
||||
|
||||
.text
|
||||
.align 12
|
||||
|
||||
_start:
|
||||
.type _start,%function
|
||||
bx lr
|
||||
.size _start,.-_start
|
||||
|
||||
.align 8
|
||||
.thumb
|
||||
.global _func
|
||||
.type _func,%function
|
||||
_func:
|
||||
bx lr
|
||||
.size _func,.-_func
|
||||
|
||||
.align 11
|
||||
.space 2042
|
||||
|
||||
.align 1
|
||||
.thumb
|
||||
.global _test
|
||||
.type _test,%function
|
||||
_test:
|
||||
add.w r0, r0, 0
|
||||
b.w _func
|
||||
.size _test,.-_test
|
30
gold/testsuite/arm_cortex_a8_b_cond.s
Normal file
30
gold/testsuite/arm_cortex_a8_b_cond.s
Normal file
@ -0,0 +1,30 @@
|
||||
.syntax unified
|
||||
.cpu cortex-a8
|
||||
|
||||
.text
|
||||
.align 12
|
||||
|
||||
_start:
|
||||
.type _start,%function
|
||||
bx lr
|
||||
.size _start,.-_start
|
||||
|
||||
.align 8
|
||||
.thumb
|
||||
.global _func
|
||||
.type _func,%function
|
||||
_func:
|
||||
bx lr
|
||||
.size _func,.-_func
|
||||
|
||||
.align 11
|
||||
.space 2042
|
||||
|
||||
.align 1
|
||||
.thumb
|
||||
.global _test
|
||||
.type _test,%function
|
||||
_test:
|
||||
add.w r0, r0, 0
|
||||
beq.w _func
|
||||
.size _test,.-_test
|
52
gold/testsuite/arm_cortex_a8_b_local.s
Normal file
52
gold/testsuite/arm_cortex_a8_b_local.s
Normal file
@ -0,0 +1,52 @@
|
||||
.syntax unified
|
||||
.cpu cortex-a8
|
||||
|
||||
.section .text.0, "x"
|
||||
.align 12
|
||||
|
||||
_start:
|
||||
.type _start,%function
|
||||
bx lr
|
||||
.size _start,.-_start
|
||||
|
||||
.section .text.1, "x"
|
||||
.align 11
|
||||
.thumb
|
||||
.type .Lfunc1,%function
|
||||
.Lfunc1:
|
||||
bx lr
|
||||
.size .Lfunc1,.-.Lfunc1
|
||||
|
||||
.section .text.2, "x"
|
||||
.align 11
|
||||
.space 2042
|
||||
|
||||
.align 1
|
||||
.thumb
|
||||
.global _test1
|
||||
.type _test1,%function
|
||||
_test1:
|
||||
add.w r0, r0, 0
|
||||
b.w .Lfunc1
|
||||
.size _test1,.-_test1
|
||||
|
||||
.align 8
|
||||
.thumb
|
||||
.type .Lfunc2,%function
|
||||
.Lfunc2:
|
||||
bx lr
|
||||
.size .Lfunc2,.-.Lfunc1
|
||||
|
||||
.align 11
|
||||
.space 2042
|
||||
|
||||
.align 1
|
||||
.thumb
|
||||
.global _test2
|
||||
.type _test2,%function
|
||||
_test2:
|
||||
add.w r0, r0, 0
|
||||
b.w .Lfunc2
|
||||
.size _test2,.-_test2
|
||||
|
||||
|
30
gold/testsuite/arm_cortex_a8_bl.s
Normal file
30
gold/testsuite/arm_cortex_a8_bl.s
Normal file
@ -0,0 +1,30 @@
|
||||
.syntax unified
|
||||
.cpu cortex-a8
|
||||
|
||||
.text
|
||||
.align 12
|
||||
|
||||
_start:
|
||||
.type _start,%function
|
||||
bx lr
|
||||
.size _start,.-_start
|
||||
|
||||
.align 8
|
||||
.thumb
|
||||
.global _func
|
||||
.type _func,%function
|
||||
_func:
|
||||
bx lr
|
||||
.size _func,.-_func
|
||||
|
||||
.align 11
|
||||
.space 2042
|
||||
|
||||
.align 1
|
||||
.thumb
|
||||
.global _test
|
||||
.type _test,%function
|
||||
_test:
|
||||
add.w r0, r0, 0
|
||||
bl _func
|
||||
.size _test,.-_test
|
33
gold/testsuite/arm_cortex_a8_blx.s
Normal file
33
gold/testsuite/arm_cortex_a8_blx.s
Normal file
@ -0,0 +1,33 @@
|
||||
.syntax unified
|
||||
.cpu cortex-a8
|
||||
|
||||
.text
|
||||
.align 12
|
||||
|
||||
_start:
|
||||
.type _start,%function
|
||||
bx lr
|
||||
.size _start,.-_start
|
||||
|
||||
.align 8
|
||||
.global _func
|
||||
.type _func,%function
|
||||
_func:
|
||||
bx lr
|
||||
.size _func,.-_func
|
||||
|
||||
.align 11
|
||||
.space 2042
|
||||
|
||||
.align 1
|
||||
.thumb
|
||||
.global _test
|
||||
.type _test,%function
|
||||
_test:
|
||||
add.w r0, r0, 0
|
||||
blx _func
|
||||
.size _test,.-_test
|
||||
|
||||
# We have no mapping symbols for stubs. This make the disassembler
|
||||
# list the stub correctly in ARM mode.
|
||||
.arm
|
29
gold/testsuite/arm_cortex_a8_local.s
Normal file
29
gold/testsuite/arm_cortex_a8_local.s
Normal file
@ -0,0 +1,29 @@
|
||||
.syntax unified
|
||||
.cpu cortex-a8
|
||||
|
||||
.text
|
||||
.align 12
|
||||
|
||||
_start:
|
||||
.type _start,%function
|
||||
bx lr
|
||||
.size _start,.-_start
|
||||
|
||||
.align 8
|
||||
.thumb
|
||||
.type .Lfunc,%function
|
||||
.Lfunc:
|
||||
bx lr
|
||||
.size .Lfunc,.-.Lfunc
|
||||
|
||||
.align 11
|
||||
.space 2042
|
||||
|
||||
.align 1
|
||||
.thumb
|
||||
.global _test
|
||||
.type _test,%function
|
||||
_test:
|
||||
add.w r0, r0, 0
|
||||
bpl.w .Lfunc
|
||||
.size _test,.-_test
|
31
gold/testsuite/arm_cortex_a8_local_reloc.s
Normal file
31
gold/testsuite/arm_cortex_a8_local_reloc.s
Normal file
@ -0,0 +1,31 @@
|
||||
.syntax unified
|
||||
.cpu cortex-a8
|
||||
|
||||
.section .text.0, "x"
|
||||
.align 12
|
||||
|
||||
_start:
|
||||
.type _start,%function
|
||||
bx lr
|
||||
.size _start,.-_start
|
||||
|
||||
.section .text.1, "x"
|
||||
.align 11
|
||||
.thumb
|
||||
.type .Lfunc,%function
|
||||
.Lfunc:
|
||||
bx lr
|
||||
.size .Lfunc,.-.Lfunc
|
||||
|
||||
.section .text.2, "x"
|
||||
.align 11
|
||||
.space 2042
|
||||
|
||||
.align 1
|
||||
.thumb
|
||||
.global _test
|
||||
.type _test,%function
|
||||
_test:
|
||||
add.w r0, r0, 0
|
||||
b.w .Lfunc
|
||||
.size _test,.-_test
|
@ -16,6 +16,8 @@ _backward_target:
|
||||
.size _backward_target, .-_backward_target
|
||||
|
||||
.text
|
||||
# Use 256-byte alignment so that we know where the stubs start.
|
||||
.align 8
|
||||
|
||||
# Define _start so that linker does not complain.
|
||||
.global _start
|
||||
@ -42,6 +44,10 @@ _forward_test:
|
||||
bl _forward_target
|
||||
.size _forward_test, .-_forward_test
|
||||
|
||||
# switch back to ARM mode so that stubs are disassembled correctly.
|
||||
.code 32
|
||||
nop
|
||||
|
||||
.section .text.post,"x"
|
||||
|
||||
# Add padding so that target is just out of branch range.
|
||||
|
61
gold/testsuite/thumb_bl_out_of_range_local.s
Normal file
61
gold/testsuite/thumb_bl_out_of_range_local.s
Normal file
@ -0,0 +1,61 @@
|
||||
# thumb_bl_out_of_range_local.s
|
||||
# Test THUMB/THUMB-2 bl instructions just out of the branch range limits
|
||||
# and with local branch targets.
|
||||
.syntax unified
|
||||
|
||||
.section .text.pre,"x"
|
||||
|
||||
# Add padding so that target is just output of branch range.
|
||||
.space 6
|
||||
|
||||
.code 16
|
||||
.thumb_func
|
||||
.type .Lbackward_target, %function
|
||||
.Lbackward_target:
|
||||
bx lr
|
||||
.size .Lbackward_target, .-.Lbackward_target
|
||||
|
||||
.text
|
||||
# Use 256-byte alignment so that we know where the stubs start.
|
||||
.align 8
|
||||
|
||||
# Define _start so that linker does not complain.
|
||||
.global _start
|
||||
.code 32
|
||||
.align 2
|
||||
.type _start, %function
|
||||
_start:
|
||||
bx lr
|
||||
.size _start, .-_start
|
||||
|
||||
.global _backward_test
|
||||
.code 16
|
||||
.thumb_func
|
||||
.type _backward_test, %function
|
||||
_backward_test:
|
||||
bl .Lbackward_target
|
||||
.size _backward_test, .-_backward_test
|
||||
|
||||
.global _forward_test
|
||||
.code 16
|
||||
.thumb_func
|
||||
.type _forward_test, %function
|
||||
_forward_test:
|
||||
bl .Lforward_target
|
||||
.size _forward_test, .-_forward_test
|
||||
|
||||
# Switch back to ARM mode so that we can see stubs
|
||||
.code 32
|
||||
nop
|
||||
|
||||
.section .text.post,"x"
|
||||
|
||||
# Add padding so that target is just out of branch range.
|
||||
.space 12
|
||||
|
||||
.code 16
|
||||
.thumb_func
|
||||
.type .Lforward_target, %function
|
||||
.Lforward_target:
|
||||
bx lr
|
||||
.size .Lforward_target, .-.Lforward_target
|
@ -15,6 +15,8 @@ _backward_target:
|
||||
.size _backward_target, .-_backward_target
|
||||
|
||||
.text
|
||||
# Use 256-byte alignment so that we know where the stubs start.
|
||||
.align 8
|
||||
|
||||
# Define _start so that linker does not complain.
|
||||
.align 2
|
||||
@ -46,7 +48,10 @@ _forward_test:
|
||||
nop.n
|
||||
bl _forward_target
|
||||
.size _forward_test, .-_forward_test
|
||||
|
||||
# switch back to ARM mode so that stubs are disassembled correctly.
|
||||
.code 32
|
||||
nop
|
||||
|
||||
.section .text.post,"x"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user