* 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.
This commit is contained in:
Alan Modra 2012-10-18 04:18:18 +00:00
parent 522307fe68
commit 168a472611
8 changed files with 80 additions and 63 deletions

View File

@ -1,3 +1,19 @@
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

View File

@ -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)
{

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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)
{

View File

@ -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,

View File

@ -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,