Refactor gold to enable support for MIPS-64 relocation format. For MIPS-64, the r_info field in the relocation format is replaced by several individual fields, including r_sym and r_type. To enable support for this format, I've refactored target-independent code to remove almost all uses of the r_info field. (I've left alone a couple of routines used only for incremental linking, which I can update if/when the MIPS target adds support for incremental linking.) For routines that are already templated on a Classify_reloc class (namely, gc_process_relocs, relocate_section, and relocate_relocs), I've extended the Classify_reloc interface to include sh_type (which no longer needs to be a separate template parameter) as well as get_r_sym() and get_r_type() methods for extracting the r_sym and r_type fields. For scan_relocatable_relocs, I've extended the Default_scan_relocatable_relocs class by converting it to a class template with Classify_reloc as a template parameter. For the remaining routines that need to access r_sym, I've added a virtual Target::get_r_sym() method with an override for the MIPS target. In elfcpp, I've added Mips64_rel, etc., accessor classes and corresponding internal data structures. The MIPS target uses these new classes within its own Mips_classify_reloc class. The Mips64_ accessor classes also expose the r_ssym, r_type2, and r_type3 fields from the relocation. These changes should be functionally the same for all but the MIPS target. 2016-01-11 Cary Coutant elfcpp/ * elfcpp.h (Mips64_rel, Mips64_rel_write): New classes. (Mips64_rela, Mips64_rela_write): New classes. * elfcpp_internal.h (Mips64_rel_data, Mips64_rela_data): New structs. gold/ * gc.h (get_embedded_addend_size): Remove sh_type parameter. (gc_process_relocs): Remove sh_type template parameter. Use Classify_reloc to access r_sym, r_type, and r_addend fields. * object.h (Sized_relobj_file::split_stack_adjust): Add target parameter. (Sized_relobj_file::split_stack_adjust_reltype): Likewise. * reloc-types.h (Reloc_types::copy_reloc_addend): (SHT_REL and SHT_RELA specializations) Remove. * reloc.cc (Emit_relocs_strategy): Rename and move to target-reloc.h. (Sized_relobj_file::emit_relocs_scan): Call Target::emit_relocs_scan(). (Sized_relobj_file::emit_relocs_scan_reltype): Remove. (Sized_relobj_file::split_stack_adjust): Add target parameter. Adjust all callers. (Sized_relobj_file::split_stack_adjust_reltype): Likewise. Call Target::get_r_sym() to get r_sym field from relocations. (Track_relocs::next_symndx): Call Target::get_r_sym(). * target-reloc.h (scan_relocs): Remove sh_type template parameter; add Classify_reloc template parameter. Use for accessing r_sym and r_type. (relocate_section): Likewise. (Default_classify_reloc): New class (renamed and moved from reloc.cc). (Default_scan_relocatable_relocs): Remove sh_type template parameter. (Default_scan_relocatable_relocs::Reltype): New typedef. (Default_scan_relocatable_relocs::reloc_size): New const. (Default_scan_relocatable_relocs::sh_type): New const. (Default_scan_relocatable_relocs::get_r_sym): New method. (Default_scan_relocatable_relocs::get_r_type): New method. (Default_emit_relocs_strategy): New class. (scan_relocatable_relocs): Replace sh_type template parameter with Scan_relocatable_relocs class. Use it to access r_sym and r_type fields. (relocate_relocs): Replace sh_type template parameter with Classify_reloc class. Use it to access r_sym and r_type fields. * target.h (Target::is_call_to_non_split): Replace r_type parameter with pointer to relocation. Adjust all callers. (Target::do_is_call_to_non_split): Likewise. (Target::emit_relocs_scan): New virtual method. (Sized_target::get_r_sym): New virtual method. * target.cc (Target::do_is_call_to_non_split): Replace r_type parameter with pointer to relocation. * aarch64.cc (Target_aarch64::emit_relocs_scan): New method. (Target_aarch64::Relocatable_size_for_reloc): Remove. (Target_aarch64::gc_process_relocs): Use Default_classify_reloc. (Target_aarch64::scan_relocs): Likewise. (Target_aarch64::relocate_section): Likewise. (Target_aarch64::Relocatable_size_for_reloc::get_size_for_reloc): Remove. (Target_aarch64::scan_relocatable_relocs): Use Default_classify_reloc. (Target_aarch64::relocate_relocs): Use Default_classify_reloc. * arm.cc (Target_arm::Arm_scan_relocatable_relocs): Remove sh_type template parameter. (Target_arm::emit_relocs_scan): New method. (Target_arm::Relocatable_size_for_reloc): Replace with... (Target_arm::Classify_reloc): ...this. (Target_arm::gc_process_relocs): Use Classify_reloc. (Target_arm::scan_relocs): Likewise. (Target_arm::relocate_section): Likewise. (Target_arm::scan_relocatable_relocs): Likewise. (Target_arm::relocate_relocs): Likewise. * i386.cc (Target_i386::emit_relocs_scan): New method. (Target_i386::Relocatable_size_for_reloc): Replace with... (Target_i386::Classify_reloc): ...this. (Target_i386::gc_process_relocs): Use Classify_reloc. (Target_i386::scan_relocs): Likewise. (Target_i386::relocate_section): Likewise. (Target_i386::scan_relocatable_relocs): Likewise. (Target_i386::relocate_relocs): Likewise. * mips.cc (Mips_scan_relocatable_relocs): Remove sh_type template parameter. (Mips_reloc_types): New class template. (Mips_classify_reloc): New class template. (Target_mips::Reltype): New typedef. (Target_mips::Relatype): New typedef. (Target_mips::emit_relocs_scan): New method. (Target_mips::get_r_sym): New method. (Target_mips::Relocatable_size_for_reloc): Replace with Mips_classify_reloc. (Target_mips::copy_reloc): Use Mips_classify_reloc. (Target_mips::gc_process_relocs): Likewise. (Target_mips::scan_relocs): Likewise. (Target_mips::relocate_section): Likewise. (Target_mips::scan_relocatable_relocs): Likewise. (Target_mips::relocate_relocs): Likewise. (mips_get_size_for_reloc): New function, factored out from Relocatable_size_for_reloc::get_size_for_reloc. (Target_mips::Scan::local): Use Mips_classify_reloc. (Target_mips::Scan::global): Likewise. (Target_mips::Relocate::relocate): Likewise. * powerpc.cc (Target_powerpc::emit_relocs_scan): New method. (Target_powerpc::Relocatable_size_for_reloc): Remove. (Target_powerpc::gc_process_relocs): Use Default_classify_reloc. (Target_powerpc::scan_relocs): Likewise. (Target_powerpc::relocate_section): Likewise. (Powerpc_scan_relocatable_reloc): Convert to class template. (Powerpc_scan_relocatable_reloc::Reltype): New typedef. (Powerpc_scan_relocatable_reloc::reloc_size): New const. (Powerpc_scan_relocatable_reloc::sh_type): New const. (Powerpc_scan_relocatable_reloc::get_r_sym): New method. (Powerpc_scan_relocatable_reloc::get_r_type): New method. (Target_powerpc::scan_relocatable_relocs): Use Powerpc_scan_relocatable_reloc. (Target_powerpc::relocate_relocs): Use Default_classify_reloc. * s390.cc (Target_s390::emit_relocs_scan): New method. (Target_s390::Relocatable_size_for_reloc): Remove. (Target_s390::gc_process_relocs): Use Default_classify_reloc. (Target_s390::scan_relocs): Likewise. (Target_s390::relocate_section): Likewise. (Target_s390::Relocatable_size_for_reloc::get_size_for_reloc): Remove. (Target_s390::scan_relocatable_relocs): Use Default_classify_reloc. (Target_s390::relocate_relocs): Use Default_classify_reloc. * sparc.cc (Target_sparc::emit_relocs_scan): New method. (Target_sparc::Relocatable_size_for_reloc): Remove. (Target_sparc::gc_process_relocs): Use Default_classify_reloc. (Target_sparc::scan_relocs): Likewise. (Target_sparc::relocate_section): Likewise. (Target_sparc::Relocatable_size_for_reloc::get_size_for_reloc): Remove. (Target_sparc::scan_relocatable_relocs): Use Default_classify_reloc. (Target_sparc::relocate_relocs): Use Default_classify_reloc. * tilegx.cc (Target_tilegx::emit_relocs_scan): New method. (Target_tilegx::Relocatable_size_for_reloc): Remove. (Target_tilegx::gc_process_relocs): Use Default_classify_reloc. (Target_tilegx::scan_relocs): Likewise. (Target_tilegx::relocate_section): Likewise. (Target_tilegx::Relocatable_size_for_reloc::get_size_for_reloc): Remove. (Target_tilegx::scan_relocatable_relocs): Use Default_classify_reloc. (Target_tilegx::relocate_relocs): Use Default_classify_reloc. * x86_64.cc (Target_x86_64::emit_relocs_scan): New method. (Target_x86_64::Relocatable_size_for_reloc): Remove. (Target_x86_64::gc_process_relocs): Use Default_classify_reloc. (Target_x86_64::scan_relocs): Likewise. (Target_x86_64::relocate_section): Likewise. (Target_x86_64::Relocatable_size_for_reloc::get_size_for_reloc): Remove. (Target_x86_64::scan_relocatable_relocs): Use Default_classify_reloc. (Target_x86_64::relocate_relocs): Use Default_classify_reloc. * testsuite/testfile.cc (Target_test::emit_relocs_scan): New method. diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h index e0eae42..3d7039a 100644 --- a/elfcpp/elfcpp.h +++ b/elfcpp/elfcpp.h @@ -1661,6 +1661,172 @@ class Rela_write internal::Rela_data* p_; }; +// MIPS-64 has a non-standard relocation layout. + +template +class Mips64_rel +{ + public: + Mips64_rel(const unsigned char* p) + : p_(reinterpret_cast(p)) + { } + + template + Mips64_rel(File* file, typename File::Location loc) + : p_(reinterpret_cast( + file->view(loc.file_offset, loc.data_size).data())) + { } + + typename Elf_types<64>::Elf_Addr + get_r_offset() const + { return Convert<64, big_endian>::convert_host(this->p_->r_offset); } + + Elf_Word + get_r_sym() const + { return Convert<32, big_endian>::convert_host(this->p_->r_sym); } + + unsigned char + get_r_ssym() const + { return this->p_->r_ssym; } + + unsigned char + get_r_type() const + { return this->p_->r_type; } + + unsigned char + get_r_type2() const + { return this->p_->r_type2; } + + unsigned char + get_r_type3() const + { return this->p_->r_type3; } + + private: + const internal::Mips64_rel_data* p_; +}; + +template +class Mips64_rel_write +{ + public: + Mips64_rel_write(unsigned char* p) + : p_(reinterpret_cast(p)) + { } + + void + put_r_offset(typename Elf_types<64>::Elf_Addr v) + { this->p_->r_offset = Convert<64, big_endian>::convert_host(v); } + + void + put_r_sym(Elf_Word v) + { this->p_->r_sym = Convert<32, big_endian>::convert_host(v); } + + void + put_r_ssym(unsigned char v) + { this->p_->r_ssym = v; } + + void + put_r_type(unsigned char v) + { this->p_->r_type = v; } + + void + put_r_type2(unsigned char v) + { this->p_->r_type2 = v; } + + void + put_r_type3(unsigned char v) + { this->p_->r_type3 = v; } + + private: + internal::Mips64_rel_data* p_; +}; + +template +class Mips64_rela +{ + public: + Mips64_rela(const unsigned char* p) + : p_(reinterpret_cast(p)) + { } + + template + Mips64_rela(File* file, typename File::Location loc) + : p_(reinterpret_cast( + file->view(loc.file_offset, loc.data_size).data())) + { } + + typename Elf_types<64>::Elf_Addr + get_r_offset() const + { return Convert<64, big_endian>::convert_host(this->p_->r_offset); } + + Elf_Word + get_r_sym() const + { return Convert<32, big_endian>::convert_host(this->p_->r_sym); } + + unsigned char + get_r_ssym() const + { return this->p_->r_ssym; } + + unsigned char + get_r_type() const + { return this->p_->r_type; } + + unsigned char + get_r_type2() const + { return this->p_->r_type2; } + + unsigned char + get_r_type3() const + { return this->p_->r_type3; } + + typename Elf_types<64>::Elf_Swxword + get_r_addend() const + { return Convert<64, big_endian>::convert_host(this->p_->r_addend); } + + private: + const internal::Mips64_rela_data* p_; +}; + +template +class Mips64_rela_write +{ + public: + Mips64_rela_write(unsigned char* p) + : p_(reinterpret_cast(p)) + { } + + void + put_r_offset(typename Elf_types<64>::Elf_Addr v) + { this->p_->r_offset = Convert<64, big_endian>::convert_host(v); } + + void + put_r_sym(Elf_Word v) + { this->p_->r_sym = Convert<32, big_endian>::convert_host(v); } + + void + put_r_ssym(unsigned char v) + { this->p_->r_ssym = v; } + + void + put_r_type(unsigned char v) + { this->p_->r_type = v; } + + void + put_r_type2(unsigned char v) + { this->p_->r_type2 = v; } + + void + put_r_type3(unsigned char v) + { this->p_->r_type3 = v; } + + void + put_r_addend(typename Elf_types<64>::Elf_Swxword v) + { this->p_->r_addend = Convert<64, big_endian>::convert_host(v); } + + private: + internal::Mips64_rela_data* p_; +}; + // Accessor classes for entries in the ELF SHT_DYNAMIC section aka // PT_DYNAMIC segment. diff --git a/elfcpp/elfcpp_internal.h b/elfcpp/elfcpp_internal.h index 7080a2d..edca55f 100644 --- a/elfcpp/elfcpp_internal.h +++ b/elfcpp/elfcpp_internal.h @@ -180,6 +180,29 @@ struct Rela_data typename Elf_types::Elf_Swxword r_addend; }; +// MIPS-64 has a non-standard layout for relocations. + +struct Mips64_rel_data +{ + typename Elf_types<64>::Elf_Addr r_offset; + Elf_Word r_sym; + unsigned char r_ssym; + unsigned char r_type3; + unsigned char r_type2; + unsigned char r_type; +}; + +struct Mips64_rela_data +{ + typename Elf_types<64>::Elf_Addr r_offset; + Elf_Word r_sym; + unsigned char r_ssym; + unsigned char r_type3; + unsigned char r_type2; + unsigned char r_type; + typename Elf_types<64>::Elf_Swxword r_addend; +}; + // An entry in the ELF SHT_DYNAMIC section aka PT_DYNAMIC segment. template diff --git a/gold/aarch64.cc b/gold/aarch64.cc index 715936b..20f2f4f 100644 --- a/gold/aarch64.cc +++ b/gold/aarch64.cc @@ -2869,6 +2869,21 @@ class Target_aarch64 : public Sized_target const unsigned char* plocal_symbols, Relocatable_relocs*); + // Scan the relocs for --emit-relocs. + void + emit_relocs_scan(Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr); + // Relocate a section during a relocatable link. void relocate_relocs( @@ -3224,15 +3239,6 @@ class Target_aarch64 : public Sized_target }; // End of class Relocate - // A class which returns the size required for a relocation type, - // used while scanning relocs during a relocatable link. - class Relocatable_size_for_reloc - { - public: - unsigned int - get_size_for_reloc(unsigned int, Relobj*); - }; - // Adjust TLS relocation type based on the options and whether this // is a local symbol. static tls::Tls_optimization @@ -6630,17 +6636,16 @@ Target_aarch64::gc_process_relocs( size_t local_symbol_count, const unsigned char* plocal_symbols) { + typedef Target_aarch64 Aarch64; + typedef gold::Default_classify_reloc + Classify_reloc; + if (sh_type == elfcpp::SHT_REL) { return; } - gold::gc_process_relocs< - size, big_endian, - Target_aarch64, - elfcpp::SHT_RELA, - typename Target_aarch64::Scan, - typename Target_aarch64::Relocatable_size_for_reloc>( + gold::gc_process_relocs( symtab, layout, this, @@ -6671,13 +6676,18 @@ Target_aarch64::scan_relocs( size_t local_symbol_count, const unsigned char* plocal_symbols) { + typedef Target_aarch64 Aarch64; + typedef gold::Default_classify_reloc + Classify_reloc; + if (sh_type == elfcpp::SHT_REL) { gold_error(_("%s: unsupported REL reloc section"), object->name().c_str()); return; } - gold::scan_relocs( + + gold::scan_relocs( symtab, layout, this, @@ -7868,10 +7878,15 @@ Target_aarch64::relocate_section( section_size_type view_size, const Reloc_symbol_changes* reloc_symbol_changes) { - gold_assert(sh_type == elfcpp::SHT_RELA); + typedef Target_aarch64 Aarch64; typedef typename Target_aarch64::Relocate AArch64_relocate; - gold::relocate_section( + typedef gold::Default_classify_reloc + Classify_reloc; + + gold_assert(sh_type == elfcpp::SHT_RELA); + + gold::relocate_section( relinfo, this, prelocs, @@ -7884,21 +7899,6 @@ Target_aarch64::relocate_section( reloc_symbol_changes); } -// Return the size of a relocation while scanning during a relocatable -// link. - -template -unsigned int -Target_aarch64::Relocatable_size_for_reloc:: -get_size_for_reloc( - unsigned int , - Relobj* ) -{ - // We will never support SHT_REL relocations. - gold_unreachable(); - return 0; -} - // Scan the relocs during a relocatable link. template @@ -7917,13 +7917,14 @@ Target_aarch64::scan_relocatable_relocs( const unsigned char* plocal_symbols, Relocatable_relocs* rr) { - gold_assert(sh_type == elfcpp::SHT_RELA); + typedef gold::Default_classify_reloc + Classify_reloc; + typedef gold::Default_scan_relocatable_relocs + Scan_relocatable_relocs; - typedef gold::Default_scan_relocatable_relocs Scan_relocatable_relocs; + gold_assert(sh_type == elfcpp::SHT_RELA); - gold::scan_relocatable_relocs( + gold::scan_relocatable_relocs( symtab, layout, object, @@ -7937,6 +7938,45 @@ Target_aarch64::scan_relocatable_relocs( rr); } +// Scan the relocs for --emit-relocs. + +template +void +Target_aarch64::emit_relocs_scan( + Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr) +{ + typedef gold::Default_classify_reloc + Classify_reloc; + typedef gold::Default_emit_relocs_strategy + Emit_relocs_strategy; + + gold_assert(sh_type == elfcpp::SHT_RELA); + + gold::scan_relocatable_relocs( + symtab, + layout, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_syms, + rr); +} + // Relocate a section during a relocatable link. template @@ -7954,9 +7994,12 @@ Target_aarch64::relocate_relocs( unsigned char* reloc_view, section_size_type reloc_view_size) { + typedef gold::Default_classify_reloc + Classify_reloc; + gold_assert(sh_type == elfcpp::SHT_RELA); - gold::relocate_relocs( + gold::relocate_relocs( relinfo, prelocs, reloc_count, diff --git a/gold/arm.cc b/gold/arm.cc index c20eb6d..4cd0b91 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -2040,9 +2040,9 @@ class Arm_output_data_got : public Output_data_got<32, big_endian> // bits. The default handling of relocatable relocation cannot process these // relocations. So we have to extend the default code. -template +template class Arm_scan_relocatable_relocs : - public Default_scan_relocatable_relocs + public Default_scan_relocatable_relocs { public: // Return the strategy to use for a local symbol which is a section @@ -2050,7 +2050,7 @@ class Arm_scan_relocatable_relocs : inline Relocatable_relocs::Reloc_strategy local_section_strategy(unsigned int r_type, Relobj*) { - if (sh_type == elfcpp::SHT_RELA) + if (Classify_reloc::sh_type == elfcpp::SHT_RELA) return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA; else { @@ -2301,6 +2301,21 @@ class Target_arm : public Sized_target<32, big_endian> const unsigned char* plocal_symbols, Relocatable_relocs*); + // Scan the relocs for --emit-relocs. + void + emit_relocs_scan(Symbol_table* symtab, + Layout* layout, + Sized_relobj_file<32, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr); + // Emit relocations for a section. void relocate_relocs(const Relocate_info<32, big_endian>*, @@ -2727,12 +2742,15 @@ class Target_arm : public Sized_target<32, big_endian> }; - // A class which returns the size required for a relocation type, - // used while scanning relocs during a relocatable link. - class Relocatable_size_for_reloc + // A class for inquiring about properties of a relocation, + // used while scanning relocs during a relocatable link and + // garbage collection. + class Classify_reloc : + public gold::Default_classify_reloc { public: - unsigned int + // Return the size of the addend of the relocation (only used for SHT_REL). + static unsigned int get_size_for_reloc(unsigned int, Relobj*); }; @@ -9170,8 +9188,7 @@ Target_arm::gc_process_relocs( typedef Target_arm Arm; typedef typename Target_arm::Scan Scan; - gold::gc_process_relocs<32, big_endian, Arm, elfcpp::SHT_REL, Scan, - typename Target_arm::Relocatable_size_for_reloc>( + gold::gc_process_relocs<32, big_endian, Arm, Scan, Classify_reloc>( symtab, layout, this, @@ -9201,7 +9218,6 @@ Target_arm::scan_relocs(Symbol_table* symtab, size_t local_symbol_count, const unsigned char* plocal_symbols) { - typedef typename Target_arm::Scan Scan; if (sh_type == elfcpp::SHT_RELA) { gold_error(_("%s: unsupported RELA reloc section"), @@ -9209,7 +9225,7 @@ Target_arm::scan_relocs(Symbol_table* symtab, return; } - gold::scan_relocs<32, big_endian, Target_arm, elfcpp::SHT_REL, Scan>( + gold::scan_relocs<32, big_endian, Target_arm, Scan, Classify_reloc>( symtab, layout, this, @@ -10109,8 +10125,8 @@ Target_arm::relocate_section( } } - gold::relocate_section<32, big_endian, Target_arm, elfcpp::SHT_REL, - Arm_relocate, gold::Default_comdat_behavior>( + gold::relocate_section<32, big_endian, Target_arm, Arm_relocate, + gold::Default_comdat_behavior, Classify_reloc>( relinfo, this, prelocs, @@ -10128,7 +10144,7 @@ Target_arm::relocate_section( template unsigned int -Target_arm::Relocatable_size_for_reloc::get_size_for_reloc( +Target_arm::Classify_reloc::get_size_for_reloc( unsigned int r_type, Relobj* object) { @@ -10165,13 +10181,12 @@ Target_arm::scan_relocatable_relocs( const unsigned char* plocal_symbols, Relocatable_relocs* rr) { - gold_assert(sh_type == elfcpp::SHT_REL); + typedef Arm_scan_relocatable_relocs + Scan_relocatable_relocs; - typedef Arm_scan_relocatable_relocs Scan_relocatable_relocs; + gold_assert(sh_type == elfcpp::SHT_REL); - gold::scan_relocatable_relocs<32, big_endian, elfcpp::SHT_REL, - Scan_relocatable_relocs>( + gold::scan_relocatable_relocs<32, big_endian, Scan_relocatable_relocs>( symtab, layout, object, @@ -10185,6 +10200,44 @@ Target_arm::scan_relocatable_relocs( rr); } +// Scan the relocs for --emit-relocs. + +template +void +Target_arm::emit_relocs_scan(Symbol_table* symtab, + Layout* layout, + Sized_relobj_file<32, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr) +{ + typedef gold::Default_classify_reloc + Classify_reloc; + typedef gold::Default_emit_relocs_strategy + Emit_relocs_strategy; + + gold_assert(sh_type == elfcpp::SHT_REL); + + gold::scan_relocatable_relocs<32, big_endian, Emit_relocs_strategy>( + symtab, + layout, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_syms, + rr); +} + // Emit relocations for a section. template @@ -10204,7 +10257,7 @@ Target_arm::relocate_relocs( { gold_assert(sh_type == elfcpp::SHT_REL); - gold::relocate_relocs<32, big_endian, elfcpp::SHT_REL>( + gold::relocate_relocs<32, big_endian, Classify_reloc>( relinfo, prelocs, reloc_count, diff --git a/gold/gc.h b/gold/gc.h index 2dcf61a..d0b16b2 100644 --- a/gold/gc.h +++ b/gold/gc.h @@ -38,9 +38,6 @@ class Object; template class Sized_relobj_file; -template -struct Reloc_types; - class Output_section; class General_options; class Layout; @@ -153,12 +150,11 @@ struct Symbols_data template inline unsigned int -get_embedded_addend_size(int sh_type, int r_type, Relobj* obj) +get_embedded_addend_size(int r_type, Relobj* obj) { - if (sh_type != elfcpp::SHT_REL) - return 0; - Classify_reloc classify_reloc; - return classify_reloc.get_size_for_reloc(r_type, obj); + if (Classify_reloc::sh_type == elfcpp::SHT_REL) + return Classify_reloc::get_size_for_reloc(r_type, obj); + return 0; } // This function implements the generic part of reloc @@ -167,7 +163,7 @@ get_embedded_addend_size(int sh_type, int r_type, Relobj* obj) // garbage collection (--gc-sections) and identical code // folding (--icf). -template inline void gc_process_relocs( @@ -185,8 +181,8 @@ gc_process_relocs( { Scan scan; - typedef typename Reloc_types::Reloc Reltype; - const int reloc_size = Reloc_types::reloc_size; + typedef typename Classify_reloc::Reltype Reltype; + const int reloc_size = Classify_reloc::reloc_size; const int sym_size = elfcpp::Elf_sizes::sym_size; Icf::Sections_reachable_info* secvec = NULL; @@ -224,11 +220,10 @@ gc_process_relocs( for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size) { Reltype reloc(prelocs); - typename elfcpp::Elf_types::Elf_WXword r_info = reloc.get_r_info(); - unsigned int r_sym = elfcpp::elf_r_sym(r_info); - unsigned int r_type = elfcpp::elf_r_type(r_info); + unsigned int r_sym = Classify_reloc::get_r_sym(&reloc); + unsigned int r_type = Classify_reloc::get_r_type(&reloc); typename elfcpp::Elf_types::Elf_Swxword addend = - Reloc_types::get_reloc_addend_noerror(&reloc); + Classify_reloc::get_r_addend(&reloc); Relobj* dst_obj; unsigned int dst_indx; typedef typename elfcpp::Elf_types::Elf_Addr Address; @@ -260,8 +255,7 @@ gc_process_relocs( convert_to_section_size_type(reloc.get_r_offset()); (*offsetvec).push_back(reloc_offset); (*reloc_addend_size_vec).push_back( - get_embedded_addend_size(sh_type, r_type, - src_obj)); + get_embedded_addend_size(r_type, src_obj)); } // When doing safe folding, check to see if this relocation is that @@ -337,8 +331,7 @@ gc_process_relocs( convert_to_section_size_type(reloc.get_r_offset()); (*offsetvec).push_back(reloc_offset); (*reloc_addend_size_vec).push_back( - get_embedded_addend_size(sh_type, r_type, - src_obj)); + get_embedded_addend_size(r_type, src_obj)); } if (dst_obj == NULL) diff --git a/gold/i386.cc b/gold/i386.cc index 57e5542..82886d4 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -429,6 +429,21 @@ class Target_i386 : public Sized_target<32, false> const unsigned char* plocal_symbols, Relocatable_relocs*); + // Scan the relocs for --emit-relocs. + void + emit_relocs_scan(Symbol_table* symtab, + Layout* layout, + Sized_relobj_file<32, false>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr); + // Emit relocations for a section. void relocate_relocs(const Relocate_info<32, false>*, @@ -485,7 +500,7 @@ class Target_i386 : public Sized_target<32, false> // Return whether SYM is call to a non-split function. bool - do_is_call_to_non_split(const Symbol* sym, unsigned int) const; + do_is_call_to_non_split(const Symbol* sym, const unsigned char*) const; // Adjust -fsplit-stack code which calls non-split-stack code. void @@ -723,12 +738,15 @@ class Target_i386 : public Sized_target<32, false> Local_dynamic_type local_dynamic_type_; }; - // A class which returns the size required for a relocation type, - // used while scanning relocs during a relocatable link. - class Relocatable_size_for_reloc + // A class for inquiring about properties of a relocation, + // used while scanning relocs during a relocatable link and + // garbage collection. + class Classify_reloc : + public gold::Default_classify_reloc { public: - unsigned int + // Return the size of the addend of the relocation (only used for SHT_REL). + static unsigned int get_size_for_reloc(unsigned int, Relobj*); }; @@ -2564,9 +2582,7 @@ Target_i386::gc_process_relocs(Symbol_table* symtab, size_t local_symbol_count, const unsigned char* plocal_symbols) { - gold::gc_process_relocs<32, false, Target_i386, elfcpp::SHT_REL, - Target_i386::Scan, - Target_i386::Relocatable_size_for_reloc>( + gold::gc_process_relocs<32, false, Target_i386, Scan, Classify_reloc>( symtab, layout, this, @@ -2602,8 +2618,7 @@ Target_i386::scan_relocs(Symbol_table* symtab, return; } - gold::scan_relocs<32, false, Target_i386, elfcpp::SHT_REL, - Target_i386::Scan>( + gold::scan_relocs<32, false, Target_i386, Scan, Classify_reloc>( symtab, layout, this, @@ -3609,8 +3624,8 @@ Target_i386::relocate_section(const Relocate_info<32, false>* relinfo, { gold_assert(sh_type == elfcpp::SHT_REL); - gold::relocate_section<32, false, Target_i386, elfcpp::SHT_REL, - Target_i386::Relocate, gold::Default_comdat_behavior>( + gold::relocate_section<32, false, Target_i386, Relocate, + gold::Default_comdat_behavior, Classify_reloc>( relinfo, this, prelocs, @@ -3627,7 +3642,7 @@ Target_i386::relocate_section(const Relocate_info<32, false>* relinfo, // link. unsigned int -Target_i386::Relocatable_size_for_reloc::get_size_for_reloc( +Target_i386::Classify_reloc::get_size_for_reloc( unsigned int r_type, Relobj* object) { @@ -3712,13 +3727,12 @@ Target_i386::scan_relocatable_relocs(Symbol_table* symtab, const unsigned char* plocal_symbols, Relocatable_relocs* rr) { - gold_assert(sh_type == elfcpp::SHT_REL); + typedef gold::Default_scan_relocatable_relocs + Scan_relocatable_relocs; - typedef gold::Default_scan_relocatable_relocs Scan_relocatable_relocs; + gold_assert(sh_type == elfcpp::SHT_REL); - gold::scan_relocatable_relocs<32, false, elfcpp::SHT_REL, - Scan_relocatable_relocs>( + gold::scan_relocatable_relocs<32, false, Scan_relocatable_relocs>( symtab, layout, object, @@ -3732,6 +3746,43 @@ Target_i386::scan_relocatable_relocs(Symbol_table* symtab, rr); } +// Scan the relocs for --emit-relocs. + +void +Target_i386::emit_relocs_scan(Symbol_table* symtab, + Layout* layout, + Sized_relobj_file<32, false>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr) +{ + typedef gold::Default_classify_reloc + Classify_reloc; + typedef gold::Default_emit_relocs_strategy + Emit_relocs_strategy; + + gold_assert(sh_type == elfcpp::SHT_REL); + + gold::scan_relocatable_relocs<32, false, Emit_relocs_strategy>( + symtab, + layout, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_syms, + rr); +} + // Emit relocations for a section. void @@ -3750,7 +3801,7 @@ Target_i386::relocate_relocs( { gold_assert(sh_type == elfcpp::SHT_REL); - gold::relocate_relocs<32, false, elfcpp::SHT_REL>( + gold::relocate_relocs<32, false, Classify_reloc>( relinfo, prelocs, reloc_count, @@ -3867,7 +3918,8 @@ Target_i386::do_ehframe_datarel_base() const // get_pc_thunk function. bool -Target_i386::do_is_call_to_non_split(const Symbol* sym, unsigned int) const +Target_i386::do_is_call_to_non_split(const Symbol* sym, + const unsigned char*) const { return (sym->type() == elfcpp::STT_FUNC && !is_prefix_of("__i686.get_pc_thunk.", sym->name())); diff --git a/gold/mips.cc b/gold/mips.cc index 3d513ff..c57ef4f 100644 --- a/gold/mips.cc +++ b/gold/mips.cc @@ -2642,9 +2642,9 @@ class Mips_output_section_reginfo : public Output_section // The MIPS target has relocation types which default handling of relocatable // relocation cannot process. So we have to extend the default code. -template +template class Mips_scan_relocatable_relocs : - public Default_scan_relocatable_relocs + public Default_scan_relocatable_relocs { public: // Return the strategy to use for a local symbol which is a section @@ -2652,7 +2652,7 @@ class Mips_scan_relocatable_relocs : inline Relocatable_relocs::Reloc_strategy local_section_strategy(unsigned int r_type, Relobj* object) { - if (sh_type == elfcpp::SHT_RELA) + if (Classify_reloc::sh_type == elfcpp::SHT_RELA) return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA; else { @@ -2662,7 +2662,7 @@ class Mips_scan_relocatable_relocs : return Relocatable_relocs::RELOC_SPECIAL; default: - return Default_scan_relocatable_relocs:: + return Default_scan_relocatable_relocs:: local_section_strategy(r_type, object); } } @@ -2860,6 +2860,182 @@ class Symbol_visitor_check_symbols Symbol_table* symtab_; }; +// Relocation types, parameterized by SHT_REL vs. SHT_RELA, size, +// and endianness. The relocation format for MIPS-64 is non-standard. + +template +struct Mips_reloc_types; + +template +struct Mips_reloc_types +{ + typedef typename elfcpp::Rel<32, big_endian> Reloc; + typedef typename elfcpp::Rel_write<32, big_endian> Reloc_write; + + static unsigned typename elfcpp::Elf_types<32>::Elf_Swxword + get_r_addend(const Reloc*) + { return 0; } + + static inline void + set_reloc_addend(Reloc_write*, + typename elfcpp::Elf_types<32>::Elf_Swxword) + { gold_unreachable(); } +}; + +template +struct Mips_reloc_types +{ + typedef typename elfcpp::Rela<32, big_endian> Reloc; + typedef typename elfcpp::Rela_write<32, big_endian> Reloc_write; + + static unsigned typename elfcpp::Elf_types<32>::Elf_Swxword + get_r_addend(const Reloc* reloc) + { return reloc->get_r_addend(); } + + static inline void + set_reloc_addend(Reloc_write* p, + typename elfcpp::Elf_types<32>::Elf_Swxword val) + { p->put_r_addend(val); } +}; + +template +struct Mips_reloc_types +{ + typedef typename elfcpp::Mips64_rel Reloc; + typedef typename elfcpp::Mips64_rel_write Reloc_write; + + static unsigned typename elfcpp::Elf_types<64>::Elf_Swxword + get_r_addend(const Reloc*) + { return 0; } + + static inline void + set_reloc_addend(Reloc_write*, + typename elfcpp::Elf_types<64>::Elf_Swxword) + { gold_unreachable(); } +}; + +template +struct Mips_reloc_types +{ + typedef typename elfcpp::Mips64_rela Reloc; + typedef typename elfcpp::Mips64_rela_write Reloc_write; + + static unsigned typename elfcpp::Elf_types<64>::Elf_Swxword + get_r_addend(const Reloc* reloc) + { return reloc->get_r_addend(); } + + static inline void + set_reloc_addend(Reloc_write* p, + typename elfcpp::Elf_types<64>::Elf_Swxword val) + { p->put_r_addend(val); } +}; + +// Forward declaration. +static unsigned int +mips_get_size_for_reloc(unsigned int, Relobj*); + +// A class for inquiring about properties of a relocation, +// used while scanning relocs during a relocatable link and +// garbage collection. + +template +class Mips_classify_reloc; + +template +class Mips_classify_reloc : + public gold::Default_classify_reloc +{ + public: + typedef typename Mips_reloc_types::Reloc + Reltype; + typedef typename Mips_reloc_types::Reloc_write + Reltype_write; + + // Return the symbol referred to by the relocation. + static inline unsigned int + get_r_sym(const Reltype* reloc) + { return elfcpp::elf_r_sym<32>(reloc->get_r_info()); } + + // Return the type of the relocation. + static inline unsigned int + get_r_type(const Reltype* reloc) + { return elfcpp::elf_r_type<32>(reloc->get_r_info()); } + + // Return the explicit addend of the relocation (return 0 for SHT_REL). + static inline unsigned int + get_r_addend(const Reltype* reloc) + { return Mips_reloc_types::get_r_addend(reloc); } + + // Write the r_info field to a new reloc, using the r_info field from + // the original reloc, replacing the r_sym field with R_SYM. + static inline void + put_r_info(Reltype_write* new_reloc, Reltype* reloc, unsigned int r_sym) + { + unsigned int r_type = elfcpp::elf_r_type<32>(reloc->get_r_info()); + new_reloc->put_r_info(elfcpp::elf_r_info<64>(r_sym, r_type)); + } + + // Write the r_addend field to a new reloc. + static inline void + put_r_addend(Reltype_write* to, + typename elfcpp::Elf_types<32>::Elf_Swxword addend) + { Mips_reloc_types::set_reloc_addend(to, addend); } + + // Return the size of the addend of the relocation (only used for SHT_REL). + static unsigned int + get_size_for_reloc(unsigned int r_type, Relobj* obj) + { return mips_get_size_for_reloc(r_type, obj); } +}; + +template +class Mips_classify_reloc : + public gold::Default_classify_reloc +{ + public: + typedef typename Mips_reloc_types::Reloc + Reltype; + typedef typename Mips_reloc_types::Reloc_write + Reltype_write; + + // Return the symbol referred to by the relocation. + static inline unsigned int + get_r_sym(const Reltype* reloc) + { return reloc->get_r_sym(); } + + // Return the type of the relocation. + static inline unsigned int + get_r_type(const Reltype* reloc) + { return reloc->get_r_type(); } + + // Return the explicit addend of the relocation (return 0 for SHT_REL). + static inline typename elfcpp::Elf_types<64>::Elf_Swxword + get_r_addend(const Reltype* reloc) + { return Mips_reloc_types::get_r_addend(reloc); } + + // Write the r_info field to a new reloc, using the r_info field from + // the original reloc, replacing the r_sym field with R_SYM. + static inline void + put_r_info(Reltype_write* new_reloc, Reltype* reloc, unsigned int r_sym) + { + new_reloc->put_r_sym(r_sym); + new_reloc->put_r_ssym(reloc->get_r_ssym()); + new_reloc->put_r_type3(reloc->get_r_type3()); + new_reloc->put_r_type2(reloc->get_r_type2()); + new_reloc->put_r_type(reloc->get_r_type()); + } + + // Write the r_addend field to a new reloc. + static inline void + put_r_addend(Reltype_write* to, + typename elfcpp::Elf_types<64>::Elf_Swxword addend) + { Mips_reloc_types::set_reloc_addend(to, addend); } + + // Return the size of the addend of the relocation (only used for SHT_REL). + static unsigned int + get_size_for_reloc(unsigned int r_type, Relobj* obj) + { return mips_get_size_for_reloc(r_type, obj); } +}; + template class Target_mips : public Sized_target { @@ -2870,6 +3046,10 @@ class Target_mips : public Sized_target Reloca_section; typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype32; typedef typename elfcpp::Swap::Valtype Valtype; + typedef typename Mips_reloc_types::Reloc + Reltype; + typedef typename Mips_reloc_types::Reloc + Relatype; public: Target_mips(const Target::Target_info* info = &mips_info) @@ -2955,6 +3135,21 @@ class Target_mips : public Sized_target const unsigned char* plocal_symbols, Relocatable_relocs*); + // Scan the relocs for --emit-relocs. + void + emit_relocs_scan(Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr); + // Emit relocations for a section. void relocate_relocs(const Relocate_info*, @@ -3164,6 +3359,17 @@ class Target_mips : public Sized_target use_32bit_micromips_instructions() const { return this->insn32_; } + // Return the r_sym field from a relocation. + unsigned int + get_r_sym(const unsigned char* preloc) const + { + // Since REL and RELA relocs share the same structure through + // the r_info field, we can just use REL here. + Reltype rel(preloc); + return Mips_classify_reloc:: + get_r_sym(&rel); + } + protected: // Return the value to use for a dynamic symbol which requires special // treatment. This is how we support equality comparisons of function @@ -3268,7 +3474,7 @@ class Target_mips : public Sized_target Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, - const elfcpp::Rel& reloc, unsigned int r_type, + const Reltype& reloc, unsigned int r_type, const elfcpp::Sym& lsym, bool is_discarded); @@ -3277,7 +3483,7 @@ class Target_mips : public Sized_target Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, - const elfcpp::Rela& reloc, unsigned int r_type, + const Relatype& reloc, unsigned int r_type, const elfcpp::Sym& lsym, bool is_discarded); @@ -3286,8 +3492,8 @@ class Target_mips : public Sized_target Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, - const elfcpp::Rela* rela, - const elfcpp::Rel* rel, + const Relatype* rela, + const Reltype* rel, unsigned int rel_type, unsigned int r_type, const elfcpp::Sym& lsym, @@ -3298,7 +3504,7 @@ class Target_mips : public Sized_target Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, - const elfcpp::Rel& reloc, unsigned int r_type, + const Reltype& reloc, unsigned int r_type, Symbol* gsym); inline void @@ -3306,7 +3512,7 @@ class Target_mips : public Sized_target Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, - const elfcpp::Rela& reloc, unsigned int r_type, + const Relatype& reloc, unsigned int r_type, Symbol* gsym); inline void @@ -3314,8 +3520,8 @@ class Target_mips : public Sized_target Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, - const elfcpp::Rela* rela, - const elfcpp::Rel* rel, + const Relatype* rela, + const Reltype* rel, unsigned int rel_type, unsigned int r_type, Symbol* gsym); @@ -3326,7 +3532,7 @@ class Target_mips : public Sized_target Sized_relobj_file*, unsigned int, Output_section*, - const elfcpp::Rel&, + const Reltype&, unsigned int, const elfcpp::Sym&) { return false; } @@ -3337,7 +3543,7 @@ class Target_mips : public Sized_target Sized_relobj_file*, unsigned int, Output_section*, - const elfcpp::Rel&, + const Reltype&, unsigned int, Symbol*) { return false; } @@ -3347,7 +3553,7 @@ class Target_mips : public Sized_target Sized_relobj_file*, unsigned int, Output_section*, - const elfcpp::Rela&, + const Relatype&, unsigned int, const elfcpp::Sym&) { return false; } @@ -3358,7 +3564,7 @@ class Target_mips : public Sized_target Sized_relobj_file*, unsigned int, Output_section*, - const elfcpp::Rela&, + const Relatype&, unsigned int, Symbol*) { return false; } private: @@ -3397,15 +3603,6 @@ class Target_mips : public Sized_target unsigned char*, Mips_address, section_size_type); }; - // A class which returns the size required for a relocation type, - // used while scanning relocs during a relocatable link. - class Relocatable_size_for_reloc - { - public: - unsigned int - get_size_for_reloc(unsigned int, Relobj*); - }; - // This POD class holds the dynamic relocations that should be emitted instead // of R_MIPS_32, R_MIPS_REL32 and R_MIPS_64 relocations. We will emit these // relocations if it turns out that the symbol does not have static @@ -3573,9 +3770,11 @@ class Target_mips : public Sized_target copy_reloc(Symbol_table* symtab, Layout* layout, Sized_relobj_file* object, unsigned int shndx, Output_section* output_section, - Symbol* sym, const elfcpp::Rel& reloc) + Symbol* sym, const Reltype& reloc) { - unsigned int r_type = elfcpp::elf_r_type(reloc.get_r_info()); + unsigned int r_type = + Mips_classify_reloc:: + get_r_type(&reloc); this->copy_relocs_.copy_reloc(symtab, layout, symtab->get_sized_symbol(sym), object, shndx, output_section, @@ -3725,7 +3924,6 @@ class Target_mips : public Sized_target bool insn32_; }; - // Helper structure for R_MIPS*_HI16/LO16 and R_MIPS*_GOT16/LO16 relocations. // It records high part of the relocation pair. @@ -7510,10 +7708,10 @@ Target_mips::gc_process_relocs( const unsigned char* plocal_symbols) { typedef Target_mips Mips; - typedef typename Target_mips::Scan Scan; + typedef Mips_classify_reloc + Classify_reloc; - gold::gc_process_relocs( + gold::gc_process_relocs( symtab, layout, this, @@ -7545,34 +7743,43 @@ Target_mips::scan_relocs( const unsigned char* plocal_symbols) { typedef Target_mips Mips; - typedef typename Target_mips::Scan Scan; if (sh_type == elfcpp::SHT_REL) - gold::scan_relocs( - symtab, - layout, - this, - object, - data_shndx, - prelocs, - reloc_count, - output_section, - needs_special_offset_handling, - local_symbol_count, - plocal_symbols); + { + typedef Mips_classify_reloc + Classify_reloc; + + gold::scan_relocs( + symtab, + layout, + this, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols); + } else if (sh_type == elfcpp::SHT_RELA) - gold::scan_relocs( - symtab, - layout, - this, - object, - data_shndx, - prelocs, - reloc_count, - output_section, - needs_special_offset_handling, - local_symbol_count, - plocal_symbols); + { + typedef Mips_classify_reloc + Classify_reloc; + + gold::scan_relocs( + symtab, + layout, + this, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols); + } } template @@ -8227,41 +8434,48 @@ Target_mips::relocate_section( typedef typename Target_mips::Relocate Mips_relocate; if (sh_type == elfcpp::SHT_REL) - gold::relocate_section( - relinfo, - this, - prelocs, - reloc_count, - output_section, - needs_special_offset_handling, - view, - address, - view_size, - reloc_symbol_changes); + { + typedef Mips_classify_reloc + Classify_reloc; + + gold::relocate_section( + relinfo, + this, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + view, + address, + view_size, + reloc_symbol_changes); + } else if (sh_type == elfcpp::SHT_RELA) - gold::relocate_section( - relinfo, - this, - prelocs, - reloc_count, - output_section, - needs_special_offset_handling, - view, - address, - view_size, - reloc_symbol_changes); + { + typedef Mips_classify_reloc + Classify_reloc; + + gold::relocate_section( + relinfo, + this, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + view, + address, + view_size, + reloc_symbol_changes); + } } // Return the size of a relocation while scanning during a relocatable // link. -template unsigned int -Target_mips::Relocatable_size_for_reloc::get_size_for_reloc( - unsigned int r_type, - Relobj* object) +mips_get_size_for_reloc(unsigned int r_type, Relobj* object) { switch (r_type) { @@ -8344,13 +8558,14 @@ Target_mips::scan_relocatable_relocs( const unsigned char* plocal_symbols, Relocatable_relocs* rr) { - gold_assert(sh_type == elfcpp::SHT_REL); + typedef Mips_classify_reloc + Classify_reloc; + typedef Mips_scan_relocatable_relocs + Scan_relocatable_relocs; - typedef Mips_scan_relocatable_relocs Scan_relocatable_relocs; + gold_assert(sh_type == elfcpp::SHT_REL); - gold::scan_relocatable_relocs( + gold::scan_relocatable_relocs( symtab, layout, object, @@ -8364,6 +8579,45 @@ Target_mips::scan_relocatable_relocs( rr); } +// Scan the relocs for --emit-relocs. + +template +void +Target_mips::emit_relocs_scan( + Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr) +{ + typedef Mips_classify_reloc + Classify_reloc; + typedef gold::Default_emit_relocs_strategy + Emit_relocs_strategy; + + gold_assert(sh_type == elfcpp::SHT_REL); + + gold::scan_relocatable_relocs( + symtab, + layout, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_syms, + rr); +} + // Emit relocations for a section. template @@ -8382,9 +8636,12 @@ Target_mips::relocate_relocs( unsigned char* reloc_view, section_size_type reloc_view_size) { + typedef Mips_classify_reloc + Classify_reloc; + gold_assert(sh_type == elfcpp::SHT_REL); - gold::relocate_relocs( + gold::relocate_relocs( relinfo, prelocs, reloc_count, @@ -8550,8 +8807,8 @@ Target_mips::Scan::local( Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, - const elfcpp::Rela* rela, - const elfcpp::Rel* rel, + const Relatype* rela, + const Reltype* rel, unsigned int rel_type, unsigned int r_type, const elfcpp::Sym& lsym, @@ -8561,23 +8818,24 @@ Target_mips::Scan::local( return; Mips_address r_offset; - typename elfcpp::Elf_types::Elf_WXword r_info; + unsigned int r_sym; typename elfcpp::Elf_types::Elf_Swxword r_addend; if (rel_type == elfcpp::SHT_RELA) { r_offset = rela->get_r_offset(); - r_info = rela->get_r_info(); + r_sym = Mips_classify_reloc:: + get_r_sym(rela); r_addend = rela->get_r_addend(); } else { r_offset = rel->get_r_offset(); - r_info = rel->get_r_info(); + r_sym = Mips_classify_reloc:: + get_r_sym(rel); r_addend = 0; } - unsigned int r_sym = elfcpp::elf_r_sym(r_info); Mips_relobj* mips_obj = Mips_relobj::as_mips_relobj(object); @@ -8655,7 +8913,6 @@ Target_mips::Scan::local( // R_MIPS_GOT_LO16 or R_MIPS_CALL_LO16. Mips_output_data_got* got = target->got_section(symtab, layout); - unsigned int r_sym = elfcpp::elf_r_sym(r_info); got->record_local_got_symbol(mips_obj, r_sym, r_addend, r_type, -1U); } @@ -8790,7 +9047,6 @@ Target_mips::Scan::local( // executable), we need to create a dynamic relocation for // this location. Reloc_section* rel_dyn = target->rel_dyn_section(layout); - unsigned int r_sym = elfcpp::elf_r_sym<32>(r_info); rel_dyn->add_symbolless_local_addend(object, r_sym, elfcpp::R_MIPS_REL32, output_section, data_shndx, @@ -8809,7 +9065,6 @@ Target_mips::Scan::local( case elfcpp::R_MIPS16_TLS_GD: case elfcpp::R_MICROMIPS_TLS_GD: { - unsigned int r_sym = elfcpp::elf_r_sym(r_info); bool output_is_shared = parameters->options().shared(); const tls::Tls_optimization optimized_type = Target_mips::optimize_tls_reloc( @@ -8929,7 +9184,7 @@ Target_mips::Scan::local( Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, - const elfcpp::Rel& reloc, + const Reltype& reloc, unsigned int r_type, const elfcpp::Sym& lsym, bool is_discarded) @@ -8944,7 +9199,7 @@ Target_mips::Scan::local( object, data_shndx, output_section, - (const elfcpp::Rela*) NULL, + (const Relatype*) NULL, &reloc, elfcpp::SHT_REL, r_type, @@ -8961,7 +9216,7 @@ Target_mips::Scan::local( Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, - const elfcpp::Rela& reloc, + const Relatype& reloc, unsigned int r_type, const elfcpp::Sym& lsym, bool is_discarded) @@ -8977,7 +9232,7 @@ Target_mips::Scan::local( data_shndx, output_section, &reloc, - (const elfcpp::Rel*) NULL, + (const Reltype*) NULL, elfcpp::SHT_RELA, r_type, lsym, is_discarded); @@ -8994,30 +9249,31 @@ Target_mips::Scan::global( Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, - const elfcpp::Rela* rela, - const elfcpp::Rel* rel, + const Relatype* rela, + const Reltype* rel, unsigned int rel_type, unsigned int r_type, Symbol* gsym) { Mips_address r_offset; - typename elfcpp::Elf_types::Elf_WXword r_info; + unsigned int r_sym; typename elfcpp::Elf_types::Elf_Swxword r_addend; if (rel_type == elfcpp::SHT_RELA) { r_offset = rela->get_r_offset(); - r_info = rela->get_r_info(); + r_sym = Mips_classify_reloc:: + get_r_sym(rela); r_addend = rela->get_r_addend(); } else { r_offset = rel->get_r_offset(); - r_info = rel->get_r_info(); + r_sym = Mips_classify_reloc:: + get_r_sym(rel); r_addend = 0; } - unsigned int r_sym = elfcpp::elf_r_sym(r_info); Mips_relobj* mips_obj = Mips_relobj::as_mips_relobj(object); Mips_symbol* mips_sym = Mips_symbol::as_mips_sym(gsym); @@ -9434,7 +9690,7 @@ Target_mips::Scan::global( Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, - const elfcpp::Rela& reloc, + const Relatype& reloc, unsigned int r_type, Symbol* gsym) { @@ -9446,7 +9702,7 @@ Target_mips::Scan::global( data_shndx, output_section, &reloc, - (const elfcpp::Rel*) NULL, + (const Reltype*) NULL, elfcpp::SHT_RELA, r_type, gsym); @@ -9461,7 +9717,7 @@ Target_mips::Scan::global( Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, - const elfcpp::Rel& reloc, + const Reltype& reloc, unsigned int r_type, Symbol* gsym) { @@ -9472,7 +9728,7 @@ Target_mips::Scan::global( object, data_shndx, output_section, - (const elfcpp::Rela*) NULL, + (const Relatype*) NULL, &reloc, elfcpp::SHT_REL, r_type, @@ -9546,32 +9802,38 @@ Target_mips::Relocate::relocate( section_size_type) { Mips_address r_offset; - typename elfcpp::Elf_types::Elf_WXword r_info; + unsigned int r_sym; + unsigned int r_type; typename elfcpp::Elf_types::Elf_Swxword r_addend; if (rel_type == elfcpp::SHT_RELA) { - const elfcpp::Rela rela(preloc); + const Relatype rela(preloc); r_offset = rela.get_r_offset(); - r_info = rela.get_r_info(); + r_sym = Mips_classify_reloc:: + get_r_sym(&rela); + r_type = Mips_classify_reloc:: + get_r_type(&rela); r_addend = rela.get_r_addend(); } else { - const elfcpp::Rel rel(preloc); + + const Reltype rel(preloc); r_offset = rel.get_r_offset(); - r_info = rel.get_r_info(); + r_sym = Mips_classify_reloc:: + get_r_sym(&rel); + r_type = Mips_classify_reloc:: + get_r_type(&rel); r_addend = 0; } - unsigned int r_type = elfcpp::elf_r_type(r_info); typedef Mips_relocate_functions Reloc_funcs; typename Reloc_funcs::Status reloc_status = Reloc_funcs::STATUS_OKAY; Mips_relobj* object = - Mips_relobj::as_mips_relobj(relinfo->object); + Mips_relobj::as_mips_relobj(relinfo->object); - unsigned int r_sym = elfcpp::elf_r_sym(r_info); bool target_is_16_bit_code = false; bool target_is_micromips_code = false; bool cross_mode_jump; diff --git a/gold/object.h b/gold/object.h index 25af341..95f6d56 100644 --- a/gold/object.h +++ b/gold/object.h @@ -2710,7 +2710,8 @@ class Sized_relobj_file : public Sized_relobj unsigned int sh_type, unsigned int shndx, const unsigned char* prelocs, size_t reloc_count, unsigned char* view, section_size_type view_size, - Reloc_symbol_changes** reloc_map); + Reloc_symbol_changes** reloc_map, + const Sized_target* target); template void @@ -2718,7 +2719,8 @@ class Sized_relobj_file : public Sized_relobj unsigned int shndx, const unsigned char* prelocs, size_t reloc_count, unsigned char* view, section_size_type view_size, - Reloc_symbol_changes** reloc_map); + Reloc_symbol_changes** reloc_map, + const Sized_target* target); // Find all functions in a section. void diff --git a/gold/powerpc.cc b/gold/powerpc.cc index b1c5aea..e26a198 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -663,6 +663,21 @@ class Target_powerpc : public Sized_target const unsigned char* plocal_symbols, Relocatable_relocs*); + // Scan the relocs for --emit-relocs. + void + emit_relocs_scan(Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr); + // Emit relocations for a section. void relocate_relocs(const Relocate_info*, @@ -1105,19 +1120,6 @@ class Target_powerpc : public Sized_target } }; - // A class which returns the size required for a relocation type, - // used while scanning relocs during a relocatable link. - class Relocatable_size_for_reloc - { - public: - unsigned int - get_size_for_reloc(unsigned int, Relobj*) - { - gold_unreachable(); - return 0; - } - }; - // Optimize the TLS relocation type based on what we know about the // symbol. IS_FINAL is true if the final address of this symbol is // known at link time. @@ -6430,7 +6432,9 @@ Target_powerpc::gc_process_relocs( const unsigned char* plocal_symbols) { typedef Target_powerpc Powerpc; - typedef typename Target_powerpc::Scan Scan; + typedef gold::Default_classify_reloc + Classify_reloc; + Powerpc_relobj* ppc_object = static_cast*>(object); if (size == 64) @@ -6460,8 +6464,7 @@ Target_powerpc::gc_process_relocs( return; } - gold::gc_process_relocs( + gold::gc_process_relocs( symtab, layout, this, @@ -6707,7 +6710,8 @@ Target_powerpc::scan_relocs( const unsigned char* plocal_symbols) { typedef Target_powerpc Powerpc; - typedef typename Target_powerpc::Scan Scan; + typedef gold::Default_classify_reloc + Classify_reloc; if (sh_type == elfcpp::SHT_REL) { @@ -6716,7 +6720,7 @@ Target_powerpc::scan_relocs( return; } - gold::scan_relocs( + gold::scan_relocs( symtab, layout, this, @@ -8177,11 +8181,13 @@ Target_powerpc::relocate_section( typedef typename Target_powerpc::Relocate Powerpc_relocate; typedef typename Target_powerpc::Relocate_comdat_behavior Powerpc_comdat_behavior; + typedef gold::Default_classify_reloc + Classify_reloc; gold_assert(sh_type == elfcpp::SHT_RELA); - gold::relocate_section( + gold::relocate_section( relinfo, this, prelocs, @@ -8194,9 +8200,26 @@ Target_powerpc::relocate_section( reloc_symbol_changes); } +template class Powerpc_scan_relocatable_reloc { public: + typedef typename Reloc_types::Reloc + Reltype; + static const int reloc_size = + Reloc_types::reloc_size; + static const int sh_type = elfcpp::SHT_RELA; + + // Return the symbol referred to by the relocation. + static inline unsigned int + get_r_sym(const Reltype* reloc) + { return elfcpp::elf_r_sym(reloc->get_r_info()); } + + // Return the type of the relocation. + static inline unsigned int + get_r_type(const Reltype* reloc) + { return elfcpp::elf_r_type(reloc->get_r_info()); } + // Return the strategy to use for a local symbol which is not a // section symbol, given the relocation type. inline Relocatable_relocs::Reloc_strategy @@ -8244,10 +8267,11 @@ Target_powerpc::scan_relocatable_relocs( const unsigned char* plocal_symbols, Relocatable_relocs* rr) { + typedef Powerpc_scan_relocatable_reloc Scan_strategy; + gold_assert(sh_type == elfcpp::SHT_RELA); - gold::scan_relocatable_relocs( + gold::scan_relocatable_relocs( symtab, layout, object, @@ -8261,6 +8285,45 @@ Target_powerpc::scan_relocatable_relocs( rr); } +// Scan the relocs for --emit-relocs. + +template +void +Target_powerpc::emit_relocs_scan( + Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr) +{ + typedef gold::Default_classify_reloc + Classify_reloc; + typedef gold::Default_emit_relocs_strategy + Emit_relocs_strategy; + + gold_assert(sh_type == elfcpp::SHT_RELA); + + gold::scan_relocatable_relocs( + symtab, + layout, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_syms, + rr); +} + // Emit relocations for a section. // This is a modified version of the function by the same name in // target-reloc.h. Using relocate_special_relocatable for diff --git a/gold/reloc-types.h b/gold/reloc-types.h index b42be59..7334b9f 100644 --- a/gold/reloc-types.h +++ b/gold/reloc-types.h @@ -56,10 +56,6 @@ struct Reloc_types set_reloc_addend(Reloc_write*, typename elfcpp::Elf_types::Elf_Swxword) { gold_unreachable(); } - - static inline void - copy_reloc_addend(Reloc_write*, const Reloc*) - { gold_unreachable(); } }; template @@ -81,10 +77,6 @@ struct Reloc_types set_reloc_addend(Reloc_write* p, typename elfcpp::Elf_types::Elf_Swxword val) { p->put_r_addend(val); } - - static inline void - copy_reloc_addend(Reloc_write* to, const Reloc* from) - { to->put_r_addend(from->get_r_addend()); } }; }; // End namespace gold. diff --git a/gold/reloc.cc b/gold/reloc.cc index 3354019..b1a50e6 100644 --- a/gold/reloc.cc +++ b/gold/reloc.cc @@ -424,8 +424,8 @@ Sized_relobj_file::do_gc_process_relocs(Symbol_table* symtab, template void Sized_relobj_file::do_scan_relocs(Symbol_table* symtab, - Layout* layout, - Read_relocs_data* rd) + Layout* layout, + Read_relocs_data* rd) { Sized_target* target = parameters->sized_target(); @@ -501,41 +501,6 @@ Sized_relobj_file::do_scan_relocs(Symbol_table* symtab, } } -// This is a strategy class we use when scanning for --emit-relocs. - -template -class Emit_relocs_strategy -{ - public: - // A local non-section symbol. - inline Relocatable_relocs::Reloc_strategy - local_non_section_strategy(unsigned int, Relobj*, unsigned int) - { return Relocatable_relocs::RELOC_COPY; } - - // A local section symbol. - inline Relocatable_relocs::Reloc_strategy - local_section_strategy(unsigned int, Relobj*) - { - if (sh_type == elfcpp::SHT_RELA) - return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA; - else - { - // The addend is stored in the section contents. Since this - // is not a relocatable link, we are going to apply the - // relocation contents to the section as usual. This means - // that we have no way to record the original addend. If the - // original addend is not zero, there is basically no way for - // the user to handle this correctly. Caveat emptor. - return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0; - } - } - - // A global symbol. - inline Relocatable_relocs::Reloc_strategy - global_strategy(unsigned int, Relobj*, unsigned int) - { return Relocatable_relocs::RELOC_COPY; } -}; - // Scan the input relocations for --emit-relocs. template @@ -546,40 +511,18 @@ Sized_relobj_file::emit_relocs_scan( const unsigned char* plocal_syms, const Read_relocs_data::Relocs_list::iterator& p) { + Sized_target* target = + parameters->sized_target(); + Relocatable_relocs* rr = this->relocatable_relocs(p->reloc_shndx); gold_assert(rr != NULL); rr->set_reloc_count(p->reloc_count); - - if (p->sh_type == elfcpp::SHT_REL) - this->emit_relocs_scan_reltype(symtab, layout, - plocal_syms, p, rr); - else - { - gold_assert(p->sh_type == elfcpp::SHT_RELA); - this->emit_relocs_scan_reltype(symtab, layout, - plocal_syms, p, rr); - } -} - -// Scan the input relocation for --emit-relocs, templatized on the -// type of the relocation section. - -template -template -void -Sized_relobj_file::emit_relocs_scan_reltype( - Symbol_table* symtab, - Layout* layout, - const unsigned char* plocal_syms, - const Read_relocs_data::Relocs_list::iterator& p, - Relocatable_relocs* rr) -{ - scan_relocatable_relocs >( + target->emit_relocs_scan( symtab, layout, this, p->data_shndx, + p->sh_type, p->contents->data(), p->reloc_count, p->output_section, @@ -628,8 +571,8 @@ Sized_relobj_file::incremental_relocs_scan_reltype( reloc.get_r_offset())) continue; - typename elfcpp::Elf_types::Elf_WXword r_info = - reloc.get_r_info(); + // FIXME: Some targets have a non-standard r_info field. + typename elfcpp::Elf_types::Elf_WXword r_info = reloc.get_r_info(); const unsigned int r_sym = elfcpp::elf_r_sym(r_info); if (r_sym >= this->local_symbol_count_) @@ -1025,7 +968,7 @@ Sized_relobj_file::do_relocate_sections( if ((data_shdr.get_sh_flags() & elfcpp::SHF_EXECINSTR) != 0) this->split_stack_adjust(symtab, pshdrs, sh_type, index, prelocs, reloc_count, view, view_size, - &reloc_map); + &reloc_map, target); } Relocatable_relocs* rr = NULL; @@ -1142,6 +1085,7 @@ Sized_relobj_file::incremental_relocs_write_reltype( { Reloc reloc(prelocs); + // FIXME: Some targets have a non-standard r_info field. typename elfcpp::Elf_types::Elf_WXword r_info = reloc.get_r_info(); const unsigned int r_sym = elfcpp::elf_r_sym(r_info); const unsigned int r_type = elfcpp::elf_r_type(r_info); @@ -1240,20 +1184,21 @@ Sized_relobj_file::split_stack_adjust( size_t reloc_count, unsigned char* view, section_size_type view_size, - Reloc_symbol_changes** reloc_map) + Reloc_symbol_changes** reloc_map, + const Sized_target* target) { if (sh_type == elfcpp::SHT_REL) this->split_stack_adjust_reltype(symtab, pshdrs, shndx, prelocs, reloc_count, view, view_size, - reloc_map); + reloc_map, target); else { gold_assert(sh_type == elfcpp::SHT_RELA); this->split_stack_adjust_reltype(symtab, pshdrs, shndx, prelocs, reloc_count, view, view_size, - reloc_map); + reloc_map, target); } } @@ -1271,7 +1216,8 @@ Sized_relobj_file::split_stack_adjust_reltype( size_t reloc_count, unsigned char* view, section_size_type view_size, - Reloc_symbol_changes** reloc_map) + Reloc_symbol_changes** reloc_map, + const Sized_target* target) { typedef typename Reloc_types::Reloc Reltype; const int reloc_size = Reloc_types::reloc_size; @@ -1283,10 +1229,10 @@ Sized_relobj_file::split_stack_adjust_reltype( const unsigned char* pr = prelocs; for (size_t i = 0; i < reloc_count; ++i, pr += reloc_size) { - Reltype reloc(pr); - - typename elfcpp::Elf_types::Elf_WXword r_info = reloc.get_r_info(); - unsigned int r_sym = elfcpp::elf_r_sym(r_info); + // Some supported targets have a non-standard r_info field. + // If this call is too slow, we can move this routine to + // target-reloc.h and templatize it on Classify_reloc. + unsigned int r_sym = target->get_r_sym(pr); if (r_sym < local_count) continue; @@ -1305,9 +1251,9 @@ Sized_relobj_file::split_stack_adjust_reltype( && gsym->source() == Symbol::FROM_OBJECT && !gsym->object()->uses_split_stack()) { - unsigned int r_type = elfcpp::elf_r_type(reloc.get_r_info()); - if (parameters->target().is_call_to_non_split(gsym, r_type)) + if (parameters->target().is_call_to_non_split(gsym, pr)) { + Reltype reloc(pr); section_offset_type offset = convert_to_section_size_type(reloc.get_r_offset()); non_split_refs.push_back(offset); @@ -1378,9 +1324,7 @@ Sized_relobj_file::split_stack_adjust_reltype( { Reltype reloc(pr); - typename elfcpp::Elf_types::Elf_WXword r_info = - reloc.get_r_info(); - unsigned int r_sym = elfcpp::elf_r_sym(r_info); + unsigned int r_sym = target->get_r_sym(pr); if (r_sym < local_count) continue; @@ -1600,11 +1544,9 @@ Track_relocs::next_symndx() const { if (this->pos_ >= this->len_) return -1U; - - // Rel and Rela start out the same, so we can use Rel to find the - // symbol index. - elfcpp::Rel rel(this->prelocs_ + this->pos_); - return elfcpp::elf_r_sym(rel.get_r_info()); + Sized_target* target + = parameters->sized_target(); + return target->get_r_sym(this->prelocs_ + this->pos_); } // Return the addend of the next reloc, or 0 if there isn't one. diff --git a/gold/s390.cc b/gold/s390.cc index eb92fb7..2671441 100644 --- a/gold/s390.cc +++ b/gold/s390.cc @@ -348,6 +348,21 @@ class Target_s390 : public Sized_target const unsigned char* plocal_symbols, Relocatable_relocs*); + // Scan the relocs for --emit-relocs. + void + emit_relocs_scan(Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr); + // Return a string used to fill a code section with nops. std::string do_code_fill(section_size_type length) const; @@ -596,15 +611,6 @@ class Target_s390 : public Sized_target section_size_type view_size); }; - // A class which returns the size required for a relocation type, - // used while scanning relocs during a relocatable link. - class Relocatable_size_for_reloc - { - public: - unsigned int - get_size_for_reloc(unsigned int, Relobj*); - }; - // Adjust TLS relocation type based on the options and whether this // is a local symbol. static tls::Tls_optimization @@ -3086,13 +3092,13 @@ Target_s390::gc_process_relocs(Symbol_table* symtab, size_t local_symbol_count, const unsigned char* plocal_symbols) { + typedef gold::Default_classify_reloc + Classify_reloc; if (sh_type == elfcpp::SHT_REL) return; - gold::gc_process_relocs, elfcpp::SHT_RELA, - typename Target_s390::Scan, - typename Target_s390::Relocatable_size_for_reloc>( + gold::gc_process_relocs, Scan, Classify_reloc>( symtab, layout, this, @@ -3924,6 +3930,9 @@ Target_s390::scan_relocs(Symbol_table* symtab, size_t local_symbol_count, const unsigned char* plocal_symbols) { + typedef gold::Default_classify_reloc + Classify_reloc; + if (sh_type == elfcpp::SHT_REL) { gold_error(_("%s: unsupported REL reloc section"), @@ -3931,8 +3940,7 @@ Target_s390::scan_relocs(Symbol_table* symtab, return; } - gold::scan_relocs, elfcpp::SHT_RELA, - typename Target_s390::Scan>( + gold::scan_relocs, Scan, Classify_reloc>( symtab, layout, this, @@ -4019,113 +4027,50 @@ Target_s390::do_finalize_sections( } } -// Return the size of a relocation while scanning during a relocatable -// link. +// Scan the relocs during a relocatable link. template -unsigned int -Target_s390::Relocatable_size_for_reloc::get_size_for_reloc( - unsigned int r_type, - Relobj* object) +void +Target_s390::scan_relocatable_relocs( + Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols, + Relocatable_relocs* rr) { - switch (r_type) - { - case elfcpp::R_390_NONE: - case elfcpp::R_390_GNU_VTINHERIT: - case elfcpp::R_390_GNU_VTENTRY: - case elfcpp::R_390_TLS_GD32: // Global-dynamic - case elfcpp::R_390_TLS_GD64: - case elfcpp::R_390_TLS_GDCALL: - case elfcpp::R_390_TLS_LDM32: // Local-dynamic - case elfcpp::R_390_TLS_LDM64: - case elfcpp::R_390_TLS_LDO32: - case elfcpp::R_390_TLS_LDO64: - case elfcpp::R_390_TLS_LDCALL: - case elfcpp::R_390_TLS_IE32: // Initial-exec - case elfcpp::R_390_TLS_IE64: - case elfcpp::R_390_TLS_IEENT: - case elfcpp::R_390_TLS_GOTIE12: - case elfcpp::R_390_TLS_GOTIE20: - case elfcpp::R_390_TLS_GOTIE32: - case elfcpp::R_390_TLS_GOTIE64: - case elfcpp::R_390_TLS_LOAD: - case elfcpp::R_390_TLS_LE32: // Local-exec - case elfcpp::R_390_TLS_LE64: - return 0; - - case elfcpp::R_390_64: - case elfcpp::R_390_PC64: - case elfcpp::R_390_GOT64: - case elfcpp::R_390_PLT64: - case elfcpp::R_390_GOTOFF64: - case elfcpp::R_390_GOTPLT64: - case elfcpp::R_390_PLTOFF64: - return 8; + typedef gold::Default_classify_reloc + Classify_reloc; + typedef gold::Default_scan_relocatable_relocs + Scan_relocatable_relocs; - case elfcpp::R_390_32: - case elfcpp::R_390_PC32: - case elfcpp::R_390_GOT32: - case elfcpp::R_390_PLT32: - case elfcpp::R_390_GOTOFF32: - case elfcpp::R_390_GOTPC: - case elfcpp::R_390_PC32DBL: - case elfcpp::R_390_PLT32DBL: - case elfcpp::R_390_GOTPCDBL: - case elfcpp::R_390_GOTENT: - case elfcpp::R_390_GOTPLT32: - case elfcpp::R_390_GOTPLTENT: - case elfcpp::R_390_PLTOFF32: - case elfcpp::R_390_20: - case elfcpp::R_390_GOT20: - case elfcpp::R_390_GOTPLT20: - return 4; - - case elfcpp::R_390_PC24DBL: - case elfcpp::R_390_PLT24DBL: - return 3; - - case elfcpp::R_390_12: - case elfcpp::R_390_GOT12: - case elfcpp::R_390_GOTPLT12: - case elfcpp::R_390_PC12DBL: - case elfcpp::R_390_PLT12DBL: - case elfcpp::R_390_16: - case elfcpp::R_390_GOT16: - case elfcpp::R_390_PC16: - case elfcpp::R_390_PC16DBL: - case elfcpp::R_390_PLT16DBL: - case elfcpp::R_390_GOTOFF16: - case elfcpp::R_390_GOTPLT16: - case elfcpp::R_390_PLTOFF16: - return 2; - - case elfcpp::R_390_8: - return 1; - - // These are relocations which should only be seen by the - // dynamic linker, and should never be seen here. - case elfcpp::R_390_COPY: - case elfcpp::R_390_GLOB_DAT: - case elfcpp::R_390_JMP_SLOT: - case elfcpp::R_390_RELATIVE: - case elfcpp::R_390_IRELATIVE: - case elfcpp::R_390_TLS_DTPMOD: - case elfcpp::R_390_TLS_DTPOFF: - case elfcpp::R_390_TLS_TPOFF: - object->error(_("unexpected reloc %u in object file"), r_type); - return 0; + gold_assert(sh_type == elfcpp::SHT_RELA); - default: - object->error(_("unsupported reloc %u in object file"), r_type); - return 0; - } + gold::scan_relocatable_relocs( + symtab, + layout, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols, + rr); } -// Scan the relocs during a relocatable link. +// Scan the relocs for --emit-relocs. template void -Target_s390::scan_relocatable_relocs( +Target_s390::emit_relocs_scan( Symbol_table* symtab, Layout* layout, Sized_relobj_file* object, @@ -4136,16 +4081,17 @@ Target_s390::scan_relocatable_relocs( Output_section* output_section, bool needs_special_offset_handling, size_t local_symbol_count, - const unsigned char* plocal_symbols, + const unsigned char* plocal_syms, Relocatable_relocs* rr) { - gold_assert(sh_type == elfcpp::SHT_RELA); + typedef gold::Default_classify_reloc + Classify_reloc; + typedef gold::Default_emit_relocs_strategy + Emit_relocs_strategy; - typedef gold::Default_scan_relocatable_relocs Scan_relocatable_relocs; + gold_assert(sh_type == elfcpp::SHT_RELA); - gold::scan_relocatable_relocs( + gold::scan_relocatable_relocs( symtab, layout, object, @@ -4155,7 +4101,7 @@ Target_s390::scan_relocatable_relocs( output_section, needs_special_offset_handling, local_symbol_count, - plocal_symbols, + plocal_syms, rr); } @@ -4176,9 +4122,12 @@ Target_s390::relocate_relocs( unsigned char* reloc_view, section_size_type reloc_view_size) { + typedef gold::Default_classify_reloc + Classify_reloc; + gold_assert(sh_type == elfcpp::SHT_RELA); - gold::relocate_relocs( + gold::relocate_relocs( relinfo, prelocs, reloc_count, @@ -4259,11 +4208,13 @@ Target_s390::relocate_section( section_size_type view_size, const Reloc_symbol_changes* reloc_symbol_changes) { + typedef gold::Default_classify_reloc + Classify_reloc; + gold_assert(sh_type == elfcpp::SHT_RELA); - gold::relocate_section, elfcpp::SHT_RELA, - typename Target_s390::Relocate, - gold::Default_comdat_behavior>( + gold::relocate_section, Relocate, + gold::Default_comdat_behavior, Classify_reloc>( relinfo, this, prelocs, diff --git a/gold/sparc.cc b/gold/sparc.cc index 049e0ab..c97c32c 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -131,6 +131,21 @@ class Target_sparc : public Sized_target const unsigned char* plocal_symbols, Relocatable_relocs*); + // Scan the relocs for --emit-relocs. + void + emit_relocs_scan(Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr); + // Emit relocations for a section. void relocate_relocs(const Relocate_info*, @@ -345,15 +360,6 @@ class Target_sparc : public Sized_target unsigned char *reloc_adjust_addr_; }; - // A class which returns the size required for a relocation type, - // used while scanning relocs during a relocatable link. - class Relocatable_size_for_reloc - { - public: - unsigned int - get_size_for_reloc(unsigned int, Relobj*); - }; - // Get the GOT section, creating it if necessary. Output_data_got* got_section(Symbol_table*, Layout*); @@ -3036,9 +3042,10 @@ Target_sparc::gc_process_relocs( { typedef Target_sparc Sparc; typedef typename Target_sparc::Scan Scan; + typedef gold::Default_classify_reloc + Classify_reloc; - gold::gc_process_relocs( + gold::gc_process_relocs( symtab, layout, this, @@ -3070,7 +3077,8 @@ Target_sparc::scan_relocs( const unsigned char* plocal_symbols) { typedef Target_sparc Sparc; - typedef typename Target_sparc::Scan Scan; + typedef gold::Default_classify_reloc + Classify_reloc; if (sh_type == elfcpp::SHT_REL) { @@ -3079,7 +3087,7 @@ Target_sparc::scan_relocs( return; } - gold::scan_relocs( + gold::scan_relocs( symtab, layout, this, @@ -4142,11 +4150,13 @@ Target_sparc::relocate_section( { typedef Target_sparc Sparc; typedef typename Target_sparc::Relocate Sparc_relocate; + typedef gold::Default_classify_reloc + Classify_reloc; gold_assert(sh_type == elfcpp::SHT_RELA); - gold::relocate_section( + gold::relocate_section( relinfo, this, prelocs, @@ -4159,20 +4169,6 @@ Target_sparc::relocate_section( reloc_symbol_changes); } -// Return the size of a relocation while scanning during a relocatable -// link. - -template -unsigned int -Target_sparc::Relocatable_size_for_reloc::get_size_for_reloc( - unsigned int, - Relobj*) -{ - // We are always SHT_RELA, so we should never get here. - gold_unreachable(); - return 0; -} - // Scan the relocs during a relocatable link. template @@ -4191,13 +4187,14 @@ Target_sparc::scan_relocatable_relocs( const unsigned char* plocal_symbols, Relocatable_relocs* rr) { - gold_assert(sh_type == elfcpp::SHT_RELA); + typedef gold::Default_classify_reloc + Classify_reloc; + typedef gold::Default_scan_relocatable_relocs + Scan_relocatable_relocs; - typedef gold::Default_scan_relocatable_relocs Scan_relocatable_relocs; + gold_assert(sh_type == elfcpp::SHT_RELA); - gold::scan_relocatable_relocs( + gold::scan_relocatable_relocs( symtab, layout, object, @@ -4211,6 +4208,45 @@ Target_sparc::scan_relocatable_relocs( rr); } +// Scan the relocs for --emit-relocs. + +template +void +Target_sparc::emit_relocs_scan( + Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr) +{ + typedef gold::Default_classify_reloc + Classify_reloc; + typedef gold::Default_emit_relocs_strategy + Emit_relocs_strategy; + + gold_assert(sh_type == elfcpp::SHT_RELA); + + gold::scan_relocatable_relocs( + symtab, + layout, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_syms, + rr); +} + // Emit relocations for a section. template @@ -4228,9 +4264,12 @@ Target_sparc::relocate_relocs( unsigned char* reloc_view, section_size_type reloc_view_size) { + typedef gold::Default_classify_reloc + Classify_reloc; + gold_assert(sh_type == elfcpp::SHT_RELA); - gold::relocate_relocs( + gold::relocate_relocs( relinfo, prelocs, reloc_count, diff --git a/gold/target-reloc.h b/gold/target-reloc.h index cec5ee1..bdf673d 100644 --- a/gold/target-reloc.h +++ b/gold/target-reloc.h @@ -39,8 +39,8 @@ namespace gold // avoid making a function call for each relocation, and to avoid // repeating the generic code for each target. -template +template inline void scan_relocs( Symbol_table* symtab, @@ -55,8 +55,8 @@ scan_relocs( size_t local_count, const unsigned char* plocal_syms) { - typedef typename Reloc_types::Reloc Reltype; - const int reloc_size = Reloc_types::reloc_size; + typedef typename Classify_reloc::Reltype Reltype; + const int reloc_size = Classify_reloc::reloc_size; const int sym_size = elfcpp::Elf_sizes::sym_size; Scan scan; @@ -69,9 +69,8 @@ scan_relocs( reloc.get_r_offset())) continue; - typename elfcpp::Elf_types::Elf_WXword r_info = reloc.get_r_info(); - unsigned int r_sym = elfcpp::elf_r_sym(r_info); - unsigned int r_type = elfcpp::elf_r_type(r_info); + unsigned int r_sym = Classify_reloc::get_r_sym(&reloc); + unsigned int r_type = Classify_reloc::get_r_type(&reloc); if (r_sym < local_count) { @@ -253,9 +252,10 @@ issue_undefined_symbol_error(const Symbol* sym) // symbol for the relocation, ignoring the symbol index in the // relocation. -template + typename Relocate_comdat_behavior, + typename Classify_reloc> inline void relocate_section( const Relocate_info* relinfo, @@ -269,8 +269,8 @@ relocate_section( section_size_type view_size, const Reloc_symbol_changes* reloc_symbol_changes) { - typedef typename Reloc_types::Reloc Reltype; - const int reloc_size = Reloc_types::reloc_size; + typedef typename Classify_reloc::Reltype Reltype; + const int reloc_size = Classify_reloc::reloc_size; Relocate relocate; Relocate_comdat_behavior relocate_comdat_behavior; @@ -295,8 +295,7 @@ relocate_section( continue; } - typename elfcpp::Elf_types::Elf_WXword r_info = reloc.get_r_info(); - unsigned int r_sym = elfcpp::elf_r_sym(r_info); + unsigned int r_sym = Classify_reloc::get_r_sym(&reloc); const Sized_symbol* sym; @@ -399,8 +398,8 @@ relocate_section( if (offset < 0 || static_cast(offset) >= view_size) v = NULL; - if (!relocate.relocate(relinfo, sh_type, target, output_section, - i, prelocs, sym, psymval, + if (!relocate.relocate(relinfo, Classify_reloc::sh_type, target, + output_section, i, prelocs, sym, psymval, v, view_address + offset, view_size)) continue; @@ -464,18 +463,90 @@ apply_relocation(const Relocate_info* relinfo, view + r_offset, address + r_offset, view_size); } +// A class for inquiring about properties of a relocation, +// used while scanning relocs during a relocatable link and +// garbage collection. This class may be used as the default +// for SHT_RELA targets, but SHT_REL targets must implement +// a derived class that overrides get_size_for_reloc. +// The MIPS-64 target also needs to override the methods +// for accessing the r_sym and r_type fields of a relocation, +// due to its non-standard use of the r_info field. + +template +class Default_classify_reloc +{ + public: + typedef typename Reloc_types::Reloc + Reltype; + typedef typename Reloc_types::Reloc_write + Reltype_write; + static const int reloc_size = + Reloc_types::reloc_size; + static const int sh_type = sh_type_; + + // Return the symbol referred to by the relocation. + static inline unsigned int + get_r_sym(const Reltype* reloc) + { return elfcpp::elf_r_sym(reloc->get_r_info()); } + + // Return the type of the relocation. + static inline unsigned int + get_r_type(const Reltype* reloc) + { return elfcpp::elf_r_type(reloc->get_r_info()); } + + // Return the explicit addend of the relocation (return 0 for SHT_REL). + static inline typename elfcpp::Elf_types::Elf_Swxword + get_r_addend(const Reltype* reloc) + { return Reloc_types::get_reloc_addend(reloc); } + + // Write the r_info field to a new reloc, using the r_info field from + // the original reloc, replacing the r_sym field with R_SYM. + static inline void + put_r_info(Reltype_write* new_reloc, Reltype* reloc, unsigned int r_sym) + { + unsigned int r_type = elfcpp::elf_r_type(reloc->get_r_info()); + new_reloc->put_r_info(elfcpp::elf_r_info(r_sym, r_type)); + } + + // Write the r_addend field to a new reloc. + static inline void + put_r_addend(Reltype_write* to, + typename elfcpp::Elf_types::Elf_Swxword addend) + { Reloc_types::set_reloc_addend(to, addend); } + + // Return the size of the addend of the relocation (only used for SHT_REL). + static unsigned int + get_size_for_reloc(unsigned int, Relobj*) + { + gold_unreachable(); + return 0; + } +}; + // This class may be used as a typical class for the -// Scan_relocatable_reloc parameter to scan_relocatable_relocs. The -// template parameter Classify_reloc must be a class type which -// provides a function get_size_for_reloc which returns the number of -// bytes to which a reloc applies. This class is intended to capture -// the most typical target behaviour, while still permitting targets -// to define their own independent class for Scan_relocatable_reloc. - -template +// Scan_relocatable_reloc parameter to scan_relocatable_relocs. +// This class is intended to capture the most typical target behaviour, +// while still permitting targets to define their own independent class +// for Scan_relocatable_reloc. + +template class Default_scan_relocatable_relocs { public: + typedef typename Classify_reloc::Reltype Reltype; + static const int reloc_size = Classify_reloc::reloc_size; + static const int sh_type = Classify_reloc::sh_type; + + // Return the symbol referred to by the relocation. + static inline unsigned int + get_r_sym(const Reltype* reloc) + { return Classify_reloc::get_r_sym(reloc); } + + // Return the type of the relocation. + static inline unsigned int + get_r_type(const Reltype* reloc) + { return Classify_reloc::get_r_type(reloc); } + // Return the strategy to use for a local symbol which is not a // section symbol, given the relocation type. inline Relocatable_relocs::Reloc_strategy @@ -497,8 +568,7 @@ class Default_scan_relocatable_relocs return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA; else { - Classify_reloc classify; - switch (classify.get_size_for_reloc(r_type, object)) + switch (Classify_reloc::get_size_for_reloc(r_type, object)) { case 0: return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0; @@ -523,6 +593,56 @@ class Default_scan_relocatable_relocs { return Relocatable_relocs::RELOC_COPY; } }; +// This is a strategy class used with scan_relocatable_relocs +// and --emit-relocs. + +template +class Default_emit_relocs_strategy +{ + public: + typedef typename Classify_reloc::Reltype Reltype; + static const int reloc_size = Classify_reloc::reloc_size; + static const int sh_type = Classify_reloc::sh_type; + + // Return the symbol referred to by the relocation. + static inline unsigned int + get_r_sym(const Reltype* reloc) + { return Classify_reloc::get_r_sym(reloc); } + + // Return the type of the relocation. + static inline unsigned int + get_r_type(const Reltype* reloc) + { return Classify_reloc::get_r_type(reloc); } + + // A local non-section symbol. + inline Relocatable_relocs::Reloc_strategy + local_non_section_strategy(unsigned int, Relobj*, unsigned int) + { return Relocatable_relocs::RELOC_COPY; } + + // A local section symbol. + inline Relocatable_relocs::Reloc_strategy + local_section_strategy(unsigned int, Relobj*) + { + if (sh_type == elfcpp::SHT_RELA) + return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA; + else + { + // The addend is stored in the section contents. Since this + // is not a relocatable link, we are going to apply the + // relocation contents to the section as usual. This means + // that we have no way to record the original addend. If the + // original addend is not zero, there is basically no way for + // the user to handle this correctly. Caveat emptor. + return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0; + } + } + + // A global symbol. + inline Relocatable_relocs::Reloc_strategy + global_strategy(unsigned int, Relobj*, unsigned int) + { return Relocatable_relocs::RELOC_COPY; } +}; + // Scan relocs during a relocatable link. This is a default // definition which should work for most targets. // Scan_relocatable_reloc must name a class type which provides three @@ -531,8 +651,7 @@ class Default_scan_relocatable_relocs // local_section_strategy. Most targets should be able to use // Default_scan_relocatable_relocs as this class. -template +template void scan_relocatable_relocs( Symbol_table*, @@ -547,8 +666,8 @@ scan_relocatable_relocs( const unsigned char* plocal_syms, Relocatable_relocs* rr) { - typedef typename Reloc_types::Reloc Reltype; - const int reloc_size = Reloc_types::reloc_size; + typedef typename Scan_relocatable_reloc::Reltype Reltype; + const int reloc_size = Scan_relocatable_reloc::reloc_size; const int sym_size = elfcpp::Elf_sizes::sym_size; Scan_relocatable_reloc scan; @@ -564,10 +683,9 @@ scan_relocatable_relocs( strategy = Relocatable_relocs::RELOC_DISCARD; else { - typename elfcpp::Elf_types::Elf_WXword r_info = - reloc.get_r_info(); - const unsigned int r_sym = elfcpp::elf_r_sym(r_info); - const unsigned int r_type = elfcpp::elf_r_type(r_info); + const unsigned int r_sym = Scan_relocatable_reloc::get_r_sym(&reloc); + const unsigned int r_type = + Scan_relocatable_reloc::get_r_type(&reloc); if (r_sym >= local_symbol_count) strategy = scan.global_strategy(r_type, object, r_sym); @@ -610,7 +728,7 @@ scan_relocatable_relocs( // Relocate relocs. Called for a relocatable link, and for --emit-relocs. // This is a default definition which should work for most targets. -template +template void relocate_relocs( const Relocate_info* relinfo, @@ -625,10 +743,9 @@ relocate_relocs( section_size_type reloc_view_size) { typedef typename elfcpp::Elf_types::Elf_Addr Address; - typedef typename Reloc_types::Reloc Reltype; - typedef typename Reloc_types::Reloc_write - Reltype_write; - const int reloc_size = Reloc_types::reloc_size; + typedef typename Classify_reloc::Reltype Reltype; + typedef typename Classify_reloc::Reltype_write Reltype_write; + const int reloc_size = Classify_reloc::reloc_size; const Address invalid_address = static_cast
(0) - 1; Sized_relobj_file* const object = relinfo->object; @@ -647,8 +764,8 @@ relocate_relocs( // Target wants to handle this relocation. Sized_target* target = parameters->sized_target(); - target->relocate_special_relocatable(relinfo, sh_type, prelocs, - i, output_section, + target->relocate_special_relocatable(relinfo, Classify_reloc::sh_type, + prelocs, i, output_section, offset_in_output_section, view, view_address, view_size, pwrite); @@ -658,9 +775,7 @@ relocate_relocs( Reltype reloc(prelocs); Reltype_write reloc_write(pwrite); - typename elfcpp::Elf_types::Elf_WXword r_info = reloc.get_r_info(); - const unsigned int r_sym = elfcpp::elf_r_sym(r_info); - const unsigned int r_type = elfcpp::elf_r_type(r_info); + const unsigned int r_sym = Classify_reloc::get_r_sym(&reloc); // Get the new symbol index. @@ -748,16 +863,15 @@ relocate_relocs( } reloc_write.put_r_offset(new_offset); - reloc_write.put_r_info(elfcpp::elf_r_info(new_symndx, r_type)); + Classify_reloc::put_r_info(&reloc_write, &reloc, new_symndx); // Handle the reloc addend based on the strategy. if (strategy == Relocatable_relocs::RELOC_COPY) { - if (sh_type == elfcpp::SHT_RELA) - Reloc_types:: - copy_reloc_addend(&reloc_write, - &reloc); + if (Classify_reloc::sh_type == elfcpp::SHT_RELA) + Classify_reloc::put_r_addend(&reloc_write, + Classify_reloc::get_r_addend(&reloc)); } else { @@ -777,12 +891,10 @@ relocate_relocs( case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA: { typename elfcpp::Elf_types::Elf_Swxword addend; - addend = Reloc_types:: - get_reloc_addend(&reloc); + addend = Classify_reloc::get_r_addend(&reloc); gold_assert(os != NULL); addend = psymval->value(object, addend) - os->address(); - Reloc_types:: - set_reloc_addend(&reloc_write, addend); + Classify_reloc::put_r_addend(&reloc_write, addend); } break; diff --git a/gold/target.cc b/gold/target.cc index 658fadf..cc3765a 100644 --- a/gold/target.cc +++ b/gold/target.cc @@ -152,7 +152,7 @@ Target::do_make_output_section(const char* name, elfcpp::Elf_Word type, // whether the symbol is a function. bool -Target::do_is_call_to_non_split(const Symbol* sym, unsigned int) const +Target::do_is_call_to_non_split(const Symbol* sym, const unsigned char*) const { return sym->type() == elfcpp::STT_FUNC; } diff --git a/gold/target.h b/gold/target.h index 27e8a2e..c0f24ee 100644 --- a/gold/target.h +++ b/gold/target.h @@ -321,13 +321,13 @@ class Target ehframe_datarel_base() const { return this->do_ehframe_datarel_base(); } - // Return true if a reference to SYM from a reloc of type R_TYPE + // Return true if a reference to SYM from a reloc at *PRELOC // means that the current function may call an object compiled // without -fsplit-stack. SYM is known to be defined in an object // compiled without -fsplit-stack. bool - is_call_to_non_split(const Symbol* sym, unsigned int r_type) const - { return this->do_is_call_to_non_split(sym, r_type); } + is_call_to_non_split(const Symbol* sym, const unsigned char* preloc) const + { return this->do_is_call_to_non_split(sym, preloc); } // A function starts at OFFSET in section SHNDX in OBJECT. That // function was compiled with -fsplit-stack, but it refers to a @@ -661,7 +661,7 @@ class Target // default implementation is that any function not defined by the // ABI is a call to a non-split function. virtual bool - do_is_call_to_non_split(const Symbol* sym, unsigned int) const; + do_is_call_to_non_split(const Symbol* sym, const unsigned char*) const; // Virtual function which may be overridden by the child class. virtual void @@ -926,6 +926,22 @@ class Sized_target : public Target const unsigned char* plocal_symbols, Relocatable_relocs*) = 0; + // Scan the relocs for --emit-relocs. The parameters are + // like scan_relocatable_relocs. + virtual void + emit_relocs_scan(Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr) = 0; + // Emit relocations for a section during a relocatable link, and for // --emit-relocs. The parameters are like relocate_section, with // additional parameters for the view of the output reloc section. @@ -1084,6 +1100,19 @@ class Sized_target : public Target dst_obj, dst_shndx, dst_off); } + // Return the r_sym field from a relocation. + // Most targets can use the default version of this routine, + // but some targets have a non-standard r_info field, and will + // need to provide a target-specific version. + virtual unsigned int + get_r_sym(const unsigned char* preloc) const + { + // Since REL and RELA relocs share the same structure through + // the r_info field, we can just use REL here. + elfcpp::Rel rel(preloc); + return elfcpp::elf_r_sym(rel.get_r_info()); + } + protected: Sized_target(const Target::Target_info* pti) : Target(pti) diff --git a/gold/testsuite/testfile.cc b/gold/testsuite/testfile.cc index bb5ff70..4049e4a 100644 --- a/gold/testsuite/testfile.cc +++ b/gold/testsuite/testfile.cc @@ -72,6 +72,14 @@ class Target_test : public Sized_target { ERROR("call to Target_test::scan_relocatable_relocs"); } void + emit_relocs_scan(Symbol_table*, Layout*, + Sized_relobj_file*, unsigned int, + unsigned int, const unsigned char*, + size_t, Output_section*, bool, size_t, + const unsigned char*, Relocatable_relocs*) + { ERROR("call to Target_test::emit_relocs_scan"); } + + void relocate_relocs(const Relocate_info*, unsigned int, const unsigned char*, size_t, Output_section*, typename elfcpp::Elf_types::Elf_Off, diff --git a/gold/tilegx.cc b/gold/tilegx.cc index 07960ef..bb17330 100644 --- a/gold/tilegx.cc +++ b/gold/tilegx.cc @@ -308,6 +308,21 @@ class Target_tilegx : public Sized_target const unsigned char* plocal_symbols, Relocatable_relocs*); + // Scan the relocs for --emit-relocs. + void + emit_relocs_scan(Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr); + // Relocate a section during a relocatable link. void relocate_relocs( @@ -523,15 +538,6 @@ class Target_tilegx : public Sized_target section_size_type); }; - // A class which returns the size required for a relocation type, - // used while scanning relocs during a relocatable link. - class Relocatable_size_for_reloc - { - public: - unsigned int - get_size_for_reloc(unsigned int, Relobj*); - }; - // Adjust TLS relocation type based on the options and whether this // is a local symbol. static tls::Tls_optimization @@ -4154,26 +4160,26 @@ Target_tilegx::gc_process_relocs(Symbol_table* symtab, { typedef Target_tilegx Tilegx; typedef typename Target_tilegx::Scan Scan; + typedef gold::Default_classify_reloc + Classify_reloc; if (sh_type == elfcpp::SHT_REL) { return; } - gold::gc_process_relocs::Relocatable_size_for_reloc>( - symtab, - layout, - this, - object, - data_shndx, - prelocs, - reloc_count, - output_section, - needs_special_offset_handling, - local_symbol_count, - plocal_symbols); + gold::gc_process_relocs( + symtab, + layout, + this, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols); } // Scan relocations for a section. @@ -4193,6 +4199,8 @@ Target_tilegx::scan_relocs(Symbol_table* symtab, { typedef Target_tilegx Tilegx; typedef typename Target_tilegx::Scan Scan; + typedef gold::Default_classify_reloc + Classify_reloc; if (sh_type == elfcpp::SHT_REL) { @@ -4201,7 +4209,7 @@ Target_tilegx::scan_relocs(Symbol_table* symtab, return; } - gold::scan_relocs( + gold::scan_relocs( symtab, layout, this, @@ -4743,11 +4751,13 @@ Target_tilegx::relocate_section( { typedef Target_tilegx Tilegx; typedef typename Target_tilegx::Relocate Tilegx_relocate; + typedef gold::Default_classify_reloc + Classify_reloc; gold_assert(sh_type == elfcpp::SHT_RELA); - gold::relocate_section( + gold::relocate_section( relinfo, this, prelocs, @@ -4788,24 +4798,50 @@ Target_tilegx::apply_relocation( view_size); } -// Return the size of a relocation while scanning during a relocatable -// link. +// Scan the relocs during a relocatable link. template -unsigned int -Target_tilegx::Relocatable_size_for_reloc::get_size_for_reloc( - unsigned int, Relobj*) +void +Target_tilegx::scan_relocatable_relocs( + Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols, + Relocatable_relocs* rr) { - // We are always SHT_RELA, so we should never get here. - gold_unreachable(); - return 0; + typedef gold::Default_classify_reloc + Classify_reloc; + typedef gold::Default_scan_relocatable_relocs + Scan_relocatable_relocs; + + gold_assert(sh_type == elfcpp::SHT_RELA); + + gold::scan_relocatable_relocs( + symtab, + layout, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols, + rr); } -// Scan the relocs during a relocatable link. +// Scan the relocs for --emit-relocs. template void -Target_tilegx::scan_relocatable_relocs( +Target_tilegx::emit_relocs_scan( Symbol_table* symtab, Layout* layout, Sized_relobj_file* object, @@ -4816,16 +4852,17 @@ Target_tilegx::scan_relocatable_relocs( Output_section* output_section, bool needs_special_offset_handling, size_t local_symbol_count, - const unsigned char* plocal_symbols, + const unsigned char* plocal_syms, Relocatable_relocs* rr) { - gold_assert(sh_type == elfcpp::SHT_RELA); + typedef gold::Default_classify_reloc + Classify_reloc; + typedef gold::Default_emit_relocs_strategy + Emit_relocs_strategy; - typedef gold::Default_scan_relocatable_relocs Scan_relocatable_relocs; + gold_assert(sh_type == elfcpp::SHT_RELA); - gold::scan_relocatable_relocs( + gold::scan_relocatable_relocs( symtab, layout, object, @@ -4835,7 +4872,7 @@ Target_tilegx::scan_relocatable_relocs( output_section, needs_special_offset_handling, local_symbol_count, - plocal_symbols, + plocal_syms, rr); } @@ -4856,9 +4893,12 @@ Target_tilegx::relocate_relocs( unsigned char* reloc_view, section_size_type reloc_view_size) { + typedef gold::Default_classify_reloc + Classify_reloc; + gold_assert(sh_type == elfcpp::SHT_RELA); - gold::relocate_relocs( + gold::relocate_relocs( relinfo, prelocs, reloc_count, diff --git a/gold/x86_64.cc b/gold/x86_64.cc index c48a513..3cfc064 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -496,6 +496,21 @@ class Target_x86_64 : public Sized_target const unsigned char* plocal_symbols, Relocatable_relocs*); + // Scan the relocs for --emit-relocs. + void + emit_relocs_scan(Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_syms, + Relocatable_relocs* rr); + // Emit relocations for a section. void relocate_relocs( @@ -859,15 +874,6 @@ class Target_x86_64 : public Sized_target bool skip_call_tls_get_addr_; }; - // A class which returns the size required for a relocation type, - // used while scanning relocs during a relocatable link. - class Relocatable_size_for_reloc - { - public: - unsigned int - get_size_for_reloc(unsigned int, Relobj*); - }; - // Check if relocation against this symbol is a candidate for // conversion from // mov foo@GOTPCREL(%rip), %reg @@ -3191,15 +3197,16 @@ Target_x86_64::gc_process_relocs(Symbol_table* symtab, size_t local_symbol_count, const unsigned char* plocal_symbols) { + typedef gold::Default_classify_reloc + Classify_reloc; if (sh_type == elfcpp::SHT_REL) { return; } - gold::gc_process_relocs, elfcpp::SHT_RELA, - typename Target_x86_64::Scan, - typename Target_x86_64::Relocatable_size_for_reloc>( + gold::gc_process_relocs, Scan, + Classify_reloc>( symtab, layout, this, @@ -3229,6 +3236,9 @@ Target_x86_64::scan_relocs(Symbol_table* symtab, size_t local_symbol_count, const unsigned char* plocal_symbols) { + typedef gold::Default_classify_reloc + Classify_reloc; + if (sh_type == elfcpp::SHT_REL) { gold_error(_("%s: unsupported REL reloc section"), @@ -3236,8 +3246,7 @@ Target_x86_64::scan_relocs(Symbol_table* symtab, return; } - gold::scan_relocs, elfcpp::SHT_RELA, - typename Target_x86_64::Scan>( + gold::scan_relocs, Scan, Classify_reloc>( symtab, layout, this, @@ -4268,11 +4277,13 @@ Target_x86_64::relocate_section( section_size_type view_size, const Reloc_symbol_changes* reloc_symbol_changes) { + typedef gold::Default_classify_reloc + Classify_reloc; + gold_assert(sh_type == elfcpp::SHT_RELA); - gold::relocate_section, elfcpp::SHT_RELA, - typename Target_x86_64::Relocate, - gold::Default_comdat_behavior>( + gold::relocate_section, Relocate, + gold::Default_comdat_behavior, Classify_reloc>( relinfo, this, prelocs, @@ -4313,86 +4324,50 @@ Target_x86_64::apply_relocation( view_size); } -// Return the size of a relocation while scanning during a relocatable -// link. +// Scan the relocs during a relocatable link. template -unsigned int -Target_x86_64::Relocatable_size_for_reloc::get_size_for_reloc( - unsigned int r_type, - Relobj* object) +void +Target_x86_64::scan_relocatable_relocs( + Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols, + Relocatable_relocs* rr) { - switch (r_type) - { - case elfcpp::R_X86_64_NONE: - case elfcpp::R_X86_64_GNU_VTINHERIT: - case elfcpp::R_X86_64_GNU_VTENTRY: - case elfcpp::R_X86_64_TLSGD: // Global-dynamic - case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url) - case elfcpp::R_X86_64_TLSDESC_CALL: - case elfcpp::R_X86_64_TLSLD: // Local-dynamic - case elfcpp::R_X86_64_DTPOFF32: - case elfcpp::R_X86_64_DTPOFF64: - case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec - case elfcpp::R_X86_64_TPOFF32: // Local-exec - return 0; + typedef gold::Default_classify_reloc + Classify_reloc; + typedef gold::Default_scan_relocatable_relocs + Scan_relocatable_relocs; - case elfcpp::R_X86_64_64: - case elfcpp::R_X86_64_PC64: - case elfcpp::R_X86_64_GOTOFF64: - case elfcpp::R_X86_64_GOTPC64: - case elfcpp::R_X86_64_PLTOFF64: - case elfcpp::R_X86_64_GOT64: - case elfcpp::R_X86_64_GOTPCREL64: - case elfcpp::R_X86_64_GOTPCREL: - case elfcpp::R_X86_64_GOTPCRELX: - case elfcpp::R_X86_64_REX_GOTPCRELX: - case elfcpp::R_X86_64_GOTPLT64: - return 8; - - case elfcpp::R_X86_64_32: - case elfcpp::R_X86_64_32S: - case elfcpp::R_X86_64_PC32: - case elfcpp::R_X86_64_PC32_BND: - case elfcpp::R_X86_64_PLT32: - case elfcpp::R_X86_64_PLT32_BND: - case elfcpp::R_X86_64_GOTPC32: - case elfcpp::R_X86_64_GOT32: - return 4; - - case elfcpp::R_X86_64_16: - case elfcpp::R_X86_64_PC16: - return 2; - - case elfcpp::R_X86_64_8: - case elfcpp::R_X86_64_PC8: - return 1; - - case elfcpp::R_X86_64_COPY: - case elfcpp::R_X86_64_GLOB_DAT: - case elfcpp::R_X86_64_JUMP_SLOT: - case elfcpp::R_X86_64_RELATIVE: - case elfcpp::R_X86_64_IRELATIVE: - // These are outstanding tls relocs, which are unexpected when linking - case elfcpp::R_X86_64_TPOFF64: - case elfcpp::R_X86_64_DTPMOD64: - case elfcpp::R_X86_64_TLSDESC: - object->error(_("unexpected reloc %u in object file"), r_type); - return 0; + gold_assert(sh_type == elfcpp::SHT_RELA); - case elfcpp::R_X86_64_SIZE32: - case elfcpp::R_X86_64_SIZE64: - default: - object->error(_("unsupported reloc %u against local symbol"), r_type); - return 0; - } + gold::scan_relocatable_relocs( + symtab, + layout, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols, + rr); } -// Scan the relocs during a relocatable link. +// Scan the relocs for --emit-relocs. template void -Target_x86_64::scan_relocatable_relocs( +Target_x86_64::emit_relocs_scan( Symbol_table* symtab, Layout* layout, Sized_relobj_file* object, @@ -4403,16 +4378,17 @@ Target_x86_64::scan_relocatable_relocs( Output_section* output_section, bool needs_special_offset_handling, size_t local_symbol_count, - const unsigned char* plocal_symbols, + const unsigned char* plocal_syms, Relocatable_relocs* rr) { - gold_assert(sh_type == elfcpp::SHT_RELA); + typedef gold::Default_classify_reloc + Classify_reloc; + typedef gold::Default_emit_relocs_strategy + Emit_relocs_strategy; - typedef gold::Default_scan_relocatable_relocs Scan_relocatable_relocs; + gold_assert(sh_type == elfcpp::SHT_RELA); - gold::scan_relocatable_relocs( + gold::scan_relocatable_relocs( symtab, layout, object, @@ -4422,7 +4398,7 @@ Target_x86_64::scan_relocatable_relocs( output_section, needs_special_offset_handling, local_symbol_count, - plocal_symbols, + plocal_syms, rr); } @@ -4443,9 +4419,12 @@ Target_x86_64::relocate_relocs( unsigned char* reloc_view, section_size_type reloc_view_size) { + typedef gold::Default_classify_reloc + Classify_reloc; + gold_assert(sh_type == elfcpp::SHT_RELA); - gold::relocate_relocs( + gold::relocate_relocs( relinfo, prelocs, reloc_count,