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 /tapsets.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 'tapsets.cxx')
-rw-r--r-- | tapsets.cxx | 903 |
1 files changed, 259 insertions, 644 deletions
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, - ®ister_dwarf_kernel_entry, - ®ister_dwarf_module, - ®ister_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); |