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] adjust local symbol values


This adds a means of adjusting and/or dropping local symbols defined
in relaxed sections.  compute_final_local_value might be a better
place to do any adjustment, but that would require two virtual
functions, one to discard unnecessary or invalid local symbols and
another to adjust values.

The powerpc changes here don't make any adjustments to symbols; That
will come in a later patch that shrinks .opd.

OK to apply?

	* object.h (Sized_relobj_file::adjust_local_symbol,
	do_adjust_local_symbol): New functions.
	* object.cc (Sized_relobj_file::do_count_local_symbols): Use the above.
	* powerpc.cc (Powerpc_relobj::do_adjust_local_symbol): New function.
	(Powerpc_relobj::scan_opd_relocs): Warn on unexpected opd relocs
	and irregular opd entry spacing.
	(Powerpc_relobj::do_read_relocs): Add opd size checks.
	(Global_symbol_visitor_opd): New functor.
	(Target_powerpc::do_finalize_sections): Omit global symbols defined
	on deleted opd entries.

Index: gold/object.h
===================================================================
RCS file: /cvs/src/src/gold/object.h,v
retrieving revision 1.120
diff -u -p -r1.120 object.h
--- gold/object.h	12 Sep 2012 18:29:18 -0000	1.120
+++ gold/object.h	20 Sep 2012 06:54:09 -0000
@@ -2112,6 +2112,12 @@ class Sized_relobj_file : public Sized_r
   void
   set_local_plt_offset(unsigned int symndx, unsigned int plt_offset);
 
+  // Adjust this local symbol value.  Return false if the symbol
+  // should be discarded from the output file.
+  bool
+  adjust_local_symbol(Symbol_value<size>* lv) const
+  { return this->do_adjust_local_symbol(lv); }
+
   // Return the name of the symbol that spans the given offset in the
   // specified section in this object.  This is used only for error
   // messages and is not particularly efficient.
@@ -2381,6 +2387,12 @@ class Sized_relobj_file : public Sized_r
 		       const unsigned char* pshdrs, Output_file* of,
 		       Views* pviews);
 
+  // Adjust this local symbol value.  Return false if the symbol
+  // should be discarded from the output file.
+  virtual bool
+  do_adjust_local_symbol(Symbol_value<size>*) const
+  { return true; }
+
   // Allow a child to set output local symbol count.
   void
   set_output_local_symbol_count(unsigned int value)
Index: gold/object.cc
===================================================================
RCS file: /cvs/src/src/gold/object.cc,v
retrieving revision 1.159
diff -u -p -r1.159 object.cc
--- gold/object.cc	7 Sep 2012 20:14:06 -0000	1.159
+++ gold/object.cc	20 Sep 2012 06:54:09 -0000
@@ -2110,7 +2110,8 @@ Sized_relobj_file<size, big_endian>::do_
 	  continue;
 	}
 
-      if (sym.get_st_type() == elfcpp::STT_SECTION)
+      if (sym.get_st_type() == elfcpp::STT_SECTION
+	  || !this->adjust_local_symbol(&lv))
 	{
 	  lv.set_no_output_symtab_entry();
 	  gold_assert(!lv.needs_output_dynsym_entry());
Index: gold/powerpc.cc
===================================================================
RCS file: /cvs/src/src/gold/powerpc.cc,v
retrieving revision 1.58
diff -u -p -r1.58 powerpc.cc
--- gold/powerpc.cc	12 Sep 2012 22:43:54 -0000	1.58
+++ gold/powerpc.cc	20 Sep 2012 06:54:09 -0000
@@ -174,6 +174,22 @@ public:
   bool
   do_find_special_sections(Read_symbols_data* sd);
 
+  // Adjust this local symbol value.  Return false if the symbol
+  // should be discarded from the output file.
+  bool
+  do_adjust_local_symbol(Symbol_value<size>* lv) const
+  {
+    if (size == 64 && this->opd_shndx() != 0)
+      {
+	bool is_ordinary;
+	if (lv->input_shndx(&is_ordinary) != this->opd_shndx())
+	  return true;
+	if (this->get_opd_discard(lv->input_value()))
+	  return false;
+      }
+    return true;
+  }
+
   // Return offset in output GOT section that this object will use
   // as a TOC pointer.  Won't be just a constant with multi-toc support.
   Address
@@ -1183,6 +1199,9 @@ Powerpc_relobj<size, big_endian>::scan_o
       const int reloc_size
 	= Reloc_types<elfcpp::SHT_RELA, size, big_endian>::reloc_size;
       const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
+      Address expected_off = 0;
+      bool regular = true;
+      unsigned int opd_ent_size = 0;
 
       for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
 	{
@@ -1209,8 +1228,37 @@ Powerpc_relobj<size, big_endian>::scan_o
 						       &is_ordinary);
 	      this->set_opd_ent(reloc.get_r_offset(), shndx,
 				value + reloc.get_r_addend());
+	      if (i == 2)
+		{
+		  expected_off = reloc.get_r_offset();
+		  opd_ent_size = expected_off;
+		}
+	      else if (expected_off != reloc.get_r_offset())
+		regular = false;
+	      expected_off += opd_ent_size;
+	    }
+	  else if (r_type == elfcpp::R_PPC64_TOC)
+	    {
+	      if (expected_off - opd_ent_size + 8 != reloc.get_r_offset())
+		regular = false;
+	    }
+	  else
+	    {
+	      gold_warning(_("%s: unexpected reloc type %u in .opd section"),
+			   this->name().c_str(), r_type);
+	      regular = false;
 	    }
 	}
+      if (reloc_count <= 2)
+	opd_ent_size = this->section_size(this->opd_shndx());
+      if (opd_ent_size != 24 && opd_ent_size != 16)
+	regular = false;
+      if (!regular)
+	{
+	  gold_warning(_("%s: .opd is not a regular array of opd entries"),
+		       this->name().c_str());
+	  opd_ent_size = 0;
+	}
     }
 }
 
@@ -1227,9 +1275,14 @@ Powerpc_relobj<size, big_endian>::do_rea
 	{
 	  if (p->data_shndx == this->opd_shndx())
 	    {
-	      this->init_opd(this->section_size(this->opd_shndx()));
-	      this->scan_opd_relocs(p->reloc_count, p->contents->data(),
-				    rd->local_symbols->data());
+	      uint64_t opd_size = this->section_size(this->opd_shndx());
+	      gold_assert(opd_size == static_cast<size_t>(opd_size));
+	      if (opd_size != 0)
+		{
+		  this->init_opd(opd_size);
+		  this->scan_opd_relocs(p->reloc_count, p->contents->data(),
+					rd->local_symbols->data());
+		}
 	      break;
 	    }
 	}
@@ -3204,6 +3257,38 @@ Target_powerpc<size, big_endian>::scan_r
     plocal_symbols);
 }
 
+// Functor class for processing the global symbol table.
+// Removes symbols defined on discarded opd entries.
+
+template<bool big_endian>
+class Global_symbol_visitor_opd
+{
+ public:
+  Global_symbol_visitor_opd()
+  { }
+
+  void
+  operator()(Sized_symbol<64>* sym)
+  {
+    if (sym->has_symtab_index()
+	|| sym->source() != Symbol::FROM_OBJECT
+	|| !sym->in_real_elf())
+      return;
+
+    Powerpc_relobj<64, big_endian>* symobj
+      = static_cast<Powerpc_relobj<64, big_endian>*>(sym->object());
+    if (symobj->is_dynamic()
+	|| symobj->opd_shndx() == 0)
+      return;
+
+    bool is_ordinary;
+    unsigned int shndx = sym->shndx(&is_ordinary);
+    if (shndx == symobj->opd_shndx()
+	&& symobj->get_opd_discard(sym->value()))
+      sym->set_symtab_index(-1U);
+  }
+};
+
 // Finalize the sections.
 
 template<int size, bool big_endian>
@@ -3211,8 +3296,14 @@ void
 Target_powerpc<size, big_endian>::do_finalize_sections(
     Layout* layout,
     const Input_objects*,
-    Symbol_table*)
+    Symbol_table* symtab)
 {
+  if (size == 64)
+    {
+      typedef Global_symbol_visitor_opd<big_endian> Symbol_visitor;
+      symtab->for_all_symbols<64, Symbol_visitor>(Symbol_visitor());
+    }
+
   // Fill in some more dynamic tags.
   const Reloc_section* rel_plt = (this->plt_ == NULL
 				  ? NULL

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