* configure.ac: Add --with-lib-path option. Define LIB_PATH and
[deliverable/binutils-gdb.git] / gold / arm.cc
index 8fd20be6b8959bfe760d8d09e8b2b3c10c82bcf1..200c371310118b79a26c008e6d8f4ba1c19371a2 100644 (file)
@@ -2177,21 +2177,11 @@ class Target_arm : public Sized_target<32, big_endian>
       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
@@ -2253,6 +2243,36 @@ class Target_arm : public Sized_target<32, big_endian>
            || 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.
@@ -2922,8 +2942,6 @@ class Target_arm : public Sized_target<32, big_endian>
   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.
@@ -3215,11 +3233,10 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
        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);
 
@@ -3277,15 +3294,17 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
        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);
   }
@@ -3297,11 +3316,10 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
        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;
   }
 
@@ -3313,11 +3331,10 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
        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;
   }
 
@@ -3435,13 +3452,12 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
         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);
   }
@@ -3952,7 +3968,7 @@ Arm_relocate_functions<big_endian>::arm_branch_common(
 
   // 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()
@@ -4083,7 +4099,7 @@ Arm_relocate_functions<big_endian>::thumb_branch_common(
   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);
 
@@ -4466,7 +4482,7 @@ Reloc_stub::stub_type_for_reloc(
     {
       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();
@@ -4475,7 +4491,7 @@ Reloc_stub::stub_type_for_reloc(
     {
       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();
@@ -5221,8 +5237,7 @@ Arm_exidx_cantunwind::do_fixed_endian_write(Output_file* of)
   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);
@@ -5263,8 +5278,10 @@ Arm_exidx_cantunwind::do_fixed_endian_write(Output_file* of)
   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);
 }
@@ -8605,12 +8622,8 @@ Target_arm<big_endian>::do_finalize_sections(
   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();
@@ -8631,7 +8644,7 @@ Target_arm<big_endian>::do_finalize_sections(
   // 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"));
 
@@ -11798,7 +11811,7 @@ Target_arm<big_endian>::scan_span_for_cortex_a8_erratum(
              // 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;
This page took 0.030006 seconds and 4 git commands to generate.