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]

powerpc gold, work around pr17670


pr17670 is about an assert triggering on a branch to an undefined
weak symbol, the symbol being undefined due to dropping its comdat
group section.  (Well sort of.  The symbol is actually defined in
an .opd section which isn't part of the group, but the code section
the opd entry points at is dropped.)  So don't assert.
Also, don't make long branch stubs to such symbols, and arrange to
have target-reloc.h code warn when applying relocs that use the sym
by making the sym seem to be undefined.  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.

OK to apply?

	PR 17670
	* symtab.h (Symbol::set_shndx): New function.
	* 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, value 0, and flag as discarded.
	(Target_powerpc::Relocate::relocate): Localize variable.

diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 5805c0b..7b8d604 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,12 @@ 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_shndx(elfcpp::SHN_UNDEF);
+	sym->set_value(0);
+	sym->set_symtab_index(-1U);
+	sym->set_is_defined_in_discarded_section();
+      }
   }
 };
 
@@ -6727,12 +6733,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 +6750,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 +6772,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 +6938,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 +7198,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 +7211,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.h b/gold/symtab.h
index 7984dd6..8b7650d 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -167,6 +167,14 @@ class Symbol
     return this->u_.from_object.shndx;
   }
 
+  // Set section index in the relocatable or dynamic object file.
+  void
+  set_shndx(unsigned int shndx)
+  {
+    gold_assert(this->source_ == FROM_OBJECT);
+    this->u_.from_object.shndx = shndx;
+  }
+
   // Return the output data section with which this symbol is
   // associated, if the symbol was specially defined with respect to
   // an output data section.

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