powerpc gold, work around pr17670

Alan Modra amodra@gmail.com
Wed Dec 3 23:13:00 GMT 2014


On Wed, Dec 03, 2014 at 11:19:47AM -0800, Cary Coutant wrote:
> > Making the sym undefined can
> > be done via override_base() but using that function requires setting
> > up an elfcpp::Sym, so I opted for a simpler new Symbol interface.
> 
> We already have Symbol::set_undefined(), which currently asserts that
> the symbol is predefined. I'd be OK with removing that assert, and
> allowing set_undefined() for any symbol.

That works.  Thanks!  I'm about to commit the following.

diff --git a/gold/ChangeLog b/gold/ChangeLog
index b98b76a..8ab8387 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,16 @@
+2014-12-04  Alan Modra  <amodra@gmail.com>
+
+	PR 17670
+	* symtab.cc (Symbol::set_undefined): Remove assertion.
+	* powerpc.cc (Target_powerpc::symval_for_branch): Don't assert
+	on symbols defined in discarded sections, instead return false.
+	Rearrange params, update all callers.
+	(Target_powerpc::Branch_info::make_stub): Don't make stubs for
+	branches to syms in discarded sections.
+	(Global_symbol_visitor_opd::operator()): Set discarded opd syms
+	undefined and flag as discarded.
+	(Target_powerpc::Relocate::relocate): Localize variable.
+
 2014-12-03  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR gold/17675
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 5805c0b..0da355f 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -1035,11 +1035,11 @@ class Target_powerpc : public Sized_target<size, big_endian>
     bool issued_non_pic_error_;
   };
 
-  Address
-  symval_for_branch(const Symbol_table* symtab, Address value,
+  bool
+  symval_for_branch(const Symbol_table* symtab,
 		    const Sized_symbol<size>* gsym,
 		    Powerpc_relobj<size, big_endian>* object,
-		    unsigned int *dest_shndx);
+		    Address *value, unsigned int *dest_shndx);
 
   // The class which implements relocation.
   class Relocate : protected Track_tls
@@ -2717,8 +2717,9 @@ Target_powerpc<size, big_endian>::Branch_info::make_stub(
       if (size == 64 && target->abiversion() < 2)
 	{
 	  unsigned int dest_shndx;
-	  to = target->symval_for_branch(symtab, to, gsym,
-					 this->object_, &dest_shndx);
+	  if (!target->symval_for_branch(symtab, gsym, this->object_,
+					 &to, &dest_shndx))
+	    return true;
 	}
       Address delta = to - from;
       if (delta + max_branch_offset >= 2 * max_branch_offset)
@@ -6549,7 +6550,11 @@ class Global_symbol_visitor_opd
     unsigned int shndx = sym->shndx(&is_ordinary);
     if (shndx == symobj->opd_shndx()
 	&& symobj->get_opd_discard(sym->value()))
-      sym->set_symtab_index(-1U);
+      {
+	sym->set_undefined();
+	sym->set_is_defined_in_discarded_section();
+	sym->set_symtab_index(-1U);
+      }
   }
 };
 
@@ -6727,12 +6732,12 @@ ok_lo_toc_insn(uint32_t insn)
 // Return the value to use for a branch relocation.
 
 template<int size, bool big_endian>
-typename Target_powerpc<size, big_endian>::Address
+bool
 Target_powerpc<size, big_endian>::symval_for_branch(
     const Symbol_table* symtab,
-    Address value,
     const Sized_symbol<size>* gsym,
     Powerpc_relobj<size, big_endian>* object,
+    Address *value,
     unsigned int *dest_shndx)
 {
   if (size == 32 || this->abiversion() >= 2)
@@ -6744,20 +6749,20 @@ Target_powerpc<size, big_endian>::symval_for_branch(
   Powerpc_relobj<size, big_endian>* symobj = object;
   if (gsym != NULL
       && gsym->source() != Symbol::FROM_OBJECT)
-    return value;
+    return true;
   if (gsym != NULL)
     symobj = static_cast<Powerpc_relobj<size, big_endian>*>(gsym->object());
   unsigned int shndx = symobj->opd_shndx();
   if (shndx == 0)
-    return value;
+    return true;
   Address opd_addr = symobj->get_output_section_offset(shndx);
   if (opd_addr == invalid_address)
-    return value;
+    return true;
   opd_addr += symobj->output_section_address(shndx);
-  if (value >= opd_addr && value < opd_addr + symobj->section_size(shndx))
+  if (*value >= opd_addr && *value < opd_addr + symobj->section_size(shndx))
     {
       Address sec_off;
-      *dest_shndx = symobj->get_opd_ent(value - opd_addr, &sec_off);
+      *dest_shndx = symobj->get_opd_ent(*value - opd_addr, &sec_off);
       if (symtab->is_section_folded(symobj, *dest_shndx))
 	{
 	  Section_id folded
@@ -6766,11 +6771,13 @@ Target_powerpc<size, big_endian>::symval_for_branch(
 	  *dest_shndx = folded.second;
 	}
       Address sec_addr = symobj->get_output_section_offset(*dest_shndx);
-      gold_assert(sec_addr != invalid_address);
+      if (sec_addr == invalid_address)
+	return false;
+
       sec_addr += symobj->output_section(*dest_shndx)->address();
-      value = sec_addr + sec_off;
+      *value = sec_addr + sec_off;
     }
-  return value;
+  return true;
 }
 
 // Perform a relocation.
@@ -6930,10 +6937,9 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
 		  if (target->abiversion() < 2)
 		    {
 		      Address addend = rela.get_r_addend();
-		      Address opdent = psymval->value(object, addend);
-		      code = target->symval_for_branch(relinfo->symtab,
-						       opdent, gsym, object,
-						       &dest_shndx);
+		      code = psymval->value(object, addend);
+		      target->symval_for_branch(relinfo->symtab, gsym, object,
+						&code, &dest_shndx);
 		    }
 		  bool is_ordinary;
 		  if (dest_shndx == 0)
@@ -7191,7 +7197,6 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
   else if (!has_stub_value)
     {
       Address addend = 0;
-      unsigned int dest_shndx;
       if (r_type != elfcpp::R_PPC_PLTREL24)
 	addend = rela.get_r_addend();
       value = psymval->value(object, addend);
@@ -7205,8 +7210,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
 		value += object->ppc64_local_entry_offset(r_sym);
 	    }
 	  else
-	    value = target->symval_for_branch(relinfo->symtab, value,
-					      gsym, object, &dest_shndx);
+	    {
+	      unsigned int dest_shndx;
+	      target->symval_for_branch(relinfo->symtab, gsym, object,
+					&value, &dest_shndx);
+	    }
 	}
       unsigned long max_branch_offset = max_branch_delta(r_type);
       if (max_branch_offset != 0
diff --git a/gold/symtab.cc b/gold/symtab.cc
index 70fb3f0..c433018 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -547,7 +547,6 @@ Symbol::set_output_segment(Output_segment* os, Segment_offset_base base)
 void
 Symbol::set_undefined()
 {
-  gold_assert(this->is_predefined_);
   this->source_ = IS_UNDEFINED;
   this->is_predefined_ = false;
 }

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list