summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgraydon <graydon>2005-06-29 22:42:23 +0000
committergraydon <graydon>2005-06-29 22:42:23 +0000
commit20c6c071f5dfe6942438d97364e74f424217c94b (patch)
tree28e6a1a2dace1f2143ed16fb80f407082536676e
parent05785c11dfdeaf11d98e7d65486a3870d00b5206 (diff)
downloadsystemtap-steved-20c6c071f5dfe6942438d97364e74f424217c94b.tar.gz
systemtap-steved-20c6c071f5dfe6942438d97364e74f424217c94b.tar.xz
systemtap-steved-20c6c071f5dfe6942438d97364e74f424217c94b.zip
2005-06-27 Graydon Hoare <graydon@redhat.com>
* staptree.{h,cxx} (probe_alias): New structure. * parse.{h,cxx} (parser::parse): Parse probes or probe aliases. (parser::parse_probe): Likewise. * tapsets.{h,cxx}: (derived_probe_builder): (match_key): (match_node): (alias_derived_probe): Move from here, * elaborate.{h,cxx}: to here. * elaborate.h (systemtap_session::pattern_root): New member. (register_library_aliases): New function. * tapsets.cxx: Build one dwarf_derived_probe per target address.
-rw-r--r--ChangeLog15
-rw-r--r--elaborate.cxx306
-rw-r--r--elaborate.h62
-rw-r--r--parse.cxx66
-rw-r--r--parse.h2
-rw-r--r--staptree.cxx25
-rw-r--r--staptree.h13
-rw-r--r--tapsets.cxx903
-rw-r--r--tapsets.h54
9 files changed, 729 insertions, 717 deletions
diff --git a/ChangeLog b/ChangeLog
index 42155910..4a5a6ebe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2005-06-27 Graydon Hoare <graydon@redhat.com>
+
+ * staptree.{h,cxx} (probe_alias): New structure.
+ * parse.{h,cxx} (parser::parse): Parse probes or probe aliases.
+ (parser::parse_probe): Likewise.
+ * tapsets.{h,cxx}:
+ (derived_probe_builder):
+ (match_key):
+ (match_node):
+ (alias_derived_probe): Move from here,
+ * elaborate.{h,cxx}: to here.
+ * elaborate.h (systemtap_session::pattern_root): New member.
+ (register_library_aliases): New function.
+ * tapsets.cxx: Build one dwarf_derived_probe per target address.
+
2005-06-23 Graydon Hoare <graydon@redhat.com>
* tapsets.cxx
diff --git a/elaborate.cxx b/elaborate.cxx
index 2104c005..707d22f6 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -9,6 +9,7 @@
#include "config.h"
#include "elaborate.h"
#include "parse.h"
+#include "tapsets.h"
extern "C" {
#include <sys/utsname.h>
@@ -50,9 +51,306 @@ derived_probe::derived_probe (probe *p, probe_point *l):
this->locals = p->locals;
}
+// ------------------------------------------------------------------------
+
+// Members of match_key.
+
+match_key::match_key(string const & n)
+ : name(n),
+ have_parameter(false),
+ parameter_type(tok_junk)
+{
+}
+
+match_key::match_key(probe_point::component const & c)
+ : name(c.functor),
+ have_parameter(c.arg != NULL),
+ parameter_type(c.arg ? c.arg->tok->type : tok_junk)
+{
+}
+
+match_key &
+match_key::with_number()
+{
+ have_parameter = true;
+ parameter_type = tok_number;
+ return *this;
+}
+
+match_key &
+match_key::with_string()
+{
+ have_parameter = true;
+ parameter_type = tok_string;
+ return *this;
+}
+
+string
+match_key::str() const
+{
+ if (have_parameter)
+ switch (parameter_type)
+ {
+ case tok_string: return name + "(string)";
+ case tok_number: return name + "(number)";
+ default: return name + "(...)";
+ }
+ return name;
+}
+
+bool
+match_key::operator<(match_key const & other) const
+{
+ return ((name < other.name)
+
+ || (name == name
+ && have_parameter < other.have_parameter)
+
+ || (name == name
+ && have_parameter == other.have_parameter
+ && parameter_type < other.parameter_type));
+}
+
+// ------------------------------------------------------------------------
+// Members of match_node
+// ------------------------------------------------------------------------
+
+match_node::match_node()
+ : end(NULL)
+{}
+
+match_node *
+match_node::bind(match_key const & k)
+{
+ map<match_key, match_node *>::const_iterator i = sub.find(k);
+ if (i != sub.end())
+ return i->second;
+ match_node * n = new match_node();
+ sub.insert(make_pair(k, n));
+ return n;
+}
+
+void
+match_node::bind(derived_probe_builder * e)
+{
+ if (end)
+ throw semantic_error("already have a pattern ending");
+ end = e;
+}
+
+match_node *
+match_node::bind(string const & k)
+{
+ return bind(match_key(k));
+}
+
+match_node *
+match_node::bind_str(string const & k)
+{
+ return bind(match_key(k).with_string());
+}
+
+match_node *
+match_node::bind_num(string const & k)
+{
+ return bind(match_key(k).with_number());
+}
+
+derived_probe_builder *
+match_node::find_builder(vector<probe_point::component *> const & components,
+ unsigned pos,
+ vector< pair<string, literal *> > & parameters)
+{
+ assert(pos <= components.size());
+ if (pos == components.size())
+ {
+ // Probe_point ends here. We match iff we have
+ // an "end" entry here. If we don't, it'll be null.
+ return end;
+ }
+ else
+ {
+ // Probe_point contains a component here. We match iff there's
+ // an entry in the sub table, and its value matches the rest
+ // of the probe_point.
+ match_key k(*components[pos]);
+ if (verbose)
+ clog << "searching for component " << k.str() << endl;
+ map<match_key, match_node *>::const_iterator i = sub.find(k);
+ if (i == sub.end())
+ {
+ if (verbose)
+ clog << "no match found" << endl;
+ return NULL;
+ }
+ else
+ {
+ if (verbose)
+ clog << "matched " << k.str() << endl;
+ derived_probe_builder * builder = NULL;
+ if (k.have_parameter)
+ {
+ assert(components[pos]->arg);
+ parameters.push_back(make_pair(components[pos]->functor,
+ components[pos]->arg));
+ }
+ else
+ {
+ // store a "null parameter" for any component we run into, anyways
+ literal_string *empty = NULL;
+ parameters.push_back(make_pair(components[pos]->functor, empty));
+ }
+ builder = i->second->find_builder(components, pos+1, parameters);
+ if (k.have_parameter && !builder)
+ parameters.pop_back();
+ return builder;
+ }
+ }
+}
+
+static void
+param_vec_to_map(vector< pair<string, literal *> > const & param_vec,
+ map<string, literal *> & param_map)
+{
+ for (vector< pair<string, literal *> >::const_iterator i = param_vec.begin();
+ i != param_vec.end(); ++i)
+ {
+ param_map[i->first] = i->second;
+ }
+}
+
+// ------------------------------------------------------------------------
+// Alias probes
// ------------------------------------------------------------------------
+struct
+alias_expansion_builder
+ : public derived_probe_builder
+{
+ probe_alias * alias;
+
+ alias_expansion_builder(probe_alias * a)
+ : alias(a)
+ {}
+
+ virtual void build(probe * use,
+ probe_point * location,
+ std::map<std::string, literal *> const & parameters,
+ vector<probe *> & results_to_expand_further,
+ vector<derived_probe *> & finished_results)
+ {
+ // We're going to build a new probe and wrap it up in an
+ // alias_expansion_probe so that the expansion loop recognizer it as
+ // such and re-expands its expansion.
+
+ probe * n = new probe();
+ n->body = new block();
+
+ // The new probe gets the location list of the alias,
+ n->locations = alias->locations;
+
+ // 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));
+ copy(alias->body->statements.begin(),
+ alias->body->statements.end(),
+ back_inserter(n->body->statements));
+ copy(use->body->statements.begin(),
+ use->body->statements.end(),
+ back_inserter(n->body->statements));
+
+ results_to_expand_further.push_back(n);
+ }
+};
+
+
+// ------------------------------------------------------------------------
+// Pattern matching
+// ------------------------------------------------------------------------
+
+
+// Register all the aliases we've seen in library files, and the user
+// file, as patterns.
+
+void
+systemtap_session::register_library_aliases()
+{
+ vector<stapfile*> files(library_files);
+ files.push_back(user_file);
+
+ for (unsigned f = 0; f < files.size(); ++f)
+ {
+ stapfile * file = files[f];
+ for (unsigned a = 0; a < file->aliases.size(); ++a)
+ {
+ probe_alias * alias = file->aliases[a];
+ for (unsigned n = 0; n < alias->alias_names.size(); ++n)
+ {
+ probe_point * name = alias->alias_names[n];
+ if (verbose)
+ {
+ clog << "registering probe alias ";
+ for (unsigned c = 0; c < name->components.size(); ++c)
+ clog << (c > 0 ? "." : "") << name->components[c]->functor;
+ clog << endl;
+ }
+ match_node * n = pattern_root;
+ for (unsigned c = 0; c < name->components.size(); ++c)
+ {
+ probe_point::component * comp = name->components[c];
+ // XXX: alias parameters
+ if (comp->arg)
+ throw semantic_error("alias component "
+ + comp->functor
+ + " contains illegal parameter");
+ n = n->bind(comp->functor);
+ }
+ n->bind(new alias_expansion_builder(alias));
+ }
+ }
+ }
+}
+
+
+// The match-and-expand loop.
+void
+symresolution_info::derive_probes (match_node * root,
+ probe *p, vector<derived_probe*>& dps)
+{
+ for (unsigned i = 0; i < p->locations.size(); ++i)
+ {
+ probe_point *loc = p->locations[i];
+ vector< pair<string, literal *> > param_vec;
+ map<string, literal *> param_map;
+ vector<probe *> re_expand;
+
+ derived_probe_builder * builder =
+ root->find_builder(loc->components, 0, param_vec);
+
+ if (!builder)
+ throw semantic_error ("no match for probe point", loc->tok);
+
+ param_vec_to_map(param_vec, param_map);
+
+ builder->build(p, loc, param_map, re_expand, dps);
+
+ // Recursively expand any further-expanding results
+ if (!re_expand.empty())
+ {
+ for (unsigned j = 0; j < re_expand.size(); ++j)
+ derive_probes(root, re_expand[j], dps);
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+
static int semantic_pass_symbols (systemtap_session&);
static int semantic_pass_types (systemtap_session&);
@@ -62,7 +360,7 @@ static int semantic_pass_types (systemtap_session&);
// Link up symbols to their declarations. Set the session's
// files/probes/functions/globals vectors from the transitively
// reached set of stapfiles in s.library_files, starting from
-// s.user_file. Perform automatic tapset inclusion and XXX: probe
+// s.user_file. Perform automatic tapset inclusion and probe
// alias expansion.
static int
semantic_pass_symbols (systemtap_session& s)
@@ -114,7 +412,7 @@ semantic_pass_symbols (systemtap_session& s)
{
// much magic happens here: probe alias expansion,
// provider identification
- sym.derive_probes (p, dps);
+ sym.derive_probes (s.pattern_root, p, dps);
}
catch (const semantic_error& e)
{
@@ -149,6 +447,9 @@ semantic_pass_symbols (systemtap_session& s)
int
semantic_pass (systemtap_session& s)
{
+ s.register_library_aliases();
+ register_standard_tapsets(s.pattern_root);
+
int rc = semantic_pass_symbols (s);
if (rc == 0) rc = semantic_pass_types (s);
return rc;
@@ -159,6 +460,7 @@ semantic_pass (systemtap_session& s)
systemtap_session::systemtap_session ():
+ pattern_root(new match_node),
user_file (0), op (0), up (0), num_errors (0)
{
}
diff --git a/elaborate.h b/elaborate.h
index 06cec813..3c0c8ed4 100644
--- a/elaborate.h
+++ b/elaborate.h
@@ -13,12 +13,16 @@
#include "parse.h"
#include <string>
#include <vector>
-
+#include <iostream>
+#include <sstream>
+#include <map>
// ------------------------------------------------------------------------
struct systemtap_session;
struct derived_probe;
+struct match_node;
+
struct symresolution_info: public traversing_visitor
{
protected:
@@ -30,7 +34,7 @@ public:
symresolution_info (systemtap_session& s);
// XXX: instead in systemtap_session?
- void derive_probes (probe *p, std::vector<derived_probe*>& dps);
+ void derive_probes (match_node * root, probe *p, std::vector<derived_probe*>& dps);
protected:
vardecl* find_scalar (const std::string& name);
@@ -130,6 +134,57 @@ struct derived_probe: public probe
// }
};
+// ------------------------------------------------------------------------
+
+struct
+derived_probe_builder
+{
+ virtual void build(probe * base,
+ probe_point * location,
+ std::map<std::string, literal *> const & parameters,
+ std::vector<probe *> & results_to_expand_further,
+ std::vector<derived_probe *> & finished_results) = 0;
+ virtual ~derived_probe_builder() {}
+};
+
+
+struct
+match_key
+{
+ std::string name;
+ bool have_parameter;
+ token_type parameter_type;
+
+ match_key(std::string const & n);
+ match_key(probe_point::component const & c);
+
+ match_key & with_number();
+ match_key & with_string();
+ std::string str() const;
+ bool operator<(match_key const & other) const;
+};
+
+
+class
+match_node
+{
+ std::map<match_key, match_node *> sub;
+ derived_probe_builder * end;
+
+ public:
+ match_node();
+ derived_probe_builder * find_builder(std::vector<probe_point::component *> const & components,
+ unsigned pos,
+ std::vector< std::pair<std::string, literal *> > & parameters);
+
+ match_node * bind(match_key const & k);
+ match_node * bind(std::string const & k);
+ match_node * bind_str(std::string const & k);
+ match_node * bind_num(std::string const & k);
+ void bind(derived_probe_builder * e);
+};
+
+// ------------------------------------------------------------------------
class unparser;
@@ -139,6 +194,9 @@ struct systemtap_session
{
systemtap_session ();
+ match_node * pattern_root;
+ void register_library_aliases();
+
// parse trees for the various script files
stapfile* user_file;
std::vector<stapfile*> library_files;
diff --git a/parse.cxx b/parse.cxx
index d6908ed0..d8953f68 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -373,7 +373,15 @@ parser::parse ()
empty = false;
if (t->type == tok_identifier && t->content == "probe")
- f->probes.push_back (parse_probe ());
+ {
+ probe * p;
+ probe_alias * a;
+ parse_probe (p, a);
+ if (a)
+ f->aliases.push_back(a);
+ else
+ f->probes.push_back (p);
+ }
else if (t->type == tok_identifier && t->content == "global")
parse_global (f->globals);
else if (t->type == tok_identifier && t->content == "function")
@@ -414,31 +422,49 @@ parser::parse ()
}
-probe*
-parser::parse_probe ()
+void
+parser::parse_probe (probe * & probe_ret,
+ probe_alias * & alias_ret)
{
const token* t0 = next ();
if (! (t0->type == tok_identifier && t0->content == "probe"))
throw parse_error ("expected 'probe'");
- probe *p = new probe;
- p->tok = t0;
+ probe_ret = NULL;
+ alias_ret = NULL;
+
+ vector<probe_point *> aliases;
+ vector<probe_point *> locations;
+
+ bool equals_ok = true;
while (1)
{
const token *t = peek ();
if (t && t->type == tok_identifier)
{
- p->locations.push_back (parse_probe_point ());
+ probe_point * pp = parse_probe_point ();
t = peek ();
- if (t && t->type == tok_operator && t->content == ",")
+ if (equals_ok && t
+ && t->type == tok_operator && t->content == "=")
{
+ aliases.push_back(pp);
+ next ();
+ continue;
+ }
+ else if (t && t->type == tok_operator && t->content == ",")
+ {
+ locations.push_back(pp);
+ equals_ok = false;
next ();
continue;
}
else if (t && t->type == tok_operator && t->content == "{")
- break;
+ {
+ locations.push_back(pp);
+ break;
+ }
else
throw parse_error ("expected ',' or '{'");
// XXX: unify logic with that in parse_symbol()
@@ -446,10 +472,22 @@ parser::parse_probe ()
else
throw parse_error ("expected probe point specifier");
}
-
+
+ probe *p;
+ if (aliases.empty())
+ {
+ probe_ret = new probe;
+ p = probe_ret;
+ }
+ else
+ {
+ alias_ret = new probe_alias(aliases);;
+ p = alias_ret;
+ }
+
+ p->tok = t0;
+ p->locations = locations;
p->body = parse_stmt_block ();
-
- return p;
}
@@ -646,7 +684,7 @@ parser::parse_probe_point ()
t = peek ();
if (t && t->type == tok_operator
- && (t->content == "{" || t->content == ","))
+ && (t->content == "{" || t->content == "," || t->content == "="))
break;
if (t && t->type == tok_operator && t->content == "(")
@@ -660,7 +698,7 @@ parser::parse_probe_point ()
t = peek ();
if (t && t->type == tok_operator
- && (t->content == "{" || t->content == ","))
+ && (t->content == "{" || t->content == "," || t->content == "="))
break;
else if (t && t->type == tok_operator &&
t->content == "(")
@@ -671,7 +709,7 @@ parser::parse_probe_point ()
if (t && t->type == tok_operator && t->content == ".")
next ();
else
- throw parse_error ("expected '.' or ',' or '(' or '{'");
+ throw parse_error ("expected '.' or ',' or '(' or '{' or '='");
}
return pl;
diff --git a/parse.h b/parse.h
index b7054b0d..26cac17d 100644
--- a/parse.h
+++ b/parse.h
@@ -95,7 +95,7 @@ private:
unsigned num_errors;
private: // nonterminals
- probe* parse_probe ();
+ void parse_probe (probe *&, probe_alias *&);
probe_point* parse_probe_point ();
literal* parse_literal ();
void parse_global (std::vector<vardecl*>&);
diff --git a/staptree.cxx b/staptree.cxx
index f74f9a91..1243df98 100644
--- a/staptree.cxx
+++ b/staptree.cxx
@@ -373,6 +373,12 @@ void stapfile::print (ostream& o)
o << endl;
}
+ for (unsigned i=0; i<aliases.size(); i++)
+ {
+ aliases[i]->print (o);
+ o << endl;
+ }
+
for (unsigned i=0; i<probes.size(); i++)
{
probes[i]->print (o);
@@ -417,6 +423,25 @@ void probe_point::print (ostream& o)
}
}
+probe_alias::probe_alias(std::vector<probe_point*> const & aliases):
+ probe (), alias_names (aliases)
+{
+}
+
+void probe_alias::printsig (ostream& o)
+{
+ for (unsigned i=0; i<alias_names.size(); i++)
+ {
+ o << (i>0 ? " = " : "");
+ alias_names[i]->print (o);
+ }
+ for (unsigned i=0; i<locations.size(); i++)
+ {
+ o << (i>0 ? ", " : "");
+ locations[i]->print (o);
+ }
+}
+
ostream& operator << (ostream& o, probe_point& k)
{
diff --git a/staptree.h b/staptree.h
index dd53c42e..8d55f053 100644
--- a/staptree.h
+++ b/staptree.h
@@ -356,10 +356,12 @@ struct next_statement: public statement
struct probe;
+struct probe_alias;
struct stapfile
{
std::string name;
std::vector<probe*> probes;
+ std::vector<probe_alias*> aliases;
std::vector<functiondecl*> functions;
std::vector<vardecl*> globals;
void print (std::ostream& o);
@@ -392,9 +394,18 @@ struct probe
std::vector<vardecl*> locals;
probe ();
void print (std::ostream& o);
- void printsig (std::ostream &o);
+ virtual void printsig (std::ostream &o);
+ virtual ~probe() {}
};
+struct probe_alias
+ : public probe
+{
+ probe_alias(std::vector<probe_point*> const & aliases);
+ std::vector<probe_point*> alias_names;
+ virtual void printsig (std::ostream &o);
+ virtual ~probe_alias() {}
+};
// An derived visitor instance is used to visit the entire
diff --git a/tapsets.cxx b/tapsets.cxx
index bdbb1bf2..a56fb659 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -30,227 +30,6 @@ extern "C" {
using namespace std;
-// Members of match_key.
-
-match_key::match_key(string const & n)
- : name(n),
- have_parameter(false),
- parameter_type(tok_junk)
-{
-}
-
-match_key::match_key(probe_point::component const & c)
- : name(c.functor),
- have_parameter(c.arg != NULL),
- parameter_type(c.arg ? c.arg->tok->type : tok_junk)
-{
-}
-
-match_key &
-match_key::with_number()
-{
- have_parameter = true;
- parameter_type = tok_number;
- return *this;
-}
-
-match_key &
-match_key::with_string()
-{
- have_parameter = true;
- parameter_type = tok_string;
- return *this;
-}
-
-string
-match_key::str() const
-{
- if (have_parameter)
- switch (parameter_type)
- {
- case tok_string: return name + "(string)";
- case tok_number: return name + "(number)";
- default: return name + "(...)";
- }
- return name;
-}
-
-bool
-match_key::operator<(match_key const & other) const
-{
- return ((name < other.name)
-
- || (name == name
- && have_parameter < other.have_parameter)
-
- || (name == name
- && have_parameter == other.have_parameter
- && parameter_type < other.parameter_type));
-}
-
-
-// Members of match_node.
-
-match_node::match_node()
- : end(NULL)
-{}
-
-match_node &
-match_node::bind(match_key const & k)
-{
- map<match_key, match_node *>::const_iterator i = sub.find(k);
- if (i != sub.end())
- return *i->second;
- match_node * n = new match_node();
- sub.insert(make_pair(k, n));
- return *n;
-}
-
-void
-match_node::bind(derived_probe_builder * e)
-{
- if (end)
- throw semantic_error("already have a pattern ending");
- end = e;
-}
-
-match_node &
-match_node::bind(string const & k)
-{
- return bind(match_key(k));
-}
-
-match_node &
-match_node::bind_str(string const & k)
-{
- return bind(match_key(k).with_string());
-}
-
-match_node &
-match_node::bind_num(string const & k)
-{
- return bind(match_key(k).with_number());
-}
-
-derived_probe_builder *
-match_node::find_builder(vector<probe_point::component *> const & components,
- unsigned pos,
- vector< pair<string, literal *> > & parameters)
-{
- assert(pos <= components.size());
- if (pos == components.size())
- {
- // Probe_point ends here. We match iff we have
- // an "end" entry here. If we don't, it'll be null.
- return end;
- }
- else
- {
- // Probe_point contains a component here. We match iff there's
- // an entry in the sub table, and its value matches the rest
- // of the probe_point.
- match_key k(*components[pos]);
- map<match_key, match_node *>::const_iterator i = sub.find(k);
- if (i == sub.end())
- return NULL;
- else
- {
- derived_probe_builder * builder = NULL;
- if (k.have_parameter)
- {
- assert(components[pos]->arg);
- parameters.push_back(make_pair(components[pos]->functor,
- components[pos]->arg));
- }
- else
- {
- // store a "null parameter" for any component we run into, anyways
- literal_string *empty = NULL;
- parameters.push_back(make_pair(components[pos]->functor, empty));
- }
- builder = i->second->find_builder(components, pos+1, parameters);
- if (k.have_parameter && !builder)
- parameters.pop_back();
- return builder;
- }
- }
-}
-
-
-static void
-param_vec_to_map(vector< pair<string, literal *> > const & param_vec,
- map<string, literal *> & param_map)
-{
- for (vector< pair<string, literal *> >::const_iterator i = param_vec.begin();
- i != param_vec.end(); ++i)
- {
- param_map[i->first] = i->second;
- }
-}
-
-// XXX: bind patterns for probe aliases found in AST
-
-struct
-alias_derived_probe
-{
- alias_derived_probe(probe_point * expansion)
- : alias_expansion(expansion) {}
- probe_point * alias_expansion;
- void emit_registrations (translator_output* o, unsigned i) {}
- void emit_deregistrations (translator_output* o, unsigned i) {}
- void emit_probe_entries (translator_output* o, unsigned i) {}
-};
-
-// The root of the global pattern-matching tree.
-static match_node * root_node;
-
-
-// The match-and-expand loop.
-void
-symresolution_info::derive_probes (probe *p, vector<derived_probe*>& dps)
-{
- if (!root_node)
- {
- root_node = new match_node();
- register_standard_tapsets(*root_node);
- }
-
- assert(root_node);
-
- deque<probe_point *> work(p->locations.begin(), p->locations.end());
-
- while(!work.empty())
- {
- probe_point *loc = work.front();
- work.pop_front();
-
- vector< pair<string, literal *> > param_vec;
- map<string, literal *> param_map;
-
- derived_probe_builder * builder =
- root_node->find_builder(loc->components, 0, param_vec);
-
- if (!builder)
- throw semantic_error ("no match for probe point", loc->tok);
-
- param_vec_to_map(param_vec, param_map);
-
- derived_probe *derived = builder->build(p, loc, param_map);
- assert(derived);
-
- // Append to worklist if it's an alias; append to result otherwise.
- alias_derived_probe *as_alias = dynamic_cast<alias_derived_probe *>(derived);
- if (as_alias)
- {
- work.push_back(as_alias->alias_expansion);
- delete derived;
- }
- else
- dps.push_back (derived);
- }
-}
-
-
// ------------------------------------------------------------------------
// begin/end probes are run right during registration / deregistration
// ------------------------------------------------------------------------
@@ -273,11 +52,13 @@ be_builder
{
bool begin;
be_builder(bool b) : begin(b) {}
- virtual derived_probe * build(probe * base,
- probe_point * location,
- map<string, literal *> const & parameters)
+ virtual void build(probe * base,
+ probe_point * location,
+ std::map<std::string, literal *> const & parameters,
+ vector<probe *> & results_to_expand_further,
+ vector<derived_probe *> & finished_results)
{
- return new be_derived_probe(base, location, begin);
+ finished_results.push_back(new be_derived_probe(base, location, begin));
}
virtual ~be_builder() {}
};
@@ -334,10 +115,10 @@ be_derived_probe::emit_probe_entries (translator_output* o, unsigned j)
}
+#ifdef HAVE_ELFUTILS_LIBDWFL_H
// ------------------------------------------------------------------------
// Dwarf derived probes.
// ------------------------------------------------------------------------
-#ifdef HAVE_ELFUTILS_LIBDWFL_H
// Helper for dealing with selected portions of libdwfl in a more readable
// fashion, and with specific cleanup / checking / logging options.
@@ -665,6 +446,19 @@ dwflpp
}
};
+static string TOK_PROCESS("process");
+static string TOK_KERNEL("kernel");
+static string TOK_MODULE("module");
+
+static string TOK_FUNCTION("function");
+static string TOK_RETURN("return");
+static string TOK_CALLEES("callees");
+
+static string TOK_STATEMENT("statement");
+static string TOK_LABEL("label");
+static string TOK_RELATIVE("relative");
+
+
enum
function_spec_type
{
@@ -674,53 +468,51 @@ function_spec_type
};
enum
-probe_type
+dwarf_probe_type
{
probe_address,
- probe_function_return
+ probe_function_return,
};
-struct
-probe_spec
-{
- probe_spec(Dwarf_Addr a, probe_type ty)
- : address(a), type(ty)
- {}
- Dwarf_Addr address;
- probe_type type;
- bool operator<(probe_spec const & other) const
- {
- return ((address < other.address) ||
- ((address == other.address) && (type < other.type)));
- }
-};
-
struct dwarf_builder;
struct dwarf_derived_probe : public derived_probe
{
- dwarf_derived_probe (probe* p, probe_point* l,
- map<string, literal *> const & params);
-
- static string TOK_PROCESS;
- static string TOK_KERNEL;
- static string TOK_MODULE;
- static string TOK_FUNCTION;
- static string TOK_STATEMENT;
- static string TOK_CALLEES;
- static string TOK_RETURN;
- static string TOK_RELATIVE;
- static string TOK_LABEL;
+ dwarf_derived_probe (probe * p,
+ probe_point * l,
+ string const & module_name,
+ dwarf_probe_type type,
+ Dwarf_Addr addr);
+ string module_name;
+ dwarf_probe_type type;
+ Dwarf_Addr addr;
+
// Pattern registration helpers.
- static void register_relative_variants(match_node & root,
+ static void register_relative_variants(match_node * root,
dwarf_builder * dw);
- static void register_statement_variants(match_node & root,
+ static void register_statement_variants(match_node * root,
dwarf_builder * dw);
- static void register_callee_variants(match_node & root,
+ static void register_callee_variants(match_node * root,
dwarf_builder * dw);
- static void register_function_and_statement_variants(match_node & root,
+ static void register_function_and_statement_variants(match_node * root,
dwarf_builder * dw);
- static void register_patterns(match_node & root);
+ static void register_patterns(match_node * root);
+
+ virtual void emit_registrations (translator_output * o, unsigned i);
+ virtual void emit_deregistrations (translator_output * o, unsigned i);
+ virtual void emit_probe_entries (translator_output * o, unsigned i);
+ virtual ~dwarf_derived_probe() {}
+};
+
+// Helper struct to thread through the dwfl callbacks.
+struct
+dwarf_query
+{
+ dwarf_query(probe * base_probe,
+ probe_point * base_loc,
+ dwflpp & dw,
+ map<string, literal *> const & params,
+ vector<derived_probe *> & results);
// Parameter extractors.
static bool has_null_param(map<string, literal *> const & params,
@@ -730,63 +522,47 @@ struct dwarf_derived_probe : public derived_probe
static bool get_number_param(map<string, literal *> const & params,
string const & k, long & v);
- // The results of all our hard work go in these vectors.
- set<probe_spec> kernel_probes;
- map<string, set<probe_spec>*> module_probes;
-
- void add_kernel_probe(probe_spec const & p);
- void add_module_probe(string const & module, probe_spec const & p);
-
- // Helper struct to thread through the dwfl callbacks.
- struct
- dwarf_query
- {
- dwarf_query(dwarf_derived_probe & probe,
- dwflpp & d,
- map<string, literal *> const & params);
-
- bool has_kernel;
- bool has_process;
- bool has_module;
- string process_val;
- string module_val;
- string function_val;
-
- bool has_function_str;
- bool has_statement_str;
- bool has_function_num;
- bool has_statement_num;
- string statement_str_val;
- string function_str_val;
- long statement_num_val;
- long function_num_val;
-
- bool has_callees;
- long callee_val;
-
- bool has_return;
-
- bool has_label;
- string label_val;
-
- bool has_relative;
- long relative_val;
-
- function_spec_type parse_function_spec(string & spec);
- function_spec_type spec_type;
- string function;
- string file;
- int line;
-
-
- dwarf_derived_probe & probe;
- dwflpp & dw;
- };
-
- virtual void emit_registrations (translator_output* o, unsigned i);
- virtual void emit_deregistrations (translator_output* o, unsigned i);
- virtual void emit_probe_entries (translator_output* o, unsigned i);
- virtual ~dwarf_derived_probe() {}
+ vector<derived_probe *> & results;
+ void add_kernel_probe(dwarf_probe_type type, Dwarf_Addr addr);
+ void add_module_probe(string const & module,
+ dwarf_probe_type type, Dwarf_Addr addr);
+
+ bool has_kernel;
+ bool has_process;
+ bool has_module;
+ string process_val;
+ string module_val;
+ string function_val;
+
+ bool has_function_str;
+ bool has_statement_str;
+ bool has_function_num;
+ bool has_statement_num;
+ string statement_str_val;
+ string function_str_val;
+ long statement_num_val;
+ long function_num_val;
+
+ bool has_callees;
+ long callee_val;
+
+ bool has_return;
+
+ bool has_label;
+ string label_val;
+
+ bool has_relative;
+ long relative_val;
+
+ function_spec_type parse_function_spec(string & spec);
+ function_spec_type spec_type;
+ string function;
+ string file;
+ int line;
+
+ probe * base_probe;
+ probe_point * base_loc;
+ dwflpp & dw;
};
struct
@@ -794,18 +570,17 @@ dwarf_builder
: public derived_probe_builder
{
dwarf_builder() {}
- virtual derived_probe * build(probe * base,
- probe_point * location,
- map<string, literal *> const & parameters)
- {
- return new dwarf_derived_probe(base, location, parameters);
- }
+ virtual void build(probe * base,
+ probe_point * location,
+ std::map<std::string, literal *> const & parameters,
+ vector<probe *> & results_to_expand_further,
+ vector<derived_probe *> & finished_results);
virtual ~dwarf_builder() {}
};
bool
-dwarf_derived_probe::has_null_param(map<string, literal *> const & params,
- string const & k)
+dwarf_query::has_null_param(map<string, literal *> const & params,
+ string const & k)
{
map<string, literal *>::const_iterator i = params.find(k);
if (i != params.end() && i->second == NULL)
@@ -814,8 +589,8 @@ dwarf_derived_probe::has_null_param(map<string, literal *> const & params,
}
bool
-dwarf_derived_probe::get_string_param(map<string, literal *> const & params,
- string const & k, string & v)
+dwarf_query::get_string_param(map<string, literal *> const & params,
+ string const & k, string & v)
{
map<string, literal *>::const_iterator i = params.find(k);
if (i == params.end())
@@ -828,8 +603,8 @@ dwarf_derived_probe::get_string_param(map<string, literal *> const & params,
}
bool
-dwarf_derived_probe::get_number_param(map<string, literal *> const & params,
- string const & k, long & v)
+dwarf_query::get_number_param(map<string, literal *> const & params,
+ string const & k, long & v)
{
map<string, literal *>::const_iterator i = params.find(k);
if (i == params.end())
@@ -844,39 +619,34 @@ dwarf_derived_probe::get_number_param(map<string, literal *> const & params,
}
void
-dwarf_derived_probe::add_kernel_probe(probe_spec const & p)
+dwarf_query::add_kernel_probe(dwarf_probe_type type,
+ Dwarf_Addr addr)
{
- kernel_probes.insert(p);
+ results.push_back(new dwarf_derived_probe(base_probe, base_loc,
+ "", type, addr));
}
void
-dwarf_derived_probe::add_module_probe(string const & module,
- probe_spec const & p)
+dwarf_query::add_module_probe(string const & module,
+ dwarf_probe_type type,
+ Dwarf_Addr addr)
{
- set<probe_spec>* specs;
-
- map<string, set<probe_spec>*>::const_iterator i
- = module_probes.find(module);
-
- if (i == module_probes.end())
- {
- specs = new set<probe_spec>();
- module_probes.insert(make_pair(module, specs));
- }
- else
- {
- specs = i->second;
- }
- specs->insert(p);
+ results.push_back(new dwarf_derived_probe(base_probe, base_loc,
+ module, type, addr));
}
-dwarf_derived_probe::dwarf_query::dwarf_query(dwarf_derived_probe & probe,
- dwflpp & d,
- map<string, literal *> const & params)
- : probe(probe),
- dw(d)
+dwarf_query::dwarf_query(probe * base_probe,
+ probe_point * base_loc,
+ dwflpp & dw,
+ map<string, literal *> const & params,
+ vector<derived_probe *> & results)
+ : results(results),
+ base_probe(base_probe),
+ base_loc(base_loc),
+ dw(dw)
{
+
// Reduce the query to more reasonable semantic values (booleans,
// extracted strings, numbers, etc).
@@ -917,10 +687,10 @@ lex_cast(IN const & in)
}
function_spec_type
-dwarf_derived_probe::dwarf_query::parse_function_spec(string & spec)
+dwarf_query::parse_function_spec(string & spec)
{
string::const_iterator i = spec.begin(), e = spec.end();
-
+
function.clear();
file.clear();
line = 0;
@@ -976,41 +746,44 @@ dwarf_derived_probe::dwarf_query::parse_function_spec(string & spec)
}
bad:
- throw semantic_error("malformed specification '" + spec + "'", probe.tok);
+ throw semantic_error("malformed specification '" + spec + "'",
+ base_probe->tok);
}
static void
-query_statement(Dwarf_Addr stmt_addr, dwarf_derived_probe::dwarf_query *q)
+query_statement(Dwarf_Addr stmt_addr, dwarf_query * q)
{
// XXX: implement
if (q->has_relative)
- throw semantic_error("incomplete: do not know how to interpret .relative", q->probe.tok);
+ throw semantic_error("incomplete: do not know how to interpret .relative",
+ q->base_probe->tok);
- probe_type ty = (((q->has_function_str || q->has_function_num) && q->has_return)
- ? probe_function_return
- : probe_address);
+ dwarf_probe_type ty = (((q->has_function_str || q->has_function_num) && q->has_return)
+ ? probe_function_return
+ : probe_address);
if (q->has_module)
- q->probe.add_module_probe(q->dw.module_name,
- probe_spec(q->dw.global_address_to_module(stmt_addr), ty));
+ q->add_module_probe(q->dw.module_name,
+ ty, q->dw.global_address_to_module(stmt_addr));
else
- q->probe.add_kernel_probe(probe_spec(stmt_addr, ty));
+ q->add_kernel_probe(ty, stmt_addr);
}
static int
query_function(Dwarf_Func * func, void * arg)
{
- dwarf_derived_probe::dwarf_query *q =
- static_cast<dwarf_derived_probe::dwarf_query *>(arg);
+ dwarf_query * q = static_cast<dwarf_query *>(arg);
// XXX: implement
if (q->has_callees)
- throw semantic_error("incomplete: do not know how to interpret .callees", q->probe.tok);
+ throw semantic_error("incomplete: do not know how to interpret .callees",
+ q->base_probe->tok);
if (q->has_label)
- throw semantic_error("incomplete: do not know how to interpret .label", q->probe.tok);
+ throw semantic_error("incomplete: do not know how to interpret .label",
+ q->base_probe->tok);
q->dw.focus_on_function(func);
@@ -1059,8 +832,7 @@ query_function(Dwarf_Func * func, void * arg)
static int
query_cu (Dwarf_Die * cudie, void * arg)
{
- dwarf_derived_probe::dwarf_query *q =
- static_cast<dwarf_derived_probe::dwarf_query *>(arg);
+ dwarf_query * q = static_cast<dwarf_query *>(arg);
q->dw.focus_on_cu(cudie);
@@ -1099,8 +871,7 @@ query_module (Dwfl_Module *mod __attribute__ ((unused)),
void *arg __attribute__ ((unused)))
{
- dwarf_derived_probe::dwarf_query *q =
- static_cast<dwarf_derived_probe::dwarf_query *>(arg);
+ dwarf_query * q = static_cast<dwarf_query *>(arg);
q->dw.focus_on_module(mod);
@@ -1136,57 +907,20 @@ query_module (Dwfl_Module *mod __attribute__ ((unused)),
return DWARF_CB_OK;
}
-dwarf_derived_probe::dwarf_derived_probe (probe* p, probe_point* l,
- map<string, literal *> const & params)
- : derived_probe (p, l)
+dwarf_derived_probe::dwarf_derived_probe (probe * p,
+ probe_point * l,
+ string const & module_name,
+ dwarf_probe_type type,
+ Dwarf_Addr addr)
+ : derived_probe (p, l),
+ module_name(module_name),
+ type(type),
+ addr(addr)
{
- dwflpp dw;
- dwarf_query q(*this, dw, params);
-
- dw.setup(q.has_kernel || q.has_module);
-
- if (q.has_kernel && q.has_statement_num)
- {
- // If we have kernel.statement(0xbeef), the address is global
- // (relative to the kernel) and we can seek directly to the
- // statement in question.
- query_statement(q.statement_num_val, &q);
- }
- else if (q.has_kernel && q.has_function_num)
- {
- // If we have kernel.function(0xbeef), the address is global
- // (relative to the kernel) and we can seek directly to the
- // cudie in question.
- dw.focus_on_cu_containing_global_address(q.function_num_val);
- dw.iterate_over_functions(&query_function, &q);
- }
- else
- {
- // Otherwise we have module("foo"), kernel.statement("foo"), or
- // kernel.function("foo"); in these cases we need to scan all
- // the modules.
- assert((q.has_kernel && q.has_function_str) ||
- (q.has_kernel && q.has_statement_str) ||
- (q.has_module));
- dw.iterate_over_modules(&query_module, &q);
- }
}
-string dwarf_derived_probe::TOK_PROCESS("process");
-string dwarf_derived_probe::TOK_KERNEL("kernel");
-string dwarf_derived_probe::TOK_MODULE("module");
-
-string dwarf_derived_probe::TOK_FUNCTION("function");
-string dwarf_derived_probe::TOK_RETURN("return");
-string dwarf_derived_probe::TOK_CALLEES("callees");
-
-string dwarf_derived_probe::TOK_STATEMENT("statement");
-string dwarf_derived_probe::TOK_LABEL("label");
-string dwarf_derived_probe::TOK_RELATIVE("relative");
-
-
void
-dwarf_derived_probe::register_relative_variants(match_node & root,
+dwarf_derived_probe::register_relative_variants(match_node * root,
dwarf_builder * dw)
{
// Here we match 2 forms:
@@ -1194,12 +928,12 @@ dwarf_derived_probe::register_relative_variants(match_node & root,
// .
// .relative(NN)
- root.bind(dw);
- root.bind_num(TOK_RELATIVE).bind(dw);
+ root->bind(dw);
+ root->bind_num(TOK_RELATIVE)->bind(dw);
}
void
-dwarf_derived_probe::register_statement_variants(match_node & root,
+dwarf_derived_probe::register_statement_variants(match_node * root,
dwarf_builder * dw)
{
// Here we match 3 forms:
@@ -1209,12 +943,12 @@ dwarf_derived_probe::register_statement_variants(match_node & root,
// .label("foo")
register_relative_variants(root, dw);
- register_relative_variants(root.bind(TOK_RETURN), dw);
- register_relative_variants(root.bind_str(TOK_LABEL), dw);
+ register_relative_variants(root->bind(TOK_RETURN), dw);
+ register_relative_variants(root->bind_str(TOK_LABEL), dw);
}
void
-dwarf_derived_probe::register_callee_variants(match_node & root,
+dwarf_derived_probe::register_callee_variants(match_node * root,
dwarf_builder * dw)
{
// Here we match 3 forms:
@@ -1227,12 +961,12 @@ dwarf_derived_probe::register_callee_variants(match_node & root,
// recursive .callees.callees.callees... pattern-matching on our part.
register_statement_variants(root, dw);
- register_statement_variants(root.bind(TOK_CALLEES), dw);
- register_statement_variants(root.bind_num(TOK_CALLEES), dw);
+ register_statement_variants(root->bind(TOK_CALLEES), dw);
+ register_statement_variants(root->bind_num(TOK_CALLEES), dw);
}
void
-dwarf_derived_probe::register_function_and_statement_variants(match_node & root,
+dwarf_derived_probe::register_function_and_statement_variants(match_node * root,
dwarf_builder * dw)
{
// Here we match 4 forms:
@@ -1242,14 +976,14 @@ dwarf_derived_probe::register_function_and_statement_variants(match_node & root,
// .statement("foo")
// .statement(0xdeadbeef)
- register_callee_variants(root.bind_str(TOK_FUNCTION), dw);
- register_callee_variants(root.bind_num(TOK_FUNCTION), dw);
- register_statement_variants(root.bind_str(TOK_STATEMENT), dw);
- register_statement_variants(root.bind_num(TOK_STATEMENT), dw);
+ register_callee_variants(root->bind_str(TOK_FUNCTION), dw);
+ register_callee_variants(root->bind_num(TOK_FUNCTION), dw);
+ register_statement_variants(root->bind_str(TOK_STATEMENT), dw);
+ register_statement_variants(root->bind_num(TOK_STATEMENT), dw);
}
void
-dwarf_derived_probe::register_patterns(match_node & root)
+dwarf_derived_probe::register_patterns(match_node * root)
{
dwarf_builder *dw = new dwarf_builder();
@@ -1259,9 +993,9 @@ dwarf_derived_probe::register_patterns(match_node & root)
// .module("foo")
// .process("foo")
- register_function_and_statement_variants(root.bind(TOK_KERNEL), dw);
- register_function_and_statement_variants(root.bind_str(TOK_MODULE), dw);
- register_function_and_statement_variants(root.bind_str(TOK_PROCESS), dw);
+ register_function_and_statement_variants(root->bind(TOK_KERNEL), dw);
+ register_function_and_statement_variants(root->bind_str(TOK_MODULE), dw);
+ register_function_and_statement_variants(root->bind_str(TOK_PROCESS), dw);
}
static string
@@ -1271,228 +1005,63 @@ probe_entry_function_name(unsigned probenum)
}
static string
-probe_entry_struct_kprobe_name(unsigned probenum,
- unsigned entrynum)
-{
- return "dwarf_kprobe_" + lex_cast<string>(probenum)
- + "_entry_" + lex_cast<string>(entrynum);
-}
-
-static string
-end_of_block(unsigned probenum)
+probe_entry_struct_kprobe_name(unsigned probenum)
{
- return "block_end_" + lex_cast<string>(probenum);
+ return "dwarf_kprobe_" + lex_cast<string>(probenum);
}
-typedef unsigned module_index;
-typedef unsigned probe_index;
-typedef unsigned entry_index;
-
-static void
-foreach_dwarf_probe_entry(dwarf_derived_probe const & p,
- translator_output *o,
- probe_index probenum,
- void (*kernel_entry_cb)(translator_output *,
- probe_index,
- entry_index,
- probe_spec const &),
- void (*module_cb)(translator_output *,
- probe_index,
- module_index,
- string const &),
- void (*module_entry_cb)(translator_output *,
- probe_index,
- string const &,
- module_index,
- entry_index,
- probe_spec const &))
+void
+dwarf_derived_probe::emit_registrations (translator_output* o, unsigned probenum)
{
- // Just a helper function for an ugly iteration task.
-
- entry_index entrynum = 0;
-
- for (set<probe_spec>::const_iterator i = p.kernel_probes.begin();
- i != p.kernel_probes.end(); ++i, ++entrynum)
+ if (module_name.empty())
{
- if (kernel_entry_cb)
- kernel_entry_cb(o, probenum, entrynum, *i);
+ o->newline() << probe_entry_struct_kprobe_name(probenum)
+ << ".addr = 0x" << hex << addr << ";";
+ o->newline() << "register_probe (&"
+ << probe_entry_struct_kprobe_name(probenum)
+ << ");";
}
-
- module_index modnum = 0;
-
- for (map<string, set<probe_spec>*>::const_iterator i = p.module_probes.begin();
- i != p.module_probes.end(); ++i, ++modnum)
+ else
{
- string modname = i->first;
- set<probe_spec>* probes = i->second;
- if (module_cb)
- module_cb(o, probenum, modnum, modname);
- for (set<probe_spec>::const_iterator j = probes->begin();
- j != probes->end(); ++j, ++entrynum)
- {
- if (module_entry_cb)
- module_entry_cb(o, probenum, modname, modnum, entrynum, *j);
- }
+ o->newline() << "{";
+ o->indent(1);
+ o->newline() << "struct module *mod = get_module(\"" << module_name << "\");";
+ o->newline() << "if (!mod)";
+ o->indent(1);
+ o->newline() << "rc++";
+ o->indent(-1);
+ o->newline() << "else";
+ o->newline() << "{";
+ o->indent(1);
+ o->newline() << probe_entry_struct_kprobe_name(probenum)
+ << ".addr = mod->module_core + 0x" << hex << addr << ";";
+ o->newline() << "register_probe (&"
+ << probe_entry_struct_kprobe_name(probenum)
+ << ");";
+ o->indent(-1);
+ o->newline() << "}";
+ o->indent(-1);
+ o->newline() << "}";
}
}
-
-static void
-declare_dwarf_kernel_entry(translator_output *o,
- probe_index probenum,
- entry_index entrynum,
- probe_spec const & probe)
-{
- o->newline() << "/* probe for "
- << (probe.type == probe_function_return ? "return from " : "")
- << "function at 0x" << hex << probe.address << " in kernel */";
- o->newline() << "static struct kprobe "
- << probe_entry_struct_kprobe_name(probenum, entrynum);
- o->newline() << "{";
- o->indent(1);
- o->newline() << ".addr = 0x" << hex << probe.address << ",";
- o->newline() << ".pre_handler = &" << probe_entry_function_name(probenum) << ",";
- o->indent(-1);
- o->newline() << "}";
-}
-
-static void
-register_dwarf_kernel_entry(translator_output *o,
- probe_index probenum,
- entry_index entrynum,
- probe_spec const & probe)
-{
- o->newline() << "register_probe (&"
- << probe_entry_struct_kprobe_name(probenum, entrynum)
- << ");";
-}
-
-static void
-deregister_dwarf_kernel_entry(translator_output *o,
- probe_index probenum,
- entry_index entrynum,
- probe_spec const & probe)
-{
- o->newline() << "deregister_probe (&"
- << probe_entry_struct_kprobe_name(probenum, entrynum)
- << ");";
-}
-
-static void
-register_dwarf_module(translator_output *o,
- probe_index probenum,
- module_index modnum,
- string const & modname)
-{
- o->newline() << "mod = get_module(\"" << modname << "\");";
- o->newline() << "if (!mod)";
- o->newline() << "{";
- o->indent(1);
- o->newline() << "rc = 1;";
- o->newline() << "goto " << end_of_block(probenum) << ";";
- o->indent(-1);
- o->newline() << "}";
-
-}
-
-static void
-declare_dwarf_module_entry(translator_output *o,
- probe_index probenum,
- string const & modname,
- module_index modnum,
- entry_index entrynum,
- probe_spec const & probe)
-{
- o->newline();
- o->newline() << "/* probe for "
- << (probe.type == probe_function_return ? "return from " : "")
- << "function at 0x" << hex << probe.address
- << " in module " << modname << " */";
-
- o->newline() << "static struct kprobe ";
- o->newline() << probe_entry_struct_kprobe_name(probenum, entrynum);
- o->newline() << "{";
- o->indent(1);
- o->newline() << "/* .addr is calculated at init-time */";
- o->newline() << ".addr = 0,";
- o->newline() << ".pre_handler = &" << probe_entry_function_name(probenum) << ",";
- o->indent(-1);
- o->newline() << "}";
- o->newline();
-}
-
-static void
-register_dwarf_module_entry(translator_output *o,
- probe_index probenum,
- string const & modname,
- module_index modnum,
- entry_index entrynum,
- probe_spec const & probe)
-{
- o->newline();
- o->newline() << probe_entry_struct_kprobe_name(probenum, entrynum)
- << ".addr = mod->module_core + 0x" << hex << probe.address << ";";
- o->newline() << "register_probe (&"
- << probe_entry_struct_kprobe_name(probenum, entrynum)
- << ");";
-}
-
-static void
-deregister_dwarf_module_entry(translator_output *o,
- probe_index probenum,
- string const & modname,
- module_index modnum,
- entry_index entrynum,
- probe_spec const & probe)
-{
- o->newline() << "deregister_probe (&"
- << probe_entry_struct_kprobe_name(probenum, entrynum)
- << ");";
-}
-
-
-void
-dwarf_derived_probe::emit_registrations (translator_output* o, unsigned probenum)
-{
- o->newline() << "{";
- o->indent(1);
- o->newline() << "struct module *mod = NULL;";
- foreach_dwarf_probe_entry(*this, o, probenum,
- &register_dwarf_kernel_entry,
- &register_dwarf_module,
- &register_dwarf_module_entry);
- o->newline();
- o->newline() << end_of_block(probenum) << ":";
- o->newline();
- o->indent(-1);
- o->newline() << "}";
-}
-
void
dwarf_derived_probe::emit_deregistrations (translator_output* o, unsigned probenum)
{
o->newline();
- foreach_dwarf_probe_entry(*this, o, probenum,
- &deregister_dwarf_kernel_entry,
- NULL,
- &deregister_dwarf_module_entry);
- o->newline();
+ o->newline() << "deregister_probe (&"
+ << probe_entry_struct_kprobe_name(probenum)
+ << ");";
}
void
dwarf_derived_probe::emit_probe_entries (translator_output* o, unsigned probenum)
{
- // We should have expanded each location in the initial probe to a
- // separate derived_probe instance; each derived_probe should only
- // have one location.
- assert(locations.size() == 1);
- // Construct a single entry function, and a struct kprobe for each
- // address this derived probe will match, all of which point into
- // the entry function.
+ // Construct a single entry function, and a struct kprobe pointing into
+ // the entry function. The entry function will call the probe function.
- // First the entry function
- o->newline() << "/* probe " << probenum << " entry function */";
+ o->newline();
o->newline() << "static void ";
o->newline() << probe_entry_function_name(probenum) << " ()";
o->newline() << "{";
@@ -1507,11 +1076,57 @@ dwarf_derived_probe::emit_probe_entries (translator_output* o, unsigned probenum
o->newline() << "c->busy --;";
o->newline(-1) << "}" << endl;
- foreach_dwarf_probe_entry(*this, o, probenum,
- &declare_dwarf_kernel_entry,
- NULL,
- &declare_dwarf_module_entry);
+ o->newline();
+ o->newline() << "static struct kprobe "
+ << probe_entry_struct_kprobe_name(probenum);
+ o->newline() << "{";
+ o->indent(1);
+ o->newline() << ".addr = 0x0, /* filled in during module init */" ;
+ o->newline() << ".pre_handler = &" << probe_entry_function_name(probenum) << ",";
+ o->indent(-1);
+ o->newline() << "}";
+ o->newline();
+}
+
+void
+dwarf_builder::build(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);
+
+ dw.setup(q.has_kernel || q.has_module);
+
+ if (q.has_kernel && q.has_statement_num)
+ {
+ // If we have kernel.statement(0xbeef), the address is global
+ // (relative to the kernel) and we can seek directly to the
+ // statement in question.
+ query_statement(q.statement_num_val, &q);
+ }
+ else if (q.has_kernel && q.has_function_num)
+ {
+ // If we have kernel.function(0xbeef), the address is global
+ // (relative to the kernel) and we can seek directly to the
+ // cudie in question.
+ dw.focus_on_cu_containing_global_address(q.function_num_val);
+ dw.iterate_over_functions(&query_function, &q);
+ }
+ else
+ {
+ // Otherwise we have module("foo"), kernel.statement("foo"), or
+ // kernel.function("foo"); in these cases we need to scan all
+ // the modules.
+ assert((q.has_kernel && q.has_function_str) ||
+ (q.has_kernel && q.has_statement_str) ||
+ (q.has_module));
+ dw.iterate_over_modules(&query_module, &q);
+ }
}
#endif /* HAVE_ELFUTILS_LIBDWFL_H */
@@ -1522,11 +1137,11 @@ dwarf_derived_probe::emit_probe_entries (translator_output* o, unsigned probenum
// ------------------------------------------------------------------------
void
-register_standard_tapsets(match_node & root)
+register_standard_tapsets(match_node * root)
{
// Rudimentary binders for begin and end targets
- root.bind("begin").bind(new be_builder(true));
- root.bind("end").bind(new be_builder(false));
+ root->bind("begin")->bind(new be_builder(true));
+ root->bind("end")->bind(new be_builder(false));
#ifdef HAVE_ELFUTILS_LIBDWFL_H
dwarf_derived_probe::register_patterns(root);
diff --git a/tapsets.h b/tapsets.h
index e1ca5f8d..774fa59b 100644
--- a/tapsets.h
+++ b/tapsets.h
@@ -12,61 +12,9 @@
#include "config.h"
#include "staptree.h"
#include "elaborate.h"
-#include "translate.h"
-#include <iostream>
-#include <sstream>
-#include <vector>
-#include <map>
-
-struct
-derived_probe_builder
-{
- virtual derived_probe * build(probe * base,
- probe_point * location,
- std::map<std::string, literal *> const & parameters) = 0;
- virtual ~derived_probe_builder() {}
-};
-
-
-struct
-match_key
-{
- std::string name;
- bool have_parameter;
- token_type parameter_type;
-
- match_key(std::string const & n);
- match_key(probe_point::component const & c);
-
- match_key & with_number();
- match_key & with_string();
- std::string str() const;
- bool operator<(match_key const & other) const;
-};
-
-
-class
-match_node
-{
- std::map<match_key, match_node *> sub;
- derived_probe_builder * end;
-
- public:
- match_node();
- derived_probe_builder * find_builder(std::vector<probe_point::component *> const & components,
- unsigned pos,
- std::vector< std::pair<std::string, literal *> > & parameters);
-
- match_node & bind(match_key const & k);
- match_node & bind(std::string const & k);
- match_node & bind_str(std::string const & k);
- match_node & bind_num(std::string const & k);
- void bind(derived_probe_builder * e);
-};
-
void
-register_standard_tapsets(match_node & root);
+register_standard_tapsets(match_node * root);
#endif // TAPSETS_H