From 425bd9e1bb32b25881dd20d76678d041f7bf04f8 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Thu, 5 Mar 2015 12:14:26 +0000 Subject: [PATCH] Allows the binutils to cope with PE binaries where the section addresses have been changed, but the DWARF debug info has not been altered. PR binutils/18025 * coffgen.c (coff_find_nearest_line_with_names): If the dwarf2 lookup fails, check for an address bias in the dwarf info, and if one exists, retry the lookup with the biased value. * dwarf2.c (_bfd_dwarf2_find_symbol_bias): New function. Determines if a bias exists bewteen the addresses of functions based on DWARF information vs symbol table information. * libbfd-in.h (_bfd_dwarf2_find_symbol_bias): Prototype. * libbfd.h: Regenerate. --- bfd/ChangeLog | 12 ++++++++++++ bfd/coffgen.c | 20 +++++++++++++++++++ bfd/dwarf2.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ bfd/libbfd-in.h | 4 ++++ bfd/libbfd.h | 4 ++++ 5 files changed, 91 insertions(+) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index db02752683..3f8cc863ea 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +2015-03-05 Nick Clifton + + PR binutils/18025 + * coffgen.c (coff_find_nearest_line_with_names): If the dwarf2 + lookup fails, check for an address bias in the dwarf info, and if + one exists, retry the lookup with the biased value. + * dwarf2.c (_bfd_dwarf2_find_symbol_bias): New function. + Determines if a bias exists bewteen the addresses of functions + based on DWARF information vs symbol table information. + * libbfd-in.h (_bfd_dwarf2_find_symbol_bias): Prototype. + * libbfd.h: Regenerate. + 2015-03-04 Marcus Shawcroft * elfxx-aarch64.c (decode_add_imm, decode_movw_imm) diff --git a/bfd/coffgen.c b/bfd/coffgen.c index 83673d4846..5c664a49f2 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -2245,6 +2245,26 @@ coff_find_nearest_line_with_names (bfd *abfd, &coff_data(abfd)->dwarf2_find_line_info)) return TRUE; + /* If the DWARF lookup failed, but there is DWARF information available + then the problem might be that the file has been rebased. This tool + changes the VMAs of all the sections, but it does not update the DWARF + information. So try again, using a bias against the address sought. */ + if (coff_data (abfd)->dwarf2_find_line_info != NULL) + { + bfd_signed_vma bias; + + bias = _bfd_dwarf2_find_symbol_bias (symbols, + & coff_data (abfd)->dwarf2_find_line_info); + + if (bias + && _bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, + offset + bias, + filename_ptr, functionname_ptr, + line_ptr, NULL, debug_sections, 0, + &coff_data(abfd)->dwarf2_find_line_info)) + return TRUE; + } + *filename_ptr = 0; *functionname_ptr = 0; *line_ptr = 0; diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index 0a5d1cec4d..cbd4cf6486 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -3788,6 +3788,57 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, return TRUE; } +/* 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 + the symbol's address. Returns 0 if no suitable symbol could be found. */ + +bfd_signed_vma +_bfd_dwarf2_find_symbol_bias (asymbol ** symbols, void ** pinfo) +{ + struct dwarf2_debug *stash; + struct comp_unit * unit; + + stash = (struct dwarf2_debug *) *pinfo; + + if (stash == NULL) + return 0; + + for (unit = stash->all_comp_units; unit; unit = unit->next_unit) + { + struct funcinfo * func; + + if (unit->function_table == NULL) + { + if (unit->line_table == NULL) + unit->line_table = decode_line_info (unit, stash); + if (unit->line_table != NULL) + scan_unit_for_symbols (unit); + } + + for (func = unit->function_table; func != NULL; func = func->prev_func) + if (func->name && func->arange.low) + { + asymbol ** psym; + + /* FIXME: Do we need to scan the aranges looking for the lowest pc value ? */ + + for (psym = symbols; * psym != NULL; psym++) + { + 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)); + } + } + } + + return 0; +} + /* Find the source code location of SYMBOL. If SYMBOL is NULL then find the nearest source code location corresponding to the address SECTION + OFFSET. diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index 7c661e3479..06fa652e67 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -551,6 +551,10 @@ extern bfd_boolean _bfd_dwarf2_find_nearest_line const char **, const char **, unsigned int *, unsigned int *, const struct dwarf_debug_section *, unsigned int, void **); +/* Find the bias between DWARF addresses and real addresses. */ +extern bfd_signed_vma _bfd_dwarf2_find_symbol_bias + (asymbol **, void **); + /* Find inliner info after calling bfd_find_nearest_line. */ extern bfd_boolean _bfd_dwarf2_find_inliner_info (bfd *, const char **, const char **, unsigned int *, void **); diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 2aafecfbb1..14600aa1aa 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -556,6 +556,10 @@ extern bfd_boolean _bfd_dwarf2_find_nearest_line const char **, const char **, unsigned int *, unsigned int *, const struct dwarf_debug_section *, unsigned int, void **); +/* Find the bias between DWARF addresses and real addresses. */ +extern bfd_signed_vma _bfd_dwarf2_find_symbol_bias + (asymbol **, void **); + /* Find inliner info after calling bfd_find_nearest_line. */ extern bfd_boolean _bfd_dwarf2_find_inliner_info (bfd *, const char **, const char **, unsigned int *, void **);