* arm.cc (Target_arm::relocate::reloc_is_non_pic): Return true for
authorIan Lance Taylor <ian@airs.com>
Fri, 9 Oct 2009 22:56:41 +0000 (22:56 +0000)
committerIan Lance Taylor <ian@airs.com>
Fri, 9 Oct 2009 22:56:41 +0000 (22:56 +0000)
R_ARM_THM_ABS5, R_ARM_ABS8, R_ARM_ABS12, R_ARM_ABS16,
R_ARM_BASE_ABS.
(Arm_relocate_functions::abs8): Remove has_thumb_bit parameter.
(Arm_relocate_functions::thm_abs5): New function.
(Arm_relocate_functions::abs12): New function.
(Arm_relocate_functions::abs16): New function.
(Arm_relocate_functions::base_abs): New function.
(Scan::check_non_pic): Handle R_ARM_ABS32_NOI.
(Scan::local): Remove special handling of R_ARM_ABS8.  Handle
R_ARM_ABS32_NOI, R_ARM_THM_ABS5, R_ARM_ABS12, R_ARM_ABS16, and
R_ARM_BASE_ABS.
(Scan::global): Likewise.
(Relocate::relocate): Handle R_ARM_ABS12, R_ARM_ABS16,
R_ARM_ABS32_NOI, R_ARM_THM_ABS5, and R_ARM_BASE_ABS.
(Relocatable_size_for_reloc::get_size_for_reloc): Handle
R_ARM_ABS16, R_ARM_THM_ABS5, R_ARM_ABS32_NOI, R_ARM_ABS12, and
R_ARM_BASE_ABS.

gold/ChangeLog
gold/arm.cc

index a80805fb2d5397e0a95bca303003bf993709869d..a8939ee0f3e648b4561cc1d8819a2f70d9fc09b0 100644 (file)
@@ -1,3 +1,24 @@
+2009-10-09  Viktor Kutuzov  <vkutuzov@accesssoftek.com>
+
+       * arm.cc (Target_arm::relocate::reloc_is_non_pic): Return true for
+       R_ARM_THM_ABS5, R_ARM_ABS8, R_ARM_ABS12, R_ARM_ABS16,
+       R_ARM_BASE_ABS.
+       (Arm_relocate_functions::abs8): Remove has_thumb_bit parameter.
+       (Arm_relocate_functions::thm_abs5): New function.
+       (Arm_relocate_functions::abs12): New function.
+       (Arm_relocate_functions::abs16): New function.
+       (Arm_relocate_functions::base_abs): New function.
+       (Scan::check_non_pic): Handle R_ARM_ABS32_NOI.
+       (Scan::local): Remove special handling of R_ARM_ABS8.  Handle
+       R_ARM_ABS32_NOI, R_ARM_THM_ABS5, R_ARM_ABS12, R_ARM_ABS16, and
+       R_ARM_BASE_ABS.
+       (Scan::global): Likewise.
+       (Relocate::relocate): Handle R_ARM_ABS12, R_ARM_ABS16,
+       R_ARM_ABS32_NOI, R_ARM_THM_ABS5, and R_ARM_BASE_ABS.
+       (Relocatable_size_for_reloc::get_size_for_reloc): Handle
+       R_ARM_ABS16, R_ARM_THM_ABS5, R_ARM_ABS32_NOI, R_ARM_ABS12, and
+       R_ARM_BASE_ABS.
+
 2009-10-09  Viktor Kutuzov  <vkutuzov@accesssoftek.com>
 
        * arm.cc (Arm_relocate_functions::movw_prel_nc): New function.
index edfd35c5aefadc41ed438a02e71d3b6620f633fe..7067de71831b1b302e01f5b6659ef71fdd944a18 100644 (file)
@@ -59,6 +59,12 @@ class Output_data_plt_arm;
 //
 // R_ARM_NONE
 // R_ARM_ABS32
+// R_ARM_ABS32_NOI
+// R_ARM_ABS16
+// R_ARM_ABS12
+// R_ARM_ABS8
+// R_ARM_THM_ABS5
+// R_ARM_BASE_ABS
 // R_ARM_REL32
 // R_ARM_THM_CALL
 // R_ARM_COPY
@@ -366,6 +372,11 @@ class Target_arm : public Sized_target<32, big_endian>
        case elfcpp::R_ARM_CALL:
        case elfcpp::R_ARM_JUMP24:
        case elfcpp::R_ARM_PREL31:
+       case elfcpp::R_ARM_THM_ABS5:
+       case elfcpp::R_ARM_ABS8:
+       case elfcpp::R_ARM_ABS12:
+       case elfcpp::R_ARM_ABS16:
+       case elfcpp::R_ARM_BASE_ABS:
          return true;
        default:
          return false;
@@ -659,14 +670,14 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
   static inline typename This::Status
   abs8(unsigned char *view,
        const Sized_relobj<32, big_endian>* object,
-       const Symbol_value<32>* psymval, bool has_thumb_bit)
+       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 = This::arm_symbol_value(object, psymval, addend, has_thumb_bit);
+    Reltype x = This::arm_symbol_value(object, psymval, addend, false);
     val = utils::bit_select(val, x, 0xffU);
     elfcpp::Swap<8, big_endian>::writeval(wv, val);
     return (utils::has_signed_unsigned_overflow<8>(x)
@@ -674,6 +685,63 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
            : This::STATUS_OKAY);
   }
 
+  // R_ARM_THM_ABS5: S + A
+  static inline typename This::Status
+  thm_abs5(unsigned char *view,
+       const Sized_relobj<32, big_endian>* object,
+       const Symbol_value<32>* psymval)
+  {
+    typedef typename elfcpp::Swap<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 = (val & 0x7e0U) >> 6;
+    Reltype x = This::arm_symbol_value(object, psymval, addend, false);
+    val = utils::bit_select(val, x << 6, 0x7e0U);
+    elfcpp::Swap<16, big_endian>::writeval(wv, val);
+    return (utils::has_overflow<5>(x)
+           ? This::STATUS_OVERFLOW
+           : This::STATUS_OKAY);
+  }
+
+  // R_ARM_ABS12: S + A
+  static inline typename This::Status
+  abs12(unsigned char *view,
+       const Sized_relobj<32, big_endian>* object,
+       const Symbol_value<32>* psymval)
+  {
+    typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
+    typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype;
+    Valtype* wv = reinterpret_cast<Valtype*>(view);
+    Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
+    Reltype addend = val & 0x0fffU;
+    Reltype x = This::arm_symbol_value(object, psymval, addend, false);
+    val = utils::bit_select(val, x, 0x0fffU);
+    elfcpp::Swap<32, big_endian>::writeval(wv, val);
+    return (utils::has_overflow<12>(x)
+           ? This::STATUS_OVERFLOW
+           : This::STATUS_OKAY);
+  }
+
+  // R_ARM_ABS16: S + A
+  static inline typename This::Status
+  abs16(unsigned char *view,
+       const Sized_relobj<32, big_endian>* object,
+       const Symbol_value<32>* psymval)
+  {
+    typedef typename elfcpp::Swap<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 = This::arm_symbol_value(object, psymval, addend, false);
+    val = utils::bit_select(val, x, 0xffffU);
+    elfcpp::Swap<16, big_endian>::writeval(wv, val);
+    return (utils::has_signed_unsigned_overflow<16>(x)
+           ? This::STATUS_OVERFLOW
+           : This::STATUS_OKAY);
+  }
+
   // R_ARM_ABS32: (S + A) | T
   static inline typename This::Status
   abs32(unsigned char *view,
@@ -753,6 +821,15 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
     return STATUS_OKAY;
   }
 
+  // R_ARM_BASE_ABS: B(S) + A
+  static inline typename This::Status
+  base_abs(unsigned char* view,
+           elfcpp::Elf_types<32>::Elf_Addr origin)
+  {
+    Base::rel32(view, origin);
+    return STATUS_OKAY;
+  }
+
   // R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG
   static inline typename This::Status
   got_brel(unsigned char* view,
@@ -1308,6 +1385,7 @@ Target_arm<big_endian>::Scan::check_non_pic(Relobj* object,
     case elfcpp::R_ARM_GLOB_DAT:
     case elfcpp::R_ARM_JUMP_SLOT:
     case elfcpp::R_ARM_ABS32:
+    case elfcpp::R_ARM_ABS32_NOI:
     case elfcpp::R_ARM_PC24:
     // FIXME: The following 3 types are not supported by Android's dynamic
     // linker.
@@ -1355,16 +1433,8 @@ Target_arm<big_endian>::Scan::local(const General_options&,
     case elfcpp::R_ARM_NONE:
       break;
 
-    case elfcpp::R_ARM_ABS8:
-      if (parameters->options().output_is_position_independent())
-       {
-         // FIXME: Create a dynamic relocation for this location.
-         gold_error(_("%s: gold bug: need dynamic ABS8 reloc"),
-                    object->name().c_str());
-       }
-      break;
-
     case elfcpp::R_ARM_ABS32:
+    case elfcpp::R_ARM_ABS32_NOI:
       // If building a shared library (or a position-independent
       // executable), we need to create a dynamic relocation for
       // this location. The relocation applied at link time will
@@ -1389,6 +1459,11 @@ Target_arm<big_endian>::Scan::local(const General_options&,
     case elfcpp::R_ARM_PREL31:
     case elfcpp::R_ARM_JUMP24:
     case elfcpp::R_ARM_PLT32:
+    case elfcpp::R_ARM_THM_ABS5:
+    case elfcpp::R_ARM_ABS8:
+    case elfcpp::R_ARM_ABS12:
+    case elfcpp::R_ARM_ABS16:
+    case elfcpp::R_ARM_BASE_ABS:
     case elfcpp::R_ARM_MOVW_ABS_NC:
     case elfcpp::R_ARM_MOVT_ABS:
     case elfcpp::R_ARM_THM_MOVW_ABS_NC:
@@ -1486,17 +1561,8 @@ Target_arm<big_endian>::Scan::global(const General_options&,
     case elfcpp::R_ARM_NONE:
       break;
 
-    case elfcpp::R_ARM_ABS8:
-      // Make a dynamic relocation if necessary.
-      if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF))
-       {
-         // FIXME: Create a dynamic relocation for this location.
-         gold_error(_("%s: gold bug: need dynamic ABS8 reloc for %s"),
-                    object->name().c_str(), gsym->demangled_name().c_str());
-       }
-      break;
-
     case elfcpp::R_ARM_ABS32:
+    case elfcpp::R_ARM_ABS32_NOI:
       {
        // Make a dynamic relocation if necessary.
        if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF))
@@ -1537,6 +1603,23 @@ Target_arm<big_endian>::Scan::global(const General_options&,
     case elfcpp::R_ARM_THM_MOVT_PREL:
       break;
 
+    case elfcpp::R_ARM_THM_ABS5:
+    case elfcpp::R_ARM_ABS8:
+    case elfcpp::R_ARM_ABS12:
+    case elfcpp::R_ARM_ABS16:
+    case elfcpp::R_ARM_BASE_ABS:
+      {
+       // No dynamic relocs of this kinds.
+       // Report the error in case of PIC.
+       int flags = Symbol::NON_PIC_REF;
+       if (gsym->type() == elfcpp::STT_FUNC
+           || gsym->type() == elfcpp::STT_ARM_TFUNC)
+         flags |= Symbol::FUNCTION_CALL;
+       if (gsym->needs_dynamic_reloc(flags))
+         check_non_pic(object, r_type);
+      }
+      break;
+
     case elfcpp::R_ARM_REL32:
     case elfcpp::R_ARM_PREL31:
       {
@@ -1919,8 +2002,19 @@ Target_arm<big_endian>::Relocate::relocate(
     case elfcpp::R_ARM_ABS8:
       if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
                                    output_section))
-       reloc_status = Arm_relocate_functions::abs8(view, object, psymval,
-                                                   has_thumb_bit);
+       reloc_status = Arm_relocate_functions::abs8(view, object, psymval);
+      break;
+
+    case elfcpp::R_ARM_ABS12:
+      if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
+                                   output_section))
+       reloc_status = Arm_relocate_functions::abs12(view, object, psymval);
+      break;
+
+    case elfcpp::R_ARM_ABS16:
+      if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
+                                   output_section))
+       reloc_status = Arm_relocate_functions::abs16(view, object, psymval);
       break;
 
     case elfcpp::R_ARM_ABS32:
@@ -1930,6 +2024,14 @@ Target_arm<big_endian>::Relocate::relocate(
                                                     has_thumb_bit);
       break;
 
+    case elfcpp::R_ARM_ABS32_NOI:
+      if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true,
+                                   output_section))
+       // No thumb bit for this relocation: (S + A)
+       reloc_status = Arm_relocate_functions::abs32(view, object, psymval,
+                                                    false);
+      break;
+
     case elfcpp::R_ARM_MOVW_ABS_NC:
       if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true,
                                    output_section))
@@ -1998,6 +2100,12 @@ Target_arm<big_endian>::Relocate::relocate(
                                                   address, has_thumb_bit);
       break;
 
+    case elfcpp::R_ARM_THM_ABS5:
+      if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
+                                   output_section))
+       reloc_status = Arm_relocate_functions::thm_abs5(view, object, psymval);
+      break;
+
     case elfcpp::R_ARM_THM_CALL:
       reloc_status = Arm_relocate_functions::thm_call(view, object, psymval,
                                                      address, has_thumb_bit);
@@ -2032,6 +2140,35 @@ Target_arm<big_endian>::Relocate::relocate(
       }
       break;
 
+    case elfcpp::R_ARM_BASE_ABS:
+      {
+       if (!should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true,
+                                     output_section))
+         break;
+
+       uint32_t origin;
+       // Get the addressing origin of the output segment defining
+       // the symbol gsym (AAELF 4.6.1.2 Relocation types).
+       if (gsym == NULL)
+         // R_ARM_BASE_ABS with the NULL symbol will give the
+         // absolute address of the GOT origin (GOT_ORG) (see ARM IHI
+         // 0044C (AAELF): 4.6.1.8 Proxy generating relocations).
+         origin = target->got_plt_section()->address();
+       else if (gsym->source() == Symbol::IN_OUTPUT_SEGMENT)
+         origin = gsym->output_segment()->vaddr();
+       else if (gsym->source () == Symbol::IN_OUTPUT_DATA)
+         origin = gsym->output_data()->address();
+       else
+         {
+            gold_error_at_location(relinfo, relnum, rel.get_r_offset(),
+                                  _("cannot find origin of R_ARM_BASE_ABS"));
+           return true;
+         }
+
+       reloc_status = Arm_relocate_functions::base_abs(view, origin);
+      }
+      break;
+
     case elfcpp::R_ARM_GOT_BREL:
       gold_assert(have_got_offset);
       reloc_status = Arm_relocate_functions::got_brel(view, got_offset);
@@ -2172,7 +2309,14 @@ Target_arm<big_endian>::Relocatable_size_for_reloc::get_size_for_reloc(
     case elfcpp::R_ARM_ABS8:
       return 1;
 
+    case elfcpp::R_ARM_ABS16:
+    case elfcpp::R_ARM_THM_ABS5:
+      return 2;
+
     case elfcpp::R_ARM_ABS32:
+    case elfcpp::R_ARM_ABS32_NOI:
+    case elfcpp::R_ARM_ABS12:
+    case elfcpp::R_ARM_BASE_ABS:
     case elfcpp::R_ARM_REL32:
     case elfcpp::R_ARM_THM_CALL:
     case elfcpp::R_ARM_GOTOFF32: