diff options
Diffstat (limited to 'tapsets.cxx')
-rw-r--r-- | tapsets.cxx | 847 |
1 files changed, 595 insertions, 252 deletions
diff --git a/tapsets.cxx b/tapsets.cxx index 6e393b63..62c9e897 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -159,8 +159,7 @@ be_derived_probe::join_group (systemtap_session& s) void common_probe_entryfn_prologue (translator_output* o, string statestr, bool overload_processing = true, - bool interruptible = true, - bool fakeregs = false) + bool interruptible = true) { o->newline() << "struct context* __restrict__ c;"; if (! interruptible) @@ -216,6 +215,7 @@ common_probe_entryfn_prologue (translator_output* o, string statestr, o->newline() << "c->last_stmt = 0;"; o->newline() << "c->last_error = 0;"; o->newline() << "c->nesting = 0;"; + o->newline() << "c->regs = 0;"; o->newline() << "c->unwaddr = 0;"; // reset unwound address cache o->newline() << "c->pi = 0;"; @@ -240,20 +240,6 @@ common_probe_entryfn_prologue (translator_output* o, string statestr, o->newline() << "c->cycles_base = 0;"; o->newline() << "#endif"; */ - - /* PR6961: Let's prep a bare-bones pt_regs struct, just in case our - kind of probe point does not supply one. */ - if (fakeregs) - { - o->newline() << "#ifdef STP_NEED_UNWIND_DATA"; - o->newline() << "memset (& c->regs_buffer, 0, sizeof (c->regs_buffer));"; - o->newline() << "REG_IP((& c->regs_buffer)) = (unsigned long)__builtin_return_address (0);"; - o->newline() << "REG_SP((& c->regs_buffer)) = (unsigned long)& c;"; - o->newline() << "c->regs = & c->regs_buffer;"; - o->newline() << "#endif"; - } - else - o->newline() << "c->regs = 0;"; } @@ -350,31 +336,31 @@ be_derived_probe_group::emit_module_decls (systemtap_session& s) if (probes.empty()) return; s.op->newline() << "/* ---- begin/end probes ---- */"; - s.op->newline() << "void enter_begin_probe (void (*fn)(struct context*), const char* pp) {"; + s.op->newline() << "static void enter_begin_probe (void (*fn)(struct context*), const char* pp) {"; s.op->indent(1); - common_probe_entryfn_prologue (s.op, "STAP_SESSION_STARTING", false, true, true); + common_probe_entryfn_prologue (s.op, "STAP_SESSION_STARTING", false, true); s.op->newline() << "c->probe_point = pp;"; s.op->newline() << "(*fn) (c);"; common_probe_entryfn_epilogue (s.op, false, true); s.op->newline(-1) << "}"; - s.op->newline() << "void enter_end_probe (void (*fn)(struct context*), const char* pp) {"; + s.op->newline() << "static void enter_end_probe (void (*fn)(struct context*), const char* pp) {"; s.op->indent(1); - common_probe_entryfn_prologue (s.op, "STAP_SESSION_STOPPING", false, true, true); + common_probe_entryfn_prologue (s.op, "STAP_SESSION_STOPPING", false, true); s.op->newline() << "c->probe_point = pp;"; s.op->newline() << "(*fn) (c);"; common_probe_entryfn_epilogue (s.op, false, true); s.op->newline(-1) << "}"; - s.op->newline() << "void enter_error_probe (void (*fn)(struct context*), const char* pp) {"; + s.op->newline() << "static void enter_error_probe (void (*fn)(struct context*), const char* pp) {"; s.op->indent(1); - common_probe_entryfn_prologue (s.op, "STAP_SESSION_ERROR", false, true, true); + common_probe_entryfn_prologue (s.op, "STAP_SESSION_ERROR", false, true); s.op->newline() << "c->probe_point = pp;"; s.op->newline() << "(*fn) (c);"; common_probe_entryfn_epilogue (s.op, false, true); s.op->newline(-1) << "}"; - s.op->newline() << "struct stap_be_probe {"; + s.op->newline() << "static struct stap_be_probe {"; s.op->newline(1) << "void (*ph)(struct context*);"; s.op->newline() << "const char* pp;"; s.op->newline() << "int type;"; @@ -480,6 +466,7 @@ static string TOK_STATEMENT("statement"); static string TOK_ABSOLUTE("absolute"); static string TOK_PROCESS("process"); static string TOK_MARK("mark"); +static string TOK_LABEL("label"); // Can we handle this query with just symbol-table info? enum dbinfo_reqt @@ -552,7 +539,8 @@ inline_instance_info }; -struct dwarf_query; // forward decls +struct base_query; // forward decls +struct dwarf_query; struct dwflpp; struct symbol_table; @@ -1024,7 +1012,7 @@ struct dwflpp void iterate_over_modules(int (* callback)(Dwfl_Module *, void **, const char *, Dwarf_Addr, void *), - dwarf_query *data) + base_query *data) { ptrdiff_t off = 0; do @@ -1042,7 +1030,7 @@ struct dwflpp // Defined after dwarf_query - void query_modules(dwarf_query *q); + void query_modules(base_query *q); // ----------------------------------------------------------------- @@ -1159,10 +1147,8 @@ struct dwflpp return DWARF_CB_OK; } - Dwarf_Die *declaration_resolve(Dwarf_Die *die) + Dwarf_Die *declaration_resolve(const char *name) { - const char *name = dwarf_diename(die); - if (!name) return NULL; @@ -1329,6 +1315,82 @@ struct dwflpp } } + void + iterate_over_cu_labels (string label_val, Dwarf_Die *cu, void *data, + void (* callback)(const string &, + const char *, + int, + Dwarf_Die *, + Dwarf_Addr, + dwarf_query *)) + { + dwarf_query * q __attribute__ ((unused)) = static_cast<dwarf_query *>(data) ; + + get_module_dwarf(); + + const char * sym = label_val.c_str(); + Dwarf_Die die; + dwarf_child (cu, &die); + static string function_name; + do + { + Dwarf_Attribute attr_mem; + Dwarf_Attribute *attr = dwarf_attr (&die, DW_AT_name, &attr_mem); + int tag = dwarf_tag(&die); + const char *name = dwarf_formstring (attr); + if (name == NULL) + continue; + if (tag == DW_TAG_subprogram) + { + function_name = name; + } + else if (tag == DW_TAG_label + && ((strncmp(name, sym, strlen(sym)) == 0) + || (name_has_wildcard (sym) + && function_name_matches_pattern (name, sym)))) + { + const char *file = dwarf_decl_file (&die); + // Get the line number for this label + Dwarf_Attribute attr; + dwarf_attr (&die,DW_AT_decl_line, &attr); + Dwarf_Sword dline; + dwarf_formsdata (&attr, &dline); + Dwarf_Addr stmt_addr; + if (dwarf_lowpc (&die, &stmt_addr) != 0) + { + // There is no lowpc so figure out the address + // Get the real die for this cu + Dwarf_Die cudie; + dwarf_diecu (cu, &cudie, NULL, NULL); + size_t nlines = 0; + // Get the line for this label + Dwarf_Line **aline; + dwarf_getsrc_file (module_dwarf, file, (int)dline, 0, &aline, &nlines); + // Get the address + for (size_t i = 0; i < nlines; i++) + { + dwarf_lineaddr (*aline, &stmt_addr); + if ((dwarf_haspc (&die, stmt_addr))) + break; + } + } + + Dwarf_Die *scopes; + int nscopes = 0; + nscopes = dwarf_getscopes_die (&die, &scopes); + if (nscopes > 1) + callback(function_name.c_str(), file, + (int)dline, &scopes[1], stmt_addr, q); + } + if (dwarf_haschildren (&die) && tag != DW_TAG_structure_type + && tag != DW_TAG_union_type) + { + iterate_over_cu_labels (label_val, &die, q, callback); + } + } + while (dwarf_siblingof (&die, &die) == 0); + } + void collect_srcfiles_matching (string const & pattern, set<char const *> & filtered_srcfiles) @@ -1709,12 +1771,16 @@ struct dwflpp assert (cu); - if (scope_die && pc == 0) - nscopes = dwarf_getscopes_die (scope_die, &scopes); - else - nscopes = dwarf_getscopes (cu, pc, &scopes); + nscopes = dwarf_getscopes (cu, pc, &scopes); + int sidx; + // if pc and scope_die are disjoint then we need dwarf_getscopes_die + for (sidx = 0; sidx < nscopes; sidx++) + if (scopes[sidx].addr == scope_die->addr) + break; + if (sidx == nscopes) + nscopes = dwarf_getscopes_die (scope_die, &scopes); - if (nscopes == 0) + if (nscopes <= 0) { throw semantic_error ("unable to find any scopes containing " + lex_cast_hex<string>(pc) @@ -1773,7 +1839,13 @@ struct dwflpp Dwarf_Op *expr; size_t len; - switch (dwarf_getlocation_addr (attr, pc - module_bias, &expr, &len, 1)) + /* PR9768: formerly, we added pc+module_bias here. However, that bias value + is not present in the pc value by the time we get it, so adding it would + result in false negatives of variable reachibility. In other instances + further below, the c_translate_FOO functions, the module_bias value used + to be passed in, but instead should now be zero for the same reason. */ + + switch (dwarf_getlocation_addr (attr, pc /*+ module_bias*/, &expr, &len, 1)) { case 1: /* Should always happen. */ if (len > 0) @@ -1791,7 +1863,7 @@ struct dwflpp return c_translate_location (pool, &loc2c_error, this, &loc2c_emit_address, - 1, module_bias, + 1, 0 /* PR9768 */, pc, expr, len, tail, fb_attr); } @@ -1876,12 +1948,15 @@ struct dwflpp Dwarf_Die *die_mem, Dwarf_Attribute *attr_mem) { - Dwarf_Die *die = vardie; + Dwarf_Die *die = die_mem; Dwarf_Die struct_die; Dwarf_Attribute temp_attr; unsigned i = 0; + if (vardie) + *die_mem = *vardie; + static unsigned int func_call_level ; static unsigned int dwarf_error_flag ; // indicates current error is dwarf error static unsigned int dwarf_error_count ; // keeps track of no of dwarf errors @@ -1898,7 +1973,6 @@ struct dwflpp obstack_printf (pool, "c->last_stmt = %s;", lex_cast_qstring(piece).c_str()); #endif - die = dwarf_formref_die (attr_mem, die_mem); const int typetag = dwarf_tag (die); switch (typetag) { @@ -1914,13 +1988,13 @@ struct dwflpp // XXX: of course, we should support this the same way C does, // by explicit pointer arithmetic etc. PR4166. - c_translate_pointer (pool, 1, module_bias, die, tail); + c_translate_pointer (pool, 1, 0 /* PR9768*/, die, tail); break; case DW_TAG_array_type: if (components[i].first == target_symbol::comp_literal_array_index) { - c_translate_array (pool, 1, module_bias, die, tail, + c_translate_array (pool, 1, 0 /* PR9768 */, die, tail, NULL, lex_cast<Dwarf_Word>(components[i].second)); ++i; } @@ -1935,7 +2009,7 @@ struct dwflpp struct_die = *die; if (dwarf_hasattr(die, DW_AT_declaration)) { - Dwarf_Die *tmpdie = dwflpp::declaration_resolve(die); + Dwarf_Die *tmpdie = dwflpp::declaration_resolve(dwarf_diename(die)); if (tmpdie == NULL) throw semantic_error ("unresolved struct " + string (dwarf_diename_integrate (die) ?: "<anonymous>")); @@ -2049,6 +2123,7 @@ struct dwflpp /* Now iterate on the type in DIE's attribute. */ if (dwarf_attr_integrate (die, DW_AT_type, attr_mem) == NULL) throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1))); + die = dwarf_formref_die (attr_mem, die_mem); } return die; } @@ -2153,10 +2228,10 @@ struct dwflpp ty = pe_long; if (lvalue) - c_translate_store (pool, 1, module_bias, die, typedie, tail, + c_translate_store (pool, 1, 0 /* PR9768 */, die, typedie, tail, "THIS->value"); else - c_translate_fetch (pool, 1, module_bias, die, typedie, tail, + c_translate_fetch (pool, 1, 0 /* PR9768 */, die, typedie, tail, "THIS->__retvalue"); break; @@ -2183,7 +2258,7 @@ struct dwflpp if (typetag == DW_TAG_array_type) throw semantic_error ("cannot write to array address"); assert (typetag == DW_TAG_pointer_type); - c_translate_pointer_store (pool, 1, module_bias, typedie, tail, + c_translate_pointer_store (pool, 1, 0 /* PR9768 */, typedie, tail, "THIS->value"); } else @@ -2197,10 +2272,10 @@ struct dwflpp ty = pe_long; if (typetag == DW_TAG_array_type) - c_translate_array (pool, 1, module_bias, typedie, tail, NULL, 0); + c_translate_array (pool, 1, 0 /* PR9768 */, typedie, tail, NULL, 0); else - c_translate_pointer (pool, 1, module_bias, typedie, tail); - c_translate_addressof (pool, 1, module_bias, NULL, pointee_typedie, tail, + c_translate_pointer (pool, 1, 0 /* PR9768 */, typedie, tail); + c_translate_addressof (pool, 1, 0 /* PR9768 */, NULL, pointee_typedie, tail, "THIS->__retvalue"); } } @@ -2292,8 +2367,9 @@ struct dwflpp /* Translate the ->bar->baz[NN] parts. */ Dwarf_Die die_mem, *die = NULL; + die = dwarf_formref_die (&attr_mem, &die_mem); die = translate_components (&pool, &tail, pc, components, - &vardie, &die_mem, &attr_mem); + die, &die_mem, &attr_mem); if(!die) { die = dwarf_formref_die (&attr_mem, &vardie); @@ -2363,7 +2439,7 @@ struct dwflpp struct location *head = c_translate_location (&pool, &loc2c_error, this, &loc2c_emit_address, - 1, module_bias, + 1, 0 /* PR9768 */, pc, locops, nlocops, &tail, NULL); @@ -2410,6 +2486,60 @@ struct dwflpp } + string + literal_stmt_for_pointer (Dwarf_Die *type_die, + vector<pair<target_symbol::component_type, + std::string> > const & components, + bool lvalue, + exp_type & ty) + { + if (sess.verbose>2) + clog << "literal_stmt_for_pointer: finding value for " + << (dwarf_diename(type_die) ?: "<unknown>") + << "(" + << (dwarf_diename(cu) ?: "<unknown>") + << ")\n"; + + struct obstack pool; + obstack_init (&pool); + struct location *head = c_translate_argument (&pool, &loc2c_error, this, + &loc2c_emit_address, + 1, "THIS->pointer"); + struct location *tail = head; + + /* Translate the ->bar->baz[NN] parts. */ + + Dwarf_Attribute attr_mem; + Dwarf_Die die_mem, *die = NULL; + die = translate_components (&pool, &tail, 0, components, + type_die, &die_mem, &attr_mem); + if(!die) + { + die = dwarf_formref_die (&attr_mem, &die_mem); + stringstream alternatives; + print_members(die ?: type_die, alternatives); + throw semantic_error("unable to find member for struct " + + string(dwarf_diename(die ?: type_die) ?: "<unknown>") + + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")"))); + } + + + /* Translate the assignment part, either + x = (THIS->pointer)->bar->baz[NN] + or + (THIS->pointer)->bar->baz[NN] = x + */ + + string prelude, postlude; + translate_final_fetch_or_store (&pool, &tail, module_bias, + die, &attr_mem, lvalue, + prelude, postlude, ty); + + /* Write the translation to a string. */ + return express_as_string(prelude, postlude, head); + } + + ~dwflpp() { if (dwfl) @@ -2466,7 +2596,7 @@ struct dwarf_derived_probe: public derived_probe dwarf_builder * dw); static void register_function_and_statement_variants(match_node * root, dwarf_builder * dw); - static void register_patterns(match_node * root); + static void register_patterns(systemtap_session& s); }; @@ -2521,19 +2651,12 @@ public: // Helper struct to thread through the dwfl callbacks. struct base_query { - base_query(systemtap_session & sess, - probe * base_probe, - probe_point * base_loc, - dwflpp & dw, - literal_map_t const & params, - vector<derived_probe *> & results); + base_query(dwflpp & dw, literal_map_t const & params); + base_query(dwflpp & dw, const string & module_val); virtual ~base_query() {} systemtap_session & sess; - probe * base_probe; - probe_point * base_loc; dwflpp & dw; - vector<derived_probe *> & results; // Parameter extractors. static bool has_null_param(literal_map_t const & params, @@ -2555,14 +2678,8 @@ struct base_query }; -base_query::base_query(systemtap_session & sess, - probe * base_probe, - probe_point * base_loc, - dwflpp & dw, - literal_map_t const & params, - vector<derived_probe *> & results) - : sess(sess), base_probe(base_probe), base_loc(base_loc), dw(dw), - results(results) +base_query::base_query(dwflpp & dw, literal_map_t const & params): + sess(dw.sess), dw(dw) { has_kernel = has_null_param (params, TOK_KERNEL); if (has_kernel) @@ -2581,6 +2698,24 @@ base_query::base_query(systemtap_session & sess, assert (has_kernel || has_process || has_module); } +base_query::base_query(dwflpp & dw, const string & module_val) + : sess(dw.sess), dw(dw), module_val(module_val) +{ + // NB: This uses '/' to distinguish between kernel modules and userspace, + // which means that userspace modules won't get any PATH searching. + if (module_val.find('/') == string::npos) + { + has_kernel = (module_val == TOK_KERNEL); + has_module = !has_kernel; + has_process = false; + } + else + { + has_kernel = has_module = false; + has_process = true; + } +} + bool base_query::has_null_param(literal_map_t const & params, string const & k) @@ -2627,6 +2762,10 @@ struct dwarf_query : public base_query literal_map_t const & params, vector<derived_probe *> & results); + vector<derived_probe *> & results; + probe * base_probe; + probe_point * base_loc; + virtual void handle_query_module(); void query_module_dwarf(); void query_module_symtab(); @@ -2910,7 +3049,8 @@ dwarf_query::dwarf_query(systemtap_session & sess, dwflpp & dw, literal_map_t const & params, vector<derived_probe *> & results) - : base_query(sess, base_probe, base_loc, dw, params, results) + : base_query(dw, params), results(results), + base_probe(base_probe), base_loc(base_loc) { // Reduce the query to more reasonable semantic values (booleans, // extracted strings, numbers, etc). @@ -2920,6 +3060,8 @@ dwarf_query::dwarf_query(systemtap_session & sess, has_statement_str = get_string_param(params, TOK_STATEMENT, statement_str_val); has_statement_num = get_number_param(params, TOK_STATEMENT, statement_num_val); + has_label = get_string_param(params, TOK_LABEL, label_val); + has_call = has_null_param(params, TOK_CALL); has_inline = has_null_param(params, TOK_INLINE); has_return = has_null_param(params, TOK_RETURN); @@ -3089,7 +3231,12 @@ dwarf_query::build_blacklist() blfile += "kernel/kprobes.c"; // first alternative, no "|" blfile += "|arch/.*/kernel/kprobes.c"; + // Older kernels need ... blfile += "|include/asm/io.h"; + blfile += "|include/asm/bitops.h"; + // While newer ones need ... + blfile += "|arch/.*/include/asm/io.h"; + blfile += "|arch/.*/include/asm/bitops.h"; blfile += "|drivers/ide/ide-iops.c"; // XXX: it would be nice if these blacklisted functions were pulled @@ -3895,6 +4042,12 @@ query_cu (Dwarf_Die * cudie, void * arg) q->dw.iterate_over_srcfile_lines (*i, q->line, q->has_statement_str, q->line_type, query_srcfile_line, q); } + else if (q->has_label) + { + // If we have a pattern string with target *label*, we + // have to look at labels in all the matched srcfiles. + q->dw.iterate_over_cu_labels (q->label_val, q->dw.cu, q, query_statement); + } else { // Otherwise, simply probe all resolved functions. @@ -4139,22 +4292,22 @@ query_module (Dwfl_Module *mod, } void -dwflpp::query_modules(dwarf_query *q) +dwflpp::query_modules(base_query *q) { iterate_over_modules(&query_module, q); } -struct var_expanding_copy_visitor: public deep_copy_visitor +struct var_expanding_visitor: public update_visitor { static unsigned tick; stack<functioncall**> target_symbol_setter_functioncalls; - var_expanding_copy_visitor() {} + var_expanding_visitor() {} void visit_assignment (assignment* e); }; -struct dwarf_var_expanding_copy_visitor: public var_expanding_copy_visitor +struct dwarf_var_expanding_visitor: public var_expanding_visitor { dwarf_query & q; Dwarf_Die *scope_die; @@ -4164,17 +4317,18 @@ struct dwarf_var_expanding_copy_visitor: public var_expanding_copy_visitor std::map<std::string, symbol *> return_ts_map; bool visited; - dwarf_var_expanding_copy_visitor(dwarf_query & q, Dwarf_Die *sd, Dwarf_Addr a): + dwarf_var_expanding_visitor(dwarf_query & q, Dwarf_Die *sd, Dwarf_Addr a): q(q), scope_die(sd), addr(a), add_block(NULL), add_probe(NULL), visited(false) {} void visit_target_symbol (target_symbol* e); + void visit_cast_op (cast_op* e); }; -unsigned var_expanding_copy_visitor::tick = 0; +unsigned var_expanding_visitor::tick = 0; void -var_expanding_copy_visitor::visit_assignment (assignment* e) +var_expanding_visitor::visit_assignment (assignment* e) { // Our job would normally be to require() the left and right sides // into a new assignment. What we're doing is slightly trickier: @@ -4192,9 +4346,9 @@ var_expanding_copy_visitor::visit_assignment (assignment* e) expression *new_left, *new_right; target_symbol_setter_functioncalls.push (&fcall); - require<expression*> (this, &new_left, e->left); + new_left = require (e->left); target_symbol_setter_functioncalls.pop (); - require<expression*> (this, &new_right, e->right); + new_right = require (e->right); if (fcall != NULL) { @@ -4202,7 +4356,7 @@ var_expanding_copy_visitor::visit_assignment (assignment* e) // and it has been replaced with a set_target_foo() function // call; we are going to provide that function call -- with the // right child spliced in as sole argument -- in place of - // ourselves, in the deep copy we're in the middle of making. + // ourselves, in the var expansion we're in the middle of making. // FIXME: for the time being, we only support plan $foo = bar, // not += or any other op= variant. This is fixable, but a bit @@ -4213,22 +4367,19 @@ var_expanding_copy_visitor::visit_assignment (assignment* e) assert (new_left == fcall); fcall->args.push_back (new_right); - provide <expression*> (this, fcall); + provide (fcall); } else { - assignment* n = new assignment; - n->op = e->op; - n->tok = e->tok; - n->left = new_left; - n->right = new_right; - provide <assignment*> (this, n); + e->left = new_left; + e->right = new_right; + provide (e); } } void -dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) +dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) { assert(e->base_name.size() > 0 && e->base_name[0] == '$'); visited = true; @@ -4257,7 +4408,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) map<string, symbol *>::iterator i = return_ts_map.find(ts_name); if (i != return_ts_map.end()) { - provide <symbol*> (this, i->second); + provide (i->second); return; } @@ -4515,7 +4666,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) // (4) Provide the '_dwarf_tvar_{name}_{num}_tmp' variable to // our parent so it can be used as a substitute for the target // symbol. - provide <symbol*> (this, tmpsym); + provide (tmpsym); // (5) Remember this replacement since we might be able to reuse // it later if the same return probe references this target @@ -4561,7 +4712,8 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) // Ignore any variable that isn't accessible. tsym->saved_conversion_error = 0; - this->visit_target_symbol(tsym); // NB: throws nothing ... + expression *texp = tsym; + texp = require (texp); // NB: throws nothing ... if (tsym->saved_conversion_error) // ... but this is how we know it happened. { @@ -4570,7 +4722,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) { pf->raw_components += "return"; pf->raw_components += "=%#x "; - pf->args.push_back(*(expression**)this->targets.top()); + pf->args.push_back(texp); } } else @@ -4604,7 +4756,8 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) // Ignore any variable that isn't accessible. tsym->saved_conversion_error = 0; - this->visit_target_symbol(tsym); // NB: throws nothing ... + expression *texp = tsym; + texp = require (texp); // NB: throws nothing ... if (tsym->saved_conversion_error) // ... but this is how we know it happened. { if (q.sess.verbose>2) @@ -4623,14 +4776,14 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) { pf->raw_components += diename; pf->raw_components += "=%#x "; - pf->args.push_back(*(expression**)this->targets.top()); + pf->args.push_back(texp); } } while (dwarf_siblingof (&result, &result) == 0); } pf->components = print_format::string_to_components(pf->raw_components); - provide <print_format*> (this, pf); + provide (pf); return; } @@ -4674,7 +4827,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) // target_symbol to the next pass. We hope that this value ends // up not being referenced after all, so it can be optimized out // quietly. - provide <target_symbol*> (this, e); + provide (e); semantic_error* saveme = new semantic_error (er); // copy it saveme->tok1 = e->tok; // XXX: token not passed to q.dw code generation routines // NB: we can have multiple errors, since a $target variable @@ -4722,7 +4875,240 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) *(target_symbol_setter_functioncalls.top()) = n; } - provide <functioncall*> (this, n); + provide (n); +} + + +void +dwarf_var_expanding_visitor::visit_cast_op (cast_op *e) +{ + // Fill in our current module context if needed + if (e->module.empty()) + e->module = q.dw.module_name; + + var_expanding_visitor::visit_cast_op(e); +} + + +struct dwarf_cast_query : public base_query +{ + const cast_op& e; + const bool lvalue; + exp_type& pe_type; + + bool resolved; + string code; + + dwarf_cast_query(dwflpp& dw, const cast_op& e, bool lvalue, exp_type& pe_type): + base_query(dw, e.module), e(e), lvalue(lvalue), pe_type(pe_type), resolved(false) {} + const string& get_code(); + + void handle_query_module(); + int handle_query_cu(Dwarf_Die * cudie); + + static int cast_query_cu (Dwarf_Die * cudie, void * arg); +}; + + +const string& +dwarf_cast_query::get_code() +{ + if (!resolved) + dw.query_modules(this); + + if (!resolved) + throw semantic_error("type definition not found"); + + return code; +} + + +void +dwarf_cast_query::handle_query_module() +{ + if (resolved) + return; + + // look for the type in each CU + dw.iterate_over_cus(cast_query_cu, this); +} + + +int +dwarf_cast_query::handle_query_cu(Dwarf_Die * cudie) +{ + if (resolved) + return DWARF_CB_ABORT; + + dw.focus_on_cu (cudie); + Dwarf_Die* type_die = dw.declaration_resolve(e.type.c_str()); + if (type_die) + { + try + { + code = dw.literal_stmt_for_pointer (type_die, e.components, + lvalue, pe_type); + } + catch (const semantic_error& e) + { + // XXX might be better to save the error + // and try again in another CU + sess.print_error (e); + return DWARF_CB_ABORT; + } + + resolved = true; + return DWARF_CB_ABORT; + } + return DWARF_CB_OK; +} + + +int +dwarf_cast_query::cast_query_cu (Dwarf_Die * cudie, void * arg) +{ + dwarf_cast_query * q = static_cast<dwarf_cast_query *>(arg); + if (pending_interrupts) return DWARF_CB_ABORT; + return q->handle_query_cu(cudie); +} + + +struct dwarf_cast_expanding_visitor: public var_expanding_visitor +{ + systemtap_session& s; + dwarf_builder& db; + + dwarf_cast_expanding_visitor(systemtap_session& s, dwarf_builder& db): + s(s), db(db) {} + void visit_cast_op (cast_op* e); +}; + + +void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e) +{ + bool lvalue = is_active_lvalue(e); + if (lvalue && !s.guru_mode) + throw semantic_error("write to typecast value not permitted", e->tok); + + if (e->module.empty()) + e->module = "kernel"; // "*" may also be reasonable to search all kernel modules + + if (! s.module_cache) + s.module_cache = new module_cache (); + + string code; + exp_type type = pe_long; + try + { + // NB: This uses '/' to distinguish between kernel modules and userspace, + // which means that userspace modules won't get any PATH searching. + dwflpp* dw; + if (e->module.find('/') == string::npos) + { + // kernel or kernel module target + if (! db.kern_dw) + { + db.kern_dw = new dwflpp(s); + db.kern_dw->setup_kernel(true); + } + dw = db.kern_dw; + } + else + { + e->module = find_executable (e->module); // canonicalize it + + // user-space target; we use one dwflpp instance per module name + // (= program or shared library) + if (db.user_dw.find(e->module) == db.user_dw.end()) + { + dw = new dwflpp(s); + dw->setup_user(e->module); + db.user_dw[e->module] = dw; + } + else + dw = db.user_dw[e->module]; + } + + dwarf_cast_query q (*dw, *e, lvalue, type); + code = q.get_code(); + } + catch (const semantic_error& er) + { + // We suppress this error message, and pass the unresolved + // cast_op to the next pass. We hope that this value ends + // up not being referenced after all, so it can be optimized out + // quietly. + semantic_error* saveme = new semantic_error (er); // copy it + saveme->tok1 = e->tok; // XXX: token not passed to dw code generation routines + // NB: we can have multiple errors, since a @cast + // may be expanded in several different contexts: + // function ("*") { @cast(...) } + saveme->chain = e->saved_conversion_error; + e->saved_conversion_error = saveme; + provide (e); + return; + } + + string fname = (string(lvalue ? "_dwarf_tvar_set" : "_dwarf_tvar_get") + + "_" + e->base_name.substr(1) + + "_" + lex_cast<string>(tick++)); + + // Synthesize a function. + functiondecl *fdecl = new functiondecl; + fdecl->tok = e->tok; + fdecl->type = type; + fdecl->name = fname; + + embeddedcode *ec = new embeddedcode; + ec->tok = e->tok; + ec->code = code; + fdecl->body = ec; + + // Give the fdecl an argument for the pointer we're trying to cast + vardecl *v1 = new vardecl; + v1->type = pe_long; + v1->name = "pointer"; + v1->tok = e->tok; + fdecl->formal_args.push_back(v1); + + if (lvalue) + { + // Modify the fdecl so it carries a second pe_long formal + // argument called "value". + + // FIXME: For the time being we only support setting target + // variables which have base types; these are 'pe_long' in + // stap's type vocabulary. Strings and pointers might be + // reasonable, some day, but not today. + + vardecl *v2 = new vardecl; + v2->type = pe_long; + v2->name = "value"; + v2->tok = e->tok; + fdecl->formal_args.push_back(v2); + } + else + ec->code += "/* pure */"; + + s.functions[fdecl->name] = fdecl; + + // Synthesize a functioncall. + functioncall* n = new functioncall; + n->tok = e->tok; + n->function = fname; + n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session + n->args.push_back(e->operand); + + if (lvalue) + { + // Provide the functioncall to our parent, so that it can be + // used to substitute for the assignment node immediately above + // us. + assert(!target_symbol_setter_functioncalls.empty()); + *(target_symbol_setter_functioncalls.top()) = n; + } + + provide (n); } @@ -4791,11 +5177,11 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname, + lex_cast<string>(USHRT_MAX) + "]", q.base_loc->tok); - // Make a target-variable-expanded copy of the probe body + // Expand target variables in the probe body if (!null_die(scope_die)) { - dwarf_var_expanding_copy_visitor v (q, scope_die, dwfl_addr); - require <statement*> (&v, &(this->body), this->body); + dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr); + this->body = v.require (this->body); this->access_vars = v.visited; // If during target-variable-expanding the probe, we added a new block @@ -4913,13 +5299,19 @@ dwarf_derived_probe::register_function_and_statement_variants(match_node * root, } void -dwarf_derived_probe::register_patterns(match_node * root) +dwarf_derived_probe::register_patterns(systemtap_session& s) { + match_node* root = s.pattern_root; dwarf_builder *dw = new dwarf_builder(); + update_visitor *filter = new dwarf_cast_expanding_visitor(s, *dw); + s.code_filters.push_back(filter); + register_function_and_statement_variants(root->bind(TOK_KERNEL), dw); register_function_and_statement_variants(root->bind_str(TOK_MODULE), dw); root->bind(TOK_KERNEL)->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE)->bind(dw); + root->bind(TOK_KERNEL)->bind_str(TOK_FUNCTION)->bind_str(TOK_LABEL)->bind(dw); + root->bind_str(TOK_PROCESS)->bind_str(TOK_FUNCTION)->bind_str(TOK_LABEL)->bind(dw); register_function_and_statement_variants(root->bind_str(TOK_PROCESS), dw); root->bind_str(TOK_PROCESS)->bind_str(TOK_MARK)->bind(dw); @@ -4978,7 +5370,7 @@ dwarf_derived_probe_group::emit_module_decls (systemtap_session& s) // NB: we used to plop a union { struct kprobe; struct kretprobe } into // struct stap_dwarf_probe, but it being initialized data makes it add // hundreds of bytes of padding per stap_dwarf_probe. (PR5673) - s.op->newline() << "struct stap_dwarf_kprobe {"; + s.op->newline() << "static struct stap_dwarf_kprobe {"; s.op->newline(1) << "union { struct kprobe kp; struct kretprobe krp; } u;"; s.op->newline() << "#ifdef __ia64__"; s.op->newline() << "struct kprobe dummy;"; @@ -4986,7 +5378,7 @@ dwarf_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(-1) << "} stap_dwarf_kprobes[" << probes_by_module.size() << "];"; // NB: bss! - s.op->newline() << "struct stap_dwarf_probe {"; + s.op->newline() << "static struct stap_dwarf_probe {"; s.op->newline(1) << "const unsigned return_p:1;"; s.op->newline() << "const unsigned maxactive_p:1;"; s.op->newline() << "unsigned registered_p:1;"; @@ -5301,30 +5693,39 @@ dwarf_builder::build(systemtap_session & sess, { enum probe_types { - no_debuginfo = 0, - use_debuginfo = 1 + probes_and_dwarf = 0, // Use statement address + dwarf_no_probes = 1, // Use label name + probes_no_dwarf = 2 }; -// location->components[0]->arg = new literal_string(sess.cmd); -// ((literal_map_t&)parameters)[location->components[0]->functor] = location->components[0]->arg; + int probe_type = dwarf_no_probes; + string probe_name = (char*) location->components[1]->arg->tok->content.c_str(); + __uint64_t probe_arg = 0; Dwarf_Addr bias; Elf* elf = dwfl_module_getelf (dw->module, &bias); size_t shstrndx; - Elf_Scn *probe_scn = NULL; + bool probe_found = false; + dwfl_assert ("getshstrndx", elf_getshstrndx (elf, &shstrndx)); - __uint64_t probe_arg = 0; - int probe_type = no_debuginfo; - char *probe_name; - // Find the .probes section where the static probe label and arg are stored + GElf_Shdr *shdr = NULL; + + // Is there a .probes section? while ((probe_scn = elf_nextscn (elf, probe_scn))) { GElf_Shdr shdr_mem; - GElf_Shdr *shdr = gelf_getshdr (probe_scn, &shdr_mem); + shdr = gelf_getshdr (probe_scn, &shdr_mem); assert (shdr != NULL); - if (strcmp (elf_strptr (elf, shstrndx, shdr->sh_name), ".probes") != 0) - continue; + if (strcmp (elf_strptr (elf, shstrndx, shdr->sh_name), ".probes") == 0) + { + probe_type = probes_and_dwarf; + break; + } + } + + if (probe_type == probes_and_dwarf) + { Elf_Data *pdata = elf_getdata_rawchunk (elf, shdr->sh_offset, shdr->sh_size, ELF_T_BYTE); assert (pdata != NULL); size_t probe_scn_offset = 0; @@ -5342,95 +5743,35 @@ dwarf_builder::build(systemtap_session & sess, if (probe_scn_offset % (sizeof(__uint64_t))) probe_scn_offset += sizeof(__uint64_t) - (probe_scn_offset % sizeof(__uint64_t)); - // pdata->d_buf + *(long*)(pdata->d_buf + probe_scn_offset) - probe_scn_addr probe_name = ((char*)((long)(pdata->d_buf) + (long)(*((int*)((long)pdata->d_buf + probe_scn_offset)) - probe_scn_addr))); probe_scn_offset += sizeof(void*); if (probe_scn_offset % (sizeof(__uint64_t))) probe_scn_offset += sizeof(__uint64_t) - (probe_scn_offset % sizeof(__uint64_t)); probe_arg = *((__uint64_t*)((char*)pdata->d_buf + probe_scn_offset)); - if (strcmp (location->components[1]->arg->tok->content.c_str(), probe_name) == 0) - break; - if (probe_scn_offset % (sizeof(__uint64_t)*2)) - probe_scn_offset = (probe_scn_offset + sizeof(__uint64_t)*2) - (probe_scn_offset % (sizeof(__uint64_t)*2)); - } - if (probe_scn_offset < pdata->d_size) - break; - } - - if (probe_type == no_debuginfo) - { - // Many probe labels correspond to _stap_probe_N - // Generate: _probe_string = user_string($probe); - block *b = ((block*)(base->body)); - assignment *as = new assignment; - symbol* lsym = new symbol; - lsym->type = pe_string; - lsym->name = "_probe_string"; - lsym->tok = base->body->tok; - as->left = lsym; - as->op = "="; - functioncall *fc = new functioncall; - fc->function = "user_string"; - fc->tok = base->body->tok; - target_symbol* rsym = new target_symbol; - rsym->base_name = "$probe"; - rsym->tok = base->body->tok; - fc->args.push_back(rsym); - as->right = fc; - expr_statement* es = new expr_statement; - es->value = as; - - // Generate: if (_probe_string != mark("label")) next; - if_statement *is = new if_statement; - is->thenblock = new next_statement; - is->elseblock = NULL; - is->tok = base->body->tok; - comparison *be = new comparison; - be->op = "!="; - be->tok = base->body->tok; - be->left = lsym; - be->right = new literal_string(location->components[1]->arg->tok->content);; - is->condition = be; - - b->statements.insert(b->statements.begin(),(statement*) is); - b->statements.insert(b->statements.begin(),(statement*) es); - } - - Dwarf *dwarf = dwfl_module_getdwarf(dw->module, &dw->module_bias); - Dwarf_Off off; - size_t cuhl; - Dwarf_Off noff = 0; - const char *probe_file = "@sduprobes.c"; - // Find where the probe instrumentation landing points are defined - while (dwarf_nextcu (dwarf, off = noff, &noff, &cuhl, NULL, NULL, NULL) == 0) - { - Dwarf_Die cudie_mem; - Dwarf_Die *cudie = dwarf_offdie (dwarf, off + cuhl, &cudie_mem); - if (cudie == NULL) - continue; - if (probe_type == no_debuginfo) - { - if (strncmp (dwarf_diename(&cudie_mem), "sduprobes", 9) == 0) + if (strcmp (location->components[1]->arg->tok->content.c_str(), probe_name.c_str()) == 0) { + probe_found = true; break; } + if (probe_scn_offset % (sizeof(__uint64_t)*2)) + probe_scn_offset = (probe_scn_offset + sizeof(__uint64_t)*2) - (probe_scn_offset % (sizeof(__uint64_t)*2)); } + location->components[1]->functor = TOK_STATEMENT; + location->components[1]->arg = new literal_number((int)probe_arg); + ((literal_map_t&)parameters)[TOK_STATEMENT] = location->components[1]->arg; } - location->components[1]->functor = TOK_STATEMENT; - if (probe_type == no_debuginfo) - { - string probe_arg_str = string(1,'0' + probe_arg); - location->components[1]->arg - = new literal_string("_stap_probe_" - + (probe_arg_str) - + probe_file + "+1"); - } - else + + if (probe_type == dwarf_no_probes || ! probe_found) { - location->components[1]->arg = new literal_number((int)probe_arg); + location->components[1]->functor = TOK_FUNCTION; + location->components[1]->arg = new literal_string("*"); + ((literal_map_t&)parameters)[TOK_FUNCTION] = location->components[1]->arg; + location->components.push_back(new probe_point::component(TOK_LABEL)); + location->components[2]->arg = new literal_string("_stapprobe1_" + probe_name); + ((literal_map_t&)parameters).erase(TOK_MARK); + ((literal_map_t&)parameters).insert(pair<string,literal*>(TOK_LABEL, location->components[2]->arg)); } - ((literal_map_t&)parameters)[TOK_STATEMENT] = location->components[1]->arg; dw->module = 0; } @@ -6058,7 +6399,7 @@ itrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(-1) << "return rc;"; s.op->newline(-1) << "}"; - s.op->newline() << "struct stap_itrace_probe stap_itrace_probes[] = {"; + s.op->newline() << "static struct stap_itrace_probe stap_itrace_probes[] = {"; s.op->indent(1); // Set up 'process(PATH)' probes @@ -6178,10 +6519,10 @@ public: }; -struct utrace_var_expanding_copy_visitor: public var_expanding_copy_visitor +struct utrace_var_expanding_visitor: public var_expanding_visitor { - utrace_var_expanding_copy_visitor(systemtap_session& s, const string& pn, - enum utrace_derived_probe_flags f): + utrace_var_expanding_visitor(systemtap_session& s, const string& pn, + enum utrace_derived_probe_flags f): sess (s), probe_name (pn), flags (f), target_symbol_seen (false) {} systemtap_session& sess; @@ -6204,9 +6545,9 @@ utrace_derived_probe::utrace_derived_probe (systemtap_session &s, has_path(hp), path(pn), pid(pd), flags(f), target_symbol_seen(false) { - // Make a local-variable-expanded copy of the probe body - utrace_var_expanding_copy_visitor v (s, name, flags); - require <statement*> (&v, &(this->body), base->body); + // Expand local variables in the probe body + utrace_var_expanding_visitor v (s, name, flags); + this->body = v.require (this->body); target_symbol_seen = v.target_symbol_seen; // Reset the sole element of the "locations" vector as a @@ -6268,7 +6609,7 @@ utrace_derived_probe::join_group (systemtap_session& s) void -utrace_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e) +utrace_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) { string argnum_s = e->base_name.substr(4,e->base_name.length()-4); int argnum = lex_cast<int>(argnum_s); @@ -6317,11 +6658,11 @@ utrace_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e) num->tok = e->tok; n->args.push_back(num); - provide <functioncall*> (this, n); + provide (n); } void -utrace_var_expanding_copy_visitor::visit_target_symbol_context (target_symbol* e) +utrace_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) { string sname = e->base_name; @@ -6368,11 +6709,11 @@ utrace_var_expanding_copy_visitor::visit_target_symbol_context (target_symbol* e n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - provide <functioncall*> (this, n); + provide (n); } void -utrace_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e) +utrace_var_expanding_visitor::visit_target_symbol (target_symbol* e) { assert(e->base_name.size() > 0 && e->base_name[0] == '$'); @@ -6622,7 +6963,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "static void stap_utrace_probe_handler(struct task_struct *tsk, struct stap_utrace_probe *p) {"; s.op->indent(1); - common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", true, true, true); + common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING"); s.op->newline() << "c->probe_point = p->pp;"; // call probe function @@ -6798,7 +7139,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "return rc;"; s.op->newline(-1) << "}"; - s.op->newline() << "struct stap_utrace_probe stap_utrace_probes[] = {"; + s.op->newline() << "static struct stap_utrace_probe stap_utrace_probes[] = {"; s.op->indent(1); // Set up 'process(PATH)' probes @@ -6927,11 +7268,11 @@ uprobe_derived_probe::uprobe_derived_probe (const string& function, this->tok = q.base_probe->tok; - // Make a target-variable-expanded copy of the probe body + // Expand target variables in the probe body if (!null_die(scope_die)) { - dwarf_var_expanding_copy_visitor v (q, scope_die, dwfl_addr); // XXX: user-space deref's! - require <statement*> (&v, &(this->body), this->body); + dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr); // XXX: user-space deref's! + this->body = v.require (this->body); // If during target-variable-expanding the probe, we added a new block // of code, add it to the start of the probe. @@ -7090,13 +7431,13 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) // In .bss, the shared pool of uprobe/uretprobe structs. These are // too big to embed in the initialized .data stap_uprobe_spec array. - s.op->newline() << "struct stap_uprobe {"; + s.op->newline() << "static struct stap_uprobe {"; s.op->newline(1) << "union { struct uprobe up; struct uretprobe urp; };"; s.op->newline() << "int spec_index;"; // index into stap_uprobe_specs; <0 == free && unregistered s.op->newline(-1) << "} stap_uprobes [MAXUPROBES];"; s.op->newline() << "DEFINE_MUTEX(stap_uprobes_lock);"; // protects against concurrent registration/unregistration - s.op->newline() << "struct stap_uprobe_spec {"; + s.op->newline() << "static struct stap_uprobe_spec {"; s.op->newline(1) << "struct stap_task_finder_target finder;"; s.op->newline() << "unsigned long address;"; s.op->newline() << "const char *pathname;"; @@ -7441,7 +7782,7 @@ timer_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "/* ---- timer probes ---- */"; - s.op->newline() << "struct stap_timer_probe {"; + s.op->newline() << "static struct stap_timer_probe {"; s.op->newline(1) << "struct timer_list timer_list;"; s.op->newline() << "const char *pp;"; s.op->newline() << "void (*ph) (struct context*);"; @@ -7471,7 +7812,7 @@ timer_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->line() << ");"; s.op->newline(-1) << "{"; s.op->indent(1); - common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", true, true, true); + common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING"); s.op->newline() << "c->probe_point = stp->pp;"; s.op->newline() << "(*stp->ph) (c);"; common_probe_entryfn_epilogue (s.op); @@ -7613,7 +7954,7 @@ profile_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)"; // == using_rpn of yore - s.op->newline() << "int enter_profile_probes (struct notifier_block *self," + s.op->newline() << "static int enter_profile_probes (struct notifier_block *self," << " unsigned long val, void *data) {"; s.op->newline(1) << "(void) self; (void) val;"; s.op->newline() << "enter_all_profile_probes ((struct pt_regs *) data);"; @@ -7624,7 +7965,7 @@ profile_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "#else"; - s.op->newline() << "int enter_profile_probes (struct pt_regs *regs) {"; + s.op->newline() << "static int enter_profile_probes (struct pt_regs *regs) {"; s.op->newline(1) << "enter_all_profile_probes (regs);"; s.op->newline() << "return 0;"; s.op->newline(-1) << "}"; @@ -7711,10 +8052,10 @@ public: }; -struct procfs_var_expanding_copy_visitor: public var_expanding_copy_visitor +struct procfs_var_expanding_visitor: public var_expanding_visitor { - procfs_var_expanding_copy_visitor(systemtap_session& s, const string& pn, - string path, bool write_probe): + procfs_var_expanding_visitor(systemtap_session& s, const string& pn, + string path, bool write_probe): sess (s), probe_name (pn), path (path), write_probe (write_probe), target_symbol_seen (false) {} @@ -7732,9 +8073,9 @@ procfs_derived_probe::procfs_derived_probe (systemtap_session &s, probe* p, probe_point* l, string ps, bool w): derived_probe(p, l), path(ps), write(w), target_symbol_seen(false) { - // Make a local-variable-expanded copy of the probe body - procfs_var_expanding_copy_visitor v (s, name, path, write); - require <statement*> (&v, &(this->body), base->body); + // Expand local variables in the probe body + procfs_var_expanding_visitor v (s, name, path, write); + this->body = v.require (this->body); target_symbol_seen = v.target_symbol_seen; } @@ -7791,9 +8132,10 @@ procfs_derived_probe_group::emit_module_decls (systemtap_session& s) return; s.op->newline() << "/* ---- procfs probes ---- */"; + s.op->newline() << "#include \"procfs.c\""; // Emit the procfs probe data list - s.op->newline() << "struct stap_procfs_probe {"; + s.op->newline() << "static struct stap_procfs_probe {"; s.op->newline(1)<< "const char *path;"; s.op->newline() << "const char *read_pp;"; s.op->newline() << "void (*read_ph) (struct context*);"; @@ -7850,7 +8192,7 @@ procfs_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "int bytes = 0;"; s.op->newline() << "string_t strdata = {'\\0'};"; - common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", true, true, true); + common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING"); s.op->newline() << "c->probe_point = spp->read_pp;"; s.op->newline() << "if (c->data == NULL)"; @@ -7893,7 +8235,7 @@ procfs_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(1) << "struct stap_procfs_probe *spp = (struct stap_procfs_probe *)data;"; s.op->newline() << "string_t strdata = {'\\0'};"; - common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", true, true, true); + common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING"); s.op->newline() << "c->probe_point = spp->write_pp;"; s.op->newline() << "if (count > (MAXSTRINGLEN - 1))"; @@ -7983,7 +8325,7 @@ procfs_derived_probe_group::emit_module_exit (systemtap_session& s) void -procfs_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e) +procfs_var_expanding_visitor::visit_target_symbol (target_symbol* e) { assert(e->base_name.size() > 0 && e->base_name[0] == '$'); @@ -8068,7 +8410,7 @@ procfs_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e) *(target_symbol_setter_functioncalls.top()) = n; } - provide <functioncall*> (this, n); + provide (n); } @@ -8187,11 +8529,10 @@ public: }; -struct mark_var_expanding_copy_visitor: public var_expanding_copy_visitor +struct mark_var_expanding_visitor: public var_expanding_visitor { - mark_var_expanding_copy_visitor(systemtap_session& s, - const string& pn, - vector <struct mark_arg *> &mark_args): + mark_var_expanding_visitor(systemtap_session& s, const string& pn, + vector <struct mark_arg *> &mark_args): sess (s), probe_name (pn), mark_args (mark_args), target_symbol_seen (false) {} systemtap_session& sess; @@ -8242,7 +8583,7 @@ hex_dump(unsigned char *data, size_t len) void -mark_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e) +mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) { string argnum_s = e->base_name.substr(4,e->base_name.length()-4); int argnum = atoi (argnum_s.c_str()); @@ -8303,12 +8644,12 @@ mark_var_expanding_copy_visitor::visit_target_symbol_arg (target_symbol* e) n->tok = e->tok; n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - provide <functioncall*> (this, n); + provide (n); } void -mark_var_expanding_copy_visitor::visit_target_symbol_context (target_symbol* e) +mark_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) { string sname = e->base_name; @@ -8345,11 +8686,11 @@ mark_var_expanding_copy_visitor::visit_target_symbol_context (target_symbol* e) n->tok = e->tok; n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - provide <functioncall*> (this, n); + provide (n); } void -mark_var_expanding_copy_visitor::visit_target_symbol (target_symbol* e) +mark_var_expanding_visitor::visit_target_symbol (target_symbol* e) { assert(e->base_name.size() > 0 && e->base_name[0] == '$'); @@ -8382,9 +8723,9 @@ mark_derived_probe::mark_derived_probe (systemtap_session &s, // expand the marker format parse_probe_format(); - // Now make a local-variable-expanded copy of the probe body - mark_var_expanding_copy_visitor v (sess, name, mark_args); - require <statement*> (&v, &(this->body), base->body); + // Now expand the local variables in the probe body + mark_var_expanding_visitor v (sess, name, mark_args); + this->body = v.require (this->body); target_symbol_seen = v.target_symbol_seen; if (sess.verbose > 2) @@ -8627,7 +8968,7 @@ mark_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "/* ---- marker probes ---- */"; - s.op->newline() << "struct stap_marker_probe {"; + s.op->newline() << "static struct stap_marker_probe {"; s.op->newline(1) << "const char * const name;"; s.op->newline() << "const char * const format;"; s.op->newline() << "const char * const pp;"; @@ -8655,7 +8996,7 @@ mark_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(); s.op->newline() << "static void enter_marker_probe (void *probe_data, void *call_data, const char *fmt, va_list *args) {"; s.op->newline(1) << "struct stap_marker_probe *smp = (struct stap_marker_probe *)probe_data;"; - common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", true, true, true); + common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING"); s.op->newline() << "c->probe_point = smp->pp;"; s.op->newline() << "c->marker_name = smp->name;"; s.op->newline() << "c->marker_format = smp->format;"; @@ -8838,7 +9179,6 @@ mark_builder::build(systemtap_session & sess, it->first, it->second, base, loc); finished_results.push_back (dp); - sess.unwindsym_modules.insert ("kernel"); } } } @@ -8934,8 +9274,8 @@ hrtimer_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "/* ---- hrtimer probes ---- */"; - s.op->newline() << "unsigned long stap_hrtimer_resolution;"; // init later - s.op->newline() << "struct stap_hrtimer_probe {"; + s.op->newline() << "static unsigned long stap_hrtimer_resolution;"; // init later + s.op->newline() << "static struct stap_hrtimer_probe {"; s.op->newline(1) << "struct hrtimer hrtimer;"; s.op->newline() << "const char *pp;"; s.op->newline() << "void (*ph) (struct context*);"; @@ -8985,7 +9325,7 @@ hrtimer_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(-1) << "}"; s.op->newline() << "{"; s.op->indent(1); - common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", true, true, true); + common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING"); s.op->newline() << "c->probe_point = stp->pp;"; s.op->newline() << "(*stp->ph) (c);"; common_probe_entryfn_epilogue (s.op); @@ -9041,7 +9381,7 @@ struct timer_builder: public derived_probe_builder literal_map_t const & parameters, vector<derived_probe *> & finished_results); - static void register_patterns(match_node *root); + static void register_patterns(systemtap_session& s); }; void @@ -9112,8 +9452,9 @@ timer_builder::build(systemtap_session & sess, } void -timer_builder::register_patterns(match_node *root) +timer_builder::register_patterns(systemtap_session& s) { + match_node* root = s.pattern_root; derived_probe_builder *builder = new timer_builder(); root = root->bind(TOK_TIMER); @@ -9153,18 +9494,18 @@ timer_builder::register_patterns(match_node *root) // -struct perfmon_var_expanding_copy_visitor: public var_expanding_copy_visitor +struct perfmon_var_expanding_visitor: public var_expanding_visitor { systemtap_session & sess; unsigned counter_number; - perfmon_var_expanding_copy_visitor(systemtap_session & s, unsigned c): + perfmon_var_expanding_visitor(systemtap_session & s, unsigned c): sess(s), counter_number(c) {} void visit_target_symbol (target_symbol* e); }; void -perfmon_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) +perfmon_var_expanding_visitor::visit_target_symbol (target_symbol *e) { assert(e->base_name.size() > 0 && e->base_name[0] == '$'); @@ -9218,7 +9559,7 @@ perfmon_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) n->function = fname; n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - provide <functioncall*> (this, n); + provide (n); } @@ -9286,9 +9627,9 @@ perfmon_derived_probe::perfmon_derived_probe (probe* p, probe_point* l, { ++probes_allocated; - // Now make a local-variable-expanded copy of the probe body - perfmon_var_expanding_copy_visitor v (sess, probes_allocated-1); - require <statement*> (&v, &(this->body), base->body); + // Now expand the local variables in the probe body + perfmon_var_expanding_visitor v (sess, probes_allocated-1); + this->body = v.require (this->body); if (sess.verbose > 1) clog << "perfmon-based probe" << endl; @@ -9581,13 +9922,13 @@ register_standard_tapsets(systemtap_session & s) s.pattern_root->bind(TOK_NEVER)->bind(new never_builder()); - timer_builder::register_patterns(s.pattern_root); + timer_builder::register_patterns(s); s.pattern_root->bind(TOK_TIMER)->bind("profile")->bind(new profile_builder()); s.pattern_root->bind("perfmon")->bind_str("counter") ->bind(new perfmon_builder()); // dwarf-based kprobe/uprobe parts - dwarf_derived_probe::register_patterns(s.pattern_root); + dwarf_derived_probe::register_patterns(s); // XXX: user-space starter set s.pattern_root->bind_num(TOK_PROCESS) @@ -9688,3 +10029,5 @@ all_session_groups(systemtap_session& s) #undef DOONE return g; } + +/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ |