aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog12
-rw-r--r--bfd/coffgen.c20
-rw-r--r--bfd/dwarf2.c51
-rw-r--r--bfd/libbfd-in.h4
-rw-r--r--bfd/libbfd.h4
5 files changed, 91 insertions, 0 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index db02752..3f8cc86 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,15 @@
+2015-03-05 Nick Clifton <nickc@redhat.com>
+
+ 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 <marcus.shawcroft@arm.com>
* elfxx-aarch64.c (decode_add_imm, decode_movw_imm)
diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index 83673d4..5c664a4 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 0a5d1ce..cbd4cf6 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 7c661e3..06fa652 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 2aafecf..14600aa 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 **);