diff options
author | Josh Stone <jistone@redhat.com> | 2009-09-10 17:06:11 -0700 |
---|---|---|
committer | Josh Stone <jistone@redhat.com> | 2009-09-10 17:06:11 -0700 |
commit | 729455a739d4755269f20b73d2db231db2a1fdd7 (patch) | |
tree | 8b09cc7f762877b2daa4cb2c436a67a283e8e9cd /tapsets.cxx | |
parent | c9efa5c99498ccb3d2f0f87bc373da7dfd1cc067 (diff) | |
download | systemtap-steved-729455a739d4755269f20b73d2db231db2a1fdd7.tar.gz systemtap-steved-729455a739d4755269f20b73d2db231db2a1fdd7.tar.xz systemtap-steved-729455a739d4755269f20b73d2db231db2a1fdd7.zip |
PR10594 cont'd: Use parent die cache for variable lookup
Variable lookup is usually done through the scopes from dwarf_getscopes
at a particular pc. This requires an expensive traversal to find the
inner-most die containing the pc. For cases where that containing die
is known, e.g. at a particular function entry, we can do much better
with our die_parent_cache.
This may also help get more accurate variable scopes in cases where
multiple dies contain a pc and the innermost isn't what we're trying to
probe. For example, an inlined call chain of foo->bar->baz may all have
the same entry pc, but if the probe was on function("bar"), we would
want the variables in bar's scope, not baz's.
* dwflpp.h (struct dwflpp): Remove pc_cached_scopes, num_cached_scopes,
and cached_scopes, as they are now remembered by the caller.
* dwflpp.cxx (dwflpp::getscopes): New - the DIE version uses the parent
cache, and the pc version just defers to dwarf_getscopes.
(dwflpp::print_locals, literal_stmt_for_local): Take a scopes vector.
(dwflpp::find_variable_and_frame_base): Take a scopes vector from the
caller instead of computing it every time.
(dwflpp::dwarf_getscopes_cached): Removed.
* tapsets.cxx (dwarf_var_expanding_visitor::getscopes): New cached
lookup function which gets the scopes from the DIE if possible.
(dwarf_var_expanding_visitor::visit_target_symbol): Call getscopes.
Diffstat (limited to 'tapsets.cxx')
-rw-r--r-- | tapsets.cxx | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/tapsets.cxx b/tapsets.cxx index fc8cb88b..deb1e795 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -1761,7 +1761,8 @@ struct dwarf_var_expanding_visitor: public var_expanding_visitor Dwarf_Addr addr; block *add_block; probe *add_probe; - std::map<std::string, symbol *> return_ts_map; + map<std::string, symbol *> return_ts_map; + vector<Dwarf_Die> scopes; bool visited; dwarf_var_expanding_visitor(dwarf_query & q, Dwarf_Die *sd, Dwarf_Addr a): @@ -1770,6 +1771,8 @@ struct dwarf_var_expanding_visitor: public var_expanding_visitor void visit_target_symbol_context (target_symbol* e); void visit_target_symbol (target_symbol* e); void visit_cast_op (cast_op* e); +private: + vector<Dwarf_Die>& getscopes(target_symbol *e); }; @@ -2281,7 +2284,7 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) } else { - ec->code = q.dw.literal_stmt_for_local (scope_die, + ec->code = q.dw.literal_stmt_for_local (getscopes(e), addr, e->base_name.substr(1), e, @@ -2391,6 +2394,35 @@ dwarf_var_expanding_visitor::visit_cast_op (cast_op *e) } +vector<Dwarf_Die>& +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); + + if (scopes.empty()) + throw semantic_error ("unable to find any scopes containing " + + lex_cast_hex(addr) + + ((scope_die == NULL) ? "" + : (string (" in ") + + (dwarf_diename(scope_die) ?: "<unknown>") + + "(" + (dwarf_diename(q.dw.cu) ?: "<unknown>") + + ")")) + + " while searching for local '" + + e->base_name.substr(1) + "'", + e->tok); + } + return scopes; +} + + struct dwarf_cast_query : public base_query { cast_op& e; |