From: Josh Stone Date: Thu, 19 Aug 2010 21:32:09 +0000 (-0700) Subject: Resolve statement scopes lexically instead of by raw PC X-Git-Tag: release-1.4~272 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=f5958c8f368ffab013222116bb42f4c0ee969252;p=systemtap.git Resolve statement scopes lexically instead of by raw PC 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. --- diff --git a/dwflpp.cxx b/dwflpp.cxx index 067de133c..3ca803833 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -1234,8 +1234,12 @@ dwflpp::iterate_over_labels (Dwarf_Die *begin_die, vector 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) ?: "") + << "' (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, ...) { diff --git a/dwflpp.h b/dwflpp.h index 40df8b6af..7d7248a5b 100644 --- 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& scopes, Dwarf_Addr pc, diff --git a/tapsets.cxx b/tapsets.cxx index d051f500c..1155e9f22 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -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)