From: Alan Modra Date: Wed, 9 Feb 2011 08:16:00 +0000 (+0000) Subject: * elf64-ppc.c (ppc64_elf_edit_toc): Don't free toc relocs until X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=425b145b6ec65eefa2c23131c7c9997f08ebf88c;p=deliverable%2Fbinutils-gdb.git * elf64-ppc.c (ppc64_elf_edit_toc): Don't free toc relocs until we are done. When optimising large toc, check that a global symbol on a toc reloc is defined in a kept section. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9935a841f5..64e1ccd7c0 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2011-02-09 Alan Modra + + * elf64-ppc.c (ppc64_elf_edit_toc): Don't free toc relocs until + we are done. When optimising large toc, check that a global + symbol on a toc reloc is defined in a kept section. + 2011-02-08 Nick Clifton PR binutils/12467 diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 4e85e90105..25d0d2efee 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -7907,7 +7907,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) asection *toc, *sec; Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Sym *local_syms; - Elf_Internal_Rela *relstart, *rel; + Elf_Internal_Rela *relstart, *rel, *toc_relocs; unsigned long *skip, *drop; unsigned char *used; unsigned char *keep, last, some_unused; @@ -7922,6 +7922,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) || elf_discarded_section (toc)) continue; + toc_relocs = NULL; local_syms = NULL; symtab_hdr = &elf_symtab_hdr (ibfd); @@ -8017,12 +8018,12 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) && toc->reloc_count != 0) { /* Read toc relocs. */ - relstart = _bfd_elf_link_read_relocs (ibfd, toc, NULL, NULL, - info->keep_memory); - if (relstart == NULL) + toc_relocs = _bfd_elf_link_read_relocs (ibfd, toc, NULL, NULL, + info->keep_memory); + if (toc_relocs == NULL) goto error_ret; - for (rel = relstart; rel < relstart + toc->reloc_count; ++rel) + for (rel = toc_relocs; rel < toc_relocs + toc->reloc_count; ++rel) { enum elf_ppc64_reloc_type r_type; unsigned long r_symndx; @@ -8040,6 +8041,10 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) r_symndx, ibfd)) goto error_ret; + if (sym_sec == NULL + || elf_discarded_section (sym_sec)) + continue; + if (!SYMBOL_CALLS_LOCAL (info, h)) continue; @@ -8078,11 +8083,8 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) } skip[rel->r_offset >> 3] - |= can_optimize | ((rel - relstart) << 2); + |= can_optimize | ((rel - toc_relocs) << 2); } - - if (elf_section_data (toc)->relocs != relstart) - free (relstart); } if (skip == NULL) @@ -8099,6 +8101,9 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) && relstart != NULL && elf_section_data (sec)->relocs != relstart) free (relstart); + if (toc_relocs != NULL + && elf_section_data (toc)->relocs != toc_relocs) + free (toc_relocs); if (skip != NULL) free (skip); return FALSE; @@ -8338,7 +8343,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) else if ((skip[val >> 3] & can_optimize) != 0) { Elf_Internal_Rela *tocrel - = elf_section_data (toc)->relocs + (skip[val >> 3] >> 2); + = toc_relocs + (skip[val >> 3] >> 2); unsigned long tsym = ELF64_R_SYM (tocrel->r_info); switch (r_type) @@ -8418,15 +8423,9 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) Elf_Internal_Rela *wrel; bfd_size_type sz; - /* Read toc relocs. */ - relstart = _bfd_elf_link_read_relocs (ibfd, toc, NULL, NULL, - TRUE); - if (relstart == NULL) - goto error_ret; - /* Remove unused toc relocs, and adjust those we keep. */ - wrel = relstart; - for (rel = relstart; rel < relstart + toc->reloc_count; ++rel) + wrel = toc_relocs; + for (rel = toc_relocs; rel < toc_relocs + toc->reloc_count; ++rel) if ((skip[rel->r_offset >> 3] & (ref_from_discarded | can_optimize)) == 0) { @@ -8439,12 +8438,15 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) &local_syms, NULL, NULL)) goto error_ret; - toc->reloc_count = wrel - relstart; + elf_section_data (toc)->relocs = toc_relocs; + toc->reloc_count = wrel - toc_relocs; rel_hdr = _bfd_elf_single_rel_hdr (toc); sz = rel_hdr->sh_entsize; rel_hdr->sh_size = toc->reloc_count * sz; } } + else if (elf_section_data (toc)->relocs != toc_relocs) + free (toc_relocs); if (local_syms != NULL && symtab_hdr->contents != (unsigned char *) local_syms)