X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fcoffgen.c;h=9e62feb65ce50e06d11a5fe7526a2a9b2a81f35d;hb=c8e98e3692cec125b92c995d8f881d9bdf1fac00;hp=3c60ed438f6ca349a35d34c132a91e32643289f7;hpb=e643cb45bf85fa5c8c49a89ff177de246af4212e;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/coffgen.c b/bfd/coffgen.c index 3c60ed438f..9e62feb65c 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -1,5 +1,5 @@ /* Support for the generic parts of COFF, for BFD. - Copyright (C) 1990-2017 Free Software Foundation, Inc. + Copyright (C) 1990-2018 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -72,9 +72,9 @@ make_a_section_from_file (bfd *abfd, const char *strings; /* Flag that this BFD uses long names, even though the format might - expect them to be off by default. This won't directly affect the - format of any output BFD created from this one, but the information - can be used to decide what to do. */ + expect them to be off by default. This won't directly affect the + format of any output BFD created from this one, but the information + can be used to decide what to do. */ bfd_coff_set_long_section_names (abfd, TRUE); memcpy (buf, hdr->s_name + 1, SCNNMLEN - 1); buf[SCNNMLEN - 1] = '\0'; @@ -88,7 +88,7 @@ make_a_section_from_file (bfd *abfd, return FALSE; strings += strindex; name = (char *) bfd_alloc (abfd, - (bfd_size_type) strlen (strings) + 1 + 1); + (bfd_size_type) strlen (strings) + 1 + 1); if (name == NULL) return FALSE; strcpy (name, strings); @@ -99,7 +99,7 @@ make_a_section_from_file (bfd *abfd, { /* Assorted wastage to null-terminate the name, thanks AT&T! */ name = (char *) bfd_alloc (abfd, - (bfd_size_type) sizeof (hdr->s_name) + 1 + 1); + (bfd_size_type) sizeof (hdr->s_name) + 1 + 1); if (name == NULL) return FALSE; strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name)); @@ -175,7 +175,7 @@ make_a_section_from_file (bfd *abfd, { _bfd_error_handler /* xgettext: c-format */ - (_("%B: unable to initialize compress status for section %s"), + (_("%pB: unable to initialize compress status for section %s"), abfd, name); return FALSE; } @@ -193,13 +193,13 @@ make_a_section_from_file (bfd *abfd, memcpy (new_name + 2, name + 1, len); } } - break; + break; case decompress: if (!bfd_init_section_decompress_status (abfd, return_section)) { _bfd_error_handler /* xgettext: c-format */ - (_("%B: unable to initialize decompress status for section %s"), + (_("%pB: unable to initialize decompress status for section %s"), abfd, name); return FALSE; } @@ -226,9 +226,9 @@ make_a_section_from_file (bfd *abfd, ECOFF as well. */ const bfd_target * coff_real_object_p (bfd *, - unsigned, - struct internal_filehdr *, - struct internal_aouthdr *); + unsigned, + struct internal_filehdr *, + struct internal_aouthdr *); const bfd_target * coff_real_object_p (bfd *abfd, unsigned nscns, @@ -595,7 +595,7 @@ coff_count_linenumbers (bfd *abfd) if (limit == 0) { /* This may be from the backend linker, in which case the - lineno_count in the sections is correct. */ + lineno_count in the sections is correct. */ for (s = abfd->sections; s != NULL; s = s->next) total += s->lineno_count; return total; @@ -613,13 +613,13 @@ coff_count_linenumbers (bfd *abfd) coff_symbol_type *q = coffsymbol (q_maybe); /* The AIX 4.1 compiler can sometimes generate line numbers - attached to debugging symbols. We try to simply ignore - those here. */ + attached to debugging symbols. We try to simply ignore + those here. */ if (q->lineno != NULL && q->symbol.section->owner != NULL) { /* This symbol has line numbers. Increment the owning - section's linenumber count. */ + section's linenumber count. */ alent *l = q->lineno; do @@ -675,11 +675,11 @@ fixup_symbol_value (bfd *abfd, syment->n_value = (coff_symbol_ptr->symbol.value + coff_symbol_ptr->symbol.section->output_offset); if (! obj_pe (abfd)) - { - syment->n_value += (syment->n_sclass == C_STATLAB) - ? coff_symbol_ptr->symbol.section->output_section->lma - : coff_symbol_ptr->symbol.section->output_section->vma; - } + { + syment->n_value += (syment->n_sclass == C_STATLAB) + ? coff_symbol_ptr->symbol.section->output_section->lma + : coff_symbol_ptr->symbol.section->output_section->vma; + } } else { @@ -823,8 +823,8 @@ coff_mangle_symbols (bfd *bfd_ptr) if (s->fix_line) { /* The value is the offset into the line number entries - for the symbol's section. On output, the symbol's - section should be N_DEBUG. */ + for the symbol's section. On output, the symbol's + section should be N_DEBUG. */ s->u.syment.n_value = (coff_symbol_ptr->symbol.section->output_section->line_filepos + s->u.syment.n_value * bfd_coff_linesz (bfd_ptr)); @@ -835,7 +835,7 @@ coff_mangle_symbols (bfd *bfd_ptr) for (i = 0; i < s->u.syment.n_numaux; i++) { combined_entry_type *a = s + i + 1; - + BFD_ASSERT (! a->is_sym); if (a->fix_tag) { @@ -888,13 +888,13 @@ coff_fix_symbol_name (bfd *abfd, if (bfd_coff_force_symnames_in_strings (abfd)) { - native->u.syment._n._n_n._n_offset = + native->u.syment._n._n_n._n_offset = (*string_size_p + STRING_SIZE_SIZE); native->u.syment._n._n_n._n_zeroes = 0; *string_size_p += 6; /* strlen(".file") + 1 */ } else - strncpy (native->u.syment._n._n_name, ".file", SYMNMLEN); + strncpy (native->u.syment._n._n_name, ".file", SYMNMLEN); BFD_ASSERT (! (native + 1)->is_sym); auxent = &(native + 1)->u.auxent; @@ -1088,7 +1088,7 @@ coff_write_alien_symbol (bfd *abfd, { symbol->name = ""; if (isym != NULL) - memset (isym, 0, sizeof (*isym)); + memset (isym, 0, sizeof (*isym)); return TRUE; } native = dummy; @@ -1115,12 +1115,12 @@ coff_write_alien_symbol (bfd *abfd, else if (symbol->flags & BSF_DEBUGGING) { /* There isn't much point to writing out a debugging symbol - unless we are prepared to convert it into COFF debugging - format. So, we just ignore them. We must clobber the symbol - name to keep it from being put in the string table. */ + unless we are prepared to convert it into COFF debugging + format. So, we just ignore them. We must clobber the symbol + name to keep it from being put in the string table. */ symbol->name = ""; if (isym != NULL) - memset (isym, 0, sizeof (*isym)); + memset (isym, 0, sizeof (*isym)); return TRUE; } else @@ -1132,7 +1132,7 @@ coff_write_alien_symbol (bfd *abfd, native->u.syment.n_value += output_section->vma; /* Copy the any flags from the file header into the symbol. - FIXME: Why? */ + FIXME: Why? */ { coff_symbol_type *c = coff_symbol_from (symbol); if (c != (coff_symbol_type *) NULL) @@ -1418,8 +1418,8 @@ coff_write_symbols (bfd *abfd) else { /* We would normally not write anything here, but we'll write - out 4 so that any stupid coff reader which tries to read the - string table even when there isn't one won't croak. */ + out 4 so that any stupid coff reader which tries to read the + string table even when there isn't one won't croak. */ unsigned int size = STRING_SIZE_SIZE; bfd_byte buffer[STRING_SIZE_SIZE]; @@ -1521,7 +1521,8 @@ coff_pointerize_aux (bfd *abfd, combined_entry_type *table_base, combined_entry_type *symbol, unsigned int indaux, - combined_entry_type *auxent) + combined_entry_type *auxent, + combined_entry_type *table_end) { unsigned int type = symbol->u.syment.n_type; unsigned int n_sclass = symbol->u.syment.n_sclass; @@ -1547,15 +1548,22 @@ coff_pointerize_aux (bfd *abfd, if ((ISFCN (type) || ISTAG (n_sclass) || n_sclass == C_BLOCK || n_sclass == C_FCN) - && auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l > 0) + && auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l > 0 + && auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l + < (long) obj_raw_syment_count (abfd) + && table_base + auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l + < table_end) { auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p = table_base + auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l; auxent->fix_end = 1; } + /* A negative tagndx is meaningless, but the SCO 3.2v4 cc can generate one, so we must be careful to ignore it. */ - if (auxent->u.auxent.x_sym.x_tagndx.l > 0) + if ((unsigned long) auxent->u.auxent.x_sym.x_tagndx.l + < obj_raw_syment_count (abfd) + && table_base + auxent->u.auxent.x_sym.x_tagndx.l < table_end) { auxent->u.auxent.x_sym.x_tagndx.p = table_base + auxent->u.auxent.x_sym.x_tagndx.l; @@ -1640,13 +1648,25 @@ _bfd_coff_get_external_symbols (bfd *abfd) size = obj_raw_syment_count (abfd) * symesz; if (size == 0) return TRUE; + /* Check for integer overflow and for unreasonable symbol counts. */ + if (size < obj_raw_syment_count (abfd) + || (bfd_get_file_size (abfd) > 0 + && size > bfd_get_file_size (abfd))) + + { + _bfd_error_handler (_("%pB: corrupt symbol count: %#" PRIx64 ""), + abfd, (uint64_t) obj_raw_syment_count (abfd)); + return FALSE; + } syms = bfd_malloc (size); if (syms == NULL) { /* PR 21013: Provide an error message when the alloc fails. */ - _bfd_error_handler (_("%B: Not enough memory to allocate space for %lu symbols"), - abfd, size); + _bfd_error_handler (_("%pB: not enough memory to allocate space " + "for %#" PRIx64 " symbols of size %#" PRIx64), + abfd, (uint64_t) obj_raw_syment_count (abfd), + (uint64_t) symesz); return FALSE; } @@ -1659,7 +1679,6 @@ _bfd_coff_get_external_symbols (bfd *abfd) } obj_coff_external_syms (abfd) = syms; - return TRUE; } @@ -1709,11 +1728,11 @@ _bfd_coff_read_string_table (bfd *abfd) #endif } - if (strsize < STRING_SIZE_SIZE) + if (strsize < STRING_SIZE_SIZE || strsize > bfd_get_file_size (abfd)) { _bfd_error_handler /* xgettext: c-format */ - (_("%B: bad string table size %lu"), abfd, (unsigned long) strsize); + (_("%pB: bad string table size %" PRIu64), abfd, (uint64_t) strsize); bfd_set_error (bfd_error_bad_value); return NULL; } @@ -1747,12 +1766,16 @@ _bfd_coff_read_string_table (bfd *abfd) bfd_boolean _bfd_coff_free_symbols (bfd *abfd) { + if (! bfd_family_coff (abfd)) + return FALSE; + if (obj_coff_external_syms (abfd) != NULL && ! obj_coff_keep_syms (abfd)) { free (obj_coff_external_syms (abfd)); obj_coff_external_syms (abfd) = NULL; } + if (obj_coff_strings (abfd) != NULL && ! obj_coff_keep_strings (abfd)) { @@ -1760,6 +1783,7 @@ _bfd_coff_free_symbols (bfd *abfd) obj_coff_strings (abfd) = NULL; obj_coff_strings_len (abfd) = 0; } + return TRUE; } @@ -1790,6 +1814,9 @@ coff_get_normalized_symtab (bfd *abfd) return NULL; size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type); + /* Check for integer overflow. */ + if (size < obj_raw_syment_count (abfd)) + return NULL; internal = (combined_entry_type *) bfd_zalloc (abfd, size); if (internal == NULL && size != 0) return NULL; @@ -1847,7 +1874,7 @@ coff_get_normalized_symtab (bfd *abfd) internal_ptr->is_sym = FALSE; coff_pointerize_aux (abfd, internal, symbol_ptr, i, - internal_ptr); + internal_ptr, internal_end); } } @@ -1890,8 +1917,8 @@ coff_get_normalized_symtab (bfd *abfd) else { /* Ordinary short filename, put into memory anyway. The - Microsoft PE tools sometimes store a filename in - multiple AUX entries. */ + Microsoft PE tools sometimes store a filename in + multiple AUX entries. */ if (internal_ptr->u.syment.n_numaux > 1 && coff_data (abfd)->pe) internal_ptr->u.syment._n._n_n._n_offset = @@ -1916,7 +1943,7 @@ coff_get_normalized_symtab (bfd *abfd) char *newstring; /* Find the length of this string without walking into memory - that isn't ours. */ + that isn't ours. */ for (i = 0; i < 8; ++i) if (internal_ptr->u.syment._n._n_name[i] == '\0') break; @@ -1933,7 +1960,7 @@ coff_get_normalized_symtab (bfd *abfd) else if (!bfd_coff_symname_in_debug (abfd, &internal_ptr->u.syment)) { /* Long name already. Point symbol at the string in the - table. */ + table. */ if (string_table == NULL) { string_table = _bfd_coff_read_string_table (abfd); @@ -2222,13 +2249,13 @@ _bfd_coff_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, bfd_boolean coff_find_nearest_line_with_names (bfd *abfd, - asymbol **symbols, - asection *section, - bfd_vma offset, - const char **filename_ptr, - const char **functionname_ptr, - unsigned int *line_ptr, - const struct dwarf_debug_section *debug_sections) + asymbol **symbols, + asection *section, + bfd_vma offset, + const char **filename_ptr, + const char **functionname_ptr, + unsigned int *line_ptr, + const struct dwarf_debug_section *debug_sections) { bfd_boolean found; unsigned int i; @@ -2363,7 +2390,7 @@ coff_find_nearest_line_with_names (bfd *abfd, file_addr += coff_section_from_bfd_index (abfd, p2->u.syment.n_scnum)->vma; /* We use <= MAXDIFF here so that if we get a zero length - file, we actually use the next file entry. */ + file, we actually use the next file entry. */ if (p2 < pend && offset + sec_vma >= file_addr && offset + sec_vma - file_addr <= maxdiff) @@ -2503,8 +2530,8 @@ coff_find_nearest_line (bfd *abfd, if (discriminator_ptr) *discriminator_ptr = 0; return coff_find_nearest_line_with_names (abfd, symbols, section, offset, - filename_ptr, functionname_ptr, - line_ptr, dwarf_debug_sections); + filename_ptr, functionname_ptr, + line_ptr, dwarf_debug_sections); } bfd_boolean @@ -2538,9 +2565,9 @@ coff_sizeof_headers (bfd *abfd, struct bfd_link_info *info) /* Change the class of a coff symbol held by BFD. */ bfd_boolean -bfd_coff_set_symbol_class (bfd * abfd, - asymbol * symbol, - unsigned int symbol_class) +bfd_coff_set_symbol_class (bfd * abfd, + asymbol * symbol, + unsigned int symbol_class) { coff_symbol_type * csym; @@ -2777,19 +2804,33 @@ _bfd_coff_gc_mark_hook (asection *sec, if (h != NULL) { switch (h->root.type) - { - case bfd_link_hash_defined: - case bfd_link_hash_defweak: - return h->root.u.def.section; + { + case bfd_link_hash_defined: + case bfd_link_hash_defweak: + return h->root.u.def.section; - case bfd_link_hash_common: - return h->root.u.c.p->section; + case bfd_link_hash_common: + return h->root.u.c.p->section; - case bfd_link_hash_undefined: case bfd_link_hash_undefweak: - default: - break; - } + if (h->symbol_class == C_NT_WEAK && h->numaux == 1) + { + /* PE weak externals. A weak symbol may include an auxiliary + record indicating that if the weak symbol is not resolved, + another external symbol is used instead. */ + struct coff_link_hash_entry *h2 = + h->auxbfd->tdata.coff_obj_data->sym_hashes[ + h->aux->x_sym.x_tagndx.l]; + + if (h2 && h2->root.type != bfd_link_hash_undefined) + return h2->root.u.def.section; + } + break; + + case bfd_link_hash_undefined: + default: + break; + } return NULL; } @@ -2868,19 +2909,19 @@ _bfd_coff_gc_mark (struct bfd_link_info *info, struct coff_reloc_cookie cookie; if (!init_reloc_cookie_for_section (&cookie, info, sec)) - ret = FALSE; + ret = FALSE; else - { - for (; cookie.rel < cookie.relend; cookie.rel++) - { + { + for (; cookie.rel < cookie.relend; cookie.rel++) + { if (!_bfd_coff_gc_mark_reloc (info, sec, gc_mark_hook, &cookie)) { ret = FALSE; break; } } - fini_reloc_cookie_for_section (&cookie, sec); - } + fini_reloc_cookie_for_section (&cookie, sec); + } } return ret; @@ -2897,7 +2938,7 @@ _bfd_coff_gc_mark_extra_sections (struct bfd_link_info *info, asection *isec; bfd_boolean some_kept; - if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) + if (bfd_get_flavour (ibfd) != bfd_target_coff_flavour) continue; /* Ensure all linker created sections are kept, and see whether @@ -2968,10 +3009,10 @@ coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) for (o = sub->sections; o != NULL; o = o->next) { /* Keep debug and special sections. */ - if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0 + if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0 || (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0) o->gc_mark = 1; - else if (CONST_STRNEQ (o->name, ".idata") + else if (CONST_STRNEQ (o->name, ".idata") || CONST_STRNEQ (o->name, ".pdata") || CONST_STRNEQ (o->name, ".xdata") || CONST_STRNEQ (o->name, ".rsrc")) @@ -2990,7 +3031,8 @@ coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) if (info->print_gc_sections && o->size != 0) /* xgettext: c-format */ - _bfd_error_handler (_("Removing unused section '%s' in file '%B'"), sub, o->name); + _bfd_error_handler (_("removing unused section '%pA' in file '%pB'"), + o, sub); #if 0 /* But we also have to update some of the relocation @@ -3066,7 +3108,7 @@ bfd_coff_gc_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) if (!bed->can_gc_sections || !is_coff_hash_table (info->hash)) { - _bfd_error_handler(_("Warning: gc-sections option ignored")); + _bfd_error_handler(_("warning: gc-sections option ignored")); return TRUE; } #endif @@ -3079,10 +3121,10 @@ bfd_coff_gc_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) asection *o; if (bfd_get_flavour (sub) != bfd_target_coff_flavour) - continue; + continue; for (o = sub->sections; o != NULL; o = o->next) - { + { if (((o->flags & (SEC_EXCLUDE | SEC_KEEP)) == SEC_KEEP || CONST_STRNEQ (o->name, ".vectors") || CONST_STRNEQ (o->name, ".ctors") @@ -3092,7 +3134,7 @@ bfd_coff_gc_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) if (!_bfd_coff_gc_mark (info, o, _bfd_coff_gc_mark_hook)) return FALSE; } - } + } } /* Allow the backend to mark additional target specific sections. */