aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-ppc.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2014-10-16 09:38:09 +1030
committerAlan Modra <amodra@gmail.com>2014-10-16 11:22:14 +1030
commit459609d6f8f65d4b4440385499b84cc8c1804f65 (patch)
tree4d10b3336f05717fd4eb4a5554a3e245b635008b /bfd/elf64-ppc.c
parent983037647b9ffd052df16fb8e6abfe7e3e8c0683 (diff)
downloadgdb-459609d6f8f65d4b4440385499b84cc8c1804f65.zip
gdb-459609d6f8f65d4b4440385499b84cc8c1804f65.tar.gz
gdb-459609d6f8f65d4b4440385499b84cc8c1804f65.tar.bz2
PR17488, powerpc64-linux-ld segfault
For binary ouput, we don't have an ELF bfd output so can't access elf_elfheader. The elf64-ppc.c changes are really just a tidy, triggered by looking at all places where the abiversion bits are accessed. bfd/ * elf64-ppc.c (ppc64_elf_before_check_relocs): Do .opd processing even when output is not ppc64 ELF. Remove redundant tests on type of input bfd. ld/ PR 17488 * emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Don't attempt to access ELF header e_flags when not ppc64 ELF output.
Diffstat (limited to 'bfd/elf64-ppc.c')
-rw-r--r--bfd/elf64-ppc.c126
1 files changed, 61 insertions, 65 deletions
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 123a33a..974f992 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -4962,81 +4962,77 @@ ppc64_elf_before_check_relocs (bfd *ibfd, struct bfd_link_info *info)
{
struct ppc_link_hash_table *htab;
struct ppc_link_hash_entry **p, *eh;
+ asection *opd = bfd_get_section_by_name (ibfd, ".opd");
- if (!is_ppc64_elf (info->output_bfd))
- return TRUE;
- htab = ppc_hash_table (info);
- if (htab == NULL)
- return FALSE;
-
- if (is_ppc64_elf (ibfd))
+ if (opd != NULL && opd->size != 0)
{
- asection *opd = bfd_get_section_by_name (ibfd, ".opd");
-
- if (opd != NULL && opd->size != 0)
+ if (abiversion (ibfd) == 0)
+ set_abiversion (ibfd, 1);
+ else if (abiversion (ibfd) == 2)
{
- if (abiversion (ibfd) == 0)
- set_abiversion (ibfd, 1);
- else if (abiversion (ibfd) == 2)
- {
- info->callbacks->einfo (_("%P: %B .opd not allowed in ABI"
- " version %d\n"),
- ibfd, abiversion (ibfd));
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
-
- if ((ibfd->flags & DYNAMIC) == 0
- && (opd->flags & SEC_RELOC) != 0
- && opd->reloc_count != 0
- && !bfd_is_abs_section (opd->output_section))
- {
- /* Garbage collection needs some extra help with .opd sections.
- We don't want to necessarily keep everything referenced by
- relocs in .opd, as that would keep all functions. Instead,
- if we reference an .opd symbol (a function descriptor), we
- want to keep the function code symbol's section. This is
- easy for global symbols, but for local syms we need to keep
- information about the associated function section. */
- bfd_size_type amt;
- asection **opd_sym_map;
-
- amt = opd->size * sizeof (*opd_sym_map) / 8;
- opd_sym_map = bfd_zalloc (ibfd, amt);
- if (opd_sym_map == NULL)
- return FALSE;
- ppc64_elf_section_data (opd)->u.opd.func_sec = opd_sym_map;
- BFD_ASSERT (ppc64_elf_section_data (opd)->sec_type == sec_normal);
- ppc64_elf_section_data (opd)->sec_type = sec_opd;
- }
+ info->callbacks->einfo (_("%P: %B .opd not allowed in ABI"
+ " version %d\n"),
+ ibfd, abiversion (ibfd));
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
}
- /* For input files without an explicit abiversion in e_flags
- we should have flagged any with symbol st_other bits set
- as ELFv1 and above flagged those with .opd as ELFv2.
- Set the output abiversion if not yet set, and for any input
- still ambiguous, take its abiversion from the output.
- Differences in ABI are reported later. */
- if (abiversion (info->output_bfd) == 0)
- set_abiversion (info->output_bfd, abiversion (ibfd));
- else if (abiversion (ibfd) == 0)
- set_abiversion (ibfd, abiversion (info->output_bfd));
-
- p = &htab->dot_syms;
- while ((eh = *p) != NULL)
+ if ((ibfd->flags & DYNAMIC) == 0
+ && (opd->flags & SEC_RELOC) != 0
+ && opd->reloc_count != 0
+ && !bfd_is_abs_section (opd->output_section))
{
- *p = NULL;
- if (&eh->elf == htab->elf.hgot)
- ;
- else if (htab->elf.hgot == NULL
- && strcmp (eh->elf.root.root.string, ".TOC.") == 0)
- htab->elf.hgot = &eh->elf;
- else if (!add_symbol_adjust (eh, info))
+ /* Garbage collection needs some extra help with .opd sections.
+ We don't want to necessarily keep everything referenced by
+ relocs in .opd, as that would keep all functions. Instead,
+ if we reference an .opd symbol (a function descriptor), we
+ want to keep the function code symbol's section. This is
+ easy for global symbols, but for local syms we need to keep
+ information about the associated function section. */
+ bfd_size_type amt;
+ asection **opd_sym_map;
+
+ amt = opd->size * sizeof (*opd_sym_map) / 8;
+ opd_sym_map = bfd_zalloc (ibfd, amt);
+ if (opd_sym_map == NULL)
return FALSE;
- p = &eh->u.next_dot_sym;
+ ppc64_elf_section_data (opd)->u.opd.func_sec = opd_sym_map;
+ BFD_ASSERT (ppc64_elf_section_data (opd)->sec_type == sec_normal);
+ ppc64_elf_section_data (opd)->sec_type = sec_opd;
}
}
+ if (!is_ppc64_elf (info->output_bfd))
+ return TRUE;
+ htab = ppc_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
+ /* For input files without an explicit abiversion in e_flags
+ we should have flagged any with symbol st_other bits set
+ as ELFv1 and above flagged those with .opd as ELFv2.
+ Set the output abiversion if not yet set, and for any input
+ still ambiguous, take its abiversion from the output.
+ Differences in ABI are reported later. */
+ if (abiversion (info->output_bfd) == 0)
+ set_abiversion (info->output_bfd, abiversion (ibfd));
+ else if (abiversion (ibfd) == 0)
+ set_abiversion (ibfd, abiversion (info->output_bfd));
+
+ p = &htab->dot_syms;
+ while ((eh = *p) != NULL)
+ {
+ *p = NULL;
+ if (&eh->elf == htab->elf.hgot)
+ ;
+ else if (htab->elf.hgot == NULL
+ && strcmp (eh->elf.root.root.string, ".TOC.") == 0)
+ htab->elf.hgot = &eh->elf;
+ else if (!add_symbol_adjust (eh, info))
+ return FALSE;
+ p = &eh->u.next_dot_sym;
+ }
+
/* Clear the list for non-ppc64 input files. */
p = &htab->dot_syms;
while ((eh = *p) != NULL)