diff options
author | Doug Kwan <dougkwan@google.com> | 2016-09-02 15:51:59 -0700 |
---|---|---|
committer | Doug Kwan <dougkwan@google.com> | 2016-09-02 15:51:59 -0700 |
commit | bc99685c7387acaa9fc20f7e45e9cd477bf0c619 (patch) | |
tree | a84234b0bf1fe0b6eb2a4d9634cbd2cf247b8971 /gold/arm.cc | |
parent | 4aa4e28bdcf5f0d733def62b542fea11d5f219d5 (diff) | |
download | binutils-bc99685c7387acaa9fc20f7e45e9cd477bf0c619.zip binutils-bc99685c7387acaa9fc20f7e45e9cd477bf0c619.tar.gz binutils-bc99685c7387acaa9fc20f7e45e9cd477bf0c619.tar.bz2 |
Handle ARM-specific --target1-abs, --target1-rel and --target2 options
Diffstat (limited to 'gold/arm.cc')
-rw-r--r-- | gold/arm.cc | 59 |
1 files changed, 46 insertions, 13 deletions
diff --git a/gold/arm.cc b/gold/arm.cc index a885c33..9171d0b 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -2128,8 +2128,36 @@ class Target_arm : public Sized_target<32, big_endian> stub_tables_(), stub_factory_(Stub_factory::get_instance()), should_force_pic_veneer_(false), arm_input_section_map_(), attributes_section_data_(NULL), - fix_cortex_a8_(false), cortex_a8_relocs_info_() - { } + fix_cortex_a8_(false), cortex_a8_relocs_info_(), + target1_reloc_(elfcpp::R_ARM_ABS32), + // This can be any reloc type but usually is R_ARM_GOT_PREL. + target2_reloc_(elfcpp::R_ARM_GOT_PREL) + { + if (parameters->options().user_set_target1_rel()) + { + // FIXME: This is not strictly compatible with ld, which allows both + // --target1-abs and --target-rel to be given. + if (parameters->options().user_set_target1_abs()) + gold_error(_("Cannot use both --target1-abs and --target1-rel.")); + else + this->target1_reloc_ = elfcpp::R_ARM_REL32; + } + // We don't need to handle --target1-abs because target1_reloc_ is set + // to elfcpp::R_ARM_ABS32 in the member initializer list. + + if (parameters->options().user_set_target2()) + { + const char* target2 = parameters->options().target2(); + if (strcmp(target2, "rel") == 0) + this->target2_reloc_ = elfcpp::R_ARM_REL32; + else if (strcmp(target2, "abs") == 0) + this->target2_reloc_ = elfcpp::R_ARM_ABS32; + else if (strcmp(target2, "got-rel") == 0) + this->target2_reloc_ = elfcpp::R_ARM_GOT_PREL; + else + gold_unreachable(); + } + } // Whether we force PCI branch veneers. bool @@ -2391,8 +2419,8 @@ class Target_arm : public Sized_target<32, big_endian> rel_irelative_section(Layout*); // Map platform-specific reloc types - static unsigned int - get_real_reloc_type(unsigned int r_type); + unsigned int + get_real_reloc_type(unsigned int r_type) const; // // Methods to support stub-generations. @@ -3002,6 +3030,11 @@ class Target_arm : public Sized_target<32, big_endian> bool fix_cortex_a8_; // Map addresses to relocs for Cortex-A8 erratum. Cortex_a8_relocs_info cortex_a8_relocs_info_; + // What R_ARM_TARGET1 maps to. It can be R_ARM_REL32 or R_ARM_ABS32. + unsigned int target1_reloc_; + // What R_ARM_TARGET2 maps to. It should be one of R_ARM_REL32, R_ARM_ABS32 + // and R_ARM_GOT_PREL. + unsigned int target2_reloc_; }; template<bool big_endian> @@ -8520,7 +8553,7 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab, if (is_discarded) return; - r_type = get_real_reloc_type(r_type); + r_type = target->get_real_reloc_type(r_type); // A local STT_GNU_IFUNC symbol may require a PLT entry. bool is_ifunc = lsym.get_st_type() == elfcpp::STT_GNU_IFUNC; @@ -8926,7 +8959,7 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab, && this->reloc_needs_plt_for_ifunc(object, r_type)) target->make_plt_entry(symtab, layout, gsym); - r_type = get_real_reloc_type(r_type); + r_type = target->get_real_reloc_type(r_type); switch (r_type) { case elfcpp::R_ARM_NONE: @@ -9552,7 +9585,7 @@ Target_arm<big_endian>::Relocate::relocate( const elfcpp::Rel<32, big_endian> rel(preloc); unsigned int r_type = elfcpp::elf_r_type<32>(rel.get_r_info()); - r_type = get_real_reloc_type(r_type); + r_type = target->get_real_reloc_type(r_type); const Arm_reloc_property* reloc_property = arm_reloc_property_table->get_implemented_static_reloc_property(r_type); if (reloc_property == NULL) @@ -10262,7 +10295,9 @@ Target_arm<big_endian>::Classify_reloc::get_size_for_reloc( unsigned int r_type, Relobj* object) { - r_type = get_real_reloc_type(r_type); + Target_arm<big_endian>* arm_target = + Target_arm<big_endian>::default_target(); + r_type = arm_target->get_real_reloc_type(r_type); const Arm_reloc_property* arp = arm_reloc_property_table->get_implemented_static_reloc_property(r_type); if (arp != NULL) @@ -10686,17 +10721,15 @@ Target_arm<big_endian>::do_dynsym_value(const Symbol* gsym) const // template<bool big_endian> unsigned int -Target_arm<big_endian>::get_real_reloc_type(unsigned int r_type) +Target_arm<big_endian>::get_real_reloc_type(unsigned int r_type) const { switch (r_type) { case elfcpp::R_ARM_TARGET1: - // This is either R_ARM_ABS32 or R_ARM_REL32; - return elfcpp::R_ARM_ABS32; + return this->target1_reloc_; case elfcpp::R_ARM_TARGET2: - // This can be any reloc type but usually is R_ARM_GOT_PREL - return elfcpp::R_ARM_GOT_PREL; + return this->target2_reloc_; default: return r_type; |