summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--NEWS4
-rw-r--r--parse.cxx56
-rw-r--r--stap.1.in13
-rw-r--r--tapset/syscalls2.stp30
-rw-r--r--testsuite/ChangeLog5
-rw-r--r--testsuite/systemtap.base/preprocessor.exp52
7 files changed, 132 insertions, 40 deletions
diff --git a/ChangeLog b/ChangeLog
index fad79819..491d114b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2008-02-26 Srinivasa DS <srinivasa@in.ibm.com>
+ PR5772
+ * tapset/syscall2.stp: Modify wait4,waitid argument list
+ for kernel > 2.6.24.
+
+2008-02-25 Frank Ch. Eigler <fche@elastic.org>
+
+ PR5792.
+ * parse.cxx (eval_pp_conditional): Support wildcards in
+ %( kernel_v/kernel_vr/arch ==/!= "*foo?" %) operands.
+ * NEWS, stap.1.in: Document this.
+
2008-02-22 Frank Ch. Eigler <fche@elastic.org>
PR5787, PR2608, .statement()
diff --git a/NEWS b/NEWS
index 073945e1..df7e27b4 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,9 @@
* What's new in version 0.6 / 0.6.1
+- Preprocessor conditional expressions can now include wildcard style
+ matches on kernel versions.
+ %( kernel_vr != "*xen" %? foo %: bar %)
+
- Prototype support for user-space probing is showing some progress.
No symbolic notations are supported yet (so no probing by function names,
file names, process names, and no access to $context variables), but at
diff --git a/parse.cxx b/parse.cxx
index a829fa10..ea22f36d 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -24,6 +24,9 @@
#include <sstream>
#include <cstring>
#include <cctype>
+extern "C" {
+#include <fnmatch.h>
+}
using namespace std;
@@ -173,10 +176,16 @@ bool eval_pp_conditional (systemtap_session& s,
if (! (r->type == tok_string))
throw parse_error ("expected string literal", r);
- string query_kernel_vr = r->content;
-
+
+ string target = (l->content == "kernel_vr" ?
+ target_kernel_vr.c_str() :
+ target_kernel_v.c_str());
+ string query = r->content;
+ bool rhs_wildcard = (strpbrk (query.c_str(), "*?[") != 0);
+
// collect acceptable strverscmp results.
int rvc_ok1, rvc_ok2;
+ bool wc_ok = false;
if (op->type == tok_operator && op->content == "<=")
{ rvc_ok1 = -1; rvc_ok2 = 0; }
else if (op->type == tok_operator && op->content == ">=")
@@ -186,21 +195,30 @@ bool eval_pp_conditional (systemtap_session& s,
else if (op->type == tok_operator && op->content == ">")
{ rvc_ok1 = 1; rvc_ok2 = 1; }
else if (op->type == tok_operator && op->content == "==")
- { rvc_ok1 = 0; rvc_ok2 = 0; }
+ { rvc_ok1 = 0; rvc_ok2 = 0; wc_ok = true; }
else if (op->type == tok_operator && op->content == "!=")
- { rvc_ok1 = -1; rvc_ok2 = 1; }
+ { rvc_ok1 = -1; rvc_ok2 = 1; wc_ok = true; }
else
throw parse_error ("expected comparison operator", op);
-
- int rvc_result = strverscmp ((l->content == "kernel_vr" ?
- target_kernel_vr.c_str() :
- target_kernel_v.c_str()),
- query_kernel_vr.c_str());
- // normalize rvc_result
- if (rvc_result < 0) rvc_result = -1;
- if (rvc_result > 0) rvc_result = 1;
-
- return (rvc_result == rvc_ok1 || rvc_result == rvc_ok2);
+
+ if ((!wc_ok) && rhs_wildcard)
+ throw parse_error ("wildcard not allowed with order comparison operators", op);
+
+ if (rhs_wildcard)
+ {
+ int rvc_result = fnmatch (query.c_str(), target.c_str(),
+ FNM_NOESCAPE); // spooky
+ bool badness = (rvc_result == 0) ^ (op->content == "==");
+ return !badness;
+ }
+ else
+ {
+ int rvc_result = strverscmp (target.c_str(), query.c_str());
+ // normalize rvc_result
+ if (rvc_result < 0) rvc_result = -1;
+ if (rvc_result > 0) rvc_result = 1;
+ return (rvc_result == rvc_ok1 || rvc_result == rvc_ok2);
+ }
}
else if (l->type == tok_identifier && l->content == "arch")
{
@@ -209,11 +227,15 @@ bool eval_pp_conditional (systemtap_session& s,
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
+
bool result;
if (op->type == tok_operator && op->content == "==")
- result = target_architecture == query_architecture;
+ result = !nomatch;
else if (op->type == tok_operator && op->content == "!=")
- result = target_architecture != query_architecture;
+ result = nomatch;
else
throw parse_error ("expected '==' or '!='", op);
@@ -245,6 +267,8 @@ bool eval_pp_conditional (systemtap_session& s,
if (rvc_result < 0) rvc_result = -1;
if (rvc_result > 0) rvc_result = 1;
+ // NB: no wildcarding option here
+
return (rvc_result == rvc_ok1 || rvc_result == rvc_ok2);
}
else if (l->type == tok_string && r->type == tok_number
diff --git a/stap.1.in b/stap.1.in
index 05eecda2..c557350a 100644
--- a/stap.1.in
+++ b/stap.1.in
@@ -224,6 +224,15 @@ version of the target kernel (as optionally overridden by the
option) compares to the given version string. The comparison is
performed by the glibc function
.BR strverscmp .
+As a special case, if the operator is for simple equality
+.RB ( == ),
+or inequality
+.RB ( != ),
+and the third part contains any wildcard characters
+.RB ( * " or " ? " or " [ "),"
+then the expression is treated as a wildcard (mis)match as evaluated
+by
+.BR fnmatch .
.PP
If, on the other hand, the first part is the identifier
.BR arch
@@ -231,7 +240,7 @@ to refer to the processor architecture, then the second part
then the second part is one of the two string comparison operators
.BR == " or " != ,
and the third part is a string literal for matching it. This
-comparison is simple string (in)equality.
+comparison is a wildcard (mis)match.
.PP
Otherwise, the CONDITION is expected to be a comparison between two string
literals or two numeric literals. In this case, the arguments are the only
@@ -249,7 +258,7 @@ The following code might adapt to hypothetical kernel version drift:
.SAMPLE
probe kernel.function (
%( kernel_v <= "2.6.12" %? "__mm_do_fault" %:
- %( kernel_vr == "2.6.13\-1.8273FC3smp" %? "do_page_fault" %:
+ %( kernel_vr == "2.6.13*smp" %? "do_page_fault" %:
UNSUPPORTED %) %)
) { /* ... */ }
diff --git a/tapset/syscalls2.stp b/tapset/syscalls2.stp
index 80c88707..b0118423 100644
--- a/tapset/syscalls2.stp
+++ b/tapset/syscalls2.stp
@@ -3023,20 +3023,14 @@ probe syscall.compat_vmsplice.return = kernel.function("compat_sys_vmsplice").re
#
probe syscall.wait4 = kernel.function("sys_wait4") {
name = "wait4"
-%( kernel_vr > "2.6.24" %?
- pid = $upid
-%:
- pid = $pid
-%)
+ pid = %( kernel_vr > "2.6.24"%? $upid %: $pid%)
status_uaddr = $stat_addr
options = $options
options_str = _wait4_opt_str($options)
rusage_uaddr = $ru
-%( kernel_vr > "2.6.24" %?
- argstr = sprintf("%d, %p, %s, %p", $upid, $stat_addr, _wait4_opt_str($options), $ru)
-%:
- argstr = sprintf("%d, %p, %s, %p", $pid, $stat_addr, _wait4_opt_str($options), $ru)
-%)
+ argstr = sprintf("%d, %p, %s, %p",
+ %( kernel_vr > "2.6.24"%? $upid %: $pid%),
+ $stat_addr,_wait4_opt_str($options), $ru)
}
probe syscall.wait4.return = kernel.function("sys_wait4").return {
name = "wait4"
@@ -3052,24 +3046,16 @@ probe syscall.wait4.return = kernel.function("sys_wait4").return {
#
probe syscall.waitid = kernel.function("sys_waitid") {
name = "waitid"
+ pid = %( kernel_vr > "2.6.24"%? $upid %: $pid%)
which = $which
which_str = _waitid_which_str($which)
-%( kernel_vr > "2.6.24" %?
- pid = $upid
-%:
- pid = $pid
-%)
infop_uaddr = $infop
options = $options
options_str = _waitid_opt_str($options)
rusage_uaddr = $ru
-%( kernel_vr > "2.6.24" %?
- argstr = sprintf("%d, %d, %p, %s, %p", $which, $upid,
- $infop, _waitid_opt_str($options), $ru)
-%:
- argstr = sprintf("%d, %d, %p, %s, %p", $which, $pid,
- $infop, _waitid_opt_str($options), $ru)
-%)
+ argstr = sprintf("%d, %d, %p, %s, %p", $which,
+ %( kernel_vr > "2.6.24"%? $upid %: $pid%), $infop,
+ _waitid_opt_str($options), $ru)
}
probe syscall.waitid.return = kernel.function("sys_waitid").return {
name = "waitid"
diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog
index c6f7ced8..addab719 100644
--- a/testsuite/ChangeLog
+++ b/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2008-02-25 Frank Ch. Eigler <fche@elastic.org>
+
+ PR5792.
+ * systemtap.base/preprocessor.exp: New test.
+
2008-02-23 Frank Ch. Eigler <fche@elastic.org>
* systemtap.printf/*.exp: Canonicalize pass/fail messages.
diff --git a/testsuite/systemtap.base/preprocessor.exp b/testsuite/systemtap.base/preprocessor.exp
new file mode 100644
index 00000000..4e0c7fc2
--- /dev/null
+++ b/testsuite/systemtap.base/preprocessor.exp
@@ -0,0 +1,52 @@
+
+set kvr [exec uname -r]
+set kv [exec uname -r | cut -f1 -d-]
+# a pattern bound to match
+set kr {2?[0-9]*}
+# a pattern bound to mismatch
+set krx {?noSuchKernel*}
+
+set arch [exec uname -m]
+set ar "?[string range $arch 1 end-1]?"
+set arx {?noSuchArch?}
+
+# This test works so that if all the preprocessor conditionals
+# work as expected, stap will indicate no error.
+
+set test "preprocessor basic ops"
+spawn stap -p2 -e "probe never {}
+%( kernel_v == \"$kv\" %? %: ERROR %)
+%( kernel_v == \"$kr\" %? %: ERROR %)
+%( kernel_v == \"$krx\" %? ERROR %: %)
+%( kernel_v != \"$kv\" %? ERROR %: %)
+%( kernel_v != \"$kr\" %? ERROR %: %)
+%( kernel_v != \"$krx\" %? %: ERROR %)
+%( kernel_v < \"9.9999\" %? %: ERROR %)
+%( kernel_v <= \"9.9999\" %? %: ERROR %)
+%( kernel_v > \"9.9999\" %? ERROR %: %)
+%( kernel_v >= \"9.9999\" %? ERROR %: %)
+%( kernel_vr == \"$kvr\" %? %: ERROR %)
+%( kernel_vr == \"$kr\" %? %: ERROR %)
+%( kernel_vr == \"$krx\" %? ERROR %: %)
+%( kernel_vr != \"$kvr\" %? ERROR %: %)
+%( kernel_vr != \"$kr\" %? ERROR %: %)
+%( kernel_vr != \"$krx\" %? %: ERROR %)
+%( kernel_vr < \"9.9999\" %? %: ERROR %)
+%( kernel_vr <= \"9.9999\" %? %: ERROR %)
+%( kernel_vr > \"9.9999\" %? ERROR %: %)
+%( kernel_vr >= \"9.9999\" %? ERROR %: %)
+%( arch == \"$arch\" %? %: ERROR %)
+%( arch == \"$ar\" %? %: ERROR %)
+%( arch == \"$arx\" %? ERROR %: %)
+%( arch != \"$arch\" %? ERROR %: %)
+%( arch != \"$ar\" %? ERROR %: %)
+%( arch != \"$arx\" %? %: ERROR %)
+"
+set ok 0
+expect {
+ "never" { incr ok }
+ eof { }
+ timeout { }
+}
+catch {close; wait}
+if {$ok == 1} { pass $test } { fail $test }