From a2a5095467760e431d692bee57d524bf218c6ab7 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 16 May 2012 13:57:11 +0000 Subject: [PATCH] * dwarf2.c: Formatting. (arange_add): Pass in unit rather than bfd. Update callers. Ignore empty ranges. Don't ask for cleared memory. (parse_comp_unit): Only set unit->base_address if processing DW_TAG_compile_unit. (find_debug_info): Optimise section lookup. (place_sections): Use bfd_alloc for stash->adjusted_sections. (find_line): Match previously parsed comp unit addresses as we do for newly parsed comp units. --- bfd/ChangeLog | 12 ++++ bfd/dwarf2.c | 188 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 127 insertions(+), 73 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9db6ed35ae3..760d4d9390d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +2012-05-16 Alan Modra + + * dwarf2.c: Formatting. + (arange_add): Pass in unit rather than bfd. Update callers. + Ignore empty ranges. Don't ask for cleared memory. + (parse_comp_unit): Only set unit->base_address if processing + DW_TAG_compile_unit. + (find_debug_info): Optimise section lookup. + (place_sections): Use bfd_alloc for stash->adjusted_sections. + (find_line): Match previously parsed comp unit addresses as we + do for newly parsed comp units. + 2012-05-16 Alan Modra * archive.c (_bfd_generic_read_ar_hdr_mag): Ensure sscanf diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index f7d5d4a1132..d31b84939ad 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -405,8 +405,8 @@ create_info_hash_table (bfd *abfd) { struct info_hash_table *hash_table; - hash_table = (struct info_hash_table *) - bfd_alloc (abfd, sizeof (struct info_hash_table)); + hash_table = ((struct info_hash_table *) + bfd_alloc (abfd, sizeof (struct info_hash_table))); if (!hash_table) return hash_table; @@ -503,7 +503,7 @@ read_section (bfd * abfd, if (syms) { *section_buffer - = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, syms); + = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, syms); if (! *section_buffer) return FALSE; } @@ -522,7 +522,8 @@ read_section (bfd * abfd, that the client wants. Validate it here to avoid trouble later. */ if (offset != 0 && offset >= *section_size) { - (*_bfd_error_handler) (_("Dwarf Error: Offset (%lu) greater than or equal to %s size (%lu)."), + (*_bfd_error_handler) (_("Dwarf Error: Offset (%lu)" + " greater than or equal to %s size (%lu)."), (long) offset, section_name, *section_size); bfd_set_error (bfd_error_bad_value); return FALSE; @@ -1014,20 +1015,27 @@ struct line_info_table /* Remember some information about each function. If the function is inlined (DW_TAG_inlined_subroutine) it may have two additional attributes, DW_AT_call_file and DW_AT_call_line, which specify the - source code location where this function was inlined. */ + source code location where this function was inlined. */ struct funcinfo { - struct funcinfo *prev_func; /* Pointer to previous function in list of all functions */ - struct funcinfo *caller_func; /* Pointer to function one scope higher */ - char *caller_file; /* Source location file name where caller_func inlines this func */ - int caller_line; /* Source location line number where caller_func inlines this func */ - char *file; /* Source location file name */ - int line; /* Source location line number */ + /* Pointer to previous function in list of all functions. */ + struct funcinfo *prev_func; + /* Pointer to function one scope higher. */ + struct funcinfo *caller_func; + /* Source location file name where caller_func inlines this func. */ + char *caller_file; + /* Source location line number where caller_func inlines this func. */ + int caller_line; + /* Source location file name. */ + char *file; + /* Source location line number. */ + int line; int tag; char *name; struct arange arange; - asection *sec; /* Where the symbol is defined */ + /* Where the symbol is defined. */ + asection *sec; }; struct varinfo @@ -1248,12 +1256,16 @@ concat_filename (struct line_info_table *table, unsigned int file) } static bfd_boolean -arange_add (bfd *abfd, struct arange *first_arange, +arange_add (const struct comp_unit *unit, struct arange *first_arange, bfd_vma low_pc, bfd_vma high_pc) { struct arange *arange; - /* If the first arange is empty, use it. */ + /* Ignore empty ranges. */ + if (low_pc == high_pc) + return TRUE; + + /* If the first arange is empty, use it. */ if (first_arange->high == 0) { first_arange->low = low_pc; @@ -1281,7 +1293,7 @@ arange_add (bfd *abfd, struct arange *first_arange, /* Need to allocate a new arange and insert it into the arange list. Order isn't significant, so just insert after the first arange. */ - arange = (struct arange *) bfd_zalloc (abfd, sizeof (*arange)); + arange = (struct arange *) bfd_alloc (unit->abfd, sizeof (*arange)); if (arange == NULL) return FALSE; arange->low = low_pc; @@ -1582,15 +1594,15 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) /* Special operand. */ adj_opcode = op_code - lh.opcode_base; if (lh.maximum_ops_per_insn == 1) - address += (adj_opcode / lh.line_range) - * lh.minimum_instruction_length; + address += (adj_opcode / lh.line_range + * lh.minimum_instruction_length); else { - address += ((op_index + (adj_opcode / lh.line_range)) - / lh.maximum_ops_per_insn) - * lh.minimum_instruction_length; - op_index = (op_index + (adj_opcode / lh.line_range)) - % lh.maximum_ops_per_insn; + address += ((op_index + adj_opcode / lh.line_range) + / lh.maximum_ops_per_insn + * lh.minimum_instruction_length); + op_index = ((op_index + adj_opcode / lh.line_range) + % lh.maximum_ops_per_insn); } line += lh.line_base + (adj_opcode % lh.line_range); /* Append row to matrix using current values. */ @@ -1605,7 +1617,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) else switch (op_code) { case DW_LNS_extended_op: - exop_len = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + exop_len = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; extended_op = read_1_byte (abfd, line_ptr); line_ptr += 1; @@ -1621,7 +1633,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) low_pc = address; if (address > high_pc) high_pc = address; - if (!arange_add (unit->abfd, &unit->arange, low_pc, high_pc)) + if (!arange_add (unit, &unit->arange, low_pc, high_pc)) goto line_fail; break; case DW_LNE_set_address: @@ -1659,11 +1671,12 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; break; - case DW_LNE_HP_source_file_correlation: - line_ptr += exop_len - 1; - break; + case DW_LNE_HP_source_file_correlation: + line_ptr += exop_len - 1; + break; default: - (*_bfd_error_handler) (_("Dwarf Error: mangled line number section.")); + (*_bfd_error_handler) + (_("Dwarf Error: mangled line number section.")); bfd_set_error (bfd_error_bad_value); line_fail: if (filename != NULL) @@ -1682,15 +1695,15 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) break; case DW_LNS_advance_pc: if (lh.maximum_ops_per_insn == 1) - address += lh.minimum_instruction_length - * read_unsigned_leb128 (abfd, line_ptr, - &bytes_read); + address += (lh.minimum_instruction_length + * read_unsigned_leb128 (abfd, line_ptr, + &bytes_read)); else { bfd_vma adjust = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - address = ((op_index + adjust) / lh.maximum_ops_per_insn) - * lh.minimum_instruction_length; + address = ((op_index + adjust) / lh.maximum_ops_per_insn + * lh.minimum_instruction_length); op_index = (op_index + adjust) % lh.maximum_ops_per_insn; } line_ptr += bytes_read; @@ -1723,13 +1736,14 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) break; case DW_LNS_const_add_pc: if (lh.maximum_ops_per_insn == 1) - address += lh.minimum_instruction_length - * ((255 - lh.opcode_base) / lh.line_range); + address += (lh.minimum_instruction_length + * ((255 - lh.opcode_base) / lh.line_range)); else { bfd_vma adjust = ((255 - lh.opcode_base) / lh.line_range); - address += lh.minimum_instruction_length - * ((op_index + adjust) / lh.maximum_ops_per_insn); + address += (lh.minimum_instruction_length + * ((op_index + adjust) + / lh.maximum_ops_per_insn)); op_index = (op_index + adjust) % lh.maximum_ops_per_insn; } break; @@ -1855,8 +1869,9 @@ lookup_address_in_function_table (struct comp_unit *unit, { if (addr >= arange->low && addr < arange->high) { - if (!best_fit || - ((arange->high - arange->low) < (best_fit->arange.high - best_fit->arange.low))) + if (!best_fit + || (arange->high - arange->low + < best_fit->arange.high - best_fit->arange.low)) best_fit = each_func; } } @@ -1904,8 +1919,8 @@ lookup_symbol_in_function_table (struct comp_unit *unit, && each_func->name && strcmp (name, each_func->name) == 0 && (!best_fit - || ((arange->high - arange->low) - < (best_fit->arange.high - best_fit->arange.low)))) + || (arange->high - arange->low + < best_fit->arange.high - best_fit->arange.low))) best_fit = each_func; } } @@ -1990,8 +2005,8 @@ find_abstract_instance_name (struct comp_unit *unit, abbrev = lookup_abbrev (abbrev_number, unit->abbrevs); if (! abbrev) { - (*_bfd_error_handler) (_("Dwarf Error: Could not find abbrev number %u."), - abbrev_number); + (*_bfd_error_handler) + (_("Dwarf Error: Could not find abbrev number %u."), abbrev_number); bfd_set_error (bfd_error_bad_value); } else @@ -2056,7 +2071,7 @@ read_rangelist (struct comp_unit *unit, struct arange *arange, base_address = high_pc; else { - if (!arange_add (unit->abfd, arange, + if (!arange_add (unit, arange, base_address + low_pc, base_address + high_pc)) return FALSE; } @@ -2082,7 +2097,7 @@ scan_unit_for_symbols (struct comp_unit *unit) can use to set the caller_func field. */ nested_funcs_size = 32; nested_funcs = (struct funcinfo **) - bfd_malloc (nested_funcs_size * sizeof (struct funcinfo *)); + bfd_malloc (nested_funcs_size * sizeof (struct funcinfo *)); if (nested_funcs == NULL) return FALSE; nested_funcs[nesting_level] = 0; @@ -2286,7 +2301,7 @@ scan_unit_for_symbols (struct comp_unit *unit) if (func && high_pc != 0) { - if (!arange_add (unit->abfd, &func->arange, low_pc, high_pc)) + if (!arange_add (unit, &func->arange, low_pc, high_pc)) goto fail; } @@ -2300,8 +2315,8 @@ scan_unit_for_symbols (struct comp_unit *unit) nested_funcs_size *= 2; tmp = (struct funcinfo **) - bfd_realloc (nested_funcs, - (nested_funcs_size * sizeof (struct funcinfo *))); + bfd_realloc (nested_funcs, + nested_funcs_size * sizeof (struct funcinfo *)); if (tmp == NULL) goto fail; nested_funcs = tmp; @@ -2362,23 +2377,29 @@ parse_comp_unit (struct dwarf2_debug *stash, if (version != 2 && version != 3 && version != 4) { - (*_bfd_error_handler) (_("Dwarf Error: found dwarf version '%u', this reader only handles version 2, 3 and 4 information."), version); + (*_bfd_error_handler) + (_("Dwarf Error: found dwarf version '%u', this reader" + " only handles version 2, 3 and 4 information."), version); bfd_set_error (bfd_error_bad_value); return 0; } if (addr_size > sizeof (bfd_vma)) { - (*_bfd_error_handler) (_("Dwarf Error: found address size '%u', this reader can not handle sizes greater than '%u'."), - addr_size, - (unsigned int) sizeof (bfd_vma)); + (*_bfd_error_handler) + (_("Dwarf Error: found address size '%u', this reader" + " can not handle sizes greater than '%u'."), + addr_size, + (unsigned int) sizeof (bfd_vma)); bfd_set_error (bfd_error_bad_value); return 0; } if (addr_size != 2 && addr_size != 4 && addr_size != 8) { - (*_bfd_error_handler) ("Dwarf Error: found address size '%u', this reader can only handle address sizes '2', '4' and '8'.", addr_size); + (*_bfd_error_handler) + ("Dwarf Error: found address size '%u', this reader" + " can only handle address sizes '2', '4' and '8'.", addr_size); bfd_set_error (bfd_error_bad_value); return 0; } @@ -2386,14 +2407,14 @@ parse_comp_unit (struct dwarf2_debug *stash, /* Read the abbrevs for this compilation unit into a table. */ abbrevs = read_abbrevs (abfd, abbrev_offset, stash); if (! abbrevs) - return 0; + return 0; abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); info_ptr += bytes_read; if (! abbrev_number) { (*_bfd_error_handler) (_("Dwarf Error: Bad abbrev number: %u."), - abbrev_number); + abbrev_number); bfd_set_error (bfd_error_bad_value); return 0; } @@ -2402,7 +2423,7 @@ parse_comp_unit (struct dwarf2_debug *stash, if (! abbrev) { (*_bfd_error_handler) (_("Dwarf Error: Could not find abbrev number %u."), - abbrev_number); + abbrev_number); bfd_set_error (bfd_error_bad_value); return 0; } @@ -2445,7 +2466,8 @@ parse_comp_unit (struct dwarf2_debug *stash, /* If the compilation unit DIE has a DW_AT_low_pc attribute, this is the base address to use when reading location lists or range lists. */ - unit->base_address = low_pc; + if (abbrev->tag == DW_TAG_compile_unit) + unit->base_address = low_pc; break; case DW_AT_high_pc: @@ -2482,7 +2504,7 @@ parse_comp_unit (struct dwarf2_debug *stash, high_pc += low_pc; if (high_pc != 0) { - if (!arange_add (unit->abfd, &unit->arange, low_pc, high_pc)) + if (!arange_add (unit, &unit->arange, low_pc, high_pc)) return NULL; } @@ -2752,25 +2774,43 @@ static asection * find_debug_info (bfd *abfd, const struct dwarf_debug_section *debug_sections, asection *after_sec) { - asection * msec; + asection *msec; + const char *look; + + if (after_sec == NULL) + { + look = debug_sections[debug_info].uncompressed_name; + msec = bfd_get_section_by_name (abfd, look); + if (msec != NULL) + return msec; - msec = after_sec != NULL ? after_sec->next : abfd->sections; + look = debug_sections[debug_info].compressed_name; + if (look != NULL) + { + msec = bfd_get_section_by_name (abfd, look); + if (msec != NULL) + return msec; + } - while (msec) + for (msec = abfd->sections; msec != NULL; msec = msec->next) + if (CONST_STRNEQ (msec->name, GNU_LINKONCE_INFO)) + return msec; + + return NULL; + } + + for (msec = after_sec->next; msec != NULL; msec = msec->next) { - if (strcmp (msec->name, - debug_sections[debug_info].uncompressed_name) == 0) + look = debug_sections[debug_info].uncompressed_name; + if (strcmp (msec->name, look) == 0) return msec; - if (debug_sections[debug_info].compressed_name != NULL - && strcmp (msec->name, - debug_sections[debug_info].compressed_name) == 0) + look = debug_sections[debug_info].compressed_name; + if (look != NULL && strcmp (msec->name, look) == 0) return msec; if (CONST_STRNEQ (msec->name, GNU_LINKONCE_INFO)) return msec; - - msec = msec->next; } return NULL; @@ -2844,7 +2884,7 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash) } amt = i * sizeof (struct adjusted_section); - p = (struct adjusted_section *) bfd_zalloc (abfd, amt); + p = (struct adjusted_section *) bfd_alloc (abfd, amt); if (! p) return FALSE; @@ -2938,8 +2978,8 @@ info_hash_lookup_funcinfo (struct info_hash_table *hash_table, && addr >= arange->low && addr < arange->high && (!best_fit - || ((arange->high - arange->low) - < (best_fit->arange.high - best_fit->arange.low)))) + || (arange->high - arange->low + < best_fit->arange.high - best_fit->arange.low))) best_fit = each_func; } } @@ -3359,6 +3399,7 @@ find_line (bfd *abfd, /* Check the previously read comp. units first. */ for (each = stash->all_comp_units; each; each = each->next_unit) if ((symbol->flags & BSF_FUNCTION) == 0 + || each->arange.high == 0 || comp_unit_contains_address (each, addr)) { found = comp_unit_find_line (each, symbol, addr, filename_ptr, @@ -3372,7 +3413,8 @@ find_line (bfd *abfd, { for (each = stash->all_comp_units; each; each = each->next_unit) { - found = (comp_unit_contains_address (each, addr) + found = ((each->arange.high == 0 + || comp_unit_contains_address (each, addr)) && comp_unit_find_nearest_line (each, addr, filename_ptr, functionname_ptr, @@ -3485,7 +3527,7 @@ find_line (bfd *abfd, } } -done: + done: if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0) unset_sections (stash); -- 2.30.2