diff options
author | Alan Modra <amodra@gmail.com> | 2014-10-16 09:38:09 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2014-10-16 11:22:14 +1030 |
commit | 459609d6f8f65d4b4440385499b84cc8c1804f65 (patch) | |
tree | 4d10b3336f05717fd4eb4a5554a3e245b635008b /bfd/elf64-ppc.c | |
parent | 983037647b9ffd052df16fb8e6abfe7e3e8c0683 (diff) | |
download | gdb-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.c | 126 |
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) |