diff --git a/gold/ChangeLog b/gold/ChangeLog index 91c01b81c1b..0b728bbded8 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,19 @@ +2012-10-18 Alan Modra + + * 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 * powerpc.cc (Target_powerpc::Scan::local, global): Always emit diff --git a/gold/arm.cc b/gold/arm.cc index d874ce02795..d8471265705 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -9518,7 +9518,7 @@ Target_arm::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::scan_reloc_section_for_stubs( Arm_relobj::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::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 9c52e93166e..78f977029d8 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 69386020ece..5e4006ce72b 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -619,6 +619,32 @@ class Target_powerpc : public Sized_target 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::relocate_section( { typedef Target_powerpc Powerpc; typedef typename Target_powerpc::Relocate Powerpc_relocate; + typedef typename Target_powerpc::Relocate_comdat_behavior + Powerpc_comdat_behavior; gold_assert(sh_type == elfcpp::SHT_RELA); - unsigned char *opd_rel = NULL; - Powerpc_relobj* const object - = static_cast*>(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::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::Reloc - reloc(rrel); - typename elfcpp::Elf_types::Elf_WXword r_info - = reloc.get_r_info(); - unsigned int r_type = elfcpp::elf_r_type(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( + Powerpc_relocate, Powerpc_comdat_behavior>( relinfo, this, prelocs, @@ -5103,9 +5094,6 @@ Target_powerpc::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 4ec3037c4ab..456ee462b81 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -4138,7 +4138,7 @@ Target_sparc::relocate_section( gold_assert(sh_type == elfcpp::SHT_RELA); gold::relocate_section( + Sparc_relocate, gold::Default_comdat_behavior>( relinfo, this, prelocs, diff --git a/gold/target-reloc.h b/gold/target-reloc.h index 5e6dba77248..769a524f7ad 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 + typename Relocate, + typename Relocate_comdat_behavior> inline void relocate_section( const Relocate_info* relinfo, @@ -258,6 +268,7 @@ relocate_section( typedef typename Reloc_types::Reloc Reltype; const int reloc_size = Reloc_types::reloc_size; Relocate relocate; + Relocate_comdat_behavior relocate_comdat_behavior; Sized_relobj_file* 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 3c618028a64..f03014fdc36 100644 --- a/gold/tilegx.cc +++ b/gold/tilegx.cc @@ -4733,8 +4733,8 @@ Target_tilegx::relocate_section( gold_assert(sh_type == elfcpp::SHT_RELA); - gold::relocate_section( + gold::relocate_section( relinfo, this, prelocs, diff --git a/gold/x86_64.cc b/gold/x86_64.cc index 0fbfec62dbe..6c379ba0c9a 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -4060,7 +4060,8 @@ Target_x86_64::relocate_section( gold_assert(sh_type == elfcpp::SHT_RELA); gold::relocate_section, elfcpp::SHT_RELA, - typename Target_x86_64::Relocate>( + typename Target_x86_64::Relocate, + gold::Default_comdat_behavior>( relinfo, this, prelocs,