Move bfd *_pointer_linker_section into elf32-ppc.c

Alan Modra amodra@bigpond.net.au
Mon Jul 7 15:58:00 GMT 2003


This moves the "linker_section_pointer" field out of elf_link_hash_entry
and into ppc_elf_link_hash_entry.  I've also ripped out unused code and
struct fields in the process of cleaning up this area.

One thing of note is that I've removed a hack Ian added here:

Mon Sep 23 13:33:00 1996  Ian Lance Taylor  <ian@cygnus.com>

	* elf32-ppc.c (ppc_elf_add_symbol_hook): Create the .sbss section
	by hand, rather than by calling bfd_make_section.

Why this was needed, I don't know.  The idea seemed to be to create a
section that wasn't found when traversing a bfd's sections, and plunk
the small common syms in the specially unhooked section.  The syms don't
_stay_ in the section, since when _bfd_generic_link_add_one_symbol is
called a few microseconds after add_symbol_hook returns, case COM checks
that the common section belongs to the bfd, and if not, creates a section
anyway.

	* elf-bfd.h (struct elf_link_hash_entry): Remove linker_section_pointer
	field.
	(enum elf_linker_section_enum): Delete.
	(struct elf_linker_section): Delete.
	(struct elf_linker_section_pointers): Delete.
	(struct elf_obj_tdata): Remove #if 0 chunk.  Remove linker_section.
	Make linker_section_pointers a void**.
	(elf_local_ptr_offsets, elf_linker_section): Don't define.
	* elf32-ppc.c (enum elf_linker_section_enum): New, cut-down version
	of old item in elf-bfd.h.
	(struct elf_linker_section): Likewise.
	(struct elf_linker_section_pointers): Likewise.
	(elf_local_ptr_offsets): Define.
	(struct ppc_elf_link_hash_entry): Add linker_section_pointer.
	(ppc_elf_link_hash_newfunc): Init it.
	(struct ppc_elf_link_hash_table): Add sbss.
	(ppc_elf_link_hash_table_create): zmalloc rather than clearing
	individual fields.
	(elf_create_linker_section): Fold into..
	(ppc_elf_create_linker_section): ..here.  Remove hole_size code.
	Make rela section here if shared.
	(elf_find_pointer_linker_section): Pass lsect rather than enum.
	(elf_create_pointer_linker_section): Adjust.  zalloc rather than
	clearing in a loop.
	(elf_finish_pointer_linker_section): Adjust.  Don't make rela
	section here.
	(ppc_elf_check_relocs): Adjust.
	(ppc_elf_add_symbol_hook): Tighten hash creator test.  Remove code
	creating .sbss by hand.
	* elf.c (_bfd_elf_link_hash_newfunc): Adjust.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.101
diff -u -p -r1.101 elf-bfd.h
--- bfd/elf-bfd.h	4 Jul 2003 13:57:14 -0000	1.101
+++ bfd/elf-bfd.h	7 Jul 2003 06:28:21 -0000
@@ -118,11 +118,6 @@ struct elf_link_hash_entry
      one.  Otherwise it is NULL.  */
   struct elf_link_hash_entry *weakdef;
 
-  /* If this symbol is used in the linker created sections, the processor
-     specific backend uses this field to map the field into the offset
-     from the beginning of the section.  */
-  struct elf_linker_section_pointers *linker_section_pointer;
-
   /* Version information.  */
   union
   {
@@ -1036,52 +1031,6 @@ struct bfd_elf_section_data
 #define get_elf_backend_data(abfd) \
   ((struct elf_backend_data *) (abfd)->xvec->backend_data)
 
-/* Enumeration to specify the special section.  */
-typedef enum elf_linker_section_enum
-{
-  LINKER_SECTION_UNKNOWN,		/* not used */
-  LINKER_SECTION_GOT,			/* .got section for global offset pointers */
-  LINKER_SECTION_PLT,			/* .plt section for generated procedure stubs */
-  LINKER_SECTION_SDATA,			/* .sdata/.sbss section for PowerPC */
-  LINKER_SECTION_SDATA2,		/* .sdata2/.sbss2 section for PowerPC */
-  LINKER_SECTION_MAX			/* # of linker sections */
-} elf_linker_section_enum_t;
-
-/* Sections created by the linker.  */
-
-typedef struct elf_linker_section
-{
-  char *name;				/* name of the section */
-  char *rel_name;			/* name of the associated .rel{,a}. section */
-  char *bss_name;			/* name of a related .bss section */
-  char *sym_name;			/* name of symbol to reference this section */
-  asection *section;			/* pointer to the section */
-  asection *bss_section;		/* pointer to the bss section associated with this */
-  asection *rel_section;		/* pointer to the relocations needed for this section */
-  struct elf_link_hash_entry *sym_hash;	/* pointer to the created symbol hash value */
-  bfd_vma initial_size;			/* initial size before any linker generated allocations */
-  bfd_vma sym_offset;			/* offset of symbol from beginning of section */
-  bfd_vma hole_size;			/* size of reserved address hole in allocation */
-  bfd_vma hole_offset;			/* current offset for the hole */
-  bfd_vma max_hole_offset;		/* maximum offset for the hole */
-  elf_linker_section_enum_t which;	/* which section this is */
-  bfd_boolean hole_written_p;		/* whether the hole has been initialized */
-  unsigned int alignment;		/* alignment for the section */
-  flagword flags;			/* flags to use to create the section */
-} elf_linker_section_t;
-
-/* Linked list of allocated pointer entries.  This hangs off of the symbol lists, and
-   provides allows us to return different pointers, based on different addend's.  */
-
-typedef struct elf_linker_section_pointers
-{
-  struct elf_linker_section_pointers *next;	/* next allocated pointer for this symbol */
-  bfd_vma offset;				/* offset of pointer from beginning of section */
-  bfd_vma addend;				/* addend used */
-  elf_linker_section_enum_t which;		/* which linker section this is */
-  bfd_boolean written_address_p;		/* whether address was written yet */
-} elf_linker_section_pointers_t;
-
 /* This struct is used to pass information to routines called via
    elf_link_hash_traverse which must return failure.  */
 
@@ -1151,12 +1100,6 @@ struct elf_obj_tdata
   unsigned int symtab_shndx_section;
   unsigned int dynversym_section, dynverdef_section, dynverref_section;
   file_ptr next_file_pos;
-#if 0
-  /* we don't need these inside bfd anymore, and I think
-     these weren't used outside bfd.  */
-  void *prstatus;			/* The raw /proc prstatus structure */
-  void *prpsinfo;			/* The raw /proc prpsinfo structure */
-#endif
   bfd_vma gp;				/* The gp value */
   unsigned int gp_size;			/* The gp size */
 
@@ -1189,10 +1132,6 @@ struct elf_obj_tdata
       struct got_entry **ents;
     } local_got;
 
-  /* A mapping from local symbols to offsets into the various linker
-     sections added.  This is index by the symbol index.  */
-  elf_linker_section_pointers_t **linker_section_pointers;
-
   /* The linker ELF emulation code needs to let the backend ELF linker
      know what filename should be used for a dynamic object if the
      dynamic object is found using a search.  The emulation code then
@@ -1263,8 +1202,9 @@ struct elf_obj_tdata
   /* Symbol version references to external objects.  */
   Elf_Internal_Verneed *verref;
 
-  /* Linker sections that we are interested in.  */
-  struct elf_linker_section *linker_section[ (int)LINKER_SECTION_MAX ];
+  /* A mapping from local symbols to offsets into the various linker
+     sections added.  This is index by the symbol index.  */
+  void **linker_section_pointers;
 
   /* The Irix 5 support uses two virtual sections, which represent
      text/data symbols defined in dynamic objects.  */
@@ -1297,12 +1237,10 @@ struct elf_obj_tdata
 #define elf_local_got_refcounts(bfd) (elf_tdata(bfd) -> local_got.refcounts)
 #define elf_local_got_offsets(bfd) (elf_tdata(bfd) -> local_got.offsets)
 #define elf_local_got_ents(bfd) (elf_tdata(bfd) -> local_got.ents)
-#define elf_local_ptr_offsets(bfd) (elf_tdata(bfd) -> linker_section_pointers)
 #define elf_dt_name(bfd)	(elf_tdata(bfd) -> dt_name)
 #define elf_dt_soname(bfd)	(elf_tdata(bfd) -> dt_soname)
 #define elf_bad_symtab(bfd)	(elf_tdata(bfd) -> bad_symtab)
 #define elf_flags_init(bfd)	(elf_tdata(bfd) -> flags_init)
-#define elf_linker_section(bfd,n) (elf_tdata(bfd) -> linker_section[(int)n])
 
 extern void _bfd_elf_swap_verdef_in
   PARAMS ((bfd *, const Elf_External_Verdef *, Elf_Internal_Verdef *));
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.190
diff -u -p -r1.190 elf.c
--- bfd/elf.c	25 Jun 2003 06:40:19 -0000	1.190
+++ bfd/elf.c	7 Jul 2003 06:28:23 -0000
@@ -1428,7 +1428,6 @@ _bfd_elf_link_hash_newfunc (entry, table
       ret->dynstr_index = 0;
       ret->elf_hash_value = 0;
       ret->weakdef = NULL;
-      ret->linker_section_pointer = NULL;
       ret->verinfo.verdef = NULL;
       ret->vtable_entries_size = 0;
       ret->vtable_entries_used = NULL;
Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.90
diff -u -p -r1.90 elf32-ppc.c
--- bfd/elf32-ppc.c	4 Jul 2003 13:53:37 -0000	1.90
+++ bfd/elf32-ppc.c	7 Jul 2003 15:43:57 -0000
@@ -70,6 +70,49 @@ static bfd_reloc_status_type ppc_elf_unh
 #define DTP_OFFSET	0x8000
 
 
+/* Enumeration to specify the special section.  */
+enum elf_linker_section_enum
+{
+  LINKER_SECTION_SDATA,
+  LINKER_SECTION_SDATA2
+};
+
+/* Sections created by the linker.  */
+
+typedef struct elf_linker_section
+{
+  /* pointer to the section */
+  asection *section;
+  /* pointer to the relocations needed for this section */
+  asection *rel_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;
+} elf_linker_section_t;
+
+/* Linked list of allocated pointer entries.  This hangs off of the
+   symbol lists, and provides allows us to return different pointers,
+   based on different addend's.  */
+
+typedef struct elf_linker_section_pointers
+{
+  /* next allocated pointer for this symbol */
+  struct elf_linker_section_pointers *next;
+  /* offset of pointer from beginning of section */
+  bfd_vma offset;
+  /* addend used */
+  bfd_vma addend;
+  /* which linker section this is */
+  elf_linker_section_t *lsect;
+  /* whether address was written yet */
+  bfd_boolean written_address_p;
+} elf_linker_section_pointers_t;
+
+#define elf_local_ptr_offsets(bfd) \
+  ((elf_linker_section_pointers_t **) \
+   (elf_tdata (bfd)->linker_section_pointers))
+
 /* The PPC linker needs to keep track of the number of relocs that it
    decides to copy as dynamic relocs in check_relocs for each symbol.
    This is so that it can later discard them if they are found to be
@@ -96,6 +139,11 @@ struct ppc_elf_link_hash_entry
 {
   struct elf_link_hash_entry elf;
 
+  /* If this symbol is used in the linker created sections, the processor
+     specific backend uses this field to map the field into the offset
+     from the beginning of the section.  */
+  elf_linker_section_pointers_t *linker_section_pointer;
+
   /* Track dynamic relocs copied for this symbol.  */
   struct ppc_elf_dyn_relocs *dyn_relocs;
 
@@ -132,6 +180,7 @@ struct ppc_elf_link_hash_table
   asection *relsbss;
   elf_linker_section_t *sdata;
   elf_linker_section_t *sdata2;
+  asection *sbss;
 
   /* Short-cut to first output tls section.  */
   asection *tls_sec;
@@ -175,6 +224,7 @@ ppc_elf_link_hash_newfunc (struct bfd_ha
   entry = _bfd_elf_link_hash_newfunc (entry, table, string);
   if (entry != NULL)
     {
+      ppc_elf_hash_entry (entry)->linker_section_pointer = NULL;
       ppc_elf_hash_entry (entry)->dyn_relocs = NULL;
       ppc_elf_hash_entry (entry)->tls_mask = 0;
     }
@@ -189,7 +239,7 @@ ppc_elf_link_hash_table_create (bfd *abf
 {
   struct ppc_elf_link_hash_table *ret;
 
-  ret = bfd_malloc (sizeof (struct ppc_elf_link_hash_table));
+  ret = bfd_zmalloc (sizeof (struct ppc_elf_link_hash_table));
   if (ret == NULL)
     return NULL;
 
@@ -200,21 +250,6 @@ ppc_elf_link_hash_table_create (bfd *abf
       return NULL;
     }
 
-  ret->got = NULL;
-  ret->relgot = NULL;
-  ret->plt = NULL;
-  ret->relplt = NULL;
-  ret->dynbss = NULL;
-  ret->relbss = NULL;
-  ret->dynsbss = NULL;
-  ret->relsbss = NULL;
-  ret->sdata = NULL;
-  ret->sdata2 = NULL;
-  ret->tls_sec = NULL;
-  ret->tls_get_addr = NULL;
-  ret->tlsld_got.refcount = 0;
-  ret->sym_sec.abfd = NULL;
-
   return &ret->elf.root;
 }
 
@@ -2169,127 +2204,16 @@ ppc_elf_fake_sections (bfd *abfd ATTRIBU
   return TRUE;
 }
 
-/* Create a special linker section, or return a pointer to a linker
-   section already created */
-
-static elf_linker_section_t *
-elf_create_linker_section (bfd *abfd,
-			   struct bfd_link_info *info,
-			   enum elf_linker_section_enum which,
-			   elf_linker_section_t *defaults)
-{
-  bfd *dynobj = elf_hash_table (info)->dynobj;
-  elf_linker_section_t *lsect;
-
-  /* Record the first bfd section that needs the special section */
-  if (!dynobj)
-    dynobj = elf_hash_table (info)->dynobj = abfd;
-
-  /* If this is the first time, create the section */
-  lsect = elf_linker_section (dynobj, which);
-  if (!lsect)
-    {
-      asection *s;
-      bfd_size_type amt = sizeof (elf_linker_section_t);
-
-      lsect = bfd_alloc (dynobj, amt);
-
-      *lsect = *defaults;
-      elf_linker_section (dynobj, which) = lsect;
-      lsect->which = which;
-      lsect->hole_written_p = FALSE;
-
-      /* See if the sections already exist */
-      lsect->section = s = bfd_get_section_by_name (dynobj, lsect->name);
-      if (!s || (s->flags & defaults->flags) != defaults->flags)
-	{
-	  lsect->section = s = bfd_make_section_anyway (dynobj, lsect->name);
-
-	  if (s == NULL)
-	    return NULL;
-
-	  bfd_set_section_flags (dynobj, s, defaults->flags);
-	  bfd_set_section_alignment (dynobj, s, lsect->alignment);
-	}
-      else if (bfd_get_section_alignment (dynobj, s) < lsect->alignment)
-	bfd_set_section_alignment (dynobj, s, lsect->alignment);
-
-      s->_raw_size = align_power (s->_raw_size, lsect->alignment);
-
-      /* Is there a hole we have to provide?  If so check whether the
-	 segment is too big already */
-      if (lsect->hole_size)
-	{
-	  lsect->hole_offset = s->_raw_size;
-	  s->_raw_size += lsect->hole_size;
-	  if (lsect->hole_offset > lsect->max_hole_offset)
-	    {
-	      (*_bfd_error_handler)
-		(_("%s: Section %s is too large to add hole of %ld bytes"),
-		 bfd_get_filename (abfd),
-		 lsect->name,
-		 (long) lsect->hole_size);
-
-	      bfd_set_error (bfd_error_bad_value);
-	      return NULL;
-	    }
-	}
-
-#ifdef DEBUG
-      fprintf (stderr, "Creating section %s, current size = %ld\n",
-	       lsect->name, (long) s->_raw_size);
-#endif
-
-      if (lsect->sym_name)
-	{
-	  struct elf_link_hash_entry *h;
-	  struct bfd_link_hash_entry *bh;
-
-#ifdef DEBUG
-	  fprintf (stderr, "Adding %s to section %s\n",
-		   lsect->sym_name,
-		   lsect->name);
-#endif
-	  bh = bfd_link_hash_lookup (info->hash, lsect->sym_name,
-				     FALSE, FALSE, FALSE);
-
-	  if ((bh == NULL || bh->type == bfd_link_hash_undefined)
-	      && !(_bfd_generic_link_add_one_symbol
-		   (info, abfd, lsect->sym_name, BSF_GLOBAL, s,
-		    (lsect->hole_size
-		     ? s->_raw_size - lsect->hole_size + lsect->sym_offset
-		     : lsect->sym_offset),
-		    NULL, FALSE,
-		    get_elf_backend_data (abfd)->collect, &bh)))
-	    return NULL;
-	  h = (struct elf_link_hash_entry *) bh;
-
-	  if ((defaults->which != LINKER_SECTION_SDATA)
-	      && (defaults->which != LINKER_SECTION_SDATA2))
-	    h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_DYNAMIC;
-
-	  h->type = STT_OBJECT;
-	  lsect->sym_hash = h;
-
-	  if (info->shared
-	      && ! _bfd_elf_link_record_dynamic_symbol (info, h))
-	    return NULL;
-	}
-    }
-
-  return lsect;
-}
-
 /* Find a linker generated pointer with a given addend and type.  */
 
 static elf_linker_section_pointers_t *
 elf_find_pointer_linker_section
   (elf_linker_section_pointers_t *linker_pointers,
    bfd_vma addend,
-   elf_linker_section_enum_t which)
+   elf_linker_section_t *lsect)
 {
   for ( ; linker_pointers != NULL; linker_pointers = linker_pointers->next)
-    if (which == linker_pointers->which && addend == linker_pointers->addend)
+    if (lsect == linker_pointers->lsect && addend == linker_pointers->addend)
       return linker_pointers;
 
   return NULL;
@@ -2314,13 +2238,16 @@ elf_create_pointer_linker_section (bfd *
   /* Is this a global symbol?  */
   if (h != NULL)
     {
+      struct ppc_elf_link_hash_entry *eh;
+
       /* Has this symbol already been allocated?  If so, our work is done.  */
-      if (elf_find_pointer_linker_section (h->linker_section_pointer,
+      eh = (struct ppc_elf_link_hash_entry *) h;
+      if (elf_find_pointer_linker_section (eh->linker_section_pointer,
 					   rel->r_addend,
-					   lsect->which))
+					   lsect))
 	return TRUE;
 
-      ptr_linker_section_ptr = &h->linker_section_pointer;
+      ptr_linker_section_ptr = &eh->linker_section_pointer;
       /* Make sure this symbol is output as a dynamic symbol.  */
       if (h->dynindx == -1)
 	{
@@ -2340,24 +2267,21 @@ elf_create_pointer_linker_section (bfd *
       if (!ptr)
 	{
 	  unsigned int num_symbols = elf_tdata (abfd)->symtab_hdr.sh_info;
-	  register unsigned int i;
 
 	  amt = num_symbols;
 	  amt *= sizeof (elf_linker_section_pointers_t *);
-	  ptr = bfd_alloc (abfd, amt);
+	  ptr = bfd_zalloc (abfd, amt);
 
 	  if (!ptr)
 	    return FALSE;
 
 	  elf_local_ptr_offsets (abfd) = ptr;
-	  for (i = 0; i < num_symbols; i++)
-	    ptr[i] = NULL;
 	}
 
       /* Has this symbol already been allocated?  If so, our work is done.  */
       if (elf_find_pointer_linker_section (ptr[r_symndx],
 					   rel->r_addend,
-					   lsect->which))
+					   lsect))
 	return TRUE;
 
       ptr_linker_section_ptr = &ptr[r_symndx];
@@ -2383,7 +2307,7 @@ elf_create_pointer_linker_section (bfd *
 
   linker_section_ptr->next = *ptr_linker_section_ptr;
   linker_section_ptr->addend = rel->r_addend;
-  linker_section_ptr->which = lsect->which;
+  linker_section_ptr->lsect = lsect;
   linker_section_ptr->written_address_p = FALSE;
   *ptr_linker_section_ptr = linker_section_ptr;
 
@@ -2421,10 +2345,13 @@ elf_finish_pointer_linker_section (bfd *
   if (h != NULL)
     {
       /* Handle global symbol.  */
+      struct ppc_elf_link_hash_entry *eh;
+
+      eh = (struct ppc_elf_link_hash_entry *) h;
       linker_section_ptr
-	= elf_find_pointer_linker_section (h->linker_section_pointer,
+	= elf_find_pointer_linker_section (eh->linker_section_pointer,
 					   rel->r_addend,
-					   lsect->which);
+					   lsect);
 
       BFD_ASSERT (linker_section_ptr != NULL);
 
@@ -2460,7 +2387,7 @@ elf_finish_pointer_linker_section (bfd *
       linker_section_ptr = (elf_find_pointer_linker_section
 			    (elf_local_ptr_offsets (input_bfd)[r_symndx],
 			     rel->r_addend,
-			     lsect->which));
+			     lsect));
 
       BFD_ASSERT (linker_section_ptr != NULL);
 
@@ -2473,21 +2400,15 @@ elf_finish_pointer_linker_section (bfd *
 
 	  if (info->shared)
 	    {
+	      /* We need to generate a relative reloc for the dynamic
+		 linker.  */
+
 	      asection *srel = lsect->rel_section;
 	      Elf_Internal_Rela outrel[MAX_INT_RELS_PER_EXT_REL];
 	      bfd_byte *erel;
 	      struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
 	      unsigned int i;
 
-	      /* We need to generate a relative reloc for the dynamic
-		 linker.  */
-	      if (!srel)
-		{
-		  srel = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
-						  lsect->rel_name);
-		  lsect->rel_section = srel;
-		}
-
 	      BFD_ASSERT (srel != NULL);
 
 	      for (i = 0; i < bed->s->int_rels_per_ext_rel; i++)
@@ -2509,7 +2430,6 @@ elf_finish_pointer_linker_section (bfd *
 
   relocation = (lsect->section->output_offset
 		+ linker_section_ptr->offset
-		- lsect->hole_offset
 		- lsect->sym_offset);
 
 #ifdef DEBUG
@@ -2529,65 +2449,114 @@ ppc_elf_create_linker_section (bfd *abfd
 			       struct bfd_link_info *info,
 			       enum elf_linker_section_enum which)
 {
-  bfd *dynobj = elf_hash_table (info)->dynobj;
   elf_linker_section_t *lsect;
+  struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
+  asection *s;
+  bfd_size_type amt;
+  flagword flags;
+  const char *name;
+  const char *rel_name;
+  const char *sym_name;
+  bfd_vma sym_offset;
+
+  /* Both of these sections are (technically) created by the user
+     putting data in them, so they shouldn't be marked
+     SEC_LINKER_CREATED.
+
+     The linker creates them so it has somewhere to attach their
+     respective symbols. In fact, if they were empty it would
+     be OK to leave the symbol set to 0 (or any random number), because
+     the appropriate register should never be used.  */
+  flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+  sym_offset = 32768;
+
+  switch (which)
+    {
+    default:
+      abort ();
+      return NULL;
 
-  /* Record the first bfd section that needs the special section.  */
-  if (!dynobj)
-    dynobj = elf_hash_table (info)->dynobj = abfd;
-
-  /* If this is the first time, create the section.  */
-  lsect = elf_linker_section (dynobj, which);
-  if (!lsect)
-    {
-      elf_linker_section_t defaults;
-      static elf_linker_section_t zero_section;
-
-      defaults = zero_section;
-      defaults.which = which;
-      defaults.hole_written_p = FALSE;
-      defaults.alignment = 2;
-
-      /* Both of these sections are (technically) created by the user
-	 putting data in them, so they shouldn't be marked
-	 SEC_LINKER_CREATED.
-
-	 The linker creates them so it has somewhere to attach their
-	 respective symbols. In fact, if they were empty it would
-	 be OK to leave the symbol set to 0 (or any random number), because
-	 the appropriate register should never be used.  */
-      defaults.flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
-			| SEC_IN_MEMORY);
+    case LINKER_SECTION_SDATA:	/* .sdata/.sbss section */
+      name	= ".sdata";
+      rel_name	= ".rela.sdata";
+      sym_name	= "_SDA_BASE_";
+      break;
 
-      switch (which)
-	{
-	default:
-	  (*_bfd_error_handler) (_("%s: unknown special linker type %d"),
-				 bfd_get_filename (abfd),
-				 (int) which);
+    case LINKER_SECTION_SDATA2:	/* .sdata2/.sbss2 section */
+      name	= ".sdata2";
+      rel_name	= ".rela.sdata2";
+      sym_name	= "_SDA2_BASE_";
+      flags    |= SEC_READONLY;
+      break;
+    }
 
-	  bfd_set_error (bfd_error_bad_value);
-	  return NULL;
+  /* Record the first bfd that needs the special sections.  */
+  if (!htab->elf.dynobj)
+    htab->elf.dynobj = abfd;
 
-	case LINKER_SECTION_SDATA:	/* .sdata/.sbss section */
-	  defaults.name		  = ".sdata";
-	  defaults.rel_name	  = ".rela.sdata";
-	  defaults.bss_name	  = ".sbss";
-	  defaults.sym_name	  = "_SDA_BASE_";
-	  defaults.sym_offset	  = 32768;
-	  break;
+  amt = sizeof (elf_linker_section_t);
+  lsect = bfd_zalloc (htab->elf.dynobj, amt);
 
-	case LINKER_SECTION_SDATA2:	/* .sdata2/.sbss2 section */
-	  defaults.name		  = ".sdata2";
-	  defaults.rel_name	  = ".rela.sdata2";
-	  defaults.bss_name	  = ".sbss2";
-	  defaults.sym_name	  = "_SDA2_BASE_";
-	  defaults.sym_offset	  = 32768;
-	  defaults.flags	 |= SEC_READONLY;
-	  break;
-	}
+  lsect->sym_offset = sym_offset;
 
-      lsect = elf_create_linker_section (abfd, info, which, &defaults);
+  /* See if the sections already exist.  */
+  s = bfd_get_section_by_name (htab->elf.dynobj, name);
+  if (s == NULL || (s->flags & flags) != flags)
+    {
+      s = bfd_make_section_anyway (htab->elf.dynobj, name);
+      if (s == NULL
+	  || !bfd_set_section_flags (htab->elf.dynobj, s, flags))
+	return NULL;
+    }
+  lsect->section = s;
+
+  if (bfd_get_section_alignment (htab->elf.dynobj, s) < 2
+      && !bfd_set_section_alignment (htab->elf.dynobj, s, 2))
+    return NULL;
+
+  s->_raw_size = align_power (s->_raw_size, 2);
+
+#ifdef DEBUG
+  fprintf (stderr, "Creating section %s, current size = %ld\n",
+	   name, (long) s->_raw_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, s, 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;
+    }
+
+  if (info->shared)
+    {
+      s = bfd_make_section_anyway (htab->elf.dynobj, rel_name);
+      lsect->rel_section = s;
+      flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+	       | SEC_LINKER_CREATED | SEC_READONLY);
+      if (s == NULL
+	  || ! bfd_set_section_flags (htab->elf.dynobj, s, flags)
+	  || ! bfd_set_section_alignment (htab->elf.dynobj, s, 2))
+	return NULL;
     }
 
   return lsect;
@@ -3459,20 +3428,16 @@ ppc_elf_check_relocs (bfd *abfd,
   htab = ppc_elf_hash_table (info);
   if (htab->sdata == NULL)
     {
-      htab->sdata = elf_linker_section (abfd, LINKER_SECTION_SDATA);
-      if (htab->sdata == NULL)
-	htab->sdata = ppc_elf_create_linker_section (abfd, info,
-						     LINKER_SECTION_SDATA);
+      htab->sdata = ppc_elf_create_linker_section (abfd, info,
+						   LINKER_SECTION_SDATA);
       if (htab->sdata == NULL)
 	return FALSE;
     }
 
   if (htab->sdata2 == NULL)
     {
-      htab->sdata2 = elf_linker_section (abfd, LINKER_SECTION_SDATA2);
-      if (htab->sdata2 == NULL)
-	htab->sdata2 = ppc_elf_create_linker_section (abfd, info,
-						      LINKER_SECTION_SDATA2);
+      htab->sdata2 = ppc_elf_create_linker_section (abfd, info,
+						    LINKER_SECTION_SDATA2);
       if (htab->sdata2 == NULL)
 	return FALSE;
     }
@@ -4272,42 +4237,25 @@ ppc_elf_add_symbol_hook (bfd *abfd,
   if (sym->st_shndx == SHN_COMMON
       && !info->relocatable
       && sym->st_size <= elf_gp_size (abfd)
-      && info->hash->creator->flavour == bfd_target_elf_flavour)
+      && (info->hash->creator == abfd->xvec
+	  || info->hash->creator == abfd->xvec->alternative_target))
     {
       /* Common symbols less than or equal to -G nn bytes are automatically
-	 put into .sdata.  */
-      elf_linker_section_t *sdata
-	= ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA);
+	 put into .sbss.  */
+      struct ppc_elf_link_hash_table *htab;
 
-      if (!sdata->bss_section)
+      htab = ppc_elf_hash_table (info);
+      if (htab->sbss == NULL)
 	{
-	  bfd_size_type amt;
+	  flagword flags = SEC_IS_COMMON;
 
-	  /* We don't go through bfd_make_section, because we don't
-	     want to attach this common section to DYNOBJ.  The linker
-	     will move the symbols to the appropriate output section
-	     when it defines common symbols.  */
-	  amt = sizeof (asection);
-	  sdata->bss_section = bfd_zalloc (abfd, amt);
-	  if (sdata->bss_section == NULL)
-	    return FALSE;
-	  sdata->bss_section->name = sdata->bss_name;
-	  sdata->bss_section->flags = SEC_IS_COMMON;
-	  sdata->bss_section->output_section = sdata->bss_section;
-	  amt = sizeof (asymbol);
-	  sdata->bss_section->symbol = bfd_zalloc (abfd, amt);
-	  amt = sizeof (asymbol *);
-	  sdata->bss_section->symbol_ptr_ptr = bfd_zalloc (abfd, amt);
-	  if (sdata->bss_section->symbol == NULL
-	      || sdata->bss_section->symbol_ptr_ptr == NULL)
+	  htab->sbss = bfd_make_section_anyway (abfd, ".sbss");
+	  if (htab->sbss == NULL
+	      || ! bfd_set_section_flags (abfd, htab->sbss, flags))
 	    return FALSE;
-	  sdata->bss_section->symbol->name = sdata->bss_name;
-	  sdata->bss_section->symbol->flags = BSF_SECTION_SYM;
-	  sdata->bss_section->symbol->section = sdata->bss_section;
-	  *sdata->bss_section->symbol_ptr_ptr = sdata->bss_section->symbol;
 	}
 
-      *secp = sdata->bss_section;
+      *secp = htab->sbss;
       *valp = sym->st_size;
     }
 

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre



More information about the Binutils mailing list