summaryrefslogtreecommitdiff
path: root/libbacktrace
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2013-01-17 01:20:28 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2013-01-17 01:20:28 +0000
commitfeded019e23def2b8c02f564b56151478583354b (patch)
treefa68e2b6eeffcff78bb569afe6213c7f225a0816 /libbacktrace
parent1adefaca482e49c616a203f25ed7fec65604706e (diff)
downloadgcc-feded019e23def2b8c02f564b56151478583354b.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@195257 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libbacktrace')
-rw-r--r--libbacktrace/ChangeLog7
-rw-r--r--libbacktrace/dwarf.c53
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 <iant@google.com>
+
+ * 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 <rdsandiford@googlemail.com>
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. */