From 16bfc7bb18b272d5a4e40ee37ced21e4b9a8fbb4 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 16 Oct 2014 09:38:09 +1030 Subject: [PATCH] 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. --- bfd/ChangeLog | 5 ++ bfd/elf64-ppc.c | 126 +++++++++++++++++++++++------------------------ ld/ChangeLog | 8 +++ ld/emultempl/ppc64elf.em | 3 +- 4 files changed, 76 insertions(+), 66 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index aa6ea5b..9727555 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,6 +1,11 @@ 2014-10-28 Alan Modra Apply trunk patches + 2014-10-16 Alan Modra + * 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. + 2014-10-15 Alan Modra PR 17481 * aoutx.h (NAME (aout, find_nearest_line)): Add "discriminator_ptr" 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) diff --git a/ld/ChangeLog b/ld/ChangeLog index 27da9d4..a1ec84f 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,11 @@ +2014-10-28 Alan Modra + + Apply trunk patches + 2014-10-16 Alan Modra + PR 17488 + * emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Don't attempt + to access ELF header e_flags when not ppc64 ELF output. + 2014-10-24 Tejas Belagod * emultempl/aarch64elf.em: Add command-line option for erratum diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em index 914fc52..59ea786 100644 --- a/ld/emultempl/ppc64elf.em +++ b/ld/emultempl/ppc64elf.em @@ -531,7 +531,8 @@ gld${EMULATION_NAME}_finish (void) /* e_entry on PowerPC64 points to the function descriptor for _start. If _start is missing, default to the first function descriptor in the .opd section. */ - if ((elf_elfheader (link_info.output_bfd)->e_flags & EF_PPC64_ABI) == 1) + if (stub_file != NULL + && (elf_elfheader (link_info.output_bfd)->e_flags & EF_PPC64_ABI) == 1) entry_section = ".opd"; if (params.emit_stub_syms < 0) -- 2.7.4