aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-ppc.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2011-02-09 08:16:00 +0000
committerAlan Modra <amodra@gmail.com>2011-02-09 08:16:00 +0000
commit425b145b6ec65eefa2c23131c7c9997f08ebf88c (patch)
treecbb48605c5de7dd01c42bcbbf162d03e73970a10 /bfd/elf64-ppc.c
parent4fdf02beb7634e541bf9f9ba9a65331722067c87 (diff)
downloadgdb-425b145b6ec65eefa2c23131c7c9997f08ebf88c.zip
gdb-425b145b6ec65eefa2c23131c7c9997f08ebf88c.tar.gz
gdb-425b145b6ec65eefa2c23131c7c9997f08ebf88c.tar.bz2
* 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.
Diffstat (limited to 'bfd/elf64-ppc.c')
-rw-r--r--bfd/elf64-ppc.c40
1 files changed, 21 insertions, 19 deletions
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 4e85e90..25d0d2e 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)