diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | elaborate.cxx | 83 | ||||
-rw-r--r-- | elaborate.h | 6 | ||||
-rw-r--r-- | staptree.cxx | 1 | ||||
-rw-r--r-- | tapsets.cxx | 105 | ||||
-rwxr-xr-x | testsuite/semok/fourteen.stp | 30 | ||||
-rwxr-xr-x | testsuite/semok/thirteen.stp | 27 | ||||
-rwxr-xr-x | testsuite/semok/twelve.stp | 17 |
8 files changed, 193 insertions, 85 deletions
@@ -1,3 +1,12 @@ +2005-07-05 Graydon Hoare <graydon@redhat.com> + + * elaborate.{h,cxx}: Revert previous changes. + * tapsets.{h,cxx}: Adapt to verbose as a member of session. + * elaborate.cxx (alias_expansion_builder::build): Avoid copying + locals between alias definition and use. + * testsuite/semok/{twelve,thirteen,fourteen}.stp: New tests. + * staptree.cxx (probe_alias::printsig): Print equals sign. + 2005-07-05 Frank Ch. Eigler <fche@redhat.com> * elaborate.h (systemtap_session): Add more command-line arguments. diff --git a/elaborate.cxx b/elaborate.cxx index 890d6f4a..37d43ee1 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -234,7 +234,8 @@ alias_expansion_builder : alias(a) {} - virtual void build(probe * use, + virtual void build(systemtap_session & sess, + probe * use, probe_point * location, std::map<std::string, literal *> const & parameters, vector<probe *> & results_to_expand_further, @@ -253,10 +254,14 @@ alias_expansion_builder // the token location of the use, n->tok = use->tok; - // and a set of locals and statements representing the - // concatenation of the alias' body with the use's. - copy(alias->locals.begin(), alias->locals.end(), back_inserter(n->locals)); - copy(use->locals.begin(), use->locals.end(), back_inserter(n->locals)); + // and statements representing the concatenation of the alias' + // body with the use's. + // + // NB: locals are *not* copied forward, from either alias or + // use. The expansion should have its locals re-inferred since + // there's concatenated code here and we only want one vardecl per + // resulting variable. + copy(alias->body->statements.begin(), alias->body->statements.end(), back_inserter(n->body->statements)); @@ -317,11 +322,32 @@ systemtap_session::register_library_aliases() } +static unsigned max_recursion = 100; + +struct +recursion_guard +{ + unsigned & i; + recursion_guard(unsigned & i) : i(i) + { + if (i > max_recursion) + throw semantic_error("recursion limit reached"); + ++i; + } + ~recursion_guard() + { + --i; + } +}; + // The match-and-expand loop. void symresolution_info::derive_probes (match_node * root, probe *p, vector<derived_probe*>& dps) { + static unsigned depth=0; + recursion_guard guard(depth); + for (unsigned i = 0; i < p->locations.size(); ++i) { probe_point *loc = p->locations[i]; @@ -337,7 +363,7 @@ symresolution_info::derive_probes (match_node * root, param_vec_to_map(param_vec, param_map); - builder->build(p, loc, param_map, re_expand, dps); + builder->build(session, p, loc, param_map, re_expand, dps); // Recursively expand any further-expanding results if (!re_expand.empty()) @@ -393,7 +419,6 @@ semantic_pass_symbols (systemtap_session& s) { sym.current_function = fd; sym.current_probe = 0; - sym.current_derived_probe = 0; fd->body->visit (& sym); } catch (const semantic_error& e) @@ -402,36 +427,8 @@ semantic_pass_symbols (systemtap_session& s) } } - // Pass 3: resolve symbols in probes (pre-derivation). Symbols - // used in a probe are bound to vardecls in the probe's "locals" - // vector. - - for (unsigned i=0; i<dome->probes.size(); i++) - { - probe *p = dome->probes[i]; - sym.current_function = 0; - sym.current_probe = p; - sym.current_derived_probe = 0; - p->body->visit (& sym); - } - - // Pass 4: resolve symbols in aliases (pre-expansion). Symbols - // used in an alias probe are bound to vardecls in the alias' - // "locals" vector. - - for (unsigned i=0; i<dome->aliases.size(); i++) - { - probe *p = dome->aliases[i]; - sym.current_function = 0; - sym.current_probe = p; - sym.current_derived_probe = 0; - p->body->visit (& sym); - } - - // Pass 5: derive probes and resolve any further symbols in the - // derived results. Symbols used in a derived probe (but not - // already bound to the base probe) are bound to vardecls in the - // derived probe's "locals" vector. + // Pass 3: derive probes and resolve any further symbols in the + // derived results. for (unsigned i=0; i<dome->probes.size(); i++) { @@ -458,8 +455,7 @@ semantic_pass_symbols (systemtap_session& s) try { sym.current_function = 0; - sym.current_probe = 0; - sym.current_derived_probe = dp; + sym.current_probe = dp; dp->body->visit (& sym); } catch (const semantic_error& e) @@ -514,8 +510,7 @@ systemtap_session::print_error (const semantic_error& e) symresolution_info::symresolution_info (systemtap_session& s): - session (s), current_function (0), - current_probe (0), current_derived_probe(0) + session (s), current_function (0), current_probe (0) { } @@ -575,8 +570,6 @@ symresolution_info::visit_symbol (symbol* e) current_function->locals.push_back (v); else if (current_probe) current_probe->locals.push_back (v); - else if (current_derived_probe) - current_derived_probe->locals.push_back (v); else // must not happen throw semantic_error ("no current probe/function", e->tok); @@ -625,9 +618,7 @@ symresolution_info::find_scalar (const string& name) // search locals vector<vardecl*>& locals = (current_function ? current_function->locals : - (current_probe ? - current_probe->locals : - current_derived_probe->locals)); + current_probe->locals); for (unsigned i=0; i<locals.size(); i++) if (locals[i]->name == name) diff --git a/elaborate.h b/elaborate.h index e61796fa..f25ee5e7 100644 --- a/elaborate.h +++ b/elaborate.h @@ -30,8 +30,7 @@ protected: public: functiondecl* current_function; - probe* current_probe; - derived_probe* current_derived_probe; + derived_probe* current_probe; symresolution_info (systemtap_session& s); // XXX: instead in systemtap_session? @@ -140,7 +139,8 @@ struct derived_probe: public probe struct derived_probe_builder { - virtual void build(probe * base, + virtual void build(systemtap_session & sess, + probe * base, probe_point * location, std::map<std::string, literal *> const & parameters, std::vector<probe *> & results_to_expand_further, diff --git a/staptree.cxx b/staptree.cxx index 1243df98..e64c3710 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -435,6 +435,7 @@ void probe_alias::printsig (ostream& o) o << (i>0 ? " = " : ""); alias_names[i]->print (o); } + o << " = "; for (unsigned i=0; i<locations.size(); i++) { o << (i>0 ? ", " : ""); diff --git a/tapsets.cxx b/tapsets.cxx index 160cb2fe..3dbbfa81 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -52,7 +52,8 @@ be_builder { bool begin; be_builder(bool b) : begin(b) {} - virtual void build(probe * base, + virtual void build(systemtap_session & sess, + probe * base, probe_point * location, std::map<std::string, literal *> const & parameters, vector<probe *> & results_to_expand_further, @@ -126,7 +127,7 @@ be_derived_probe::emit_probe_entries (translator_output* o, unsigned j) struct dwflpp { - + systemtap_session & sess; Dwfl * dwfl; // These are "current" values we focus on. @@ -145,22 +146,28 @@ dwflpp { if (in) return in; - if (verbose) + if (sess.verbose) clog << "WARNING: no name found for " << type << endl; return string("default_anonymous_" ) + type; } + void get_module_dwarf() + { + if (!module_dwarf) + module_dwarf = dwfl_module_getdwarf(module, &module_bias); + } + void focus_on_module(Dwfl_Module * m) { assert(m); module = m; - module_dwarf = dwfl_module_getdwarf(module, &module_bias); + module_dwarf = NULL; module_name = default_name(dwfl_module_info(module, NULL, NULL, NULL, NULL, NULL, NULL, NULL), "module"); - if (verbose) + if (sess.verbose) clog << "focused on module " << module_name << endl; } @@ -169,7 +176,7 @@ dwflpp assert(c); cu = c; cu_name = default_name(dwarf_diename(c), "cu"); - if (verbose) + if (sess.verbose) clog << "focused on CU " << cu_name << ", in module " << module_name << endl; } @@ -180,7 +187,7 @@ dwflpp function = f; function_name = default_name(dwarf_func_name(function), "function"); - if (verbose) + if (sess.verbose) clog << "focused on function " << function_name << ", in CU " << cu_name << ", module " << module_name << endl; @@ -189,7 +196,7 @@ dwflpp void focus_on_module_containing_global_address(Dwarf_Addr a) { assert(dwfl); - if (verbose) + if (sess.verbose) clog << "focusing on module containing global addr " << a << endl; focus_on_module(dwfl_addrmodule(dwfl, a)); } @@ -199,7 +206,8 @@ dwflpp assert(dwfl); assert(module); Dwarf_Addr bias; - if (verbose) + get_module_dwarf(); + if (sess.verbose) clog << "focusing on cu containing module addr " << a << endl; focus_on_cu(dwfl_module_addrdie(module, a, &bias)); assert(bias == module_bias); @@ -208,7 +216,8 @@ dwflpp void focus_on_cu_containing_global_address(Dwarf_Addr a) { assert(dwfl); - if (verbose) + get_module_dwarf(); + if (sess.verbose) clog << "focusing on cu containing global addr " << a << endl; focus_on_module_containing_global_address(a); assert(a > module_bias); @@ -219,7 +228,8 @@ dwflpp Dwarf_Addr module_address_to_global(Dwarf_Addr a) { assert(module); - if (verbose) + get_module_dwarf(); + if (sess.verbose) clog << "module addr " << a << " + bias " << module_bias << " -> global addr " << a + module_bias << endl; @@ -229,7 +239,8 @@ dwflpp Dwarf_Addr global_address_to_module(Dwarf_Addr a) { assert(module); - if (verbose) + get_module_dwarf(); + if (sess.verbose) clog << "global addr " << a << " - bias " << module_bias << " -> module addr " << a - module_bias << endl; @@ -240,8 +251,9 @@ dwflpp bool module_name_matches(string pattern) { assert(module); + get_module_dwarf(); bool t = (fnmatch(pattern.c_str(), module_name.c_str(), 0) == 0); - if (verbose) + if (sess.verbose) clog << "pattern '" << pattern << "' " << (t ? "matches " : "does not match ") << "module '" << module_name << "'" << endl; @@ -252,7 +264,7 @@ dwflpp { assert(function); bool t = (fnmatch(pattern.c_str(), function_name.c_str(), 0) == 0); - if (verbose) + if (sess.verbose) clog << "pattern '" << pattern << "' " << (t ? "matches " : "does not match ") << "function '" << function_name << "'" << endl; @@ -263,7 +275,7 @@ dwflpp { assert(cu); bool t = (fnmatch(pattern.c_str(), cu_name.c_str(), 0) == 0); - if (verbose) + if (sess.verbose) clog << "pattern '" << pattern << "' " << (t ? "matches " : "does not match ") << "CU '" << cu_name << "'" << endl; @@ -276,8 +288,9 @@ dwflpp throw semantic_error(string("dwfl failure: ") + dwfl_errmsg(rc)); } - dwflpp() + dwflpp(systemtap_session & sess) : + sess(sess), dwfl(NULL), module(NULL), module_dwarf(NULL), @@ -330,7 +343,7 @@ dwflpp Dwarf *, Dwarf_Addr, void *), void * data) { - if (verbose) + if (sess.verbose) clog << "iterating over modules" << endl; ptrdiff_t off = 0; do @@ -338,7 +351,7 @@ dwflpp off = dwfl_getdwarf(dwfl, callback, data, off); } while (off > 0); - if (verbose) + if (sess.verbose) clog << "finished iterating over modules" << endl; dwflpp_assert(off); } @@ -346,13 +359,15 @@ dwflpp void iterate_over_cus (int (*callback)(Dwarf_Die * die, void * arg), void * data) { + get_module_dwarf(); + if (!module_dwarf) { cerr << "WARNING: no dwarf info found for module " << module_name << endl; return; } - if (verbose) + if (sess.verbose) clog << "iterating over CUs in module " << module_name << endl; Dwarf *dw = module_dwarf; @@ -375,7 +390,7 @@ dwflpp { assert(module); assert(cu); - if (verbose) + if (sess.verbose) clog << "iterating over functions in CU " << cu_name << endl; dwarf_getfuncs(cu, callback, data, 0); } @@ -393,20 +408,20 @@ dwflpp Dwarf_Addr lo, hi; if (dwarf_func_lowpc(function, &lo) != 0) { - if (verbose) + if (sess.verbose) clog << "WARNING: cannot find low PC value for function " << function_name << endl; return false; } if (dwarf_func_highpc(function, &hi) != 0) { - if (verbose) + if (sess.verbose) clog << "WARNING: cannot find high PC value for function " << function_name << endl; return false; } bool t = lo <= addr && addr <= hi; - if (verbose) + if (sess.verbose) clog << "function " << function_name << " = [" << lo << "," << hi << "] " << (t ? "contains " : "does not contain ") << " global addr " << addr << endl; @@ -430,7 +445,7 @@ dwflpp dwflpp_assert(dwarf_getsrclines(cu, &lines, &nlines)); linep = dwarf_onesrcline(lines, line); dwflpp_assert(dwarf_lineaddr(linep, &addr)); - if (verbose) + if (sess.verbose) clog << "line " << line << " of cu " << cu_name << " has module address " << addr @@ -508,12 +523,15 @@ struct dwarf_derived_probe : public derived_probe struct dwarf_query { - dwarf_query(probe * base_probe, + dwarf_query(systemtap_session & sess, + probe * base_probe, probe_point * base_loc, dwflpp & dw, map<string, literal *> const & params, vector<derived_probe *> & results); + systemtap_session & sess; + // Parameter extractors. static bool has_null_param(map<string, literal *> const & params, string const & k); @@ -570,7 +588,8 @@ dwarf_builder : public derived_probe_builder { dwarf_builder() {} - virtual void build(probe * base, + virtual void build(systemtap_session & sess, + probe * base, probe_point * location, std::map<std::string, literal *> const & parameters, vector<probe *> & results_to_expand_further, @@ -636,12 +655,14 @@ dwarf_query::add_module_probe(string const & module, } -dwarf_query::dwarf_query(probe * base_probe, +dwarf_query::dwarf_query(systemtap_session & sess, + probe * base_probe, probe_point * base_loc, dwflpp & dw, map<string, literal *> const & params, vector<derived_probe *> & results) - : results(results), + : sess(sess), + results(results), base_probe(base_probe), base_loc(base_loc), dw(dw) @@ -704,7 +725,7 @@ dwarf_query::parse_function_spec(string & spec) if (i == e) { - if (verbose) + if (sess.verbose) clog << "parsed '" << spec << "' -> func '" << function << "'" << endl; @@ -719,7 +740,7 @@ dwarf_query::parse_function_spec(string & spec) if (i == e) { - if (verbose) + if (sess.verbose) clog << "parsed '" << spec << "' -> func '"<< function << "', file '" << file @@ -733,7 +754,7 @@ dwarf_query::parse_function_spec(string & spec) try { line = lex_cast<int>(string(i, e)); - if (verbose) + if (sess.verbose) clog << "parsed '" << spec << "' -> func '"<< function << "', file '" << file @@ -791,7 +812,7 @@ query_function(Dwarf_Func * func, void * arg) Dwarf_Addr addr; if (!q->dw.function_entrypc(&addr)) { - if (verbose) + if (q->sess.verbose) clog << "WARNING: cannot find entry PC for function " << q->dw.function_name << endl; return DWARF_CB_OK; @@ -877,7 +898,11 @@ query_module (Dwfl_Module *mod __attribute__ ((unused)), // If we have enough information in the pattern to skip a module and // the module does not match that information, return early. - if (!q->dw.module_name_matches(q->module_val)) + + if (q->has_kernel && !q->dw.module_name_matches("kernel")) + return DWARF_CB_OK; + + if (q->has_module && !q->dw.module_name_matches(q->module_val)) return DWARF_CB_OK; if (q->has_function_num || q->has_statement_num) @@ -904,6 +929,13 @@ query_module (Dwfl_Module *mod __attribute__ ((unused)), q->dw.iterate_over_cus(&query_cu, q); } + // If we just processed the module "kernel", and the user asked for + // the kernel patterh, there's no need to iterate over any further + // modules + + if (q->has_kernel && q->dw.module_name_matches("kernel")) + return DWARF_CB_ABORT; + return DWARF_CB_OK; } @@ -1092,15 +1124,16 @@ dwarf_derived_probe::emit_probe_entries (translator_output* o, unsigned probenum void -dwarf_builder::build(probe * base, +dwarf_builder::build(systemtap_session & sess, + probe * base, probe_point * location, std::map<std::string, literal *> const & parameters, vector<probe *> & results_to_expand_further, vector<derived_probe *> & finished_results) { - dwflpp dw; - dwarf_query q(base, location, dw, parameters, finished_results); + dwflpp dw(sess); + dwarf_query q(sess, base, location, dw, parameters, finished_results); dw.setup(q.has_kernel || q.has_module); diff --git a/testsuite/semok/fourteen.stp b/testsuite/semok/fourteen.stp new file mode 100755 index 00000000..9326ebe2 --- /dev/null +++ b/testsuite/semok/fourteen.stp @@ -0,0 +1,30 @@ +#! stap -p2 + +function trace (s) { return 0 } + +# recursive alias expansion + +probe foo = begin +{ + trace("hello") +} + +probe bar = foo +{ + x=1 +} + +probe baz = bar +{ + y=2 +} + +probe quux = baz +{ + z = x + y +} + +probe quux, end +{ + trace("goodbye") +} diff --git a/testsuite/semok/thirteen.stp b/testsuite/semok/thirteen.stp new file mode 100755 index 00000000..91d767fb --- /dev/null +++ b/testsuite/semok/thirteen.stp @@ -0,0 +1,27 @@ +#! stap -p2 + +function trace (s) { return 0 } + +# define some aliases which resolve to kernel functions + +probe pipe_read = kernel.function("pipe_read") +{ + fname = "pipe_read" + reading_from_pipe = 1 +} + +probe pipe_write = kernel.function("pipe_write") +{ + fname = "pipe_write" + reading_from_pipe = 0 +} + +# use the aliases, including variables defined in them + +probe pipe_read, pipe_write +{ + if (reading_from_pipe) + trace("reading from pipe in " . fname) + else + trace("writing to pipe in " . fname) +} diff --git a/testsuite/semok/twelve.stp b/testsuite/semok/twelve.stp new file mode 100755 index 00000000..8eccd463 --- /dev/null +++ b/testsuite/semok/twelve.stp @@ -0,0 +1,17 @@ +#! stap -p2 + +function trace (s) { return 0 } + +# resolve to a set of kernel functions + +probe kernel.function("pipe_*") +{ + trace("doing something with a pipe") +} + +# resolve to a set of module functions + +probe module("jbd").function("journal_get_*_access@*/transaction.c") +{ + trace("inside journal_get_*_access, in transaction.c") +} |