diff options
-rw-r--r-- | bfd/ChangeLog | 13 | ||||
-rw-r--r-- | bfd/elf64-ppc.c | 117 |
2 files changed, 84 insertions, 46 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index cd7e8f1..7253d0a 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,18 @@ 2006-11-07 Alan Modra <amodra@bigpond.net.au> + * elf64-ppc.c (enum _ppc64_sec_type): New. + (struct _ppc64_elf_section_data): Move "t_symndx" into opd union, + and rename fields. Add sec_type and has_14bit_branch. + (struct ppc_link_hash_table): Remove has_14bit_branch. + (get_opd_info, get_tls_mask, ppc64_elf_edit_opd): Adjust. + (ppc64_elf_relocate_section): Likewise. + (ppc64_elf_check_relocs): Likewise. Set per-section has_14bit_branch. + (ppc64_elf_size_stubs): Don't set default group size here. + (group_sections): Instead do so here, and group sections using + their individual requirements. + +2006-11-07 Alan Modra <amodra@bigpond.net.au> + * elf64-ppc.c (struct ppc64_elf_obj_tdata): Remove "has_dotsym" and union. (struct ppc_link_hash_entry): Add "next_dot_sym". diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 84a7b5f..0c81e5e 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -2525,6 +2525,12 @@ static const struct bfd_elf_special_section ppc64_elf_special_sections[]= { NULL, 0, 0, 0, 0 } }; +enum _ppc64_sec_type { + sec_normal = 0, + sec_opd = 1, + sec_toc = 2 +}; + struct _ppc64_elf_section_data { struct bfd_elf_section_data elf; @@ -2533,14 +2539,20 @@ struct _ppc64_elf_section_data union { /* Points to the function code section for local opd entries. */ - asection **func_sec; + asection **opd_func_sec; /* After editing .opd, adjust references to opd local syms. */ - long *adjust; - } opd; + long *opd_adjust; + + /* An array for toc sections, indexed by offset/8. + Specifies the relocation symbol index used at a given toc offset. */ + unsigned *t_symndx; + } u; + + enum _ppc64_sec_type sec_type:2; - /* An array for toc sections, indexed by offset/8. - Specifies the relocation symbol index used at a given toc offset. */ - unsigned *t_symndx; + /* Flag set when small branches are detected. Used to + select suitable defaults for the stub group size. */ + unsigned int has_14bit_branch:1; }; #define ppc64_elf_section_data(sec) \ @@ -2568,8 +2580,8 @@ get_opd_info (asection * sec) { if (sec != NULL && ppc64_elf_section_data (sec) != NULL - && ppc64_elf_section_data (sec)->opd.adjust != NULL) - return ppc64_elf_section_data (sec)->opd.adjust; + && ppc64_elf_section_data (sec)->sec_type == sec_opd) + return ppc64_elf_section_data (sec)->u.opd_adjust; return NULL; } @@ -3358,10 +3370,6 @@ struct ppc_link_hash_table /* Set on error. */ unsigned int stub_error:1; - /* Flag set when small branches are detected. Used to - select suitable defaults for the stub group size. */ - unsigned int has_14bit_branch:1; - /* Temp used by ppc64_elf_check_directives. */ unsigned int twiddled_syms:1; @@ -4373,7 +4381,9 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, opd_sym_map = bfd_zalloc (abfd, amt); if (opd_sym_map == NULL) return FALSE; - ppc64_elf_section_data (sec)->opd.func_sec = opd_sym_map; + ppc64_elf_section_data (sec)->u.opd_func_sec = opd_sym_map; + BFD_ASSERT (ppc64_elf_section_data (sec)->sec_type == sec_normal); + ppc64_elf_section_data (sec)->sec_type = sec_opd; } if (htab->sfpr == NULL @@ -4387,6 +4397,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, struct elf_link_hash_entry *h; enum elf_ppc64_reloc_type r_type; int tls_type = 0; + struct _ppc64_elf_section_data *ppc64_sec; r_symndx = ELF64_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info) @@ -4568,7 +4579,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, dest = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec, r_symndx); if (dest != sec) - htab->has_14bit_branch = 1; + ppc64_elf_section_data (sec)->has_14bit_branch = 1; } /* Fall through. */ @@ -4639,23 +4650,26 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, rel->r_addend, tls_type)) return FALSE; - if (ppc64_elf_section_data (sec)->t_symndx == NULL) + ppc64_sec = ppc64_elf_section_data (sec); + if (ppc64_sec->sec_type != sec_toc) { /* One extra to simplify get_tls_mask. */ bfd_size_type amt = sec->size * sizeof (unsigned) / 8 + 1; - ppc64_elf_section_data (sec)->t_symndx = bfd_zalloc (abfd, amt); - if (ppc64_elf_section_data (sec)->t_symndx == NULL) + ppc64_sec->u.t_symndx = bfd_zalloc (abfd, amt); + if (ppc64_sec->u.t_symndx == NULL) return FALSE; + BFD_ASSERT (ppc64_sec->sec_type == sec_normal); + ppc64_sec->sec_type = sec_toc; } BFD_ASSERT (rel->r_offset % 8 == 0); - ppc64_elf_section_data (sec)->t_symndx[rel->r_offset / 8] = r_symndx; + ppc64_sec->u.t_symndx[rel->r_offset / 8] = r_symndx; /* Mark the second slot of a GD or LD entry. -1 to indicate GD and -2 to indicate LD. */ if (tls_type == (TLS_EXPLICIT | TLS_TLS | TLS_GD)) - ppc64_elf_section_data (sec)->t_symndx[rel->r_offset / 8 + 1] = -1; + ppc64_sec->u.t_symndx[rel->r_offset / 8 + 1] = -1; else if (tls_type == (TLS_EXPLICIT | TLS_TLS | TLS_LD)) - ppc64_elf_section_data (sec)->t_symndx[rel->r_offset / 8 + 1] = -2; + ppc64_sec->u.t_symndx[rel->r_offset / 8 + 1] = -2; goto dodyn; case R_PPC64_TPREL16: @@ -6051,7 +6065,7 @@ get_tls_mask (char **tls_maskp, unsigned long *toc_symndx, if ((*tls_maskp != NULL && **tls_maskp != 0) || sec == NULL - || ppc64_elf_section_data (sec)->t_symndx == NULL) + || ppc64_elf_section_data (sec)->sec_type != sec_toc) return 1; /* Look inside a TOC section too. */ @@ -6064,8 +6078,8 @@ get_tls_mask (char **tls_maskp, unsigned long *toc_symndx, off = sym->st_value; off += rel->r_addend; BFD_ASSERT (off % 8 == 0); - r_symndx = ppc64_elf_section_data (sec)->t_symndx[off / 8]; - next_r = ppc64_elf_section_data (sec)->t_symndx[off / 8 + 1]; + r_symndx = ppc64_elf_section_data (sec)->u.t_symndx[off / 8]; + next_r = ppc64_elf_section_data (sec)->u.t_symndx[off / 8 + 1]; if (!get_sym_h (&h, &sym, &sec, tls_maskp, locsymsp, r_symndx, ibfd)) return 0; if (toc_symndx != NULL) @@ -6306,7 +6320,9 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info, opd_adjust = bfd_alloc (obfd, amt); if (opd_adjust == NULL) return FALSE; - ppc64_elf_section_data (sec)->opd.adjust = opd_adjust; + ppc64_elf_section_data (sec)->u.opd_adjust = opd_adjust; + BFD_ASSERT (ppc64_elf_section_data (sec)->sec_type == sec_normal); + ppc64_elf_section_data (sec)->sec_type = sec_opd; } memset (opd_adjust, 0, amt); @@ -8940,7 +8956,29 @@ group_sections (struct ppc_link_hash_table *htab, bfd_size_type stub_group_size, bfd_boolean stubs_always_before_branch) { - asection **list = htab->input_list + htab->top_index; + asection **list; + bfd_size_type stub14_group_size; + bfd_boolean suppress_size_errors; + + suppress_size_errors = FALSE; + stub14_group_size = stub_group_size; + if (stub_group_size == 1) + { + /* Default values. */ + if (stubs_always_before_branch) + { + stub_group_size = 0x1e00000; + stub14_group_size = 0x7800; + } + else + { + stub_group_size = 0x1c00000; + stub14_group_size = 0x7000; + } + suppress_size_errors = TRUE; + } + + list = htab->input_list + htab->top_index; do { asection *tail = *list; @@ -8954,15 +8992,17 @@ group_sections (struct ppc_link_hash_table *htab, curr = tail; total = tail->size; - big_sec = total > stub_group_size; - if (big_sec) + big_sec = total > (ppc64_elf_section_data (tail)->has_14bit_branch + ? stub14_group_size : stub_group_size); + 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; while ((prev = PREV_SEC (curr)) != NULL && ((total += curr->output_offset - prev->output_offset) - < stub_group_size) + < (ppc64_elf_section_data (prev)->has_14bit_branch + ? stub14_group_size : stub_group_size)) && htab->stub_group[prev->id].toc_off == curr_toc) curr = prev; @@ -8994,7 +9034,8 @@ group_sections (struct ppc_link_hash_table *htab, total = 0; while (prev != NULL && ((total += tail->output_offset - prev->output_offset) - < stub_group_size) + < (ppc64_elf_section_data (prev)->has_14bit_branch + ? stub14_group_size : stub_group_size)) && htab->stub_group[prev->id].toc_off == curr_toc) { tail = prev; @@ -9035,22 +9076,6 @@ ppc64_elf_size_stubs (bfd *output_bfd, stub_group_size = -group_size; else stub_group_size = group_size; - if (stub_group_size == 1) - { - /* Default values. */ - if (stubs_always_before_branch) - { - stub_group_size = 0x1e00000; - if (htab->has_14bit_branch) - stub_group_size = 0x7800; - } - else - { - stub_group_size = 0x1c00000; - if (htab->has_14bit_branch) - stub_group_size = 0x7000; - } - } group_sections (htab, stub_group_size, stubs_always_before_branch); @@ -9721,7 +9746,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, TOCstart = elf_gp (output_bfd); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); - is_opd = ppc64_elf_section_data (input_section)->opd.adjust != NULL; + is_opd = ppc64_elf_section_data (input_section)->sec_type == sec_opd; rel = relocs; relend = relocs + input_section->reloc_count; |