[GOLD] PowerPC64 support for sym+addend GOT entries

Alan Modra amodra@gmail.com
Thu Sep 2 03:33:04 GMT 2021


Pass addends to all the GOT handling functions, plus remove some
extraneous asserts.

	PR 28192
	* powerpc.cc (Output_data_got_powerpc): Add addend parameter to
	all methods creating got entries.
	(Target_powerpc::Scan::local): Pass reloc addend to got handling
	functions, and when creating dynamic got relocations.
	(Target_powerpc::Scan::global): Likewise.
	(Target_powerpc::Relocate::relocate): Likewise.  Remove extraneous
	assertions.

diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 0b6405915c2..0cee975f8bd 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -2970,77 +2970,85 @@ public:
   // Override all the Output_data_got methods we use so as to first call
   // reserve_ent().
   bool
-  add_global(Symbol* gsym, unsigned int got_type)
+  add_global(Symbol* gsym, unsigned int got_type, uint64_t addend)
   {
     this->reserve_ent();
-    return Output_data_got<size, big_endian>::add_global(gsym, got_type);
+    return Output_data_got<size, big_endian>::add_global(gsym, got_type,
+							 addend);
   }
 
   bool
-  add_global_plt(Symbol* gsym, unsigned int got_type)
+  add_global_plt(Symbol* gsym, unsigned int got_type, uint64_t addend)
   {
     this->reserve_ent();
-    return Output_data_got<size, big_endian>::add_global_plt(gsym, got_type);
+    return Output_data_got<size, big_endian>::add_global_plt(gsym, got_type,
+							     addend);
   }
 
   bool
-  add_global_tls(Symbol* gsym, unsigned int got_type)
-  { return this->add_global_plt(gsym, got_type); }
+  add_global_tls(Symbol* gsym, unsigned int got_type, uint64_t addend)
+  { return this->add_global_plt(gsym, got_type, addend); }
 
   void
   add_global_with_rel(Symbol* gsym, unsigned int got_type,
-		      Output_data_reloc_generic* rel_dyn, unsigned int r_type)
+		      Output_data_reloc_generic* rel_dyn,
+		      unsigned int r_type, uint64_t addend)
   {
     this->reserve_ent();
     Output_data_got<size, big_endian>::
-      add_global_with_rel(gsym, got_type, rel_dyn, r_type);
+      add_global_with_rel(gsym, got_type, rel_dyn, r_type, addend);
   }
 
   void
   add_global_pair_with_rel(Symbol* gsym, unsigned int got_type,
 			   Output_data_reloc_generic* rel_dyn,
-			   unsigned int r_type_1, unsigned int r_type_2)
+			   unsigned int r_type_1, unsigned int r_type_2,
+			   uint64_t addend)
   {
     if (gsym->has_got_offset(got_type))
       return;
 
     this->reserve_ent(2);
     Output_data_got<size, big_endian>::
-      add_global_pair_with_rel(gsym, got_type, rel_dyn, r_type_1, r_type_2);
+      add_global_pair_with_rel(gsym, got_type, rel_dyn, r_type_1, r_type_2,
+			       addend);
   }
 
   bool
-  add_local(Relobj* object, unsigned int sym_index, unsigned int got_type)
+  add_local(Relobj* object, unsigned int sym_index, unsigned int got_type,
+	    uint64_t addend)
   {
     this->reserve_ent();
     return Output_data_got<size, big_endian>::add_local(object, sym_index,
-							got_type);
+							got_type, addend);
   }
 
   bool
-  add_local_plt(Relobj* object, unsigned int sym_index, unsigned int got_type)
+  add_local_plt(Relobj* object, unsigned int sym_index,
+		unsigned int got_type, uint64_t addend)
   {
     this->reserve_ent();
     return Output_data_got<size, big_endian>::add_local_plt(object, sym_index,
-							    got_type);
+							    got_type, addend);
   }
 
   bool
-  add_local_tls(Relobj* object, unsigned int sym_index, unsigned int got_type)
-  { return this->add_local_plt(object, sym_index, got_type); }
+  add_local_tls(Relobj* object, unsigned int sym_index,
+		unsigned int got_type, uint64_t addend)
+  { return this->add_local_plt(object, sym_index, got_type, addend); }
 
   void
   add_local_tls_pair(Relobj* object, unsigned int sym_index,
 		     unsigned int got_type,
 		     Output_data_reloc_generic* rel_dyn,
-		     unsigned int r_type)
+		     unsigned int r_type, uint64_t addend)
   {
-    if (object->local_has_got_offset(sym_index, got_type))
+    if (object->local_has_got_offset(sym_index, got_type, addend))
       return;
 
     this->reserve_ent(2);
     Output_data_got<size, big_endian>::
-      add_local_tls_pair(object, sym_index, got_type, rel_dyn, r_type);
+      add_local_tls_pair(object, sym_index, got_type, rel_dyn, r_type, addend);
   }
 
   unsigned int
@@ -8195,29 +8203,30 @@ Target_powerpc<size, big_endian>::Scan::local(
 	Output_data_got_powerpc<size, big_endian>* got
 	  = target->got_section(symtab, layout);
 	unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+	uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 
 	if (!parameters->options().output_is_position_independent())
 	  {
 	    if (is_ifunc
 		&& (size == 32 || target->abiversion() >= 2))
-	      got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD);
+	      got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD, addend);
 	    else
-	      got->add_local(object, r_sym, GOT_TYPE_STANDARD);
+	      got->add_local(object, r_sym, GOT_TYPE_STANDARD, addend);
 	  }
-	else if (!object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD))
+	else if (!object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD, addend))
 	  {
 	    // If we are generating a shared object or a pie, this
 	    // symbol's GOT entry will be set by a dynamic relocation.
 	    unsigned int off;
 	    off = got->add_constant(0);
-	    object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off);
+	    object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off, addend);
 
 	    Reloc_section* rela_dyn = target->rela_dyn_section(symtab, layout,
 							       is_ifunc);
 	    unsigned int dynrel = (is_ifunc ? elfcpp::R_POWERPC_IRELATIVE
 				   : elfcpp::R_POWERPC_RELATIVE);
 	    rela_dyn->add_local_relative(object, r_sym, dynrel,
-					 got, off, 0, false);
+					 got, off, addend, false);
 	  }
       }
       break;
@@ -8246,9 +8255,11 @@ Target_powerpc<size, big_endian>::Scan::local(
 	    Output_data_got_powerpc<size, big_endian>* got
 	      = target->got_section(symtab, layout);
 	    unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+	    uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 	    Reloc_section* rela_dyn = target->rela_dyn_section(layout);
 	    got->add_local_tls_pair(object, r_sym, GOT_TYPE_TLSGD,
-				    rela_dyn, elfcpp::R_POWERPC_DTPMOD);
+				    rela_dyn, elfcpp::R_POWERPC_DTPMOD,
+				    addend);
 	  }
 	else if (tls_type == tls::TLSOPT_TO_LE)
 	  {
@@ -8296,7 +8307,8 @@ Target_powerpc<size, big_endian>::Scan::local(
 	Output_data_got_powerpc<size, big_endian>* got
 	  = target->got_section(symtab, layout);
 	unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-	got->add_local_tls(object, r_sym, GOT_TYPE_DTPREL);
+	uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
+	got->add_local_tls(object, r_sym, GOT_TYPE_DTPREL, addend);
       }
       break;
 
@@ -8310,17 +8322,18 @@ Target_powerpc<size, big_endian>::Scan::local(
 	if (tls_type == tls::TLSOPT_NONE)
 	  {
 	    unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-	    if (!object->local_has_got_offset(r_sym, GOT_TYPE_TPREL))
+	    uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
+	    if (!object->local_has_got_offset(r_sym, GOT_TYPE_TPREL, addend))
 	      {
 		Output_data_got_powerpc<size, big_endian>* got
 		  = target->got_section(symtab, layout);
 		unsigned int off = got->add_constant(0);
-		object->set_local_got_offset(r_sym, GOT_TYPE_TPREL, off);
+		object->set_local_got_offset(r_sym, GOT_TYPE_TPREL, off, addend);
 
 		Reloc_section* rela_dyn = target->rela_dyn_section(layout);
 		rela_dyn->add_symbolless_local_addend(object, r_sym,
 						      elfcpp::R_POWERPC_TPREL,
-						      got, off, 0);
+						      got, off, addend);
 	      }
 	  }
 	else if (tls_type == tls::TLSOPT_TO_LE)
@@ -8980,22 +8993,23 @@ Target_powerpc<size, big_endian>::Scan::global(
       {
 	// The symbol requires a GOT entry.
 	Output_data_got_powerpc<size, big_endian>* got;
+	uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 
 	got = target->got_section(symtab, layout);
 	if (gsym->final_value_is_known())
 	  {
 	    if (is_ifunc
 		&& (size == 32 || target->abiversion() >= 2))
-	      got->add_global_plt(gsym, GOT_TYPE_STANDARD);
+	      got->add_global_plt(gsym, GOT_TYPE_STANDARD, addend);
 	    else
-	      got->add_global(gsym, GOT_TYPE_STANDARD);
+	      got->add_global(gsym, GOT_TYPE_STANDARD, addend);
 	  }
-	else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
+	else if (!gsym->has_got_offset(GOT_TYPE_STANDARD, addend))
 	  {
 	    // If we are generating a shared object or a pie, this
 	    // symbol's GOT entry will be set by a dynamic relocation.
 	    unsigned int off = got->add_constant(0);
-	    gsym->set_got_offset(GOT_TYPE_STANDARD, off);
+	    gsym->set_got_offset(GOT_TYPE_STANDARD, off, addend);
 
 	    Reloc_section* rela_dyn
 	      = target->rela_dyn_section(symtab, layout, is_ifunc);
@@ -9008,12 +9022,13 @@ Target_powerpc<size, big_endian>::Scan::global(
 	      {
 		unsigned int dynrel = (is_ifunc ? elfcpp::R_POWERPC_IRELATIVE
 				       : elfcpp::R_POWERPC_RELATIVE);
-		rela_dyn->add_global_relative(gsym, dynrel, got, off, 0, false);
+		rela_dyn->add_global_relative(gsym, dynrel, got, off,
+					      addend, false);
 	      }
 	    else
 	      {
 		unsigned int dynrel = elfcpp::R_POWERPC_GLOB_DAT;
-		rela_dyn->add_global(gsym, dynrel, got, off, 0);
+		rela_dyn->add_global(gsym, dynrel, got, off, addend);
 	      }
 	  }
       }
@@ -9046,9 +9061,11 @@ Target_powerpc<size, big_endian>::Scan::global(
 	    Output_data_got_powerpc<size, big_endian>* got
 	      = target->got_section(symtab, layout);
 	    Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+	    uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 	    got->add_global_pair_with_rel(gsym, GOT_TYPE_TLSGD, rela_dyn,
 					  elfcpp::R_POWERPC_DTPMOD,
-					  elfcpp::R_POWERPC_DTPREL);
+					  elfcpp::R_POWERPC_DTPREL,
+					  addend);
 	  }
 	else if (tls_type == tls::TLSOPT_TO_IE)
 	  {
@@ -9057,11 +9074,12 @@ Target_powerpc<size, big_endian>::Scan::global(
 		Output_data_got_powerpc<size, big_endian>* got
 		  = target->got_section(symtab, layout);
 		Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+		uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 		if (gsym->is_undefined()
 		    || gsym->is_from_dynobj())
 		  {
 		    got->add_global_with_rel(gsym, GOT_TYPE_TPREL, rela_dyn,
-					     elfcpp::R_POWERPC_TPREL);
+					     elfcpp::R_POWERPC_TPREL, addend);
 		  }
 		else
 		  {
@@ -9069,7 +9087,7 @@ Target_powerpc<size, big_endian>::Scan::global(
 		    gsym->set_got_offset(GOT_TYPE_TPREL, off);
 		    unsigned int dynrel = elfcpp::R_POWERPC_TPREL;
 		    rela_dyn->add_symbolless_global_addend(gsym, dynrel,
-							   got, off, 0);
+							   got, off, addend);
 		  }
 	      }
 	    ppc_object->set_tls_marker();
@@ -9119,15 +9137,16 @@ Target_powerpc<size, big_endian>::Scan::global(
       {
 	Output_data_got_powerpc<size, big_endian>* got
 	  = target->got_section(symtab, layout);
+	uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 	if (!gsym->final_value_is_known()
 	    && (gsym->is_from_dynobj()
 		|| gsym->is_undefined()
 		|| gsym->is_preemptible()))
 	  got->add_global_with_rel(gsym, GOT_TYPE_DTPREL,
 				   target->rela_dyn_section(layout),
-				   elfcpp::R_POWERPC_DTPREL);
+				   elfcpp::R_POWERPC_DTPREL, addend);
 	else
-	  got->add_global_tls(gsym, GOT_TYPE_DTPREL);
+	  got->add_global_tls(gsym, GOT_TYPE_DTPREL, addend);
       }
       break;
 
@@ -9146,11 +9165,12 @@ Target_powerpc<size, big_endian>::Scan::global(
 		Output_data_got_powerpc<size, big_endian>* got
 		  = target->got_section(symtab, layout);
 		Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+		uint64_t addend = size == 32 ? 0 : reloc.get_r_addend();
 		if (gsym->is_undefined()
 		    || gsym->is_from_dynobj())
 		  {
 		    got->add_global_with_rel(gsym, GOT_TYPE_TPREL, rela_dyn,
-					     elfcpp::R_POWERPC_TPREL);
+					     elfcpp::R_POWERPC_TPREL, addend);
 		  }
 		else
 		  {
@@ -9158,7 +9178,7 @@ Target_powerpc<size, big_endian>::Scan::global(
 		    gsym->set_got_offset(GOT_TYPE_TPREL, off);
 		    unsigned int dynrel = elfcpp::R_POWERPC_TPREL;
 		    rela_dyn->add_symbolless_global_addend(gsym, dynrel,
-							   got, off, 0);
+							   got, off, addend);
 		  }
 	      }
 	  }
@@ -10655,16 +10675,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     }
   else if (is_got_reloc(r_type))
     {
+      uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
       if (gsym != NULL)
-	{
-	  gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
-	  value = gsym->got_offset(GOT_TYPE_STANDARD);
-	}
+	value = gsym->got_offset(GOT_TYPE_STANDARD, addend);
       else
-	{
-	  gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
-	  value = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
-	}
+	value = object->local_got_offset(r_sym, GOT_TYPE_STANDARD, addend);
       if (r_type == elfcpp::R_PPC64_GOT_PCREL34)
 	value += target->got_section()->address();
       else
@@ -10764,16 +10779,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
 	got_type = GOT_TYPE_TPREL;
       if (got_type != GOT_TYPE_STANDARD)
 	{
+	  uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
 	  if (gsym != NULL)
-	    {
-	      gold_assert(gsym->has_got_offset(got_type));
-	      value = gsym->got_offset(got_type);
-	    }
+	    value = gsym->got_offset(got_type, addend);
 	  else
-	    {
-	      gold_assert(object->local_has_got_offset(r_sym, got_type));
-	      value = object->local_got_offset(r_sym, got_type);
-	    }
+	    value = object->local_got_offset(r_sym, got_type, addend);
 	  if (r_type == elfcpp::R_PPC64_GOT_TLSGD_PCREL34)
 	    value += target->got_section()->address();
 	  else
@@ -10920,16 +10930,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     {
       // Accesses relative to a local dynamic sequence address,
       // no optimisation here.
+      uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
       if (gsym != NULL)
-	{
-	  gold_assert(gsym->has_got_offset(GOT_TYPE_DTPREL));
-	  value = gsym->got_offset(GOT_TYPE_DTPREL);
-	}
+	value = gsym->got_offset(GOT_TYPE_DTPREL, addend);
       else
-	{
-	  gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_DTPREL));
-	  value = object->local_got_offset(r_sym, GOT_TYPE_DTPREL);
-	}
+	value = object->local_got_offset(r_sym, GOT_TYPE_DTPREL, addend);
       if (r_type == elfcpp::R_PPC64_GOT_DTPREL_PCREL34)
 	value += target->got_section()->address();
       else
@@ -10946,16 +10951,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
       tls::Tls_optimization tls_type = target->optimize_tls_ie(final);
       if (tls_type == tls::TLSOPT_NONE)
 	{
+	  uint64_t addend = size == 32 ? 0 : rela.get_r_addend();
 	  if (gsym != NULL)
-	    {
-	      gold_assert(gsym->has_got_offset(GOT_TYPE_TPREL));
-	      value = gsym->got_offset(GOT_TYPE_TPREL);
-	    }
+	    value = gsym->got_offset(GOT_TYPE_TPREL, addend);
 	  else
-	    {
-	      gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_TPREL));
-	      value = object->local_got_offset(r_sym, GOT_TYPE_TPREL);
-	    }
+	    value = object->local_got_offset(r_sym, GOT_TYPE_TPREL, addend);
 	  if (r_type == elfcpp::R_PPC64_GOT_TPREL_PCREL34)
 	    value += target->got_section()->address();
 	  else

-- 
Alan Modra
Australia Development Lab, IBM


More information about the Binutils mailing list