[GOLD] override get_comdat_behavior

Alan Modra amodra@gmail.com
Thu Oct 18 00:02:00 GMT 2012


On Thu, Oct 18, 2012 at 09:00:53AM +1030, Alan Modra wrote:
> On Wed, Oct 17, 2012 at 11:33:55AM -0700, Ian Lance Taylor wrote:
> > On Wed, Oct 17, 2012 at 8:02 AM, Alan Modra <amodra@gmail.com> wrote:
> > > Powerpc use of .got2 section in -fPIC code can lead to "relocation
> > > refers to discarded section" warnings in testcases like gcc's
> > > g++.old-deja/g++.other/comdat5.C when comdat group sections for a
> > > function are dropped but not the function's .got2 entries.  This type
> > > of problem shows up in other sections shared between functions on
> > > powerpc64, eg. .opd and .toc.  Fixed by suppressing the warning the
> > > same way bfd ld does.  OK to apply?
> > >
> > >         * target-reloc.h (relocate_section): Call get_comdat_behavior
> > >         from class Relocate.
> > >         * arm.cc (Relocate::get_comdat_behavior): New.
> > >         * i386.cc (Relocate::get_comdat_behavior): New.
> > >         * sparc.cc (Relocate::get_comdat_behavior): New.
> > >         * tilegx.cc (Relocate::get_comdat_behavior): New.
> > >         * x86_64.cc (Relocate::get_comdat_behavior): New.
> > >         * powerpc.cc (Relocate::get_comdat_behavior): New.
> > >         (Target_powerpc::relocate_section): Don't zap opd relocs.
> > 
> > 
> > You can implement this without requiring every target to have a
> > trivial get_comdat_behavior method.  Add a new template parameter to
> > relocate_section in target-reloc.h.  Give it a default value.
> > 
> > template<..., typename Relocate_comdat_behaviour = Default_comdat_behavior>
> > inline void
> > Relocate_section(...)
> 
> I thought about doing that but
> 
> error: default template arguments may not be used in function templates without -std=c++0x or -std=gnu++

So now without the default template arg.

	* 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.

Index: gold/target-reloc.h
===================================================================
RCS file: /cvs/src/src/gold/target-reloc.h,v
retrieving revision 1.54
diff -u -p -r1.54 target-reloc.h
--- gold/target-reloc.h	12 Sep 2012 22:43:53 -0000	1.54
+++ gold/target-reloc.h	17 Oct 2012 23:29:19 -0000
@@ -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 Symbo
 // 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 Symbo
 // 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: gold/arm.cc
===================================================================
RCS file: /cvs/src/src/gold/arm.cc,v
retrieving revision 1.155
diff -u -p -r1.155 arm.cc
--- gold/arm.cc	12 Sep 2012 22:43:53 -0000	1.155
+++ gold/arm.cc	17 Oct 2012 23:39:04 -0000
@@ -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_secti
     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_secti
 	  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: gold/i386.cc
===================================================================
RCS file: /cvs/src/src/gold/i386.cc,v
retrieving revision 1.149
diff -u -p -r1.149 i386.cc
--- gold/i386.cc	5 Oct 2012 00:45:54 -0000	1.149
+++ gold/i386.cc	17 Oct 2012 23:29:18 -0000
@@ -3487,7 +3487,7 @@ Target_i386::relocate_section(const Relo
   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: gold/powerpc.cc
===================================================================
RCS file: /cvs/src/src/gold/powerpc.cc,v
retrieving revision 1.65
diff -u -p -r1.65 powerpc.cc
--- gold/powerpc.cc	17 Oct 2012 14:33:41 -0000	1.65
+++ gold/powerpc.cc	17 Oct 2012 23:29:18 -0000
@@ -619,6 +619,32 @@ class Target_powerpc : public Sized_targ
     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>::reloca
 {
   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>::reloca
     address,
     view_size,
     reloc_symbol_changes);
-
-  if (opd_rel != NULL)
-    delete[] opd_rel;
 }
 
 class Powerpc_scan_relocatable_reloc
Index: gold/sparc.cc
===================================================================
RCS file: /cvs/src/src/gold/sparc.cc,v
retrieving revision 1.62
diff -u -p -r1.62 sparc.cc
--- gold/sparc.cc	5 Oct 2012 00:45:54 -0000	1.62
+++ gold/sparc.cc	17 Oct 2012 23:29:18 -0000
@@ -4138,7 +4138,7 @@ Target_sparc<size, big_endian>::relocate
   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: gold/tilegx.cc
===================================================================
RCS file: /cvs/src/src/gold/tilegx.cc,v
retrieving revision 1.3
diff -u -p -r1.3 tilegx.cc
--- gold/tilegx.cc	5 Oct 2012 00:45:54 -0000	1.3
+++ gold/tilegx.cc	17 Oct 2012 23:29:19 -0000
@@ -4733,8 +4733,8 @@ Target_tilegx<size, big_endian>::relocat
 
   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: gold/x86_64.cc
===================================================================
RCS file: /cvs/src/src/gold/x86_64.cc,v
retrieving revision 1.158
diff -u -p -r1.158 x86_64.cc
--- gold/x86_64.cc	5 Oct 2012 00:45:54 -0000	1.158
+++ gold/x86_64.cc	17 Oct 2012 23:29:19 -0000
@@ -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,


-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list