]> sourceware.org Git - systemtap.git/commitdiff
Resolve statement scopes lexically instead of by raw PC
authorJosh Stone <jistone@redhat.com>
Thu, 19 Aug 2010 21:32:09 +0000 (14:32 -0700)
committerJosh Stone <jistone@redhat.com>
Fri, 20 Aug 2010 01:26:23 +0000 (18:26 -0700)
When we have a statement PC within a function that we wish to probe,
it's not reliable to use getscopes(PC) for variable scoping.  This is
because there may also be inline instances at the PC, and so you can end
up in a different scope altogether.

So now we can traverse the DIEs within a function looking for the
innermost containing the PC, avoiding those nested DIEs which are
actually inlines.  This also lets us get rid of the hack that made
function prologues do a PC search, so we should have more reliable
scoping all around.

* dwflpp.cxx (dwflpp::inner_die_containing_pc): New, scan lexical scopes
  for the innermost DIE that contains a PC, avoiding inlines.
  (dwflpp::iterate_over_labels): Use the above to find the lexical scope
  containing the label's address.
* tapsets.cxx (query_srcfile_line): Use the above to find the closest
  DIE for each statement probe.
  (dwarf_var_expanding_visitor::getscopes): Always call getscopes on the
  given scope_die, so we don't have the trouble that a PC search entails.

dwflpp.cxx
dwflpp.h
tapsets.cxx

index 067de133c5acf5c0b8c91753d1c2e0e5aea1e382..3ca8038330bf7ab25bbe34911095db2ce0de15e3 100644 (file)
@@ -1234,8 +1234,12 @@ dwflpp::iterate_over_labels (Dwarf_Die *begin_die,
 
                   vector<Dwarf_Die> scopes = getscopes_die(&die);
                   if (scopes.size() > 1)
-                    callback(function, name, file, dline,
-                             &scopes[1], stmt_addr, q);
+                    {
+                      Dwarf_Die scope;
+                      inner_die_containing_pc(scopes[1], stmt_addr, scope);
+                      callback(function, name, file, dline,
+                               &scope, stmt_addr, q);
+                    }
                 }
             }
           break;
@@ -1537,6 +1541,46 @@ dwflpp::die_has_pc (Dwarf_Die & die, Dwarf_Addr pc)
 }
 
 
+void
+dwflpp::inner_die_containing_pc(Dwarf_Die& scope, Dwarf_Addr addr,
+                                Dwarf_Die& result)
+{
+  if (!die_has_pc(scope, addr))
+    {
+      ostringstream msg;
+      msg << "dwflpp::inner_die_containing_pc internal error, '"
+          << (dwarf_diename(&scope) ?: "<unknown>")
+          << "' (dieoffset: " << lex_cast_hex(dwarf_dieoffset(&scope))
+          << ") doesn't contain address " << lex_cast_hex(addr);
+      throw semantic_error (msg.str());
+    }
+
+  Dwarf_Die child;
+  result = scope;
+  int rc = dwarf_child(&result, &child);
+  while (rc == 0)
+    {
+      switch (dwarf_tag (&child))
+        {
+        // lexical tags to recurse within the same starting scope
+        // NB: this intentionally doesn't cross into inlines!
+        case DW_TAG_lexical_block:
+        case DW_TAG_with_stmt:
+        case DW_TAG_catch_block:
+        case DW_TAG_try_block:
+        case DW_TAG_entry_point:
+          if (die_has_pc(child, addr))
+            {
+              result = child;
+              rc = dwarf_child(&result, &child);
+              continue;
+            }
+        }
+      rc = dwarf_siblingof(&child, &child);
+    }
+}
+
+
 void
 dwflpp::loc2c_error (void *, const char *fmt, ...)
 {
index 40df8b6afead73ec41ddaa016f2d6326ddb27ec5..7d7248a5bdd0c662cd9a0e3c24d37e0441cb6364 100644 (file)
--- a/dwflpp.h
+++ b/dwflpp.h
@@ -258,6 +258,8 @@ struct dwflpp
   void function_line (int *linep);
 
   bool die_has_pc (Dwarf_Die & die, Dwarf_Addr pc);
+  void inner_die_containing_pc(Dwarf_Die& scope, Dwarf_Addr addr,
+                               Dwarf_Die& result);
 
   std::string literal_stmt_for_local (std::vector<Dwarf_Die>& scopes,
                                       Dwarf_Addr pc,
index d051f500c3a23b1343b39d0920afa5923c1fb48c..1155e9f224c62e5ce400069939430c2462070af5 100644 (file)
@@ -1455,9 +1455,13 @@ query_srcfile_line (const dwarf_line_t& line, void * arg)
          if (q->sess.verbose>3)
            clog << "function DIE lands on srcfile\n";
          if (q->has_statement_str)
-           query_statement (i->name, i->decl_file,
-                            lineno, // NB: not q->line !
-                             &(i->die), addr, q);
+            {
+              Dwarf_Die scope;
+              q->dw.inner_die_containing_pc(i->die, addr, scope);
+              query_statement (i->name, i->decl_file,
+                               lineno, // NB: not q->line !
+                               &scope, addr, q);
+            }
          else
            query_func_info (i->entrypc, *i, q);
        }
@@ -1472,8 +1476,12 @@ query_srcfile_line (const dwarf_line_t& line, void * arg)
          if (q->sess.verbose>3)
            clog << "inline instance DIE lands on srcfile\n";
          if (q->has_statement_str)
-           query_statement (i->name, i->decl_file,
-                            q->line[0], &(i->die), addr, q);
+            {
+              Dwarf_Die scope;
+              q->dw.inner_die_containing_pc(i->die, addr, scope);
+              query_statement (i->name, i->decl_file,
+                               q->line[0], &scope, addr, q);
+            }
          else
            query_inline_instance_info (*i, q);
        }
@@ -3365,14 +3373,7 @@ dwarf_var_expanding_visitor::getscopes(target_symbol *e)
 {
   if (scopes.empty())
     {
-      // If the address is at the beginning of the scope_die, we can do a fast
-      // getscopes from there.  Otherwise we need to look it up by address.
-      Dwarf_Addr entrypc;
-      if (q.dw.die_entrypc(scope_die, &entrypc) && entrypc == addr)
-        scopes = q.dw.getscopes(scope_die);
-      else
-        scopes = q.dw.getscopes(addr);
-
+      scopes = q.dw.getscopes(scope_die);
       if (scopes.empty())
         throw semantic_error ("unable to find any scopes containing "
                               + lex_cast_hex(addr)
This page took 0.083851 seconds and 5 git commands to generate.