X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Fcoffgen.c;h=5474f6c24d8d35d513ebb0fe36912aae236d649a;hb=784712bf4fed9507cb807277ac64d07686bab2c1;hp=44bdc6ed508d19e1bf30d8005d4589ae3d649138;hpb=1b7868733d45220e63b72a1814f30e090f761821;p=binutils-gdb.git diff --git a/bfd/coffgen.c b/bfd/coffgen.c index 44bdc6ed508..5474f6c24d8 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-2015 Free Software Foundation, Inc. + Copyright (C) 1990-2021 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -37,6 +37,7 @@ coff_data (abfd). */ #include "sysdep.h" +#include #include "bfd.h" #include "libbfd.h" #include "coff/internal.h" @@ -45,14 +46,14 @@ /* Take a section header read from a coff file (in HOST byte order), and make a BFD "section" out of it. This is used by ECOFF. */ -static bfd_boolean +static bool make_a_section_from_file (bfd *abfd, struct internal_scnhdr *hdr, unsigned int target_index) { asection *return_section; char *name; - bfd_boolean result = TRUE; + bool result = true; flagword flags; name = NULL; @@ -72,10 +73,10 @@ 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. */ - bfd_coff_set_long_section_names (abfd, TRUE); + 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'; strindex = strtol (buf, &p, 10); @@ -83,14 +84,14 @@ make_a_section_from_file (bfd *abfd, { strings = _bfd_coff_read_string_table (abfd); if (strings == NULL) - return FALSE; + return false; if ((bfd_size_type)(strindex + 2) >= obj_coff_strings_len (abfd)) - return FALSE; + 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; + return false; strcpy (name, strings); } } @@ -99,16 +100,16 @@ 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; + return false; strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name)); name[sizeof (hdr->s_name)] = 0; } return_section = bfd_make_section_anyway (abfd, name); if (return_section == NULL) - return FALSE; + return false; return_section->vma = hdr->s_vaddr; return_section->lma = hdr->s_paddr; @@ -128,7 +129,7 @@ make_a_section_from_file (bfd *abfd, if (! bfd_coff_styp_to_sec_flags_hook (abfd, hdr, name, return_section, & flags)) - result = FALSE; + result = false; return_section->flags = flags; @@ -173,10 +174,11 @@ make_a_section_from_file (bfd *abfd, case compress: if (!bfd_init_section_compress_status (abfd, return_section)) { - (*_bfd_error_handler) - (_("%B: unable to initialize compress status for section %s"), + _bfd_error_handler + /* xgettext: c-format */ + (_("%pB: unable to initialize compress status for section %s"), abfd, name); - return FALSE; + return false; } if (return_section->compress_status == COMPRESS_SECTION_DONE) { @@ -186,20 +188,21 @@ make_a_section_from_file (bfd *abfd, new_name = bfd_alloc (abfd, len + 2); if (new_name == NULL) - return FALSE; + return false; new_name[0] = '.'; new_name[1] = 'z'; memcpy (new_name + 2, name + 1, len); } } - break; + break; case decompress: if (!bfd_init_section_decompress_status (abfd, return_section)) { - (*_bfd_error_handler) - (_("%B: unable to initialize decompress status for section %s"), + _bfd_error_handler + /* xgettext: c-format */ + (_("%pB: unable to initialize decompress status for section %s"), abfd, name); - return FALSE; + return false; } if (name[1] == 'z') { @@ -207,14 +210,14 @@ make_a_section_from_file (bfd *abfd, new_name = bfd_alloc (abfd, len); if (new_name == NULL) - return FALSE; + return false; new_name[0] = '.'; memcpy (new_name + 1, name + 2, len - 1); } break; } if (new_name != NULL) - bfd_rename_section (abfd, return_section, new_name); + bfd_rename_section (return_section, new_name); } return result; @@ -222,12 +225,12 @@ make_a_section_from_file (bfd *abfd, /* Read in a COFF object and make it into a BFD. This is used by ECOFF as well. */ -const bfd_target * +bfd_cleanup coff_real_object_p (bfd *, - unsigned, - struct internal_filehdr *, - struct internal_aouthdr *); -const bfd_target * + unsigned, + struct internal_filehdr *, + struct internal_aouthdr *); +bfd_cleanup coff_real_object_p (bfd *abfd, unsigned nscns, struct internal_filehdr *internal_f, @@ -254,14 +257,14 @@ coff_real_object_p (bfd *abfd, if ((internal_f->f_flags & F_EXEC) != 0) abfd->flags |= D_PAGED; - bfd_get_symcount (abfd) = internal_f->f_nsyms; + abfd->symcount = internal_f->f_nsyms; if (internal_f->f_nsyms) abfd->flags |= HAS_SYMS; if (internal_a != (struct internal_aouthdr *) NULL) - bfd_get_start_address (abfd) = internal_a->entry; + abfd->start_address = internal_a->entry; else - bfd_get_start_address (abfd) = 0; + abfd->start_address = 0; /* Set up the tdata area. ECOFF uses its own routine, and overrides abfd->flags. */ @@ -272,13 +275,10 @@ coff_real_object_p (bfd *abfd, scnhsz = bfd_coff_scnhsz (abfd); readsize = (bfd_size_type) nscns * scnhsz; - external_sections = (char *) bfd_alloc (abfd, readsize); + external_sections = (char *) _bfd_alloc_and_read (abfd, readsize, readsize); if (!external_sections) goto fail; - if (bfd_bread ((void *) external_sections, readsize, abfd) != readsize) - goto fail; - /* Set the arch/mach *before* swapping in sections; section header swapping may depend on arch/mach info. */ if (! bfd_coff_set_arch_mach_hook (abfd, (void *) internal_f)) @@ -299,21 +299,23 @@ coff_real_object_p (bfd *abfd, } } - return abfd->xvec; + _bfd_coff_free_symbols (abfd); + return _bfd_no_cleanup; fail: + _bfd_coff_free_symbols (abfd); bfd_release (abfd, tdata); fail2: abfd->tdata.any = tdata_save; abfd->flags = oflags; - bfd_get_start_address (abfd) = ostart; - return (const bfd_target *) NULL; + abfd->start_address = ostart; + return NULL; } /* Turn a COFF file into a BFD, but fail with bfd_error_wrong_format if it is not a COFF file. This is also used by ECOFF. */ -const bfd_target * +bfd_cleanup coff_object_p (bfd *abfd) { bfd_size_type filhsz; @@ -327,14 +329,11 @@ coff_object_p (bfd *abfd) filhsz = bfd_coff_filhsz (abfd); aoutsz = bfd_coff_aoutsz (abfd); - filehdr = bfd_alloc (abfd, filhsz); + filehdr = _bfd_alloc_and_read (abfd, filhsz, filhsz); if (filehdr == NULL) - return NULL; - if (bfd_bread (filehdr, filhsz, abfd) != filhsz) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); - bfd_release (abfd, filehdr); return NULL; } bfd_coff_swap_filehdr_in (abfd, filehdr, &internal_f); @@ -360,18 +359,13 @@ coff_object_p (bfd *abfd) { void * opthdr; - opthdr = bfd_alloc (abfd, aoutsz); + opthdr = _bfd_alloc_and_read (abfd, aoutsz, internal_f.f_opthdr); if (opthdr == NULL) return NULL; - if (bfd_bread (opthdr, (bfd_size_type) internal_f.f_opthdr, abfd) - != internal_f.f_opthdr) - { - bfd_release (abfd, opthdr); - return NULL; - } /* PR 17512: file: 11056-1136-0.004. */ if (internal_f.f_opthdr < aoutsz) - memset (((char *) opthdr) + internal_f.f_opthdr, 0, aoutsz - internal_f.f_opthdr); + memset (((char *) opthdr) + internal_f.f_opthdr, 0, + aoutsz - internal_f.f_opthdr); bfd_coff_swap_aouthdr_in (abfd, opthdr, (void *) &internal_a); bfd_release (abfd, opthdr); @@ -492,9 +486,9 @@ _bfd_coff_internal_syment_name (bfd *abfd, struct internal_reloc * _bfd_coff_read_internal_relocs (bfd *abfd, asection *sec, - bfd_boolean cache, + bool cache, bfd_byte *external_relocs, - bfd_boolean require_internal, + bool require_internal, struct internal_reloc *internal_relocs) { bfd_size_type relsz; @@ -550,11 +544,8 @@ _bfd_coff_read_internal_relocs (bfd *abfd, for (; erel < erel_end; erel += relsz, irel++) bfd_coff_swap_reloc_in (abfd, (void *) erel, (void *) irel); - if (free_external != NULL) - { - free (free_external); - free_external = NULL; - } + free (free_external); + free_external = NULL; if (cache && free_internal != NULL) { @@ -572,10 +563,8 @@ _bfd_coff_read_internal_relocs (bfd *abfd, return internal_relocs; error_return: - if (free_external != NULL) - free (free_external); - if (free_internal != NULL) - free (free_internal); + free (free_external); + free (free_internal); return NULL; } @@ -593,7 +582,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; @@ -611,13 +600,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 @@ -673,11 +662,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 { @@ -696,7 +685,7 @@ fixup_symbol_value (bfd *abfd, chain, and that the last one points to the first external symbol. We do that here too. */ -bfd_boolean +bool coff_renumber_symbols (bfd *bfd_ptr, int *first_undef) { unsigned int symbol_count = bfd_get_symcount (bfd_ptr); @@ -723,7 +712,7 @@ coff_renumber_symbols (bfd *bfd_ptr, int *first_undef) amt = sizeof (asymbol *) * ((bfd_size_type) symbol_count + 1); newsyms = (asymbol **) bfd_alloc (bfd_ptr, amt); if (!newsyms) - return FALSE; + return false; bfd_ptr->outsymbols = newsyms; for (i = 0; i < symbol_count; i++) if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) != 0 @@ -785,7 +774,7 @@ coff_renumber_symbols (bfd *bfd_ptr, int *first_undef) obj_conv_table_size (bfd_ptr) = native_index; - return TRUE; + return true; } /* Run thorough the symbol table again, and fix it so that all @@ -821,8 +810,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)); @@ -858,6 +847,34 @@ coff_mangle_symbols (bfd *bfd_ptr) } } +static void +coff_write_auxent_fname (bfd *abfd, + char *str, + union internal_auxent *auxent, + bfd_size_type *string_size_p) +{ + unsigned int str_length = strlen (str); + unsigned int filnmlen = bfd_coff_filnmlen (abfd); + + if (bfd_coff_long_filenames (abfd)) + { + if (str_length <= filnmlen) + strncpy (auxent->x_file.x_n.x_fname, str, filnmlen); + else + { + auxent->x_file.x_n.x_n.x_offset = *string_size_p + STRING_SIZE_SIZE; + auxent->x_file.x_n.x_n.x_zeroes = 0; + *string_size_p += str_length + 1; + } + } + else + { + strncpy (auxent->x_file.x_n.x_fname, str, filnmlen); + if (str_length > filnmlen) + str[filnmlen] = '\0'; + } +} + static void coff_fix_symbol_name (bfd *abfd, asymbol *symbol, @@ -867,7 +884,6 @@ coff_fix_symbol_name (bfd *abfd, bfd_size_type *debug_string_size_p) { unsigned int name_length; - union internal_auxent *auxent; char *name = (char *) (symbol->name); if (name == NULL) @@ -882,40 +898,19 @@ coff_fix_symbol_name (bfd *abfd, if (native->u.syment.n_sclass == C_FILE && native->u.syment.n_numaux > 0) { - unsigned int filnmlen; - 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; - - filnmlen = bfd_coff_filnmlen (abfd); - - if (bfd_coff_long_filenames (abfd)) - { - if (name_length <= filnmlen) - strncpy (auxent->x_file.x_fname, name, filnmlen); - else - { - auxent->x_file.x_n.x_offset = *string_size_p + STRING_SIZE_SIZE; - auxent->x_file.x_n.x_zeroes = 0; - *string_size_p += name_length + 1; - } - } - else - { - strncpy (auxent->x_file.x_fname, name, filnmlen); - if (name_length > filnmlen) - name[filnmlen] = '\0'; - } + coff_write_auxent_fname (abfd, name, &(native + 1)->u.auxent, + string_size_p); } else { @@ -979,7 +974,7 @@ coff_fix_symbol_name (bfd *abfd, /* Write a symbol out to a COFF file. */ -static bfd_boolean +static bool coff_write_symbol (bfd *abfd, asymbol *symbol, combined_entry_type *native, @@ -1022,10 +1017,10 @@ coff_write_symbol (bfd *abfd, symesz = bfd_coff_symesz (abfd); buf = bfd_alloc (abfd, symesz); if (!buf) - return FALSE; + return false; bfd_coff_swap_sym_out (abfd, &native->u.syment, buf); if (bfd_bwrite (buf, symesz, abfd) != symesz) - return FALSE; + return false; bfd_release (abfd, buf); if (native->u.syment.n_numaux > 0) @@ -1036,17 +1031,25 @@ coff_write_symbol (bfd *abfd, auxesz = bfd_coff_auxesz (abfd); buf = bfd_alloc (abfd, auxesz); if (!buf) - return FALSE; + return false; for (j = 0; j < native->u.syment.n_numaux; j++) { BFD_ASSERT (! (native + j + 1)->is_sym); + + /* Adjust auxent only if this isn't the filename + auxiliary entry. */ + if (native->u.syment.n_sclass == C_FILE + && (native + j + 1)->u.auxent.x_file.x_ftype) + coff_write_auxent_fname (abfd, (char *) (native + j + 1)->extrap, + &(native + j + 1)->u.auxent, string_size_p); + bfd_coff_swap_aux_out (abfd, &((native + j + 1)->u.auxent), type, n_sclass, (int) j, native->u.syment.n_numaux, buf); if (bfd_bwrite (buf, auxesz, abfd) != auxesz) - return FALSE; + return false; } bfd_release (abfd, buf); } @@ -1055,17 +1058,18 @@ coff_write_symbol (bfd *abfd, set_index (symbol, *written); *written += numaux + 1; - return TRUE; + return true; } /* Write out a symbol to a COFF file that does not come from a COFF file originally. This symbol may have been created by the linker, or we may be linking a non COFF file to a COFF file. */ -bfd_boolean +bool coff_write_alien_symbol (bfd *abfd, asymbol *symbol, struct internal_syment *isym, + union internal_auxent *iaux, bfd_vma *written, bfd_size_type *string_size_p, asection **debug_string_section_p, @@ -1077,7 +1081,7 @@ coff_write_alien_symbol (bfd *abfd, ? symbol->section->output_section : symbol->section; struct bfd_link_info *link_info = coff_data (abfd)->link_info; - bfd_boolean ret; + bool ret; if ((!link_info || link_info->strip_discarded) && !bfd_is_abs_section (symbol->section) @@ -1085,12 +1089,12 @@ coff_write_alien_symbol (bfd *abfd, { symbol->name = ""; if (isym != NULL) - memset (isym, 0, sizeof (*isym)); - return TRUE; + memset (isym, 0, sizeof (*isym)); + return true; } native = dummy; - native->is_sym = TRUE; - native[1].is_sym = FALSE; + native->is_sym = true; + native[1].is_sym = false; native->u.syment.n_type = T_NULL; native->u.syment.n_flags = 0; native->u.syment.n_numaux = 0; @@ -1112,13 +1116,13 @@ 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)); - return TRUE; + memset (isym, 0, sizeof (*isym)); + return true; } else { @@ -1129,7 +1133,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) @@ -1151,12 +1155,14 @@ coff_write_alien_symbol (bfd *abfd, debug_string_section_p, debug_string_size_p); if (isym != NULL) *isym = native->u.syment; + if (iaux != NULL && native->u.syment.n_numaux) + *iaux = native[1].u.auxent; return ret; } /* Write a native symbol to a COFF file. */ -static bfd_boolean +static bool coff_write_native_symbol (bfd *abfd, coff_symbol_type *symbol, bfd_vma *written, @@ -1173,7 +1179,7 @@ coff_write_native_symbol (bfd *abfd, && symbol->symbol.section->output_section == bfd_abs_section_ptr) { symbol->symbol.name = ""; - return TRUE; + return true; } BFD_ASSERT (native->is_sym); @@ -1202,7 +1208,7 @@ coff_write_native_symbol (bfd *abfd, + symbol->symbol.section->output_offset); count++; } - symbol->done_lineno = TRUE; + symbol->done_lineno = true; if (! bfd_is_const_section (symbol->symbol.section->output_section)) symbol->symbol.section->output_section->moving_line_filepos += @@ -1215,13 +1221,14 @@ coff_write_native_symbol (bfd *abfd, } static void -null_error_handler (const char * fmt ATTRIBUTE_UNUSED, ...) +null_error_handler (const char *fmt ATTRIBUTE_UNUSED, + va_list ap ATTRIBUTE_UNUSED) { } /* Write out the COFF symbols. */ -bfd_boolean +bool coff_write_symbols (bfd *abfd) { bfd_size_type string_size; @@ -1256,7 +1263,7 @@ coff_write_symbols (bfd *abfd) /* Seek to the right place. */ if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0) - return FALSE; + return false; /* Output all the symbols we have. */ written = 0; @@ -1268,10 +1275,10 @@ coff_write_symbols (bfd *abfd) if (c_symbol == (coff_symbol_type *) NULL || c_symbol->native == (combined_entry_type *) NULL) { - if (!coff_write_alien_symbol (abfd, symbol, NULL, &written, + if (!coff_write_alien_symbol (abfd, symbol, NULL, NULL, &written, &string_size, &debug_string_section, &debug_string_size)) - return FALSE; + return false; } else { @@ -1316,7 +1323,7 @@ coff_write_symbols (bfd *abfd) if (!coff_write_native_symbol (abfd, c_symbol, &written, &string_size, &debug_string_section, &debug_string_size)) - return FALSE; + return false; } } @@ -1335,7 +1342,7 @@ coff_write_symbols (bfd *abfd) #endif if (bfd_bwrite ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd) != sizeof (buffer)) - return FALSE; + return false; /* Handle long section names. This code must handle section names just as they are handled in coff_write_object_contents. */ @@ -1352,7 +1359,7 @@ coff_write_symbols (bfd *abfd) { if (bfd_bwrite (o->name, (bfd_size_type) (len + 1), abfd) != len + 1) - return FALSE; + return false; } } } @@ -1365,6 +1372,7 @@ coff_write_symbols (bfd *abfd) size_t name_length = strlen (q->name); coff_symbol_type *c_symbol = coff_symbol_from (q); size_t maxlen; + bool is_c_file = false; /* Figure out whether the symbol name should go in the string table. Symbol names that are short enough are stored @@ -1391,10 +1399,11 @@ coff_write_symbols (bfd *abfd) else if (c_symbol->native->u.syment.n_sclass == C_FILE && c_symbol->native->u.syment.n_numaux > 0) { + is_c_file=true; if (bfd_coff_force_symnames_in_strings (abfd)) { if (bfd_bwrite (".file", (bfd_size_type) 6, abfd) != 6) - return FALSE; + return false; } maxlen = bfd_coff_filnmlen (abfd); } @@ -1405,15 +1414,44 @@ coff_write_symbols (bfd *abfd) { if (bfd_bwrite ((void *) (q->name), (bfd_size_type) name_length + 1, abfd) != name_length + 1) - return FALSE; + return false; + } + + /* Add strings for C_FILE aux entries. */ + if (is_c_file + && c_symbol->native->u.syment.n_numaux > 1) + { + for (int j = 1; j < c_symbol->native->u.syment.n_numaux; j++) + { + char *str; + size_t str_length; + + /* Add strings from aux entries only if this isn't the + filename auxiliary entry. */ + if (!c_symbol->native[j + 1].u.auxent.x_file.x_ftype) + continue; + + if (c_symbol->native[j + 1].u.auxent.x_file.x_n.x_fname[0] != 0) + continue; + + str = (char *) c_symbol->native[j + 1].extrap; + str_length = strlen (str); + if (str_length > maxlen) + { + if (bfd_bwrite ((void *) (str), (bfd_size_type) str_length + 1, + abfd) != str_length + 1) + return false; + } + + } } } } 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]; @@ -1424,7 +1462,7 @@ coff_write_symbols (bfd *abfd) #endif if (bfd_bwrite ((void *) buffer, (bfd_size_type) STRING_SIZE_SIZE, abfd) != STRING_SIZE_SIZE) - return FALSE; + return false; } /* Make sure the .debug section was created to be the correct size. @@ -1438,10 +1476,10 @@ coff_write_symbols (bfd *abfd) 1 << debug_string_section->alignment_power) == debug_string_section->size))); - return TRUE; + return true; } -bfd_boolean +bool coff_write_linenumbers (bfd *abfd) { asection *s; @@ -1451,14 +1489,14 @@ coff_write_linenumbers (bfd *abfd) linesz = bfd_coff_linesz (abfd); buff = bfd_alloc (abfd, linesz); if (!buff) - return FALSE; + return false; for (s = abfd->sections; s != (asection *) NULL; s = s->next) { if (s->lineno_count) { asymbol **q = abfd->outsymbols; if (bfd_seek (abfd, s->line_filepos, SEEK_SET) != 0) - return FALSE; + return false; /* Find all the linenumbers in this section. */ while (*q) { @@ -1479,7 +1517,7 @@ coff_write_linenumbers (bfd *abfd) bfd_coff_swap_lineno_out (abfd, &out, buff); if (bfd_bwrite (buff, (bfd_size_type) linesz, abfd) != linesz) - return FALSE; + return false; l++; while (l->line_number) { @@ -1488,7 +1526,7 @@ coff_write_linenumbers (bfd *abfd) bfd_coff_swap_lineno_out (abfd, &out, buff); if (bfd_bwrite (buff, (bfd_size_type) linesz, abfd) != linesz) - return FALSE; + return false; l++; } } @@ -1498,7 +1536,7 @@ coff_write_linenumbers (bfd *abfd) } } bfd_release (abfd, buff); - return TRUE; + return true; } alent * @@ -1515,7 +1553,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; @@ -1533,6 +1572,8 @@ coff_pointerize_aux (bfd *abfd, return; if (n_sclass == C_FILE) return; + if (n_sclass == C_DWARF) + return; BFD_ASSERT (! auxent->is_sym); /* Otherwise patch up. */ @@ -1541,15 +1582,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; @@ -1576,19 +1624,20 @@ build_debug_section (bfd *abfd, asection ** sect_return) return NULL; } - sec_size = sect->size; - debug_section = (char *) bfd_alloc (abfd, sec_size); - if (debug_section == NULL) - return NULL; - /* Seek to the beginning of the `.debug' section and read it. Save the current position first; it is needed by our caller. Then read debug section and reset the file pointer. */ position = bfd_tell (abfd); - if (bfd_seek (abfd, sect->filepos, SEEK_SET) != 0 - || bfd_bread (debug_section, sec_size, abfd) != sec_size - || bfd_seek (abfd, position, SEEK_SET) != 0) + if (bfd_seek (abfd, sect->filepos, SEEK_SET) != 0) + return NULL; + + sec_size = sect->size; + debug_section = (char *) _bfd_alloc_and_read (abfd, sec_size, sec_size); + if (debug_section == NULL) + return NULL; + + if (bfd_seek (abfd, position, SEEK_SET) != 0) return NULL; * sect_return = sect; @@ -1619,37 +1668,31 @@ copy_name (bfd *abfd, char *name, size_t maxlen) /* Read in the external symbols. */ -bfd_boolean +bool _bfd_coff_get_external_symbols (bfd *abfd) { - bfd_size_type symesz; - bfd_size_type size; + size_t symesz; + size_t size; void * syms; if (obj_coff_external_syms (abfd) != NULL) - return TRUE; + return true; symesz = bfd_coff_symesz (abfd); - - size = obj_raw_syment_count (abfd) * symesz; - if (size == 0) - return TRUE; - - syms = bfd_malloc (size); - if (syms == NULL) - return FALSE; - - if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0 - || bfd_bread (syms, size, abfd) != size) + if (_bfd_mul_overflow (obj_raw_syment_count (abfd), symesz, &size)) { - if (syms != NULL) - free (syms); - return FALSE; + bfd_set_error (bfd_error_file_truncated); + return false; } - obj_coff_external_syms (abfd) = syms; + if (size == 0) + return true; - return TRUE; + if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0) + return false; + syms = _bfd_malloc_and_read (abfd, size, size); + obj_coff_external_syms (abfd) = syms; + return syms != NULL; } /* Read in the external strings. The strings are not loaded until @@ -1664,7 +1707,10 @@ _bfd_coff_read_string_table (bfd *abfd) char extstrsize[STRING_SIZE_SIZE]; bfd_size_type strsize; char *strings; - file_ptr pos; + ufile_ptr pos; + ufile_ptr filesize; + size_t symesz; + size_t size; if (obj_coff_strings (abfd) != NULL) return obj_coff_strings (abfd); @@ -1675,9 +1721,16 @@ _bfd_coff_read_string_table (bfd *abfd) return NULL; } + symesz = bfd_coff_symesz (abfd); pos = obj_sym_filepos (abfd); - pos += obj_raw_syment_count (abfd) * bfd_coff_symesz (abfd); - if (bfd_seek (abfd, pos, SEEK_SET) != 0) + if (_bfd_mul_overflow (obj_raw_syment_count (abfd), symesz, &size) + || pos + size < pos) + { + bfd_set_error (bfd_error_file_truncated); + return NULL; + } + + if (bfd_seek (abfd, pos + size, SEEK_SET) != 0) return NULL; if (bfd_bread (extstrsize, (bfd_size_type) sizeof extstrsize, abfd) @@ -1698,10 +1751,13 @@ _bfd_coff_read_string_table (bfd *abfd) #endif } - if (strsize < STRING_SIZE_SIZE) + filesize = bfd_get_file_size (abfd); + if (strsize < STRING_SIZE_SIZE + || (filesize != 0 && strsize > filesize)) { - (*_bfd_error_handler) - (_("%B: bad string table size %lu"), abfd, (unsigned long) strsize); + _bfd_error_handler + /* xgettext: c-format */ + (_("%pB: bad string table size %" PRIu64), abfd, (uint64_t) strsize); bfd_set_error (bfd_error_bad_value); return NULL; } @@ -1732,15 +1788,19 @@ _bfd_coff_read_string_table (bfd *abfd) /* Free up the external symbols and strings read from a COFF file. */ -bfd_boolean +bool _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)) { @@ -1748,7 +1808,8 @@ _bfd_coff_free_symbols (bfd *abfd) obj_coff_strings (abfd) = NULL; obj_coff_strings_len (abfd) = 0; } - return TRUE; + + return true; } /* Read a symbol table into freshly bfd_allocated memory, swap it, and @@ -1777,7 +1838,11 @@ coff_get_normalized_symtab (bfd *abfd) if (! _bfd_coff_get_external_symbols (abfd)) return NULL; - size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type); + size = obj_raw_syment_count (abfd); + /* Check for integer overflow. */ + if (size > (bfd_size_type) -1 / sizeof (combined_entry_type)) + return NULL; + size *= sizeof (combined_entry_type); internal = (combined_entry_type *) bfd_zalloc (abfd, size); if (internal == NULL && size != 0) return NULL; @@ -1787,7 +1852,7 @@ coff_get_normalized_symtab (bfd *abfd) /* Mark the end of the symbols. */ symesz = bfd_coff_symesz (abfd); - raw_end = (char *) raw_src + obj_raw_syment_count (abfd) * symesz; + raw_end = PTR_ADD (raw_src, obj_raw_syment_count (abfd) * symesz); /* FIXME SOMEDAY. A string table size of zero is very weird, but probably possible. If one shows up, it will probably kill us. */ @@ -1802,13 +1867,10 @@ coff_get_normalized_symtab (bfd *abfd) bfd_coff_swap_sym_in (abfd, (void *) raw_src, (void *) & internal_ptr->u.syment); symbol_ptr = internal_ptr; - internal_ptr->is_sym = TRUE; + internal_ptr->is_sym = true; - /* PR 17512: file: 1353-1166-0.004. */ - if (symbol_ptr->u.syment.n_sclass == C_FILE - && symbol_ptr->u.syment.n_numaux > 0 - && raw_src + symesz + symbol_ptr->u.syment.n_numaux - * symesz > raw_end) + /* PR 17512: Prevent buffer overrun. */ + if (symbol_ptr->u.syment.n_numaux > ((raw_end - 1) - raw_src) / symesz) { bfd_release (abfd, internal); return NULL; @@ -1819,30 +1881,27 @@ coff_get_normalized_symtab (bfd *abfd) i++) { internal_ptr++; - /* PR 17512: Prevent buffer overrun. */ - if (internal_ptr >= internal_end) - { - bfd_release (abfd, internal); - return NULL; - } - raw_src += symesz; + bfd_coff_swap_aux_in (abfd, (void *) raw_src, symbol_ptr->u.syment.n_type, symbol_ptr->u.syment.n_sclass, (int) i, symbol_ptr->u.syment.n_numaux, &(internal_ptr->u.auxent)); - internal_ptr->is_sym = FALSE; + internal_ptr->is_sym = false; coff_pointerize_aux (abfd, internal, symbol_ptr, i, - internal_ptr); + internal_ptr, internal_end); } } - /* Free the raw symbols, but not the strings (if we have them). */ - obj_coff_keep_strings (abfd) = TRUE; - if (! _bfd_coff_free_symbols (abfd)) - return NULL; + /* Free the raw symbols. */ + if (obj_coff_external_syms (abfd) != NULL + && ! obj_coff_keep_syms (abfd)) + { + free (obj_coff_external_syms (abfd)); + obj_coff_external_syms (abfd) = NULL; + } for (internal_ptr = internal; internal_ptr < internal_end; internal_ptr++) @@ -1858,7 +1917,7 @@ coff_get_normalized_symtab (bfd *abfd) the text ".file" is redundant. */ BFD_ASSERT (! aux->is_sym); - if (aux->u.auxent.x_file.x_n.x_zeroes == 0) + if (aux->u.auxent.x_file.x_n.x_n.x_zeroes == 0) { /* The filename is a long one, point into the string table. */ if (string_table == NULL) @@ -1868,32 +1927,65 @@ coff_get_normalized_symtab (bfd *abfd) return NULL; } - if ((bfd_size_type)(aux->u.auxent.x_file.x_n.x_offset) + if ((bfd_size_type)(aux->u.auxent.x_file.x_n.x_n.x_offset) >= obj_coff_strings_len (abfd)) internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _(""); else internal_ptr->u.syment._n._n_n._n_offset = - (bfd_hostptr_t) (string_table + (aux->u.auxent.x_file.x_n.x_offset)); + (bfd_hostptr_t) (string_table + (aux->u.auxent.x_file.x_n.x_n.x_offset)); } 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 = (bfd_hostptr_t) copy_name (abfd, - aux->u.auxent.x_file.x_fname, + aux->u.auxent.x_file.x_n.x_fname, internal_ptr->u.syment.n_numaux * symesz); else internal_ptr->u.syment._n._n_n._n_offset = ((bfd_hostptr_t) copy_name (abfd, - aux->u.auxent.x_file.x_fname, + aux->u.auxent.x_file.x_n.x_fname, (size_t) bfd_coff_filnmlen (abfd))); } + + /* Normalize other strings available in C_FILE aux entries. */ + if (!coff_data (abfd)->pe) + for (int numaux = 1; numaux < internal_ptr->u.syment.n_numaux; numaux++) + { + aux = internal_ptr + numaux + 1; + BFD_ASSERT (! aux->is_sym); + + if (aux->u.auxent.x_file.x_n.x_n.x_zeroes == 0) + { + /* The string information is a long one, point into the string table. */ + if (string_table == NULL) + { + string_table = _bfd_coff_read_string_table (abfd); + if (string_table == NULL) + return NULL; + } + + if ((bfd_size_type)(aux->u.auxent.x_file.x_n.x_n.x_offset) + >= obj_coff_strings_len (abfd)) + aux->u.auxent.x_file.x_n.x_n.x_offset = (bfd_hostptr_t) _(""); + else + aux->u.auxent.x_file.x_n.x_n.x_offset = + (bfd_hostptr_t) (string_table + (aux->u.auxent.x_file.x_n.x_n.x_offset)); + } + else + aux->u.auxent.x_file.x_n.x_n.x_offset = + ((bfd_hostptr_t) + copy_name (abfd, + aux->u.auxent.x_file.x_n.x_fname, + (size_t) bfd_coff_filnmlen (abfd))); + } + } else { @@ -1904,7 +1996,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; @@ -1921,7 +2013,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); @@ -1975,13 +2067,20 @@ coff_get_reloc_upper_bound (bfd *abfd, sec_ptr asect) bfd_set_error (bfd_error_invalid_operation); return -1; } - return (asect->reloc_count + 1) * sizeof (arelent *); +#if SIZEOF_LONG == SIZEOF_INT + if (asect->reloc_count >= LONG_MAX / sizeof (arelent *)) + { + bfd_set_error (bfd_error_file_too_big); + return -1; + } +#endif + return (asect->reloc_count + 1L) * sizeof (arelent *); } asymbol * coff_make_empty_symbol (bfd *abfd) { - bfd_size_type amt = sizeof (coff_symbol_type); + size_t amt = sizeof (coff_symbol_type); coff_symbol_type *new_symbol = (coff_symbol_type *) bfd_zalloc (abfd, amt); if (new_symbol == NULL) @@ -1989,7 +2088,7 @@ coff_make_empty_symbol (bfd *abfd) new_symbol->symbol.section = 0; new_symbol->native = NULL; new_symbol->lineno = NULL; - new_symbol->done_lineno = FALSE; + new_symbol->done_lineno = false; new_symbol->symbol.the_bfd = abfd; return & new_symbol->symbol; @@ -2002,7 +2101,7 @@ coff_bfd_make_debug_symbol (bfd *abfd, void * ptr ATTRIBUTE_UNUSED, unsigned long sz ATTRIBUTE_UNUSED) { - bfd_size_type amt = sizeof (coff_symbol_type); + size_t amt = sizeof (coff_symbol_type); coff_symbol_type *new_symbol = (coff_symbol_type *) bfd_alloc (abfd, amt); if (new_symbol == NULL) @@ -2013,11 +2112,11 @@ coff_bfd_make_debug_symbol (bfd *abfd, new_symbol->native = (combined_entry_type *) bfd_zalloc (abfd, amt); if (!new_symbol->native) return NULL; - new_symbol->native->is_sym = TRUE; + new_symbol->native->is_sym = true; new_symbol->symbol.section = bfd_abs_section_ptr; new_symbol->symbol.flags = BSF_DEBUGGING; new_symbol->lineno = NULL; - new_symbol->done_lineno = FALSE; + new_symbol->done_lineno = false; new_symbol->symbol.the_bfd = abfd; return & new_symbol->symbol; @@ -2031,8 +2130,10 @@ coff_get_symbol_info (bfd *abfd, asymbol *symbol, symbol_info *ret) if (coffsymbol (symbol)->native != NULL && coffsymbol (symbol)->native->fix_value && coffsymbol (symbol)->native->is_sym) - ret->value = coffsymbol (symbol)->native->u.syment.n_value - - (bfd_hostptr_t) obj_raw_syments (abfd); + ret->value = + ((coffsymbol (symbol)->native->u.syment.n_value - + (bfd_hostptr_t) obj_raw_syments (abfd)) + / sizeof (combined_entry_type)); } /* Print out information about COFF symbol. */ @@ -2080,7 +2181,8 @@ coff_print_symbol (bfd *abfd, if (! combined->fix_value) val = (bfd_vma) combined->u.syment.n_value; else - val = combined->u.syment.n_value - (bfd_hostptr_t) root; + val = ((combined->u.syment.n_value - (bfd_hostptr_t) root) + / sizeof (combined_entry_type)); fprintf (file, "(sec %2d)(fl 0x%02x)(ty %3x)(scl %3d) (nx %d) 0x", combined->u.syment.n_scnum, @@ -2111,6 +2213,18 @@ coff_print_symbol (bfd *abfd, { case C_FILE: fprintf (file, "File "); + /* Add additional information if this isn't the filename + auxiliary entry. */ + if (auxp->u.auxent.x_file.x_ftype) + fprintf (file, "ftype %d fname \"%s\"", + auxp->u.auxent.x_file.x_ftype, + (char *) auxp->u.auxent.x_file.x_n.x_n.x_offset); + break; + + case C_DWARF: + fprintf (file, "AUX scnlen 0x%lx nreloc %ld", + (unsigned long) auxp->u.auxent.x_sect.x_scnlen, + auxp->u.auxent.x_sect.x_nreloc); break; case C_STAT: @@ -2130,7 +2244,7 @@ coff_print_symbol (bfd *abfd, auxp->u.auxent.x_scn.x_comdat); break; } - /* Otherwise fall through. */ + /* Fall through. */ case C_EXT: case C_AIX_WEAKEXT: if (ISFCN (combined->u.syment.n_type)) @@ -2150,7 +2264,7 @@ coff_print_symbol (bfd *abfd, llnos, next); break; } - /* Otherwise fall through. */ + /* Fall through. */ default: fprintf (file, "AUX lnno %d size 0x%x tagndx %ld", auxp->u.auxent.x_sym.x_misc.x_lnsz.x_lnno, @@ -2197,7 +2311,7 @@ coff_print_symbol (bfd *abfd, function for the is_local_label_name entry point, but some may override it. */ -bfd_boolean +bool _bfd_coff_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, const char *name) { @@ -2208,17 +2322,17 @@ _bfd_coff_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, section, calculate and return the name of the source file and the line nearest to the wanted location. */ -bfd_boolean +bool 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; + bool found; unsigned int i; unsigned int line_base; coff_data_type *cof = coff_data (abfd); @@ -2227,7 +2341,7 @@ coff_find_nearest_line_with_names (bfd *abfd, combined_entry_type *pend; alent *l; struct coff_section_tdata *sec_data; - bfd_size_type amt; + size_t amt; /* Before looking through the symbol table, try to use a .stab section to find the information. */ @@ -2235,17 +2349,19 @@ coff_find_nearest_line_with_names (bfd *abfd, &found, filename_ptr, functionname_ptr, line_ptr, &coff_data(abfd)->line_info)) - return FALSE; + return false; if (found) - return TRUE; + return true; /* Also try examining DWARF2 debugging information. */ if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset, filename_ptr, functionname_ptr, - line_ptr, NULL, debug_sections, 0, + line_ptr, NULL, debug_sections, &coff_data(abfd)->dwarf2_find_line_info)) - return TRUE; + return true; + + sec_data = coff_section_data (abfd, section); /* If the DWARF lookup failed, but there is DWARF information available then the problem might be that the file has been rebased. This tool @@ -2253,18 +2369,37 @@ coff_find_nearest_line_with_names (bfd *abfd, information. So try again, using a bias against the address sought. */ if (coff_data (abfd)->dwarf2_find_line_info != NULL) { - bfd_signed_vma bias; + bfd_signed_vma bias = 0; - bias = _bfd_dwarf2_find_symbol_bias (symbols, - & coff_data (abfd)->dwarf2_find_line_info); + /* Create a cache of the result for the next call. */ + if (sec_data == NULL && section->owner == abfd) + { + amt = sizeof (struct coff_section_tdata); + section->used_by_bfd = bfd_zalloc (abfd, amt); + sec_data = (struct coff_section_tdata *) section->used_by_bfd; + } + + if (sec_data != NULL && sec_data->saved_bias) + bias = sec_data->saved_bias; + else if (symbols) + { + bias = _bfd_dwarf2_find_symbol_bias (symbols, + & coff_data (abfd)->dwarf2_find_line_info); + + if (sec_data) + { + sec_data->saved_bias = true; + sec_data->bias = bias; + } + } if (bias && _bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset + bias, filename_ptr, functionname_ptr, - line_ptr, NULL, debug_sections, 0, + line_ptr, NULL, debug_sections, &coff_data(abfd)->dwarf2_find_line_info)) - return TRUE; + return true; } *filename_ptr = 0; @@ -2273,15 +2408,15 @@ coff_find_nearest_line_with_names (bfd *abfd, /* Don't try and find line numbers in a non coff file. */ if (!bfd_family_coff (abfd)) - return FALSE; + return false; if (cof == NULL) - return FALSE; + return false; /* Find the first C_FILE symbol. */ p = cof->raw_syments; if (!p) - return FALSE; + return false; pend = p + cof->raw_syment_count; while (p < pend) @@ -2298,7 +2433,7 @@ coff_find_nearest_line_with_names (bfd *abfd, bfd_vma maxdiff; /* Look through the C_FILE symbols to find the best one. */ - sec_vma = bfd_get_section_vma (abfd, section); + sec_vma = bfd_section_vma (section); *filename_ptr = (char *) p->u.syment._n._n_n._n_offset; maxdiff = (bfd_vma) 0 - (bfd_vma) 1; while (1) @@ -2331,7 +2466,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) @@ -2340,21 +2475,30 @@ coff_find_nearest_line_with_names (bfd *abfd, maxdiff = offset + sec_vma - p2->u.syment.n_value; } + if (p->u.syment.n_value >= cof->raw_syment_count) + break; + /* Avoid endless loops on erroneous files by ensuring that we always move forward in the file. */ if (p >= cof->raw_syments + p->u.syment.n_value) break; p = cof->raw_syments + p->u.syment.n_value; - if (p > pend || p->u.syment.n_sclass != C_FILE) + if (!p->is_sym || p->u.syment.n_sclass != C_FILE) break; } } - /* Now wander though the raw linenumbers of the section. */ - /* If we have been called on this section before, and the offset we - want is further down then we can prime the lookup loop. */ - sec_data = coff_section_data (abfd, section); + if (section->lineno_count == 0) + { + *functionname_ptr = NULL; + *line_ptr = 0; + return true; + } + + /* Now wander though the raw linenumbers of the section. + If we have been called on this section before, and the offset + we want is further down then we can prime the lookup loop. */ if (sec_data != NULL && sec_data->i > 0 && offset >= sec_data->offset) @@ -2383,6 +2527,7 @@ coff_find_nearest_line_with_names (bfd *abfd, coff_symbol_type *coff = (coff_symbol_type *) (l->u.sym); if (coff->symbol.value > offset) break; + *functionname_ptr = coff->symbol.name; last_value = coff->symbol.value; if (coff->native) @@ -2394,11 +2539,15 @@ coff_find_nearest_line_with_names (bfd *abfd, /* In XCOFF a debugging symbol can follow the function symbol. */ - if (s->u.syment.n_scnum == N_DEBUG) + if (((size_t) ((char *) s - (char *) obj_raw_syments (abfd)) + < obj_raw_syment_count (abfd) * sizeof (*s)) + && s->u.syment.n_scnum == N_DEBUG) s = s + 1 + s->u.syment.n_numaux; /* S should now point to the .bf of the function. */ - if (s->u.syment.n_numaux) + if (((size_t) ((char *) s - (char *) obj_raw_syments (abfd)) + < obj_raw_syment_count (abfd) * sizeof (*s)) + && s->u.syment.n_numaux) { /* The linenumber is stored in the auxent. */ union internal_auxent *a = &((s + 1)->u.auxent); @@ -2439,6 +2588,7 @@ coff_find_nearest_line_with_names (bfd *abfd, section->used_by_bfd = bfd_zalloc (abfd, amt); sec_data = (struct coff_section_tdata *) section->used_by_bfd; } + if (sec_data != NULL) { sec_data->offset = offset; @@ -2447,10 +2597,10 @@ coff_find_nearest_line_with_names (bfd *abfd, sec_data->line_base = line_base; } - return TRUE; + return true; } -bfd_boolean +bool coff_find_nearest_line (bfd *abfd, asymbol **symbols, asection *section, @@ -2463,17 +2613,17 @@ 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 +bool coff_find_inliner_info (bfd *abfd, const char **filename_ptr, const char **functionname_ptr, unsigned int *line_ptr) { - bfd_boolean found; + bool found; found = _bfd_dwarf2_find_inliner_info (abfd, filename_ptr, functionname_ptr, line_ptr, @@ -2486,7 +2636,7 @@ coff_sizeof_headers (bfd *abfd, struct bfd_link_info *info) { size_t size; - if (!info->relocatable) + if (!bfd_link_relocatable (info)) size = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd); else size = bfd_coff_filhsz (abfd); @@ -2497,10 +2647,10 @@ 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) +bool +bfd_coff_set_symbol_class (bfd * abfd, + asymbol * symbol, + unsigned int symbol_class) { coff_symbol_type * csym; @@ -2508,7 +2658,7 @@ bfd_coff_set_symbol_class (bfd * abfd, if (csym == NULL) { bfd_set_error (bfd_error_invalid_operation); - return FALSE; + return false; } else if (csym->native == NULL) { @@ -2518,13 +2668,13 @@ bfd_coff_set_symbol_class (bfd * abfd, coff_write_alien_symbol(). */ combined_entry_type * native; - bfd_size_type amt = sizeof (* native); + size_t amt = sizeof (* native); native = (combined_entry_type *) bfd_zalloc (abfd, amt); if (native == NULL) - return FALSE; + return false; - native->is_sym = TRUE; + native->is_sym = true; native->u.syment.n_type = T_NULL; native->u.syment.n_sclass = symbol_class; @@ -2557,10 +2707,10 @@ bfd_coff_set_symbol_class (bfd * abfd, else csym->native->u.syment.n_sclass = symbol_class; - return TRUE; + return true; } -bfd_boolean +bool _bfd_coff_section_already_linked (bfd *abfd, asection *sec, struct bfd_link_info *info) @@ -2571,22 +2721,25 @@ _bfd_coff_section_already_linked (bfd *abfd, struct bfd_section_already_linked_hash_entry *already_linked_list; struct coff_comdat_info *s_comdat; + if (sec->output_section == bfd_abs_section_ptr) + return false; + flags = sec->flags; if ((flags & SEC_LINK_ONCE) == 0) - return FALSE; + return false; /* The COFF backend linker doesn't support group sections. */ if ((flags & SEC_GROUP) != 0) - return FALSE; + return false; - name = bfd_get_section_name (abfd, sec); + name = bfd_section_name (sec); s_comdat = bfd_coff_get_comdat_section (abfd, sec); if (s_comdat != NULL) key = s_comdat->name; else { - if (CONST_STRNEQ (name, ".gnu.linkonce.") + if (startswith (name, ".gnu.linkonce.") && (key = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL) key++; else @@ -2613,7 +2766,8 @@ _bfd_coff_section_already_linked (bfd *abfd, .gnu.linkonce.*.. */ if (((s_comdat != NULL) == (l_comdat != NULL) && strcmp (name, l->sec->name) == 0) - || (l->sec->owner->flags & BFD_PLUGIN) != 0) + || (l->sec->owner->flags & BFD_PLUGIN) != 0 + || (sec->owner->flags & BFD_PLUGIN) != 0) { /* The section has already been linked. See if we should issue a warning. */ @@ -2624,12 +2778,12 @@ _bfd_coff_section_already_linked (bfd *abfd, /* This is the first section with this name. Record it. */ if (!bfd_section_already_linked_table_insert (already_linked_list, sec)) info->callbacks->einfo (_("%F%P: already_linked_table: %E\n")); - return FALSE; + return false; } /* Initialize COOKIE for input bfd ABFD. */ -static bfd_boolean +static bool init_reloc_cookie (struct coff_reloc_cookie *cookie, struct bfd_link_info *info ATTRIBUTE_UNUSED, bfd *abfd) @@ -2642,7 +2796,7 @@ init_reloc_cookie (struct coff_reloc_cookie *cookie, cookie->symbols = obj_symbols (abfd); - return TRUE; + return true; } /* Free the memory allocated by init_reloc_cookie, if appropriate. */ @@ -2657,7 +2811,7 @@ fini_reloc_cookie (struct coff_reloc_cookie *cookie ATTRIBUTE_UNUSED, /* Initialize the relocation information in COOKIE for input section SEC of input bfd ABFD. */ -static bfd_boolean +static bool init_reloc_cookie_rels (struct coff_reloc_cookie *cookie, struct bfd_link_info *info ATTRIBUTE_UNUSED, bfd *abfd, @@ -2668,17 +2822,18 @@ init_reloc_cookie_rels (struct coff_reloc_cookie *cookie, cookie->rels = NULL; cookie->relend = NULL; cookie->rel = NULL; - return TRUE; + return true; } - cookie->rels = _bfd_coff_read_internal_relocs (abfd, sec, FALSE, NULL, 0, NULL); + cookie->rels = _bfd_coff_read_internal_relocs (abfd, sec, false, NULL, + 0, NULL); if (cookie->rels == NULL) - return FALSE; + return false; cookie->rel = cookie->rels; cookie->relend = (cookie->rels + sec->reloc_count); - return TRUE; + return true; } /* Free the memory allocated by init_reloc_cookie_rels, @@ -2688,26 +2843,32 @@ static void fini_reloc_cookie_rels (struct coff_reloc_cookie *cookie, asection *sec) { - if (cookie->rels && coff_section_data (NULL, sec)->relocs != cookie->rels) + if (cookie->rels + /* PR 20401. The relocs may not have been cached, so check first. + If the relocs were loaded by init_reloc_cookie_rels() then this + will be the case. FIXME: Would performance be improved if the + relocs *were* cached ? */ + && coff_section_data (NULL, sec) + && coff_section_data (NULL, sec)->relocs != cookie->rels) free (cookie->rels); } /* Initialize the whole of COOKIE for input section SEC. */ -static bfd_boolean +static bool init_reloc_cookie_for_section (struct coff_reloc_cookie *cookie, struct bfd_link_info *info, asection *sec) { if (!init_reloc_cookie (cookie, info, sec->owner)) - return FALSE; + return false; if (!init_reloc_cookie_rels (cookie, info, sec->owner, sec)) { fini_reloc_cookie (cookie, sec->owner); - return FALSE; + return false; } - return TRUE; + return true; } /* Free the memory allocated by init_reloc_cookie_for_section, @@ -2731,19 +2892,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; } @@ -2776,14 +2951,14 @@ _bfd_coff_gc_mark_rsec (struct bfd_link_info *info, asection *sec, + obj_convert (sec->owner)[cookie->rel->r_symndx])->native->u.syment); } -static bfd_boolean _bfd_coff_gc_mark +static bool _bfd_coff_gc_mark (struct bfd_link_info *, asection *, coff_gc_mark_hook_fn); /* COOKIE->rel describes a relocation against section SEC, which is a section we've decided to keep. Mark the section that contains the relocation symbol. */ -static bfd_boolean +static bool _bfd_coff_gc_mark_reloc (struct bfd_link_info *info, asection *sec, coff_gc_mark_hook_fn gc_mark_hook, @@ -2797,21 +2972,21 @@ _bfd_coff_gc_mark_reloc (struct bfd_link_info *info, if (bfd_get_flavour (rsec->owner) != bfd_target_coff_flavour) rsec->gc_mark = 1; else if (!_bfd_coff_gc_mark (info, rsec, gc_mark_hook)) - return FALSE; + return false; } - return TRUE; + return true; } /* The mark phase of garbage collection. For a given section, mark it and any sections in this section's group, and all the sections which define symbols to which it refers. */ -static bfd_boolean +static bool _bfd_coff_gc_mark (struct bfd_link_info *info, asection *sec, coff_gc_mark_hook_fn gc_mark_hook) { - bfd_boolean ret = TRUE; + bool ret = true; sec->gc_mark = 1; @@ -2822,25 +2997,25 @@ _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; + ret = false; break; } } - fini_reloc_cookie_for_section (&cookie, sec); - } + fini_reloc_cookie_for_section (&cookie, sec); + } } return ret; } -static bfd_boolean +static bool _bfd_coff_gc_mark_extra_sections (struct bfd_link_info *info, coff_gc_mark_hook_fn mark_hook ATTRIBUTE_UNUSED) { @@ -2849,20 +3024,20 @@ _bfd_coff_gc_mark_extra_sections (struct bfd_link_info *info, for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { asection *isec; - bfd_boolean some_kept; + bool 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 any other section is already marked. */ - some_kept = FALSE; + some_kept = false; for (isec = ibfd->sections; isec != NULL; isec = isec->next) { if ((isec->flags & SEC_LINKER_CREATED) != 0) isec->gc_mark = 1; else if (isec->gc_mark) - some_kept = TRUE; + some_kept = true; } /* If no section in this file will be kept, then we can @@ -2877,12 +3052,12 @@ _bfd_coff_gc_mark_extra_sections (struct bfd_link_info *info, || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0) isec->gc_mark = 1; } - return TRUE; + return true; } /* Sweep symbols in swept sections. Called via coff_link_hash_traverse. */ -static bfd_boolean +static bool coff_gc_sweep_symbol (struct coff_link_hash_entry *h, void *data ATTRIBUTE_UNUSED) { @@ -2899,15 +3074,15 @@ coff_gc_sweep_symbol (struct coff_link_hash_entry *h, h->symbol_class = C_HIDDEN; } - return TRUE; + return true; } /* The sweep phase of garbage collection. Remove all garbage sections. */ -typedef bfd_boolean (*gc_sweep_hook_fn) +typedef bool (*gc_sweep_hook_fn) (bfd *, struct bfd_link_info *, asection *, const struct internal_reloc *); -static bfd_boolean +static bool coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) { bfd *sub; @@ -2922,13 +3097,13 @@ 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") - || CONST_STRNEQ (o->name, ".pdata") - || CONST_STRNEQ (o->name, ".xdata") - || CONST_STRNEQ (o->name, ".rsrc")) + else if (startswith (o->name, ".idata") + || startswith (o->name, ".pdata") + || startswith (o->name, ".xdata") + || startswith (o->name, ".rsrc")) o->gc_mark = 1; if (o->gc_mark) @@ -2943,7 +3118,9 @@ coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) o->flags |= SEC_EXCLUDE; if (info->print_gc_sections && o->size != 0) - _bfd_error_handler (_("Removing unused section '%s' in file '%B'"), sub, o->name); + /* xgettext: c-format */ + _bfd_error_handler (_("removing unused section '%pA' in file '%pB'"), + o, sub); #if 0 /* But we also have to update some of the relocation @@ -2954,13 +3131,13 @@ coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) && !bfd_is_abs_section (o->output_section)) { struct internal_reloc *internal_relocs; - bfd_boolean r; + bool r; internal_relocs = _bfd_coff_link_read_relocs (o->owner, o, NULL, NULL, info->keep_memory); if (internal_relocs == NULL) - return FALSE; + return false; r = (*gc_sweep_hook) (o->owner, info, o, internal_relocs); @@ -2968,7 +3145,7 @@ coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) free (internal_relocs); if (!r) - return FALSE; + return false; } #endif } @@ -2979,7 +3156,7 @@ coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) coff_link_hash_traverse (coff_hash_table (info), coff_gc_sweep_symbol, NULL); - return TRUE; + return true; } /* Keep all sections containing symbols undefined on the command-line, @@ -2995,7 +3172,7 @@ _bfd_coff_gc_keep (struct bfd_link_info *info) struct coff_link_hash_entry *h; h = coff_link_hash_lookup (coff_hash_table (info), sym->name, - FALSE, FALSE, FALSE); + false, false, false); if (h != NULL && (h->root.type == bfd_link_hash_defined @@ -3007,7 +3184,7 @@ _bfd_coff_gc_keep (struct bfd_link_info *info) /* Do mark and sweep of unused sections. */ -bfd_boolean +bool bfd_coff_gc_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) { bfd *sub; @@ -3019,8 +3196,8 @@ 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")); - return TRUE; + _bfd_error_handler(_("warning: gc-sections option ignored")); + return true; } #endif @@ -3032,20 +3209,20 @@ 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") - || CONST_STRNEQ (o->name, ".dtors")) + || startswith (o->name, ".vectors") + || startswith (o->name, ".ctors") + || startswith (o->name, ".dtors")) && !o->gc_mark) { if (!_bfd_coff_gc_mark (info, o, _bfd_coff_gc_mark_hook)) - return FALSE; + return false; } - } + } } /* Allow the backend to mark additional target specific sections. */ @@ -3054,3 +3231,37 @@ bfd_coff_gc_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) /* ... and mark SEC_EXCLUDE for those that go. */ return coff_gc_sweep (abfd, info); } + +/* Return name used to identify a comdat group. */ + +const char * +bfd_coff_group_name (bfd *abfd, const asection *sec) +{ + struct coff_comdat_info *ci = bfd_coff_get_comdat_section (abfd, sec); + if (ci != NULL) + return ci->name; + return NULL; +} + +bool +_bfd_coff_close_and_cleanup (bfd *abfd) +{ + struct coff_tdata *tdata = coff_data (abfd); + + if (tdata != NULL) + { + /* PR 25447: + Do not clear the keep_syms and keep_strings flags. + These may have been set by pe_ILF_build_a_bfd() indicating + that the syms and strings pointers are not to be freed. */ + if (bfd_get_format (abfd) == bfd_object + && bfd_family_coff (abfd) + && !_bfd_coff_free_symbols (abfd)) + return false; + + if (bfd_get_format (abfd) == bfd_object + || bfd_get_format (abfd) == bfd_core) + _bfd_dwarf2_cleanup_debug_info (abfd, &tdata->dwarf2_find_line_info); + } + return _bfd_generic_close_and_cleanup (abfd); +}