mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-18 12:24:38 +08:00
* 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.
This commit is contained in:
parent
4fdf02beb7
commit
425b145b6e
@ -1,3 +1,9 @@
|
|||||||
|
2011-02-09 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* 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 <nickc@redhat.com>
|
2011-02-08 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
PR binutils/12467
|
PR binutils/12467
|
||||||
|
@ -7907,7 +7907,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
|
|||||||
asection *toc, *sec;
|
asection *toc, *sec;
|
||||||
Elf_Internal_Shdr *symtab_hdr;
|
Elf_Internal_Shdr *symtab_hdr;
|
||||||
Elf_Internal_Sym *local_syms;
|
Elf_Internal_Sym *local_syms;
|
||||||
Elf_Internal_Rela *relstart, *rel;
|
Elf_Internal_Rela *relstart, *rel, *toc_relocs;
|
||||||
unsigned long *skip, *drop;
|
unsigned long *skip, *drop;
|
||||||
unsigned char *used;
|
unsigned char *used;
|
||||||
unsigned char *keep, last, some_unused;
|
unsigned char *keep, last, some_unused;
|
||||||
@ -7922,6 +7922,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
|
|||||||
|| elf_discarded_section (toc))
|
|| elf_discarded_section (toc))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
toc_relocs = NULL;
|
||||||
local_syms = NULL;
|
local_syms = NULL;
|
||||||
symtab_hdr = &elf_symtab_hdr (ibfd);
|
symtab_hdr = &elf_symtab_hdr (ibfd);
|
||||||
|
|
||||||
@ -8017,12 +8018,12 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
|
|||||||
&& toc->reloc_count != 0)
|
&& toc->reloc_count != 0)
|
||||||
{
|
{
|
||||||
/* Read toc relocs. */
|
/* Read toc relocs. */
|
||||||
relstart = _bfd_elf_link_read_relocs (ibfd, toc, NULL, NULL,
|
toc_relocs = _bfd_elf_link_read_relocs (ibfd, toc, NULL, NULL,
|
||||||
info->keep_memory);
|
info->keep_memory);
|
||||||
if (relstart == NULL)
|
if (toc_relocs == NULL)
|
||||||
goto error_ret;
|
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;
|
enum elf_ppc64_reloc_type r_type;
|
||||||
unsigned long r_symndx;
|
unsigned long r_symndx;
|
||||||
@ -8040,6 +8041,10 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
|
|||||||
r_symndx, ibfd))
|
r_symndx, ibfd))
|
||||||
goto error_ret;
|
goto error_ret;
|
||||||
|
|
||||||
|
if (sym_sec == NULL
|
||||||
|
|| elf_discarded_section (sym_sec))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!SYMBOL_CALLS_LOCAL (info, h))
|
if (!SYMBOL_CALLS_LOCAL (info, h))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -8078,11 +8083,8 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
skip[rel->r_offset >> 3]
|
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)
|
if (skip == NULL)
|
||||||
@ -8099,6 +8101,9 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
|
|||||||
&& relstart != NULL
|
&& relstart != NULL
|
||||||
&& elf_section_data (sec)->relocs != relstart)
|
&& elf_section_data (sec)->relocs != relstart)
|
||||||
free (relstart);
|
free (relstart);
|
||||||
|
if (toc_relocs != NULL
|
||||||
|
&& elf_section_data (toc)->relocs != toc_relocs)
|
||||||
|
free (toc_relocs);
|
||||||
if (skip != NULL)
|
if (skip != NULL)
|
||||||
free (skip);
|
free (skip);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -8338,7 +8343,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
|
|||||||
else if ((skip[val >> 3] & can_optimize) != 0)
|
else if ((skip[val >> 3] & can_optimize) != 0)
|
||||||
{
|
{
|
||||||
Elf_Internal_Rela *tocrel
|
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);
|
unsigned long tsym = ELF64_R_SYM (tocrel->r_info);
|
||||||
|
|
||||||
switch (r_type)
|
switch (r_type)
|
||||||
@ -8418,15 +8423,9 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
|
|||||||
Elf_Internal_Rela *wrel;
|
Elf_Internal_Rela *wrel;
|
||||||
bfd_size_type sz;
|
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. */
|
/* Remove unused toc relocs, and adjust those we keep. */
|
||||||
wrel = relstart;
|
wrel = toc_relocs;
|
||||||
for (rel = relstart; rel < relstart + toc->reloc_count; ++rel)
|
for (rel = toc_relocs; rel < toc_relocs + toc->reloc_count; ++rel)
|
||||||
if ((skip[rel->r_offset >> 3]
|
if ((skip[rel->r_offset >> 3]
|
||||||
& (ref_from_discarded | can_optimize)) == 0)
|
& (ref_from_discarded | can_optimize)) == 0)
|
||||||
{
|
{
|
||||||
@ -8439,12 +8438,15 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
|
|||||||
&local_syms, NULL, NULL))
|
&local_syms, NULL, NULL))
|
||||||
goto error_ret;
|
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);
|
rel_hdr = _bfd_elf_single_rel_hdr (toc);
|
||||||
sz = rel_hdr->sh_entsize;
|
sz = rel_hdr->sh_entsize;
|
||||||
rel_hdr->sh_size = toc->reloc_count * sz;
|
rel_hdr->sh_size = toc->reloc_count * sz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (elf_section_data (toc)->relocs != toc_relocs)
|
||||||
|
free (toc_relocs);
|
||||||
|
|
||||||
if (local_syms != NULL
|
if (local_syms != NULL
|
||||||
&& symtab_hdr->contents != (unsigned char *) local_syms)
|
&& symtab_hdr->contents != (unsigned char *) local_syms)
|
||||||
|
Loading…
Reference in New Issue
Block a user