DTrace Action Basics

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:

pid

This variable contains the current process ID.

execname

This variable contains the current executable name.

timestamp

This variable contains the time since boot, expressed in nanoseconds.

curthread

This variable contains a pointer to the kthread_t structure that represents the current thread.

probemod

This variable contains the module name of the current probe.

probefunc

This variable contains the function name of the current probe.

probename

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:

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
...

Data Recording Actions

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.

The trace function

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.

The tracemem function

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.

The printf function

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 .

The printa function

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.

The stack function

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.

The ustack function

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.

The jstack function

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.

Destructive Actions

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 .

Process Destructive Actions

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.

The stop function

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.

The raise function
void raise(int signal)

The raise action sends the specified signal to the currently running process.

The copyout function
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.

The copyoutstr function
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.

The system function
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.

Kernel Destructive Actions

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.

The breakpoint function
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.

The panic function
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.

The chill function
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.