+2007-12-05 Masami Hiramatsu <mhiramat@redhat.com>
+
+ PR 4935
+ * tapsets.cxx (dwarf_derived_probe::dwarf_derived_probe): Allow user
+ to access kernel variables in the condition of probe points.
+ * stapprobes.5.in : Document the conditional probe point.
+ * NEWS : Ditto.
+
2007-12-03 Masami Hiramatsu <mhiramat@redhat.com>
PR 5376
* What's new in version 0.6 / since version 0.5.15?
+- You can add a conditional statement for each probe point or aliase, which
+ is evaluated when the probe point is hit. If the condition is false, the
+ whole probe body(including aliases) is skipped. For example:
+
+ global switch = 0;
+ probe syscall.* if (switch) { ... }
+ probe procfs.write {switch = strtol($value,10)} /* enable/disable ctrl */
+
- Systemtap will warn you if your script contains unused variables or
functions. This is helpful in case of misspelled variables. If it
doth protest too much, turn it off with "stap -w ...".
resolve, then no further probe points in the same comma-separated list
will be resolved. Therefore, the "!" sufficiency mark only makes
sense in a list of probe point alternatives.
+.PP
+Additionally, a probe point may be followed by a "if (expr)" statement, in
+order to enable/disable the probe point on-the-fly. With the "if" statement,
+if the "expr" is false when the probe point is hit, the whole probe body
+including alias's body is skipped. The condition is stacked up through
+all levels of alias/wildcard expansion. So the final condition becomes
+the logical-and of conditions of all expanded alias/wildcard.
These are all syntactically valid probe points:
syscall.*
kernel.function("no_such_function") ?
module("awol").function("no_such_function") !
+signal.*? if (switch)
.ESAMPLE
Probes may be broadly classified into "synchronous" and
this->tok = q.base_probe->tok;
+ // add condition from base location
+ if (q.base_loc->condition)
+ add_condition (q.base_loc->condition);
+ insert_condition_statement ();
+
// Make a target-variable-expanded copy of the probe body
if (scope_die)
{
dwarf_var_expanding_copy_visitor v (q, scope_die, dwfl_addr);
- require <block*> (&v, &(this->body), q.base_probe->body);
+ require <block*> (&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.
(TOK_MAXACTIVE, new literal_number(maxactive_val)));
locations.push_back(new probe_point(comps, q.base_loc->tok));
- if (q.base_loc->condition)
- add_condition (q.base_loc->condition);
- insert_condition_statement ();
}
+2007-12-05 Masami Hiramatsu <mhiramat@redhat.com>
+
+ PR 4935
+ * parseok/five.stp: Add an example of conditional probe point.
+ * parseko/probepoint04.stp: New test for conditional probe point.
+ * parseko/probepoint05.stp: Ditto.
+ * parseko/probepoint06.stp: Ditto.
+ * parseko/probepoint07.stp: Ditto.
+ * parseko/probepoint08.stp: Ditto.
+ * parseko/probepoint09.stp: Ditto.
+ * semok/twentynine.stp: Ditto.
+ * semko/thirtynine.stp: Ditto.
+ * systemtap.base/onoffprobe.*: Ditto.
+
2007-12-03 Masami Hiramatsu <mhiramat@redhat.com>
PR 5376
--- /dev/null
+#! stap -p1
+
+# bad probe point
+probe foo(5) if (1)?
--- /dev/null
+#! stap -p1
+
+# bad probe point
+probe foo(5) if (1)(10)
--- /dev/null
+#! stap -p1
+
+# bad probe point
+probe if (1) foo(5)
--- /dev/null
+#! stap -p1
+
+# bad probe point
+probe foo(5) if (1(
--- /dev/null
+#! stap -p1
+
+# bad probe point
+probe foo(5) if
--- /dev/null
+#! stap -p1
+
+# bad probe point
+probe foo(5) if(1) bar(2)
probe begin {}
probe something?, or?, nothing? {}
probe something!, or, nothing!, and?, zoo {}
+probe something? if (ture), or, nothing! if (false), then* if (0) {}
--- /dev/null
+#! stap -p2
+
+probe kernel.function("sys_open").if(1) {} /* if statement doesn't need '.'*/
--- /dev/null
+#! stap -p2
+global p
+function dummy:long () {return p;}
+
+# alias with a condition
+probe alias0 = begin if (3) {p=1}
+# alias with a kernel-variable condition
+probe alias1 = kernel.function("sys_read").return if ($return) {p=0}
+# alias with a function-call condition
+probe blias0 = timer.s(1) if (dummy()) {p=10}
+
+# multiple probe point with conditions
+probe alias2 = alias0 if (1), alias1 if (-1) {p=2}
+
+# wildcard with a global-variable condition
+probe *lias0 if (p) {print(p)}
+
+# multi level alias with a condition
+probe alias2 if(4) {print(p)}
+
--- /dev/null
+set test "onoffprobe"
+if {![installtest_p]} { untested $test; return }
+
+spawn stap $srcdir/$subdir/$test.stp -m $test
+set pid $spawn_id
+set ok 0
+expect {
+ -timeout 240
+ "begin probed\r\n" {
+ if {$ok == 0} {
+ incr ok
+ pass "conditional begin probe"
+ exec echo 1 > /proc/systemtap/$test/switch
+ exec echo "dummy" > /dev/null
+ exp_continue;
+ }
+ }
+ "function return probed\r\n" {
+ if {$ok == 1} {
+ incr ok
+ pass "conditional dwarf probe (return)"
+ exec echo 2 > /proc/systemtap/$test/switch
+ exec echo "dummy" > /dev/null
+ exp_continue;
+ }
+ }
+ "function entry probed\r\n" {
+ if {$ok == 2} {
+ incr ok
+ pass "conditional dwarf probe (entry)"
+ exec echo 3 > /proc/systemtap/$test/switch
+ exp_continue;
+ }
+ }
+ "timer probed\r\n" {
+ if {$ok == 3} {
+ incr ok
+ pass "conditional timer probe"
+ exec echo 4 > /proc/systemtap/$test/switch
+ exp_continue;
+ }
+ }
+ "profile probed\r\n" {
+ if {$ok == 4} {
+ incr ok
+ pass "conditional profile probe"
+ }
+ }
+ timeout { fail "$test (timeout)" }
+ eof { }
+}
+send "\003"
+#FIXME does not handle case of hanging pfaults.stp correctly
+wait
+exec rm -f $test.ko
+if {$ok != 5} {fail "conditional probes ($ok)"}
+
--- /dev/null
+global switch=0
+
+#begin probe
+probe begin if (switch==0) {
+ log("begin probed\n");
+}
+
+#dwarf probe (return)
+probe kernel.function("sys_write").return if (switch == 1) {
+ log("function return probed\n")
+ switch = 0
+}
+
+#dwarf probe (entry)
+probe kernel.function("sys_write") if (switch == 2) {
+ log("function entry probed\n")
+ switch = 0
+}
+
+#timer probe
+probe timer.s(1) if (switch == 3) {
+ log("timer probed\n")
+ switch = 0
+}
+
+#profile probe
+probe timer.profile if (switch == 4) {
+ log("profile probed\n")
+ switch = 0
+}
+
+probe procfs("switch").write {
+ switch = strtol($value, 10)
+}
+