Actions enable DTrace to interact with the system outside of the DTrace framework. The most common actions record data to a DTrace buffer. Other actions can stop the current process, raise a specific signal on the current process, or cease tracing. Actions that change the system state are considered destructive actions. Data recording actions record data to the principal buffer by default. The principal buffer is present in every DTrace invocation and is always allocated on a per-CPU basis. Tracing and buffer allocation can be restricted to a single CPU by using the -cpu option. See Chapter 11, Buffers and Buffering, in Solaris Dynamic Tracing Guide for more information about DTrace buffering.
The examples in this section use D expressions that consist of built-in D variables. Some of the most commonly used D variables are listed below:
This variable contains the current process ID.
This variable contains the current executable name.
This variable contains the time since boot, expressed in nanoseconds.
This variable contains a pointer to the kthread_t structure that represents the current thread.
This variable contains the module name of the current probe.
This variable contains the function name of the current probe.
This variable contains the name of the current probe.
For a complete list of the built-in variables of the D scripting language, see Variables.
The D scripting language also provides built-in functions that perform specific actions. You can find a complete list of these built-in functions at Chapter 10, Actions and Subroutines, in Solaris Dynamic Tracing Guide. The trace() function records the result of a D expression to the trace buffer, as in the following examples:
trace(pid) traces the current process ID
trace(execname) traces the name of the current executable
trace(curthread->t_pri) traces the t_pri field of the current thread
trace(probefunc) traces the function name of the probe
To indicate a particular action you want a probe to take, type the name of the action between {} characters, as in the following example.
Example 2-10 Specifying a Probe's Action
# dtrace -n 'readch {trace(pid)}' dtrace: description 'readch ' matched 4 probes CPU ID FUNCTION:NAME 0 4036 read:readch 2040 0 4036 read:readch 2177 0 4036 read:readch 2177 0 4036 read:readch 2040 0 4036 read:readch 2181 0 4036 read:readch 2181 0 4036 read:readch 7 ...
Since the requested action is trace(pid), the process identification number (PID) appears in the last column of the output.
Example 2-11 Tracing an Executable Name
# dtrace -m 'ufs {trace(execname)}' dtrace: description 'ufs ' matched 889 probes CPU ID FUNCTION:NAME 0 14977 ufs_lookup:entry ls 0 15748 ufs_iaccess:entry ls 0 15749 ufs_iaccess:return ls 0 14978 ufs_lookup:return ls ... 0 15007 ufs_seek:entry utmpd 0 15008 ufs_seek:return utmpd 0 14963 ufs_close:entry utmpd ^C
Example 2-12 Tracing A System Call's Time of Entry
# dtrace -n 'syscall:::entry {trace(timestamp)}' dtrace: description 'syscall:::entry ' matched 226 probes CPU ID FUNCTION:NAME 0 312 portfs:entry 157088479572713 0 98 ioctl:entry 157088479637542 0 98 ioctl:entry 157088479674339 0 234 sysconfig:entry 157088479767243 ... 0 98 ioctl:entry 157088481033225 0 60 fstat:entry 157088481050686 0 60 fstat:entry 157088481074680 ^C
Example 2-13 Specifying Multiple Actions
To specify multiple actions, list the actions separated by the ; character.
# dtrace -n 'zfod {trace(pid);trace(execname)}' dtrace: description 'zfod ' matched 3 probes CPU ID FUNCTION:NAME 0 4080 anon_zero:zfod 2195 dtrace 0 4080 anon_zero:zfod 2195 dtrace 0 4080 anon_zero:zfod 2195 dtrace 0 4080 anon_zero:zfod 2195 dtrace 0 4080 anon_zero:zfod 2195 dtrace 0 4080 anon_zero:zfod 2197 bash 0 4080 anon_zero:zfod 2207 vi 0 4080 anon_zero:zfod 2207 vi ...
The actions in this section record data to the principal buffer by default, but each action may also be used to record data to speculative buffers. See Speculative Tracing for more details on speculative buffers.
void trace(expression)
The most basic action is the trace() action, which takes a D expression as its argument and traces the result to the directed buffer.
void tracemem(address, size_t nbytes)
The tracemem() action copies data from an address in memory to a buffer . The number of bytes that this action copies is specified in nbytes. The address that the data is copied from is specified in addr as a D expression. The buffer that the data is copied to is specified in buf.
void printf(string format, ...)
Like the trace() action, the printf() action traces D expressions. However, the printf() action lets you control formatting in ways similar to the printf(3C) function. Like the printf function, the parameters consists of a format string followed by a variable number of arguments. By default, the arguments are traced to the directed buffer. The arguments are later formatted for output by the dtrace command according to the specified format string.
For more information on the printf() action, see Chapter 12, Output Formatting, in Solaris Dynamic Tracing Guide.
void printa(aggregation) void printa(string format, aggregation)
The printa() action enables you to display and format aggregations. See Chapter 9, Aggregations, in Solaris Dynamic Tracing Guide for more detail on aggregations. If a format value is not provided, the printa() action only traces a directive to the DTrace consumer. The consumer that receives that directive processes and displays the aggregation with the default format. See Chapter 12, Output Formatting, in Solaris Dynamic Tracing Guide for a more detailed description of the printa() format string.
void stack(int nframes) void stack(void)
The stack() action records a kernel stack trace to the directed buffer. The depth of the kernel stack is given by the value given in nframes. If no value is given for nframes, the stack action records a number of stack frames specified by the stackframes option.
void ustack(int nframes, int strsize) void ustack(int nframes) void ustack(void)
The ustack() action records a user stack trace to the directed buffer. The depth of the user stack is equal to the value specified in nframes. If there is no value for nframes, the ustack action records a number of stack frames that is specified by the ustackframes option. The ustack() action determines the address of the calling frames when the probe fires. The ustack() action does not translate the stack frames into symbols until the DTrace consumer processes the ustack() action at the user level. If a value for strsize is specified and not zero, the ustack() action allocates the specified amount of string space and uses it to perform address-to-symbol translation directly from the kernel.
void jstack(int nframes, int strsize) void jstack(int nframes) void jstack(void)
The jstack() action is an alias for ustack() that uses the value specified by the jstackframes option for the number of stack frames. The jstack action uses the value specified by the jstackstrsize option to determine the string space size. The jstacksize action defaults to a non-zero value.
You must explicitly enable destructive actions in order to use them. You can enable destructive actions by using the -w option. If you attempt to use destructive actions in dtrace without explicitly enabling them, dtrace fails with a message similar to the following example:
dtrace: failed to enable 'syscall': destructive actions not allowed
For more information on DTrace actions, including destructive actions, see Chapter 10, Actions and Subroutines, in Solaris Dynamic Tracing Guide.
Some actions are destructive only to a particular process. These actions are available to users with the dtrace_proc or dtrace_user privileges. See Chapter 35, Security, in Solaris Dynamic Tracing Guide for details on DTrace security privileges.
When a probe fires with the stop() action enabled, the process that fired that probe stops upon leaving the kernel. This process stops in the same way as a process that is stopped by a proc(4) action.
void raise(int signal)
The raise() action sends the specified signal to the currently running process.
void copyout(void *buf, uintptr_t addr, size_t nbytes)
The copyout() action copies data from a buffer to an address in memory. The number of bytes that this action copies is specified in nbytes. The buffer that the data is copied from is specified in buf. The address that the data is copied to is specified in addr. That address is in the address space of the process that is associated with the current thread.
void copyoutstr(string str, uintptr_t addr, size_t maxlen)
The copyoutstr() action copies a string to an address in memory. The string to copy is specified in str. The address that the string is copied to is specified in addr. That address is in the address space of the process that is associated with the current thread.
void system(string program, ...)
The system() action causes the program specified by program to be executed by the system as if it were given to the shell as input.
Some destructive actions are destructive to the entire system. Use these actions with caution. These actions affect every process on the system and may affect other systems, depending upon the affected system's network services.
void breakpoint(void)
The breakpoint() action induces a kernel breakpoint, causing the system to stop and transfer control to the kernel debugger. The kernel debugger will emit a string that denotes the DTrace probe that triggered the action.
void panic(void)
When a probe with the panic() action triggers, the kernel panics. This action can force a system crash dump at a time of interest. You can use this action in conjunction with ring buffering and postmortem analysis to diagnose a system problem. For more information, see Chapter 11, Buffers and Buffering, in Solaris Dynamic Tracing Guide and Chapter 37, Postmortem Tracing, in Solaris Dynamic Tracing Guide respectively.
void chill(int nanoseconds)
When a probe with the chill() action triggers, DTrace spins for the specified number of nanoseconds. The chill() action is useful for exploring problems related to timing. Because interrupts are disabled while in DTrace probe context, any use of chill() will induce interrupt latency, scheduling latency, dispatch latency.