(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>
+
+ * 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
}
gold::relocate_section<32, big_endian, Target_arm, elfcpp::SHT_REL,
- Arm_relocate>(
+ Arm_relocate, gold::Default_comdat_behavior>(
relinfo,
this,
prelocs,
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)
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)
{
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,
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
{
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,
address,
view_size,
reloc_symbol_changes);
-
- if (opd_rel != NULL)
- delete[] opd_rel;
}
class Powerpc_scan_relocatable_reloc
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,
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.
// 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.
// 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,
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();
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)
{
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,
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,