public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* PowerPC _GLOBAL_OFFSET_TABLE_
@ 2008-09-16 13:43 Alan Modra
  2008-09-19  9:50 ` Alan Modra
  0 siblings, 1 reply; 2+ messages in thread
From: Alan Modra @ 2008-09-16 13:43 UTC (permalink / raw)
  To: binutils

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)
 \f
 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;
 }
 \f
 #define TARGET_LITTLE_SYM	bfd_elf32_powerpcle_vec

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: PowerPC _GLOBAL_OFFSET_TABLE_
  2008-09-16 13:43 PowerPC _GLOBAL_OFFSET_TABLE_ Alan Modra
@ 2008-09-19  9:50 ` Alan Modra
  0 siblings, 0 replies; 2+ messages in thread
From: Alan Modra @ 2008-09-19  9:50 UTC (permalink / raw)
  To: binutils

On Tue, Sep 16, 2008 at 11:12:48PM +0930, Alan Modra wrote:
> 	(ppc_elf_finish_dynamic_sections): Likewise.  Error if
> 	htab->elf.hgot symbol is not defined in htab->got section.

My 2008-09-16 change resulted in "_GLOBAL_OFFSET_TABLE_ not defined
in linker created .got" errors on powerpc-vxworks, since in that case
the symbol is defined in .got.plt.  However, I think the code setting
up the got header has been broken since the original vxworks commit.
Space for the header is allocated in .got.plt, but the .dynamic
address was being written to .got, overwriting the first .got entry.

I couldn't find details on what vxworks expects in the got header,
so don't really know if this is correct even now..

	* elf32-ppc.c (ppc_elf_finish_dynamic_sections): Handle vxworks
	_GLOBAL_OFFSET_TABLE_ in .got.plt section.  Add BFD_ASSERTs.

Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.245
diff -u -p -r1.245 elf32-ppc.c
--- bfd/elf32-ppc.c	16 Sep 2008 13:43:36 -0000	1.245
+++ bfd/elf32-ppc.c	19 Sep 2008 09:01:06 -0000
@@ -7727,29 +7727,38 @@ ppc_elf_finish_dynamic_sections (bfd *ou
 	}
     }
 
-  /* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 so that a function can
-     easily find the address of the _GLOBAL_OFFSET_TABLE_.  */
   if (htab->got != NULL)
     {
-      if (htab->elf.hgot->root.u.def.section == htab->got)
+      if (htab->elf.hgot->root.u.def.section == htab->got
+	  || htab->elf.hgot->root.u.def.section == htab->sgotplt)
 	{
-	  unsigned char *p = htab->got->contents;
-	  bfd_vma val;
+	  unsigned char *p = htab->elf.hgot->root.u.def.section->contents;
 
 	  p += htab->elf.hgot->root.u.def.value;
 	  if (htab->plt_type == PLT_OLD)
-	    bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, p - 4);
+	    {
+	      /* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4
+		 so that a function can easily find the address of
+		 _GLOBAL_OFFSET_TABLE_.  */
+	      BFD_ASSERT (htab->elf.hgot->root.u.def.value - 4
+			  < htab->elf.hgot->root.u.def.section->size);
+	      bfd_put_32 (output_bfd, 0x4e800021, p - 4);
+	    }
 
-	  val = 0;
 	  if (sdyn != NULL)
-	    val = sdyn->output_section->vma + sdyn->output_offset;
-	  bfd_put_32 (output_bfd, val, p);
+	    {
+	      bfd_vma val = sdyn->output_section->vma + sdyn->output_offset;
+	      BFD_ASSERT (htab->elf.hgot->root.u.def.value
+			  < htab->elf.hgot->root.u.def.section->size);
+	      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);
+				 (htab->sgotplt != NULL
+				  ? htab->sgotplt->name : htab->got->name));
 	  bfd_set_error (bfd_error_bad_value);
 	  ret = FALSE;
 	}

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2008-09-19  9:50 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-09-16 13:43 PowerPC _GLOBAL_OFFSET_TABLE_ Alan Modra
2008-09-19  9:50 ` Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).