diff options
-rw-r--r-- | ChangeLog | 24 | ||||
-rw-r--r-- | elaborate.cxx | 180 | ||||
-rw-r--r-- | runtime/ChangeLog | 5 | ||||
-rw-r--r-- | runtime/task_finder.c | 126 | ||||
-rw-r--r-- | staptree.cxx | 8 | ||||
-rw-r--r-- | staptree.h | 4 | ||||
-rw-r--r-- | tapset/ChangeLog | 7 | ||||
-rw-r--r-- | tapset/tcp.stp | 65 | ||||
-rw-r--r-- | tapsets.cxx | 34 | ||||
-rw-r--r-- | testsuite/ChangeLog | 10 | ||||
-rwxr-xr-x | testsuite/semko/twelve.stp | 4 | ||||
-rwxr-xr-x | testsuite/semok/optimize.stp | 18 | ||||
-rwxr-xr-x | testsuite/semok/twenty.stp | 2 | ||||
-rw-r--r-- | testsuite/systemtap.base/cache.exp | 4 | ||||
-rw-r--r-- | testsuite/systemtap.base/maxactive.exp | 6 | ||||
-rw-r--r-- | testsuite/systemtap.base/warnings.exp | 4 | ||||
-rw-r--r-- | testsuite/systemtap.examples/ChangeLog | 3 | ||||
-rw-r--r-- | testsuite/systemtap.examples/check.exp | 75 | ||||
-rw-r--r-- | testsuite/systemtap.pass1-4/buildok.exp | 2 | ||||
-rwxr-xr-x | testsuite/transok/eight.stp | 3 |
20 files changed, 437 insertions, 147 deletions
@@ -1,3 +1,25 @@ +2008-04-29 Frank Ch. Eigler <fche@elastic.org> + + PR 6466 + * elaborate.cxx + (dead_stmtexpr_remover): Expand scope to kill far more + side-effect-free statemnets, including if/for/foreach. + (semantic_pass_opt4): Warn on elided function/probe bodies. + (typeresolution_info::visit_target_symbol): Dump parse tree of + resolution-challenged functions/probes. + (*): Adapt to probe->body being a statement* + rather than a block*. + * tapsets.cxx (*): Ditto. + * staptree.cxx (block::block ctor): New cons constructor. + * staptree.h: Corresponding changes. + +2008-04-29 David Smith <dsmith@redhat.com> + + * tapsets.cxx (utrace_derived_probe_group::emit_probe_decl): Added + death event handlers to ensure that for every utrace_attach there + is a corresponding utrace_detach. + (utrace_derived_probe_group::emit_module_decls): Ditto. + 2008-04-28 Frank Ch. Eigler <fche@elastic.org> * translate.cxx (translate_pass): Don't #define TEST_MODE. @@ -11,6 +33,8 @@ * systemtap.spec.in: Simplify configuration defaults. +2008-04-29 David Smith <dsmith@redhat.com>:ChangeLog + 2008-04-25 David Smith <dsmith@redhat.com> PR 6455. diff --git a/elaborate.cxx b/elaborate.cxx index 5a794128..306baff1 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -492,7 +492,6 @@ alias_expansion_builder // the token location of the alias, n->tok = location->tok; - n->body->tok = location->tok; // and statements representing the concatenation of the alias' // body with the use's. @@ -503,25 +502,9 @@ alias_expansion_builder // resulting variable. if (alias->epilogue_style) - { - for (unsigned i = 0; i < use->body->statements.size(); ++i) - n->body->statements.push_back - (deep_copy_visitor::deep_copy(use->body->statements[i])); - - for (unsigned i = 0; i < alias->body->statements.size(); ++i) - n->body->statements.push_back - (deep_copy_visitor::deep_copy(alias->body->statements[i])); - } + n->body = new block (use->body, alias->body); else - { - for (unsigned i = 0; i < alias->body->statements.size(); ++i) - n->body->statements.push_back - (deep_copy_visitor::deep_copy(alias->body->statements[i])); - - for (unsigned i = 0; i < use->body->statements.size(); ++i) - n->body->statements.push_back - (deep_copy_visitor::deep_copy(use->body->statements[i])); - } + n->body = new block (alias->body, use->body); derive_probes (sess, n, finished_results, location->optional); } @@ -1041,7 +1024,7 @@ semantic_pass_conditions (systemtap_session & sess) notex->tok = e->tok; notex->operand = e; ifs->condition = notex; - p->body->statements.insert (p->body->statements.begin(), ifs); + p->body = new block (ifs, p->body); } } @@ -1799,6 +1782,7 @@ struct dead_stmtexpr_remover: public traversing_visitor session(s), relaxed_p(r), current_stmt(0) {} void visit_block (block *s); + void visit_null_statement (null_statement *s); void visit_if_statement (if_statement* s); void visit_foreach_loop (foreach_loop *s); void visit_for_loop (for_loop *s); @@ -1809,15 +1793,44 @@ struct dead_stmtexpr_remover: public traversing_visitor void +dead_stmtexpr_remover::visit_null_statement (null_statement *s) +{ + // easy! + if (session.verbose>2) + clog << "Eliding side-effect-free null statement " << *s->tok << endl; + *current_stmt = 0; +} + + +void dead_stmtexpr_remover::visit_block (block *s) { - for (unsigned i=0; i<s->statements.size(); i++) + vector<statement*> new_stmts; + for (unsigned i=0; i<s->statements.size(); i++ ) { statement** last_stmt = current_stmt; current_stmt = & s->statements[i]; s->statements[i]->visit (this); + if (*current_stmt != 0) + new_stmts.push_back (*current_stmt); current_stmt = last_stmt; } + if (new_stmts.size() == 0) + { + if (session.verbose>2) + clog << "Eliding side-effect-free empty block " << *s->tok << endl; + *current_stmt = 0; + } + else if (new_stmts.size() == 1) + { + if (session.verbose>2) + clog << "Eliding side-effect-free singleton block " << *s->tok << endl; + *current_stmt = new_stmts[0]; + } + else + { + s->statements = new_stmts; + } } void @@ -1826,12 +1839,36 @@ dead_stmtexpr_remover::visit_if_statement (if_statement *s) statement** last_stmt = current_stmt; current_stmt = & s->thenblock; s->thenblock->visit (this); + if (s->elseblock) { current_stmt = & s->elseblock; s->elseblock->visit (this); + // null *current_stmt is OK here. } current_stmt = last_stmt; + + if (s->elseblock == 0 && s->thenblock == 0) + { + // We may be able to elide this statement, if the condition + // expression is side-effect-free. + varuse_collecting_visitor vct; + s->condition->visit(& vct); + if (vct.side_effect_free ()) + { + if (session.verbose>2) + clog << "Eliding side-effect-free if statement " << *s->tok << endl; + *current_stmt = 0; // yeah, baby + return; + } + } + + if (s->thenblock == 0) + { + // Can't elide this whole if/else statement; put a null in there. + s->thenblock = new null_statement(); + s->thenblock->tok = s->tok; + } } void @@ -1841,6 +1878,13 @@ dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s) current_stmt = & s->block; s->block->visit (this); current_stmt = last_stmt; + + if (s->block == 0) + { + if (session.verbose>2) + clog << "Eliding side-effect-free foreach statement " << *s->tok << endl; + *current_stmt = 0; // yeah, baby + } } void @@ -1850,6 +1894,27 @@ dead_stmtexpr_remover::visit_for_loop (for_loop *s) current_stmt = & s->block; s->block->visit (this); current_stmt = last_stmt; + + if (s->block == 0) + { + // We may be able to elide this statement, if the condition + // expression is side-effect-free. + varuse_collecting_visitor vct; + if (s->init) s->init->visit(& vct); + s->cond->visit(& vct); + if (s->incr) s->incr->visit(& vct); + if (vct.side_effect_free ()) + { + if (session.verbose>2) + clog << "Eliding side-effect-free for statement " << *s->tok << endl; + *current_stmt = 0; // yeah, baby + return; + } + + // Can't elide this whole statement; put a null in there. + s->block = new null_statement(); + s->block->tok = s->tok; + } } @@ -1886,14 +1951,10 @@ dead_stmtexpr_remover::visit_expr_statement (expr_statement *s) clog << "Eliding side-effect-free expression " << *s->tok << endl; - null_statement* ns = new null_statement; - ns->tok = s->tok; - * current_stmt = ns; - // XXX: A null_statement carries more weight in the translator's - // output than a nonexistent statement. It might be nice to - // work a little harder and completely eliminate all traces of - // an elided statement. - + // NB: this 0 pointer is invalid to leave around for any length of + // time, but the parent parse tree objects above handle it. + * current_stmt = 0; + relaxed_p = false; } } @@ -1910,23 +1971,48 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) for (unsigned i=0; i<s.probes.size(); i++) { + derived_probe* p = s.probes[i]; + duv.focal_vars.clear (); duv.focal_vars.insert (s.globals.begin(), s.globals.end()); - duv.focal_vars.insert (s.probes[i]->locals.begin(), - s.probes[i]->locals.end()); - s.probes[i]->body->visit (& duv); + duv.focal_vars.insert (p->locals.begin(), + p->locals.end()); + + duv.current_stmt = & p->body; + p->body->visit (& duv); + if (p->body == 0) + { + if (! s.suppress_warnings) + clog << "WARNING: side-effect-free probe '" << p->name << "' " + << *p->tok << endl; + + p->body = new null_statement(); + p->body->tok = p->tok; + } } for (unsigned i=0; i<s.functions.size(); i++) { + functiondecl* fn = s.functions[i]; duv.focal_vars.clear (); - duv.focal_vars.insert (s.functions[i]->locals.begin(), - s.functions[i]->locals.end()); - duv.focal_vars.insert (s.functions[i]->formal_args.begin(), - s.functions[i]->formal_args.end()); + duv.focal_vars.insert (fn->locals.begin(), + fn->locals.end()); + duv.focal_vars.insert (fn->formal_args.begin(), + fn->formal_args.end()); duv.focal_vars.insert (s.globals.begin(), s.globals.end()); - s.functions[i]->body->visit (& duv); + + duv.current_stmt = & fn->body; + fn->body->visit (& duv); + if (fn->body == 0) + { + if (! s.suppress_warnings) + clog << "WARNING: side-effect-free function '" << fn->name << "' " + << *fn->tok << endl; + + fn->body = new null_statement(); + fn->body->tok = fn->tok; + } } } @@ -2509,6 +2595,26 @@ typeresolution_info::visit_target_symbol (target_symbol* e) // later unused-expression-elimination pass didn't get rid of it // either. So we have a target symbol that is believed to be of // genuine use, yet unresolved by the provider. + + if (session.verbose > 2) + { + clog << "Resolution problem with "; + if (current_function) + { + clog << "function " << current_function->name << endl; + current_function->body->print (clog); + clog << endl; + } + else if (current_probe) + { + clog << "probe " << current_probe->name << endl; + current_probe->body->print (clog); + clog << endl; + } + else + clog << "other" << endl; + } + if (e->saved_conversion_error) throw (* (e->saved_conversion_error)); else diff --git a/runtime/ChangeLog b/runtime/ChangeLog index f5df06f9..3eabede9 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,8 @@ +2008-04-29 David Smith <dsmith@redhat.com> + + * task_finder.c: Made more robust by ensuring that all utrace + attaches have a corresponding utrace detach. + 2008-04-28 Frank Ch. Eigler <fche@elastic.org> * runtime.h (TEST_MODE): Remove. diff --git a/runtime/task_finder.c b/runtime/task_finder.c index aafe9c32..915925a3 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -5,6 +5,12 @@ static LIST_HEAD(__stp_task_finder_list); struct stap_task_finder_target; +#define __STP_TF_STARTING 0 +#define __STP_TF_RUNNING 1 +#define __STP_TF_STOPPING 2 +#define __STP_TF_STOPPED 3 +atomic_t __stp_task_finder_state = ATOMIC_INIT(__STP_TF_STARTING); + typedef int (*stap_task_finder_callback)(struct task_struct *tsk, int register_p, struct stap_task_finder_target *tgt); @@ -24,6 +30,10 @@ struct stap_task_finder_target { stap_task_finder_callback callback; }; +static u32 +__stp_utrace_task_finder_target_death(struct utrace_attached_engine *engine, + struct task_struct *tsk); + static int stap_register_task_finder_target(struct stap_task_finder_target *new_tgt) { @@ -39,6 +49,11 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt) else new_tgt->pathlen = 0; + // Make sure everything is initialized properly. + new_tgt->engine_attached = 0; + memset(&new_tgt->ops, 0, sizeof(new_tgt->ops)); + new_tgt->ops.report_death = &__stp_utrace_task_finder_target_death; + // Search the list for an existing entry for pathname/pid. list_for_each(node, &__stp_task_finder_list) { tgt = list_entry(node, struct stap_task_finder_target, list); @@ -63,7 +78,6 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt) } // Add this target to the callback list for this task. - new_tgt->engine_attached = 0; list_add_tail(&new_tgt->callback_list, &tgt->callback_list_head); return 0; } @@ -169,19 +183,23 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen) } #define __STP_UTRACE_TASK_FINDER_EVENTS (UTRACE_EVENT(CLONE) \ - | UTRACE_EVENT(EXEC)) + | UTRACE_EVENT(EXEC) \ + | UTRACE_EVENT(DEATH)) #define __STP_UTRACE_ATTACHED_TASK_EVENTS (UTRACE_EVENT(DEATH)) static u32 -__stp_utrace_task_finder_clone(struct utrace_attached_engine *engine, - struct task_struct *parent, - unsigned long clone_flags, - struct task_struct *child) +__stp_utrace_task_finder_report_clone(struct utrace_attached_engine *engine, + struct task_struct *parent, + unsigned long clone_flags, + struct task_struct *child) { struct utrace_attached_engine *child_engine; struct mm_struct *mm; + if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) + return UTRACE_ACTION_RESUME; + // On clone, attach to the child. Ignore threads with no mm // (which are kernel threads). mm = get_task_mm(child); @@ -201,44 +219,19 @@ __stp_utrace_task_finder_clone(struct utrace_attached_engine *engine, } static u32 -__stp_utrace_task_finder_death(struct utrace_attached_engine *engine, - struct task_struct *tsk) -{ - struct stap_task_finder_target *tgt = engine->data; - - // The first implementation of this added a - // UTRACE_EVENT(DEATH) handler to - // __stp_utrace_task_finder_ops. However, dead threads don't - // have a mm_struct, so we can't find the exe's path. So, we - // don't know which callback(s) to call. - // - // So, now when an "interesting" thread is found, we add a - // separate UTRACE_EVENT(DEATH) handler for every probe. - - if (tgt != NULL && tgt->callback != NULL) { - int rc; - - // Call the callback - rc = tgt->callback(tsk, 0, tgt); - if (rc != 0) { - _stp_error("death callback for %d failed: %d", - (int)tsk->pid, rc); - } - } - return UTRACE_ACTION_RESUME; -} - -static u32 -__stp_utrace_task_finder_exec(struct utrace_attached_engine *engine, - struct task_struct *tsk, - const struct linux_binprm *bprm, - struct pt_regs *regs) +__stp_utrace_task_finder_report_exec(struct utrace_attached_engine *engine, + struct task_struct *tsk, + const struct linux_binprm *bprm, + struct pt_regs *regs) { size_t filelen; struct list_head *tgt_node; struct stap_task_finder_target *tgt; int found_node = 0; + if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) + return UTRACE_ACTION_RESUME; + // On exec, check bprm if (bprm->filename == NULL) return UTRACE_ACTION_RESUME; @@ -276,10 +269,6 @@ __stp_utrace_task_finder_exec(struct utrace_attached_engine *engine, } // Set up thread death notification. - memset(&cb_tgt->ops, 0, sizeof(cb_tgt->ops)); - cb_tgt->ops.report_death - = &__stp_utrace_task_finder_death; - engine = utrace_attach(tsk, UTRACE_ATTACH_CREATE, &cb_tgt->ops, cb_tgt); @@ -298,9 +287,49 @@ __stp_utrace_task_finder_exec(struct utrace_attached_engine *engine, return UTRACE_ACTION_RESUME; } +static u32 +stap_utrace_task_finder_report_death(struct utrace_attached_engine *engine, + struct task_struct *tsk) +{ + return UTRACE_ACTION_DETACH; +} + +static u32 +__stp_utrace_task_finder_target_death(struct utrace_attached_engine *engine, + struct task_struct *tsk) +{ + struct stap_task_finder_target *tgt = engine->data; + + if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) { + return UTRACE_ACTION_DETACH; + } + + // The first implementation of this added a + // UTRACE_EVENT(DEATH) handler to + // __stp_utrace_task_finder_ops. However, dead threads don't + // have a mm_struct, so we can't find the exe's path. So, we + // don't know which callback(s) to call. + // + // So, now when an "interesting" thread is found, we add a + // separate UTRACE_EVENT(DEATH) handler for every probe. + + if (tgt != NULL && tgt->callback != NULL) { + int rc; + + // Call the callback + rc = tgt->callback(tsk, 0, tgt); + if (rc != 0) { + _stp_error("death callback for %d failed: %d", + (int)tsk->pid, rc); + } + } + return UTRACE_ACTION_DETACH; +} + struct utrace_engine_ops __stp_utrace_task_finder_ops = { - .report_clone = __stp_utrace_task_finder_clone, - .report_exec = __stp_utrace_task_finder_exec, + .report_clone = __stp_utrace_task_finder_report_clone, + .report_exec = __stp_utrace_task_finder_report_exec, + .report_death = stap_utrace_task_finder_report_death, }; int @@ -316,6 +345,9 @@ stap_start_task_finder(void) return ENOMEM; } + atomic_set(&__stp_task_finder_state, __STP_TF_RUNNING); + printk(KERN_ERR "SYSTEMTAP: in RUNNING state\n"); + rcu_read_lock(); for_each_process(tsk) { struct utrace_attached_engine *engine; @@ -398,10 +430,6 @@ stap_start_task_finder(void) } // Set up thread death notification. - memset(&cb_tgt->ops, 0, sizeof(cb_tgt->ops)); - cb_tgt->ops.report_death - = &__stp_utrace_task_finder_death; - engine = utrace_attach(tsk, UTRACE_ATTACH_CREATE, &cb_tgt->ops, cb_tgt); @@ -426,6 +454,8 @@ stap_start_task_finder(void) static void stap_stop_task_finder(void) { + atomic_set(&__stp_task_finder_state, __STP_TF_STOPPING); stap_utrace_detach_ops(&__stp_utrace_task_finder_ops); __stp_task_finder_cleanup(); + atomic_set(&__stp_task_finder_state, __STP_TF_STOPPED); } diff --git a/staptree.cxx b/staptree.cxx index 39f5580e..02a6c8dc 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -801,6 +801,14 @@ void block::print (ostream& o) const o << "}"; } +block::block (statement* car, statement* cdr) +{ + statements.push_back(car); + statements.push_back(cdr); + this->tok = car->tok; +} + + void for_loop::print (ostream& o) const { @@ -470,6 +470,8 @@ struct block: public statement std::vector<statement*> statements; void print (std::ostream& o) const; void visit (visitor* u); + block () {} + block (statement* car, statement* cdr); }; @@ -605,7 +607,7 @@ std::ostream& operator << (std::ostream& o, const probe_point& k); struct probe { std::vector<probe_point*> locations; - block* body; + statement* body; const token* tok; std::vector<vardecl*> locals; std::vector<vardecl*> unused_locals; diff --git a/tapset/ChangeLog b/tapset/ChangeLog index f269b468..cf41c9cb 100644 --- a/tapset/ChangeLog +++ b/tapset/ChangeLog @@ -1,3 +1,10 @@ +2008-04-29 Frank Ch. Eigler <fche@elastic.org> + + PR 6466 + * tcp.stp (tcp_sockstate_str, tcp_sockopt_str): Initialize + number->string lookup tables here, instead of "probe begin(-1)" + block that can be elided/warned. + 2008-04-16 Wenji Huang <wenji.huang@oracle.com> * scsi.stp (scsi.iodispatching): Correct for 2.6.25 kernel. diff --git a/tapset/tcp.stp b/tapset/tcp.stp index 3c3bd23b..7fa48000 100644 --- a/tapset/tcp.stp +++ b/tapset/tcp.stp @@ -71,7 +71,23 @@ function tcp_ts_get_info_state:long(sock:long) CATCH_DEREF_FAULT(); %} +global sockstate[13], sockstate_init_p function tcp_sockstate_str:string (state:long) { + if (! sockstate_init_p) { + sockstate_init_p = 1 + sockstate[1] = "TCP_ESTABLISHED" + sockstate[2] = "TCP_SYN_SENT" + sockstate[3] = "TCP_SYN_RECV" + sockstate[4] = "TCP_FIN_WAIT1" + sockstate[5] = "TCP_FIN_WAIT2" + sockstate[6] = "TCP_TIME_WAIT" + sockstate[7] = "TCP_CLOSE" + sockstate[8] = "TCP_CLOSE_WAIT" + sockstate[9] = "TCP_LAST_ACK" + sockstate[10] = "TCP_LISTEN" + sockstate[11] = "TCP_CLOSING" + sockstate[12] = "TCP_MAX_STATES" + } return (state in sockstate ? sockstate[state] : "UNDEF") } @@ -105,7 +121,25 @@ function tcp_ts_get_info_rcv_mss:long(sock:long) CATCH_DEREF_FAULT(); %} +global sockopt[15], sockopt_init_p function tcp_sockopt_str:string (optname:long) { + if (!sockopt_init_p) { + sockopt_init_p=1 + sockopt[1] = "TCP_NODELAY" + sockopt[2] = "TCP_MAXSEG" + sockopt[3] = "TCP_CORK" + sockopt[4] = "TCP_KEEPIDLE" + sockopt[5] = "TCP_KEEPINTVL" + sockopt[6] = "TCP_KEEPCNT" + sockopt[7] = "TCP_SYNCNT" + sockopt[8] = "TCP_LINGER2" + sockopt[9] = "TCP_DEFER_ACCEPT" + sockopt[10] = "TCP_WINDOW_CLAMP" + sockopt[11] = "TCP_INFO" + sockopt[12] = "TCP_QUICKACK" + sockopt[13] = "TCP_CONGESTION" + sockopt[14] = "TCP_MD5SIG" + } return (optname in sockopt ? sockopt[optname] : "UNDEF") } @@ -257,34 +291,3 @@ probe tcp.setsockopt.return = kernel.function("tcp_setsockopt").return { ret = $return } -global sockopt[15], sockstate[13] - -probe begin(-1) { - sockopt[1] = "TCP_NODELAY" - sockopt[2] = "TCP_MAXSEG" - sockopt[3] = "TCP_CORK" - sockopt[4] = "TCP_KEEPIDLE" - sockopt[5] = "TCP_KEEPINTVL" - sockopt[6] = "TCP_KEEPCNT" - sockopt[7] = "TCP_SYNCNT" - sockopt[8] = "TCP_LINGER2" - sockopt[9] = "TCP_DEFER_ACCEPT" - sockopt[10] = "TCP_WINDOW_CLAMP" - sockopt[11] = "TCP_INFO" - sockopt[12] = "TCP_QUICKACK" - sockopt[13] = "TCP_CONGESTION" - sockopt[14] = "TCP_MD5SIG" - - sockstate[1] = "TCP_ESTABLISHED" - sockstate[2] = "TCP_SYN_SENT" - sockstate[3] = "TCP_SYN_RECV" - sockstate[4] = "TCP_FIN_WAIT1" - sockstate[5] = "TCP_FIN_WAIT2" - sockstate[6] = "TCP_TIME_WAIT" - sockstate[7] = "TCP_CLOSE" - sockstate[8] = "TCP_CLOSE_WAIT" - sockstate[9] = "TCP_LAST_ACK" - sockstate[10] = "TCP_LISTEN" - sockstate[11] = "TCP_CLOSING" - sockstate[12] = "TCP_MAX_STATES" -} diff --git a/tapsets.cxx b/tapsets.cxx index d98595d5..4aac4488 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -3607,7 +3607,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) expr_statement* es = new expr_statement; es->tok = e->tok; es->value = a; - add_probe->body->statements.push_back (es); + add_probe->body = new block(add_probe->body, es); vardecl* vd = new vardecl; vd->tok = e->tok; @@ -3640,7 +3640,7 @@ dwarf_var_expanding_copy_visitor::visit_target_symbol (target_symbol *e) es->tok = e->tok; es->value = a; - add_probe->body->statements.push_back (es); + add_probe->body = new block(add_probe->body, es); // (4) Provide the '_dwarf_tvar_{name}_{num}_tmp' variable to // our parent so it can be used as a substitute for the target @@ -3813,12 +3813,12 @@ dwarf_derived_probe::dwarf_derived_probe(const string& funcname, if (scope_die) { dwarf_var_expanding_copy_visitor v (q, scope_die, dwfl_addr); - require <block*> (&v, &(this->body), this->body); + require <statement*> (&v, &(this->body), this->body); // If during target-variable-expanding the probe, we added a new block // of code, add it to the start of the probe. if (v.add_block) - this->body->statements.insert(this->body->statements.begin(), v.add_block); + this->body = new block(v.add_block, this->body); // If when target-variable-expanding the probe, we added a new // probe, add it in a new file to the list of files to be processed. @@ -4429,7 +4429,7 @@ utrace_derived_probe::utrace_derived_probe (systemtap_session &s, { // Make a local-variable-expanded copy of the probe body utrace_var_expanding_copy_visitor v (s, name, flags); - require <block*> (&v, &(this->body), base->body); + require <statement*> (&v, &(this->body), base->body); target_symbol_seen = v.target_symbol_seen; } @@ -4640,8 +4640,8 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s, switch (p->flags) { case UDPF_CLONE: - s.op->line() << " .ops={ .report_clone=stap_utrace_probe_clone },"; - s.op->line() << " .flags=(UTRACE_EVENT(CLONE)),"; + s.op->line() << " .ops={ .report_clone=stap_utrace_probe_clone, .report_death=stap_utrace_task_finder_report_death },"; + s.op->line() << " .flags=(UTRACE_EVENT(CLONE)|UTRACE_EVENT(DEATH)),"; break; case UDPF_EXEC: // Notice we're not setting up a .ops/.report_exec handler here. @@ -4656,12 +4656,12 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s, s.op->line() << " .flags=(UTRACE_EVENT(DEATH)),"; break; case UDPF_SYSCALL_ENTRY: - s.op->line() << " .ops={ .report_syscall_entry=stap_utrace_probe_syscall },"; - s.op->line() << " .flags=(UTRACE_EVENT(SYSCALL_ENTRY)),"; + s.op->line() << " .ops={ .report_syscall_entry=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death },"; + s.op->line() << " .flags=(UTRACE_EVENT(SYSCALL_ENTRY)|UTRACE_EVENT(DEATH)),"; break; case UDPF_SYSCALL_EXIT: - s.op->line() << " .ops={ .report_syscall_exit=stap_utrace_probe_syscall },"; - s.op->line() << " .flags=(UTRACE_EVENT(SYSCALL_EXIT)),"; + s.op->line() << " .ops={ .report_syscall_exit=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death },"; + s.op->line() << " .flags=(UTRACE_EVENT(SYSCALL_EXIT)|UTRACE_EVENT(DEATH)),"; break; default: throw semantic_error ("bad utrace probe flag"); @@ -4784,9 +4784,9 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) if (flags_seen[UDPF_CLONE] || flags_seen[UDPF_SYSCALL_ENTRY] || flags_seen[UDPF_SYSCALL_EXIT]) { - s.op->newline() << "case UTRACE_EVENT(CLONE):"; - s.op->newline() << "case UTRACE_EVENT(SYSCALL_ENTRY):"; - s.op->newline() << "case UTRACE_EVENT(SYSCALL_EXIT):"; + s.op->newline() << "case (UTRACE_EVENT(CLONE)|UTRACE_EVENT(DEATH)):"; + s.op->newline() << "case (UTRACE_EVENT(SYSCALL_ENTRY)|UTRACE_EVENT(DEATH)):"; + s.op->newline() << "case (UTRACE_EVENT(SYSCALL_EXIT)|UTRACE_EVENT(DEATH)):"; s.op->indent(1); s.op->newline() << "engine = utrace_attach(tsk, UTRACE_ATTACH_CREATE, &p->ops, p);"; s.op->newline() << "if (IS_ERR(engine)) {"; @@ -5446,7 +5446,7 @@ procfs_derived_probe::procfs_derived_probe (systemtap_session &s, probe* p, { // Make a local-variable-expanded copy of the probe body procfs_var_expanding_copy_visitor v (s, name, path, write); - require <block*> (&v, &(this->body), base->body); + require <statement*> (&v, &(this->body), base->body); target_symbol_seen = v.target_symbol_seen; } @@ -6106,7 +6106,7 @@ mark_derived_probe::mark_derived_probe (systemtap_session &s, // Now make a local-variable-expanded copy of the probe body mark_var_expanding_copy_visitor v (sess, name, mark_args); - require <block*> (&v, &(this->body), base->body); + require <statement*> (&v, &(this->body), base->body); target_symbol_seen = v.target_symbol_seen; if (sess.verbose > 2) @@ -7004,7 +7004,7 @@ perfmon_derived_probe::perfmon_derived_probe (probe* p, probe_point* l, // Now make a local-variable-expanded copy of the probe body perfmon_var_expanding_copy_visitor v (sess, probes_allocated-1); - require <block*> (&v, &(this->body), base->body); + require <statement*> (&v, &(this->body), base->body); if (sess.verbose > 1) clog << "perfmon-based probe" << endl; diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog index b8fe2db6..c951971b 100644 --- a/testsuite/ChangeLog +++ b/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2008-04-29 Frank Ch. Eigler <fche@elastic.org> + + PR 6466. + * semko/twelve.stp, semok/twenty.stp, systemtap.base/cache.exp, + systemtap.base/maxactive.exp, systemtap.base/warnings.exp, + transok/eight.stp: Adapt to new elision capabilities; add new + side-effects or -w warning-suppression flags. + * systemtap.pass1-4/buildok.exp: Remove two kfails. + * semok/optimize.stp: Test new elision. + 2008-04-24 Will Cohen <wcohen@redhat.com> * systemtap.examples: examples moved into testsuite. diff --git a/testsuite/semko/twelve.stp b/testsuite/semko/twelve.stp index ab71d579..c91eb743 100755 --- a/testsuite/semko/twelve.stp +++ b/testsuite/semko/twelve.stp @@ -1,6 +1,6 @@ #! stap -p2 probe end { - for (a=0; "hello";) {} - while ("goodbye") {} + for (a=0; "hello";) {println("hello")} + while ("goodbye") {println("world")} } diff --git a/testsuite/semok/optimize.stp b/testsuite/semok/optimize.stp index bcf8ac04..a728bd66 100755 --- a/testsuite/semok/optimize.stp +++ b/testsuite/semok/optimize.stp @@ -1,4 +1,4 @@ -#! stap -p2 +#! stap -wp2 # We count on the optimizer to blow away these ridiculous # expressions, since they have no effect on the output. @@ -21,3 +21,19 @@ probe begin { probe begin{for(i=1;i-=2;i++);} probe begin{while(i+=2);} probe begin{if(i=j);} + +global ii +probe begin{for(ii=1;ii-=2;ii++);} +probe begin{while(ii+=2);} +probe begin{if(ii=j);} + +# bug #6466 +global goo + +probe begin { while (24) ; } +probe begin { for (2<$i; zoo(333); poo) ; } +probe begin { foreach (x in goo) goo[x]+1; } +probe begin { foo = $bar; if (foo) {} } +probe begin { { { { } } } } +function useful () { return 1 } +probe begin { println (useful()) } /* don't elide this one! */ diff --git a/testsuite/semok/twenty.stp b/testsuite/semok/twenty.stp index 2e85c5e6..46dcefca 100755 --- a/testsuite/semok/twenty.stp +++ b/testsuite/semok/twenty.stp @@ -1,4 +1,4 @@ -#! stap -p2 +#! stap -wp2 probe kernel.function("*") {} probe module("*").function("*") {} diff --git a/testsuite/systemtap.base/cache.exp b/testsuite/systemtap.base/cache.exp index eaa5ca82..26d7b0ef 100644 --- a/testsuite/systemtap.base/cache.exp +++ b/testsuite/systemtap.base/cache.exp @@ -74,8 +74,8 @@ if [info exists env(SYSTEMTAP_DIR)] { set env(SYSTEMTAP_DIR) $local_systemtap_dir # Set up the scripts we'll use. -set basic_script1 "\"probe begin { }\"" -set basic_script2 "\"probe begin, end { }\"" +set basic_script1 "\"probe begin { println(1) }\"" +set basic_script2 "\"probe begin, end { println(2) }\"" set error_script "\"probe XbeginX { }\"" # Check basic functionality. The 1st compilation of a script won't diff --git a/testsuite/systemtap.base/maxactive.exp b/testsuite/systemtap.base/maxactive.exp index ca95ac53..7c03a1bf 100644 --- a/testsuite/systemtap.base/maxactive.exp +++ b/testsuite/systemtap.base/maxactive.exp @@ -13,8 +13,9 @@ proc sleep_five_sec {} { # Script1. For 5 seconds, probe the return of "sys_select" and # "sys_read". See if we skip any probes. set script1 { + global foo probe kernel.function("sys_select").return, - kernel.function("sys_read").return { } + kernel.function("sys_read").return { foo++ } probe timer.ms(5000) { exit(); } probe begin { log("systemtap starting probe"); log("systemtap ending probe");} @@ -29,8 +30,9 @@ set skipped1 $skipped_probes # "sys_read", with a limit of 1 probe active at a time. See if we # skip any probes. set script2 { + global foo probe kernel.function("sys_select").return.maxactive(1), - kernel.function("sys_read").return.maxactive(1) { } + kernel.function("sys_read").return.maxactive(1) { foo++ } probe timer.ms(5000) { exit(); } probe begin { log("systemtap starting probe"); log("systemtap ending probe");} diff --git a/testsuite/systemtap.base/warnings.exp b/testsuite/systemtap.base/warnings.exp index 90409d18..025bde89 100644 --- a/testsuite/systemtap.base/warnings.exp +++ b/testsuite/systemtap.base/warnings.exp @@ -9,8 +9,8 @@ expect { eof { } } wait -if {$ok == 6} { +if {$ok == 9} { pass $test } else { - fail $test + fail "$test ($ok)" } diff --git a/testsuite/systemtap.examples/ChangeLog b/testsuite/systemtap.examples/ChangeLog index 78083901..c85a43ee 100644 --- a/testsuite/systemtap.examples/ChangeLog +++ b/testsuite/systemtap.examples/ChangeLog @@ -1,3 +1,6 @@ +2008-04-27 William Cohen <wcohen@redhat.com> + + * check.exp: New script to run tests on cataloged examples. 2008-03-09 Wenji Huang <wenji.huang@oracle.com> diff --git a/testsuite/systemtap.examples/check.exp b/testsuite/systemtap.examples/check.exp new file mode 100644 index 00000000..2ac43050 --- /dev/null +++ b/testsuite/systemtap.examples/check.exp @@ -0,0 +1,75 @@ +# check.exp +# +# This script searches the systemtap.examples directory for .meta files +# The .meta files contain information categorizing the script. The +# .meta files are composed of lines of tags. Each tag is followed by a +# value. + +#open the file and read in all the lines of data in FILE +#return a string with the data +proc get_meta_data { FILE } { + set meta_data "" + + if [catch {open "$FILE" RDONLY} fl] { + puts "open $FILE failed: $err" + return "" + } else { + set meta_data [read -nonewline $fl] + close $fl + return "$meta_data" + } +} + +#extract value for TAG from string META_DATA +#if there is no matching tag return "" +proc extract_tag { META_DATA TAG } { + set taglines "" + set value "" + set expr "^$TAG:\[^\$\]*" + regexp -line -all $expr $META_DATA taglines + set expr "$TAG:" + regsub -line $expr $taglines "" value + return $value +} + +set curdir [pwd] + +set src_examples $srcdir/systemtap.examples +set meta_files [lsort [exec find $src_examples -path "*.meta"]] +foreach file $meta_files { + set dir [file dirname $file] + set test [regsub {.*/testsuite/} $file ""] + + cd $dir + + set meta_data [get_meta_data $file] + set test_check [extract_tag "$meta_data" "test_check"] + set test_installcheck [extract_tag "$meta_data" "test_installcheck"] + # Would like to run the tests (-p5), but pass fail logic too + # simple and fails for many examples + # FIXME following line prevents installcheck with "--tools_opts install" + set test_installcheck "" + if {[info procs installtest_p] != "" && [installtest_p] + && $test_installcheck != "" } then { + set command $test_installcheck + } else { + set command $test_check + } + + #FIXME tcl says that single quotes not dealt with + if { $command != "" } then { + verbose -log "attempting command $command" + set res [catch {eval exec $command} value] + verbose -log "OUT $value" + verbose -log "RC $res" + if {$res != 0 } { + fail $test + } else { + pass $test + } + } else { + untested $test + } +} + +cd $curdir diff --git a/testsuite/systemtap.pass1-4/buildok.exp b/testsuite/systemtap.pass1-4/buildok.exp index 77e77181..07580550 100644 --- a/testsuite/systemtap.pass1-4/buildok.exp +++ b/testsuite/systemtap.pass1-4/buildok.exp @@ -8,9 +8,7 @@ foreach file [lsort [glob -nocomplain $srcdir/$self/*.stp]] { buildok/perfmon01.stp {setup_kfail 909 *-*-*} buildok/twentysix.stp {setup_kfail 4105 *-*-*} buildok/twentyseven.stp {setup_kfail 4166 *-*-*} - buildok/process_test.stp {setup_kfail 1155 *-*-*} buildok/sched_test.stp {setup_kfail 1155 *-*-*} - buildok/socket.stp {setup_kfail 4413 *-*-*} } if {$rc == 0} { pass $test } else { fail $test } } diff --git a/testsuite/transok/eight.stp b/testsuite/transok/eight.stp index 6723b993..9198536e 100755 --- a/testsuite/transok/eight.stp +++ b/testsuite/transok/eight.stp @@ -2,10 +2,11 @@ global foo global baz +global zoo function bar() { - return foo["hello"] + return foo["hello"]+(zoo++) } probe begin |