diff options
Diffstat (limited to 'gold')
-rw-r--r-- | gold/ChangeLog | 16 | ||||
-rw-r--r-- | gold/arm.cc | 5 | ||||
-rw-r--r-- | gold/i386.cc | 2 | ||||
-rw-r--r-- | gold/powerpc.cc | 70 | ||||
-rw-r--r-- | gold/sparc.cc | 2 | ||||
-rw-r--r-- | gold/target-reloc.h | 41 | ||||
-rw-r--r-- | gold/tilegx.cc | 4 | ||||
-rw-r--r-- | gold/x86_64.cc | 3 |
8 files changed, 80 insertions, 63 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index 91c01b8..0b728bb 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,5 +1,21 @@ 2012-10-18 Alan Modra <amodra@gmail.com> + * target-reloc.h (class Default_comdat_behavior): New, package up.. + (get_comdat_behaviour): ..this. + (relocate_section): Add Relocate_comdat_behavior template arg, + adjust code to suit. + * arm.cc (Target_arm::relocate_section): Adjust to suit. + (Target_arm::scan_reloc_section): Likewise. + * i386.cc (Target_i386::relocate_section): Likewise. + * sparc.cc (Target_sparc::relocate_section): Likewise. + * tilegx.cc (Target_tilegx::relocate_section): Likewise. + * x86_64.cc (Target_x86_64::relocate_section): Likewise. + * powerpc.cc (class Relocate_comdat_behavior): New. + (Target_powerpc::relocate_section): Don't zap opd relocs. Supply + gold::relocate_section with new template arg. + +2012-10-18 Alan Modra <amodra@gmail.com> + * powerpc.cc (Target_powerpc::Scan::local, global): Always emit dynamic relocs for GOT_TPREL got entries, without symbol if resolving locally. diff --git a/gold/arm.cc b/gold/arm.cc index d874ce0..d847126 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -9518,7 +9518,7 @@ Target_arm<big_endian>::relocate_section( } gold::relocate_section<32, big_endian, Target_arm, elfcpp::SHT_REL, - Arm_relocate>( + Arm_relocate, gold::Default_comdat_behavior>( relinfo, this, prelocs, @@ -11150,6 +11150,7 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs( Arm_relobj<big_endian>::as_arm_relobj(relinfo->object); unsigned int local_count = arm_object->local_symbol_count(); + gold::Default_comdat_behavior default_comdat_behavior; Comdat_behavior comdat_behavior = CB_UNDETERMINED; for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size) @@ -11323,7 +11324,7 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs( if (comdat_behavior == CB_UNDETERMINED) { std::string name = arm_object->section_name(relinfo->data_shndx); - comdat_behavior = get_comdat_behavior(name.c_str()); + comdat_behavior = default_comdat_behavior.get(name.c_str()); } if (comdat_behavior == CB_PRETEND) { diff --git a/gold/i386.cc b/gold/i386.cc index 9c52e93..78f9770 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -3487,7 +3487,7 @@ 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>( + Target_i386::Relocate, gold::Default_comdat_behavior>( relinfo, this, prelocs, diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 6938602..5e4006c 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -619,6 +619,32 @@ class Target_powerpc : public Sized_target<size, big_endian> enum skip_tls call_tls_get_addr_; }; + class Relocate_comdat_behavior + { + public: + // Decide what the linker should do for relocations that refer to + // discarded comdat sections. + inline Comdat_behavior + get(const char* name) + { + gold::Default_comdat_behavior default_behavior; + Comdat_behavior ret = default_behavior.get(name); + if (ret == CB_WARNING) + { + if (size == 32 + && (strcmp(name, ".fixup") == 0 + || strcmp(name, ".got2") == 0)) + ret = CB_IGNORE; + if (size == 64 + && (strcmp(name, ".opd") == 0 + || strcmp(name, ".toc") == 0 + || strcmp(name, ".toc1") == 0)) + ret = CB_IGNORE; + } + return ret; + } + }; + // A class which returns the size required for a relocation type, // used while scanning relocs during a relocatable link. class Relocatable_size_for_reloc @@ -5051,48 +5077,13 @@ Target_powerpc<size, big_endian>::relocate_section( { typedef Target_powerpc<size, big_endian> Powerpc; typedef typename Target_powerpc<size, big_endian>::Relocate Powerpc_relocate; + typedef typename Target_powerpc<size, big_endian>::Relocate_comdat_behavior + Powerpc_comdat_behavior; gold_assert(sh_type == elfcpp::SHT_RELA); - unsigned char *opd_rel = NULL; - Powerpc_relobj<size, big_endian>* const object - = static_cast<Powerpc_relobj<size, big_endian>*>(relinfo->object); - if (size == 64 - && relinfo->data_shndx == object->opd_shndx()) - { - // Rewrite opd relocs, omitting those for discarded sections - // to silence gold::relocate_section errors. - const int reloc_size - = Reloc_types<elfcpp::SHT_RELA, size, big_endian>::reloc_size; - opd_rel = new unsigned char[reloc_count * reloc_size]; - const unsigned char* rrel = prelocs; - unsigned char* wrel = opd_rel; - - for (size_t i = 0; - i < reloc_count; - ++i, rrel += reloc_size, wrel += reloc_size) - { - typename Reloc_types<elfcpp::SHT_RELA, size, big_endian>::Reloc - reloc(rrel); - typename elfcpp::Elf_types<size>::Elf_WXword r_info - = reloc.get_r_info(); - unsigned int r_type = elfcpp::elf_r_type<size>(r_info); - Address r_off = reloc.get_r_offset(); - if (r_type == elfcpp::R_PPC64_TOC) - r_off -= 8; - bool is_discarded = object->get_opd_discard(r_off); - - // Reloc number is reported in some errors, so keep all relocs. - if (is_discarded) - memset(wrel, 0, reloc_size); - else - memcpy(wrel, rrel, reloc_size); - } - prelocs = opd_rel; - } - gold::relocate_section<size, big_endian, Powerpc, elfcpp::SHT_RELA, - Powerpc_relocate>( + Powerpc_relocate, Powerpc_comdat_behavior>( relinfo, this, prelocs, @@ -5103,9 +5094,6 @@ Target_powerpc<size, big_endian>::relocate_section( address, view_size, reloc_symbol_changes); - - if (opd_rel != NULL) - delete[] opd_rel; } class Powerpc_scan_relocatable_reloc diff --git a/gold/sparc.cc b/gold/sparc.cc index 4ec3037..456ee46 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -4138,7 +4138,7 @@ Target_sparc<size, big_endian>::relocate_section( gold_assert(sh_type == elfcpp::SHT_RELA); gold::relocate_section<size, big_endian, Sparc, elfcpp::SHT_RELA, - Sparc_relocate>( + Sparc_relocate, gold::Default_comdat_behavior>( relinfo, this, prelocs, diff --git a/gold/target-reloc.h b/gold/target-reloc.h index 5e6dba7..769a524 100644 --- a/gold/target-reloc.h +++ b/gold/target-reloc.h @@ -124,20 +124,24 @@ enum Comdat_behavior CB_WARNING // Print a warning. }; -// Decide what the linker should do for relocations that refer to discarded -// comdat sections. This decision is based on the name of the section being -// relocated. - -inline Comdat_behavior -get_comdat_behavior(const char* name) +class Default_comdat_behavior { - if (Layout::is_debug_info_section(name)) - return CB_PRETEND; - if (strcmp(name, ".eh_frame") == 0 - || strcmp(name, ".gcc_except_table") == 0) - return CB_IGNORE; - return CB_WARNING; -} + public: + // Decide what the linker should do for relocations that refer to + // discarded comdat sections. This decision is based on the name of + // the section being relocated. + + inline Comdat_behavior + get(const char* name) + { + if (Layout::is_debug_info_section(name)) + return CB_PRETEND; + if (strcmp(name, ".eh_frame") == 0 + || strcmp(name, ".gcc_except_table") == 0) + return CB_IGNORE; + return CB_WARNING; + } +}; // Give an error for a symbol with non-default visibility which is not // defined locally. @@ -220,6 +224,11 @@ issue_undefined_symbol_error(const Symbol* sym) // a single function, relocate(), which implements the machine // specific part of a relocation. +// The template parameter Relocate_comdat_behavior is a class type +// which provides a single function, get(), which determines what the +// linker should do for relocations that refer to discarded comdat +// sections. + // SIZE is the ELF size: 32 or 64. BIG_ENDIAN is the endianness of // the data. SH_TYPE is the section type: SHT_REL or SHT_RELA. // RELOCATE implements operator() to do a relocation. @@ -241,7 +250,8 @@ issue_undefined_symbol_error(const Symbol* sym) // relocation. template<int size, bool big_endian, typename Target_type, int sh_type, - typename Relocate> + typename Relocate, + typename Relocate_comdat_behavior> inline void relocate_section( const Relocate_info<size, big_endian>* relinfo, @@ -258,6 +268,7 @@ relocate_section( typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype; const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size; Relocate relocate; + Relocate_comdat_behavior relocate_comdat_behavior; Sized_relobj_file<size, big_endian>* object = relinfo->object; unsigned int local_count = object->local_symbol_count(); @@ -348,7 +359,7 @@ relocate_section( if (comdat_behavior == CB_UNDETERMINED) { std::string name = object->section_name(relinfo->data_shndx); - comdat_behavior = get_comdat_behavior(name.c_str()); + comdat_behavior = relocate_comdat_behavior.get(name.c_str()); } if (comdat_behavior == CB_PRETEND) { diff --git a/gold/tilegx.cc b/gold/tilegx.cc index 3c61802..f03014f 100644 --- a/gold/tilegx.cc +++ b/gold/tilegx.cc @@ -4733,8 +4733,8 @@ Target_tilegx<size, big_endian>::relocate_section( gold_assert(sh_type == elfcpp::SHT_RELA); - gold::relocate_section<size, big_endian, Tilegx, - elfcpp::SHT_RELA, Tilegx_relocate>( + gold::relocate_section<size, big_endian, Tilegx, elfcpp::SHT_RELA, + Tilegx_relocate, gold::Default_comdat_behavior>( relinfo, this, prelocs, diff --git a/gold/x86_64.cc b/gold/x86_64.cc index 0fbfec6..6c379ba 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -4060,7 +4060,8 @@ Target_x86_64<size>::relocate_section( gold_assert(sh_type == elfcpp::SHT_RELA); gold::relocate_section<size, false, Target_x86_64<size>, elfcpp::SHT_RELA, - typename Target_x86_64<size>::Relocate>( + typename Target_x86_64<size>::Relocate, + gold::Default_comdat_behavior>( relinfo, this, prelocs, |