aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
Diffstat (limited to 'gold')
-rw-r--r--gold/ChangeLog16
-rw-r--r--gold/arm.cc5
-rw-r--r--gold/i386.cc2
-rw-r--r--gold/powerpc.cc70
-rw-r--r--gold/sparc.cc2
-rw-r--r--gold/target-reloc.h41
-rw-r--r--gold/tilegx.cc4
-rw-r--r--gold/x86_64.cc3
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,