X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fecoff.c;h=4515172983df19c86be9e5ded3b15939b69f2105;hb=ef53be89160126f2fa5dec8f1ec3bd6d99fb0681;hp=cf38e3ef7b87b8b8c73ac079946c9b8bc4d7a999;hpb=c72f2fb2bb6a3e1850b081dbfce4040970fae8e6;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/ecoff.c b/bfd/ecoff.c index cf38e3ef7b..4515172983 100644 --- a/bfd/ecoff.c +++ b/bfd/ecoff.c @@ -1,5 +1,5 @@ /* Generic ECOFF (Extended-COFF) routines. - Copyright (C) 1990-2014 Free Software Foundation, Inc. + Copyright (C) 1990-2016 Free Software Foundation, Inc. Original version by Per Bothner. Full support added by Ian Lance Taylor, ian@cygnus.com. @@ -504,7 +504,6 @@ _bfd_ecoff_slurp_symbolic_info (bfd *abfd, struct fdr *fdr_ptr; bfd_size_type raw_end; bfd_size_type cb_end; - bfd_size_type amt; file_ptr pos; BFD_ASSERT (debug == &ecoff_data (abfd)->debug_info); @@ -607,14 +606,16 @@ _bfd_ecoff_slurp_symbolic_info (bfd *abfd, We need to look at the fdr to deal with a lot of information in the symbols, so we swap them here. */ - amt = internal_symhdr->ifdMax; - amt *= sizeof (struct fdr); - debug->fdr = (FDR *) bfd_alloc (abfd, amt); + debug->fdr = (FDR *) bfd_alloc2 (abfd, internal_symhdr->ifdMax, + sizeof (struct fdr)); if (debug->fdr == NULL) return FALSE; external_fdr_size = backend->debug_swap.external_fdr_size; fdr_ptr = debug->fdr; fraw_src = (char *) debug->external_fdr; + /* PR 17512: file: 3372-1243-0.004. */ + if (fraw_src == NULL && internal_symhdr->ifdMax > 0) + return FALSE; fraw_end = fraw_src + internal_symhdr->ifdMax * external_fdr_size; for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++) (*backend->debug_swap.swap_fdr_in) (abfd, (void *) fraw_src, fdr_ptr); @@ -856,7 +857,6 @@ _bfd_ecoff_slurp_symbol_table (bfd *abfd) = backend->debug_swap.swap_ext_in; void (* const swap_sym_in) (bfd *, void *, SYMR *) = backend->debug_swap.swap_sym_in; - bfd_size_type internal_size; ecoff_symbol_type *internal; ecoff_symbol_type *internal_ptr; char *eraw_src; @@ -875,9 +875,8 @@ _bfd_ecoff_slurp_symbol_table (bfd *abfd) if (bfd_get_symcount (abfd) == 0) return TRUE; - internal_size = bfd_get_symcount (abfd); - internal_size *= sizeof (ecoff_symbol_type); - internal = (ecoff_symbol_type *) bfd_alloc (abfd, internal_size); + internal = (ecoff_symbol_type *) bfd_alloc2 (abfd, bfd_get_symcount (abfd), + sizeof (ecoff_symbol_type)); if (internal == NULL) return FALSE; @@ -891,16 +890,30 @@ _bfd_ecoff_slurp_symbol_table (bfd *abfd) EXTR internal_esym; (*swap_ext_in) (abfd, (void *) eraw_src, &internal_esym); + + /* PR 17512: file: 3372-1000-0.004. */ + if (internal_esym.asym.iss >= ecoff_data (abfd)->debug_info.symbolic_header.issExtMax + || internal_esym.asym.iss < 0) + return FALSE; + internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ssext + internal_esym.asym.iss); + if (!ecoff_set_symbol_info (abfd, &internal_esym.asym, &internal_ptr->symbol, 1, internal_esym.weakext)) return FALSE; + /* The alpha uses a negative ifd field for section symbols. */ if (internal_esym.ifd >= 0) - internal_ptr->fdr = (ecoff_data (abfd)->debug_info.fdr - + internal_esym.ifd); + { + /* PR 17512: file: 3372-1983-0.004. */ + if (internal_esym.ifd >= ecoff_data (abfd)->debug_info.symbolic_header.ifdMax) + internal_ptr->fdr = NULL; + else + internal_ptr->fdr = (ecoff_data (abfd)->debug_info.fdr + + internal_esym.ifd); + } else internal_ptr->fdr = NULL; internal_ptr->local = FALSE; @@ -938,6 +951,20 @@ _bfd_ecoff_slurp_symbol_table (bfd *abfd) } } + /* PR 17512: file: 3372-3080-0.004. + A discrepancy between ecoff_data (abfd)->debug_info.symbolic_header.isymMax + and ecoff_data (abfd)->debug_info.symbolic_header.ifdMax can mean that + we have fewer symbols than we were expecting. Allow for this by updating + the symbol count and warning the user. */ + if (internal_ptr - internal < (ptrdiff_t) bfd_get_symcount (abfd)) + { + bfd_get_symcount (abfd) = internal_ptr - internal; + (*_bfd_error_handler) + (_("%B: warning: isymMax (%ld) is greater than ifdMax (%d)\n"), + abfd, ecoff_data (abfd)->debug_info.symbolic_header.isymMax, + ecoff_data (abfd)->debug_info.symbolic_header.ifdMax); + } + ecoff_data (abfd)->canonical_symbols = internal; return TRUE; @@ -1704,12 +1731,13 @@ _bfd_ecoff_canonicalize_reloc (bfd *abfd, bfd_boolean _bfd_ecoff_find_nearest_line (bfd *abfd, + asymbol **symbols ATTRIBUTE_UNUSED, asection *section, - asymbol **ignore_symbols ATTRIBUTE_UNUSED, bfd_vma offset, const char **filename_ptr, const char **functionname_ptr, - unsigned int *retline_ptr) + unsigned int *retline_ptr, + unsigned int *discriminator_ptr) { const struct ecoff_debug_swap * const debug_swap = &ecoff_backend (abfd)->debug_swap; @@ -1730,8 +1758,10 @@ _bfd_ecoff_find_nearest_line (bfd *abfd, if (ecoff_data (abfd)->find_line_info == NULL) return FALSE; } - line_info = ecoff_data (abfd)->find_line_info; + if (discriminator_ptr) + *discriminator_ptr = 0; + line_info = ecoff_data (abfd)->find_line_info; return _bfd_ecoff_locate_line (abfd, section, offset, debug_info, debug_swap, line_info, filename_ptr, functionname_ptr, retline_ptr); @@ -3497,171 +3527,29 @@ ecoff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) return FALSE; } -/* Factored out from ecoff_link_check_archive_element. */ - -static bfd_boolean -read_ext_syms_and_strs (HDRR **symhdr, bfd_size_type *external_ext_size, - bfd_size_type *esize, void **external_ext, char **ssext, bfd *abfd, - const struct ecoff_backend_data * const backend) -{ - if (! ecoff_slurp_symbolic_header (abfd)) - return FALSE; - - /* If there are no symbols, we don't want it. */ - if (bfd_get_symcount (abfd) == 0) - return TRUE; - - *symhdr = &ecoff_data (abfd)->debug_info.symbolic_header; - - *external_ext_size = backend->debug_swap.external_ext_size; - *esize = (*symhdr)->iextMax * *external_ext_size; - *external_ext = bfd_malloc (*esize); - if (*external_ext == NULL && *esize != 0) - return FALSE; - - if (bfd_seek (abfd, (file_ptr) (*symhdr)->cbExtOffset, SEEK_SET) != 0 - || bfd_bread (*external_ext, *esize, abfd) != *esize) - return FALSE; - - *ssext = (char *) bfd_malloc ((bfd_size_type) (*symhdr)->issExtMax); - if (*ssext == NULL && (*symhdr)->issExtMax != 0) - return FALSE; - - if (bfd_seek (abfd, (file_ptr) (*symhdr)->cbSsExtOffset, SEEK_SET) != 0 - || (bfd_bread (*ssext, (bfd_size_type) (*symhdr)->issExtMax, abfd) - != (bfd_size_type) (*symhdr)->issExtMax)) - return FALSE; - return TRUE; -} - -static bfd_boolean -reread_ext_syms_and_strs (HDRR **symhdr, bfd_size_type *external_ext_size, - bfd_size_type *esize, void **external_ext, char **ssext, bfd *abfd, - const struct ecoff_backend_data * const backend) -{ - if (*external_ext != NULL) - free (*external_ext); - *external_ext = NULL; - if (*ssext != NULL) - free (*ssext); - *ssext = NULL; - return read_ext_syms_and_strs (symhdr, external_ext_size, esize, - external_ext, ssext, abfd, backend); -} - /* This is called if we used _bfd_generic_link_add_archive_symbols because we were not dealing with an ECOFF archive. */ static bfd_boolean ecoff_link_check_archive_element (bfd *abfd, struct bfd_link_info *info, + struct bfd_link_hash_entry *h, + const char *name, bfd_boolean *pneeded) { - const struct ecoff_backend_data * const backend = ecoff_backend (abfd); - void (* const swap_ext_in) (bfd *, void *, EXTR *) - = backend->debug_swap.swap_ext_in; - HDRR *symhdr; - bfd_size_type external_ext_size = 0; - void * external_ext = NULL; - bfd_size_type esize = 0; - char *ssext = NULL; - char *ext_ptr; - char *ext_end; - *pneeded = FALSE; - /* Read in the external symbols and external strings. */ - if (!read_ext_syms_and_strs (&symhdr, &external_ext_size, &esize, - &external_ext, &ssext, abfd, backend)) - goto error_return; - - /* If there are no symbols, we don't want it. */ - if (bfd_get_symcount (abfd) == 0) - goto successful_return; - - /* Look through the external symbols to see if they define some - symbol that is currently undefined. */ - ext_ptr = (char *) external_ext; - ext_end = ext_ptr + esize; - for (; ext_ptr < ext_end; ext_ptr += external_ext_size) - { - EXTR esym; - bfd_boolean def; - const char *name; - bfd *oldbfd; - struct bfd_link_hash_entry *h; - - (*swap_ext_in) (abfd, (void *) ext_ptr, &esym); - - /* See if this symbol defines something. */ - if (esym.asym.st != stGlobal - && esym.asym.st != stLabel - && esym.asym.st != stProc) - continue; - - switch (esym.asym.sc) - { - case scText: - case scData: - case scBss: - case scAbs: - case scSData: - case scSBss: - case scRData: - case scCommon: - case scSCommon: - case scInit: - case scFini: - case scRConst: - def = TRUE; - break; - default: - def = FALSE; - break; - } - - if (! def) - continue; - - name = ssext + esym.asym.iss; - h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE); - - /* Unlike the generic linker, we do not pull in elements because - of common symbols. */ - if (h == NULL - || h->type != bfd_link_hash_undefined) - continue; - - /* Include this element. */ - oldbfd = abfd; - if (!(*info->callbacks - ->add_archive_element) (info, abfd, name, &abfd)) - goto error_return; - /* Potentially, the add_archive_element hook may have set a - substitute BFD for us. */ - if (abfd != oldbfd - && !reread_ext_syms_and_strs (&symhdr, &external_ext_size, &esize, - &external_ext, &ssext, abfd, backend)) - goto error_return; - if (! ecoff_link_add_externals (abfd, info, external_ext, ssext)) - goto error_return; + /* Unlike the generic linker, we do not pull in elements because + of common symbols. */ + if (h->type != bfd_link_hash_undefined) + return TRUE; - *pneeded = TRUE; - goto successful_return; - } + /* Include this element? */ + if (!(*info->callbacks->add_archive_element) (info, abfd, name, &abfd)) + return TRUE; + *pneeded = TRUE; - successful_return: - if (external_ext != NULL) - free (external_ext); - if (ssext != NULL) - free (ssext); - return TRUE; - error_return: - if (external_ext != NULL) - free (external_ext); - if (ssext != NULL) - free (ssext); - return FALSE; + return ecoff_link_add_object_symbols (abfd, info); } /* Add the symbols from an archive file to the global hash table. @@ -4008,7 +3896,7 @@ ecoff_indirect_link_order (bfd *output_bfd, modified, and we write them out now. We use the reloc_count field of output_section to keep track of the number of relocs we have output so far. */ - if (info->relocatable) + if (bfd_link_relocatable (info)) { file_ptr pos = (output_section->rel_filepos + output_section->reloc_count * external_reloc_size); @@ -4115,7 +4003,7 @@ ecoff_reloc_link_order (bfd *output_bfd, size = bfd_get_reloc_size (rel.howto); buf = (bfd_byte *) bfd_zmalloc (size); - if (buf == NULL) + if (buf == NULL && size != 0) return FALSE; rstat = _bfd_relocate_contents (rel.howto, output_bfd, (bfd_vma) addend, buf); @@ -4127,17 +4015,12 @@ ecoff_reloc_link_order (bfd *output_bfd, case bfd_reloc_outofrange: abort (); case bfd_reloc_overflow: - if (! ((*info->callbacks->reloc_overflow) - (info, NULL, - (link_order->type == bfd_section_reloc_link_order - ? bfd_section_name (output_bfd, section) - : link_order->u.reloc.p->u.name), - rel.howto->name, addend, NULL, - NULL, (bfd_vma) 0))) - { - free (buf); - return FALSE; - } + (*info->callbacks->reloc_overflow) + (info, NULL, + (link_order->type == bfd_section_reloc_link_order + ? bfd_section_name (output_bfd, section) + : link_order->u.reloc.p->u.name), + rel.howto->name, addend, NULL, NULL, (bfd_vma) 0); break; } ok = bfd_set_section_contents (output_bfd, output_section, (void *) buf, @@ -4167,10 +4050,8 @@ ecoff_reloc_link_order (bfd *output_bfd, in.r_symndx = h->indx; else { - if (! ((*info->callbacks->unattached_reloc) - (info, link_order->u.reloc.p->u.name, NULL, - NULL, (bfd_vma) 0))) - return FALSE; + (*info->callbacks->unattached_reloc) + (info, link_order->u.reloc.p->u.name, NULL, NULL, (bfd_vma) 0); in.r_symndx = 0; } in.r_extern = 1; @@ -4482,7 +4363,7 @@ _bfd_ecoff_bfd_final_link (bfd *abfd, struct bfd_link_info *info) einfo.info = info; bfd_hash_traverse (&info->hash->table, ecoff_link_write_external, &einfo); - if (info->relocatable) + if (bfd_link_relocatable (info)) { /* We need to make a pass over the link_orders to count up the number of relocations we will need to output, so that we know @@ -4512,7 +4393,7 @@ _bfd_ecoff_bfd_final_link (bfd *abfd, struct bfd_link_info *info) bfd_ecoff_debug_free (handle, abfd, debug, &backend->debug_swap, info); - if (info->relocatable) + if (bfd_link_relocatable (info)) { /* Now reset the reloc_count field of the sections in the output BFD to 0, so that we can use them to keep track of how many @@ -4532,7 +4413,7 @@ _bfd_ecoff_bfd_final_link (bfd *abfd, struct bfd_link_info *info) ecoff_data (abfd)->gp = (h->u.def.value + h->u.def.section->output_section->vma + h->u.def.section->output_offset); - else if (info->relocatable) + else if (bfd_link_relocatable (info)) { bfd_vma lo;