dwarf.c (struct unit): Add filename and abs_filename fields.
authorIan Lance Taylor <iant@google.com>
Thu, 17 Jan 2013 01:20:28 +0000 (01:20 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 17 Jan 2013 01:20:28 +0000 (01:20 +0000)
* 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
libbacktrace/dwarf.c

index 30382287f1c3b2aaf63914265241e70dad9c1050..25a56d92e22995b9d383e657b1f7cb2e7c148667 100644 (file)
@@ -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.
index 87392ddec8bca23f5b1e168ae001bafcce3cd68a..ce12bdc48a33a881babc00210db8305ebb8916c6 100644 (file)
@@ -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.  */