[GOLD] powerpc --gc-sections --shared

Alan Modra amodra@gmail.com
Fri Oct 12 09:43:00 GMT 2012


This corrects a problem with --gc-sections on powerpc64.
gc_mark_symbol can be called during Add_symbols, which happens before
.opd relocs are scanned to set up .opd info.  In that case, we need to
delay marking function sections.

	* powerpc.cc (Powerpc_relobj::add_gc_mark, process_gc_mark): New.
	(struct Opd_ent): Make "discard" a bit field.  Add "gc_mark".
	(Target_powerpc::do_gc_mark_symbol): Delay marking function code
	section if scan_opd_relocs not yet called.
	(Target_powerpc::gc_process_relocs): Call process_gc_mark.

Index: gold/powerpc.cc
===================================================================
RCS file: /cvs/src/src/gold/powerpc.cc,v
retrieving revision 1.62
diff -u -p -r1.62 powerpc.cc
--- gold/powerpc.cc	12 Oct 2012 09:39:19 -0000	1.62
+++ gold/powerpc.cc	12 Oct 2012 09:39:57 -0000
@@ -154,6 +154,28 @@ public:
     this->access_from_map_[dst_off].insert(src_id);
   }
 
+  // Add a reference to the code section specified by the .opd entry
+  // at DST_OFF
+  void
+  add_gc_mark(typename elfcpp::Elf_types<size>::Elf_Addr dst_off)
+  {
+    size_t ndx = this->opd_ent_ndx(dst_off);
+    if (ndx >= this->opd_ent_.size())
+      this->opd_ent_.resize(ndx + 1);
+    this->opd_ent_[ndx].gc_mark = true;
+  }
+
+  void
+  process_gc_mark(Symbol_table* symtab)
+  {
+    for (size_t i = 0; i < this->opd_ent_.size(); i++)
+      if (this->opd_ent_[i].gc_mark)
+	{
+	  unsigned int shndx = this->opd_ent_[i].shndx;
+	  symtab->gc()->worklist().push(Section_id(this, shndx));
+	}
+  }
+
   bool
   opd_valid() const
   { return this->opd_valid_; }
@@ -200,7 +222,8 @@ private:
   struct Opd_ent
   {
     unsigned int shndx;
-    bool discard;
+    bool discard : 1;
+    bool gc_mark : 1;
     Offset off;
   };
 
@@ -3499,6 +3522,7 @@ Target_powerpc<size, big_endian>::gc_pro
 	  p->second.clear();
 	}
       ppc_object->access_from_map()->clear();
+      ppc_object->process_gc_mark(symtab);
       // Don't look at .opd relocs as .opd will reference everything.
       return;
     }
@@ -3571,8 +3595,13 @@ Target_powerpc<size, big_endian>::do_gc_
 	{
 	  Sized_symbol<size>* gsym = symtab->get_sized_symbol<size>(sym);
 	  Address dst_off = gsym->value();
-	  unsigned int dst_indx = ppc_object->get_opd_ent(dst_off);
-	  symtab->gc()->worklist().push(Section_id(ppc_object, dst_indx));
+	  if (ppc_object->opd_valid())
+	    {
+	      unsigned int dst_indx = ppc_object->get_opd_ent(dst_off);
+	      symtab->gc()->worklist().push(Section_id(ppc_object, dst_indx));
+	    }
+	  else
+	    ppc_object->add_gc_mark(dst_off);
 	}
     }
 }

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list