From 7056e928f74587934ef1c1944a3424dbf6dc2d68 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 26 Jun 2007 14:28:13 +0000 Subject: [PATCH] * dwarf2.c (find_line): New. Contains the duplicated code from: (_bfd_dwarf2_find_nearest_line): Use it. (_bfd_dwarf2_find_line): Use it. --- bfd/ChangeLog | 6 + bfd/dwarf2.c | 385 ++++++++++++++++------------------------------------------ 2 files changed, 114 insertions(+), 277 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a18f205bb9..fcad646829 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2007-06-26 H.J. Lu + + * dwarf2.c (find_line): New. Contains the duplicated code from: + (_bfd_dwarf2_find_nearest_line): Use it. + (_bfd_dwarf2_find_line): Use it. + 2007-06-26 Joseph Myers * elf32-arm.c (copy_eabi_attributes): Copy type of attributes. diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index 2ba3152d52..411a7154b5 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -2301,22 +2301,28 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash) return TRUE; } -/* The DWARF2 version of find_nearest_line. Return TRUE if the line - is found without error. ADDR_SIZE is the number of bytes in the - initial .debug_info length field and in the abbreviation offset. - You may use zero to indicate that the default value should be - used. */ +/* Find the source code location of SYMBOL. If SYMBOL is NULL + then find the nearest source code location corresponding to + the address SECTION + OFFSET. + Returns TRUE if the line is found without error and fills in + FILENAME_PTR and LINENUMBER_PTR. In the case where SYMBOL was + NULL the FUNCTIONNAME_PTR is also filled in. + SYMBOLS contains the symbol table for ABFD. + ADDR_SIZE is the number of bytes in the initial .debug_info length + field and in the abbreviation offset, or zero to indicate that the + default value should be used. */ -bfd_boolean -_bfd_dwarf2_find_nearest_line (bfd *abfd, - asection *section, - asymbol **symbols, - bfd_vma offset, - const char **filename_ptr, - const char **functionname_ptr, - unsigned int *linenumber_ptr, - unsigned int addr_size, - void **pinfo) +static bfd_boolean +find_line (bfd *abfd, + asection *section, + bfd_vma offset, + asymbol *symbol, + asymbol **symbols, + const char **filename_ptr, + const char **functionname_ptr, + unsigned int *linenumber_ptr, + unsigned int addr_size, + void **pinfo) { /* Read each compilation unit from the section .debug_info, and check to see if it contains the address we are searching for. If yes, @@ -2331,6 +2337,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd, bfd_vma addr; struct comp_unit* each; bfd_vma found = FALSE; + bfd_boolean do_line; stash = *pinfo; @@ -2351,7 +2358,22 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd, return FALSE; } - addr = offset; + do_line = (section == NULL + && offset == 0 + && functionname_ptr == NULL + && symbol != NULL); + if (do_line) + { + addr = symbol->value; + section = bfd_get_section (symbol); + } + else if (section != NULL + && functionname_ptr != NULL + && symbol == NULL) + addr = offset; + else + abort (); + if (section->output_section) addr += section->output_section->vma + section->output_offset; else @@ -2360,13 +2382,6 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd, *functionname_ptr = NULL; *linenumber_ptr = 0; - /* The DWARF2 spec says that the initial length field, and the - offset of the abbreviation table, should both be 4-byte values. - However, some compilers do things differently. */ - if (addr_size == 0) - addr_size = 4; - BFD_ASSERT (addr_size == 4 || addr_size == 8); - if (! *pinfo) { bfd *debug_bfd; @@ -2452,254 +2467,24 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd, /* Check the previously read comp. units first. */ for (each = stash->all_comp_units; each; each = each->next_unit) - if (comp_unit_contains_address (each, addr) - && comp_unit_find_nearest_line (each, addr, filename_ptr, - functionname_ptr, - linenumber_ptr, stash)) - { - found = TRUE; - goto done; - } - - /* Read each remaining comp. units checking each as they are read. */ - while (stash->info_ptr < stash->info_ptr_end) - { - bfd_vma length; - unsigned int offset_size = addr_size; - bfd_byte *info_ptr_unit = stash->info_ptr; - - length = read_4_bytes (stash->bfd, stash->info_ptr); - /* A 0xffffff length is the DWARF3 way of indicating we use - 64-bit offsets, instead of 32-bit offsets. */ - if (length == 0xffffffff) - { - offset_size = 8; - length = read_8_bytes (stash->bfd, stash->info_ptr + 4); - stash->info_ptr += 12; - } - /* A zero length is the IRIX way of indicating 64-bit offsets, - mostly because the 64-bit length will generally fit in 32 - bits, and the endianness helps. */ - else if (length == 0) - { - offset_size = 8; - length = read_4_bytes (stash->bfd, stash->info_ptr + 4); - stash->info_ptr += 8; - } - /* In the absence of the hints above, we assume 32-bit DWARF2 - offsets even for targets with 64-bit addresses, because: - a) most of the time these targets will not have generated - more than 2Gb of debug info and so will not need 64-bit - offsets, - and - b) if they do use 64-bit offsets but they are not using - the size hints that are tested for above then they are - not conforming to the DWARF3 standard anyway. */ - else if (addr_size == 8) - { - offset_size = 4; - stash->info_ptr += 4; - } - else - stash->info_ptr += 4; - - if (length > 0) - { - each = parse_comp_unit (stash, length, info_ptr_unit, - offset_size); - stash->info_ptr += length; - - if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr) - == stash->sec->size) - { - stash->sec = find_debug_info (stash->bfd, stash->sec); - stash->sec_info_ptr = stash->info_ptr; - } - - if (each) - { - each->next_unit = stash->all_comp_units; - stash->all_comp_units = each; - - /* DW_AT_low_pc and DW_AT_high_pc are optional for - compilation units. If we don't have them (i.e., - unit->high == 0), we need to consult the line info - table to see if a compilation unit contains the given - address. */ - if ((each->arange.high == 0 - || comp_unit_contains_address (each, addr)) - && comp_unit_find_nearest_line (each, addr, - filename_ptr, - functionname_ptr, - linenumber_ptr, - stash)) - { - found = TRUE; - goto done; - } - } - } - } - -done: - if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0) - unset_sections (stash); - - return found; -} - -/* The DWARF2 version of find_line. Return TRUE if the line is found - without error. */ - -bfd_boolean -_bfd_dwarf2_find_line (bfd *abfd, - asymbol **symbols, - asymbol *symbol, - const char **filename_ptr, - unsigned int *linenumber_ptr, - unsigned int addr_size, - void **pinfo) -{ - /* Read each compilation unit from the section .debug_info, and check - to see if it contains the address we are searching for. If yes, - lookup the address, and return the line number info. If no, go - on to the next compilation unit. - - We keep a list of all the previously read compilation units, and - a pointer to the next un-read compilation unit. Check the - previously read units before reading more. */ - struct dwarf2_debug *stash; - /* What address are we looking for? */ - bfd_vma addr; - struct comp_unit* each; - asection *section; - bfd_boolean found = FALSE; - - section = bfd_get_section (symbol); - - stash = *pinfo; - - if (! stash) - { - bfd_size_type amt = sizeof (struct dwarf2_debug); - - stash = bfd_zalloc (abfd, amt); - if (! stash) - return FALSE; - } - - /* In a relocatable file, 2 functions may have the same address. - We change the section vma so that they won't overlap. */ - if (!stash && (abfd->flags & (EXEC_P | DYNAMIC)) == 0) { - if (! place_sections (abfd, stash)) - return FALSE; - } - - addr = symbol->value; - if (section->output_section) - addr += section->output_section->vma + section->output_offset; - else - addr += section->vma; - - *filename_ptr = NULL; - *filename_ptr = NULL; - *linenumber_ptr = 0; - - if (! *pinfo) - { - bfd *debug_bfd; - bfd_size_type total_size; - asection *msec; - - *pinfo = stash; - - msec = find_debug_info (abfd, NULL); - if (msec == NULL) - { - char * debug_filename = bfd_follow_gnu_debuglink (abfd, DEBUGDIR); - - if (debug_filename == NULL) - /* No dwarf2 info, and no gnu_debuglink to follow. - Note that at this point the stash has been allocated, but - contains zeros. This lets future calls to this function - fail more quickly. */ - goto done; - - if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL - || ! bfd_check_format (debug_bfd, bfd_object) - || (msec = find_debug_info (debug_bfd, NULL)) == NULL) - { - if (debug_bfd) - bfd_close (debug_bfd); - /* FIXME: Should we report our failure to follow the debuglink ? */ - free (debug_filename); - goto done; - } - } + if (do_line) + found = (((symbol->flags & BSF_FUNCTION) == 0 + || comp_unit_contains_address (each, addr)) + && comp_unit_find_line (each, symbol, addr, + filename_ptr, linenumber_ptr, + stash)); else - debug_bfd = abfd; - - /* There can be more than one DWARF2 info section in a BFD these days. - Read them all in and produce one large stash. We do this in two - passes - in the first pass we just accumulate the section sizes. - In the second pass we read in the section's contents. The allows - us to avoid reallocing the data as we add sections to the stash. */ - for (total_size = 0; msec; msec = find_debug_info (debug_bfd, msec)) - total_size += msec->size; - - stash->info_ptr = bfd_alloc (debug_bfd, total_size); - if (stash->info_ptr == NULL) + found = (comp_unit_contains_address (each, addr) + && comp_unit_find_nearest_line (each, addr, + filename_ptr, + functionname_ptr, + linenumber_ptr, + stash)); + if (found) goto done; - - stash->info_ptr_end = stash->info_ptr; - - for (msec = find_debug_info (debug_bfd, NULL); - msec; - msec = find_debug_info (debug_bfd, msec)) - { - bfd_size_type size; - bfd_size_type start; - - size = msec->size; - if (size == 0) - continue; - - start = stash->info_ptr_end - stash->info_ptr; - - if ((bfd_simple_get_relocated_section_contents - (debug_bfd, msec, stash->info_ptr + start, symbols)) == NULL) - continue; - - stash->info_ptr_end = stash->info_ptr + start + size; - } - - BFD_ASSERT (stash->info_ptr_end == stash->info_ptr + total_size); - - stash->sec = find_debug_info (debug_bfd, NULL); - stash->sec_info_ptr = stash->info_ptr; - stash->syms = symbols; - stash->bfd = debug_bfd; } - /* A null info_ptr indicates that there is no dwarf2 info - (or that an error occured while setting up the stash). */ - if (! stash->info_ptr) - goto done; - - stash->inliner_chain = NULL; - - /* Check the previously read comp. units first. */ - for (each = stash->all_comp_units; each; each = each->next_unit) - if ((symbol->flags & BSF_FUNCTION) == 0 - || comp_unit_contains_address (each, addr)) - { - found = comp_unit_find_line (each, symbol, addr, filename_ptr, - linenumber_ptr, stash); - if (found) - goto done; - } - /* The DWARF2 spec says that the initial length field, and the offset of the abbreviation table, should both be 4-byte values. However, some compilers do things differently. */ @@ -2715,8 +2500,8 @@ _bfd_dwarf2_find_line (bfd *abfd, bfd_byte *info_ptr_unit = stash->info_ptr; length = read_4_bytes (stash->bfd, stash->info_ptr); - /* A 0xffffff length is the DWARF3 way of indicating we use - 64-bit offsets, instead of 32-bit offsets. */ + /* A 0xffffff length is the DWARF3 way of indicating + we use 64-bit offsets, instead of 32-bit offsets. */ if (length == 0xffffffff) { offset_size = 8; @@ -2772,13 +2557,22 @@ _bfd_dwarf2_find_line (bfd *abfd, unit->high == 0), we need to consult the line info table to see if a compilation unit contains the given address. */ - found = (((symbol->flags & BSF_FUNCTION) == 0 - || each->arange.high <= 0 - || comp_unit_contains_address (each, addr)) - && comp_unit_find_line (each, symbol, addr, - filename_ptr, - linenumber_ptr, - stash)); + if (do_line) + found = (((symbol->flags & BSF_FUNCTION) == 0 + || each->arange.high == 0 + || comp_unit_contains_address (each, addr)) + && comp_unit_find_line (each, symbol, addr, + filename_ptr, + linenumber_ptr, + stash)); + else + found = ((each->arange.high == 0 + || comp_unit_contains_address (each, addr)) + && comp_unit_find_nearest_line (each, addr, + filename_ptr, + functionname_ptr, + linenumber_ptr, + stash)); if (found) goto done; } @@ -2792,6 +2586,42 @@ done: return found; } +/* The DWARF2 version of find_nearest_line. + Return TRUE if the line is found without error. */ + +bfd_boolean +_bfd_dwarf2_find_nearest_line (bfd *abfd, + asection *section, + asymbol **symbols, + bfd_vma offset, + const char **filename_ptr, + const char **functionname_ptr, + unsigned int *linenumber_ptr, + unsigned int addr_size, + void **pinfo) +{ + return find_line (abfd, section, offset, NULL, symbols, filename_ptr, + functionname_ptr, linenumber_ptr, addr_size, + pinfo); +} + +/* The DWARF2 version of find_line. + Return TRUE if the line is found without error. */ + +bfd_boolean +_bfd_dwarf2_find_line (bfd *abfd, + asymbol **symbols, + asymbol *symbol, + const char **filename_ptr, + unsigned int *linenumber_ptr, + unsigned int addr_size, + void **pinfo) +{ + return find_line (abfd, NULL, 0, symbol, symbols, filename_ptr, + NULL, linenumber_ptr, addr_size, + pinfo); +} + bfd_boolean _bfd_dwarf2_find_inliner_info (bfd *abfd ATTRIBUTE_UNUSED, const char **filename_ptr, @@ -2805,17 +2635,18 @@ _bfd_dwarf2_find_inliner_info (bfd *abfd ATTRIBUTE_UNUSED, if (stash) { struct funcinfo *func = stash->inliner_chain; + if (func && func->caller_func) { *filename_ptr = func->caller_file; *functionname_ptr = func->caller_func->name; *linenumber_ptr = func->caller_line; stash->inliner_chain = func->caller_func; - return (TRUE); + return TRUE; } } - return (FALSE); + return FALSE; } void -- 2.11.0