Predicates
You cannot use predicates when execution of clauses at probe points must be performed conditionally. The predicate section is identified by the presence of the when keyword immediately after the probe specification section. The predicate itself consists of regular C-style conditional expressions with the enclosing parentheses.
There are some restrictions on the expressions inside the predicate section:
- Kernel class variables are not permitted in the predicate.
- Automatic class variables are not permitted in the predicate.
- Floating-point type variables are not permitted in the predicate.
- Vue functions are not permitted inside a predicate.
- Side effects are not permitted inside a predicate and so the = assignment operator and its derivatives like +=, |=, and so on are not permitted.
- The ninth and higher parameters passed to a function ( the entry class variables __arg9, __arg10, and so on) are not permitted in the predicate.
Conditional execution of specific actions within a clause is possible by using the if ... else statement which works like the analogous statement in C. However, if the entire clause is to be issued conditionally, it is preferable to use predicates instead because ProbeVue is designed to optimize execution of predicates.
The following script uses thread-local variables inside predicates to efficiently detect when a particular character string is written to a specific file. It also shows an example of using the if statement within the action block of a clause with a predicate. Both the file name and character string are passed as parameters to the script using shell positional parameters.
/*
* Filename : chkfilewrite.e
*
* Capture when someone writes a particular word to a specific file
* takes 2 arguments: filename and word
*
* assumes file name is < 128
*
* Usage: probevue chkfilewrite.e \"<filename>\" \"<string>\"
*
* The backslashes above are necessary to prevent shell
* from stripping the double quotation mark.
*/
int open(char *fname, int m, int p);
int write(int fd, char *s, int size);
@@syscall:*:open:entry
{
__auto String fname[128];
fname = get_userstring(__arg1, -1);
if (fname == $1)
thread:opening = 1;
}
@@syscall:*:open:exit
when (thread:opening == 1)
{
thread:fd = __rv;
thread:opening = 0;
}
@@syscall:*:write:entry
when (thread:fd == __arg1)
{
__auto String buf[128];
if (__arg3 < 128)
buf = get_userstring(__arg2, __arg3);
else
buf = get_userstring(__arg2, 128);
if (strstr(buf, $2)) {
printf("%d wrote word to file.\n", __pid);
exit();
}
}
To run this program to check when someone writes the string "Error" to the foo.log file, you can issue the following command:
probevue chkfilewrite.e \"foo.log\" \"Error\"