summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2008-04-30 09:54:57 -0400
committerFrank Ch. Eigler <fche@elastic.org>2008-04-30 09:54:57 -0400
commit49628242c239feb617b838bb5d90488386645bd6 (patch)
treedb3102573ddc2b12457aa4da3dc8b3f2b4c104cf
parentb167928be06ff251ff9a6f2f0c528dd3ece527df (diff)
parentba6f838d2471c57fc3d8fc6d325766ff95ce108a (diff)
downloadsystemtap-steved-49628242c239feb617b838bb5d90488386645bd6.tar.gz
systemtap-steved-49628242c239feb617b838bb5d90488386645bd6.tar.xz
systemtap-steved-49628242c239feb617b838bb5d90488386645bd6.zip
Merge branch 'master' into pr6429-comp-unwindsyms
* master: PR6466: broad side-effect free statement elision Made utrace probes more robust. 2008-04-27 William Cohen <wcohen@redhat.com> 2008-04-27 William Cohen <wcohen@redhat.com>
-rw-r--r--ChangeLog24
-rw-r--r--elaborate.cxx180
-rw-r--r--runtime/ChangeLog5
-rw-r--r--runtime/task_finder.c126
-rw-r--r--staptree.cxx8
-rw-r--r--staptree.h4
-rw-r--r--tapset/ChangeLog7
-rw-r--r--tapset/tcp.stp65
-rw-r--r--tapsets.cxx34
-rw-r--r--testsuite/ChangeLog10
-rwxr-xr-xtestsuite/semko/twelve.stp4
-rwxr-xr-xtestsuite/semok/optimize.stp18
-rwxr-xr-xtestsuite/semok/twenty.stp2
-rw-r--r--testsuite/systemtap.base/cache.exp4
-rw-r--r--testsuite/systemtap.base/maxactive.exp6
-rw-r--r--testsuite/systemtap.base/warnings.exp4
-rw-r--r--testsuite/systemtap.examples/ChangeLog3
-rw-r--r--testsuite/systemtap.examples/check.exp75
-rw-r--r--testsuite/systemtap.pass1-4/buildok.exp2
-rwxr-xr-xtestsuite/transok/eight.stp3
20 files changed, 437 insertions, 147 deletions
diff --git a/ChangeLog b/ChangeLog
index b411d33e..a18df886 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
{
diff --git a/staptree.h b/staptree.h
index 136472fd..9adbc822 100644
--- a/staptree.h
+++ b/staptree.h
@@ -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