From 6b514c5361a5f16f5c615f2b81168a9e35be7617 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 17 Jan 2013 01:20:28 +0000 Subject: [PATCH] dwarf.c (struct unit): Add filename and abs_filename fields. * dwarf.c (struct unit): Add filename and abs_filename fields. (build_address_map): Set new fields when reading unit. (dwarf_lookup_pc): If we don't find an entry in the line table, just return the main file name. From-SVN: r195257 --- libbacktrace/ChangeLog | 7 ++++++ libbacktrace/dwarf.c | 53 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog index 30382287f1c..25a56d92e22 100644 --- a/libbacktrace/ChangeLog +++ b/libbacktrace/ChangeLog @@ -1,3 +1,10 @@ +2013-01-16 Ian Lance Taylor + + * dwarf.c (struct unit): Add filename and abs_filename fields. + (build_address_map): Set new fields when reading unit. + (dwarf_lookup_pc): If we don't find an entry in the line table, + just return the main file name. + 2013-01-14 Richard Sandiford Update copyright years. diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c index 87392ddec8b..ce12bdc48a3 100644 --- a/libbacktrace/dwarf.c +++ b/libbacktrace/dwarf.c @@ -283,8 +283,12 @@ struct unit int addrsize; /* Offset into line number information. */ off_t lineoff; + /* Primary source file. */ + const char *filename; /* Compilation command working directory. */ const char *comp_dir; + /* Absolute file name, only set if needed. */ + const char *abs_filename; /* The abbreviations for this unit. */ struct abbrevs abbrevs; @@ -1288,6 +1292,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address, int have_ranges; uint64_t lineoff; int have_lineoff; + const char *filename; const char *comp_dir; if (info.reported_underflow) @@ -1346,6 +1351,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address, have_ranges = 0; lineoff = 0; have_lineoff = 0; + filename = NULL; comp_dir = NULL; for (i = 0; i < abbrev->num_attrs; ++i) { @@ -1394,6 +1400,10 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address, have_lineoff = 1; } break; + case DW_AT_name: + if (val.encoding == ATTR_VAL_STRING) + filename = val.u.string; + break; case DW_AT_comp_dir: if (val.encoding == ATTR_VAL_STRING) comp_dir = val.u.string; @@ -1421,7 +1431,9 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address, u->version = version; u->is_dwarf64 = is_dwarf64; u->addrsize = addrsize; + u->filename = filename; u->comp_dir = comp_dir; + u->abs_filename = NULL; u->lineoff = lineoff; u->abbrevs = abbrevs; memset (&abbrevs, 0, sizeof abbrevs); @@ -2701,8 +2713,45 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata, sizeof (struct line), line_search); if (ln == NULL) { - error_callback (data, "inconsistent DWARF line number info", 0); - return 0; + /* The PC is between the low_pc and high_pc attributes of the + compilation unit, but no entry in the line table covers it. + This implies that the start of the compilation unit has no + line number information. */ + + if (entry->u->abs_filename == NULL) + { + const char *filename; + + filename = entry->u->filename; + if (filename != NULL + && !IS_ABSOLUTE_PATH (filename) + && entry->u->comp_dir != NULL) + { + size_t filename_len; + const char *dir; + size_t dir_len; + char *s; + + filename_len = strlen (filename); + dir = entry->u->comp_dir; + dir_len = strlen (dir); + s = (char *) backtrace_alloc (state, dir_len + filename_len + 2, + error_callback, data); + if (s == NULL) + { + *found = 0; + return 0; + } + memcpy (s, dir, dir_len); + /* FIXME: Should use backslash if DOS file system. */ + s[dir_len] = '/'; + memcpy (s + dir_len + 1, filename, filename_len + 1); + filename = s; + } + entry->u->abs_filename = filename; + } + + return callback (data, pc, entry->u->abs_filename, 0, NULL); } /* Search for function name within this unit. */