diff options
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | parse.cxx | 56 | ||||
-rw-r--r-- | stap.1.in | 13 | ||||
-rw-r--r-- | tapset/syscalls2.stp | 30 | ||||
-rw-r--r-- | testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | testsuite/systemtap.base/preprocessor.exp | 52 |
7 files changed, 132 insertions, 40 deletions
@@ -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() @@ -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 @@ -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 @@ -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 } |