* target-reloc.h (class Default_comdat_behavior): New, package up..
authorAlan Modra <amodra@gmail.com>
Thu, 18 Oct 2012 04:18:18 +0000 (04:18 +0000)
committerAlan Modra <amodra@gmail.com>
Thu, 18 Oct 2012 04:18:18 +0000 (04:18 +0000)
(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.

gold/ChangeLog
gold/arm.cc
gold/i386.cc
gold/powerpc.cc
gold/sparc.cc
gold/target-reloc.h
gold/tilegx.cc
gold/x86_64.cc

index 91c01b81c1b78067563eea883c1f3f2dca01a59c..0b728bbded80303c308182d9e5bb41a29bf72d07 100644 (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
index d874ce02795e7d4a2cdf1742cdd6d29c26af5d15..d8471265705e598944019a11efda074e13a5a6ff 100644 (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)
            {
index 9c52e93166e970620bb6301c3890152ea5589591..78f977029d83934a27cf4f333978a57961fac598 100644 (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,
index 69386020ece5330b91f4161246bdf89bfc3d7c6d..5e4006ce72b0c8c46178dbed971888508a37d4fe 100644 (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
index 4ec3037c4ab6ac9cca336c945fc161f522c29269..456ee462b81344938c3cd3ccb077fe373720b1bc 100644 (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,
index 5e6dba7724861d8614806f3a93a2c22d13a79e28..769a524f7ad2ddcee738fdcdb293e6e9e43e85f3 100644 (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)
            {
index 3c618028a6400f7fabe5ba3405755b267ea5e8a8..f03014fdc36762be407b08f73a760d2ef542c79f 100644 (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,
index 0fbfec62dbeb3b7449f1f2e9d25f2f2505259103..6c379ba0c9abfaab7b28c352bf1362959ac2e16c 100644 (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,