Rewrite elf32-ppc.c _SDA_BASE_ code.

Alan Modra amodra@bigpond.net.au
Mon Mar 21 15:31:00 GMT 2005


This patch rewrites code in elf32-ppc.c involved with _SDA_BASE_ and
_SDA2_BASE_ symbols, defining them only when needed as absolute hidden
symbols.  If .sdata/.sbss isn't used the symbol will be defined as zero
which is as the ABI says it ought to be.

The idea of attaching symbols to input sections wasn't that robust.
For instance, it is possible to input something to .sdata (linker script
data or file with .sdata section but no relocs) before check_relocs is
called, which results in the wrong value for _SDA_BASE_ with the old
code.  Also, the old code required that every powerpc-linux object
had a .sdata and .sdata2 section, regardless of whether they were empty
or not.

bfd/
	* elf32-ppc.c (struct elf_linker_section): Remove sym_hash and
	sym_offset.  Add name, bss_name, sym_name, sym_val.
	(struct ppc_elf_link_hash_table): Remove sdata and sdata2 pointers.
	Add sdata array of elf_linker_section_t.
	(ppc_elf_link_hash_table_create): Set name, sym_name, and bss_name.
	(enum elf_linker_section_enum): Delete.
	(ppc_elf_create_linker_section): Rewrite.  Don't create syms here.
	(ppc_elf_check_relocs): Delay ppc_elf_create_linker_section until
	the special sections are needed.  Adjust htab->sdata refs.
	Ensure dynobj is set in sreloc code.
	(ppc_elf_size_dynamic_sections): Strip sdata sections.
	(ppc_elf_set_sdata_syms): New function.
	(elf_finish_pointer_linker_section): Use 0x8000 for sym_offset.
	(ppc_elf_relocate_section): Adjust references to htab->sdata.  Use
	sym_val instead of sym_hash.
	* elf32-ppc.h (ppc_elf_set_sdata_syms): Declare.
ld/
	* emultempl/ppc32elf.em (gld${EMULATION_NAME}_after_allocation): New
	function.
	(LDEMUL_AFTER_ALLOCATION): Define.

Applying mainline.

Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.142
diff -u -p -r1.142 elf32-ppc.c
--- bfd/elf32-ppc.c	21 Mar 2005 12:24:10 -0000	1.142
+++ bfd/elf32-ppc.c	21 Mar 2005 12:26:59 -0000
@@ -1506,12 +1506,16 @@ ppc_elf_unhandled_reloc (bfd *abfd,
 
 typedef struct elf_linker_section
 {
-  /* pointer to the section */
+  /* Pointer to the bfd section.  */
   asection *section;
-  /* pointer to the created symbol hash value */
-  struct elf_link_hash_entry *sym_hash;
-  /* offset of symbol from beginning of section */
-  bfd_vma sym_offset;
+  /* Section name.  */
+  const char *name;
+  /* Associated bss section name.  */
+  const char *bss_name;
+  /* Associated symbol name.  */
+  const char *sym_name;
+  /* Value of symbol.  */
+  bfd_vma sym_val;
 } elf_linker_section_t;
 
 /* Linked list of allocated pointer entries.  This hangs off of the
@@ -2117,8 +2121,7 @@ struct ppc_elf_link_hash_table
   asection *relbss;
   asection *dynsbss;
   asection *relsbss;
-  elf_linker_section_t *sdata;
-  elf_linker_section_t *sdata2;
+  elf_linker_section_t sdata[2];
   asection *sbss;
 
   /* Shortcut to .__tls_get_addr.  */
@@ -2186,6 +2189,14 @@ ppc_elf_link_hash_table_create (bfd *abf
       return NULL;
     }
 
+  ret->sdata[0].name = ".sdata";
+  ret->sdata[0].sym_name = "_SDA_BASE_";
+  ret->sdata[0].bss_name = ".sbss";
+
+  ret->sdata[1].name = ".sdata2";
+  ret->sdata[1].sym_name = "_SDA2_BASE_";
+  ret->sdata[1].bss_name = ".sbss2";
+
   return &ret->elf.root;
 }
 
@@ -2385,121 +2399,47 @@ ppc_elf_add_symbol_hook (bfd *abfd,
   return TRUE;
 }
 
-/* Enumeration to specify the special section.  */
-enum elf_linker_section_enum
-{
-  LINKER_SECTION_SDATA,
-  LINKER_SECTION_SDATA2
-};
+/* Create a special linker section.  */
 
-/* Create a special linker section */
-static elf_linker_section_t *
+static bfd_boolean
 ppc_elf_create_linker_section (bfd *abfd,
 			       struct bfd_link_info *info,
-			       enum elf_linker_section_enum which)
+			       flagword flags,
+			       elf_linker_section_t *lsect)
 {
-  elf_linker_section_t *lsect;
   struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
-  asection *s, *sym_sec;
-  bfd_size_type amt;
-  flagword flags;
-  const char *name;
-  const char *rel_name;
-  const char *sym_name;
-  bfd_vma sym_offset;
-
-  /* The linker creates these sections so it has somewhere to attach
-     their respective symbols.  Startup code (crt1.o) uses these symbols
-     to initialize a register pointing to the section.  If the output
-     sections corresponding to these input sections were empty it would
-     be OK to set the symbol to 0 (or any random number), because the
-     associated register should never be used.
-     FIXME: Setting a symbol this way is silly.  The symbols ought to 
-     be set the same way other backends set gp.  */
-  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
-	   | SEC_LINKER_CREATED);
-  sym_offset = 32768;
-
-  switch (which)
-    {
-    default:
-      abort ();
-      return NULL;
-
-    case LINKER_SECTION_SDATA:	/* .sdata/.sbss section */
-      name	= ".sdata";
-      rel_name	= ".rela.sdata";
-      sym_name	= "_SDA_BASE_";
-      break;
+  asection *s;
 
-    case LINKER_SECTION_SDATA2:	/* .sdata2/.sbss2 section */
-      name	= ".sdata2";
-      rel_name	= ".rela.sdata2";
-      sym_name	= "_SDA2_BASE_";
-      flags    |= SEC_READONLY;
-      break;
-    }
+  flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+	    | SEC_LINKER_CREATED);
 
   /* Record the first bfd that needs the special sections.  */
   if (!htab->elf.dynobj)
     htab->elf.dynobj = abfd;
 
-  amt = sizeof (elf_linker_section_t);
-  lsect = bfd_zalloc (htab->elf.dynobj, amt);
-
-  lsect->sym_offset = sym_offset;
-
-  /* See if the sections already exist.  */
-  sym_sec = s = bfd_get_section_by_name (htab->elf.dynobj, name);
+  /* See if the section already exists.  */
+  s = bfd_get_section_by_name (htab->elf.dynobj, lsect->name);
   if (s == NULL || (s->flags & flags) != flags)
     {
-      s = bfd_make_section_anyway (htab->elf.dynobj, name);
+      s = bfd_make_section_anyway (htab->elf.dynobj, lsect->name);
       if (s == NULL
 	  || !bfd_set_section_flags (htab->elf.dynobj, s, flags))
-	return NULL;
-      if (sym_sec == NULL)
-	sym_sec = s;
+	return FALSE;
     }
   lsect->section = s;
 
   if (bfd_get_section_alignment (htab->elf.dynobj, s) < 2
       && !bfd_set_section_alignment (htab->elf.dynobj, s, 2))
-    return NULL;
+    return FALSE;
 
   s->size = align_power (s->size, 2);
 
 #ifdef DEBUG
   fprintf (stderr, "Creating section %s, current size = %ld\n",
-	   name, (long) s->size);
+	   lsect->name, (long) s->size);
 #endif
 
-  if (sym_name)
-    {
-      struct elf_link_hash_entry *h;
-      struct bfd_link_hash_entry *bh;
-
-#ifdef DEBUG
-      fprintf (stderr, "Adding %s to section %s\n", sym_name, name);
-#endif
-      bh = bfd_link_hash_lookup (info->hash, sym_name,
-				 FALSE, FALSE, FALSE);
-
-      if ((bh == NULL || bh->type == bfd_link_hash_undefined)
-	  && !(_bfd_generic_link_add_one_symbol
-	       (info, abfd, sym_name, BSF_GLOBAL, sym_sec, sym_offset, NULL,
-		FALSE, get_elf_backend_data (abfd)->collect, &bh)))
-	return NULL;
-      h = (struct elf_link_hash_entry *) bh;
-
-      h->type = STT_OBJECT;
-      lsect->sym_hash = h;
-
-      if (info->shared
-	  && ! bfd_elf_link_record_dynamic_symbol (info, h))
-	return NULL;
-    }
-
-  return lsect;
+  return TRUE;
 }
 
 /* Find a linker generated pointer with a given addend and type.  */
@@ -2675,25 +2615,7 @@ ppc_elf_check_relocs (bfd *abfd,
   if (!ppc_elf_howto_table[R_PPC_ADDR32])
     ppc_elf_howto_init ();
 
-  /* Create the linker generated sections all the time so that the
-     special symbols are created.  */
   htab = ppc_elf_hash_table (info);
-  if (htab->sdata == NULL)
-    {
-      htab->sdata = ppc_elf_create_linker_section (abfd, info,
-						   LINKER_SECTION_SDATA);
-      if (htab->sdata == NULL)
-	return FALSE;
-    }
-
-  if (htab->sdata2 == NULL)
-    {
-      htab->sdata2 = ppc_elf_create_linker_section (abfd, info,
-						    LINKER_SECTION_SDATA2);
-      if (htab->sdata2 == NULL)
-	return FALSE;
-    }
-
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
   sreloc = NULL;
@@ -2793,8 +2715,12 @@ ppc_elf_check_relocs (bfd *abfd,
 	      bad_shared_reloc (abfd, r_type);
 	      return FALSE;
 	    }
+	  if (htab->sdata[0].section == NULL
+	      && !ppc_elf_create_linker_section (abfd, info, 0,
+						 &htab->sdata[0]))
+	    return FALSE;
 	  if (!elf_create_pointer_linker_section (abfd, info,
-						  htab->sdata, h, rel))
+						  &htab->sdata[0], h, rel))
 	    return FALSE;
 	  break;
 
@@ -2805,8 +2731,12 @@ ppc_elf_check_relocs (bfd *abfd,
 	      bad_shared_reloc (abfd, r_type);
 	      return FALSE;
 	    }
+	  if (htab->sdata[1].section == NULL
+	      && !ppc_elf_create_linker_section (abfd, info, SEC_READONLY,
+						 &htab->sdata[1]))
+	    return FALSE;
 	  if (!elf_create_pointer_linker_section (abfd, info,
-						  htab->sdata2, h, rel))
+						  &htab->sdata[1], h, rel))
 	    return FALSE;
 	  break;
 
@@ -3027,6 +2959,8 @@ ppc_elf_check_relocs (bfd *abfd,
 			      && strcmp (bfd_get_section_name (abfd, sec),
 					 name + 5) == 0);
 
+		  if (htab->elf.dynobj == NULL)
+		    htab->elf.dynobj = abfd;
 		  sreloc = bfd_get_section_by_name (htab->elf.dynobj, name);
 		  if (sreloc == NULL)
 		    {
@@ -4129,14 +4058,10 @@ ppc_elf_size_dynamic_sections (bfd *outp
 	  /* Strip this section if we don't need it; see the
 	     comment below.  */
 	}
-      else if ((htab->sdata != NULL && s == htab->sdata->section)
-	       || (htab->sdata2 != NULL && s == htab->sdata2->section))
+      else if (s == htab->sdata[0].section
+	       || s == htab->sdata[1].section)
 	{
-	  if (s->size == 0)
-	    /* Don't strip these sections.  We need them because they
-	       define _SDA_BASE_ and _SDA2_BASE_.  crt1.o makes a
-	       reference to _SDA_BASE_ to set up r13.  */
-	    continue;
+	  /* Strip these too.  */
 	}
       else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0)
 	{
@@ -4638,6 +4572,51 @@ ppc_elf_relax_section (bfd *abfd,
   return FALSE;
 }
 
+/* Set _SDA_BASE_ and _SDA2_BASE.  */
+
+bfd_boolean
+ppc_elf_set_sdata_syms (bfd *obfd, struct bfd_link_info *info)
+{
+  struct ppc_elf_link_hash_table *htab;
+  unsigned i;
+
+  htab = ppc_elf_hash_table (info);
+
+  for (i = 0; i < 2; i++)
+    {
+      elf_linker_section_t *lsect = &htab->sdata[i];
+      asection *s;
+      bfd_vma val;
+      struct elf_link_hash_entry *h;
+
+      s = lsect->section;
+      if (s != NULL)
+	s = s->output_section;
+      if (s == NULL)
+	s = bfd_get_section_by_name (obfd, lsect->name);
+      if (s == NULL)
+	s = bfd_get_section_by_name (obfd, lsect->bss_name);
+
+      val = 0;
+      if (s != NULL)
+	val = s->vma + 32768;
+      lsect->sym_val = val;
+
+      h = elf_link_hash_lookup (&htab->elf, lsect->sym_name,
+				FALSE, FALSE, FALSE);
+      if (h != NULL && h->root.type == bfd_link_hash_undefined)
+	{
+	  h->root.type = bfd_link_hash_defined;
+	  h->root.u.def.section = bfd_abs_section_ptr;
+	  h->root.u.def.value = val;
+	  h->def_regular = 1;
+	  h->type = STT_OBJECT;
+	  h->other = STV_HIDDEN;
+	}
+    }
+  return TRUE;
+}
+
 #define bfd_put_ptr(BFD, VAL, ADDR) bfd_put_32 (BFD, VAL, ADDR)
 
 /* Fill in the address for a pointer generated in a linker section.  */
@@ -4715,7 +4694,7 @@ elf_finish_pointer_linker_section (bfd *
 
   relocation = (lsect->section->output_offset
 		+ linker_section_ptr->offset
-		- lsect->sym_offset);
+		- 0x8000);
 
 #ifdef DEBUG
   fprintf (stderr,
@@ -5598,20 +5579,20 @@ ppc_elf_relocate_section (bfd *output_bf
 
 	  /* Indirect .sdata relocation.  */
 	case R_PPC_EMB_SDAI16:
-	  BFD_ASSERT (htab->sdata != NULL);
+	  BFD_ASSERT (htab->sdata[0].section != NULL);
 	  relocation
 	    = elf_finish_pointer_linker_section (output_bfd, input_bfd, info,
-						 htab->sdata, h, relocation,
-						 rel);
+						 &htab->sdata[0], h,
+						 relocation, rel);
 	  break;
 
 	  /* Indirect .sdata2 relocation.  */
 	case R_PPC_EMB_SDA2I16:
-	  BFD_ASSERT (htab->sdata2 != NULL);
+	  BFD_ASSERT (htab->sdata[1].section != NULL);
 	  relocation
 	    = elf_finish_pointer_linker_section (output_bfd, input_bfd, info,
-						 htab->sdata2, h, relocation,
-						 rel);
+						 &htab->sdata[1], h,
+						 relocation, rel);
 	  break;
 
 	  /* Handle the TOC16 reloc.  We want to use the offset within the .got
@@ -5651,7 +5632,6 @@ ppc_elf_relocate_section (bfd *output_bf
 	case R_PPC_SDAREL16:
 	  {
 	    const char *name;
-	    const struct elf_link_hash_entry *sh;
 
 	    BFD_ASSERT (sec != NULL);
 	    name = bfd_get_section_name (abfd, sec->output_section);
@@ -5668,10 +5648,7 @@ ppc_elf_relocate_section (bfd *output_bf
 		   howto->name,
 		   name);
 	      }
-	    sh = htab->sdata->sym_hash;
-	    addend -= (sh->root.u.def.value
-		       + sh->root.u.def.section->output_section->vma
-		       + sh->root.u.def.section->output_offset);
+	    addend -= htab->sdata[0].sym_val;
 	  }
 	  break;
 
@@ -5679,7 +5656,6 @@ ppc_elf_relocate_section (bfd *output_bf
 	case R_PPC_EMB_SDA2REL:
 	  {
 	    const char *name;
-	    const struct elf_link_hash_entry *sh;
 
 	    BFD_ASSERT (sec != NULL);
 	    name = bfd_get_section_name (abfd, sec->output_section);
@@ -5698,10 +5674,7 @@ ppc_elf_relocate_section (bfd *output_bf
 		ret = FALSE;
 		continue;
 	      }
-	    sh = htab->sdata2->sym_hash;
-	    addend -= (sh->root.u.def.value
-		       + sh->root.u.def.section->output_section->vma
-		       + sh->root.u.def.section->output_offset);
+	    addend -= htab->sdata[1].sym_val;
 	  }
 	  break;
 
@@ -5710,7 +5683,6 @@ ppc_elf_relocate_section (bfd *output_bf
 	case R_PPC_EMB_RELSDA:
 	  {
 	    const char *name;
-	    const struct elf_link_hash_entry *sh;
 	    int reg;
 
 	    BFD_ASSERT (sec != NULL);
@@ -5721,20 +5693,14 @@ ppc_elf_relocate_section (bfd *output_bf
 		     && (name[5] == 0 || name[5] == '.'))))
 	      {
 		reg = 13;
-		sh = htab->sdata->sym_hash;
-		addend -= (sh->root.u.def.value
-			   + sh->root.u.def.section->output_section->vma
-			   + sh->root.u.def.section->output_offset);
+		addend -= htab->sdata[0].sym_val;
 	      }
 
 	    else if (strncmp (name, ".sdata2", 7) == 0
 		     || strncmp (name, ".sbss2", 6) == 0)
 	      {
 		reg = 2;
-		sh = htab->sdata2->sym_hash;
-		addend -= (sh->root.u.def.value
-			   + sh->root.u.def.section->output_section->vma
-			   + sh->root.u.def.section->output_offset);
+		addend -= htab->sdata[1].sym_val;
 	      }
 
 	    else if (strcmp (name, ".PPC.EMB.sdata0") == 0
Index: bfd/elf32-ppc.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.h,v
retrieving revision 1.3
diff -u -p -r1.3 elf32-ppc.h
--- bfd/elf32-ppc.h	4 Nov 2003 06:16:36 -0000	1.3
+++ bfd/elf32-ppc.h	21 Mar 2005 00:33:48 -0000
@@ -1,5 +1,5 @@
 /* PowerPC-specific support for 64-bit ELF.
-   Copyright 2003 Free Software Foundation, Inc.
+   Copyright 2003, 2005 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -19,3 +19,4 @@ Foundation, Inc., 59 Temple Place - Suit
 
 asection *ppc_elf_tls_setup (bfd *, struct bfd_link_info *);
 bfd_boolean ppc_elf_tls_optimize (bfd *, struct bfd_link_info *);
+bfd_boolean ppc_elf_set_sdata_syms (bfd *, struct bfd_link_info *);
Index: ld/emultempl/ppc32elf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/ppc32elf.em,v
retrieving revision 1.3
diff -u -p -r1.3 ppc32elf.em
--- ld/emultempl/ppc32elf.em	24 Jun 2003 14:04:29 -0000	1.3
+++ ld/emultempl/ppc32elf.em	21 Mar 2005 00:34:12 -0000
@@ -1,5 +1,5 @@
 # This shell script emits a C file. -*- C -*-
-#   Copyright 2003 Free Software Foundation, Inc.
+#   Copyright 2003, 2005 Free Software Foundation, Inc.
 #
 # This file is part of GLD, the Gnu Linker.
 #
@@ -26,15 +26,15 @@ cat >>e${EMULATION_NAME}.c <<EOF
 #include "libbfd.h"
 #include "elf32-ppc.h"
 
+extern const bfd_target bfd_elf32_powerpc_vec;
+extern const bfd_target bfd_elf32_powerpcle_vec;
+
 /* Whether to run tls optimization.  */
 static int notlsopt = 0;
 
 static void
 ppc_before_allocation (void)
 {
-  extern const bfd_target bfd_elf32_powerpc_vec;
-  extern const bfd_target bfd_elf32_powerpcle_vec;
-
   if (link_info.hash->creator == &bfd_elf32_powerpc_vec
       || link_info.hash->creator == &bfd_elf32_powerpcle_vec)
     {
@@ -50,6 +50,17 @@ ppc_before_allocation (void)
   gld${EMULATION_NAME}_before_allocation ();
 }
 
+static void
+gld${EMULATION_NAME}_after_allocation (void)
+{
+  if (link_info.hash->creator == &bfd_elf32_powerpc_vec
+      || link_info.hash->creator == &bfd_elf32_powerpcle_vec)
+    {
+      if (!ppc_elf_set_sdata_syms (output_bfd, &link_info))
+	einfo ("%X%P: cannot set sdata syms %E\n");
+    }
+}
+
 EOF
 
 # Define some shell vars to insert bits of code into the standard elf
@@ -78,3 +89,4 @@ PARSE_AND_LIST_ARGS_CASES='
 # Put these extra ppc64elf routines in ld_${EMULATION_NAME}_emulation
 #
 LDEMUL_BEFORE_ALLOCATION=ppc_before_allocation
+LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre



More information about the Binutils mailing list