X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fdwarf2.c;h=c3d9ffc3c5f73369a3164a09431baa7645d9432f;hb=db4e407b539180099a2aa395571bd417daa1daeb;hp=057fd91317319105717ad8fa79d85e052b3d0117;hpb=dfc19da6a6d43390544fa446bb1a33723b339a77;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index 057fd91317..c3d9ffc3c5 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -35,6 +35,7 @@ #include "libbfd.h" #include "elf-bfd.h" #include "dwarf2.h" +#include "hashtab.h" /* The data in the .debug_line statement prologue looks like this. */ @@ -801,20 +802,21 @@ read_alt_indirect_string (struct comp_unit * unit, if (stash->alt_bfd_ptr == NULL) { - bfd * debug_bfd; - char * debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR); + bfd *debug_bfd; + char *debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR); if (debug_filename == NULL) return NULL; - if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL - || ! bfd_check_format (debug_bfd, bfd_object)) - { - if (debug_bfd) - bfd_close (debug_bfd); + debug_bfd = bfd_openr (debug_filename, NULL); + free (debug_filename); + if (debug_bfd == NULL) + /* FIXME: Should we report our failure to follow the debuglink ? */ + return NULL; - /* FIXME: Should we report our failure to follow the debuglink ? */ - free (debug_filename); + if (!bfd_check_format (debug_bfd, bfd_object)) + { + bfd_close (debug_bfd); return NULL; } stash->alt_bfd_ptr = debug_bfd; @@ -849,20 +851,21 @@ read_alt_indirect_ref (struct comp_unit * unit, if (stash->alt_bfd_ptr == NULL) { - bfd * debug_bfd; - char * debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR); + bfd *debug_bfd; + char *debug_filename = bfd_follow_gnu_debugaltlink (unit->abfd, DEBUGDIR); if (debug_filename == NULL) return FALSE; - if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL - || ! bfd_check_format (debug_bfd, bfd_object)) - { - if (debug_bfd) - bfd_close (debug_bfd); + debug_bfd = bfd_openr (debug_filename, NULL); + free (debug_filename); + if (debug_bfd == NULL) + /* FIXME: Should we report our failure to follow the debuglink ? */ + return NULL; - /* FIXME: Should we report our failure to follow the debuglink ? */ - free (debug_filename); + if (!bfd_check_format (debug_bfd, bfd_object)) + { + bfd_close (debug_bfd); return NULL; } stash->alt_bfd_ptr = debug_bfd; @@ -1410,6 +1413,8 @@ struct lookup_funcinfo The highest address of all prior functions after the lookup table is sorted, which is used for binary search. */ bfd_vma high_addr; + /* Index of this function, used to ensure qsort is stable. */ + unsigned int idx; }; struct varinfo @@ -1710,6 +1715,11 @@ compare_sequences (const void* a, const void* b) if (seq1->last_line->op_index > seq2->last_line->op_index) return -1; + /* num_lines is initially an index, to make the sort stable. */ + if (seq1->num_lines < seq2->num_lines) + return -1; + if (seq1->num_lines > seq2->num_lines) + return 1; return 0; } @@ -1736,12 +1746,14 @@ build_line_info_table (struct line_info_table * table, for (each_line = seq->last_line; each_line; each_line = each_line->prev_line) num_lines++; + seq->num_lines = num_lines; if (num_lines == 0) return TRUE; /* Allocate space for the line information lookup table. */ amt = sizeof (struct line_info*) * num_lines; line_info_lookup = (struct line_info**) bfd_alloc (table->abfd, amt); + seq->line_info_lookup = line_info_lookup; if (line_info_lookup == NULL) return FALSE; @@ -1751,10 +1763,6 @@ build_line_info_table (struct line_info_table * table, line_info_lookup[--line_index] = each_line; BFD_ASSERT (line_index == 0); - - seq->num_lines = num_lines; - seq->line_info_lookup = line_info_lookup; - return TRUE; } @@ -1790,7 +1798,7 @@ sort_line_sequences (struct line_info_table* table) sequences[n].prev_sequence = NULL; sequences[n].last_line = seq->last_line; sequences[n].line_info_lookup = NULL; - sequences[n].num_lines = 0; + sequences[n].num_lines = n; seq = seq->prev_sequence; free (last_seq); } @@ -2566,6 +2574,10 @@ compare_lookup_funcinfos (const void * a, const void * b) if (lookup1->high_addr > lookup2->high_addr) return 1; + if (lookup1->idx < lookup2->idx) + return -1; + if (lookup1->idx > lookup2->idx) + return 1; return 0; } @@ -2595,6 +2607,7 @@ build_lookup_funcinfo_table (struct comp_unit * unit) { entry = &lookup_funcinfo_table[--func_index]; entry->funcinfo = each; + entry->idx = func_index; /* Calculate the lowest and highest address for this function entry. */ low_addr = entry->funcinfo->arange.low; @@ -2733,7 +2746,7 @@ lookup_symbol_in_function_table (struct comp_unit *unit, bfd_vma best_fit_len = 0; struct arange *arange; const char *name = bfd_asymbol_name (sym); - asection *sec = bfd_get_section (sym); + asection *sec = bfd_asymbol_section (sym); for (each_func = unit->function_table; each_func; @@ -2781,7 +2794,7 @@ lookup_symbol_in_variable_table (struct comp_unit *unit, unsigned int *linenumber_ptr) { const char *name = bfd_asymbol_name (sym); - asection *sec = bfd_get_section (sym); + asection *sec = bfd_asymbol_section (sym); struct varinfo* each; for (each = unit->variable_table; each; each = each->prev_var) @@ -2809,13 +2822,13 @@ static bfd_boolean comp_unit_maybe_decode_line_info (struct comp_unit *, struct dwarf2_debug *); static bfd_boolean -find_abstract_instance (struct comp_unit * unit, - bfd_byte * orig_info_ptr, - struct attribute * attr_ptr, - const char ** pname, - bfd_boolean * is_linkage, - char ** filename_ptr, - int * linenumber_ptr) +find_abstract_instance (struct comp_unit *unit, + struct attribute *attr_ptr, + unsigned int recur_count, + const char **pname, + bfd_boolean *is_linkage, + char **filename_ptr, + int *linenumber_ptr) { bfd *abfd = unit->abfd; bfd_byte *info_ptr; @@ -2826,6 +2839,14 @@ find_abstract_instance (struct comp_unit * unit, struct attribute attr; const char *name = NULL; + if (recur_count == 100) + { + _bfd_error_handler + (_("DWARF error: abstract instance recursion detected")); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + /* DW_FORM_ref_addr can reference an entry in a different CU. It is an offset from the .debug_info section, not the current CU. */ if (attr_ptr->form == DW_FORM_ref_addr) @@ -2959,15 +2980,6 @@ find_abstract_instance (struct comp_unit * unit, info_ptr, info_ptr_end); if (info_ptr == NULL) break; - /* It doesn't ever make sense for DW_AT_specification to - refer to the same DIE. Stop simple recursion. */ - if (info_ptr == orig_info_ptr) - { - _bfd_error_handler - (_("DWARF error: abstract instance recursion detected")); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } switch (attr.name) { case DW_AT_name: @@ -2981,7 +2993,7 @@ find_abstract_instance (struct comp_unit * unit, } break; case DW_AT_specification: - if (!find_abstract_instance (unit, info_ptr, &attr, + if (!find_abstract_instance (unit, &attr, recur_count + 1, &name, is_linkage, filename_ptr, linenumber_ptr)) return FALSE; @@ -3072,7 +3084,7 @@ scan_unit_for_symbols (struct comp_unit *unit) { bfd *abfd = unit->abfd; bfd_byte *info_ptr = unit->first_child_die_ptr; - bfd_byte *info_ptr_end = unit->stash->info_ptr_end; + bfd_byte *info_ptr_end = unit->end_ptr; int nesting_level = 0; struct nest_funcinfo { struct funcinfo *func; @@ -3197,7 +3209,7 @@ scan_unit_for_symbols (struct comp_unit *unit) case DW_AT_abstract_origin: case DW_AT_specification: - if (!find_abstract_instance (unit, info_ptr, &attr, + if (!find_abstract_instance (unit, &attr, 0, &func->name, &func->is_linkage, &func->file, @@ -4045,7 +4057,7 @@ info_hash_lookup_funcinfo (struct info_hash_table *hash_table, struct info_list_node *node; struct arange *arange; const char *name = bfd_asymbol_name (sym); - asection *sec = bfd_get_section (sym); + asection *sec = bfd_asymbol_section (sym); for (node = lookup_info_hash_table (hash_table, name); node; @@ -4093,7 +4105,7 @@ info_hash_lookup_varinfo (struct info_hash_table *hash_table, unsigned int *linenumber_ptr) { const char *name = bfd_asymbol_name (sym); - asection *sec = bfd_get_section (sym); + asection *sec = bfd_asymbol_section (sym); struct varinfo* each; struct info_list_node *node; @@ -4229,8 +4241,8 @@ stash_maybe_enable_info_hash_tables (bfd *abfd, struct dwarf2_debug *stash) /* We need a forced update so that the info hash tables will be created even though there is no compilation unit. That happens if STASH_INFO_HASH_TRIGGER is 0. */ - stash_maybe_update_info_hash_tables (stash); - stash->info_hash_status = STASH_INFO_HASH_ON; + if (stash_maybe_update_info_hash_tables (stash)) + stash->info_hash_status = STASH_INFO_HASH_ON; } /* Find the file and line associated with a symbol and address using the @@ -4384,18 +4396,20 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, fail more quickly. */ return FALSE; + debug_bfd = bfd_openr (debug_filename, NULL); + free (debug_filename); + if (debug_bfd == NULL) + /* FIXME: Should we report our failure to follow the debuglink ? */ + return FALSE; + /* Set BFD_DECOMPRESS to decompress debug sections. */ - if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL - || !(debug_bfd->flags |= BFD_DECOMPRESS, - bfd_check_format (debug_bfd, bfd_object)) + debug_bfd->flags |= BFD_DECOMPRESS; + if (!bfd_check_format (debug_bfd, bfd_object) || (msec = find_debug_info (debug_bfd, debug_sections, NULL)) == NULL || !bfd_generic_link_read_symbols (debug_bfd)) { - if (debug_bfd) - bfd_close (debug_bfd); - /* FIXME: Should we report our failure to follow the debuglink ? */ - free (debug_filename); + bfd_close (debug_bfd); return FALSE; } @@ -4435,7 +4449,16 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, for (total_size = 0; msec; msec = find_debug_info (debug_bfd, debug_sections, msec)) - total_size += msec->size; + { + /* Catch PR25070 testcase overflowing size calculation here. */ + if (total_size + msec->size < total_size + || total_size + msec->size < msec->size) + { + bfd_set_error (bfd_error_no_memory); + return FALSE; + } + total_size += msec->size; + } stash->info_ptr_memory = (bfd_byte *) bfd_malloc (total_size); if (stash->info_ptr_memory == NULL) @@ -4552,6 +4575,25 @@ stash_comp_unit (struct dwarf2_debug *stash) return NULL; } +/* Hash function for an asymbol. */ + +static hashval_t +hash_asymbol (const void *sym) +{ + const asymbol *asym = sym; + return htab_hash_string (asym->name); +} + +/* Equality function for asymbols. */ + +static int +eq_asymbol (const void *a, const void *b) +{ + const asymbol *sa = a; + const asymbol *sb = b; + return strcmp (sa->name, sb->name) == 0; +} + /* Scan the debug information in PINFO looking for a DW_TAG_subprogram abbrev with a DW_AT_low_pc attached to it. Then lookup that same symbol in SYMBOLS and return the difference between the low_pc and @@ -4562,12 +4604,28 @@ _bfd_dwarf2_find_symbol_bias (asymbol ** symbols, void ** pinfo) { struct dwarf2_debug *stash; struct comp_unit * unit; + htab_t sym_hash; + bfd_signed_vma result = 0; + asymbol ** psym; stash = (struct dwarf2_debug *) *pinfo; if (stash == NULL || symbols == NULL) return 0; + sym_hash = htab_create_alloc (10, hash_asymbol, eq_asymbol, + NULL, xcalloc, free); + for (psym = symbols; * psym != NULL; psym++) + { + asymbol * sym = * psym; + + if (sym->flags & BSF_FUNCTION && sym->section != NULL) + { + void **slot = htab_find_slot (sym_hash, sym, INSERT); + *slot = sym; + } + } + for (unit = stash->all_comp_units; unit; unit = unit->next_unit) { struct funcinfo * func; @@ -4577,24 +4635,24 @@ _bfd_dwarf2_find_symbol_bias (asymbol ** symbols, void ** pinfo) for (func = unit->function_table; func != NULL; func = func->prev_func) if (func->name && func->arange.low) { - asymbol ** psym; + asymbol search, *sym; /* FIXME: Do we need to scan the aranges looking for the lowest pc value ? */ - for (psym = symbols; * psym != NULL; psym++) + search.name = func->name; + sym = htab_find (sym_hash, &search); + if (sym != NULL) { - asymbol * sym = * psym; - - if (sym->flags & BSF_FUNCTION - && sym->section != NULL - && strcmp (sym->name, func->name) == 0) - return ((bfd_signed_vma) func->arange.low) - - ((bfd_signed_vma) (sym->value + sym->section->vma)); + result = ((bfd_signed_vma) func->arange.low) - + ((bfd_signed_vma) (sym->value + sym->section->vma)); + goto done; } } } - return 0; + done: + htab_delete (sym_hash); + return result; } /* Find the source code location of SYMBOL. If SYMBOL is NULL @@ -4655,7 +4713,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd, if (do_line) { BFD_ASSERT (section == NULL && offset == 0 && functionname_ptr == NULL); - section = bfd_get_section (symbol); + section = bfd_asymbol_section (symbol); addr = symbol->value; } else