You can use the dtrace(1M) utility to create interpreter files out of D programs similar to shell scripts that you can install as reusable interactive DTrace tools. The D compiler and dtrace command provide a set of macro variables that are expanded by the D compiler that make it easy to create DTrace scripts. This chapter provides a reference for the macro variable facility and tips for creating persistent scripts.
where pathname is the path of the interpreter and arg is a single optional argument. When an interpreter file is executed, the system invokes the specified interpreter. If arg was specified in the interpreter file, it is passed as an argument to the interpreter. The path to the interpreter file itself and any additional arguments specified when it was executed are then appended to the interpreter argument list. Therefore, you will always need to create DTrace interpreter files with at least these arguments:
When your interpreter file is executed, the argument to the -s option will therefore be the pathname of the interpreter file itself. dtrace will then read, compile, and execute this file as if you had typed the following command in your shell:
The following example shows how to create and execute a dtrace interpreter file. Type the following D source code and save it in a file named interp.d:
Mark the interp.d file as executable and execute it as follows:
Remember that the #! directive must comprise the first two characters of your file with no intervening or preceding whitespace. The D compiler knows to automatically ignore this line when it processes the interpreter file.
dtrace uses getopt(3C) to process command-line options, so you can combine multiple options in your single interpreter argument. For example, to add the -q option to the preceding example you could change the interpreter directive to:
If you specify multiple option letters, the -s option must always end the list of boolean options so that the next argument (the interpreter file name) is processed as the argument corresponding to the -s option.
If you need to specify more than one option that requires an argument in your interpreter file, you will not be able to fit all your options and arguments into the single interpreter argument. Instead, use the #pragma D option directive syntax to set your options. All of the dtrace command-line options have #pragma equivalents that you can use, as shown in Chapter 16, Options and Tunables.
The D compiler defines a set of built-in macro variables that you can use when writing D programs or interpreter files. Macro variables are identifiers that are prefixed with a dollar sign ($) and are expanded once by the D compiler when processing your input file. The D compiler provides the following macro variables:
|$[0-9]+||macro arguments||See Macro Arguments|
|$pgid||process group ID||getpgid(2)|
|$ppid||parent process ID||getppid(2)|
|$target||target process ID||See Target Process ID|
Except for the $[0-9]+ macro arguments and the $target macro variable, the macro variables all expand to integers corresponding to system attributes such as the process ID and user ID. The variables expand to the attribute value associated with the current dtrace process itself, or whatever process is running the D compiler.
Using macro variables in interpreter files enables you to create persistent D programs that do not need to be edited each time you want to use them. For example, to count all system calls except those executed by the dtrace command, you can use the following D program clause containing $pid:
This clause always produces the desired result, even though each invocation of the dtrace command will have a different process ID.
Macro variables can be used anywhere an integer, identifier, or string can be used in a D program. Macro variables are expanded only once (that is, not recursively) when the input file is parsed. Each macro variable is expanded to form a separate input token, and cannot be concatenated with other text to yield a single token. For example, if $pid expands to the value 456, the D code:
would expand to the two adjacent tokens 123 and 456, resulting in a syntax error, rather than the single integer token 123456.
Macro variables are expanded and concatenated with adjacent text inside of D probe descriptions at the start of your program clauses. For example, the following clause uses the DTrace pid provider to instrument the dtrace command:
Macro variables are only expanded once within each probe description field; they may not contain probe description delimiters (:).
The D compiler also provides a set of macro variables corresponding to any additional argument operands specified as part of the dtrace command invocation. These macro arguments are accessed using the built-in names $0 for name of the D program file or dtrace command, $1 for the first additional operand, $2 for the second operand, and so on. If you use the dtrace -s option, $0 expands to the value of the name of the input file used with this option. For D programs specified on the command-line, $0 expands to the value of argv used to exec dtrace itself.
Macro arguments can expand to integers, identifiers, or strings, depending on the form of the corresponding text. As with all macro variables, macro arguments can be used anywhere integer, identifier, and string tokens can be used in a D program. All of the following examples could form valid D expressions assuming appropriate macro argument values:
Macro arguments can be used to create dtrace interpreter files that act like real Solaris commands and use information specified by a user or by another tool to modify their behavior. For example, the following D interpreter file traces write(2) system calls executed by a particular process ID:
If you make this interpreter file executable, you can specify the value of $1 using an additional command-line argument to your interpreter file:
The resulting command invocation counts each write(2) system call executed by process ID 12345.
If your D program references a macro argument that is not provided on the command-line, an appropriate error message will be printed and your program will fail to compile:
D programs can reference unspecified macro arguments if the defaultargs option is set. If defaultargs is set, unspecified arguments will have the value 0. See Chapter 16, Options and Tunables for more information about D compiler options. The D compiler will also produce an error message if additional arguments are specified on the command line that are not referenced by your D program.
The macro argument values must match the form of an integer, identifier, or string. If the argument does not match any of these forms, the D compiler will report an appropriate error message. When specifying string macro arguments to a DTrace interpreter file, surround the argument in an extra pair of single quotes to avoid interpretation of the double quotes and string contents by your shell:
If you want your D macro arguments to be interpreted as string tokens even if they match the form of an integer or identifier, prefix the macro variable or argument name with two leading dollar signs (for example, $$1) to force the D compiler to interpret the argument value as if it were a string surrounded by double quotes. All the usual D string escape sequences (see Table 2–5) are expanded inside of any string macro arguments, regardless of whether they are referenced using the $arg or $$arg form of the macro. If the defaultargs option is set, unspecified arguments that are referenced with the $$arg form have the value of the empty string ("").
Use the $target macro variable to create scripts that can be applied to a particular user process of interest that is selected on the dtrace command line using the -p option or created using the -c option. The D programs specified on the command line or using the -s option are compiled after processes are created or grabbed and the $target variable expands to the integer process-ID of the first such process. For example, the following D script could be used to determine the distribution of system calls executed by a particular subject process:
To determine the number of system calls executed by the date(1) command, save the script in the file syscall.d and execute the following command: