diff options
author | graydon <graydon> | 2005-06-29 22:42:23 +0000 |
---|---|---|
committer | graydon <graydon> | 2005-06-29 22:42:23 +0000 |
commit | 20c6c071f5dfe6942438d97364e74f424217c94b (patch) | |
tree | 28e6a1a2dace1f2143ed16fb80f407082536676e /elaborate.cxx | |
parent | 05785c11dfdeaf11d98e7d65486a3870d00b5206 (diff) | |
download | systemtap-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.
Diffstat (limited to 'elaborate.cxx')
-rw-r--r-- | elaborate.cxx | 306 |
1 files changed, 304 insertions, 2 deletions
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) { } |