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]

ppc64 section group handling


Two organizational changes to the array of additional info kept for
sections.
1) Move group info into a per-group allocated struct, in preparation
for future changes that need per-group accounting.
2) Expand the array to include output sections, which simplifies
sizing and removes the need for a separate output section array.

	* section.c (section_id): Make file scope.
	(bfd_get_next_section_id): New function.
	* elf64-ppc.c (struct map_stub): Remove toc_off field.  Move decl.
	(struct ppc_stub_hash_entry): Delete stub_sec and id_sec.  Add
	group.  Update all uses.
	(struct ppc_link_hash_table): Delete top_id, top_index, and
	input_list.  Add sec_info_arr_size.  Rename stub_group to
	sec_info, and make group info indirect.  Update stub_group refs
	throughout file.
	(ppc_add_stub): Don't look for stub_sec on link_sec stub_group
	entry.
	(ppc_build_one_stub): Delete FIXME.
	(ppc64_elf_setup_section_lists): Size htab->sec_info for all
	sections, not just input sections.  Don't create htab->input_list.
	(ppc64_elf_next_input_section): Update to use sec_info union as
	list pointer.
	(PREV_SEC): Delete.
	(group_sections): Pass "info" param rather than "htab".  Iterate
	over output sections rather than input_list.  Use sec_info union
	as list pointers.  Alloc atruct map_stub, and return fail status.
	* bfd-in2.h: Regenerate.

diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 4a232b7..efa124e 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -3799,6 +3799,15 @@ enum ppc_stub_type {
   ppc_stub_global_entry
 };
 
+/* Information on stub grouping.  */
+struct map_stub
+{
+  /* The stub section.  */
+  asection *stub_sec;
+  /* This is the section to which stubs in the group will be attached.  */
+  asection *link_sec;
+};
+
 struct ppc_stub_hash_entry {
 
   /* Base hash table entry structure.  */
@@ -3806,8 +3815,8 @@ struct ppc_stub_hash_entry {
 
   enum ppc_stub_type stub_type;
 
-  /* The stub section.  */
-  asection *stub_sec;
+  /* Group information.  */
+  struct map_stub *group;
 
   /* Offset within stub_sec of the beginning of this stub.  */
   bfd_vma stub_offset;
@@ -3821,10 +3830,6 @@ struct ppc_stub_hash_entry {
   struct ppc_link_hash_entry *h;
   struct plt_entry *plt_ent;
 
-  /* Where this stub is being called from, or, in the case of combined
-     stub sections, the first input section in the group.  */
-  asection *id_sec;
-
   /* Symbol st_other.  */
   unsigned char other;
 };
@@ -3925,34 +3930,34 @@ struct ppc_link_hash_table
   /* Various options and other info passed from the linker.  */
   struct ppc64_elf_params *params;
 
-  /* Array to keep track of which stub sections have been created, and
-     information on stub grouping.  */
-  struct map_stub {
-    /* This is the section to which stubs in the group will be attached.  */
-    asection *link_sec;
-    /* The stub section.  */
-    asection *stub_sec;
-    /* Along with elf_gp, specifies the TOC pointer used in this group.  */
+  /* The size of sec_info below.  */
+  unsigned int sec_info_arr_size;
+
+  /* Per-section array of extra section info.  Done this way rather
+     than as part of ppc64_elf_section_data so we have the info for
+     non-ppc64 sections.  */
+  struct
+  {
+    /* Along with elf_gp, specifies the TOC pointer used by this section.  */
     bfd_vma toc_off;
-  } *stub_group;
+
+    union
+    {
+      /* The section group that this section belongs to.  */
+      struct map_stub *group;
+      /* A temp section list pointer.  */
+      asection *list;
+    } u;
+  } *sec_info;
 
   /* Temp used when calculating TOC pointers.  */
   bfd_vma toc_curr;
   bfd *toc_bfd;
   asection *toc_first_sec;
 
-  /* Highest input section id.  */
-  unsigned int top_id;
-
-  /* Highest output section index.  */
-  unsigned int top_index;
-
   /* Used when adding symbols.  */
   struct ppc_link_hash_entry *dot_syms;
 
-  /* List of input sections for each output section.  */
-  asection **input_list;
-
   /* Shortcuts to get to dynamic linker sections.  */
   asection *dynbss;
   asection *relbss;
@@ -4056,13 +4061,12 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
       /* Initialize the local fields.  */
       eh = (struct ppc_stub_hash_entry *) entry;
       eh->stub_type = ppc_stub_none;
-      eh->stub_sec = NULL;
+      eh->group = NULL;
       eh->stub_offset = 0;
       eh->target_value = 0;
       eh->target_section = NULL;
       eh->h = NULL;
       eh->plt_ent = NULL;
-      eh->id_sec = NULL;
       eh->other = 0;
     }
 
@@ -4412,18 +4416,18 @@ ppc_get_stub_entry (const asection *input_section,
 		    struct ppc_link_hash_table *htab)
 {
   struct ppc_stub_hash_entry *stub_entry;
-  const asection *id_sec;
+  struct map_stub *group;
 
   /* If this input section is part of a group of sections sharing one
      stub section, then use the id of the first section in the group.
      Stub names need to include a section id, as there may well be
      more than one stub used to reach say, printf, and we need to
      distinguish between them.  */
-  id_sec = htab->stub_group[input_section->id].link_sec;
+  group = htab->sec_info[input_section->id].u.group;
 
   if (h != NULL && h->u.stub_cache != NULL
       && h->u.stub_cache->h == h
-      && h->u.stub_cache->id_sec == id_sec)
+      && h->u.stub_cache->group == group)
     {
       stub_entry = h->u.stub_cache;
     }
@@ -4431,7 +4435,7 @@ ppc_get_stub_entry (const asection *input_section,
     {
       char *stub_name;
 
-      stub_name = ppc_stub_name (id_sec, sym_sec, h, rel);
+      stub_name = ppc_stub_name (group->link_sec, sym_sec, h, rel);
       if (stub_name == NULL)
 	return NULL;
 
@@ -4455,35 +4459,32 @@ ppc_add_stub (const char *stub_name,
 	      struct bfd_link_info *info)
 {
   struct ppc_link_hash_table *htab = ppc_hash_table (info);
+  struct map_stub *group;
   asection *link_sec;
   asection *stub_sec;
   struct ppc_stub_hash_entry *stub_entry;
 
-  link_sec = htab->stub_group[section->id].link_sec;
-  stub_sec = htab->stub_group[section->id].stub_sec;
+  group = htab->sec_info[section->id].u.group;
+  link_sec = group->link_sec;
+  stub_sec = group->stub_sec;
   if (stub_sec == NULL)
     {
-      stub_sec = htab->stub_group[link_sec->id].stub_sec;
-      if (stub_sec == NULL)
-	{
-	  size_t namelen;
-	  bfd_size_type len;
-	  char *s_name;
+      size_t namelen;
+      bfd_size_type len;
+      char *s_name;
 
-	  namelen = strlen (link_sec->name);
-	  len = namelen + sizeof (STUB_SUFFIX);
-	  s_name = bfd_alloc (htab->params->stub_bfd, len);
-	  if (s_name == NULL)
-	    return NULL;
+      namelen = strlen (link_sec->name);
+      len = namelen + sizeof (STUB_SUFFIX);
+      s_name = bfd_alloc (htab->params->stub_bfd, len);
+      if (s_name == NULL)
+	return NULL;
 
-	  memcpy (s_name, link_sec->name, namelen);
-	  memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX));
-	  stub_sec = (*htab->params->add_stub_section) (s_name, link_sec);
-	  if (stub_sec == NULL)
-	    return NULL;
-	  htab->stub_group[link_sec->id].stub_sec = stub_sec;
-	}
-      htab->stub_group[section->id].stub_sec = stub_sec;
+      memcpy (s_name, link_sec->name, namelen);
+      memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX));
+      stub_sec = (*htab->params->add_stub_section) (s_name, link_sec);
+      if (stub_sec == NULL)
+	return NULL;
+      group->stub_sec = stub_sec;
     }
 
   /* Enter this entry into the linker stub hash table.  */
@@ -4496,9 +4497,8 @@ ppc_add_stub (const char *stub_name,
       return NULL;
     }
 
-  stub_entry->stub_sec = stub_sec;
+  stub_entry->group = group;
   stub_entry->stub_offset = 0;
-  stub_entry->id_sec = link_sec;
   return stub_entry;
 }
 
@@ -10257,7 +10257,7 @@ plt_stub_pad (struct ppc_link_hash_table *htab,
 {
   int stub_align = 1 << htab->params->plt_stub_align;
   unsigned stub_size = plt_stub_size (htab, stub_entry, plt_off);
-  bfd_vma stub_off = stub_entry->stub_sec->size;
+  bfd_vma stub_off = stub_entry->group->stub_sec->size;
 
   if (((stub_off + stub_size - 1) & -stub_align) - (stub_off & -stub_align)
       > ((stub_size - 1) & -stub_align))
@@ -10300,7 +10300,7 @@ build_plt_stub (struct ppc_link_hash_table *htab,
       to = (glinkoff
 	    + htab->glink->output_offset
 	    + htab->glink->output_section->vma);
-      from = (p - stub_entry->stub_sec->contents
+      from = (p - stub_entry->group->stub_sec->contents
 	      + 4 * (ALWAYS_EMIT_R2SAVE
 		     || stub_entry->stub_type == ppc_stub_plt_call_r2save)
 	      + 4 * (PPC_HA (offset) != 0)
@@ -10308,8 +10308,8 @@ build_plt_stub (struct ppc_link_hash_table *htab,
 		     != PPC_HA (offset))
 	      + 4 * (plt_static_chain != 0)
 	      + 20
-	      + stub_entry->stub_sec->output_offset
-	      + stub_entry->stub_sec->output_section->vma);
+	      + stub_entry->group->stub_sec->output_offset
+	      + stub_entry->group->stub_sec->output_section->vma);
       cmp_branch_off = to - from;
       use_fake_dep = cmp_branch_off + (1 << 25) >= (1 << 26);
     }
@@ -10522,7 +10522,7 @@ get_r2off (struct bfd_link_info *info,
 	   struct ppc_stub_hash_entry *stub_entry)
 {
   struct ppc_link_hash_table *htab = ppc_hash_table (info);
-  bfd_vma r2off = htab->stub_group[stub_entry->target_section->id].toc_off;
+  bfd_vma r2off = htab->sec_info[stub_entry->target_section->id].toc_off;
 
   if (r2off == 0)
     {
@@ -10547,7 +10547,7 @@ get_r2off (struct bfd_link_info *info,
       r2off = bfd_get_64 (opd->owner, buf);
       r2off -= elf_gp (info->output_bfd);
     }
-  r2off -= htab->stub_group[stub_entry->id_sec->id].toc_off;
+  r2off -= htab->sec_info[stub_entry->group->link_sec->id].toc_off;
   return r2off;
 }
 
@@ -10574,8 +10574,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
     return FALSE;
 
   /* Make a note of the offset within the stubs for this entry.  */
-  stub_entry->stub_offset = stub_entry->stub_sec->size;
-  loc = stub_entry->stub_sec->contents + stub_entry->stub_offset;
+  stub_entry->stub_offset = stub_entry->group->stub_sec->size;
+  loc = stub_entry->group->stub_sec->contents + stub_entry->stub_offset;
 
   htab->stub_count[stub_entry->stub_type - 1] += 1;
   switch (stub_entry->stub_type)
@@ -10591,8 +10591,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       /* And this is where we are coming from.  */
       off -= (stub_entry->stub_offset
-	      + stub_entry->stub_sec->output_offset
-	      + stub_entry->stub_sec->output_section->vma);
+	      + stub_entry->group->stub_sec->output_offset
+	      + stub_entry->group->stub_sec->output_section->vma);
 
       size = 4;
       if (stub_entry->stub_type == ppc_stub_long_branch_r2off)
@@ -10631,10 +10631,10 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       if (info->emitrelocations)
 	{
-	  r = get_relocs (stub_entry->stub_sec, 1);
+	  r = get_relocs (stub_entry->group->stub_sec, 1);
 	  if (r == NULL)
 	    return FALSE;
-	  r->r_offset = loc - stub_entry->stub_sec->contents;
+	  r->r_offset = loc - stub_entry->group->stub_sec->contents;
 	  r->r_info = ELF64_R_INFO (0, R_PPC64_REL24);
 	  r->r_addend = dest;
 	  if (stub_entry->h != NULL)
@@ -10741,7 +10741,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       off = (dest
 	     - elf_gp (htab->brlt->output_section->owner)
-	     - htab->stub_group[stub_entry->id_sec->id].toc_off);
+	     - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
       if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
 	{
@@ -10755,10 +10755,10 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       if (info->emitrelocations)
 	{
-	  r = get_relocs (stub_entry->stub_sec, 1 + (PPC_HA (off) != 0));
+	  r = get_relocs (stub_entry->group->stub_sec, 1 + (PPC_HA (off) != 0));
 	  if (r == NULL)
 	    return FALSE;
-	  r[0].r_offset = loc - stub_entry->stub_sec->contents;
+	  r[0].r_offset = loc - stub_entry->group->stub_sec->contents;
 	  if (bfd_big_endian (info->output_bfd))
 	    r[0].r_offset += 2;
 	  if (stub_entry->stub_type == ppc_stub_plt_branch_r2off)
@@ -10847,11 +10847,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 	  struct ppc_link_hash_entry *fh = ppc_follow_link (stub_entry->h->oh);
 
 	  /* If the old-ABI "dot-symbol" is undefined make it weak so
-	     we don't get a link error from RELOC_FOR_GLOBAL_SYMBOL.
-	     FIXME: We used to define the symbol on one of the call
-	     stubs instead, which is why we test symbol section id
-	     against htab->top_id in various places.  Likely all
-	     these checks could now disappear.  */
+	     we don't get a link error from RELOC_FOR_GLOBAL_SYMBOL.  */
 	  if (fh->elf.root.type == bfd_link_hash_undefined)
 	    fh->elf.root.type = bfd_link_hash_undefweak;
 	  /* Stop undo_symbol_twiddle changing it back to undefined.  */
@@ -10895,7 +10891,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       off = (dest
 	     - elf_gp (plt->output_section->owner)
-	     - htab->stub_group[stub_entry->id_sec->id].toc_off);
+	     - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
       if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
 	{
@@ -10913,15 +10909,15 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 	{
 	  unsigned pad = plt_stub_pad (htab, stub_entry, off);
 
-	  stub_entry->stub_sec->size += pad;
-	  stub_entry->stub_offset = stub_entry->stub_sec->size;
+	  stub_entry->group->stub_sec->size += pad;
+	  stub_entry->stub_offset = stub_entry->group->stub_sec->size;
 	  loc += pad;
 	}
 
       r = NULL;
       if (info->emitrelocations)
 	{
-	  r = get_relocs (stub_entry->stub_sec,
+	  r = get_relocs (stub_entry->group->stub_sec,
 			  ((PPC_HA (off) != 0)
 			   + (htab->opd_abi
 			      ? 2 + (htab->params->plt_static_chain
@@ -10929,7 +10925,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 			      : 1)));
 	  if (r == NULL)
 	    return FALSE;
-	  r[0].r_offset = loc - stub_entry->stub_sec->contents;
+	  r[0].r_offset = loc - stub_entry->group->stub_sec->contents;
 	  if (bfd_big_endian (info->output_bfd))
 	    r[0].r_offset += 2;
 	  r[0].r_addend = dest;
@@ -10949,7 +10945,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       return FALSE;
     }
 
-  stub_entry->stub_sec->size += size;
+  stub_entry->group->stub_sec->size += size;
 
   if (htab->params->emit_stub_syms)
     {
@@ -10977,7 +10973,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (h->root.type == bfd_link_hash_new)
 	{
 	  h->root.type = bfd_link_hash_defined;
-	  h->root.u.def.section = stub_entry->stub_sec;
+	  h->root.u.def.section = stub_entry->group->stub_sec;
 	  h->root.u.def.value = stub_entry->stub_offset;
 	  h->ref_regular = 1;
 	  h->def_regular = 1;
@@ -11027,20 +11023,20 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       off += (plt->output_offset
 	      + plt->output_section->vma
 	      - elf_gp (plt->output_section->owner)
-	      - htab->stub_group[stub_entry->id_sec->id].toc_off);
+	      - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
       size = plt_stub_size (htab, stub_entry, off);
       if (htab->params->plt_stub_align)
 	size += plt_stub_pad (htab, stub_entry, off);
       if (info->emitrelocations)
 	{
-	  stub_entry->stub_sec->reloc_count
+	  stub_entry->group->stub_sec->reloc_count
 	    += ((PPC_HA (off) != 0)
 		+ (htab->opd_abi
 		   ? 2 + (htab->params->plt_static_chain
 			  && PPC_HA (off + 16) == PPC_HA (off))
 		   : 1));
-	  stub_entry->stub_sec->flags |= SEC_RELOC;
+	  stub_entry->group->stub_sec->flags |= SEC_RELOC;
 	}
     }
   else
@@ -11053,9 +11049,9 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       off = (stub_entry->target_value
 	     + stub_entry->target_section->output_offset
 	     + stub_entry->target_section->output_section->vma);
-      off -= (stub_entry->stub_sec->size
-	      + stub_entry->stub_sec->output_offset
-	      + stub_entry->stub_sec->output_section->vma);
+      off -= (stub_entry->group->stub_sec->size
+	      + stub_entry->group->stub_sec->output_offset
+	      + stub_entry->group->stub_sec->output_section->vma);
 
       /* Reset the stub type from the plt variant in case we now
 	 can reach with a shorter stub.  */
@@ -11118,12 +11114,13 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 		 + htab->brlt->output_offset
 		 + htab->brlt->output_section->vma
 		 - elf_gp (htab->brlt->output_section->owner)
-		 - htab->stub_group[stub_entry->id_sec->id].toc_off);
+		 - htab->sec_info[stub_entry->group->link_sec->id].toc_off);
 
 	  if (info->emitrelocations)
 	    {
-	      stub_entry->stub_sec->reloc_count += 1 + (PPC_HA (off) != 0);
-	      stub_entry->stub_sec->flags |= SEC_RELOC;
+	      stub_entry->group->stub_sec->reloc_count
+		+= 1 + (PPC_HA (off) != 0);
+	      stub_entry->group->stub_sec->flags |= SEC_RELOC;
 	    }
 
 	  if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
@@ -11146,12 +11143,12 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 	}
       else if (info->emitrelocations)
 	{
-	  stub_entry->stub_sec->reloc_count += 1;
-	  stub_entry->stub_sec->flags |= SEC_RELOC;
+	  stub_entry->group->stub_sec->reloc_count += 1;
+	  stub_entry->group->stub_sec->flags |= SEC_RELOC;
 	}
     }
 
-  stub_entry->stub_sec->size += size;
+  stub_entry->group->stub_sec->size += size;
   return TRUE;
 }
 
@@ -11162,57 +11159,22 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 int
 ppc64_elf_setup_section_lists (struct bfd_link_info *info)
 {
-  bfd *input_bfd;
-  unsigned int top_id, top_index, id;
-  asection *section;
-  asection **input_list;
+  unsigned int id;
   bfd_size_type amt;
   struct ppc_link_hash_table *htab = ppc_hash_table (info);
 
   if (htab == NULL)
     return -1;
 
-  /* Find the top input section id.  */
-  for (input_bfd = info->input_bfds, top_id = 3;
-       input_bfd != NULL;
-       input_bfd = input_bfd->link.next)
-    {
-      for (section = input_bfd->sections;
-	   section != NULL;
-	   section = section->next)
-	{
-	  if (top_id < section->id)
-	    top_id = section->id;
-	}
-    }
-
-  htab->top_id = top_id;
-  amt = sizeof (struct map_stub) * (top_id + 1);
-  htab->stub_group = bfd_zmalloc (amt);
-  if (htab->stub_group == NULL)
+  htab->sec_info_arr_size = bfd_get_next_section_id ();
+  amt = sizeof (*htab->sec_info) * (htab->sec_info_arr_size);
+  htab->sec_info = bfd_zmalloc (amt);
+  if (htab->sec_info == NULL)
     return -1;
 
   /* Set toc_off for com, und, abs and ind sections.  */
   for (id = 0; id < 3; id++)
-    htab->stub_group[id].toc_off = TOC_BASE_OFF;
-
-  /* We can't use output_bfd->section_count here to find the top output
-     section index as some sections may have been removed, and
-     strip_excluded_output_sections doesn't renumber the indices.  */
-  for (section = info->output_bfd->sections, top_index = 0;
-       section != NULL;
-       section = section->next)
-    {
-      if (top_index < section->index)
-	top_index = section->index;
-    }
-
-  htab->top_index = top_index;
-  amt = sizeof (asection *) * (top_index + 1);
-  input_list = bfd_zmalloc (amt);
-  htab->input_list = input_list;
-  if (input_list == NULL)
-    return -1;
+    htab->sec_info[id].toc_off = TOC_BASE_OFF;
 
   return 1;
 }
@@ -11761,15 +11723,13 @@ ppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec)
     return FALSE;
 
   if ((isec->output_section->flags & SEC_CODE) != 0
-      && isec->output_section->index <= htab->top_index)
+      && isec->output_section->id < htab->sec_info_arr_size)
     {
-      asection **list = htab->input_list + isec->output_section->index;
-      /* Steal the link_sec pointer for our list.  */
-#define PREV_SEC(sec) (htab->stub_group[(sec)->id].link_sec)
       /* This happens to make the list in reverse order,
 	 which is what we want.  */
-      PREV_SEC (isec) = *list;
-      *list = isec;
+      htab->sec_info[isec->id].u.list
+	= htab->sec_info[isec->output_section->id].u.list;
+      htab->sec_info[isec->output_section->id].u.list = isec;
     }
 
   if (htab->multi_toc_needed)
@@ -11793,7 +11753,7 @@ ppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec)
 	htab->toc_curr = elf_gp (isec->owner);
     }
 
-  htab->stub_group[isec->id].toc_off = htab->toc_curr;
+  htab->sec_info[isec->id].toc_off = htab->toc_curr;
   return TRUE;
 }
 
@@ -11815,8 +11775,8 @@ check_pasted_section (struct bfd_link_info *info, const char *name)
 	if (i->has_toc_reloc)
 	  {
 	    if (toc_off == 0)
-	      toc_off = htab->stub_group[i->id].toc_off;
-	    else if (toc_off != htab->stub_group[i->id].toc_off)
+	      toc_off = htab->sec_info[i->id].toc_off;
+	    else if (toc_off != htab->sec_info[i->id].toc_off)
 	      return FALSE;
 	  }
 
@@ -11824,14 +11784,14 @@ check_pasted_section (struct bfd_link_info *info, const char *name)
 	for (i = o->map_head.s; i != NULL; i = i->map_head.s)
 	  if (i->makes_toc_func_call)
 	    {
-	      toc_off = htab->stub_group[i->id].toc_off;
+	      toc_off = htab->sec_info[i->id].toc_off;
 	      break;
 	    }
 
       /* Make sure the whole pasted function uses the same toc offset.  */
       if (toc_off != 0)
 	for (i = o->map_head.s; i != NULL; i = i->map_head.s)
-	  htab->stub_group[i->id].toc_off = toc_off;
+	  htab->sec_info[i->id].toc_off = toc_off;
     }
   return TRUE;
 }
@@ -11850,15 +11810,20 @@ ppc64_elf_check_init_fini (struct bfd_link_info *info)
    _init and _fini functions into multiple parts.  Putting a stub in
    the middle of a function is not a good idea.  */
 
-static void
-group_sections (struct ppc_link_hash_table *htab,
+static bfd_boolean
+group_sections (struct bfd_link_info *info,
 		bfd_size_type stub_group_size,
 		bfd_boolean stubs_always_before_branch)
 {
-  asection **list;
+  struct ppc_link_hash_table *htab;
+  asection *osec;
   bfd_size_type stub14_group_size;
   bfd_boolean suppress_size_errors;
 
+  htab = ppc_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   suppress_size_errors = FALSE;
   stub14_group_size = stub_group_size >> 10;
   if (stub_group_size == 1)
@@ -11877,10 +11842,14 @@ group_sections (struct ppc_link_hash_table *htab,
       suppress_size_errors = TRUE;
     }
 
-  list = htab->input_list + htab->top_index;
-  do
+  for (osec = info->output_bfd->sections; osec != NULL; osec = osec->next)
     {
-      asection *tail = *list;
+      asection *tail;
+
+      if (osec->id >= htab->sec_info_arr_size)
+	continue;
+
+      tail = htab->sec_info[osec->id].u.list;
       while (tail != NULL)
 	{
 	  asection *curr;
@@ -11888,6 +11857,7 @@ group_sections (struct ppc_link_hash_table *htab,
 	  bfd_size_type total;
 	  bfd_boolean big_sec;
 	  bfd_vma curr_toc;
+	  struct map_stub *group;
 
 	  curr = tail;
 	  total = tail->size;
@@ -11897,14 +11867,14 @@ group_sections (struct ppc_link_hash_table *htab,
 	  if (big_sec && !suppress_size_errors)
 	    (*_bfd_error_handler) (_("%B section %A exceeds stub group size"),
 				     tail->owner, tail);
-	  curr_toc = htab->stub_group[tail->id].toc_off;
+	  curr_toc = htab->sec_info[tail->id].toc_off;
 
-	  while ((prev = PREV_SEC (curr)) != NULL
+	  while ((prev = htab->sec_info[curr->id].u.list) != NULL
 		 && ((total += curr->output_offset - prev->output_offset)
 		     < (ppc64_elf_section_data (prev) != NULL
 			&& ppc64_elf_section_data (prev)->has_14bit_branch
 			? stub14_group_size : stub_group_size))
-		 && htab->stub_group[prev->id].toc_off == curr_toc)
+		 && htab->sec_info[prev->id].toc_off == curr_toc)
 	    curr = prev;
 
 	  /* OK, the size from the start of CURR to the end is less
@@ -11917,11 +11887,16 @@ group_sections (struct ppc_link_hash_table *htab,
 	     only break if stubs added make the total size more than
 	     2^25, ie. for the default stub_group_size, if stubs total
 	     more than 2097152 bytes, or nearly 75000 plt call stubs.  */
+	  group = bfd_alloc (curr->owner, sizeof (*group));
+	  if (group == NULL)
+	    return FALSE;
+	  group->link_sec = curr;
+	  group->stub_sec = NULL;
 	  do
 	    {
-	      prev = PREV_SEC (tail);
+	      prev = htab->sec_info[tail->id].u.list;
 	      /* Set up this stub group.  */
-	      htab->stub_group[tail->id].link_sec = curr;
+	      htab->sec_info[tail->id].u.group = group;
 	    }
 	  while (tail != curr && (tail = prev) != NULL);
 
@@ -11938,19 +11913,17 @@ group_sections (struct ppc_link_hash_table *htab,
 			 < (ppc64_elf_section_data (prev) != NULL
 			    && ppc64_elf_section_data (prev)->has_14bit_branch
 			    ? stub14_group_size : stub_group_size))
-		     && htab->stub_group[prev->id].toc_off == curr_toc)
+		     && htab->sec_info[prev->id].toc_off == curr_toc)
 		{
 		  tail = prev;
-		  prev = PREV_SEC (tail);
-		  htab->stub_group[tail->id].link_sec = curr;
+		  prev = htab->sec_info[tail->id].u.list;
+		  htab->sec_info[tail->id].u.group = group;
 		}
 	    }
 	  tail = prev;
 	}
     }
-  while (list-- != htab->input_list);
-  free (htab->input_list);
-#undef PREV_SEC
+  return TRUE;
 }
 
 static const unsigned char glink_eh_frame_cie[] =
@@ -12055,7 +12028,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
   else
     stub_group_size = htab->params->group_size;
 
-  group_sections (htab, stub_group_size, stubs_always_before_branch);
+  if (!group_sections (info, stub_group_size, stubs_always_before_branch))
+    return FALSE;
 
   while (1)
     {
@@ -12258,8 +12232,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
 			 fact a call needing a TOC adjustment.  */
 		      if (code_sec != NULL
 			  && code_sec->output_section != NULL
-			  && (htab->stub_group[code_sec->id].toc_off
-			      != htab->stub_group[section->id].toc_off)
+			  && (htab->sec_info[code_sec->id].toc_off
+			      != htab->sec_info[section->id].toc_off)
 			  && (code_sec->has_toc_reloc
 			      || code_sec->makes_toc_func_call))
 			stub_type = ppc_stub_long_branch_r2off;
@@ -12299,7 +12273,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
 		    stub_type = ppc_stub_plt_call_r2save;
 
 		  /* Support for grouping stub sections.  */
-		  id_sec = htab->stub_group[section->id].link_sec;
+		  id_sec = htab->sec_info[section->id].u.group->link_sec;
 
 		  /* Get the name of this stub.  */
 		  stub_name = ppc_stub_name (id_sec, sym_sec, hash, irela);
@@ -13234,8 +13208,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
       if (h != NULL && &h->elf == htab->elf.hgot)
 	{
-	  relocation = (TOCstart
-			+ htab->stub_group[input_section->id].toc_off);
+	  relocation = TOCstart + htab->sec_info[input_section->id].toc_off;
 	  sec = bfd_abs_section_ptr;
 	  unresolved_reloc = FALSE;
 	}
@@ -13943,8 +13916,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	      /* Munge up the value and addend so that we call the stub
 		 rather than the procedure directly.  */
 	      relocation = (stub_entry->stub_offset
-			    + stub_entry->stub_sec->output_offset
-			    + stub_entry->stub_sec->output_section->vma);
+			    + stub_entry->group->stub_sec->output_offset
+			    + stub_entry->group->stub_sec->output_section->vma);
 	      addend = 0;
 	      reloc_dest = DEST_STUB;
 
@@ -14241,7 +14214,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	      abort ();
 
 	    relocation = got->output_section->vma + got->output_offset + off;
-	    addend = -(TOCstart + htab->stub_group[input_section->id].toc_off);
+	    addend = -(TOCstart + htab->sec_info[input_section->id].toc_off);
 	  }
 	  break;
 
@@ -14282,11 +14255,11 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	  /* Relocation value is TOC base.  */
 	  relocation = TOCstart;
 	  if (r_symndx == STN_UNDEF)
-	    relocation += htab->stub_group[input_section->id].toc_off;
+	    relocation += htab->sec_info[input_section->id].toc_off;
 	  else if (unresolved_reloc)
 	    ;
-	  else if (sec != NULL && sec->id <= htab->top_id)
-	    relocation += htab->stub_group[sec->id].toc_off;
+	  else if (sec != NULL && sec->id < htab->sec_info_arr_size)
+	    relocation += htab->sec_info[sec->id].toc_off;
 	  else
 	    unresolved_reloc = TRUE;
 	  goto dodyn;
@@ -14301,7 +14274,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	case R_PPC64_TOC16_DS:
 	case R_PPC64_TOC16_LO_DS:
 	case R_PPC64_TOC16_HA:
-	  addend -= TOCstart + htab->stub_group[input_section->id].toc_off;
+	  addend -= TOCstart + htab->sec_info[input_section->id].toc_off;
 	  break;
 
 	  /* Relocate against the beginning of the section.  */
diff --git a/bfd/section.c b/bfd/section.c
index fc6b765..834a9ab 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -821,13 +821,13 @@ _bfd_generic_new_section_hook (bfd *abfd, asection *newsect)
   return TRUE;
 }
 
+static unsigned int section_id = 0x10;  /* id 0 to 3 used by STD_SECTION.  */
+
 /* Initializes a new section.  NEWSECT->NAME is already set.  */
 
 static asection *
 bfd_section_init (bfd *abfd, asection *newsect)
 {
-  static unsigned int section_id = 0x10;  /* id 0 to 3 used by STD_SECTION.  */
-
   newsect->id = section_id;
   newsect->index = abfd->section_count;
   newsect->owner = abfd;
@@ -1275,6 +1275,23 @@ bfd_make_section (bfd *abfd, const char *name)
 
 /*
 FUNCTION
+	bfd_get_next_section_id
+
+SYNOPSIS
+	int bfd_get_next_section_id (void);
+
+DESCRIPTION
+	Returns the id that the next section created will have.
+*/
+
+int
+bfd_get_next_section_id (void)
+{
+  return section_id;
+}
+
+/*
+FUNCTION
 	bfd_set_section_flags
 
 SYNOPSIS

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