summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--elaborate.cxx83
-rw-r--r--elaborate.h6
-rw-r--r--staptree.cxx1
-rw-r--r--tapsets.cxx105
-rwxr-xr-xtestsuite/semok/fourteen.stp30
-rwxr-xr-xtestsuite/semok/thirteen.stp27
-rwxr-xr-xtestsuite/semok/twelve.stp17
8 files changed, 193 insertions, 85 deletions
diff --git a/ChangeLog b/ChangeLog
index 916ac1e8..88cb0ca1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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")
+}