copy_relocs_(elfcpp::R_ARM_COPY), dynbss_(NULL),
got_mod_index_offset_(-1U), tls_base_symbol_defined_(false),
stub_tables_(), stub_factory_(Stub_factory::get_instance()),
- may_use_blx_(false), should_force_pic_veneer_(false),
+ should_force_pic_veneer_(false),
arm_input_section_map_(), attributes_section_data_(NULL),
fix_cortex_a8_(false), cortex_a8_relocs_info_()
{ }
- // Whether we can use BLX.
- bool
- may_use_blx() const
- { return this->may_use_blx_; }
-
- // Set use-BLX flag.
- void
- set_may_use_blx(bool value)
- { this->may_use_blx_ = value; }
-
// Whether we force PCI branch veneers.
bool
should_force_pic_veneer() const
|| arch == elfcpp::TAG_CPU_ARCH_V7
|| arch == elfcpp::TAG_CPU_ARCH_V7E_M);
}
+
+ // Whether we have v4T interworking instructions available.
+ bool
+ may_use_v4t_interworking() const
+ {
+ Object_attribute* attr =
+ this->get_aeabi_object_attribute(elfcpp::Tag_CPU_arch);
+ int arch = attr->int_value();
+ return (arch != elfcpp::TAG_CPU_ARCH_PRE_V4
+ && arch != elfcpp::TAG_CPU_ARCH_V4);
+ }
+
+ // Whether we have v5T interworking instructions available.
+ bool
+ may_use_v5t_interworking() const
+ {
+ Object_attribute* attr =
+ this->get_aeabi_object_attribute(elfcpp::Tag_CPU_arch);
+ int arch = attr->int_value();
+ if (parameters->options().fix_arm1176())
+ return (arch == elfcpp::TAG_CPU_ARCH_V6T2
+ || arch == elfcpp::TAG_CPU_ARCH_V7
+ || arch == elfcpp::TAG_CPU_ARCH_V6_M
+ || arch == elfcpp::TAG_CPU_ARCH_V6S_M
+ || arch == elfcpp::TAG_CPU_ARCH_V7E_M);
+ else
+ return (arch != elfcpp::TAG_CPU_ARCH_PRE_V4
+ && arch != elfcpp::TAG_CPU_ARCH_V4
+ && arch != elfcpp::TAG_CPU_ARCH_V4T);
+ }
// Process the relocations to determine unreferenced sections for
// garbage collection.
Stub_table_list stub_tables_;
// Stub factory.
const Stub_factory &stub_factory_;
- // Whether we can use BLX.
- bool may_use_blx_;
// Whether we force PIC branch veneers.
bool should_force_pic_veneer_;
// Map for locating Arm_input_sections.
const Symbol_value<32>* psymval)
{
typedef typename elfcpp::Swap<8, big_endian>::Valtype Valtype;
- typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype;
Valtype* wv = reinterpret_cast<Valtype*>(view);
Valtype val = elfcpp::Swap<8, big_endian>::readval(wv);
- Reltype addend = utils::sign_extend<8>(val);
- Reltype x = psymval->value(object, addend);
+ int32_t addend = utils::sign_extend<8>(val);
+ Arm_address x = psymval->value(object, addend);
val = utils::bit_select(val, x, 0xffU);
elfcpp::Swap<8, big_endian>::writeval(wv, val);
const Sized_relobj_file<32, big_endian>* object,
const Symbol_value<32>* psymval)
{
- typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
+ typedef typename elfcpp::Swap_unaligned<16, big_endian>::Valtype Valtype;
typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype;
- Valtype* wv = reinterpret_cast<Valtype*>(view);
- Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
- Reltype addend = utils::sign_extend<16>(val);
- Reltype x = psymval->value(object, addend);
+ Valtype val = elfcpp::Swap_unaligned<16, big_endian>::readval(view);
+ int32_t addend = utils::sign_extend<16>(val);
+ Arm_address x = psymval->value(object, addend);
val = utils::bit_select(val, x, 0xffffU);
- elfcpp::Swap<16, big_endian>::writeval(wv, val);
- return (utils::has_signed_unsigned_overflow<16>(x)
+ elfcpp::Swap_unaligned<16, big_endian>::writeval(view, val);
+
+ // R_ARM_ABS16 permits signed or unsigned results.
+ int signed_x = static_cast<int32_t>(x);
+ return ((signed_x < -32768 || signed_x > 65536)
? This::STATUS_OVERFLOW
: This::STATUS_OKAY);
}
const Symbol_value<32>* psymval,
Arm_address thumb_bit)
{
- typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
- Valtype* wv = reinterpret_cast<Valtype*>(view);
- Valtype addend = elfcpp::Swap<32, big_endian>::readval(wv);
+ typedef typename elfcpp::Swap_unaligned<32, big_endian>::Valtype Valtype;
+ Valtype addend = elfcpp::Swap_unaligned<32, big_endian>::readval(view);
Valtype x = psymval->value(object, addend) | thumb_bit;
- elfcpp::Swap<32, big_endian>::writeval(wv, x);
+ elfcpp::Swap_unaligned<32, big_endian>::writeval(view, x);
return This::STATUS_OKAY;
}
Arm_address address,
Arm_address thumb_bit)
{
- typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
- Valtype* wv = reinterpret_cast<Valtype*>(view);
- Valtype addend = elfcpp::Swap<32, big_endian>::readval(wv);
+ typedef typename elfcpp::Swap_unaligned<32, big_endian>::Valtype Valtype;
+ Valtype addend = elfcpp::Swap_unaligned<32, big_endian>::readval(view);
Valtype x = (psymval->value(object, addend) | thumb_bit) - address;
- elfcpp::Swap<32, big_endian>::writeval(wv, x);
+ elfcpp::Swap_unaligned<32, big_endian>::writeval(view, x);
return This::STATUS_OKAY;
}
Arm_address address,
Arm_address thumb_bit)
{
- typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
- Valtype* wv = reinterpret_cast<Valtype*>(view);
- Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
+ typedef typename elfcpp::Swap_unaligned<32, big_endian>::Valtype Valtype;
+ Valtype val = elfcpp::Swap_unaligned<32, big_endian>::readval(view);
Valtype addend = utils::sign_extend<31>(val);
Valtype x = (psymval->value(object, addend) | thumb_bit) - address;
val = utils::bit_select(val, x, 0x7fffffffU);
- elfcpp::Swap<32, big_endian>::writeval(wv, val);
+ elfcpp::Swap_unaligned<32, big_endian>::writeval(view, val);
return (utils::has_overflow<31>(x) ?
This::STATUS_OVERFLOW : This::STATUS_OKAY);
}
// We need a stub if the branch offset is too large or if we need
// to switch mode.
- bool may_use_blx = arm_target->may_use_blx();
+ bool may_use_blx = arm_target->may_use_v5t_interworking();
Reloc_stub* stub = NULL;
if (!parameters->options().relocatable()
Arm_address branch_target = psymval->value(object, addend);
// For BLX, bit 1 of target address comes from bit 1 of base address.
- bool may_use_blx = arm_target->may_use_blx();
+ bool may_use_blx = arm_target->may_use_v5t_interworking();
if (thumb_bit == 0 && may_use_blx)
branch_target = utils::bit_select(branch_target, address, 0x2);
{
const Target_arm<true>* big_endian_target =
Target_arm<true>::default_target();
- may_use_blx = big_endian_target->may_use_blx();
+ may_use_blx = big_endian_target->may_use_v5t_interworking();
should_force_pic_veneer = big_endian_target->should_force_pic_veneer();
thumb2 = big_endian_target->using_thumb2();
thumb_only = big_endian_target->using_thumb_only();
{
const Target_arm<false>* little_endian_target =
Target_arm<false>::default_target();
- may_use_blx = little_endian_target->may_use_blx();
+ may_use_blx = little_endian_target->may_use_v5t_interworking();
should_force_pic_veneer = little_endian_target->should_force_pic_veneer();
thumb2 = little_endian_target->using_thumb2();
thumb_only = little_endian_target->using_thumb_only();
const section_size_type oview_size = 8;
unsigned char* const oview = of->get_output_view(offset, oview_size);
- typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
- Valtype* wv = reinterpret_cast<Valtype*>(oview);
+ typedef typename elfcpp::Swap_unaligned<32, big_endian>::Valtype Valtype;
Output_section* os = this->relobj_->output_section(this->shndx_);
gold_assert(os != NULL);
uint32_t prel31_offset = output_address - this->address();
if (utils::has_overflow<31>(offset))
gold_error(_("PREL31 overflow in EXIDX_CANTUNWIND entry"));
- elfcpp::Swap<32, big_endian>::writeval(wv, prel31_offset & 0x7fffffffU);
- elfcpp::Swap<32, big_endian>::writeval(wv + 1, elfcpp::EXIDX_CANTUNWIND);
+ elfcpp::Swap_unaligned<32, big_endian>::writeval(oview,
+ prel31_offset & 0x7fffffffU);
+ elfcpp::Swap_unaligned<32, big_endian>::writeval(oview + 4,
+ elfcpp::EXIDX_CANTUNWIND);
of->write_output_view(this->offset(), oview_size, oview);
}
if (this->attributes_section_data_ == NULL)
this->attributes_section_data_ = new Attributes_section_data(NULL, 0);
- // Check BLX use.
const Object_attribute* cpu_arch_attr =
this->get_aeabi_object_attribute(elfcpp::Tag_CPU_arch);
- if (cpu_arch_attr->int_value() > elfcpp::TAG_CPU_ARCH_V4)
- this->set_may_use_blx(true);
-
// Check if we need to use Cortex-A8 workaround.
if (parameters->options().user_set_fix_cortex_a8())
this->fix_cortex_a8_ = parameters->options().fix_cortex_a8();
// The V4BX interworking stub contains BX instruction,
// which is not specified for some profiles.
if (this->fix_v4bx() == General_options::FIX_V4BX_INTERWORKING
- && !this->may_use_blx())
+ && !this->may_use_v4t_interworking())
gold_error(_("unable to provide V4BX reloc interworking fix up; "
"the target profile does not support BX instruction"));
// an ARM instruction. If we were not making a stub,
// the BL would have been converted to a BLX. Use the
// BLX stub instead in that case.
- if (this->may_use_blx() && force_target_arm
+ if (this->may_use_v5t_interworking() && force_target_arm
&& stub_type == arm_stub_a8_veneer_bl)
{
stub_type = arm_stub_a8_veneer_blx;