diff options
-rw-r--r-- | gold/ChangeLog | 16 | ||||
-rw-r--r-- | gold/arm.cc | 149 |
2 files changed, 164 insertions, 1 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index 40287bb..e9d9e9c 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,19 @@ +2009-11-03 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::Target_arm): Initialize stub_tables_ and + stub_factory_. + (Target_arm::stub_factory): New method definition. + (Target_arm::new_arm_input_section, + Target_arm::find_arm_input_section, Target_arm::new_stub_table, + Target_arm::reloc_uses_thumb_bit): New method declarations. + (Target_arm::Stub_table_list, Target_arm::Arm_input_section_map): + New type definitions. + (Target_arm::stub_tables_, Target_arm::stub_factory_): New data + member declarations. + (Target_arm::reloc_uses_thumb_bit, Target_arm::new_arm_input_section, + Target_arm::find_arm_input_section, Target_arm::new_stub_table): + New method definitions. + 2009-11-03 Ian Lance Taylor <iant@google.com> * options.h (class General_options): Add --warn_constructors. diff --git a/gold/arm.cc b/gold/arm.cc index 3e2d70d..f0db899 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -1143,7 +1143,8 @@ class Target_arm : public Sized_target<32, big_endian> Target_arm() : Sized_target<32, big_endian>(&arm_info), got_(NULL), plt_(NULL), got_plt_(NULL), rel_dyn_(NULL), - copy_relocs_(elfcpp::R_ARM_COPY), dynbss_(NULL), + copy_relocs_(elfcpp::R_ARM_COPY), dynbss_(NULL), stub_tables_(), + stub_factory_(Stub_factory::get_instance()), may_use_blx_(true), should_force_pic_veneer_(false) { } @@ -1281,6 +1282,28 @@ class Target_arm : public Sized_target<32, big_endian> static unsigned int get_real_reloc_type (unsigned int r_type); + // + // Methods to support stub-generations. + // + + // Return the stub factory + const Stub_factory& + stub_factory() const + { return this->stub_factory_; } + + // Make a new Arm_input_section object. + Arm_input_section<big_endian>* + new_arm_input_section(Relobj*, unsigned int); + + // Find the Arm_input_section object corresponding to the SHNDX-th input + // section of RELOBJ. + Arm_input_section<big_endian>* + find_arm_input_section(Relobj* relobj, unsigned int shndx) const; + + // Make a new Stub_table + Stub_table<big_endian>* + new_stub_table(Arm_input_section<big_endian>*); + // Get the default ARM target. static const Target_arm<big_endian>& default_target() @@ -1290,6 +1313,10 @@ class Target_arm : public Sized_target<32, big_endian> return static_cast<const Target_arm<big_endian>&>(parameters->target()); } + // Whether relocation type uses LSB to distinguish THUMB addresses. + static bool + reloc_uses_thumb_bit(unsigned int r_type); + protected: void do_adjust_elf_header(unsigned char* view, int len) const; @@ -1502,6 +1529,15 @@ class Target_arm : public Sized_target<32, big_endian> GOT_TYPE_STANDARD = 0 // GOT entry for a regular symbol }; + typedef typename std::vector<Stub_table<big_endian>*> Stub_table_list; + + // Map input section to Arm_input_section. + typedef Unordered_map<Input_section_specifier, + Arm_input_section<big_endian>*, + Input_section_specifier::hash, + Input_section_specifier::equal_to> + Arm_input_section_map; + // The GOT section. Output_data_got<32, big_endian>* got_; // The PLT section. @@ -1514,6 +1550,10 @@ class Target_arm : public Sized_target<32, big_endian> Copy_relocs<elfcpp::SHT_REL, 32, big_endian> copy_relocs_; // Space for variables copied with a COPY reloc. Output_data_space* dynbss_; + // Vector of Stub_tables created. + 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. @@ -4968,6 +5008,113 @@ Target_arm<big_endian>::do_make_elf_object( } } +// Return whether a relocation type used the LSB to distinguish THUMB +// addresses. +template<bool big_endian> +bool +Target_arm<big_endian>::reloc_uses_thumb_bit(unsigned int r_type) +{ + switch (r_type) + { + case elfcpp::R_ARM_PC24: + case elfcpp::R_ARM_ABS32: + case elfcpp::R_ARM_REL32: + case elfcpp::R_ARM_SBREL32: + case elfcpp::R_ARM_THM_CALL: + case elfcpp::R_ARM_GLOB_DAT: + case elfcpp::R_ARM_JUMP_SLOT: + case elfcpp::R_ARM_GOTOFF32: + case elfcpp::R_ARM_PLT32: + case elfcpp::R_ARM_CALL: + case elfcpp::R_ARM_JUMP24: + case elfcpp::R_ARM_THM_JUMP24: + case elfcpp::R_ARM_SBREL31: + case elfcpp::R_ARM_PREL31: + case elfcpp::R_ARM_MOVW_ABS_NC: + case elfcpp::R_ARM_MOVW_PREL_NC: + case elfcpp::R_ARM_THM_MOVW_ABS_NC: + case elfcpp::R_ARM_THM_MOVW_PREL_NC: + case elfcpp::R_ARM_THM_JUMP19: + case elfcpp::R_ARM_THM_ALU_PREL_11_0: + case elfcpp::R_ARM_ALU_PC_G0_NC: + case elfcpp::R_ARM_ALU_PC_G0: + case elfcpp::R_ARM_ALU_PC_G1_NC: + case elfcpp::R_ARM_ALU_PC_G1: + case elfcpp::R_ARM_ALU_PC_G2: + case elfcpp::R_ARM_ALU_SB_G0_NC: + case elfcpp::R_ARM_ALU_SB_G0: + case elfcpp::R_ARM_ALU_SB_G1_NC: + case elfcpp::R_ARM_ALU_SB_G1: + case elfcpp::R_ARM_ALU_SB_G2: + case elfcpp::R_ARM_MOVW_BREL_NC: + case elfcpp::R_ARM_MOVW_BREL: + case elfcpp::R_ARM_THM_MOVW_BREL_NC: + case elfcpp::R_ARM_THM_MOVW_BREL: + return true; + default: + return false; + } +} + +// Stub-generation methods for Target_arm. + +// Make a new Arm_input_section object. + +template<bool big_endian> +Arm_input_section<big_endian>* +Target_arm<big_endian>::new_arm_input_section( + Relobj* relobj, + unsigned int shndx) +{ + Input_section_specifier iss(relobj, shndx); + + Arm_input_section<big_endian>* arm_input_section = + new Arm_input_section<big_endian>(relobj, shndx); + arm_input_section->init(); + + // Register new Arm_input_section in map for look-up. + std::pair<typename Arm_input_section_map::iterator, bool> ins = + this->arm_input_section_map_.insert(std::make_pair(iss, arm_input_section)); + + // Make sure that it we have not created another Arm_input_section + // for this input section already. + gold_assert(ins.second); + + return arm_input_section; +} + +// Find the Arm_input_section object corresponding to the SHNDX-th input +// section of RELOBJ. + +template<bool big_endian> +Arm_input_section<big_endian>* +Target_arm<big_endian>::find_arm_input_section( + Relobj* relobj, + unsigned int shndx) const +{ + Input_section_specifier iss(relobj, shndx); + typename Arm_input_section_map::const_iterator p = + this->arm_input_section_map_.find(iss); + return (p != this->arm_input_section_map_.end()) ? p->second : NULL; +} + +// Make a new stub table. + +template<bool big_endian> +Stub_table<big_endian>* +Target_arm<big_endian>::new_stub_table(Arm_input_section<big_endian>* owner) +{ + Stub_table<big_endian>* stub_table = + new Stub_table<big_endian>(owner); + this->stub_tables_.push_back(stub_table); + + stub_table->set_address(owner->address() + owner->data_size()); + stub_table->set_file_offset(owner->offset() + owner->data_size()); + stub_table->finalize_data_size(); + + return stub_table; +} + // The selector for arm object files. template<bool big_endian> |