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 _GLOBAL_OFFSET_TABLE_


While I closed PR 6844 as invalid, due to a link script defining
_GLOBAL_OFFSET_TABLE_ outside of the .got section (and outside the
size of the .got section too), I figure that ld shouldn't segfault.
_GLOBAL_OFFSET_TABLE_ is special.  It marks a header in the linker
generated .got section, so can't be defined somewhere else by a linker
script.

What's more, on checking uses of this symbol, I found a case where
we would generate a wrong relocation if the linker generated .got
section wasn't the first section in the output .got section.  (You'd
need decidedly odd object files to trigger this.)

	PR 6844
	* elf32-ppc.c (SYM_VAL): Define.  Use throughout to find symbol vma.
	(ppc_elf_relocate_section): Correct GOT offset calculation.
	(ppc_elf_finish_dynamic_symbol): Use PPC_HA and PPC_LO.
	(ppc_elf_finish_dynamic_sections): Likewise.  Error if
	htab->elf.hgot symbol is not defined in htab->got section.

Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.244
diff -u -p -r1.244 elf32-ppc.c
--- bfd/elf32-ppc.c	15 Sep 2008 23:41:55 -0000	1.244
+++ bfd/elf32-ppc.c	16 Sep 2008 13:26:37 -0000
@@ -157,6 +157,12 @@ static const bfd_vma ppc_elf_vxworks_pic
 /* Offset of tp and dtp pointers from start of TLS block.  */
 #define TP_OFFSET	0x7000
 #define DTP_OFFSET	0x8000
+
+/* The value of a defined global symbol.  */
+#define SYM_VAL(SYM) \
+  ((SYM)->root.u.def.section->output_section->vma	\
+   + (SYM)->root.u.def.section->output_offset		\
+   + (SYM)->root.u.def.value)
 
 static reloc_howto_type *ppc_elf_howto_table[R_PPC_max];
 
@@ -6656,8 +6662,10 @@ ppc_elf_relocate_section (bfd *output_bf
 		  }
 	      }
 
-	    relocation = htab->got->output_offset + off;
-	    relocation -= htab->elf.hgot->root.u.def.value;
+	    relocation = (htab->got->output_section->vma
+			  + htab->got->output_offset
+			  + off
+			  - SYM_VAL (htab->elf.hgot));
 
 	    /* Addends on got relocations don't make much sense.
 	       x+off@got is actually x@got+off, and since the got is
@@ -7014,7 +7022,6 @@ ppc_elf_relocate_section (bfd *output_bf
 	case R_PPC_SDAREL16:
 	  {
 	    const char *name;
-	    struct elf_link_hash_entry *sh;
 
 	    if (sec == NULL || sec->output_section == NULL)
 	      {
@@ -7036,10 +7043,7 @@ ppc_elf_relocate_section (bfd *output_bf
 		   howto->name,
 		   name);
 	      }
-	    sh = htab->sdata[0].sym;
-	    addend -= (sh->root.u.def.value
-		       + sh->root.u.def.section->output_offset
-		       + sh->root.u.def.section->output_section->vma);
+	    addend -= SYM_VAL (htab->sdata[0].sym);
 	  }
 	  break;
 
@@ -7047,7 +7051,6 @@ ppc_elf_relocate_section (bfd *output_bf
 	case R_PPC_EMB_SDA2REL:
 	  {
 	    const char *name;
-	    struct elf_link_hash_entry *sh;
 
 	    if (sec == NULL || sec->output_section == NULL)
 	      {
@@ -7071,10 +7074,7 @@ ppc_elf_relocate_section (bfd *output_bf
 		ret = FALSE;
 		continue;
 	      }
-	    sh = htab->sdata[1].sym;
-	    addend -= (sh->root.u.def.value
-		       + sh->root.u.def.section->output_offset
-		       + sh->root.u.def.section->output_section->vma);
+	    addend -= SYM_VAL (htab->sdata[1].sym);
 	  }
 	  break;
 
@@ -7084,7 +7084,6 @@ ppc_elf_relocate_section (bfd *output_bf
 	  {
 	    const char *name;
 	    int reg;
-	    struct elf_link_hash_entry *sh;
 
 	    if (sec == NULL || sec->output_section == NULL)
 	      {
@@ -7099,19 +7098,13 @@ ppc_elf_relocate_section (bfd *output_bf
 		     && (name[5] == 0 || name[5] == '.'))))
 	      {
 		reg = 13;
-		sh = htab->sdata[0].sym;
-		addend -= (sh->root.u.def.value
-			   + sh->root.u.def.section->output_offset
-			   + sh->root.u.def.section->output_section->vma);
+		addend -= SYM_VAL (htab->sdata[0].sym);
 	      }
 	    else if (CONST_STRNEQ (name, ".sdata2")
 		     || CONST_STRNEQ (name, ".sbss2"))
 	      {
 		reg = 2;
-		sh = htab->sdata[1].sym;
-		addend -= (sh->root.u.def.value
-			   + sh->root.u.def.section->output_offset
-			   + sh->root.u.def.section->output_section->vma);
+		addend -= SYM_VAL (htab->sdata[1].sym);
 	      }
 	    else if (strcmp (name, ".PPC.EMB.sdata0") == 0
 		     || strcmp (name, ".PPC.EMB.sbss0") == 0)
@@ -7366,31 +7359,22 @@ ppc_elf_finish_dynamic_symbol (bfd *outp
 		/* Fill in the .plt on VxWorks.  */
 		if (info->shared)
 		  {
-		    bfd_vma got_offset_hi = (got_offset >> 16)
-					    + ((got_offset & 0x8000) >> 15);
-
 		    bfd_put_32 (output_bfd,
-				plt_entry[0] | (got_offset_hi & 0xffff),
+				plt_entry[0] | PPC_HA (got_offset),
 				htab->plt->contents + ent->plt.offset + 0);
 		    bfd_put_32 (output_bfd,
-				plt_entry[1] | (got_offset & 0xffff),
+				plt_entry[1] | PPC_LO (got_offset),
 				htab->plt->contents + ent->plt.offset + 4);
 		  }
 		else
 		  {
-		    bfd_vma got_loc
-		      = (got_offset
-			 + htab->elf.hgot->root.u.def.value
-			 + htab->elf.hgot->root.u.def.section->output_offset
-			 + htab->elf.hgot->root.u.def.section->output_section->vma);
-		    bfd_vma got_loc_hi = (got_loc >> 16)
-					 + ((got_loc & 0x8000) >> 15);
+		    bfd_vma got_loc = got_offset + SYM_VAL (htab->elf.hgot);
 
 		    bfd_put_32 (output_bfd,
-				plt_entry[0] | (got_loc_hi & 0xffff),
+				plt_entry[0] | PPC_HA (got_loc),
 				htab->plt->contents + ent->plt.offset + 0);
 		    bfd_put_32 (output_bfd,
-				plt_entry[1] | (got_loc & 0xffff),
+				plt_entry[1] | PPC_LO (got_loc),
 				htab->plt->contents + ent->plt.offset + 4);
 		  }
 
@@ -7550,9 +7534,7 @@ ppc_elf_finish_dynamic_symbol (bfd *outp
 			 + ent->sec->output_section->vma
 			 + ent->sec->output_offset);
 		else if (htab->elf.hgot != NULL)
-		  got = (htab->elf.hgot->root.u.def.value
-			 + htab->elf.hgot->root.u.def.section->output_section->vma
-			 + htab->elf.hgot->root.u.def.section->output_offset);
+		  got = SYM_VAL (htab->elf.hgot);
 
 		plt -= got;
 
@@ -7618,9 +7600,7 @@ ppc_elf_finish_dynamic_symbol (bfd *outp
 	s = htab->relbss;
       BFD_ASSERT (s != NULL);
 
-      rela.r_offset = (h->root.u.def.value
-		       + h->root.u.def.section->output_section->vma
-		       + h->root.u.def.section->output_offset);
+      rela.r_offset = SYM_VAL (h);
       rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_COPY);
       rela.r_addend = 0;
       loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
@@ -7670,7 +7650,8 @@ ppc_elf_finish_dynamic_sections (bfd *ou
   asection *splt;
   struct ppc_elf_link_hash_table *htab;
   bfd_vma got;
-  bfd * dynobj;
+  bfd *dynobj;
+  bfd_boolean ret = TRUE;
 
 #ifdef DEBUG
   fprintf (stderr, "ppc_elf_finish_dynamic_sections called\n");
@@ -7686,9 +7667,7 @@ ppc_elf_finish_dynamic_sections (bfd *ou
 
   got = 0;
   if (htab->elf.hgot != NULL)
-    got = (htab->elf.hgot->root.u.def.value
-	   + htab->elf.hgot->root.u.def.section->output_section->vma
-	   + htab->elf.hgot->root.u.def.section->output_offset);
+    got = SYM_VAL (htab->elf.hgot);
 
   if (htab->elf.dynamic_sections_created)
     {
@@ -7752,17 +7731,28 @@ ppc_elf_finish_dynamic_sections (bfd *ou
      easily find the address of the _GLOBAL_OFFSET_TABLE_.  */
   if (htab->got != NULL)
     {
-      unsigned char *p = htab->got->contents;
-      bfd_vma val;
+      if (htab->elf.hgot->root.u.def.section == htab->got)
+	{
+	  unsigned char *p = htab->got->contents;
+	  bfd_vma val;
 
-      p += htab->elf.hgot->root.u.def.value;
-      if (htab->plt_type == PLT_OLD)
-	bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, p - 4);
-
-      val = 0;
-      if (sdyn != NULL)
-	val = sdyn->output_section->vma + sdyn->output_offset;
-      bfd_put_32 (output_bfd, val, p);
+	  p += htab->elf.hgot->root.u.def.value;
+	  if (htab->plt_type == PLT_OLD)
+	    bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, p - 4);
+
+	  val = 0;
+	  if (sdyn != NULL)
+	    val = sdyn->output_section->vma + sdyn->output_offset;
+	  bfd_put_32 (output_bfd, val, p);
+	}
+      else
+	{
+	  (*_bfd_error_handler) (_("%s not defined in linker created %s"),
+				 htab->elf.hgot->root.root.string,
+				 htab->got->name);
+	  bfd_set_error (bfd_error_bad_value);
+	  ret = FALSE;
+	}
 
       elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 4;
     }
@@ -7777,15 +7767,11 @@ ppc_elf_finish_dynamic_sections (bfd *ou
 
       if (!info->shared)
 	{
-	  bfd_vma got_value =
-	    (htab->elf.hgot->root.u.def.section->output_section->vma
-	     + htab->elf.hgot->root.u.def.section->output_offset
-	     + htab->elf.hgot->root.u.def.value);
-	  bfd_vma got_hi = (got_value >> 16) + ((got_value & 0x8000) >> 15);
+	  bfd_vma got_value = SYM_VAL (htab->elf.hgot);
 
-	  bfd_put_32 (output_bfd, plt_entry[0] | (got_hi & 0xffff),
+	  bfd_put_32 (output_bfd, plt_entry[0] | PPC_HA (got_value),
 		      splt->contents +  0);
-	  bfd_put_32 (output_bfd, plt_entry[1] | (got_value & 0xffff),
+	  bfd_put_32 (output_bfd, plt_entry[1] | PPC_LO (got_value),
 		      splt->contents +  4);
 	}
       else
@@ -8050,7 +8036,7 @@ ppc_elf_finish_dynamic_sections (bfd *ou
 	}
     }
 
-  return TRUE;
+  return ret;
 }
 
 #define TARGET_LITTLE_SYM	bfd_elf32_powerpcle_vec

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