From 6f20ed8a6ba1a01fb356eea8ea45310ed8478a27 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Mon, 31 Aug 2015 17:50:33 +0930 Subject: [PATCH] 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. --- bfd/ChangeLog | 24 ++++ bfd/bfd-in2.h | 2 + bfd/elf64-ppc.c | 321 ++++++++++++++++++++++-------------------------- bfd/section.c | 21 +++- 4 files changed, 192 insertions(+), 176 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 44f5d78f7d..58d2359b8d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,27 @@ +2015-08-31 Alan Modra + + * 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. + 2015-08-31 Alan Modra * elflink.c (elf_sort_symbol): Use correctly sized type for diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index f73abf0ba9..51fa54f1d4 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1818,6 +1818,8 @@ asection *bfd_make_section_with_flags asection *bfd_make_section (bfd *, const char *name); +int bfd_get_next_section_id (void); + bfd_boolean bfd_set_section_flags (bfd *abfd, asection *sec, flagword flags); diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 4a232b764d..efa124e43b 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 fc6b7651c3..834a9ab0b4 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; @@ -1273,6 +1273,23 @@ bfd_make_section (bfd *abfd, const char *name) return bfd_make_section_with_flags (abfd, name, 0); } +/* +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 -- 2.34.1