X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fcoffgen.c;h=94589b43d2f0d21d70e4caa87e2fb763cc0c0c28;hb=1ee1a363454d88a87ad2ade7530b2a7fb670021e;hp=309e1249ac8a4f598c2eebe1dbb207fe0873876b;hpb=827041555ac443bd57340060f3e034fd7b199dd8;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/coffgen.c b/bfd/coffgen.c index 309e1249ac..94589b43d2 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-2019 Free Software Foundation, Inc. + Copyright (C) 1990-2020 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" @@ -216,7 +217,7 @@ make_a_section_from_file (bfd *abfd, break; } if (new_name != NULL) - bfd_rename_section (abfd, return_section, new_name); + bfd_rename_section (return_section, new_name); } return result; @@ -224,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 * +bfd_cleanup coff_real_object_p (bfd *abfd, unsigned nscns, struct internal_filehdr *internal_f, @@ -256,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. */ @@ -274,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)) @@ -301,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; @@ -329,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); @@ -362,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); @@ -552,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) { @@ -574,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; } @@ -835,7 +822,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) { @@ -1590,19 +1577,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; @@ -1636,50 +1624,28 @@ copy_name (bfd *abfd, char *name, size_t maxlen) bfd_boolean _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; symesz = bfd_coff_symesz (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))) - + if (_bfd_mul_overflow (obj_raw_syment_count (abfd), symesz, &size)) { - _bfd_error_handler (_("%pB: corrupt symbol count: %#" PRIx64 ""), - abfd, (uint64_t) obj_raw_syment_count (abfd)); + bfd_set_error (bfd_error_file_truncated); return FALSE; } - syms = bfd_malloc (size); - if (syms == NULL) - { - /* PR 21013: Provide an error message when the alloc fails. */ - _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; - } - - if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0 - || bfd_bread (syms, size, abfd) != size) - { - if (syms != NULL) - free (syms); - return FALSE; - } + if (size == 0) + 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 TRUE; + return syms != NULL; } /* Read in the external strings. The strings are not loaded until @@ -1695,6 +1661,7 @@ _bfd_coff_read_string_table (bfd *abfd) bfd_size_type strsize; char *strings; file_ptr pos; + ufile_ptr filesize; if (obj_coff_strings (abfd) != NULL) return obj_coff_strings (abfd); @@ -1728,7 +1695,9 @@ _bfd_coff_read_string_table (bfd *abfd) #endif } - if (strsize < STRING_SIZE_SIZE || strsize > bfd_get_file_size (abfd)) + filesize = bfd_get_file_size (abfd); + if (strsize < STRING_SIZE_SIZE + || (filesize != 0 && strsize > filesize)) { _bfd_error_handler /* xgettext: c-format */ @@ -1813,10 +1782,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 < obj_raw_syment_count (abfd)) + 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; @@ -1843,11 +1813,8 @@ coff_get_normalized_symtab (bfd *abfd) symbol_ptr = internal_ptr; 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 - raw_src) / symesz) { bfd_release (abfd, internal); return NULL; @@ -1858,14 +1825,8 @@ 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, @@ -1878,10 +1839,13 @@ coff_get_normalized_symtab (bfd *abfd) } } - /* 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++) @@ -2014,13 +1978,20 @@ coff_get_reloc_upper_bound (bfd *abfd, sec_ptr asect) bfd_set_error (bfd_error_invalid_operation); return -1; } +#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 + 1) * 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) @@ -2041,7 +2012,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) @@ -2266,7 +2237,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. */ @@ -2282,7 +2253,7 @@ coff_find_nearest_line_with_names (bfd *abfd, /* 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; @@ -2294,7 +2265,7 @@ 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; /* Create a cache of the result for the next call. */ if (sec_data == NULL && section->owner == abfd) @@ -2306,10 +2277,11 @@ coff_find_nearest_line_with_names (bfd *abfd, if (sec_data != NULL && sec_data->saved_bias) bias = sec_data->saved_bias; - else + 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; @@ -2321,7 +2293,7 @@ coff_find_nearest_line_with_names (bfd *abfd, && _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; } @@ -2357,7 +2329,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) @@ -2399,13 +2371,16 @@ 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; } } @@ -2585,7 +2560,7 @@ 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) @@ -2638,6 +2613,9 @@ _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; @@ -2646,7 +2624,7 @@ _bfd_coff_section_already_linked (bfd *abfd, if ((flags & SEC_GROUP) != 0) 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) @@ -3143,3 +3121,31 @@ 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; +} + +bfd_boolean +_bfd_coff_close_and_cleanup (bfd *abfd) +{ + if (abfd->format == bfd_object + && bfd_family_coff (abfd) + && coff_data (abfd) != 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_coff_free_symbols (abfd)) + return FALSE; + } + return _bfd_generic_close_and_cleanup (abfd); +}