This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[GOLD] sort powerpc64 toc sections


This adds another missing piece of powerpc gold support.  When linking
large binaries with a mix of objects, some compiled with
-mcmodel=small, it is necessary to ensure the -mcmodel=small objects
have their toc sections placed in the first 64k of the output toc/got
section.  We hit this problem building gcc's libjava if the system
libc is small model, which is usually the case.

OK to apply?

	* options.h (General_options): Add --no-toc-sort.
	* output.h (Output_section::input_sections): Provide non-const variant.
	* powerpc.cc (Powerpc_relobj::has_small_toc_reloc_,
	set_has_small_toc_reloc, has_small_toc_reloc): New variable and
	accessors.
	(Target_powerpc::Scan::local, global): Call set_has_small_toc_reloc.
	(class Sort_toc_sections): New.
	(Target_powerpc::do_finalize_sections): Sort toc sections.

Index: gold/options.h
===================================================================
RCS file: /cvs/src/src/gold/options.h,v
retrieving revision 1.179
diff -u -p -r1.179 options.h
--- gold/options.h	7 Dec 2012 00:03:18 -0000	1.179
+++ gold/options.h	10 Dec 2012 11:58:36 -0000
@@ -1112,6 +1112,9 @@ class General_options
   DEFINE_bool(no_toc_optimize, options::TWO_DASHES, '\0', false,
 	      N_("(PowerPC64 only) Don't optimize TOC code sequences"), NULL);
 
+  DEFINE_bool(no_toc_sort, options::TWO_DASHES, '\0', false,
+	      N_("(PowerPC64 only) Don't sort TOC and GOT sections"), NULL);
+
   DEFINE_set(undefined, options::TWO_DASHES, 'u',
 	     N_("Create undefined reference to SYMBOL"), N_("SYMBOL"));
 
Index: gold/output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.143
diff -u -p -r1.143 output.h
--- gold/output.h	3 Dec 2012 05:48:47 -0000	1.143
+++ gold/output.h	10 Dec 2012 11:58:36 -0000
@@ -3941,6 +3941,10 @@ class Output_section : public Output_dat
   input_sections() const
   { return this->input_sections_; }
 
+  Input_section_list&
+  input_sections()
+  { return this->input_sections_; }
+
  protected:
   // Return the output section--i.e., the object itself.
   Output_section*
Index: gold/powerpc.cc
===================================================================
RCS file: /cvs/src/src/gold/powerpc.cc,v
retrieving revision 1.78
diff -u -p -r1.78 powerpc.cc
--- gold/powerpc.cc	10 Dec 2012 11:45:18 -0000	1.78
+++ gold/powerpc.cc	10 Dec 2012 11:58:36 -0000
@@ -71,7 +71,7 @@ public:
   Powerpc_relobj(const std::string& name, Input_file* input_file, off_t offset,
 		 const typename elfcpp::Ehdr<size, big_endian>& ehdr)
     : Sized_relobj_file<size, big_endian>(name, input_file, offset, ehdr),
-      special_(0), opd_valid_(false),
+      special_(0), has_small_toc_reloc_(false), opd_valid_(false),
       opd_ent_(), access_from_map_(), has14_(), stub_table_()
   { }
 
@@ -228,6 +228,14 @@ public:
   { return 0x8000; }
 
   void
+  set_has_small_toc_reloc()
+  { has_small_toc_reloc_ = true; }
+
+  bool
+  has_small_toc_reloc() const
+  { return has_small_toc_reloc_; }
+
+  void
   set_has_14bit_branch(unsigned int shndx)
   {
     if (shndx >= this->has14_.size())
@@ -281,6 +289,10 @@ private:
   // For 32-bit the .got2 section shdnx, for 64-bit the .opd section shndx.
   unsigned int special_;
 
+  // For 64-bit, whether this object uses small model relocs to access
+  // the toc.
+  bool has_small_toc_reloc_;
+
   // Set at the start of gc_process_relocs, when we know opd_ent_
   // vector is valid.  The flag could be made atomic and set in
   // do_read_relocs with memory_order_release and then tested with
@@ -4690,6 +4702,21 @@ Target_powerpc<size, big_endian>::Scan::
       unsupported_reloc_local(object, r_type);
       break;
     }
+
+  switch (r_type)
+    {
+    case elfcpp::R_POWERPC_GOT_TLSLD16:
+    case elfcpp::R_POWERPC_GOT_TLSGD16:
+    case elfcpp::R_POWERPC_GOT_TPREL16:
+    case elfcpp::R_POWERPC_GOT_DTPREL16:
+    case elfcpp::R_POWERPC_GOT16:
+    case elfcpp::R_PPC64_GOT16_DS:
+    case elfcpp::R_PPC64_TOC16:
+    case elfcpp::R_PPC64_TOC16_DS:
+      ppc_object->set_has_small_toc_reloc();
+    default:
+      break;
+    }
 }
 
 // Report an unsupported relocation against a global symbol.
@@ -5126,6 +5153,21 @@ Target_powerpc<size, big_endian>::Scan::
       unsupported_reloc_global(object, r_type, gsym);
       break;
     }
+
+  switch (r_type)
+    {
+    case elfcpp::R_POWERPC_GOT_TLSLD16:
+    case elfcpp::R_POWERPC_GOT_TLSGD16:
+    case elfcpp::R_POWERPC_GOT_TPREL16:
+    case elfcpp::R_POWERPC_GOT_DTPREL16:
+    case elfcpp::R_POWERPC_GOT16:
+    case elfcpp::R_PPC64_GOT16_DS:
+    case elfcpp::R_PPC64_TOC16:
+    case elfcpp::R_PPC64_TOC16_DS:
+      ppc_object->set_has_small_toc_reloc();
+    default:
+      break;
+    }
 }
 
 // Process relocations for gc.
@@ -5346,6 +5388,31 @@ Target_powerpc<size, big_endian>::define
     }
 }
 
+// Sort linker created .got section first (for the header), then input
+// sections belonging to files using small model code.
+
+template<bool big_endian>
+class Sort_toc_sections
+{
+ public:
+  bool
+  operator()(const Output_section::Input_section& is1,
+	     const Output_section::Input_section& is2) const
+  {
+    if (!is1.is_input_section() && is2.is_input_section())
+      return true;
+    bool small1
+      = (is1.is_input_section()
+	 && (static_cast<const Powerpc_relobj<64, big_endian>*>(is1.relobj())
+	     ->has_small_toc_reloc()));
+    bool small2
+      = (is2.is_input_section()
+	 && (static_cast<const Powerpc_relobj<64, big_endian>*>(is2.relobj())
+	     ->has_small_toc_reloc()));
+    return small1 && !small2;
+  }
+};
+
 // Finalize the sections.
 
 template<int size, bool big_endian>
@@ -5399,6 +5466,15 @@ Target_powerpc<size, big_endian>::do_fin
 	  // need to mess with the relaxation machinery checkpointing.
 	  this->got_section(symtab, layout);
 	  this->make_brlt_section(layout);
+
+	  if (!parameters->options().no_toc_sort())
+	    {
+	      Output_section* os = this->got_->output_section();
+	      if (os != NULL && os->input_sections().size() > 1)
+		std::stable_sort(os->input_sections().begin(),
+				 os->input_sections().end(),
+				 Sort_toc_sections<big_endian>());
+	    }
 	}
     }
 

-- 
Alan Modra
Australia Development Lab, IBM


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]