OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gold/] [arm.cc] - Diff between revs 27 and 159

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 27 Rev 159
Line 1... Line 1...
// arm.cc -- arm target support for gold.
// arm.cc -- arm target support for gold.
 
 
// Copyright 2009, 2010 Free Software Foundation, Inc.
// Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
// Written by Doug Kwan <dougkwan@google.com> based on the i386 code
// Written by Doug Kwan <dougkwan@google.com> based on the i386 code
// by Ian Lance Taylor <iant@google.com>.
// by Ian Lance Taylor <iant@google.com>.
// This file also contains borrowed and adapted code from
// This file also contains borrowed and adapted code from
// bfd/elf32-arm.c.
// bfd/elf32-arm.c.
 
 
Line 2180... Line 2180...
      may_use_blx_(false), should_force_pic_veneer_(false),
      may_use_blx_(false), should_force_pic_veneer_(false),
      arm_input_section_map_(), attributes_section_data_(NULL),
      arm_input_section_map_(), attributes_section_data_(NULL),
      fix_cortex_a8_(false), cortex_a8_relocs_info_()
      fix_cortex_a8_(false), cortex_a8_relocs_info_()
  { }
  { }
 
 
  // Virtual function which is set to return true by a target if
 
  // it can use relocation types to determine if a function's
 
  // pointer is taken.
 
  virtual bool
 
  can_check_for_function_pointers() const
 
  { return true; }
 
 
 
  // Whether a section called SECTION_NAME may have function pointers to
 
  // sections not eligible for safe ICF folding.
 
  virtual bool
 
  section_may_have_icf_unsafe_pointers(const char* section_name) const
 
  {
 
    return (!is_prefix_of(".ARM.exidx", section_name)
 
            && !is_prefix_of(".ARM.extab", section_name)
 
            && Target::section_may_have_icf_unsafe_pointers(section_name));
 
  }
 
 
 
  // Whether we can use BLX.
  // Whether we can use BLX.
  bool
  bool
  may_use_blx() const
  may_use_blx() const
  { return this->may_use_blx_; }
  { return this->may_use_blx_; }
 
 
Line 2551... Line 2534...
    // as the default.
    // as the default.
    gold_assert(arm_reloc_property_table == NULL);
    gold_assert(arm_reloc_property_table == NULL);
    arm_reloc_property_table = new Arm_reloc_property_table();
    arm_reloc_property_table = new Arm_reloc_property_table();
  }
  }
 
 
 
  // Virtual function which is set to return true by a target if
 
  // it can use relocation types to determine if a function's
 
  // pointer is taken.
 
  virtual bool
 
  do_can_check_for_function_pointers() const
 
  { return true; }
 
 
 
  // Whether a section called SECTION_NAME may have function pointers to
 
  // sections not eligible for safe ICF folding.
 
  virtual bool
 
  do_section_may_have_icf_unsafe_pointers(const char* section_name) const
 
  {
 
    return (!is_prefix_of(".ARM.exidx", section_name)
 
            && !is_prefix_of(".ARM.extab", section_name)
 
            && Target::do_section_may_have_icf_unsafe_pointers(section_name));
 
  }
 
 
 private:
 private:
  // The class which scans relocations.
  // The class which scans relocations.
  class Scan
  class Scan
  {
  {
   public:
   public:
Line 2944... Line 2944...
  elfcpp::EM_ARM,       // machine_code
  elfcpp::EM_ARM,       // machine_code
  false,                // has_make_symbol
  false,                // has_make_symbol
  false,                // has_resolve
  false,                // has_resolve
  false,                // has_code_fill
  false,                // has_code_fill
  true,                 // is_default_stack_executable
  true,                 // is_default_stack_executable
 
  false,                // can_icf_inline_merge_sections
  '\0',                 // wrap_char
  '\0',                 // wrap_char
  "/usr/lib/libc.so.1", // dynamic_linker
  "/usr/lib/libc.so.1", // dynamic_linker
  0x8000,               // default_text_segment_address
  0x8000,               // default_text_segment_address
  0x1000,               // abi_pagesize (overridable by -z max-page-size)
  0x1000,               // abi_pagesize (overridable by -z max-page-size)
  0x1000,               // common_pagesize (overridable by -z common-page-size)
  0x1000,               // common_pagesize (overridable by -z common-page-size)
Line 3212... Line 3213...
  abs8(unsigned char* view,
  abs8(unsigned char* view,
       const Sized_relobj_file<32, big_endian>* object,
       const Sized_relobj_file<32, big_endian>* object,
       const Symbol_value<32>* psymval)
       const Symbol_value<32>* psymval)
  {
  {
    typedef typename elfcpp::Swap<8, big_endian>::Valtype Valtype;
    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* wv = reinterpret_cast<Valtype*>(view);
    Valtype val = elfcpp::Swap<8, big_endian>::readval(wv);
    Valtype val = elfcpp::Swap<8, big_endian>::readval(wv);
    Reltype addend = utils::sign_extend<8>(val);
    int32_t addend = utils::sign_extend<8>(val);
    Reltype x = psymval->value(object, addend);
    Arm_address x = psymval->value(object, addend);
    val = utils::bit_select(val, x, 0xffU);
    val = utils::bit_select(val, x, 0xffU);
    elfcpp::Swap<8, big_endian>::writeval(wv, val);
    elfcpp::Swap<8, big_endian>::writeval(wv, val);
 
 
    // R_ARM_ABS8 permits signed or unsigned results.
    // R_ARM_ABS8 permits signed or unsigned results.
    int signed_x = static_cast<int32_t>(x);
    int signed_x = static_cast<int32_t>(x);
Line 3274... Line 3274...
  static inline typename This::Status
  static inline typename This::Status
  abs16(unsigned char* view,
  abs16(unsigned char* view,
        const Sized_relobj_file<32, big_endian>* object,
        const Sized_relobj_file<32, big_endian>* object,
        const Symbol_value<32>* psymval)
        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;
    typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype;
    Valtype* wv = reinterpret_cast<Valtype*>(view);
    Valtype val = elfcpp::Swap_unaligned<16, big_endian>::readval(view);
    Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
    int32_t addend = utils::sign_extend<16>(val);
    Reltype addend = utils::sign_extend<16>(val);
    Arm_address x = psymval->value(object, addend);
    Reltype x = psymval->value(object, addend);
 
    val = utils::bit_select(val, x, 0xffffU);
    val = utils::bit_select(val, x, 0xffffU);
    elfcpp::Swap<16, big_endian>::writeval(wv, val);
    elfcpp::Swap_unaligned<16, big_endian>::writeval(view, val);
    return (utils::has_signed_unsigned_overflow<16>(x)
 
 
    // 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_OVERFLOW
            : This::STATUS_OKAY);
            : This::STATUS_OKAY);
  }
  }
 
 
  // R_ARM_ABS32: (S + A) | T
  // R_ARM_ABS32: (S + A) | T
Line 3294... Line 3296...
  abs32(unsigned char* view,
  abs32(unsigned char* view,
        const Sized_relobj_file<32, big_endian>* object,
        const Sized_relobj_file<32, big_endian>* object,
        const Symbol_value<32>* psymval,
        const Symbol_value<32>* psymval,
        Arm_address thumb_bit)
        Arm_address thumb_bit)
  {
  {
    typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
    typedef typename elfcpp::Swap_unaligned<32, big_endian>::Valtype Valtype;
    Valtype* wv = reinterpret_cast<Valtype*>(view);
    Valtype addend = elfcpp::Swap_unaligned<32, big_endian>::readval(view);
    Valtype addend = elfcpp::Swap<32, big_endian>::readval(wv);
 
    Valtype x = psymval->value(object, addend) | thumb_bit;
    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;
    return This::STATUS_OKAY;
  }
  }
 
 
  // R_ARM_REL32: (S + A) | T - P
  // R_ARM_REL32: (S + A) | T - P
  static inline typename This::Status
  static inline typename This::Status
Line 3310... Line 3311...
        const Sized_relobj_file<32, big_endian>* object,
        const Sized_relobj_file<32, big_endian>* object,
        const Symbol_value<32>* psymval,
        const Symbol_value<32>* psymval,
        Arm_address address,
        Arm_address address,
        Arm_address thumb_bit)
        Arm_address thumb_bit)
  {
  {
    typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
    typedef typename elfcpp::Swap_unaligned<32, big_endian>::Valtype Valtype;
    Valtype* wv = reinterpret_cast<Valtype*>(view);
    Valtype addend = elfcpp::Swap_unaligned<32, big_endian>::readval(view);
    Valtype addend = elfcpp::Swap<32, big_endian>::readval(wv);
 
    Valtype x = (psymval->value(object, addend) | thumb_bit) - address;
    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;
    return This::STATUS_OKAY;
  }
  }
 
 
  // R_ARM_THM_JUMP24: (S + A) | T - P
  // R_ARM_THM_JUMP24: (S + A) | T - P
  static typename This::Status
  static typename This::Status
Line 3354... Line 3354...
            const Sized_relobj_file<32, big_endian>* object,
            const Sized_relobj_file<32, big_endian>* object,
            const Symbol_value<32>* psymval,
            const Symbol_value<32>* psymval,
            Arm_address address)
            Arm_address address)
  {
  {
    typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
    typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
    typedef typename elfcpp::Swap<16, big_endian>::Valtype Reltype;
 
    Valtype* wv = reinterpret_cast<Valtype*>(view);
    Valtype* wv = reinterpret_cast<Valtype*>(view);
    Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
    Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
    Reltype addend = utils::sign_extend<8>((val & 0x00ff) << 1);
    int32_t addend = utils::sign_extend<8>((val & 0x00ff) << 1);
    Reltype x = (psymval->value(object, addend) - address);
    int32_t x = (psymval->value(object, addend) - address);
    elfcpp::Swap<16, big_endian>::writeval(wv, (val & 0xff00) | ((x & 0x01fe) >> 1));
    elfcpp::Swap<16, big_endian>::writeval(wv, ((val & 0xff00)
    return (utils::has_overflow<8>(x)
                                                | ((x & 0x01fe) >> 1)));
 
    // We do a 9-bit overflow check because x is right-shifted by 1 bit.
 
    return (utils::has_overflow<9>(x)
            ? This::STATUS_OVERFLOW
            ? This::STATUS_OVERFLOW
            : This::STATUS_OKAY);
            : This::STATUS_OKAY);
  }
  }
 
 
  // R_ARM_THM_JUMP11: S + A – P
  // R_ARM_THM_JUMP11: S + A – P
Line 3373... Line 3374...
            const Sized_relobj_file<32, big_endian>* object,
            const Sized_relobj_file<32, big_endian>* object,
            const Symbol_value<32>* psymval,
            const Symbol_value<32>* psymval,
            Arm_address address)
            Arm_address address)
  {
  {
    typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
    typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
    typedef typename elfcpp::Swap<16, big_endian>::Valtype Reltype;
 
    Valtype* wv = reinterpret_cast<Valtype*>(view);
    Valtype* wv = reinterpret_cast<Valtype*>(view);
    Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
    Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
    Reltype addend = utils::sign_extend<11>((val & 0x07ff) << 1);
    int32_t addend = utils::sign_extend<11>((val & 0x07ff) << 1);
    Reltype x = (psymval->value(object, addend) - address);
    int32_t x = (psymval->value(object, addend) - address);
    elfcpp::Swap<16, big_endian>::writeval(wv, (val & 0xf800) | ((x & 0x0ffe) >> 1));
    elfcpp::Swap<16, big_endian>::writeval(wv, ((val & 0xf800)
    return (utils::has_overflow<11>(x)
                                                | ((x & 0x0ffe) >> 1)));
 
    // We do a 12-bit overflow check because x is right-shifted by 1 bit.
 
    return (utils::has_overflow<12>(x)
            ? This::STATUS_OVERFLOW
            ? This::STATUS_OVERFLOW
            : This::STATUS_OKAY);
            : This::STATUS_OKAY);
  }
  }
 
 
  // R_ARM_BASE_PREL: B(S) + A - P
  // R_ARM_BASE_PREL: B(S) + A - P
Line 3430... Line 3432...
         const Sized_relobj_file<32, big_endian>* object,
         const Sized_relobj_file<32, big_endian>* object,
         const Symbol_value<32>* psymval,
         const Symbol_value<32>* psymval,
         Arm_address address,
         Arm_address address,
         Arm_address thumb_bit)
         Arm_address thumb_bit)
  {
  {
    typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
    typedef typename elfcpp::Swap_unaligned<32, big_endian>::Valtype Valtype;
    Valtype* wv = reinterpret_cast<Valtype*>(view);
    Valtype val = elfcpp::Swap_unaligned<32, big_endian>::readval(view);
    Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
 
    Valtype addend = utils::sign_extend<31>(val);
    Valtype addend = utils::sign_extend<31>(val);
    Valtype x = (psymval->value(object, addend) | thumb_bit) - address;
    Valtype x = (psymval->value(object, addend) | thumb_bit) - address;
    val = utils::bit_select(val, x, 0x7fffffffU);
    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) ?
    return (utils::has_overflow<31>(x) ?
            This::STATUS_OVERFLOW : This::STATUS_OKAY);
            This::STATUS_OVERFLOW : This::STATUS_OKAY);
  }
  }
 
 
  // R_ARM_MOVW_ABS_NC: (S + A) | T     (relative address base is )
  // R_ARM_MOVW_ABS_NC: (S + A) | T     (relative address base is )
Line 5216... Line 5217...
{
{
  off_t offset = this->offset();
  off_t offset = this->offset();
  const section_size_type oview_size = 8;
  const section_size_type oview_size = 8;
  unsigned char* const oview = of->get_output_view(offset, oview_size);
  unsigned char* const oview = of->get_output_view(offset, oview_size);
 
 
  typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
  typedef typename elfcpp::Swap_unaligned<32, big_endian>::Valtype Valtype;
  Valtype* wv = reinterpret_cast<Valtype*>(oview);
 
 
 
  Output_section* os = this->relobj_->output_section(this->shndx_);
  Output_section* os = this->relobj_->output_section(this->shndx_);
  gold_assert(os != NULL);
  gold_assert(os != NULL);
 
 
  Arm_relobj<big_endian>* arm_relobj =
  Arm_relobj<big_endian>* arm_relobj =
Line 5258... Line 5258...
  // or after the end of a text section.  The second word is the special
  // or after the end of a text section.  The second word is the special
  // EXIDX_CANTUNWIND value.
  // EXIDX_CANTUNWIND value.
  uint32_t prel31_offset = output_address - this->address();
  uint32_t prel31_offset = output_address - this->address();
  if (utils::has_overflow<31>(offset))
  if (utils::has_overflow<31>(offset))
    gold_error(_("PREL31 overflow in EXIDX_CANTUNWIND entry"));
    gold_error(_("PREL31 overflow in EXIDX_CANTUNWIND entry"));
  elfcpp::Swap<32, big_endian>::writeval(wv, prel31_offset & 0x7fffffffU);
  elfcpp::Swap_unaligned<32, big_endian>::writeval(oview,
  elfcpp::Swap<32, big_endian>::writeval(wv + 1, elfcpp::EXIDX_CANTUNWIND);
                                                   prel31_offset & 0x7fffffffU);
 
  elfcpp::Swap_unaligned<32, big_endian>::writeval(oview + 4,
 
                                                   elfcpp::EXIDX_CANTUNWIND);
 
 
  of->write_output_view(this->offset(), oview_size, oview);
  of->write_output_view(this->offset(), oview_size, oview);
}
}
 
 
// Arm_exidx_merged_section methods.
// Arm_exidx_merged_section methods.
Line 5801... Line 5803...
       p != this->input_sections().end();
       p != this->input_sections().end();
       ++p)
       ++p)
    {
    {
      // We only care about plain or relaxed input sections.  We also
      // We only care about plain or relaxed input sections.  We also
      // ignore any merged sections.
      // ignore any merged sections.
      if ((p->is_input_section() || p->is_relaxed_input_section())
      if (p->is_input_section() || p->is_relaxed_input_section())
          && p->data_size() != 0)
 
        list->push_back(Text_section_list::value_type(p->relobj(),
        list->push_back(Text_section_list::value_type(p->relobj(),
                                                      p->shndx()));
                                                      p->shndx()));
    }
    }
}
}
 
 
Line 11900... Line 11901...
class Target_selector_arm : public Target_selector
class Target_selector_arm : public Target_selector
{
{
 public:
 public:
  Target_selector_arm()
  Target_selector_arm()
    : Target_selector(elfcpp::EM_ARM, 32, big_endian,
    : Target_selector(elfcpp::EM_ARM, 32, big_endian,
                      (big_endian ? "elf32-bigarm" : "elf32-littlearm"))
                      (big_endian ? "elf32-bigarm" : "elf32-littlearm"),
 
                      (big_endian ? "armelfb" : "armelf"))
  { }
  { }
 
 
  Target*
  Target*
  do_instantiate_target()
  do_instantiate_target()
  { return new Target_arm<big_endian>(); }
  { return new Target_arm<big_endian>(); }

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.