Languages and scripts
ProbeVue uses probes for problem determination and performance analysis. A probe is a software mechanism that interrupts normal system action to investigate and obtain information about current context and system state.
This is also commonly referred to as tracing. Tracing actions or probe actions typically capture information by writing the current values of global and context-specific information to a trace buffer. This information is called trace data. The system usually provides facilities to read the data out of the trace buffer and make it available to the users of the system.
A probe point identifies a point during normal system activity that is capable of being probed. With dynamic tracing, probe points do not have any probes attached to them unless they are being traced. Enabling a probe is the operation of attaching a probe to a probe point and disabling a probe is the operation of removing a probe from a probe point. A probe is triggered or fired when an enabled probe point is reached during system activity and the tracing actions are performed.
ProbeVue supports the following two broad categories of probe points:
- Probe location
- A location in user or kernel code where some tracing action is to be performed. Enabled probes at a probe location fire when any thread running code reaches that location.
- Probe event
- An event of interest at whose occurrence some tracing action is performed. Probe events do not easily map to a specific code location. Enabled probes that indicate a probe event are configured to fire when that event occurs.
ProbeVue also distinguishes probe points by their type. A probe type identifies a set of probe points that share some common characteristics, for example, probe points that identify the entry and exit of system calls, or probe points that indicate updates to system statistics. Distinguishing probes by types gives structure to the wide variety of probe points.
ProbeVue requires a probe manager to be associated with each probe type. The probe manager is the software code that defines and provides a set of probe points of the same probe type, for example, the system call probe manager.
Vue programming language
The Vue programming language provides your tracing specifications to ProbeVue. A Vue script or Vue program is a program written in Vue. You can use a Vue script for the following purposes:
- Identify the probe points where a probe is to be dynamically enabled.
- Specify the conditions, if any, that must be satisfied to cause a probe to fire.
- Specify the actions issued, including the trace data that you want to capture.
In short, a Vue script tells ProbeVue where to trace, when to trace, and what to trace. Vue scripts should have a file suffix of ".e" to distinguish them from other file types.
Note that Vue is both a programming and a script language: it is a dedicated dynamic tracing language. Vue supports a subset of C and scripting syntax that is most beneficial for dynamic tracing purposes.
Elements of C
Vue supports a subset of C. The following table describes how the support the ProbeVue compiler provides for the specified C keywords. All C keywords remain restricted in Vue. Use of any of these keywords as variable names or other symbols is not flagged as a syntax error, however, the behavior of such usage is undefined.
| Supported | Allowed in header files or in declaration section | Unsupported |
|---|---|---|
| char | auto | break |
| double | const | case |
| else | extern | continue |
| enum | register | default |
| float | static | do |
| if | typedef | for |
| int | volatile | goto |
| long | switch | |
| return | while | |
| short | ||
| signed | ||
| sizeof | ||
| struct | ||
| union | ||
| unsigned | ||
| void |
The following list describes the set of C features that Vue supports:
- Statements
- All C statements except for loop and some control flow statements.
- Operators
- All C unary, binary, and ternary operators except for the comma operator. Operator precedence and associativity follows C language rules.
- Data types
- Most legal C-89 defined variable types including all statements
and keywords (struct, union, enum, typedef, and so on) for declaring
types subject to the restrictions. This includes the types for kernel
or application variables and parameters. Note: Vue has its own rules on scope and storage classes.
- Type conversions
- Implicit type conversions as well as explicit conversions with type casts.
- Subroutine
- The syntax for calling subroutines and passing parameters to functions. There are, however, restrictions on what functions can be called.
- Variable names
- The naming conventions for variables follow C identifier rules. The complete variable specification can include colons if a variable class name is prefixed to the variable name.
- Header files
- Header files can be included for explicitly declaring the types of kernel global variables or the prototypes of functions in applications and the kernel. There are some restrictions on how the header files are included.
- Punctuators
- All C punctuators are supported and their rules are enforced. Thus, statements must be separated by the semicolon (;) character. All C white space rules are followed.
- Literals
- Representation of strings (using double quotes characters(")), character literals (using single quotes characters (')), octal and hexadecimal integers, and special characters like the \n and \t escape sequences.
- Comments
- C-style and C++-style comments. Comments can appear both inside and outside of a clause. Any line starting with a # character is ignored. Avoid using the character to indicate a comment line.
Differences from the C language
Vue has a different behavior for some C features. Some restrictions are imposed for maintaining efficiency or for ensuring that a Vue script can be issued safely inside the kernel and that it does not affect the probed process.
- Loop statements
- Loop statements are not accepted by a Vue script. This is a precaution to prevent any Vue probe from never completing.
- Conditional flow statements
- Only the "if-else" style control flow statement is accepted by a Vue script. Most conditional logic flow can be achieved through the proper use of "if" statements. Predicates are a more efficient way to do high-level conditional logic in a Vue script.
- Return statement
- The return statement is accepted by Vue to signal that the execution of the action block is to be ended immediately. However, the return statement does not take any expressions in Vue, as the Vue action block has no return values.
- Subroutines
- Vue scripts do not have access to the functions provided by the AIX® system or general user libraries. There is no support for creating archives (libraries of functions) or user functions callable from within the probes. Instead, a special internal library is available for you that provide a set of functions generally useful for dynamic tracing programs.
- Floating point
- Floating-point variables are not accepted by any clause associated with a kernel probe point. You can only use floating-point variables in simple assignment statements and as parameters to Vue functions that print data. Vue language support for floating-point variables is restricted to its capture.
- Variable modifications
- External variables are not accepted by the left-hand side of an assignment statement, that is, they cannot be modified in a Vue script.
- Header files
- Vue does not support an explicit inclusion of the header file in the Vue script itself. Instead, the name of a header file to be included must be passed through command line arguments to the probevue command. Any C-preprocessor operators or directives in the header file are ignored. This might cause unexpected behavior. To avoid this, hand-code the header file or explicitly run the C-preprocessor directly on the set of relevant header files and generate a post-processed header file for inclusion. You can include the function prototypes and structure or union definitions in the Vue script itself if they are inserted at the very beginning before starting any of the probe clauses.
- C-preprocessor
- C-preprocessor operators, macro definitions, line or pragma directives and pre-defined macro names are ignored.
- Pointer operations
- Vue does not accept pointers to script variables. For example, the address of a script variable cannot be taken. However, the address of a kernel variable can be taken and assigned to a Vue pointer variable and pointer operations supported using the pointer variable.
- Miscellaneous
-
- Trigraphs are not accepted.
- The comma operator is not accepted.
- Declaration statements cannot contain any initialization.
probevue command
The probevue command starts a dynamic tracing session or a ProbeVue session. The probevue command takes a Vue script as input reading from a file or from the command line and activates a ProbeVue session. Any trace data that is captured by the ProbeVue session can be printed to the terminal or saved to a user-specified file as per options passed in the command line.
The ProbeVue session stays active until you type a Ctrl-C on the terminal or an exit action is issued from the Vue script.
Each invocation of the probevue command activates a separate dynamic tracing session. Multiple tracing sessions can be active at one time, but each session presents only the trace data that is captured in that session. Concurrent sessions are generally unaware of each other.
Running the probevue command is a privileged operation and non-root users needs privileges to initiate a dynamic tracing session.
Vue scripts
A Vue script consists of an optional declaration section followed by one or more clauses. You can specify the clauses in a Vue script in any order. The following one is a typical layout of a Vue script:
| Declaration | Example |
|---|---|
| optional BEGIN clause | |
| one or more probe clauses | |
| optional END clause | |
You can use the optional declaration section for declaring variable types and global variables. It must not contain any executable statements.
Each clause of a Vue script consists of the following three elements:
- Probe point specification
- The probe point specification identifies a set of probe points to be dynamically enabled. It consists of one or more probe point tuples. The total length of this string is limited to 1023 characters.
- Action Block
- The action block identifies the sequence of probe actions to be performed when the probe fires.
- An optional predicate
- The predicate, if present, identifies a condition that is to be checked at the time the probe is triggered. The predicate must evaluate to TRUE for the probe actions of the clause to be issued.
A Vue script can contain comments. You can place comments anywhere in the Vue script: at the top of the Vue script, between two Vue clauses, or inside a Vue clause.
Declaration section
- Type, structure, union and enum definitions
- Function prototype declarations for functions probed
- Declarations for global and kernel variables accessed in the script
It must not contain any executable statements including any style of variable initialization.
All declarations and definitions in Vue generally follow the syntax of the C-89 language specification for the C language, although there are some Vue-specific restrictions. Additionally, Vue supports a few of its own data types and special keywords to indicate the Vue class of a variable.
Probe point specification
A probe point specification consists of one or more probe point tuples. Each probe point tuple identifies a code location whose execution or an event whose occurrence must trigger the probe actions. Multiple probe points can be associated with the same set of probe actions and the predicate, if any, by providing a comma-separated list of probe tuples at the top of the Vue clause.
The following are some of the probe types that are supported:
- User function entry probes (or uft probes)
- System call entry or exit probes (or syscall probes)
- Probes that fire at specific time intervals (or interval probes)
For a complete list of probe types that are supported, refer the probe manager section.
The probe point tuple is an ordered list of fields that are separated by colons that uniquely identify a probe point. It has the following general format, although the location field is usually present only if the probe point is a probe location.
@@ <probetype>:
<one or more probetype-specific fields separated by colons>:<location>
The probe manager defines the acceptable values for the probe-type specific fields in the probe point tuple and the length of the probe tuple. However, the following general rules are followed by all probe managers when defining probe point tuples:
- Each probe point tuple is at least a 3-tuple, that is, it has a minimum of 3 fields.
- The first field always identifies the probe type and thus its probe manager.
- For probe managers that support process-specific tracing, the second field must be a process ID.
- For probe managers that support function entry or exit probes, the location field (the last field) must use the entry or exit keyword.
- Fields are separated by the colon (:) symbol.
- An asterisk or the "*" symbol for a field in the probe point tuple indicates that it matches any possible value for that field. For example, the syscall probe manager allows for system calls of a specific process or for all processes to be probed. In the first case, the second field must be the process ID of the process to be probed. In the latter case, when all processes are to be probed, the second field must be the "*" symbol. A second use of the asterisk symbol for a field is to allow for finer-grained probes in the future while maintaining binary compatibility with existing scripts. For example, the uft probe manager currently requires the third field to be an asterisk. In the future, it can support a module name as the third field to limit probes to only functions defined in that module.
- Maximum length of the probe specification is 1023 characters.
For example:
- @@uft:34568:*:foo:entry
- Probe at entry into any function called foo in process with ID = 34568. The asterisk in the third field indicates that the foo function is to be probed if it exists in any module of the process.
- @@syscall:*:read:exit
- Probe at exit of the read system call. The asterisk indicates that the read system call for all processes are to be probed.
- @@interval:*:clock:500
- Probe to fire every 500 milliseconds (wall clock time). The asterisk is a placeholder for supporting finer probe points in the future.
The process ID for a process is often not known at the time the Vue script is written. Vue provides a simple method to avoid having to hard-code a process ID in the second field of the probe specification or anywhere in a Vue script (for example, in the predicate section).
A single Vue script can contain probe points from multiple processes in user space and in the kernel. Any trace output generated is always displayed in time order.
In addition to regular probe points defined by probe managers, Vue supports two special probe points. Each Vue script can contain a @@BEGIN probe point to indicate any action that needs to be issued before enabling any probes and an @@END probe point to indicate any action to be issued after the tracing has been terminated.
Action block
The action block identifies the trace actions to be performed when the associated probe point is triggered. Supported actions are not restricted to capturing and formatting of trace data but the full power of the Vue language can be employed.
An action block in Vue is similar to a procedure in procedural languages. It consists of a sequence of statements that are issued in order. The flow of execution is essentially sequential. The only exceptions are that conditional execution is possible using the "if-else" statement and control can be returned from the action block using the "return" statement. Vue also supports an exit function that terminates the entire script and ends the tracing session. There are no constructs for looping in Vue and C language statements, so "for", "do", "goto", and so on, are not supported.
Unlike procedures in procedural languages, an action block in Vue does not have an output or return value. It also does not have inherent support for a set of input parameters. On the other hand, the context data at the point where a probe is entered can be accessed within the action block. For example, the parameters passed to a function can be referenced within the action block of a Vue clause if the probe point is at the function's entry point.
Predicates
You must 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.
when ( <condition> )when ( __pid == 1678 )Vue script example
The following script is an example of a Vue script:
/* Global variables are auto-initialized to zero */ [1]
int count; /[2]
/*
* File: count.e
*
* Count number of times the read or write system call is entered
* by process with Id 400
*/
@@BEGIN
{
printf("Start probing\n");
}
@@syscall:*:read:entry, @@syscall:*:write:entry [3]
when (__pid == 400)[4]
{[5]
count++;
/* Print a message for every 20 system calls */
if (count % 20 == 0)
printf("Total read/writes so far: %d\n", count);
/* Exit when we exceed 100 system calls */
if (count > 100)
exit();
} [6]
/* print some statistics at exit */
@@END
{
printf("Terminating probe after %d system calls.\n", count);
}
The following superscripts used in the above example identify the different elements of a Vue script:
- Comments
- (Optional) Declaration section
- Probe specification
- (Optional) Predicate
- Start of action block
- End of action block
You can start this simple script by issuing the following command. Note that this example displays some sample output.
# probevue count.e
Total read/writes so far: 20
Total read/writes so far: 40
Total read/writes so far: 60
...
...
Running the probevue command requires privileges. To issue the above command successfully, you must have logged in as the superuser or been granted privileges to probe system calls made by any process in the system.