diff options
author | Dave Brolley <brolley@redhat.com> | 2008-08-29 16:10:01 -0400 |
---|---|---|
committer | Dave Brolley <brolley@redhat.com> | 2008-08-29 16:10:01 -0400 |
commit | 0cbf1fef13d340b4a6d01fe7242a6d0c098e8d6c (patch) | |
tree | add6c27ae60763af4c4a1aa90db7f65e465759e3 | |
parent | d1f2fc72bf8506d0ac166cddb07576c7c4a1fea6 (diff) | |
parent | 8d142c018986acb256a08c1232f4f5ff0ee063df (diff) | |
download | systemtap-steved-0cbf1fef13d340b4a6d01fe7242a6d0c098e8d6c.tar.gz systemtap-steved-0cbf1fef13d340b4a6d01fe7242a6d0c098e8d6c.tar.xz systemtap-steved-0cbf1fef13d340b4a6d01fe7242a6d0c098e8d6c.zip |
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap
Conflicts:
ChangeLog
-rw-r--r-- | ChangeLog | 22 | ||||
-rw-r--r-- | NEWS | 7 | ||||
-rw-r--r-- | buildrun.cxx | 22 | ||||
-rw-r--r-- | coveragedb.cxx | 4 | ||||
-rw-r--r-- | coveragedb.h | 4 | ||||
-rw-r--r-- | doc/ChangeLog | 4 | ||||
-rw-r--r-- | doc/langref.tex | 4 | ||||
-rw-r--r-- | dwarf_wrappers.h | 2 | ||||
-rw-r--r-- | elaborate.cxx | 347 | ||||
-rw-r--r-- | elaborate.h | 4 | ||||
-rw-r--r-- | hash.cxx | 6 | ||||
-rw-r--r-- | main.cxx | 29 | ||||
-rw-r--r-- | mdfour.c | 46 | ||||
-rw-r--r-- | mdfour.h | 10 | ||||
-rw-r--r-- | parse.cxx | 162 | ||||
-rw-r--r-- | parse.h | 10 | ||||
-rw-r--r-- | runtime/ChangeLog | 8 | ||||
-rw-r--r-- | runtime/task_finder.c | 120 | ||||
-rw-r--r-- | session.h | 6 | ||||
-rw-r--r-- | stap.1.in | 4 | ||||
-rw-r--r-- | staptree.cxx | 136 | ||||
-rw-r--r-- | staptree.h | 2 | ||||
-rw-r--r-- | tapsets.cxx | 114 | ||||
-rw-r--r-- | testsuite/ChangeLog | 6 | ||||
-rwxr-xr-x | testsuite/semok/optimize.stp | 1 | ||||
-rw-r--r-- | testsuite/systemtap.base/global_end.exp | 8 | ||||
-rw-r--r-- | testsuite/systemtap.base/utrace_p5.exp | 27 | ||||
-rw-r--r-- | translate.cxx | 506 | ||||
-rw-r--r-- | util.cxx | 6 | ||||
-rw-r--r-- | util.h | 8 |
30 files changed, 841 insertions, 794 deletions
@@ -6,12 +6,34 @@ * Makefile.in: Regenerated. * configure: Regenerated. +2008-08-29 Stan Cox <scox@redhat.com> + + * elaborate.cxx (add_global_var_display): Repopulate symbol/type info. + +2008-08-29 David Smith <dsmith@redhat.com> + + * tapsets.cxx (utrace_derived_probe_group::emit_probe_decl): + Pushed quiesce logic down into the task_finder layer. + (utrace_derived_probe_group::emit_module_decls): Removed quiesce + handler routines. Syscall probe handler detaches if systemtap + state isn't correct. + +2008-08-29 Wenji Huang <wenji.huang@oracle.com> + + * main.cxx (printscript): Print variable name and type for listing mode. + +2008-08-28 Frank Ch. Eigler <fche@elastic.org> + + * elaborate.cxx (add_global_var_display): Render array indexes + in [key,key,key] vs. [key][key][key] form. + 2008-08-27 Stan Cox <scox@redhat.com> * elaborate.cxx (add_global_var_display): New. (semantic_pass): Call it. (dead_assignment_remover::visit_assignment): Don't remove written but unread global variables. + * NEWS, stap.1.in: Document 2008-08-26 David Smith <dsmith@redhat.com> @@ -1,5 +1,12 @@ * What's new +- Global variables which are written to but never read are now + automatically displayed when the session does a shutdown. For example: + + global running_tasks + probe timer.profile {running_tasks[pid(),tid()] = execname()} + probe timer.ms(8000) {exit()} + - A formatted string representation of the variables, parameters, or local variables at a probe point is now supported via the special $$vars, $$parms, and $$locals context variables, which expand to a string diff --git a/buildrun.cxx b/buildrun.cxx index 6b2b779d..ada00027 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -53,10 +53,10 @@ run_make_cmd(systemtap_session& s, string& make_cmd) make_cmd += " >/dev/null"; else make_cmd += " -s >/dev/null 2>&1"; - + if (s.verbose > 1) clog << "Running " << make_cmd << endl; rc = system (make_cmd.c_str()); - + return rc; } @@ -133,7 +133,7 @@ compile_pass (systemtap_session& s) o << "EXTRA_CFLAGS += -freorder-blocks" << endl; // improve on -Os // o << "CFLAGS += -fno-unit-at-a-time" << endl; - + // Assumes linux 2.6 kbuild o << "EXTRA_CFLAGS += -Wno-unused -Werror" << endl; o << "EXTRA_CFLAGS += -I\"" << s.runtime_path << "\"" << endl; @@ -154,7 +154,7 @@ compile_pass (systemtap_session& s) << strerror(errno) << endl << "Make sure kernel devel is installed." << endl; return rc; - } + } // Run make string make_cmd = string("make") @@ -162,7 +162,7 @@ compile_pass (systemtap_session& s) make_cmd += string(" M=\"") + s.tmpdir + string("\" modules"); rc = run_make_cmd(s, make_cmd); - + return rc; } @@ -274,23 +274,23 @@ run_pass (systemtap_session& s) + (s.verbose>1 ? "-v " : "") + (s.verbose>2 ? "-v " : "") + (s.output_file.empty() ? "" : "-o " + s.output_file + " "); - + if (s.cmd != "") staprun_cmd += "-c " + cmdstr_quoted(s.cmd) + " "; - + if (s.target_pid) staprun_cmd += "-t " + stringify(s.target_pid) + " "; - + if (s.buffer_size) staprun_cmd += "-b " + stringify(s.buffer_size) + " "; - + if (s.need_uprobes) staprun_cmd += "-u "; staprun_cmd += s.tmpdir + "/" + s.module_name + ".ko"; - + if (s.verbose>1) clog << "Running " << staprun_cmd << endl; - + rc = system (staprun_cmd.c_str ()); return rc; } diff --git a/coveragedb.cxx b/coveragedb.cxx index 8258b359..63cc4c0f 100644 --- a/coveragedb.cxx +++ b/coveragedb.cxx @@ -35,7 +35,7 @@ void print_coverage_info(systemtap_session &s) clog << "probe: " << used_probe_list[j]->locations[k]->tok->location << endl; } - + clog << "----" << endl; // for each probe print used and unused variables for (unsigned j=0; j<s.probes[i]->locals.size(); ++j) { @@ -210,7 +210,7 @@ sql_update_used_probes(sqlite3 *db, systemtap_session &s) increment_element(db, x); } } - + // for each probe update used and unused variables for (unsigned j=0; j<s.probes[i]->locals.size(); ++j) { struct source_loc place = s.probes[i]->locals[j]->tok->location; diff --git a/coveragedb.h b/coveragedb.h index ccf1911d..df5782ca 100644 --- a/coveragedb.h +++ b/coveragedb.h @@ -62,11 +62,11 @@ public: int compiled; int executed; - coverage_element() { line = 0; col = 0; + coverage_element() { line = 0; col = 0; compiled = 0; executed = 0; } coverage_element(source_loc &place) { - file = place.file; line = place.line; col = place.column; + file = place.file; line = place.line; col = place.column; compiled = 0; executed = 0; } }; diff --git a/doc/ChangeLog b/doc/ChangeLog index a04c4cdc..d28b588d 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2008-08-28 Stan Cox <scox@redhat.com> + + * langref.tex: Document written but unread global variable display. + 2008-08-25 Frank Ch. Eigler <fche@elastic.org> * Makefile.am: Removed dist-related targets and macros. diff --git a/doc/langref.tex b/doc/langref.tex index 413ece4d..5db82550 100644 --- a/doc/langref.tex +++ b/doc/langref.tex @@ -495,7 +495,9 @@ found. Because of possible concurrency limits, such as multiple probe handlers, each global variable used by a probe is automatically read- or write-locked while the handler is running. A global declaration may be written at the outermost level anywhere in a script file, not just within a block of code. -The following declaration marks \texttt{var1} and \texttt{var2} as global. +Global variables which are written but never read will be displayed +automatically at session shutdown. The following declaration marks +\texttt{var1} and \texttt{var2} as global. The translator will infer a value type for each, and if the variable is used as an array, its key types. diff --git a/dwarf_wrappers.h b/dwarf_wrappers.h index c498de05..abf2c1e5 100644 --- a/dwarf_wrappers.h +++ b/dwarf_wrappers.h @@ -63,7 +63,7 @@ public: { return line != 0; } - + int lineno() const { int lineval; diff --git a/elaborate.cxx b/elaborate.cxx index 4fe228ab..7ecba049 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -127,7 +127,7 @@ derived_probe::sole_location () const throw semantic_error ("derived_probe with no locations", this->tok); else if (locations.size() > 1) throw semantic_error ("derived_probe with too many locations", this->tok); - else + else return locations[0]; } @@ -183,9 +183,9 @@ derived_probe_builder::has_null_param (std::map<std::string, literal*> const & p // ------------------------------------------------------------------------ // Members of match_key. -match_key::match_key(string const & n) - : name(n), - have_parameter(false), +match_key::match_key(string const & n) + : name(n), + have_parameter(false), parameter_type(pe_unknown) { } @@ -198,7 +198,7 @@ match_key::match_key(probe_point::component const & c) } match_key & -match_key::with_number() +match_key::with_number() { have_parameter = true; parameter_type = pe_long; @@ -206,14 +206,14 @@ match_key::with_number() } match_key & -match_key::with_string() +match_key::with_string() { have_parameter = true; parameter_type = pe_string; return *this; } -string +string match_key::str() const { if (have_parameter) @@ -226,16 +226,16 @@ match_key::str() const return name; } -bool +bool match_key::operator<(match_key const & other) const { return ((name < other.name) - - || (name == other.name + + || (name == other.name && have_parameter < other.have_parameter) - - || (name == other.name - && have_parameter == other.have_parameter + + || (name == other.name + && have_parameter == other.have_parameter && parameter_type < other.parameter_type)); } @@ -252,7 +252,7 @@ match_key::globmatch(match_key const & other) const const char *name_str = name.c_str(); return ((fnmatch(name_str, other_str, FNM_NOESCAPE) == 0) - && have_parameter == other.have_parameter + && have_parameter == other.have_parameter && parameter_type == other.parameter_type); } @@ -265,7 +265,7 @@ match_node::match_node() {} match_node * -match_node::bind(match_key const & k) +match_node::bind(match_key const & k) { if (k.name == "*") throw semantic_error("invalid use of wildcard probe point component"); @@ -278,7 +278,7 @@ match_node::bind(match_key const & k) return n; } -void +void match_node::bind(derived_probe_builder * e) { if (end) @@ -286,7 +286,7 @@ match_node::bind(derived_probe_builder * e) end = e; } -match_node * +match_node * match_node::bind(string const & k) { return bind(match_key(k)); @@ -298,7 +298,7 @@ match_node::bind_str(string const & k) return bind(match_key(k).with_string()); } -match_node * +match_node * match_node::bind_num(string const & k) { return bind(match_key(k).with_number()); @@ -311,7 +311,7 @@ match_node::find_and_build (systemtap_session& s, vector<derived_probe *>& results) { assert (pos <= loc->components.size()); - if (pos == loc->components.size()) // matched all probe point components so far + if (pos == loc->components.size()) // matched all probe point components so far { derived_probe_builder *b = end; // may be 0 if only nested names are bound @@ -321,7 +321,7 @@ match_node::find_and_build (systemtap_session& s, for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++) alternatives += string(" ") + i->first.str(); - throw semantic_error (string("probe point truncated at position ") + + throw semantic_error (string("probe point truncated at position ") + lex_cast<string> (pos) + " (follow:" + alternatives + ")", loc->tok); } @@ -392,14 +392,14 @@ match_node::find_and_build (systemtap_session& s, string alternatives; for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++) alternatives += string(" ") + i->first.str(); - + throw semantic_error(string("probe point mismatch at position ") + lex_cast<string> (pos) + " (alternatives:" + alternatives + ")", loc->tok); } } - else + else { match_key match (* loc->components[pos]); sub_map_iterator_t i = sub.find (match); @@ -408,8 +408,8 @@ match_node::find_and_build (systemtap_session& s, string alternatives; for (sub_map_iterator_t i = sub.begin(); i != sub.end(); i++) alternatives += string(" ") + i->first.str(); - - throw semantic_error (string("probe point mismatch at position ") + + + throw semantic_error (string("probe point mismatch at position ") + lex_cast<string> (pos) + " (alternatives:" + alternatives + ")", loc->tok); @@ -456,17 +456,17 @@ private: struct -alias_expansion_builder +alias_expansion_builder : public derived_probe_builder { probe_alias * alias; - alias_expansion_builder(probe_alias * a) + alias_expansion_builder(probe_alias * a) : alias(a) {} virtual void build(systemtap_session & sess, - probe * use, + probe * use, probe_point * location, std::map<std::string, literal *> const &, vector<derived_probe *> & finished_results) @@ -483,7 +483,7 @@ alias_expansion_builder // We're going to build a new probe and wrap it up in an // alias_expansion_probe so that the expansion loop recognizes it as // such and re-expands its expansion. - + alias_derived_probe * n = new alias_derived_probe (use, location /* soon overwritten */, this->alias); n->body = new block(); @@ -497,7 +497,7 @@ alias_expansion_builder n->tok = location->tok; // and statements representing the concatenation of the alias' - // body with the use's. + // body with the use's. // // NB: locals are *not* copied forward, from either alias or // use. The expansion should have its locals re-inferred since @@ -508,7 +508,7 @@ alias_expansion_builder n->body = new block (use->body, alias->body); else n->body = new block (alias->body, use->body); - + derive_probes (sess, n, finished_results, location->optional); } @@ -554,7 +554,7 @@ systemtap_session::register_library_aliases() for (unsigned a = 0; a < file->aliases.size(); ++a) { probe_alias * alias = file->aliases[a]; - try + try { for (unsigned n = 0; n < alias->alias_names.size(); ++n) { @@ -565,8 +565,8 @@ systemtap_session::register_library_aliases() probe_point::component * comp = name->components[c]; // XXX: alias parameters if (comp->arg) - throw semantic_error("alias component " - + comp->functor + throw semantic_error("alias component " + + comp->functor + " contains illegal parameter"); n = n->bind(comp->functor); } @@ -591,7 +591,7 @@ systemtap_session::register_library_aliases() static unsigned max_recursion = 100; -struct +struct recursion_guard { unsigned & i; @@ -601,7 +601,7 @@ recursion_guard throw semantic_error("recursion limit reached"); ++i; } - ~recursion_guard() + ~recursion_guard() { --i; } @@ -682,7 +682,7 @@ struct symbol_fetcher { symbol *&sym; - symbol_fetcher (symbol *&sym): sym(sym) + symbol_fetcher (symbol *&sym): sym(sym) {} void visit_symbol (symbol* e) @@ -732,7 +732,7 @@ struct mutated_var_collector { set<vardecl *> * mutated_vars; - mutated_var_collector (set<vardecl *> * mm) + mutated_var_collector (set<vardecl *> * mm) : mutated_vars (mm) {} @@ -768,8 +768,8 @@ struct no_var_mutation_during_iteration_check systemtap_session & session; map<functiondecl *,set<vardecl *> *> & function_mutates_vars; vector<vardecl *> vars_being_iterated; - - no_var_mutation_during_iteration_check + + no_var_mutation_during_iteration_check (systemtap_session & sess, map<functiondecl *,set<vardecl *> *> & fmv) : session(sess), function_mutates_vars (fmv) @@ -799,7 +799,7 @@ struct no_var_mutation_during_iteration_check void visit_functioncall (functioncall* e) { - map<functiondecl *,set<vardecl *> *>::const_iterator i + map<functiondecl *,set<vardecl *> *>::const_iterator i = function_mutates_vars.find (e->referent); if (i != function_mutates_vars.end()) @@ -825,7 +825,7 @@ struct no_var_mutation_during_iteration_check if (vd) vars_being_iterated.push_back (vd); - + traversing_visitor::visit_foreach_loop (s); if (vd) @@ -840,7 +840,7 @@ struct stat_decl_collector : public traversing_visitor { systemtap_session & session; - + stat_decl_collector(systemtap_session & sess) : session(sess) {} @@ -897,12 +897,12 @@ struct stat_decl_collector else { // FIXME: Support multiple co-declared histogram types - semantic_error se("multiple histogram types declared on '" + sym->name + "'", + semantic_error se("multiple histogram types declared on '" + sym->name + "'", e->tok); session.print_error (se); } } - } + } } }; @@ -912,10 +912,10 @@ semantic_pass_stats (systemtap_session & sess) { stat_decl_collector sdc(sess); - for (unsigned i = 0; i < sess.functions.size(); ++i) + for (unsigned i = 0; i < sess.functions.size(); ++i) sess.functions[i]->body->visit (&sdc); - for (unsigned i = 0; i < sess.probes.size(); ++i) + for (unsigned i = 0; i < sess.probes.size(); ++i) sess.probes[i]->body->visit (&sdc); for (unsigned i = 0; i < sess.globals.size(); ++i) @@ -923,7 +923,7 @@ semantic_pass_stats (systemtap_session & sess) vardecl *v = sess.globals[i]; if (v->type == pe_stats) { - + if (sess.stat_decls.find(v->name) == sess.stat_decls.end()) { semantic_error se("unable to infer statistic parameters for global '" + v->name + "'"); @@ -931,7 +931,7 @@ semantic_pass_stats (systemtap_session & sess) } } } - + return sess.num_errors(); } @@ -942,10 +942,10 @@ semantic_pass_stats (systemtap_session & sess) static int semantic_pass_vars (systemtap_session & sess) { - + map<functiondecl *, set<vardecl *> *> fmv; no_var_mutation_during_iteration_check chk(sess, fmv); - + for (unsigned i = 0; i < sess.functions.size(); ++i) { functiondecl * fn = sess.functions[i]; @@ -968,7 +968,7 @@ semantic_pass_vars (systemtap_session & sess) { if (sess.probes[i]->body) sess.probes[i]->body->visit (&chk); - } + } return sess.num_errors(); } @@ -986,7 +986,7 @@ semantic_pass_vars (systemtap_session & sess) // // probe begin(MAX) { if (! (g1 || g2)) %{ disable_probe_foo %} } // probe foo { if (! (g1 || g2)) next; ... } -// probe bar { ... g1 ++ ...; +// probe bar { ... g1 ++ ...; // if (g1 || g2) %{ enable_probe_foo %} else %{ disable_probe_foo %} // } // @@ -1029,7 +1029,7 @@ semantic_pass_conditions (systemtap_session & sess) ifs->condition = notex; p->body = new block (ifs, p->body); } - } + } return sess.num_errors(); } @@ -1084,7 +1084,7 @@ semantic_pass_symbols (systemtap_session& s) if (pending_interrupts) break; functiondecl* fd = dome->functions[i]; - try + try { sym.current_function = fd; sym.current_probe = 0; @@ -1097,7 +1097,7 @@ semantic_pass_symbols (systemtap_session& s) } // Pass 3: derive probes and resolve any further symbols in the - // derived results. + // derived results. for (unsigned i=0; i<dome->probes.size(); i++) { @@ -1116,7 +1116,7 @@ semantic_pass_symbols (systemtap_session& s) s.probes.push_back (dp); dp->join_group (s); - try + try { sym.current_function = 0; sym.current_probe = dp; @@ -1139,7 +1139,7 @@ semantic_pass_symbols (systemtap_session& s) // Inform all derived_probe builders that we're done with // all resolution, so it's time to release caches. s.pattern_root->build_no_more (s); - + return s.num_errors(); // all those print_error calls } @@ -1170,6 +1170,7 @@ void add_global_var_display (systemtap_session& s) probe_point::component* c = new probe_point::component("end"); token* print_tok = new token; vector<derived_probe*> dps; + block *b = new block; pl->components.push_back (c); token* p_tok = new token; @@ -1185,7 +1186,7 @@ void add_global_var_display (systemtap_session& s) g_sym->name = l->name; g_sym->tok = l->tok; g_sym->type = l->type; - g_sym->referent = l; + g_sym->referent = l; pf->print_to_stream = true; pf->print_with_format = true; @@ -1206,17 +1207,7 @@ void add_global_var_display (systemtap_session& s) expr_statement* feb = new expr_statement; feb->value = pf; feb->tok = print_tok; - block *b = new block; b->statements.push_back(feb); - p->body = b; - - derive_probes (s, p, dps); - - // Repopulate the type info. Should semantic_pass_types do this? - ((class symbol*) - ((class print_format*) - ((class expr_statement*) - ((class block*)dps[0]->body)->statements[0])->value)->args[0])->type = g_sym->type; } else // Array { @@ -1253,11 +1244,17 @@ void add_global_var_display (systemtap_session& s) } // Create a printf for the foreach loop + pf->raw_components += "["; for (int i=0; i < idx_count; i++) - if (l->index_types[i] == pe_string) - pf->raw_components += "[\"%#s\"]"; - else - pf->raw_components += "[%#d]"; + { + if (i > 0) + pf->raw_components += ","; + if (l->index_types[i] == pe_string) + pf->raw_components += "\"%#s\""; + else + pf->raw_components += "%#d"; + } + pf->raw_components += "]"; if (l->type == pe_string) pf->raw_components += "=\"%#s\"\\n"; else @@ -1273,48 +1270,32 @@ void add_global_var_display (systemtap_session& s) pf->args.push_back(idx_sym[i]); } pf->args.push_back(ai); - + pf->components = print_format::string_to_components(pf->raw_components); expr_statement* feb = new expr_statement; feb->value = pf; - block *b = new block; fe->base = g_sym; fe->block = (statement*)feb; b->statements.push_back(fe); - p->body = b; - - derive_probes (s, p, dps); - - // Repopulate the type info. Should semantic_pass_types do this? - print_format* dpf = ((print_format*) - ((expr_statement*) - ((foreach_loop*) - ((block*)dps[0]->body)->statements[0])->block)->value); - for (int i=0; i < idx_count; i++) - { - // printf argument types - dpf->args[i]->type = l->index_types[i]; - // arrayindex indices types - ((struct arrayindex*)dpf->args[idx_count])->indexes[i]->type = l->index_types[i]; - dps[0]->locals.push_back(idx_v[i]); - } - // arrayindex type - dpf->args[idx_count]->type = l->type; } - symresolution_info sym (s); - sym.current_function = 0; - sym.current_probe = dps[0]; - dps[0]->body->visit (& sym); - // Add created probe + p->body = b; + derive_probes (s, p, dps); for (unsigned i = 0; i < dps.size(); i++) { derived_probe* dp = dps[i]; s.probes.push_back (dp); dp->join_group (s); } + // Repopulate symbol and type info + symresolution_info sym (s); + sym.current_function = 0; + sym.current_probe = dps[0]; + dps[0]->body->visit (& sym); + semantic_pass_types(s); + // Mark that variable is read vut.read.insert (l); } } @@ -1324,11 +1305,11 @@ semantic_pass (systemtap_session& s) { int rc = 0; - try + try { s.register_library_aliases(); register_standard_tapsets(s); - + if (rc == 0) rc = semantic_pass_symbols (s); if (rc == 0) rc = semantic_pass_conditions (s); if (rc == 0 && ! s.unoptimized) rc = semantic_pass_optimize1 (s); @@ -1337,7 +1318,7 @@ semantic_pass (systemtap_session& s) if (rc == 0 && ! s.unoptimized) rc = semantic_pass_optimize2 (s); if (rc == 0) rc = semantic_pass_vars (s); if (rc == 0) rc = semantic_pass_stats (s); - + if (s.probes.size() == 0 && !s.listing_mode) throw semantic_error ("no probes found"); } @@ -1346,7 +1327,7 @@ semantic_pass (systemtap_session& s) s.print_error (e); rc ++; } - + return rc; } @@ -1358,18 +1339,18 @@ systemtap_session::systemtap_session (): // NB: pointer members must be manually initialized! pattern_root(new match_node), user_file (0), - be_derived_probes(0), - dwarf_derived_probes(0), - uprobe_derived_probes(0), - utrace_derived_probes(0), - itrace_derived_probes(0), - task_finder_derived_probes(0), - timer_derived_probes(0), - profile_derived_probes(0), - mark_derived_probes(0), - hrtimer_derived_probes(0), - perfmon_derived_probes(0), - procfs_derived_probes(0), + be_derived_probes(0), + dwarf_derived_probes(0), + uprobe_derived_probes(0), + utrace_derived_probes(0), + itrace_derived_probes(0), + task_finder_derived_probes(0), + timer_derived_probes(0), + profile_derived_probes(0), + mark_derived_probes(0), + hrtimer_derived_probes(0), + perfmon_derived_probes(0), + procfs_derived_probes(0), op (0), up (0), sym_kprobes_text_start (0), sym_kprobes_text_end (0), @@ -1396,7 +1377,7 @@ systemtap_session::print_token (ostream& o, const token* tok) size_t idx = ts.find (tok->location.file); if (idx != string::npos) ts.replace (idx, tok->location.file.size(), ""); - + o << ts; } else @@ -1465,7 +1446,7 @@ symresolution_info::visit_block (block* e) { for (unsigned i=0; i<e->statements.size(); i++) { - try + try { e->statements[i]->visit (this); } @@ -1483,14 +1464,14 @@ symresolution_info::visit_foreach_loop (foreach_loop* e) for (unsigned i=0; i<e->indexes.size(); i++) e->indexes[i]->visit (this); - symbol *array = NULL; + symbol *array = NULL; hist_op *hist = NULL; classify_indexable (e->base, array, hist); if (array) { if (!array->referent) - { + { vardecl* d = find_var (array->name, e->indexes.size ()); if (d) array->referent = d; @@ -1503,7 +1484,7 @@ symresolution_info::visit_foreach_loop (foreach_loop* e) } } } - else + else { assert (hist); hist->visit (this); @@ -1516,7 +1497,7 @@ symresolution_info::visit_foreach_loop (foreach_loop* e) } -struct +struct delete_statement_symresolution_info: public traversing_visitor { @@ -1539,7 +1520,7 @@ delete_statement_symresolution_info: { if (e->referent) return; - + vardecl* d = parent->find_var (e->name, -1); if (d) e->referent = d; @@ -1548,7 +1529,7 @@ delete_statement_symresolution_info: } }; -void +void symresolution_info::visit_delete_statement (delete_statement* s) { delete_statement_symresolution_info di (this); @@ -1589,7 +1570,7 @@ symresolution_info::visit_arrayindex (arrayindex* e) for (unsigned i=0; i<e->indexes.size(); i++) e->indexes[i]->visit (this); - symbol *array = NULL; + symbol *array = NULL; hist_op *hist = NULL; classify_indexable(e->base, array, hist); @@ -1616,7 +1597,7 @@ symresolution_info::visit_arrayindex (arrayindex* e) // must not happen throw semantic_error ("no current probe/function", e->tok); array->referent = v; - } + } } else { @@ -1656,19 +1637,19 @@ symresolution_info::visit_functioncall (functioncall* e) } -vardecl* +vardecl* symresolution_info::find_var (const string& name, int arity) { if (current_function || current_probe) { // search locals - vector<vardecl*>& locals = (current_function ? + vector<vardecl*>& locals = (current_function ? current_function->locals : current_probe->locals); - - + + for (unsigned i=0; i<locals.size(); i++) - if (locals[i]->name == name + if (locals[i]->name == name && locals[i]->compatible_arity(arity)) { locals[i]->set_arity (arity); @@ -1689,12 +1670,12 @@ symresolution_info::find_var (const string& name, int arity) // search processed globals for (unsigned i=0; i<session.globals.size(); i++) if (session.globals[i]->name == name - && session.globals[i]->compatible_arity(arity)) + && session.globals[i]->compatible_arity(arity)) { session.globals[i]->set_arity (arity); return session.globals[i]; } - + // search library globals for (unsigned i=0; i<session.library_files.size(); i++) { @@ -1705,12 +1686,12 @@ symresolution_info::find_var (const string& name, int arity) if (g->name == name && g->compatible_arity (arity)) { g->set_arity (arity); - - // put library into the queue if not already there - if (find (session.files.begin(), session.files.end(), f) + + // put library into the queue if not already there + if (find (session.files.begin(), session.files.end(), f) == session.files.end()) session.files.push_back (f); - + return g; } } @@ -1720,7 +1701,7 @@ symresolution_info::find_var (const string& name, int arity) } -functiondecl* +functiondecl* symresolution_info::find_function (const string& name, unsigned arity) { for (unsigned j = 0; j < session.functions.size(); j++) @@ -1744,7 +1725,7 @@ symresolution_info::find_function (const string& name, unsigned arity) cerr << " function " << name << " " << "is defined from " << f->name << endl; - if (find (session.files.begin(), session.files.end(), f) + if (find (session.files.begin(), session.files.end(), f) == session.files.end()) session.files.push_back (f); // else .. print different message? @@ -1819,10 +1800,10 @@ void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p, unsigned iterati // // for (unsigned i=0; i<s.functions.size(); i++) // s.functions[i]->body->visit (& vut); - + // Now in vut.read/written, we have a mixture of all locals, globals - - for (unsigned i=0; i<s.probes.size(); i++) + + for (unsigned i=0; i<s.probes.size(); i++) for (unsigned j=0; j<s.probes[i]->locals.size(); /* see below */) { vardecl* l = s.probes[i]->locals[j]; @@ -1864,7 +1845,7 @@ void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p, unsigned iterati j++; } } - + for (unsigned i=0; i<s.functions.size(); i++) for (unsigned j=0; j<s.functions[i]->locals.size(); /* see below */) { @@ -1941,7 +1922,7 @@ void semantic_pass_opt2 (systemtap_session& s, bool& relaxed_p, unsigned iterati for (it = s.globals.begin(); it != s.globals.end(); it++) if (l->name != (*it)->name) o << " " << (*it)->name; - + s.print_warning ("read-only global variable '" + l->name + "' " + (o.str() == "" ? "" : ("(alternatives:" + o.str() + ")")), l->tok); } @@ -1962,7 +1943,7 @@ struct dead_assignment_remover: public traversing_visitor expression** current_expr; dead_assignment_remover(systemtap_session& s, bool& r, - const varuse_collecting_visitor& v): + const varuse_collecting_visitor& v): session(s), relaxed_p(r), vut(v), current_expr(0) {} void visit_expr_statement (expr_statement* s); @@ -1998,7 +1979,7 @@ dead_assignment_remover::visit_assignment (assignment* e) vardecl* leftvar = left->referent; // NB: may be 0 for unresolved $target if (current_expr && // see XXX above: this case represents a missed // optimization opportunity - *current_expr == e && // we're not nested any deeper than expected + *current_expr == e && // we're not nested any deeper than expected leftvar) // not unresolved $target; intended sideeffect cannot be elided { expression** last_expr = current_expr; @@ -2011,7 +1992,7 @@ dead_assignment_remover::visit_assignment (assignment* e) { // NB: Not so fast! The left side could be an array whose // index expressions may have side-effects. This would be - // OK if we could replace the array assignment with a + // OK if we could replace the array assignment with a // statement-expression containing all the index expressions // and the rvalue... but we can't. // Another possibility is that we have an unread global variable @@ -2038,9 +2019,9 @@ dead_assignment_remover::visit_assignment (assignment* e) else */ if (session.verbose>2) - clog << "Eliding assignment to " << leftvar->name + clog << "Eliding assignment to " << leftvar->name << " at " << *e->tok << endl; - + *current_expr = e->right; // goodbye assignment* relaxed_p = false; } @@ -2149,7 +2130,7 @@ struct dead_stmtexpr_remover: public traversing_visitor statement** current_stmt; // pointer to current stmt* being iterated set<vardecl*> focal_vars; // vars considered subject to side-effects - dead_stmtexpr_remover(systemtap_session& s, bool& r): + dead_stmtexpr_remover(systemtap_session& s, bool& r): session(s), relaxed_p(r), current_stmt(0) {} void visit_block (block *s); @@ -2182,7 +2163,7 @@ dead_stmtexpr_remover::visit_block (block *s) statement** last_stmt = current_stmt; current_stmt = & s->statements[i]; s->statements[i]->visit (this); - if (*current_stmt != 0) + if (*current_stmt != 0) { // flatten nested blocks into this one block *b = dynamic_cast<block *>(*current_stmt); @@ -2343,16 +2324,16 @@ dead_stmtexpr_remover::visit_expr_statement (expr_statement *s) varuse_collecting_visitor vut; s->value->visit (& vut); - + if (vut.side_effect_free_wrt (focal_vars) && - *current_stmt == s) // we're not nested any deeper than expected + *current_stmt == s) // we're not nested any deeper than expected { /* PR 1119: NB: this message is not a good idea here. It can name some arbitrary RHS expression of an assignment. if (s->value->tok->location.file == session.user_file->name && // not tapset ! session.suppress_warnings) clog << "WARNING: eliding read-only " << *s->value->tok << endl; - else + else */ if (session.verbose>2) clog << "Eliding side-effect-free expression " @@ -2372,7 +2353,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) // Finally, let's remove some statement-expressions that have no // side-effect. These should be exactly those whose private varuse // visitors come back with an empty "written" and "embedded" lists. - + dead_stmtexpr_remover duv (s, relaxed_p); // This instance may be reused for multiple probe/function body trims. @@ -2948,7 +2929,7 @@ semantic_pass_types (systemtap_session& s) // next pass: type inference unsigned iterations = 0; typeresolution_info ti (s); - + ti.assert_resolvability = false; // XXX: maybe convert to exception-based error signalling while (1) @@ -2974,7 +2955,7 @@ semantic_pass_types (systemtap_session& s) // // if (fn->type == pe_unknown) // ti.unresolved (fn->tok); - } + } for (unsigned j=0; j<s.probes.size(); j++) { @@ -3002,7 +2983,7 @@ semantic_pass_types (systemtap_session& s) if (gd->type == pe_unknown) ti.unresolved (gd->tok); } - + if (ti.num_newly_resolved == 0) // converged { if (ti.num_still_unresolved == 0) @@ -3016,7 +2997,7 @@ semantic_pass_types (systemtap_session& s) } } } - + return rc + s.num_errors(); } @@ -3075,12 +3056,12 @@ typeresolution_info::visit_comparison (comparison *e) e->left->visit (this); t = (e->left->type != pe_unknown) ? e->left->type : pe_unknown; e->right->visit (this); - + if (e->left->type != pe_unknown && e->right->type != pe_unknown && e->left->type != e->right->type) mismatch (e->tok, e->left->type, e->right->type); - + if (e->type == pe_unknown) { e->type = pe_long; @@ -3184,7 +3165,7 @@ typeresolution_info::visit_assignment (assignment *e) (e->left->type != pe_unknown) ? e->left->type : pe_unknown; e->right->visit (this); - + if ((sub_type != pe_unknown) && (e->type == pe_unknown)) { e->type = sub_type; @@ -3222,7 +3203,7 @@ typeresolution_info::visit_binary_expression (binary_expression* e) e->right->type != pe_unknown && e->left->type != e->right->type) mismatch (e->tok, e->left->type, e->right->type); - + if (e->type == pe_unknown) { e->type = pe_long; @@ -3378,7 +3359,7 @@ typeresolution_info::visit_target_symbol (target_symbol* e) current_probe->body->print (clog); clog << endl; } - else + else clog << "other" << endl; } @@ -3396,7 +3377,7 @@ typeresolution_info::visit_arrayindex (arrayindex* e) symbol *array = NULL; hist_op *hist = NULL; classify_indexable(e->base, array, hist); - + // Every hist_op has type [int]:int, that is to say, every hist_op // is a pseudo-one-dimensional integer array type indexed by // integers (bucket numbers). @@ -3464,7 +3445,7 @@ typeresolution_info::visit_functioncall (functioncall* e) { assert (e->referent != 0); - resolve_2types (e, e->referent, this, t, true); // accept unknown type + resolve_2types (e, e->referent, this, t, true); // accept unknown type if (e->type == pe_stats) invalid (e->tok, e->type); @@ -3480,7 +3461,7 @@ typeresolution_info::visit_functioncall (functioncall* e) t = ft; ee->visit (this); exp_type at = ee->type; - + if (((at == pe_string) || (at == pe_long)) && ft == pe_unknown) { // propagate to formal arg @@ -3504,7 +3485,7 @@ typeresolution_info::visit_block (block* e) { for (unsigned i=0; i<e->statements.size(); i++) { - try + try { t = pe_unknown; e->statements[i]->visit (this); @@ -3548,9 +3529,9 @@ typeresolution_info::visit_for_loop (for_loop* e) t = pe_long; e->cond->visit (this); t = pe_unknown; - if (e->incr) e->incr->visit (this); + if (e->incr) e->incr->visit (this); t = pe_unknown; - e->block->visit (this); + e->block->visit (this); } @@ -3570,7 +3551,7 @@ typeresolution_info::visit_foreach_loop (foreach_loop* e) classify_indexable(e->base, array, hist); if (hist) - { + { if (e->indexes.size() != 1) unresolved (e->tok); t = pe_long; @@ -3581,7 +3562,7 @@ typeresolution_info::visit_foreach_loop (foreach_loop* e) } else { - assert (array); + assert (array); if (e->indexes.size() != array->referent->index_types.size()) unresolved (e->tok); // symbol resolution should prevent this else for (unsigned i=0; i<e->indexes.size(); i++) @@ -3591,7 +3572,7 @@ typeresolution_info::visit_foreach_loop (foreach_loop* e) t = ft; ee->visit (this); exp_type at = ee->type; - + if ((at == pe_string || at == pe_long) && ft == pe_unknown) { // propagate to formal type @@ -3617,7 +3598,7 @@ typeresolution_info::visit_foreach_loop (foreach_loop* e) } t = pe_unknown; - e->block->visit (this); + e->block->visit (this); } @@ -3635,7 +3616,7 @@ typeresolution_info::visit_expr_statement (expr_statement* e) } -struct delete_statement_typeresolution_info: +struct delete_statement_typeresolution_info: public throwing_visitor { typeresolution_info *parent; @@ -3648,11 +3629,11 @@ struct delete_statement_typeresolution_info: { parent->visit_arrayindex (e); } - + void visit_symbol (symbol* e) { exp_type ignored = pe_unknown; - assert (e->referent != 0); + assert (e->referent != 0); resolve_2types (e, e->referent, parent, ignored); } }; @@ -3711,7 +3692,7 @@ typeresolution_info::visit_return_statement (return_statement* e) // This is like symbol, where the referent is // the return value of the function. - // translation pass will print error + // translation pass will print error if (current_function == 0) return; @@ -3722,7 +3703,7 @@ typeresolution_info::visit_return_statement (return_statement* e) if (e_type != pe_unknown && e->value->type != pe_unknown && e_type != e->value->type) mismatch (current_function->tok, e_type, e->value->type); - if (e_type == pe_unknown && + if (e_type == pe_unknown && (e->value->type == pe_long || e->value->type == pe_string)) { // propagate non-statistics from value @@ -3733,7 +3714,7 @@ typeresolution_info::visit_return_statement (return_statement* e) invalid (e->value->tok, e->value->type); } -void +void typeresolution_info::visit_print_format (print_format* e) { size_t unresolved_args = 0; @@ -3758,7 +3739,7 @@ typeresolution_info::visit_print_format (print_format* e) if (e->components[i].type == print_format::conv_unspecified) throw semantic_error ("Unspecified conversion in print operator format string", e->tok); - else if (e->components[i].type == print_format::conv_literal + else if (e->components[i].type == print_format::conv_literal || e->components[i].type == print_format::conv_size) continue; components.push_back(e->components[i]); @@ -3841,7 +3822,7 @@ typeresolution_info::visit_print_format (print_format* e) } } } - + if (unresolved_args == 0) { if (e->type == pe_unknown) @@ -3849,7 +3830,7 @@ typeresolution_info::visit_print_format (print_format* e) if (e->print_to_stream) e->type = pe_long; else - e->type = pe_string; + e->type = pe_string; resolved (e->tok, e->type); } } @@ -3861,7 +3842,7 @@ typeresolution_info::visit_print_format (print_format* e) } -void +void typeresolution_info::visit_stat_op (stat_op* e) { t = pe_stats; @@ -3875,7 +3856,7 @@ typeresolution_info::visit_stat_op (stat_op* e) mismatch (e->tok, e->type, pe_long); } -void +void typeresolution_info::visit_hist_op (hist_op* e) { t = pe_stats; diff --git a/elaborate.h b/elaborate.h index afc0c569..df888360 100644 --- a/elaborate.h +++ b/elaborate.h @@ -23,7 +23,7 @@ struct derived_probe; struct match_node; -struct symresolution_info: public traversing_visitor +struct symresolution_info: public traversing_visitor { protected: systemtap_session& session; @@ -185,7 +185,7 @@ typedef std::map<std::string, literal*> literal_map_t; struct derived_probe_builder { virtual void build(systemtap_session & sess, - probe* base, + probe* base, probe_point* location, literal_map_t const & parameters, std::vector<derived_probe*> & finished_results) = 0; @@ -1,16 +1,16 @@ // Copyright (C) Andrew Tridgell 2002 (original file) // Copyright (C) 2006-2008 Red Hat Inc. (systemtap changes) -// +// // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. @@ -79,7 +79,7 @@ usage (systemtap_session& s, int exitcode) << " -u unoptimized translation" << (s.unoptimized ? " [set]" : "") << endl << " -w suppress warnings" << (s.suppress_warnings ? " [set]" : "") << endl << " -g guru mode" << (s.guru_mode ? " [set]" : "") << endl - << " -P prologue-searching for function probes" + << " -P prologue-searching for function probes" << (s.prologue_searching ? " [set]" : "") << endl << " -b bulk (percpu file) mode" << (s.bulk_mode ? " [set]" : "") << endl << " -s NUM buffer size in megabytes, instead of " @@ -165,7 +165,7 @@ printscript(systemtap_session& s, ostream& o) { assert (a->alias_names.size() >= 1); a->alias_names[0]->print(tmps); // XXX: [0] is arbitrary; perhaps print all - } + } else { assert (second->locations.size() >= 1); @@ -179,6 +179,18 @@ printscript(systemtap_session& s, ostream& o) if (seen.find (pp) == seen.end()) { o << pp << endl; + if (s.verbose) { + for (unsigned j=0; j<p->locals.size(); j++) + { + vardecl* v = p->locals[j]; + if (j>0) + o << ", "; + else + o << " "; + v->printsig (o); + } + o << endl; + } seen.insert (pp); } } @@ -193,7 +205,7 @@ printscript(systemtap_session& s, ostream& o) ec->print (o); o << endl; } - + if (s.globals.size() > 0) o << "# globals" << endl; for (unsigned i=0; i<s.globals.size(); i++) @@ -207,7 +219,7 @@ printscript(systemtap_session& s, ostream& o) } o << endl; } - + if (s.functions.size() > 0) o << "# functions" << endl; for (unsigned i=0; i<s.functions.size(); i++) @@ -230,7 +242,7 @@ printscript(systemtap_session& s, ostream& o) o << endl; } } - + if (s.probes.size() > 0) o << "# probes" << endl; for (unsigned i=0; i<s.probes.size(); i++) @@ -349,7 +361,7 @@ main (int argc, char * const argv []) s.ignore_dwarf = false; const char* s_p = getenv ("SYSTEMTAP_TAPSET"); - if (s_p != NULL) + if (s_p != NULL) { s.include_path.push_back (s_p); } @@ -581,6 +593,7 @@ main (int argc, char * const argv []) case 'l': s.suppress_warnings = true; s.listing_mode = true; + s.unoptimized = true; s.last_pass = 2; if (have_script) { @@ -733,7 +746,7 @@ main (int argc, char * const argv []) const char* tmpdir_env = getenv("TMPDIR"); if (! tmpdir_env) tmpdir_env = "/tmp"; - + string stapdir = "/stapXXXXXX"; string tmpdirt = tmpdir_env + stapdir; mode_t mask = umask(0); @@ -756,7 +769,7 @@ main (int argc, char * const argv []) // directory. s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c"; - // Set up our handler to catch routine signals, to allow clean + // Set up our handler to catch routine signals, to allow clean // and reasonably timely exit. setup_signals(&handle_interrupt); @@ -1,17 +1,17 @@ -/* +/* a implementation of MD4 designed for use in the SMB authentication protocol Copyright (C) Andrew Tridgell 1997-1998. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. @@ -21,7 +21,7 @@ #include <string.h> #include "mdfour.h" -/* NOTE: This code makes no attempt to be fast! +/* NOTE: This code makes no attempt to be fast! It assumes that a int is at least 32 bits long */ @@ -46,41 +46,41 @@ mdfour64(uint32_t *M) uint32_t AA, BB, CC, DD; uint32_t A,B,C,D; - A = m->A; B = m->B; C = m->C; D = m->D; + A = m->A; B = m->B; C = m->C; D = m->D; AA = A; BB = B; CC = C; DD = D; - ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7); + ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7); ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19); - ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7); + ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7); ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19); - ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7); + ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7); ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19); - ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7); - ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19); + ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7); + ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19); - ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5); + ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5); ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13); - ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5); + ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5); ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13); - ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5); + ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5); ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13); - ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5); + ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5); ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13); - ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9); + ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9); ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15); - ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9); + ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9); ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15); - ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9); + ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9); ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15); - ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9); + ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9); ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15); - A += AA; B += BB; + A += AA; B += BB; C += CC; D += DD; - - A &= MASK32; B &= MASK32; + + A &= MASK32; B &= MASK32; C &= MASK32; D &= MASK32; m->A = A; m->B = B; m->C = C; m->D = D; @@ -140,7 +140,7 @@ mdfour_tail(const unsigned char *in, int n) } else { - copy4(buf+120, b); + copy4(buf+120, b); copy64(M, buf); mdfour64(M); copy64(M, buf+64); @@ -1,19 +1,19 @@ -/* +/* Unix SMB/Netbios implementation. Version 1.9. a implementation of MD4 designed for use in the SMB authentication protocol Copyright (C) Andrew Tridgell 1997-1998. - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. @@ -26,7 +26,7 @@ struct mdfour uint32_t A, B, C, D; uint32_t totalN; unsigned char tail[64]; - unsigned tail_len; + unsigned tail_len; }; void mdfour_begin(struct mdfour *md); @@ -88,7 +88,7 @@ tt2str(token_type tt) ostream& operator << (ostream& o, const source_loc& loc) { - o << loc.file << ":" + o << loc.file << ":" << loc.line << ":" << loc.column; @@ -111,14 +111,14 @@ operator << (ostream& o, const token& t) o << "'"; } - o << " at " + o << " at " << t.location; return o; } -void +void parser::print_error (const parse_error &pe) { cerr << "parse error: " << pe.what () << endl; @@ -143,7 +143,7 @@ parser::print_error (const parse_error &pe) } -const token* +const token* parser::last () { return last_t; @@ -194,11 +194,11 @@ bool eval_pp_conditional (systemtap_session& s, { string target_kernel_vr = s.kernel_release; string target_kernel_v = s.kernel_base_release; - + if (! (r->type == tok_string)) throw parse_error ("expected string literal", r); - string target = (l->content == "kernel_vr" ? + string target = (l->content == "kernel_vr" ? target_kernel_vr.c_str() : target_kernel_v.c_str()); string query = r->content; @@ -247,7 +247,7 @@ bool eval_pp_conditional (systemtap_session& s, if (! (r->type == tok_string)) throw parse_error ("expected string literal", r); string query_architecture = r->content; - + int nomatch = fnmatch (query_architecture.c_str(), target_architecture.c_str(), FNM_NOESCAPE); // still spooky @@ -259,9 +259,9 @@ bool eval_pp_conditional (systemtap_session& s, result = nomatch; else throw parse_error ("expected '==' or '!='", op); - + return result; - } + } else if (l->type == tok_string && r->type == tok_string) { string lhs = l->content; @@ -307,7 +307,7 @@ parser::scan_pp (bool wildcard) const token* t = input.scan (wildcard); // NB: not recursive! if (t == 0) // EOF return t; - + if (! (t->type == tok_operator && t->content == "%(")) // ordinary token return t; @@ -349,7 +349,7 @@ parser::scan_pp (bool wildcard) } catch (const parse_error &e) { - if (result) throw e; // propagate errors if THEN branch taken + if (result) throw e; // propagate errors if THEN branch taken continue; } @@ -370,7 +370,7 @@ parser::scan_pp (bool wildcard) continue; } - + if (m && m->type == tok_operator && m->content == "%:") // ELSE { delete m; // "%:" @@ -380,10 +380,10 @@ parser::scan_pp (bool wildcard) try { m = result ? input.scan (wildcard) : scan_pp (wildcard); - } + } catch (const parse_error& e) { - if (!result) throw e; // propagate errors if ELSE branch taken + if (!result) throw e; // propagate errors if ELSE branch taken continue; } @@ -397,7 +397,7 @@ parser::scan_pp (bool wildcard) if (!m) throw parse_error ("incomplete conditional - missing %)", t); if (!result) - my_enqueued_pp.push_back (m); + my_enqueued_pp.push_back (m); if (result) delete m; // do nothing, just dispose of unkept ELSE token @@ -466,7 +466,7 @@ tok_is(token const * t, token_type tt, string const & expected) } -const token* +const token* parser::expect_known (token_type tt, string const & expected) { const token *t = next(); @@ -476,7 +476,7 @@ parser::expect_known (token_type tt, string const & expected) } -const token* +const token* parser::expect_unknown (token_type tt, string & target) { const token *t = next(); @@ -487,7 +487,7 @@ parser::expect_unknown (token_type tt, string & target) } -const token* +const token* parser::expect_unknown2 (token_type tt1, token_type tt2, string & target) { const token *t = next(); @@ -498,20 +498,20 @@ parser::expect_unknown2 (token_type tt1, token_type tt2, string & target) } -const token* +const token* parser::expect_op (std::string const & expected) { return expect_known (tok_operator, expected); } -const token* +const token* parser::expect_kw (std::string const & expected) { return expect_known (tok_identifier, expected); } -const token* +const token* parser::expect_number (int64_t & value) { bool neg = false; @@ -537,8 +537,8 @@ parser::expect_number (int64_t & value) || (neg && (unsigned long long) value > 9223372036854775808ULL) || (unsigned long long) value > 18446744073709551615ULL || value < -9223372036854775807LL-1) - throw parse_error ("number invalid or out of range"); - + throw parse_error ("number invalid or out of range"); + if (neg) value = -value; @@ -546,28 +546,28 @@ parser::expect_number (int64_t & value) } -const token* +const token* parser::expect_ident (std::string & target) { return expect_unknown (tok_identifier, target); } -const token* +const token* parser::expect_ident_or_keyword (std::string & target) { return expect_unknown2 (tok_identifier, tok_keyword, target); } -bool +bool parser::peek_op (std::string const & op) { return tok_is (peek(), tok_operator, op); } -bool +bool parser::peek_kw (std::string const & kw) { return tok_is (peek(), tok_identifier, kw); @@ -576,7 +576,7 @@ parser::peek_kw (std::string const & kw) lexer::lexer (istream& i, const string& in, systemtap_session& s): - input (i), input_name (in), cursor_suspend_count(0), + input (i), input_name (in), cursor_suspend_count(0), cursor_line (1), cursor_column (1), session(s) { } @@ -593,7 +593,7 @@ lexer::input_peek (unsigned n) } -int +int lexer::input_get () { int c = input_peek (0); @@ -691,7 +691,7 @@ lexer::scan (bool wildcard) idx = (idx * 10) + (c2 - '0'); c2 = input_peek (); } while (c2 > 0 && - isdigit (c2) && + isdigit (c2) && idx <= session.args.size()); // prevent overflow if (idx == 0 || idx-1 >= session.args.size()) @@ -736,7 +736,7 @@ lexer::scan (bool wildcard) || n->content == "string" || n->content == "long") n->type = tok_keyword; - + return n; } @@ -781,7 +781,7 @@ lexer::scan (bool wildcard) if (c == '\"') // closing double-quotes break; else if (c == '\\') // see also input_put - { + { c = input_get (); switch (c) { @@ -795,7 +795,7 @@ lexer::scan (bool wildcard) case '0' ... '7': // NB: need only match the first digit case '\\': // Pass these escapes through to the string value - // being parsed; it will be emitted into a C literal. + // being parsed; it will be emitted into a C literal. n->content.push_back('\\'); @@ -918,7 +918,7 @@ lexer::scan (bool wildcard) { n->content = s2; input_get (); // swallow other character - } + } else { n->content = s1; @@ -985,7 +985,7 @@ parser::parse () { print_error (pe); if (pe.skip_some) // for recovery - try + try { // Quietly swallow all tokens until the next '}'. while (1) @@ -1018,7 +1018,7 @@ parser::parse () delete f; return 0; } - + return f; } @@ -1041,16 +1041,16 @@ parser::parse_probe (std::vector<probe *> & probe_ret, while (1) { probe_point * pp = parse_probe_point (); - + const token* t = peek (); - if (equals_ok && t + if (equals_ok && t && t->type == tok_operator && t->content == "=") { aliases.push_back(pp); next (); continue; } - else if (equals_ok && t + else if (equals_ok && t && t->type == tok_operator && t->content == "+=") { aliases.push_back(pp); @@ -1172,7 +1172,7 @@ parser::parse_statement () n->tok = next (); return n; } - else if (t && t->type == tok_operator && t->content == "{") + else if (t && t->type == tok_operator && t->content == "{") return parse_stmt_block (); else if (t && t->type == tok_keyword && t->content == "if") return parse_if_statement (); @@ -1220,7 +1220,7 @@ parser::parse_global (vector <vardecl*>& globals, vector<probe*>&) for (unsigned i=0; i<globals.size(); i++) if (globals[i]->name == t->content) throw parse_error ("duplicate global name"); - + vardecl* d = new vardecl; d->name = t->content; d->tok = t; @@ -1326,7 +1326,7 @@ parser::parse_functiondecl (std::vector<functiondecl*>& functions) else if (t->type == tok_keyword && t->content == "long") vd->type = pe_long; else throw parse_error ("expected 'string' or 'long'"); - + t = next (); } if (t->type == tok_operator && t->content == ")") @@ -1420,11 +1420,11 @@ parser::parse_probe_point () // fall through } - if (t && t->type == tok_operator + if (t && t->type == tok_operator && (t->content == "{" || t->content == "," || t->content == "=" || t->content == "+=" )) break; - + throw parse_error ("expected one of '. , ( ? ! { = +='"); } @@ -1463,7 +1463,7 @@ parser::parse_literal () || (neg && (unsigned long long) value > 9223372036854775808ULL) || (unsigned long long) value > 18446744073709551615ULL || value < -9223372036854775807LL-1) - throw parse_error ("number invalid or out of range"); + throw parse_error ("number invalid or out of range"); if (neg) value = -value; @@ -1633,7 +1633,7 @@ parser::parse_for_loop () if (! (t->type == tok_operator && t->content == ";")) throw parse_error ("expected ';'"); } - + // increment + ")" t = peek (); if (t && t->type == tok_operator && t->content == ")") @@ -1679,7 +1679,7 @@ parser::parse_while_loop () t = next (); if (! (t->type == tok_operator && t->content == ")")) throw parse_error ("expected ')'"); - + // block s->block = parse_statement (); @@ -1746,7 +1746,7 @@ parser::parse_foreach_loop () next (); break; } - else + else throw parse_error ("expected ',' or ']'"); } else @@ -1756,7 +1756,7 @@ parser::parse_foreach_loop () t = next (); if (! (t->type == tok_keyword && t->content == "in")) throw parse_error ("expected 'in'"); - + s->base = parse_indexable(); t = peek (); @@ -1800,7 +1800,7 @@ parser::parse_assignment () const token* t = peek (); // right-associative operators - if (t && t->type == tok_operator + if (t && t->type == tok_operator && (t->content == "=" || t->content == "<<<" || t->content == "+=" || @@ -1814,7 +1814,7 @@ parser::parse_assignment () t->content == "^=" || t->content == "|=" || t->content == ".=" || - false)) + false)) { // NB: lvalueness is checked during elaboration / translation assignment* e = new assignment; @@ -1860,7 +1860,7 @@ expression* parser::parse_logical_or () { expression* op1 = parse_logical_and (); - + const token* t = peek (); while (t && t->type == tok_operator && t->content == "||") { @@ -1999,7 +1999,7 @@ parser::parse_array_in () next (); break; } - else + else throw parse_error ("expected ',' or ']'"); } else @@ -2033,7 +2033,7 @@ parser::parse_comparison () expression* op1 = parse_shift (); const token* t = peek (); - while (t && t->type == tok_operator + while (t && t->type == tok_operator && (t->content == ">" || t->content == "<" || t->content == "==" || @@ -2061,7 +2061,7 @@ parser::parse_shift () expression* op1 = parse_concatenation (); const token* t = peek (); - while (t && t->type == tok_operator && + while (t && t->type == tok_operator && (t->content == "<<" || t->content == ">>")) { binary_expression* e = new binary_expression; @@ -2108,7 +2108,7 @@ parser::parse_additive () expression* op1 = parse_multiplicative (); const token* t = peek (); - while (t && t->type == tok_operator + while (t && t->type == tok_operator && (t->content == "+" || t->content == "-")) { binary_expression* e = new binary_expression; @@ -2131,7 +2131,7 @@ parser::parse_multiplicative () expression* op1 = parse_unary (); const token* t = peek (); - while (t && t->type == tok_operator + while (t && t->type == tok_operator && (t->content == "*" || t->content == "/" || t->content == "%")) { binary_expression* e = new binary_expression; @@ -2152,9 +2152,9 @@ expression* parser::parse_unary () { const token* t = peek (); - if (t && t->type == tok_operator - && (t->content == "+" || - t->content == "-" || + if (t && t->type == tok_operator + && (t->content == "+" || + t->content == "-" || t->content == "!" || t->content == "~" || false)) @@ -2181,7 +2181,7 @@ parser::parse_crement () // as in "increment" / "decrement" // cases like "4++". const token* t = peek (); - if (t && t->type == tok_operator + if (t && t->type == tok_operator && (t->content == "++" || t->content == "--")) { pre_crement* e = new pre_crement; @@ -2194,9 +2194,9 @@ parser::parse_crement () // as in "increment" / "decrement" // post-crement or non-crement expression *op1 = parse_value (); - + t = peek (); - if (t && t->type == tok_operator + if (t && t->type == tok_operator && (t->content == "++" || t->content == "--")) { post_crement* e = new post_crement; @@ -2285,7 +2285,7 @@ parser::parse_indexable () // var, indexable[index], func(parms), printf("...", ...), $var, $var->member, @stat_op(stat) expression* -parser::parse_symbol () +parser::parse_symbol () { hist_op *hop = NULL; symbol *sym = NULL; @@ -2294,7 +2294,7 @@ parser::parse_symbol () if (!hop) { - // If we didn't get a hist_op, then we did get an identifier. We can + // If we didn't get a hist_op, then we did get an identifier. We can // now scrutinize this identifier for the various magic forms of identifier // (printf, @stat_op, and $var...) @@ -2321,7 +2321,7 @@ parser::parse_symbol () expect_op(")"); return sop; } - + else if (print_format::parse_print(name, pf_stream, pf_format, pf_delim, pf_newline, pf_char)) { @@ -2342,16 +2342,16 @@ parser::parse_symbol () // construct. This is sort of gross but it avoids // promoting histogram references to typeful // expressions. - + hop = NULL; t = parse_hist_op_or_bare_name(hop, name); assert(hop); - + // It is, sadly, possible that even while parsing a // hist_op, we *mis-guessed* and the user wishes to // print(@hist_op(foo)[bucket]), a scalar. In that case // we must parse the arrayindex and print an expression. - + if (!peek_op ("[")) fmt->hist = hop; else @@ -2410,7 +2410,7 @@ parser::parse_symbol () expect_op(")"); return fmt; } - + else if (name.size() > 0 && name[0] == '$') { // target_symbol time @@ -2421,20 +2421,20 @@ parser::parse_symbol () { string c; if (peek_op ("->")) - { - next(); + { + next(); expect_ident_or_keyword (c); tsym->components.push_back (make_pair (target_symbol::comp_struct_member, c)); } else if (peek_op ("[")) - { + { next(); expect_unknown (tok_number, c); expect_op ("]"); tsym->components.push_back (make_pair (target_symbol::comp_literal_array_index, c)); - } + } else break; } @@ -2479,8 +2479,8 @@ parser::parse_symbol () sym->tok = t; } } - - // By now, either we had a hist_op in the first place, or else + + // By now, either we had a hist_op in the first place, or else // we had a plain word and it was converted to a symbol. assert (!hop != !sym); // logical XOR @@ -2502,9 +2502,9 @@ parser::parse_symbol () { ai->indexes.push_back (parse_expression ()); if (peek_op ("]")) - { - next(); - break; + { + next(); + break; } else if (peek_op (",")) { @@ -2523,7 +2523,7 @@ parser::parse_symbol () if (hop) throw parse_error("base histogram operator where expression expected", t); - - return sym; + + return sym; } @@ -33,7 +33,7 @@ enum parse_context }; -enum token_type +enum token_type { tok_junk, tok_identifier, tok_operator, tok_string, tok_number, tok_embedded, tok_keyword @@ -55,11 +55,11 @@ struct parse_error: public std::runtime_error { const token* tok; bool skip_some; - parse_error (const std::string& msg): + parse_error (const std::string& msg): runtime_error (msg), tok (0), skip_some (true) {} - parse_error (const std::string& msg, const token* t): + parse_error (const std::string& msg, const token* t): runtime_error (msg), tok (t), skip_some (true) {} - parse_error (const std::string& msg, bool skip): + parse_error (const std::string& msg, bool skip): runtime_error (msg), tok (0), skip_some (skip) {} }; @@ -141,7 +141,7 @@ private: const token* last_t; // the last value returned by peek() or next() const token* next_t; // lookahead token - + // expectations const token* expect_known (token_type tt, std::string const & expected); const token* expect_unknown (token_type tt, std::string & target); diff --git a/runtime/ChangeLog b/runtime/ChangeLog index 926e05d9..b7e44a0f 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,11 @@ +2008-08-29 David Smith <dsmith@redhat.com> + + * task_finder.c (__stp_utrace_attach_match_filename): Don't call + the callback when the interesting thread is found, call it when + the tread is quiesced. + (stap_start_task_finder): Ditto. + (__stp_utrace_task_finder_target_quiesce): Call the callback. + 2008-08-26 David Smith <dsmith@redhat.com> * autoconf-d_path-path.c: New file. diff --git a/runtime/task_finder.c b/runtime/task_finder.c index af2345be..f1c2c41b 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -341,23 +341,41 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen) return rc; } +/* + * All user threads get an engine with __STP_TASK_FINDER_EVENTS events + * attached to it so the task_finder layer can monitor new thread + * creation/death. + */ #define __STP_TASK_FINDER_EVENTS (UTRACE_EVENT(CLONE) \ | UTRACE_EVENT(EXEC) \ | UTRACE_EVENT(DEATH)) -#define __STP_ATTACHED_TASK_BASE_EVENTS (UTRACE_EVENT(DEATH)) - -#define __STP_ATTACHED_TASK_VM_BASE_EVENTS (__STP_ATTACHED_TASK_BASE_EVENTS \ - | UTRACE_EVENT(SYSCALL_ENTRY) \ - | UTRACE_EVENT(SYSCALL_EXIT)) - -#define __STP_ATTACHED_TASK_VM_EVENTS (__STP_ATTACHED_TASK_BASE_EVENTS \ - | UTRACE_STOP \ - | UTRACE_EVENT(QUIESCE)) - -#define __STP_ATTACHED_TASK_EVENTS(tgt) \ - ((((tgt)->vm_callback) == NULL) ? __STP_ATTACHED_TASK_BASE_EVENTS \ - : __STP_ATTACHED_TASK_VM_EVENTS) +/* + * __STP_TASK_BASE_EVENTS: base events for stap_task_finder_target's + * without a vm_callback + * + * __STP_TASK_VM_BASE_EVENTS: base events for + * stap_task_finder_target's with a vm_callback + */ +#define __STP_TASK_BASE_EVENTS (UTRACE_EVENT(DEATH)) + +#define __STP_TASK_VM_BASE_EVENTS (__STP_TASK_BASE_EVENTS \ + | UTRACE_EVENT(SYSCALL_ENTRY)\ + | UTRACE_EVENT(SYSCALL_EXIT)) + +/* + * All "interesting" threads get an engine with + * __STP_ATTACHED_TASK_EVENTS events attached to it. After the thread + * quiesces, we reset the events to __STP_ATTACHED_TASK_BASE_EVENTS + * events. + */ +#define __STP_ATTACHED_TASK_EVENTS (__STP_TASK_BASE_EVENTS \ + | UTRACE_STOP \ + | UTRACE_EVENT(QUIESCE)) + +#define __STP_ATTACHED_TASK_BASE_EVENTS(tgt) \ + ((((tgt)->vm_callback) == NULL) ? __STP_TASK_BASE_EVENTS \ + : __STP_TASK_VM_BASE_EVENTS) static int stap_utrace_attach(struct task_struct *tsk, @@ -444,31 +462,40 @@ __stp_utrace_attach_match_filename(struct task_struct *tsk, if (cb_tgt == NULL) continue; - if (cb_tgt->callback != NULL) { - int rc = cb_tgt->callback(cb_tgt, tsk, - register_p, - process_p); - if (rc != 0) { - _stp_error("callback for %d failed: %d", - (int)tsk->pid, rc); - break; - } - } - // Set up events we need for attached tasks. + // When register_p is set, we won't actually + // call the callback here - we'll call it when + // the thread gets quiesced. When register_p + // isn't set, we can go ahead and call the + // callback. if (register_p) { rc = stap_utrace_attach(tsk, &cb_tgt->ops, cb_tgt, - __STP_ATTACHED_TASK_EVENTS(cb_tgt)); + __STP_ATTACHED_TASK_EVENTS); if (rc != 0 && rc != EPERM) break; cb_tgt->engine_attached = 1; } else { + if (cb_tgt->callback != NULL) { + rc = cb_tgt->callback(cb_tgt, tsk, + register_p, + process_p); + if (rc != 0) { + _stp_error("callback for %d failed: %d", + (int)tsk->pid, rc); + break; + } + } + rc = stap_utrace_detach(tsk, &cb_tgt->ops); if (rc != 0) break; - cb_tgt->engine_attached = 0; + + // Note that we don't want to set + // engine_attached to 0 here - only + // when *all* threads using this + // engine have been detached. } } } @@ -685,18 +712,32 @@ __stp_utrace_task_finder_target_quiesce(enum utrace_resume_action action, struct stap_task_finder_target *tgt = engine->data; int rc; - // Turn off quiesce handling (and turn on syscall handling). - rc = utrace_set_events(tsk, engine, __STP_ATTACHED_TASK_VM_BASE_EVENTS); + if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) { + debug_task_finder_detach(); + return UTRACE_DETACH; + } + + if (tgt == NULL) + return UTRACE_DETACH; + + // Turn off quiesce handling + rc = utrace_set_events(tsk, engine, + __STP_ATTACHED_TASK_BASE_EVENTS(tgt)); if (rc != 0) _stp_error("utrace_set_events returned error %d on pid %d", rc, (int)tsk->pid); - if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) { - debug_task_finder_detach(); - return UTRACE_DETACH; + if (tgt->callback != NULL) { + /* Call the callback. Assume that if the thread is a + * thread group leader, it is a process. */ + rc = tgt->callback(tgt, tsk, 1, (tsk->pid == tsk->tgid)); + if (rc != 0) { + _stp_error("callback for %d failed: %d", + (int)tsk->pid, rc); + } } - if (tgt != NULL && tgt->vm_callback != NULL) { + if (tgt->vm_callback != NULL) { struct mm_struct *mm; char *mmpath_buf; char *mmpath; @@ -1148,24 +1189,11 @@ stap_start_task_finder(void) callback_list); if (cb_tgt == NULL) continue; - - // Call the callback. Assume that if - // the thread is a thread group - // leader, it is a process. - if (cb_tgt->callback != NULL) { - rc = cb_tgt->callback(cb_tgt, tsk, 1, - (tsk->pid == tsk->tgid)); - if (rc != 0) { - _stp_error("attach callback for %d failed: %d", - (int)tsk->pid, rc); - goto stf_err; - } - } // Set up events we need for attached tasks. rc = stap_utrace_attach(tsk, &cb_tgt->ops, cb_tgt, - __STP_ATTACHED_TASK_EVENTS(cb_tgt)); + __STP_ATTACHED_TASK_EVENTS); if (rc != 0 && rc != EPERM) goto stf_err; cb_tgt->engine_attached = 1; @@ -52,16 +52,16 @@ struct module_cache; struct statistic_decl { statistic_decl() - : type(none), + : type(none), linear_low(0), linear_high(0), linear_step(0) - {} + {} enum { none, linear, logarithmic } type; int64_t linear_low; int64_t linear_high; int64_t linear_step; bool operator==(statistic_decl const & other) { - return type == other.type + return type == other.type && linear_low == other.linear_low && linear_high == other.linear_high && linear_step == other.linear_step; @@ -351,7 +351,9 @@ Variables may be declared global, so that they are shared amongst all probes and live as long as the entire systemtap session. There is one namespace for all global variables, regardless of which script file they are found within. A global declaration may be written at the -outermost level anywhere, not within a block of code. The following +outermost level anywhere, not within a block of code. Global +variables which are written but never read will be displayed +automatically at session shutdown. The following declaration marks a few variables as global. The translator will infer for each its value type, and if it is used as an array, its key types. Optionally, scalar globals may be initialized with a string diff --git a/staptree.cxx b/staptree.cxx index 347d799f..73d6fe93 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -27,7 +27,7 @@ using namespace std; expression::expression (): type (pe_unknown), tok (0) { -} +} expression::~expression () @@ -38,7 +38,7 @@ expression::~expression () statement::statement (): tok (0) { -} +} statement::~statement () @@ -68,7 +68,7 @@ symboldecl::symboldecl (): tok (0), type (pe_unknown) { -} +} symboldecl::~symboldecl () @@ -110,8 +110,8 @@ probe_point::component::component (): } -probe_point::component::component (std::string const & f, literal * a): - functor(f), arg(a) +probe_point::component::component (std::string const & f, literal * a): + functor(f), arg(a) { } @@ -140,7 +140,7 @@ vardecl::set_arity (int a) } } -bool +bool vardecl::compatible_arity (int a) { if (a == 0 && maxsize > 0) @@ -216,15 +216,15 @@ void literal_number::print (ostream& o) const void binary_expression::print (ostream& o) const { - o << "(" << *left << ") " - << op + o << "(" << *left << ") " + << op << " (" << *right << ")"; } void unary_expression::print (ostream& o) const { - o << op << '(' << *operand << ")"; + o << op << '(' << *operand << ")"; } void array_in::print (ostream& o) const @@ -241,7 +241,7 @@ void array_in::print (ostream& o) const void post_crement::print (ostream& o) const { - o << '(' << *operand << ")" << op; + o << '(' << *operand << ")" << op; } @@ -249,7 +249,7 @@ void ternary_expression::print (ostream& o) const { o << "(" << *cond << ")?(" << *truevalue << "):(" - << *falsevalue << ")"; + << *falsevalue << ")"; } @@ -346,7 +346,7 @@ void functioncall::print (ostream& o) const for (unsigned i=0; i<args.size(); i++) o << (i>0 ? ", " : "") << *args[i]; o << ")"; -} +} bool @@ -398,7 +398,7 @@ print_format::parse_print(const std::string &name, } -string +string print_format::components_to_string(vector<format_component> const & components) { ostringstream oss; @@ -452,7 +452,7 @@ print_format::components_to_string(vector<format_component> const & components) else if (i->prectype != prec_unspecified && i->precision > 0) oss << '.' << i->precision; - switch (i->type) + switch (i->type) { case conv_binary: oss << "b"; @@ -485,11 +485,11 @@ print_format::components_to_string(vector<format_component> const & components) case conv_string: oss << 's'; break; - + case conv_memory: oss << 'm'; break; - + case conv_size: oss << 'n'; break; @@ -501,8 +501,8 @@ print_format::components_to_string(vector<format_component> const & components) } return oss.str (); } - -vector<print_format::format_component> + +vector<print_format::format_component> print_format::string_to_components(string const & str) { format_component curr; @@ -511,7 +511,7 @@ print_format::string_to_components(string const & str) curr.clear(); string::const_iterator i = str.begin(); - + while (i != str.end()) { if (*i != '%') @@ -532,7 +532,7 @@ print_format::string_to_components(string const & str) i += 2; continue; } - else + else { assert(*i == '%'); if (curr.type != conv_unspecified) @@ -544,11 +544,11 @@ print_format::string_to_components(string const & str) } } ++i; - + if (i == str.end()) break; - // Now we are definitely parsing a conversion. + // Now we are definitely parsing a conversion. // Begin by parsing flags (which are optional). switch (*i) @@ -557,22 +557,22 @@ print_format::string_to_components(string const & str) curr.flags |= static_cast<unsigned long>(fmt_flag_zeropad); ++i; break; - + case '+': curr.flags |= static_cast<unsigned long>(fmt_flag_plus); ++i; break; - + case '-': curr.flags |= static_cast<unsigned long>(fmt_flag_left); ++i; break; - + case ' ': curr.flags |= static_cast<unsigned long>(fmt_flag_space); ++i; break; - + case '#': curr.flags |= static_cast<unsigned long>(fmt_flag_special); ++i; @@ -642,28 +642,28 @@ print_format::string_to_components(string const & str) case 'b': curr.type = conv_binary; break; - + case 's': curr.type = conv_string; break; - + case 'm': curr.type = conv_memory; break; - + case 'd': case 'i': curr.type = conv_signed_decimal; break; - + case 'o': curr.type = conv_unsigned_octal; break; - + case 'u': curr.type = conv_unsigned_decimal; break; - + case 'p': curr.type = conv_unsigned_ptr; break; @@ -671,7 +671,7 @@ print_format::string_to_components(string const & str) case 'X': curr.type = conv_unsigned_uppercase_hex; break; - + case 'x': curr.type = conv_unsigned_lowercase_hex; break; @@ -679,24 +679,24 @@ print_format::string_to_components(string const & str) case 'n': curr.type = conv_size; break; - + default: break; } - + if (curr.type == conv_unspecified) throw parse_error("invalid or missing conversion specifier"); - + ++i; res.push_back(curr); - curr.clear(); + curr.clear(); } // If there's a remaining partly-composed conversion, fail. if (!curr.is_empty()) { if (curr.type == conv_literal) - res.push_back(curr); + res.push_back(curr); else throw parse_error("trailing incomplete print format conversion"); } @@ -744,7 +744,7 @@ void stat_op::print (ostream& o) const case sc_min: o << "min("; break; - + case sc_max: o << "max("; break; @@ -753,7 +753,7 @@ void stat_op::print (ostream& o) const o << ")"; } -void +void hist_op::print (ostream& o) const { o << '@'; @@ -849,7 +849,7 @@ void foreach_loop::print (ostream& o) const void null_statement::print (ostream& o) const { - o << ";"; + o << ";"; } @@ -944,7 +944,7 @@ void probe::printsig (ostream& o) const alias->printsig (o); return; } - + for (unsigned i=0; i<locations.size(); i++) { if (i > 0) o << ","; @@ -1205,7 +1205,7 @@ symbol::visit (visitor* u) u->visit_symbol (this); } -void +void target_symbol::visit (visitor* u) { u->visit_target_symbol(this); @@ -1241,7 +1241,7 @@ hist_op::visit (visitor *u) u->visit_hist_op (this); } -void +void indexable::print_indexable (std::ostream& o) const { const symbol *sym; @@ -1253,10 +1253,10 @@ indexable::print_indexable (std::ostream& o) const { assert (hist); hist->print (o); - } + } } -void +void indexable::visit_indexable (visitor* u) { symbol *sym; @@ -1272,42 +1272,42 @@ indexable::visit_indexable (visitor* u) } -bool +bool indexable::is_symbol(symbol *& sym_out) { sym_out = NULL; return false; } -bool +bool indexable::is_hist_op(hist_op *& hist_out) { hist_out = NULL; return false; } -bool +bool indexable::is_const_symbol(const symbol *& sym_out) const { sym_out = NULL; return false; } -bool +bool indexable::is_const_hist_op(const hist_op *& hist_out) const { hist_out = NULL; return false; } -bool +bool symbol::is_symbol(symbol *& sym_out) { sym_out = this; return true; } -bool +bool symbol::is_const_symbol(const symbol *& sym_out) const { sym_out = this; @@ -1320,14 +1320,14 @@ symbol::get_tok() const return tok; } -bool +bool hist_op::is_hist_op(hist_op *& hist_out) { hist_out = this; return true; } -bool +bool hist_op::is_const_hist_op(const hist_op *& hist_out) const { hist_out = this; @@ -1343,7 +1343,7 @@ hist_op::get_tok() const void classify_indexable(indexable* ix, symbol *& array_out, - hist_op *& hist_out) + hist_op *& hist_out) { array_out = NULL; hist_out = NULL; @@ -1356,7 +1356,7 @@ classify_indexable(indexable* ix, void classify_const_indexable(const indexable* ix, const symbol *& array_out, - const hist_op *& hist_out) + const hist_op *& hist_out) { array_out = NULL; hist_out = NULL; @@ -1366,7 +1366,7 @@ classify_const_indexable(const indexable* ix, // ------------------------------------------------------------------------ -bool +bool visitor::is_active_lvalue(expression *e) { for (unsigned i = 0; i < active_lvalues.size(); ++i) @@ -1377,13 +1377,13 @@ visitor::is_active_lvalue(expression *e) return false; } -void +void visitor::push_active_lvalue(expression *e) { active_lvalues.push_back(e); } -void +void visitor::pop_active_lvalue() { assert(!active_lvalues.empty()); @@ -1438,7 +1438,7 @@ traversing_visitor::visit_for_loop (for_loop* s) void traversing_visitor::visit_foreach_loop (foreach_loop* s) { - symbol *array = NULL; + symbol *array = NULL; hist_op *hist = NULL; classify_indexable (s->base, array, hist); if (array) @@ -1622,7 +1622,7 @@ traversing_visitor::visit_hist_op (hist_op* e) void -functioncall_traversing_visitor::visit_functioncall (functioncall* e) +functioncall_traversing_visitor::visit_functioncall (functioncall* e) { traversing_visitor::visit_functioncall (e); @@ -1651,7 +1651,7 @@ varuse_collecting_visitor::visit_embeddedcode (embeddedcode *s) // Kludge(tm): we look for a magic string within the function body. // $target variables as rvalues will have this; lvalues won't. // Also, explicit side-effect-free tapset functions will have this. - + assert (current_function); // only they get embedded code if (s->code.find ("/* pure */") != string::npos) return; @@ -1677,7 +1677,7 @@ varuse_collecting_visitor::visit_print_format (print_format* e) // NB: Instead of being top-level statements, "print" and "printf" // are implemented as statement-expressions containing a // print_format. They have side-effects, but not via the - // embedded-code detection method above. + // embedded-code detection method above. // // But sprint and sprintf don't have side-effects. @@ -1801,7 +1801,7 @@ varuse_collecting_visitor::visit_foreach_loop (foreach_loop* s) // NB: we duplicate so don't bother call // functioncall_traversing_visitor::visit_foreach_loop (s); - symbol *array = NULL; + symbol *array = NULL; hist_op *hist = NULL; classify_indexable (s->base, array, hist); if (array) @@ -1813,7 +1813,7 @@ varuse_collecting_visitor::visit_foreach_loop (foreach_loop* s) // array in addition to the "read" one already noted above. if (s->sort_direction) { - symbol *array = NULL; + symbol *array = NULL; hist_op *hist = NULL; classify_indexable (s->base, array, hist); if (array) this->written.insert (array->referent); @@ -2148,7 +2148,7 @@ deep_copy_visitor::visit_for_loop (for_loop* s) require <expr_statement*> (this, &(n->init), s->init); require <expression*> (this, &(n->cond), s->cond); require <expr_statement*> (this, &(n->incr), s->incr); - require <statement*> (this, &(n->block), s->block); + require <statement*> (this, &(n->block), s->block); provide <for_loop*> (this, n); } @@ -2447,7 +2447,7 @@ deep_copy_visitor::visit_hist_op (hist_op* e) provide <hist_op*> (this, n); } -block* +block* deep_copy_visitor::deep_copy (block* b) { block* n; @@ -2456,7 +2456,7 @@ deep_copy_visitor::deep_copy (block* b) return n; } -statement* +statement* deep_copy_visitor::deep_copy (statement* s) { statement* n; @@ -346,7 +346,7 @@ struct print_format: public expression static std::string components_to_string(std::vector<format_component> const & components); static std::vector<format_component> string_to_components(std::string const & str); - static bool parse_print(const std::string &name, bool &stream, + static bool parse_print(const std::string &name, bool &stream, bool &format, bool &delim, bool &newline, bool &_char); void print (std::ostream& o) const; diff --git a/tapsets.cxx b/tapsets.cxx index 289c5fac..aa6a611d 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -6073,17 +6073,13 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s, // Handle flags switch (p->flags) { - // Look in _stp_utrace_probe_cb for description of why quiesce is - // used here. + // Notice that we'll just call the probe directly when we get + // notified, since the task_finder layer stops the thread for us. case UDPF_BEGIN: // process begin s.op->line() << " .flags=(UDPF_BEGIN),"; - s.op->line() << " .ops={ .report_quiesce=stap_utrace_probe_quiesce },"; - s.op->line() << " .events=(UTRACE_STOP|UTRACE_EVENT(QUIESCE)),"; break; case UDPF_THREAD_BEGIN: // thread begin s.op->line() << " .flags=(UDPF_THREAD_BEGIN),"; - s.op->line() << " .ops={ .report_quiesce=stap_utrace_probe_quiesce },"; - s.op->line() << " .events=(UTRACE_STOP|UTRACE_EVENT(QUIESCE)),"; break; // Notice we're not setting up a .ops/.report_death handler for @@ -6098,17 +6094,17 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s, // For UDPF_SYSCALL/UDPF_SYSCALL_RETURN probes, the .report_death // handler isn't strictly necessary. However, it helps to keep - // our attaches/detaches symmetrical. Notice we're using quiesce - // as a workaround for bug 6841. + // our attaches/detaches symmetrical. Since the task_finder layer + // stops the thread, that works around bug 6841. case UDPF_SYSCALL: s.op->line() << " .flags=(UDPF_SYSCALL),"; - s.op->line() << " .ops={ .report_syscall_entry=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death, .report_quiesce=stap_utrace_probe_syscall_quiesce },"; - s.op->line() << " .events=(UTRACE_STOP|UTRACE_EVENT(QUIESCE)|UTRACE_EVENT(DEATH)),"; + s.op->line() << " .ops={ .report_syscall_entry=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death },"; + s.op->line() << " .events=(UTRACE_EVENT(SYSCALL_ENTRY)|UTRACE_EVENT(DEATH)),"; break; case UDPF_SYSCALL_RETURN: s.op->line() << " .flags=(UDPF_SYSCALL_RETURN),"; - s.op->line() << " .ops={ .report_syscall_exit=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death, .report_quiesce=stap_utrace_probe_syscall_quiesce },"; - s.op->line() << " .events=(UTRACE_STOP|UTRACE_EVENT(QUIESCE)|UTRACE_EVENT(DEATH)),"; + s.op->line() << " .ops={ .report_syscall_exit=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death },"; + s.op->line() << " .events=(UTRACE_EVENT(SYSCALL_EXIT)|UTRACE_EVENT(DEATH)),"; break; case UDPF_NONE: @@ -6191,32 +6187,10 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(-1) << "};"; - // Output handler function for UDPF_BEGIN and UDPF_THREAD_BEGIN - if (flags_seen[UDPF_BEGIN] || flags_seen[UDPF_THREAD_BEGIN]) - { - s.op->newline() << "#ifdef UTRACE_ORIG_VERSION"; - s.op->newline() << "static u32 stap_utrace_probe_quiesce(struct utrace_attached_engine *engine, struct task_struct *tsk) {"; - s.op->newline() << "#else"; - s.op->newline() << "static u32 stap_utrace_probe_quiesce(enum utrace_resume_action action, struct utrace_attached_engine *engine, struct task_struct *tsk, unsigned long event) {"; - s.op->newline() << "#endif"; - s.op->indent(1); - s.op->newline() << "struct stap_utrace_probe *p = (struct stap_utrace_probe *)engine->data;"; - - common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING"); - s.op->newline() << "c->probe_point = p->pp;"; - - // call probe function - s.op->newline() << "(*p->ph) (c);"; - common_probe_entryfn_epilogue (s.op); - - // we're detaching, so utrace automatically restarts the thread. - s.op->newline() << "debug_task_finder_detach();"; - s.op->newline() << "return UTRACE_DETACH;"; - s.op->newline(-1) << "}"; - } - - // Output handler function for UDPF_END and UDPF_THREAD_END - if (flags_seen[UDPF_END] || flags_seen[UDPF_THREAD_END]) + // Output handler function for UDPF_BEGIN, UDPF_THREAD_BEGIN, + // UDPF_END, and UDPF_THREAD_END + if (flags_seen[UDPF_BEGIN] || flags_seen[UDPF_THREAD_BEGIN] + || flags_seen[UDPF_END] || flags_seen[UDPF_THREAD_END]) { s.op->newline() << "static void stap_utrace_probe_handler(struct task_struct *tsk, struct stap_utrace_probe *p) {"; s.op->indent(1); @@ -6236,33 +6210,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN]) { s.op->newline() << "#ifdef UTRACE_ORIG_VERSION"; - s.op->newline() << "static u32 stap_utrace_probe_syscall_quiesce(struct utrace_attached_engine *engine, struct task_struct *tsk) {"; - s.op->newline() << "#else"; - s.op->newline() << "static u32 stap_utrace_probe_syscall_quiesce(enum utrace_resume_action action, struct utrace_attached_engine *engine, struct task_struct *tsk, unsigned long event) {"; - s.op->newline() << "#endif"; - s.op->indent(1); - s.op->newline() << "struct stap_utrace_probe *p = (struct stap_utrace_probe *)engine->data;"; - s.op->newline() << "int rc = 0;"; - - // Turn off quiesce handling and turn on either syscall entry - // or exit events. - s.op->newline() << "if (p->flags == UDPF_SYSCALL)"; - s.op->indent(1); - s.op->newline() << "rc = utrace_set_events(tsk, engine, UTRACE_EVENT(SYSCALL_ENTRY)|UTRACE_EVENT(DEATH));"; - s.op->indent(-1); - s.op->newline() << "else if (p->flags == UDPF_SYSCALL_RETURN)"; - s.op->indent(1); - s.op->newline() << "rc = utrace_set_events(tsk, engine, UTRACE_EVENT(SYSCALL_EXIT)|UTRACE_EVENT(DEATH));"; - s.op->indent(-1); - s.op->newline() << "if (rc != 0)"; - s.op->indent(1); - s.op->newline() << "_stp_error(\"utrace_set_events returned error %d on pid %d\", rc, (int)tsk->pid);"; - s.op->indent(-1); - - s.op->newline() << "return UTRACE_RESUME;"; - s.op->newline(-1) << "}"; - - s.op->newline() << "#ifdef UTRACE_ORIG_VERSION"; s.op->newline() << "static u32 stap_utrace_probe_syscall(struct utrace_attached_engine *engine, struct task_struct *tsk, struct pt_regs *regs) {"; s.op->newline() << "#else"; s.op->newline() << "static u32 stap_utrace_probe_syscall(enum utrace_resume_action action, struct utrace_attached_engine *engine, struct task_struct *tsk, struct pt_regs *regs) {"; @@ -6279,6 +6226,11 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "(*p->ph) (c);"; common_probe_entryfn_epilogue (s.op); + s.op->newline() << "if ((atomic_read (&session_state) != STAP_SESSION_STARTING) && (atomic_read (&session_state) != STAP_SESSION_RUNNING)) {"; + s.op->indent(1); + s.op->newline() << "debug_task_finder_detach();"; + s.op->newline() << "return UTRACE_DETACH;"; + s.op->newline(-1) << "}"; s.op->newline() << "return UTRACE_RESUME;"; s.op->newline(-1) << "}"; } @@ -6307,11 +6259,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->indent(1); s.op->newline() << "if (process_p) {"; s.op->indent(1); - s.op->newline() << "rc = stap_utrace_attach(tsk, &p->ops, p, p->events);"; - s.op->newline() << "if (rc == 0) {"; - s.op->indent(1); - s.op->newline() << "p->engine_attached = 1;"; - s.op->newline(-1) << "}"; + s.op->newline() << "stap_utrace_probe_handler(tsk, p);"; s.op->newline(-1) << "}"; s.op->newline() << "break;"; s.op->indent(-1); @@ -6322,11 +6270,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->indent(1); s.op->newline() << "if (! process_p) {"; s.op->indent(1); - s.op->newline() << "rc = stap_utrace_attach(tsk, &p->ops, p, p->events);"; - s.op->newline() << "if (rc == 0) {"; - s.op->indent(1); - s.op->newline() << "p->engine_attached = 1;"; - s.op->newline(-1) << "}"; + s.op->newline() << "stap_utrace_probe_handler(tsk, p);"; s.op->newline(-1) << "}"; s.op->newline() << "break;"; s.op->indent(-1); @@ -6367,7 +6311,8 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(-1) << "}"; // Since this engine could be attached to multiple threads, don't - // call stap_utrace_detach_ops() here. + // call stap_utrace_detach_ops() here, only call + // stap_utrace_detach() as necessary. s.op->newline() << "else {"; s.op->indent(1); s.op->newline() << "switch (p->flags) {"; @@ -6396,15 +6341,18 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->indent(-1); } - // For begin/thread_begin probes, at deregistration time we'll try - // to detach. This will only be necessary if the new thread/process - // got killed before the probe got run in the UTRACE_EVENT(QUIESCE) - // handler. - if (flags_seen[UDPF_BEGIN] || flags_seen[UDPF_THREAD_BEGIN] - || flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN]) - { + // For begin/thread_begin probes, we don't need to do anything. + if (flags_seen[UDPF_BEGIN] || flags_seen[UDPF_THREAD_BEGIN]) + { s.op->newline() << "case UDPF_BEGIN:"; s.op->newline() << "case UDPF_THREAD_BEGIN:"; + s.op->indent(1); + s.op->newline() << "break;"; + s.op->indent(-1); + } + + if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN]) + { s.op->newline() << "case UDPF_SYSCALL:"; s.op->newline() << "case UDPF_SYSCALL_RETURN:"; s.op->indent(1); diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog index e6649a36..a0e19521 100644 --- a/testsuite/ChangeLog +++ b/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2008-08-29 David Smith <dsmith@redhat.com> + + PR6841 + * systemtap.base/utrace_p5.exp: Added system-wide syscall test for + bug 6841 fix. + 2008-08-27 Stan Cox <scox@redhat.com> * systemtap.base/global_end.exp: New. diff --git a/testsuite/semok/optimize.stp b/testsuite/semok/optimize.stp index a728bd66..621bd1ca 100755 --- a/testsuite/semok/optimize.stp +++ b/testsuite/semok/optimize.stp @@ -10,7 +10,6 @@ function zoo (x) { } probe begin { - b <<< "hello" a = b + 2 zoo (zoo (5)) b = "goodbye" diff --git a/testsuite/systemtap.base/global_end.exp b/testsuite/systemtap.base/global_end.exp index b1931a90..08cf0dea 100644 --- a/testsuite/systemtap.base/global_end.exp +++ b/testsuite/systemtap.base/global_end.exp @@ -9,10 +9,10 @@ set ok 0 expect { -timeout 180 -re {one,0x1.*one,0x2.*two,0x1.*two,0x2} { incr ok; exp_continue } - -re {alpha."one"..1.=0x1} { incr ok; exp_continue } - -re {alpha."one"..2.=0x2} { incr ok; exp_continue } - -re {alpha."two"..1.=0x3} { incr ok; exp_continue } - -re {alpha."two"..2.=0x4} { incr ok; exp_continue } + -re {alpha."one".1.=0x1} { incr ok; exp_continue } + -re {alpha."one".2.=0x2} { incr ok; exp_continue } + -re {alpha."two".1.=0x3} { incr ok; exp_continue } + -re {alpha."two".2.=0x4} { incr ok; exp_continue } -re {gamma="abcdefghijklmnopqrstuvwxyz"} { incr ok; exp_continue } -re {iota."one".="eleven"} { incr ok; exp_continue } -re {iota."two".="twelve"} { incr ok; exp_continue } diff --git a/testsuite/systemtap.base/utrace_p5.exp b/testsuite/systemtap.base/utrace_p5.exp index fcd617fe..33281350 100644 --- a/testsuite/systemtap.base/utrace_p5.exp +++ b/testsuite/systemtap.base/utrace_p5.exp @@ -73,6 +73,23 @@ set thread_end_script { } set thread_end_script_output "thread_ends = \\d+\r\n" +# Script that tests the bug 6841 fix. +set bz6841_script { + global proc,name + probe begin { printf("systemtap starting probe\n") } + probe process.syscall { + proc[pid()] <<< 1 + name[pid()] = execname() + } + probe end { printf("systemtap ending probe\n") + foreach(p+ in proc) { + printf("%s(%d) issues syscall %d times\n", + name[p], p, @sum(proc[p])) + } + } +} +set bz6841_script_output ".+ issues syscall \\d+ times\r\n" + # Try to find utrace_attach symbol in /proc/kallsyms set path "/proc/kallsyms" if {! [catch {exec grep -q utrace_attach $path} dummy]} { @@ -182,5 +199,15 @@ if {$utrace_support_found == 0} { -e $script } +set TEST_NAME "UTRACE_P5_07" +if {$utrace_support_found == 0} { + untested "$TEST_NAME : no kernel utrace support found" +} elseif {![installtest_p]} { + untested "$TEST_NAME" +} else { + stap_run $TEST_NAME run_utrace_p5_multi $bz6841_script_output \ + -e $bz6841_script +} + # Cleanup exec rm -f $exepath $multi_exepath diff --git a/translate.cxx b/translate.cxx index c4370cc8..57dfe4c3 100644 --- a/translate.cxx +++ b/translate.cxx @@ -153,12 +153,12 @@ struct c_unparser: public unparser, public visitor // for function or probe bodies. Member functions should exactly match // the corresponding c_unparser logic and traversal sequence, // to ensure interlocking naming and declaration of temp variables. -struct c_tmpcounter: +struct c_tmpcounter: public traversing_visitor { c_unparser* parent; - c_tmpcounter (c_unparser* p): - parent (p) + c_tmpcounter (c_unparser* p): + parent (p) { parent->tmpvar_counter = 0; } @@ -187,7 +187,7 @@ struct c_tmpcounter: void visit_stat_op (stat_op* e); }; -struct c_unparser_assignment: +struct c_unparser_assignment: public throwing_visitor { c_unparser* parent; @@ -201,12 +201,12 @@ struct c_unparser_assignment: throwing_visitor ("invalid lvalue type"), parent (p), op (o), rvalue (0), post (pp) {} - void prepare_rvalue (string const & op, + void prepare_rvalue (string const & op, tmpvar & rval, token const* tok); - void c_assignop(tmpvar & res, - var const & lvar, + void c_assignop(tmpvar & res, + var const & lvar, tmpvar const & tmp, token const* tok); @@ -216,7 +216,7 @@ struct c_unparser_assignment: }; -struct c_tmpcounter_assignment: +struct c_tmpcounter_assignment: public traversing_visitor // leave throwing for illegal lvalues to the c_unparser_assignment instance { @@ -242,13 +242,13 @@ ostream & operator<<(ostream & o, var const & v); /* Some clarification on the runtime structures involved in statistics: - + The basic type for collecting statistics in the runtime is struct stat_data. This contains the count, min, max, sum, and possibly histogram fields. - + There are two places struct stat_data shows up. - + 1. If you declare a statistic variable of any sort, you want to make a struct _Stat. A struct _Stat* is also called a Stat. Struct _Stat contains a per-CPU array of struct stat_data values, as well as a @@ -269,7 +269,7 @@ ostream & operator<<(ostream & o, var const & v); Because, at the moment, the runtime does not support the concept of a statistic which collects multiple histogram types, we may need to instantiate one pmap or struct _Stat for each histogram variation - the user wants to track. + the user wants to track. */ class var @@ -369,36 +369,36 @@ public: case pe_stats: { // See also mapvar::init(). - + string prefix = value() + " = _stp_stat_init ("; // Check for errors during allocation. string suffix = "if (" + value () + " == NULL) rc = -ENOMEM;"; - + switch (sd.type) { case statistic_decl::none: prefix += "HIST_NONE"; break; - + case statistic_decl::linear: prefix += string("HIST_LINEAR") - + ", " + stringify(sd.linear_low) - + ", " + stringify(sd.linear_high) + + ", " + stringify(sd.linear_low) + + ", " + stringify(sd.linear_high) + ", " + stringify(sd.linear_step); break; - + case statistic_decl::logarithmic: prefix += string("HIST_LOG"); break; - + default: throw semantic_error("unsupported stats type for " + value()); } - + prefix = prefix + "); "; return string (prefix + suffix); } - + default: throw semantic_error("unsupported initializer for " + value()); } @@ -432,7 +432,7 @@ ostream & operator<<(ostream & o, var const & v) struct stmt_expr { c_unparser & c; - stmt_expr(c_unparser & c) : c(c) + stmt_expr(c_unparser & c) : c(c) { c.o->newline() << "({"; c.o->indent(1); @@ -452,8 +452,8 @@ protected: string override_value; public: - tmpvar(exp_type ty, - unsigned & counter) + tmpvar(exp_type ty, + unsigned & counter) : var(true, ty, ("__tmp" + stringify(counter++))), overridden(false) {} @@ -473,7 +473,7 @@ public: return override_value; else return var::value(); - } + } }; ostream & operator<<(ostream & o, tmpvar const & v) @@ -484,7 +484,7 @@ ostream & operator<<(ostream & o, tmpvar const & v) struct aggvar : public var { - aggvar(unsigned & counter) + aggvar(unsigned & counter) : var(true, pe_stats, ("__tmp" + stringify(counter++))) {} @@ -506,16 +506,16 @@ struct mapvar { vector<exp_type> index_types; int maxsize; - mapvar (bool local, exp_type ty, + mapvar (bool local, exp_type ty, statistic_decl const & sd, - string const & name, + string const & name, vector<exp_type> const & index_types, int maxsize) : var (local, ty, sd, name), index_types (index_types), maxsize (maxsize) {} - + static string shortname(exp_type e); static string key_typename(exp_type e); static string value_typename(exp_type e); @@ -571,7 +571,7 @@ struct mapvar { if (!is_parallel()) throw semantic_error("aggregating non-parallel map type"); - + return "_stp_pmap_agg (" + value() + ")"; } @@ -579,7 +579,7 @@ struct mapvar { if (!is_parallel()) throw semantic_error("fetching aggregate of non-parallel map type"); - + return "_stp_pmap_get_agg(" + value() + ")"; } @@ -636,7 +636,7 @@ struct mapvar // impedance matching: empty strings -> NULL if (type() == pe_string) - res += (call_prefix("set", indices) + res += (call_prefix("set", indices) + ", (" + val.value() + "[0] ? " + val.value() + " : NULL))"); else if (type() == pe_long) res += (call_prefix("set", indices) + ", " + val.value() + ")"); @@ -664,11 +664,11 @@ struct mapvar assert (sd.type != statistic_decl::none); return "(" + fetch_existing_aggregate() + "->hist.buckets)"; } - + string init () const { string mtype = is_parallel() ? "pmap" : "map"; - string prefix = value() + " = _stp_" + mtype + "_new_" + keysym() + " (" + + string prefix = value() + " = _stp_" + mtype + "_new_" + keysym() + " (" + (maxsize > 0 ? stringify(maxsize) : "MAXMAPENTRIES") ; // See also var::init(). @@ -686,9 +686,9 @@ struct mapvar case statistic_decl::linear: // FIXME: check for "reasonable" values in linear stats - prefix = prefix + ", HIST_LINEAR" - + ", " + stringify(sdecl().linear_low) - + ", " + stringify(sdecl().linear_high) + prefix = prefix + ", HIST_LINEAR" + + ", " + stringify(sdecl().linear_low) + + ", " + stringify(sdecl().linear_high) + ", " + stringify(sdecl().linear_step); break; @@ -725,25 +725,25 @@ class itervar public: itervar (symbol* e, unsigned & counter) - : referent_ty(e->referent->type), + : referent_ty(e->referent->type), name("__tmp" + stringify(counter++)) { if (referent_ty == pe_unknown) throw semantic_error("iterating over unknown reference type", e->tok); } - + string declare () const { return "struct map_node *" + name + ";"; } - + string start (mapvar const & mv) const { string res; if (mv.type() != referent_ty) throw semantic_error("inconsistent iterator type in itervar::start()"); - + if (mv.is_parallel()) return "_stp_map_start (" + mv.fetch_existing_aggregate() + ")"; else @@ -765,7 +765,7 @@ public: { return "l->" + name; } - + string get_key (exp_type ty, unsigned i) const { // bug translator/1175: runtime uses base index 1 for the first dimension @@ -802,8 +802,8 @@ translator_output::translator_output (ostream& f): translator_output::translator_output (const string& filename, size_t bufsize): buf (new char[bufsize]), - o2 (new ofstream (filename.c_str ())), - o (*o2), + o2 (new ofstream (filename.c_str ())), + o (*o2), tablevel (0) { o2->rdbuf()->pubsetbuf(buf, bufsize); @@ -919,15 +919,15 @@ c_unparser::emit_common_header () tmp_probe_contents[oss.str()] = dp->name; // save it // XXX: probe locals need not be recursion-nested, only function locals - + o->newline() << "struct " << dp->name << "_locals {"; o->indent(1); for (unsigned j=0; j<dp->locals.size(); j++) { vardecl* v = dp->locals[j]; - try + try { - o->newline() << c_typename (v->type) << " " + o->newline() << c_typename (v->type) << " " << c_varname (v->name) << ";"; } catch (const semantic_error& e) { semantic_error e2 (e); @@ -937,7 +937,7 @@ c_unparser::emit_common_header () } // NB: This part is finicky. The logic here must - // match up with + // match up with c_tmpcounter ct (this); dp->emit_probe_context_vars (o); dp->body->visit (& ct); @@ -955,9 +955,9 @@ c_unparser::emit_common_header () for (unsigned j=0; j<fd->locals.size(); j++) { vardecl* v = fd->locals[j]; - try + try { - o->newline() << c_typename (v->type) << " " + o->newline() << c_typename (v->type) << " " << c_varname (v->name) << ";"; } catch (const semantic_error& e) { semantic_error e2 (e); @@ -968,9 +968,9 @@ c_unparser::emit_common_header () for (unsigned j=0; j<fd->formal_args.size(); j++) { vardecl* v = fd->formal_args[j]; - try + try { - o->newline() << c_typename (v->type) << " " + o->newline() << c_typename (v->type) << " " << c_varname (v->name) << ";"; } catch (const semantic_error& e) { semantic_error e2 (e); @@ -1077,7 +1077,7 @@ c_unparser::emit_module_init () vector<derived_probe_group*> g = all_session_groups (*session); for (unsigned i=0; i<g.size(); i++) g[i]->emit_module_decls (*session); - + o->newline(); o->newline() << "int systemtap_module_init (void) {"; o->newline(1) << "int rc = 0;"; @@ -1091,7 +1091,7 @@ c_unparser::emit_module_init () o->newline() << "{"; o->newline(1) << "const char* release = UTS_RELEASE;"; - // NB: This UTS_RELEASE compile-time macro directly checks only that + // NB: This UTS_RELEASE compile-time macro directly checks only that // the compile-time kbuild tree matches the compile-time debuginfo/etc. // It does not check the run time kernel value. However, this is // probably OK since the kbuild modversions system aims to prevent @@ -1131,10 +1131,10 @@ c_unparser::emit_module_init () o->newline() << "rc = -ENOMEM;"; o->newline() << "goto out;"; o->newline(-1) << "}"; - + for (unsigned i=0; i<session->globals.size(); i++) { - vardecl* v = session->globals[i]; + vardecl* v = session->globals[i]; if (v->index_types.size() > 0) o->newline() << getmap (v).init(); else @@ -1150,7 +1150,7 @@ c_unparser::emit_module_init () o->newline() << "rwlock_init (& global.s_" << c_varname (v->name) << "_lock);"; } - // initialize each Stat used for timing information + // initialize each Stat used for timing information o->newline() << "#ifdef STP_TIMING"; set<string> basest_names; for (unsigned i=0; i<session->probes.size(); i++) @@ -1170,7 +1170,7 @@ c_unparser::emit_module_init () // intended to help debug problems with systemtap modules. o->newline() << "_stp_print_kernel_info(" - << "\"" << VERSION + << "\"" << VERSION << "/" << dwfl_version (NULL) << "\"" << ", (num_online_cpus() * sizeof(struct context))" << ", " << session->probes.size() @@ -1197,7 +1197,7 @@ c_unparser::emit_module_init () // All registrations were successful. Consider the system started. o->newline() << "if (atomic_read (&session_state) == STAP_SESSION_STARTING)"; - // NB: only other valid state value is ERROR, in which case we don't + // NB: only other valid state value is ERROR, in which case we don't o->newline(1) << "atomic_set (&session_state, STAP_SESSION_RUNNING);"; o->newline(-1) << "return 0;"; @@ -1210,7 +1210,7 @@ c_unparser::emit_module_init () // as this is our only chance. for (unsigned i=0; i<session->globals.size(); i++) { - vardecl* v = session->globals[i]; + vardecl* v = session->globals[i]; if (v->index_types.size() > 0) o->newline() << getmap (v).fini(); else @@ -1238,9 +1238,9 @@ c_unparser::emit_module_exit () o->newline() << "if (atomic_read (&session_state) == STAP_SESSION_STARTING)"; o->newline(1) << "return;"; o->indent(-1); - + o->newline() << "if (atomic_read (&session_state) == STAP_SESSION_RUNNING)"; - // NB: only other valid state value is ERROR, in which case we don't + // NB: only other valid state value is ERROR, in which case we don't o->newline(1) << "atomic_set (&session_state, STAP_SESSION_STOPPING);"; o->indent(-1); // This signals any other probes that may be invoked in the next little @@ -1254,7 +1254,7 @@ c_unparser::emit_module_exit () o->newline(1) << "int i;"; o->newline() << "holdon = 0;"; o->newline() << "for (i=0; i < NR_CPUS; i++)"; - o->newline(1) << "if (cpu_possible (i) && " + o->newline(1) << "if (cpu_possible (i) && " << "atomic_read (& ((struct context *)per_cpu_ptr(contexts, i))->busy)) " << "holdon = 1;"; o->newline () << "schedule ();"; @@ -1273,7 +1273,7 @@ c_unparser::emit_module_exit () for (unsigned i=0; i<session->globals.size(); i++) { - vardecl* v = session->globals[i]; + vardecl* v = session->globals[i]; if (v->index_types.size() > 0) o->newline() << getmap (v).fini(); else @@ -1297,7 +1297,7 @@ c_unparser::emit_module_exit () basest_names.insert (nm); // NB: check for null stat object o->newline() << "if (likely (time_" << p->name << ")) {"; - o->newline(1) << "const char *probe_point = " + o->newline(1) << "const char *probe_point = " << lex_cast_qstring (* p->locations[0]) << (p->locations.size() > 1 ? "\"+\"" : "") << (p->locations.size() > 1 ? lex_cast_qstring(p->locations.size()-1) : "") @@ -1357,7 +1357,7 @@ c_unparser::emit_function (functiondecl* v) o->newline() << "#define THIS l"; o->newline() << "if (0) goto out;"; // make sure out: is marked used - // set this, in case embedded-c code sets last_error but doesn't otherwise identify itself + // set this, in case embedded-c code sets last_error but doesn't otherwise identify itself o->newline() << "c->last_stmt = " << lex_cast_qstring(*v->tok) << ";"; // check/increment nesting level @@ -1373,7 +1373,7 @@ c_unparser::emit_function (functiondecl* v) for (unsigned i=0; i<v->locals.size(); i++) { if (v->locals[i]->index_types.size() > 0) // array? - throw semantic_error ("array locals not supported, missing global declaration?", + throw semantic_error ("array locals not supported, missing global declaration?", v->locals[i]->tok); o->newline() << getvar (v->locals[i]).init(); @@ -1448,7 +1448,7 @@ c_unparser::emit_probe (derived_probe* v) // NB: This code *could* be enclosed in an "if (session->timing)". That would // recognize more duplicate probe handlers, but then the generated code could // be very different with or without -t. - oss << "c->statp = & time_" << v->basest()->name << ";" << endl; + oss << "c->statp = & time_" << v->basest()->name << ";" << endl; v->body->print(oss); @@ -1510,7 +1510,7 @@ c_unparser::emit_probe (derived_probe* v) o->newline() << "struct " << v->name << "_locals * __restrict__ l ="; o->newline(1) << "& c->locals[0]." << v->name << ";"; o->newline(-1) << "(void) l;"; // make sure "l" is marked used - + o->newline() << "#ifdef STP_TIMING"; o->newline() << "c->statp = & time_" << v->basest()->name << ";"; o->newline() << "#endif"; @@ -1530,7 +1530,7 @@ c_unparser::emit_probe (derived_probe* v) for (unsigned j=0; j<v->locals.size(); j++) { if (v->locals[j]->index_types.size() > 0) // array? - throw semantic_error ("array locals not supported, missing global declaration?", + throw semantic_error ("array locals not supported, missing global declaration?", v->locals[j]->tok); else if (v->locals[j]->type == pe_long) o->newline() << "l->" << c_varname (v->locals[j]->name) @@ -1557,7 +1557,7 @@ c_unparser::emit_probe (derived_probe* v) o->newline(-1) << "out:"; // NB: no need to uninitialize locals, except if arrays/stats can - // someday be local + // someday be local // XXX: do this flush only if the body included a // print/printf/etc. routine! @@ -1569,12 +1569,12 @@ c_unparser::emit_probe (derived_probe* v) o->newline(-1) << "}\n"; } - + this->current_probe = 0; } -void +void c_unparser::emit_locks(const varuse_collecting_visitor& vut) { o->newline() << "{"; @@ -1613,7 +1613,7 @@ c_unparser::emit_locks(const varuse_collecting_visitor& vut) continue; } - string lockcall = + string lockcall = string (write_p ? "write" : "read") + "_trylock (& global.s_" + v->name + "_lock)"; @@ -1637,7 +1637,7 @@ c_unparser::emit_locks(const varuse_collecting_visitor& vut) } -void +void c_unparser::emit_unlocks(const varuse_collecting_visitor& vut) { unsigned numvars = 0; @@ -1682,7 +1682,7 @@ c_unparser::emit_unlocks(const varuse_collecting_visitor& vut) // fall through to next variable; thus the reverse ordering } - + // emit plain "unlock" label, used if the very first lock failed. o->newline(-1) << "unlock_: ;"; o->indent(1); @@ -1704,7 +1704,7 @@ c_unparser::emit_unlocks(const varuse_collecting_visitor& vut) } -void +void c_unparser::collect_map_index_types(vector<vardecl *> const & vars, set< pair<vector<exp_type>, exp_type> > & types) { @@ -1746,7 +1746,7 @@ mapvar::key_typename(exp_type e) return "STRING"; default: throw semantic_error("array key is neither string nor long"); - } + } return ""; } @@ -1761,7 +1761,7 @@ mapvar::shortname(exp_type e) return "s"; default: throw semantic_error("array type is neither string nor long"); - } + } return ""; } @@ -1770,7 +1770,7 @@ void c_unparser::emit_map_type_instantiations () { set< pair<vector<exp_type>, exp_type> > types; - + collect_map_index_types(session->globals, types); for (unsigned i = 0; i < session->probes.size(); ++i) @@ -1799,7 +1799,7 @@ c_unparser::emit_map_type_instantiations () for (unsigned j = 0; j < i->first.size(); ++j) { o->newline() << "#undef KEY" << (j+1) << "_TYPE"; - } + } /* FIXME * For pmaps, we also need to include map-gen.c, because we might be accessing @@ -1819,7 +1819,7 @@ c_unparser::emit_map_type_instantiations () for (unsigned j = 0; j < i->first.size(); ++j) { o->newline() << "#undef KEY" << (j+1) << "_TYPE"; - } + } } } @@ -1835,9 +1835,9 @@ c_unparser::c_typename (exp_type e) switch (e) { case pe_long: return string("int64_t"); - case pe_string: return string("string_t"); + case pe_string: return string("string_t"); case pe_stats: return string("Stat"); - case pe_unknown: + case pe_unknown: default: throw semantic_error ("cannot expand unknown type"); } @@ -1892,9 +1892,9 @@ c_unparser::c_expression (expression *e) } -void +void c_unparser::c_assign (var& lvalue, const string& rvalue, const token *tok) -{ +{ switch (lvalue.type()) { case pe_string: @@ -1950,9 +1950,9 @@ c_unparser::c_assign (const string& lvalue, const string& rvalue, } -void -c_unparser_assignment::c_assignop(tmpvar & res, - var const & lval, +void +c_unparser_assignment::c_assignop(tmpvar & res, + var const & lval, tmpvar const & rval, token const * tok) { @@ -1965,7 +1965,7 @@ c_unparser_assignment::c_assignop(tmpvar & res, // lval: the lvalue of the expression, which may be damaged // rval: the rvalue of the expression, which is a temporary or constant - // we'd like to work with a local tmpvar so we can overwrite it in + // we'd like to work with a local tmpvar so we can overwrite it in // some optimized cases translator_output* o = parent->o; @@ -1973,7 +1973,7 @@ c_unparser_assignment::c_assignop(tmpvar & res, if (res.type() == pe_string) { if (post) - throw semantic_error ("post assignment on strings not supported", + throw semantic_error ("post assignment on strings not supported", tok); if (op == "=") { @@ -2064,31 +2064,31 @@ c_unparser_assignment::c_assignop(tmpvar & res, } -void -c_unparser::c_declare(exp_type ty, const string &name) +void +c_unparser::c_declare(exp_type ty, const string &name) { o->newline() << c_typename (ty) << " " << c_varname (name) << ";"; } -void -c_unparser::c_declare_static(exp_type ty, const string &name) +void +c_unparser::c_declare_static(exp_type ty, const string &name) { o->newline() << "static " << c_typename (ty) << " " << c_varname (name) << ";"; } -void -c_unparser::c_strcpy (const string& lvalue, const string& rvalue) +void +c_unparser::c_strcpy (const string& lvalue, const string& rvalue) { - o->newline() << "strlcpy (" - << lvalue << ", " + o->newline() << "strlcpy (" + << lvalue << ", " << rvalue << ", MAXSTRINGLEN);"; } -void -c_unparser::c_strcpy (const string& lvalue, expression* rvalue) +void +c_unparser::c_strcpy (const string& lvalue, expression* rvalue) { o->newline() << "strlcpy (" << lvalue << ", "; rvalue->visit (this); @@ -2096,17 +2096,17 @@ c_unparser::c_strcpy (const string& lvalue, expression* rvalue) } -void -c_unparser::c_strcat (const string& lvalue, const string& rvalue) +void +c_unparser::c_strcat (const string& lvalue, const string& rvalue) { - o->newline() << "strlcat (" - << lvalue << ", " + o->newline() << "strlcat (" + << lvalue << ", " << rvalue << ", MAXSTRINGLEN);"; } -void -c_unparser::c_strcat (const string& lvalue, expression* rvalue) +void +c_unparser::c_strcat (const string& lvalue, expression* rvalue) { o->newline() << "strlcat (" << lvalue << ", "; rvalue->visit (this); @@ -2116,7 +2116,7 @@ c_unparser::c_strcat (const string& lvalue, expression* rvalue) bool c_unparser::is_local(vardecl const *r, token const *tok) -{ +{ if (current_probe) { for (unsigned i=0; i<current_probe->locals.size(); i++) @@ -2145,7 +2145,7 @@ c_unparser::is_local(vardecl const *r, token const *tok) if (session->globals[i] == r) return false; } - + if (tok) throw semantic_error ("unresolved symbol", tok); else @@ -2153,24 +2153,24 @@ c_unparser::is_local(vardecl const *r, token const *tok) } -tmpvar -c_unparser::gensym(exp_type ty) -{ - return tmpvar (ty, tmpvar_counter); +tmpvar +c_unparser::gensym(exp_type ty) +{ + return tmpvar (ty, tmpvar_counter); } -aggvar -c_unparser::gensym_aggregate() -{ - return aggvar (tmpvar_counter); +aggvar +c_unparser::gensym_aggregate() +{ + return aggvar (tmpvar_counter); } -var -c_unparser::getvar(vardecl *v, token const *tok) -{ +var +c_unparser::getvar(vardecl *v, token const *tok) +{ bool loc = is_local (v, tok); - if (loc) + if (loc) return var (loc, v->type, v->name); else { @@ -2184,9 +2184,9 @@ c_unparser::getvar(vardecl *v, token const *tok) } -mapvar -c_unparser::getmap(vardecl *v, token const *tok) -{ +mapvar +c_unparser::getmap(vardecl *v, token const *tok) +{ if (v->arity < 1) throw semantic_error("attempt to use scalar where map expected", tok); statistic_decl sd; @@ -2199,9 +2199,9 @@ c_unparser::getmap(vardecl *v, token const *tok) } -itervar +itervar c_unparser::getiter(symbol *s) -{ +{ return itervar (s, tmpvar_counter); } @@ -2392,9 +2392,9 @@ struct arrayindex_downcaster : public traversing_visitor { arrayindex *& arr; - + arrayindex_downcaster (arrayindex *& arr) - : arr(arr) + : arr(arr) {} void visit_arrayindex (arrayindex* e) @@ -2405,7 +2405,7 @@ struct arrayindex_downcaster static bool -expression_is_arrayindex (expression *e, +expression_is_arrayindex (expression *e, arrayindex *& hist) { arrayindex *h = NULL; @@ -2423,7 +2423,7 @@ expression_is_arrayindex (expression *e, void c_tmpcounter::visit_foreach_loop (foreach_loop *s) { - symbol *array; + symbol *array; hist_op *hist; classify_indexable (s->base, array, hist); @@ -2433,17 +2433,17 @@ c_tmpcounter::visit_foreach_loop (foreach_loop *s) parent->o->newline() << iv.declare(); } else - { + { // See commentary in c_tmpcounter::visit_arrayindex for // discussion of tmpvars required to look into @hist_op(...) // expressions. // First make sure we have exactly one pe_long variable to use as // our bucket index. - + if (s->indexes.size() != 1 || s->indexes[0]->referent->type != pe_long) throw semantic_error("Invalid indexing of histogram", s->tok); - + // Then declare what we need to form the aggregate we're // iterating over, and all the tmpvars needed by our call to // load_aggregate(). @@ -2460,7 +2460,7 @@ c_tmpcounter::visit_foreach_loop (foreach_loop *s) throw semantic_error("expected arrayindex expression in iterated hist_op", s->tok); for (unsigned i=0; i<sym->referent->index_types.size(); i++) - { + { tmpvar ix = parent->gensym (sym->referent->index_types[i]); ix.declare (*parent); arr->indexes[i]->visit(this); @@ -2487,7 +2487,7 @@ c_tmpcounter::visit_foreach_loop (foreach_loop *s) void c_unparser::visit_foreach_loop (foreach_loop *s) { - symbol *array; + symbol *array; hist_op *hist; classify_indexable (s->base, array, hist); @@ -2496,14 +2496,14 @@ c_unparser::visit_foreach_loop (foreach_loop *s) mapvar mv = getmap (array->referent, s->tok); itervar iv = getiter (array); vector<var> keys; - + string ctr = stringify (label_counter++); string toplabel = "top_" + ctr; string contlabel = "continue_" + ctr; string breaklabel = "break_" + ctr; - + // NB: structure parallels for_loop - + // initialization tmpvar *res_limit = NULL; @@ -2513,7 +2513,7 @@ c_unparser::visit_foreach_loop (foreach_loop *s) res_limit = new tmpvar(gensym(pe_long)); c_assign (res_limit->value(), s->limit, "foreach limit"); } - + // aggregate array if required if (mv.is_parallel()) { @@ -2554,7 +2554,7 @@ c_unparser::visit_foreach_loop (foreach_loop *s) } } else - { + { // sort array if desired if (s->sort_direction) { @@ -2574,11 +2574,11 @@ c_unparser::visit_foreach_loop (foreach_loop *s) } // NB: sort direction sense is opposite in runtime, thus the negation - + if (mv.is_parallel()) aggregations_active.insert(mv.value()); o->newline() << iv << " = " << iv.start (mv) << ";"; - + tmpvar *limitv = NULL; if (s->limit) { @@ -2599,7 +2599,7 @@ c_unparser::visit_foreach_loop (foreach_loop *s) record_actions(1); o->newline() << "if (! (" << iv << ")) goto " << breaklabel << ";"; - + // body loop_break_labels.push_back (breaklabel); loop_continue_labels.push_back (contlabel); @@ -2628,12 +2628,12 @@ c_unparser::visit_foreach_loop (foreach_loop *s) o->newline(-1) << "}"; loop_break_labels.pop_back (); loop_continue_labels.pop_back (); - + // iteration o->newline(-1) << contlabel << ":"; o->newline(1) << iv << " = " << iv.next (mv) << ";"; o->newline() << "goto " << toplabel << ";"; - + // exit o->newline(-1) << breaklabel << ":"; o->newline(1) << "; /* dummy statement */"; @@ -2667,10 +2667,10 @@ c_unparser::visit_foreach_loop (foreach_loop *s) limitv = new tmpvar(gensym (pe_long)); o->newline() << *limitv << " = 0LL;"; } - + // XXX: break / continue don't work here yet record_actions(1, true); - o->newline() << "for (" << bucketvar << " = 0; " + o->newline() << "for (" << bucketvar << " = 0; " << bucketvar << " < " << v.buckets() << "; " << bucketvar << "++) { "; o->newline(1); @@ -2744,17 +2744,17 @@ struct delete_statement_operand_visitor: void visit_arrayindex (arrayindex* e); }; -void +void delete_statement_operand_visitor::visit_symbol (symbol* e) { assert (e->referent != 0); if (e->referent->arity > 0) { - mapvar mvar = parent->getmap(e->referent, e->tok); + mapvar mvar = parent->getmap(e->referent, e->tok); /* NB: Memory deallocation/allocation operations are not generally safe. parent->o->newline() << mvar.fini (); - parent->o->newline() << mvar.init (); + parent->o->newline() << mvar.init (); */ if (mvar.is_parallel()) parent->o->newline() << "_stp_pmap_clear (" << mvar.value() << ");"; @@ -2763,7 +2763,7 @@ delete_statement_operand_visitor::visit_symbol (symbol* e) } else { - var v = parent->getvar(e->referent, e->tok); + var v = parent->getvar(e->referent, e->tok); switch (e->type) { case pe_stats: @@ -2782,10 +2782,10 @@ delete_statement_operand_visitor::visit_symbol (symbol* e) } } -void +void delete_statement_operand_tmp_visitor::visit_arrayindex (arrayindex* e) { - symbol *array; + symbol *array; hist_op *hist; classify_indexable (e->base, array, hist); @@ -2808,10 +2808,10 @@ delete_statement_operand_tmp_visitor::visit_arrayindex (arrayindex* e) } } -void +void delete_statement_operand_visitor::visit_arrayindex (arrayindex* e) { - symbol *array; + symbol *array; hist_op *hist; classify_indexable (e->base, array, hist); @@ -2819,7 +2819,7 @@ delete_statement_operand_visitor::visit_arrayindex (arrayindex* e) { vector<tmpvar> idx; parent->load_map_indices (e, idx); - + { mapvar mvar = parent->getmap (array->referent, e->tok); parent->o->newline() << mvar.del (idx) << ";"; @@ -2932,7 +2932,7 @@ c_unparser::visit_binary_expression (binary_expression* e) e->left->type != pe_long || e->right->type != pe_long) throw semantic_error ("expected numeric types", e->tok); - + if (e->op == "+" || e->op == "-" || e->op == "*" || @@ -2995,7 +2995,7 @@ c_unparser::visit_binary_expression (binary_expression* e) o->newline(-1) << "})"; } else - throw semantic_error ("operator not yet implemented", e->tok); + throw semantic_error ("operator not yet implemented", e->tok); } @@ -3059,13 +3059,13 @@ c_unparser::visit_logical_and_expr (logical_and_expr* e) } -void +void c_tmpcounter::visit_array_in (array_in* e) { - symbol *array; + symbol *array; hist_op *hist; classify_indexable (e->operand->base, array, hist); - + if (array) { assert (array->referent != 0); @@ -3078,7 +3078,7 @@ c_tmpcounter::visit_array_in (array_in* e) ix.declare (*parent); e->operand->indexes[i]->visit(this); } - + // A boolean result. tmpvar res = parent->gensym (e->type); res.declare (*parent); @@ -3100,18 +3100,18 @@ c_tmpcounter::visit_array_in (array_in* e) void c_unparser::visit_array_in (array_in* e) { - symbol *array; + symbol *array; hist_op *hist; classify_indexable (e->operand->base, array, hist); - + if (array) { - stmt_expr block(*this); - + stmt_expr block(*this); + vector<tmpvar> idx; load_map_indices (e->operand, idx); // o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";"; - + tmpvar res = gensym (pe_long); mapvar mvar = getmap (array->referent, e->tok); c_assign (res, mvar.exists(idx), e->tok); @@ -3189,7 +3189,7 @@ c_unparser::visit_concatenation (concatenation* e) throw semantic_error ("expected string types", e->tok); tmpvar t = gensym (e->type); - + o->line() << "({ "; o->indent(1); // o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";"; @@ -3242,7 +3242,7 @@ c_unparser::visit_assignment (assignment* e) if (e->right->type != pe_long) throw semantic_error ("non-number right operand to <<< expression", e->right->tok); - + } else { @@ -3326,7 +3326,7 @@ c_tmpcounter_assignment::prepare_rvalue (tmpvar & rval) } } -void +void c_tmpcounter_assignment::c_assignop(tmpvar & res) { if (res.type() == pe_string) @@ -3380,7 +3380,7 @@ c_tmpcounter_assignment::visit_symbol (symbol *e) void -c_unparser_assignment::prepare_rvalue (string const & op, +c_unparser_assignment::prepare_rvalue (string const & op, tmpvar & rval, token const * tok) { @@ -3422,13 +3422,13 @@ c_unparser_assignment::visit_symbol (symbol *e) prepare_rvalue (op, rval, e->tok); var lvar = parent->getvar (e->referent, e->tok); - c_assignop (res, lvar, rval, e->tok); + c_assignop (res, lvar, rval, e->tok); parent->o->newline() << res << ";"; } -void +void c_unparser::visit_target_symbol (target_symbol* e) { throw semantic_error("cannot translate general target-symbol expression", e->tok); @@ -3438,7 +3438,7 @@ c_unparser::visit_target_symbol (target_symbol* e) void c_tmpcounter::load_map_indices(arrayindex *e) { - symbol *array; + symbol *array; hist_op *hist; classify_indexable (e->base, array, hist); @@ -3446,7 +3446,7 @@ c_tmpcounter::load_map_indices(arrayindex *e) { assert (array->referent != 0); vardecl* r = array->referent; - + // One temporary per index dimension, except in the case of // number or string constants. for (unsigned i=0; i<r->index_types.size(); i++) @@ -3469,26 +3469,26 @@ void c_unparser::load_map_indices(arrayindex *e, vector<tmpvar> & idx) { - symbol *array; + symbol *array; hist_op *hist; classify_indexable (e->base, array, hist); if (array) { idx.clear(); - + assert (array->referent != 0); vardecl* r = array->referent; - + if (r->index_types.size() == 0 || r->index_types.size() != e->indexes.size()) throw semantic_error ("invalid array reference", e->tok); - + for (unsigned i=0; i<r->index_types.size(); i++) { if (r->index_types[i] != e->indexes[i]->type) throw semantic_error ("array index type mismatch", e->indexes[i]->tok); - + tmpvar ix = gensym (r->index_types[i]); if (e->indexes[i]->tok->type == tok_number || e->indexes[i]->tok->type == tok_string) @@ -3514,31 +3514,31 @@ c_unparser::load_map_indices(arrayindex *e, // << lex_cast_qstring(*e->indexes[0]->tok) << ";"; c_assign (ix.value(), e->indexes[0], "array index copy"); idx.push_back(ix); - } + } } -void +void c_unparser::load_aggregate (expression *e, aggvar & agg, bool pre_agg) { symbol *sym = get_symbol_within_expression (e); - + if (sym->referent->type != pe_stats) throw semantic_error ("unexpected aggregate of non-statistic", sym->tok); - + var v = getvar(sym->referent, e->tok); if (sym->referent->arity == 0) { // o->newline() << "c->last_stmt = " << lex_cast_qstring(*sym->tok) << ";"; - o->newline() << agg << " = _stp_stat_get (" << v << ", 0);"; + o->newline() << agg << " = _stp_stat_get (" << v << ", 0);"; } else { arrayindex *arr = NULL; if (!expression_is_arrayindex (e, arr)) throw semantic_error("unexpected aggregate of non-arrayindex", e->tok); - + vector<tmpvar> idx; load_map_indices (arr, idx); mapvar mvar = getmap (sym->referent, sym->tok); @@ -3548,25 +3548,25 @@ c_unparser::load_aggregate (expression *e, aggvar & agg, bool pre_agg) } -string +string c_unparser::histogram_index_check(var & base, tmpvar & idx) const { return "((" + idx.value() + " >= 0)" - + " && (" + idx.value() + " < " + base.buckets() + "))"; + + " && (" + idx.value() + " < " + base.buckets() + "))"; } void c_tmpcounter::visit_arrayindex (arrayindex *e) { - symbol *array; + symbol *array; hist_op *hist; classify_indexable (e->base, array, hist); if (array) { load_map_indices(e); - + // The index-expression result. tmpvar res = parent->gensym (e->type); res.declare (*parent); @@ -3580,18 +3580,18 @@ c_tmpcounter::visit_arrayindex (arrayindex *e) // temporaries. The reason is that we're in the branch handling // histogram-indexing, and the histogram might be build over an // indexable entity itself. For example if we have: - // + // // global foo // ... // foo[getpid(), geteuid()] <<< 1 // ... // print @log_hist(foo[pid, euid])[bucket] - // + // // We are looking at the @log_hist(...)[bucket] expression, so // allocating one tmpvar for calculating bucket (the "index" of // this arrayindex expression), and one tmpvar for storing the // result in, just as normal. - // + // // But we are *also* going to call load_aggregate on foo, which // will itself require tmpvars for each of its indices. Since // this is not handled by delving into the subexpression (it @@ -3601,17 +3601,17 @@ c_tmpcounter::visit_arrayindex (arrayindex *e) // (bucket) tmpvar, then all the index tmpvars of our // pe_stat-valued subexpression, then our result. - + // First all the stuff related to indexing into the histogram if (e->indexes.size() != 1) throw semantic_error("Invalid indexing of histogram", e->tok); tmpvar ix = parent->gensym (pe_long); - ix.declare (*parent); + ix.declare (*parent); e->indexes[0]->visit(this); tmpvar res = parent->gensym (pe_long); res.declare (*parent); - + // Then the aggregate, and all the tmpvars needed by our call to // load_aggregate(). @@ -3627,7 +3627,7 @@ c_tmpcounter::visit_arrayindex (arrayindex *e) throw semantic_error("expected arrayindex expression in indexed hist_op", e->tok); for (unsigned i=0; i<sym->referent->index_types.size(); i++) - { + { tmpvar ix = parent->gensym (sym->referent->index_types[i]); ix.declare (*parent); arr->indexes[i]->visit(this); @@ -3639,8 +3639,8 @@ c_tmpcounter::visit_arrayindex (arrayindex *e) void c_unparser::visit_arrayindex (arrayindex* e) -{ - symbol *array; +{ + symbol *array; hist_op *hist; classify_indexable (e->base, array, hist); @@ -3650,16 +3650,16 @@ c_unparser::visit_arrayindex (arrayindex* e) if (array->referent->type == pe_stats) throw semantic_error ("statistic-valued array in rvalue context", e->tok); - stmt_expr block(*this); + stmt_expr block(*this); // NB: Do not adjust the order of the next few lines; the tmpvar // allocation order must remain the same between // c_unparser::visit_arrayindex and c_tmpcounter::visit_arrayindex - + vector<tmpvar> idx; load_map_indices (e, idx); tmpvar res = gensym (e->type); - + mapvar mvar = getmap (array->referent, e->tok); // o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";"; c_assign (res, mvar.get(idx), e->tok); @@ -3671,21 +3671,21 @@ c_unparser::visit_arrayindex (arrayindex* e) // See commentary in c_tmpcounter::visit_arrayindex assert(hist); - stmt_expr block(*this); + stmt_expr block(*this); // NB: Do not adjust the order of the next few lines; the tmpvar // allocation order must remain the same between // c_unparser::visit_arrayindex and c_tmpcounter::visit_arrayindex - + vector<tmpvar> idx; load_map_indices (e, idx); tmpvar res = gensym (e->type); - + aggvar agg = gensym_aggregate (); // These should have faulted during elaboration if not true. assert(idx.size() == 1); - assert(idx[0].type() == pe_long); + assert(idx[0].type() == pe_long); symbol *sym = get_symbol_within_expression (hist->stat); @@ -3699,7 +3699,7 @@ c_unparser::visit_arrayindex (arrayindex* e) if (aggregations_active.count(v->value())) load_aggregate(hist->stat, agg, true); - else + else load_aggregate(hist->stat, agg, false); o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";"; @@ -3719,7 +3719,7 @@ c_unparser::visit_arrayindex (arrayindex* e) o->newline(-1) << "}"; o->newline() << res << ";"; - + delete v; } } @@ -3728,14 +3728,14 @@ c_unparser::visit_arrayindex (arrayindex* e) void c_tmpcounter_assignment::visit_arrayindex (arrayindex *e) { - symbol *array; + symbol *array; hist_op *hist; classify_indexable (e->base, array, hist); if (array) { parent->load_map_indices(e); - + // The expression rval, lval, and result. exp_type ty = rvalue ? rvalue->type : e->type; tmpvar rval = parent->parent->gensym (ty); @@ -3760,14 +3760,14 @@ c_tmpcounter_assignment::visit_arrayindex (arrayindex *e) void c_unparser_assignment::visit_arrayindex (arrayindex *e) { - symbol *array; + symbol *array; hist_op *hist; classify_indexable (e->base, array, hist); if (array) { - stmt_expr block(*parent); + stmt_expr block(*parent); translator_output *o = parent->o; @@ -3778,14 +3778,14 @@ c_unparser_assignment::visit_arrayindex (arrayindex *e) // allocation order must remain the same between // c_unparser_assignment::visit_arrayindex and // c_tmpcounter_assignment::visit_arrayindex - + vector<tmpvar> idx; parent->load_map_indices (e, idx); exp_type ty = rvalue ? rvalue->type : e->type; tmpvar rvar = parent->gensym (ty); tmpvar lvar = parent->gensym (ty); tmpvar res = parent->gensym (ty); - + // NB: because these expressions are nestable, emit this construct // thusly: // ({ tmp0=(idx0); ... tmpN=(idxN); rvar=(rhs); lvar; res; @@ -3801,7 +3801,7 @@ c_unparser_assignment::visit_arrayindex (arrayindex *e) // e.g. ++a[a[c]=5] could deadlock // // - // There is an exception to the above form: if we're doign a <<< assigment to + // There is an exception to the above form: if we're doign a <<< assigment to // a statistic-valued map, there's a special form we follow: // // ({ tmp0=(idx0); ... tmpN=(idxN); rvar=(rhs); @@ -3835,12 +3835,12 @@ c_unparser_assignment::visit_arrayindex (arrayindex *e) // o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";"; if (op != "=") // don't bother fetch slot if we will just overwrite it parent->c_assign (lvar, mvar.get(idx), e->tok); - c_assignop (res, lvar, rvar, e->tok); + c_assignop (res, lvar, rvar, e->tok); o->newline() << mvar.set (idx, lvar) << ";"; } o->newline() << res << ";"; - } + } else { throw semantic_error("cannot assign to histogram buckets", e->tok); @@ -3874,7 +3874,7 @@ c_unparser::visit_functioncall (functioncall* e) if (r->formal_args.size() != e->args.size()) throw semantic_error ("invalid length argument list", e->tok); - stmt_expr block(*this); + stmt_expr block(*this); // NB: we store all actual arguments in temporary variables, // to avoid colliding sharing of context variables with @@ -3953,7 +3953,7 @@ c_tmpcounter::visit_print_format (print_format* e) arrayindex *arr = NULL; if (!expression_is_arrayindex (e->hist->stat, arr)) throw semantic_error("expected arrayindex expression in printed hist_op", e->tok); - + tmpvar ix = parent->gensym (sym->referent->index_types[i]); ix.declare (*parent); arr->indexes[i]->visit(this); @@ -3968,7 +3968,7 @@ c_tmpcounter::visit_print_format (print_format* e) tmpvar t = parent->gensym (e->args[i]->type); if (e->args[i]->type == pe_unknown) { - throw semantic_error("unknown type of arg to print operator", + throw semantic_error("unknown type of arg to print operator", e->args[i]->tok); } @@ -3980,14 +3980,14 @@ c_tmpcounter::visit_print_format (print_format* e) // And the result exp_type ty = e->print_to_stream ? pe_long : pe_string; - tmpvar res = parent->gensym (ty); + tmpvar res = parent->gensym (ty); if (ty == pe_string) res.declare (*parent); } } -void +void c_unparser::visit_print_format (print_format* e) { // Print formats can contain a general argument list *or* a special @@ -3996,7 +3996,7 @@ c_unparser::visit_print_format (print_format* e) if (e->hist) { - stmt_expr block(*this); + stmt_expr block(*this); symbol *sym = get_symbol_within_expression (e->hist->stat); aggvar agg = gensym_aggregate (); @@ -4011,7 +4011,7 @@ c_unparser::visit_print_format (print_format* e) { if (aggregations_active.count(v->value())) load_aggregate(e->hist->stat, agg, true); - else + else load_aggregate(e->hist->stat, agg, false); // PR 2142+2610: empty aggregates @@ -4029,11 +4029,11 @@ c_unparser::visit_print_format (print_format* e) } else { - stmt_expr block(*this); + stmt_expr block(*this); // Compute actual arguments vector<tmpvar> tmp; - + for (unsigned i=0; i<e->args.size(); i++) { tmpvar t = gensym(e->args[i]->type); @@ -4051,11 +4051,11 @@ c_unparser::visit_print_format (print_format* e) tmp[i].override(c_expression(e->args[i])); else c_assign (t.value(), e->args[i], - "print format actual argument evaluation"); + "print format actual argument evaluation"); } std::vector<print_format::format_component> components; - + if (e->print_with_format) { components = e->components; @@ -4099,13 +4099,13 @@ c_unparser::visit_print_format (print_format* e) // Allocate the result exp_type ty = e->print_to_stream ? pe_long : pe_string; - tmpvar res = gensym (ty); + tmpvar res = gensym (ty); int use_print = 0; string format_string = print_format::components_to_string(components); if (tmp.size() == 0 || (tmp.size() == 1 && format_string == "%s")) use_print = 1; - else if (tmp.size() == 1 + else if (tmp.size() == 1 && e->args[0]->tok->type == tok_string && format_string == "%s\\n") { @@ -4155,7 +4155,7 @@ c_unparser::visit_print_format (print_format* e) o->line() << tmp[0].value() << ");"; else o->line() << '"' << format_string << "\");"; - return; + return; } if (use_print) { @@ -4176,7 +4176,7 @@ c_unparser::visit_print_format (print_format* e) o->newline() << "_stp_snprintf (" << res.value() << ", MAXSTRINGLEN, "; o->line() << '"' << format_string << '"'; - + /* Generate the actual arguments. Make sure that they match the expected type of the format specifier. */ arg_ix = 0; @@ -4203,7 +4203,7 @@ c_unparser::visit_print_format (print_format* e) } -void +void c_tmpcounter::visit_stat_op (stat_op* e) { symbol *sym = get_symbol_within_expression (e->stat); @@ -4232,14 +4232,14 @@ c_tmpcounter::visit_stat_op (stat_op* e) } } -void +void c_unparser::visit_stat_op (stat_op* e) { // Stat ops can be *applied* to two types of expression: // - // 1. An arrayindex expression on a pe_stats-valued array. + // 1. An arrayindex expression on a pe_stats-valued array. // - // 2. A symbol of type pe_stats. + // 2. A symbol of type pe_stats. // FIXME: classify the expression the stat_op is being applied to, // call appropriate stp_get_stat() / stp_pmap_get_stat() helper, @@ -4248,12 +4248,12 @@ c_unparser::visit_stat_op (stat_op* e) // FIXME: also note that summarizing anything is expensive, and we // really ought to pass a timeout handler into the summary routine, // check its response, possibly exit if it ran out of cycles. - + { stmt_expr block(*this); symbol *sym = get_symbol_within_expression (e->stat); aggvar agg = gensym_aggregate (); - tmpvar res = gensym (pe_long); + tmpvar res = gensym (pe_long); var v = getvar(sym->referent, e->tok); { if (aggregations_active.count(v.value())) @@ -4301,13 +4301,13 @@ c_unparser::visit_stat_op (stat_op* e) break; } o->indent(-1); - } + } o->newline() << res << ";"; } } -void +void c_unparser::visit_hist_op (hist_op*) { // Hist ops can only occur in a limited set of circumstances: @@ -4387,13 +4387,13 @@ dump_unwindsyms (Dwfl_Module *m, map<unsigned, addrmap_t> addrmap; // per-relocation-base sorted addrmap Dwarf_Addr extra_offset = 0; - + for (int i = 1 /* XXX: why not 0? */ ; i < syments; ++i) { GElf_Sym sym; const char *name = dwfl_module_getsym(m, i, &sym, NULL); if (name) - { + { // NB: Yey, we found the kernel's _stext value. // Sess.sym_stext may be unset (0) at this point, since // there may have been no kernel probes set. We could @@ -4431,11 +4431,11 @@ dump_unwindsyms (Dwfl_Module *m, assert (secname != NULL); // secname adequately set } - else + else { assert (n == 0); // sym_addr is absolute, as it must be since there are no relocation bases - secname = ".absolute"; // sentinel + secname = ".absolute"; // sentinel } // Compute our section number @@ -4443,7 +4443,7 @@ dump_unwindsyms (Dwfl_Module *m, for (secidx=0; secidx<seclist.size(); secidx++) if (seclist[secidx]==secname) break; - if (secidx == seclist.size()) // new section name + if (secidx == seclist.size()) // new section name seclist.push_back (secname); (addrmap[secidx])[sym_addr] = name; @@ -4461,7 +4461,7 @@ dump_unwindsyms (Dwfl_Module *m, { if (it->first < extra_offset) continue; // skip symbols that occur before our chosen base address - + c->output << " { 0x" << hex << it->first-extra_offset << dec << ", " << lex_cast_qstring (it->second) << " }," << endl; } @@ -4481,10 +4481,10 @@ dump_unwindsyms (Dwfl_Module *m, c->output << "struct _stp_module _stp_module_" << stpmod_idx << " = {" << endl; c->output << ".name = " << lex_cast_qstring (modname) << ", " << endl; - c->output << ".sections = _stp_module_" << stpmod_idx << "_sections" << ", " << endl; + c->output << ".sections = _stp_module_" << stpmod_idx << "_sections" << ", " << endl; c->output << ".num_sections = sizeof(_stp_module_" << stpmod_idx << "_sections)/" - << "sizeof(struct _stp_section), " << endl; - + << "sizeof(struct _stp_section), " << endl; + c->output << "};" << endl << endl; c->undone_unwindsym_modules.erase (modname); @@ -4510,7 +4510,7 @@ emit_symbol_data (systemtap_session& s) // XXX: copied from tapsets.cxx, sadly static char debuginfo_path_arr[] = "-:.debug:/usr/lib/debug:build"; static char *debuginfo_env_arr = getenv("SYSTEMTAP_DEBUGINFO_PATH"); - + static char *debuginfo_path = (debuginfo_env_arr ? debuginfo_env_arr : debuginfo_path_arr); static const char *debug_path = (debuginfo_env_arr ? @@ -4524,7 +4524,7 @@ emit_symbol_data (systemtap_session& s) dwfl_offline_section_address, & debuginfo_path }; - + Dwfl *dwfl = dwfl_begin (&kernel_callbacks); if (!dwfl) throw semantic_error ("cannot open dwfl"); @@ -4615,7 +4615,7 @@ translate_pass (systemtap_session& s) try { // This is at the very top of the file. - + s.op->newline() << "#ifndef MAXNESTING"; s.op->newline() << "#define MAXNESTING 10"; s.op->newline() << "#endif"; @@ -4663,7 +4663,7 @@ translate_pass (systemtap_session& s) if (s.bulk_mode) s.op->newline() << "#define STP_BULKMODE"; - + if (s.timing) s.op->newline() << "#define STP_TIMING"; @@ -173,7 +173,7 @@ find_executable(const char *name, string& retpath) if (!p) return false; path = p; - + // Split PATH up. tokenize(path, dirs, string(":")); @@ -215,8 +215,8 @@ const string cmdstr_quoted(const string& cmd) string::size_type pos = 0; quoted_cmd += quote; - for (string::size_type quote_pos = cmd.find(quote, pos); - quote_pos != string::npos; + for (string::size_type quote_pos = cmd.find(quote, pos); + quote_pos != string::npos; quote_pos = cmd.find(quote, pos)) { quoted_cmd += cmd.substr(pos, quote_pos - pos); quoted_cmd += replace; @@ -27,7 +27,7 @@ stringify(T t) } -template <typename OUT, typename IN> +template <typename OUT, typename IN> inline OUT lex_cast(IN const & in) { std::stringstream ss; @@ -39,7 +39,7 @@ inline OUT lex_cast(IN const & in) } -template <typename OUT, typename IN> +template <typename OUT, typename IN> inline OUT lex_cast_hex(IN const & in) { @@ -54,7 +54,7 @@ lex_cast_hex(IN const & in) // Return as quoted string, so that when compiled as a C literal, it // would print to the user out nicely. -template <typename IN> +template <typename IN> inline std::string lex_cast_qstring(IN const & in) { @@ -74,7 +74,7 @@ lex_cast_qstring(IN const & in) out2 += "01234567" [(c >> 6) & 0x07]; out2 += "01234567" [(c >> 3) & 0x07]; out2 += "01234567" [(c >> 0) & 0x07]; - } + } else if (c == '"' || c == '\\') { out2 += '\\'; |