: 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,
// 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));
}
+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];
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())
{
sym.current_function = fd;
sym.current_probe = 0;
- sym.current_derived_probe = 0;
fd->body->visit (& sym);
}
catch (const semantic_error& e)
}
}
- // 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++)
{
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)
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)
{
}
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);
// 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)
{
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,
struct
dwflpp
{
-
+ systemtap_session & sess;
Dwfl * dwfl;
// These are "current" values we focus on.
{
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;
}
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;
}
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;
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));
}
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);
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);
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;
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;
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;
{
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;
{
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;
throw semantic_error(string("dwfl failure: ") + dwfl_errmsg(rc));
}
- dwflpp()
+ dwflpp(systemtap_session & sess)
:
+ sess(sess),
dwfl(NULL),
module(NULL),
module_dwarf(NULL),
Dwarf *, Dwarf_Addr, void *),
void * data)
{
- if (verbose)
+ if (sess.verbose)
clog << "iterating over modules" << endl;
ptrdiff_t off = 0;
do
off = dwfl_getdwarf(dwfl, callback, data, off);
}
while (off > 0);
- if (verbose)
+ if (sess.verbose)
clog << "finished iterating over modules" << endl;
dwflpp_assert(off);
}
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;
{
assert(module);
assert(cu);
- if (verbose)
+ if (sess.verbose)
clog << "iterating over functions in CU " << cu_name << endl;
dwarf_getfuncs(cu, callback, data, 0);
}
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;
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
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);
: 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,
}
-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)
if (i == e)
{
- if (verbose)
+ if (sess.verbose)
clog << "parsed '" << spec
<< "' -> func '" << function
<< "'" << endl;
if (i == e)
{
- if (verbose)
+ if (sess.verbose)
clog << "parsed '" << spec
<< "' -> func '"<< function
<< "', file '" << file
try
{
line = lex_cast<int>(string(i, e));
- if (verbose)
+ if (sess.verbose)
clog << "parsed '" << spec
<< "' -> func '"<< function
<< "', file '" << file
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;
// 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)
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;
}
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);