// arm.cc -- arm target support for gold.
-// Copyright (C) 2009-2016 Free Software Foundation, Inc.
+// Copyright (C) 2009-2020 Free Software Foundation, Inc.
// Written by Doug Kwan <dougkwan@google.com> based on the i386 code
// by Ian Lance Taylor <iant@google.com>.
// This file also contains borrowed and adapted code from
// Target::do_select_as_default_target() hook so that we do not spend time
// building the table if we are not linking ARM objects.
//
-// An alternative is to to process the information in arm-reloc.def in
+// An alternative is to process the information in arm-reloc.def in
// compilation time and generate a representation of it in PODs only. That
// way we can avoid initialization when the linker starts.
target1_reloc_(elfcpp::R_ARM_ABS32),
// This can be any reloc type but usually is R_ARM_GOT_PREL.
target2_reloc_(elfcpp::R_ARM_GOT_PREL)
- {
- if (parameters->options().user_set_target1_rel())
- {
- // FIXME: This is not strictly compatible with ld, which allows both
- // --target1-abs and --target-rel to be given.
- if (parameters->options().user_set_target1_abs())
- gold_error(_("Cannot use both --target1-abs and --target1-rel."));
- else
- this->target1_reloc_ = elfcpp::R_ARM_REL32;
- }
- // We don't need to handle --target1-abs because target1_reloc_ is set
- // to elfcpp::R_ARM_ABS32 in the member initializer list.
-
- if (parameters->options().user_set_target2())
- {
- const char* target2 = parameters->options().target2();
- if (strcmp(target2, "rel") == 0)
- this->target2_reloc_ = elfcpp::R_ARM_REL32;
- else if (strcmp(target2, "abs") == 0)
- this->target2_reloc_ = elfcpp::R_ARM_ABS32;
- else if (strcmp(target2, "got-rel") == 0)
- this->target2_reloc_ = elfcpp::R_ARM_GOT_PREL;
- else
- gold_unreachable();
- }
- }
+ { }
// Whether we force PCI branch veneers.
bool
// as the default.
gold_assert(arm_reloc_property_table == NULL);
arm_reloc_property_table = new Arm_reloc_property_table();
+ if (parameters->options().user_set_target1_rel())
+ {
+ // FIXME: This is not strictly compatible with ld, which allows both
+ // --target1-abs and --target-rel to be given.
+ if (parameters->options().user_set_target1_abs())
+ gold_error(_("Cannot use both --target1-abs and --target1-rel."));
+ else
+ this->target1_reloc_ = elfcpp::R_ARM_REL32;
+ }
+ // We don't need to handle --target1-abs because target1_reloc_ is set
+ // to elfcpp::R_ARM_ABS32 in the member initializer list.
+
+ if (parameters->options().user_set_target2())
+ {
+ const char* target2 = parameters->options().target2();
+ if (strcmp(target2, "rel") == 0)
+ this->target2_reloc_ = elfcpp::R_ARM_REL32;
+ else if (strcmp(target2, "abs") == 0)
+ this->target2_reloc_ = elfcpp::R_ARM_ABS32;
+ else if (strcmp(target2, "got-rel") == 0)
+ this->target2_reloc_ = elfcpp::R_ARM_GOT_PREL;
+ else
+ gold_unreachable();
+ }
}
// Virtual function which is set to return true by a target if
"aeabi", // attributes_vendor
"_start", // entry_symbol_name
32, // hash_entry_size
+ elfcpp::SHT_PROGBITS, // unwind_section_type
};
// Arm relocate functions class
const Symbol_value<32>* psymval, Arm_address address,
Arm_address thumb_bit);
- // R_ARM_THM_JUMP6: S + A – P
+ // R_ARM_THM_JUMP6: S + A - P
static inline typename This::Status
thm_jump6(unsigned char* view,
const Sized_relobj_file<32, big_endian>* object,
typedef typename elfcpp::Swap<16, big_endian>::Valtype Reltype;
Valtype* wv = reinterpret_cast<Valtype*>(view);
Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
- // bit[9]:bit[7:3]:’0’ (mask: 0x02f8)
+ // bit[9]:bit[7:3]:'0' (mask: 0x02f8)
Reltype addend = (((val & 0x0200) >> 3) | ((val & 0x00f8) >> 2));
Reltype x = (psymval->value(object, addend) - address);
val = (val & 0xfd07) | ((x & 0x0040) << 3) | ((val & 0x003e) << 2);
: This::STATUS_OKAY);
}
- // R_ARM_THM_JUMP8: S + A – P
+ // R_ARM_THM_JUMP8: S + A - P
static inline typename This::Status
thm_jump8(unsigned char* view,
const Sized_relobj_file<32, big_endian>* object,
: This::STATUS_OKAY);
}
- // R_ARM_THM_JUMP11: S + A – P
+ // R_ARM_THM_JUMP11: S + A - P
static inline typename This::Status
thm_jump11(unsigned char* view,
const Sized_relobj_file<32, big_endian>* object,
{
const Stub_template* stub_template = this->stub_template();
const Insn_template* insns = stub_template->insns();
+ const bool enable_be8 = parameters->options().be8();
- // FIXME: We do not handle BE8 encoding yet.
unsigned char* pov = view;
for (size_t i = 0; i < stub_template->insn_count(); i++)
{
switch (insns[i].type())
{
case Insn_template::THUMB16_TYPE:
- elfcpp::Swap<16, big_endian>::writeval(pov, insns[i].data() & 0xffff);
+ if (enable_be8)
+ elfcpp::Swap<16, false>::writeval(pov, insns[i].data() & 0xffff);
+ else
+ elfcpp::Swap<16, big_endian>::writeval(pov,
+ insns[i].data() & 0xffff);
break;
case Insn_template::THUMB16_SPECIAL_TYPE:
- elfcpp::Swap<16, big_endian>::writeval(
- pov,
- this->thumb16_special(i));
+ if (enable_be8)
+ elfcpp::Swap<16, false>::writeval(pov, this->thumb16_special(i));
+ else
+ elfcpp::Swap<16, big_endian>::writeval(pov,
+ this->thumb16_special(i));
break;
case Insn_template::THUMB32_TYPE:
{
uint32_t hi = (insns[i].data() >> 16) & 0xffff;
uint32_t lo = insns[i].data() & 0xffff;
- elfcpp::Swap<16, big_endian>::writeval(pov, hi);
- elfcpp::Swap<16, big_endian>::writeval(pov + 2, lo);
+ if (enable_be8)
+ {
+ elfcpp::Swap<16, false>::writeval(pov, hi);
+ elfcpp::Swap<16, false>::writeval(pov + 2, lo);
+ }
+ else
+ {
+ elfcpp::Swap<16, big_endian>::writeval(pov, hi);
+ elfcpp::Swap<16, big_endian>::writeval(pov + 2, lo);
+ }
}
break;
case Insn_template::ARM_TYPE:
+ if (enable_be8)
+ elfcpp::Swap<32, false>::writeval(pov, insns[i].data());
+ else
+ elfcpp::Swap<32, big_endian>::writeval(pov, insns[i].data());
+ break;
case Insn_template::DATA_TYPE:
elfcpp::Swap<32, big_endian>::writeval(pov, insns[i].data());
break;
Output_file* of,
typename Sized_relobj_file<32, big_endian>::Views* pviews)
{
- // Call parent to relocate sections.
- Sized_relobj_file<32, big_endian>::do_relocate_sections(symtab, layout,
- pshdrs, of, pviews);
+ // Relocate the section data.
+ this->relocate_section_range(symtab, layout, pshdrs, of, pviews,
+ 1, this->shnum() - 1);
// We do not generate stubs if doing a relocatable link.
if (parameters->options().relocatable())
{
case 0:
// Integer divide allowed if instruction contained in
- // archetecture.
+ // architecture.
if (arch == elfcpp::TAG_CPU_ARCH_V7 && (profile == 'R' || profile == 'M'))
return true;
else if (arch >= elfcpp::TAG_CPU_ARCH_V7E_M)
if (in_attr[elfcpp::Tag_MPextension_use].int_value()
!= in_attr[i].int_value())
{
- gold_error(_("%s has has both the current and legacy "
+ gold_error(_("%s has both the current and legacy "
"Tag_MPextension_use attributes"),
name);
}
const Symbol_value<32> *psymval;
bool is_defined_in_discarded_section;
unsigned int shndx;
+ const Symbol* gsym = NULL;
if (r_sym < local_count)
{
sym = NULL;
if (!is_defined_in_discarded_section)
{
typedef Sized_relobj_file<32, big_endian> ObjType;
+ if (psymval->is_section_symbol())
+ symval.set_is_section_symbol();
typename ObjType::Compute_final_local_value_status status =
arm_object->compute_final_local_value(r_sym, psymval, &symval,
relinfo->symtab);
}
else
{
- const Symbol* gsym;
gsym = arm_object->global_symbol(r_sym);
gold_assert(gsym != NULL);
if (gsym->is_forwarder())
Symbol_value<32> symval2;
if (is_defined_in_discarded_section)
{
+ std::string name = arm_object->section_name(relinfo->data_shndx);
+
if (comdat_behavior == CB_UNDETERMINED)
- {
- std::string name = arm_object->section_name(relinfo->data_shndx);
comdat_behavior = default_comdat_behavior.get(name.c_str());
- }
+
if (comdat_behavior == CB_PRETEND)
{
// FIXME: This case does not work for global symbols.
// script.
bool found;
typename elfcpp::Elf_types<32>::Elf_Addr value =
- arm_object->map_to_kept_section(shndx, &found);
+ arm_object->map_to_kept_section(shndx, name, &found);
if (found)
symval2.set_output_value(value + psymval->input_value());
else
}
else
{
- if (comdat_behavior == CB_WARNING)
- gold_warning_at_location(relinfo, i, offset,
- _("relocation refers to discarded "
- "section"));
+ if (comdat_behavior == CB_ERROR)
+ issue_discarded_error(relinfo, i, offset, r_sym, gsym);
symval2.set_output_value(0);
}
symval2.set_no_output_symtab_entry();
Arm_address target = (pc_for_insn + offset) | (is_blx ? 0 : 1);
- // Add a new stub if destination address in in the same page.
+ // Add a new stub if destination address is in the same page.
if (((address + i) & ~0xfffU) == (target & ~0xfffU))
{
Cortex_a8_stub* stub =
// branch to the stub. We use the THUMB-2 encoding here.
upper_insn = 0xf000U;
lower_insn = 0xb800U;
- // Fall through
+ // Fall through.
case arm_stub_a8_veneer_b:
case arm_stub_a8_veneer_bl:
case arm_stub_a8_veneer_blx:
const Task* task)
{
// We need to look at all the input sections in output in ascending
- // order of of output address. We do that by building a sorted list
+ // order of output address. We do that by building a sorted list
// of output sections by addresses. Then we looks at the output sections
// in order. The input sections in an output section are already sorted
// by addresses within the output section.
"aeabi", // attributes_vendor
"_start", // entry_symbol_name
32, // hash_entry_size
+ elfcpp::SHT_PROGBITS, // unwind_section_type
};
template<bool big_endian>