DTrace User Guide

Chapter 3 Scripting With the D Language

This chapter discusses the basic information that you need to start writing your own D language scripts.

Writing D Scripts

Complex sets of DTrace probes can become difficult to manage on the command line. The dtrace command supports scripts. You can specify a script by passing the -s option, along with the script's file name, to the dtrace command. You can also create executable DTrace interpreter files. A DTrace interpreter file always begins with the line #!/usr/sbin/dtrace -s.

Executable D Scripts

This example script, named syscall.d, traces the executable name every time the executable enters each system call:

syscall:::entry
{
   trace(execname);
}

Note that the filename ends with a .d suffix. This is the conventional ending for D scripts. You can run this script off the DTrace command line with the following command:

# dtrace -s syscall.d
dtrace: description 'syscall ' matched 226 probes
CPU     ID                     FUNCTION:NAME
  0    312                     pollsys:entry    java
  0     98                       ioctl:entry    dtrace
  0     98                       ioctl:entry    dtrace
  0    234                   sysconfig:entry    dtrace
  0    234                   sysconfig:entry    dtrace
  0    168                   sigaction:entry    dtrace
  0    168                   sigaction:entry    dtrace
  0     98                       ioctl:entry    dtrace
^C

You can run the script by entering the filename at the command line by following two steps. First, verify that the first line of the file invokes the interpreter. The interpreter invocation line is #!/usr/sbin/dtrace -s. Then set the execute permission for the file.


Example 3–1 Running a D Script from the Command Line

# cat syscall.d
#!/usr/sbin/dtrace -s

syscall:::entry
{
   trace(execname);
}

# chmod +x syscall.d
# ls -l syscall.d
-rwxr-xr-x   1 root     other       62 May 12 11:30 syscall.d
# ./syscall.d
dtrace: script './syscall.d' matched 226 probes
CPU     ID                     FUNCTION:NAME
  0     98                       ioctl:entry    dtrace
  0     98                       ioctl:entry    dtrace
  0    312                     pollsys:entry    java
  0    312                     pollsys:entry    java
  0    312                     pollsys:entry    java
  0     98                       ioctl:entry    dtrace
  0     98                       ioctl:entry    dtrace
  0    234                   sysconfig:entry    dtrace
  0    234                   sysconfig:entry    dtrace
^C

D Literal Strings

The D language supports literal strings. DTrace represents strings as an array of characters terminated by a null byte. The visible part of the string varies in length depending on the location of the null byte. DTrace stores each string in a fixed-size array to ensure that each probe traces a consistent amount of data. Strings cannot exceed the length of the predefined string limit. The limit can be modified in your D program or on the dtrace command line by tuning the strsize option. Refer to Chapter 16, Options and Tunables, in Solaris Dynamic Tracing Guide for more information on tunable DTrace options. The default string limit is 256 bytes.

The D language provides an explicit string type rather than using the type char * to refer to strings. See Chapter 6, Strings, in Solaris Dynamic Tracing Guide for more information about D literal strings.


Example 3–2 Using D Literal Strings With The trace() Function

# cat string.d

#!/usr/sbin/dtrace -s

fbt::bdev_strategy:entry
{
   trace(execname);
   trace(" is initiating a disk I/O\n");
}

The \n symbol at the end of the literal string produces a new line. To run this script, enter the following command:

# dtrace -s string.d
dtrace: script 'string.d' matched 1 probes
CPU     ID                     FUNCTION:NAME
  0   9215               bdev_strategy:entry   bash is initiating a disk I/O

  0   9215               bdev_strategy:entry   vi is initiating a disk I/O

  0   9215               bdev_strategy:entry   vi is initiating a disk I/O

  0   9215               bdev_strategy:entry   sched is initiating a disk I/O

^C

The -q option of the dtrace command only records the actions that are explicitly stated in the script or command line invocation. This option suppresses the default output that the dtrace command normally produces.

# dtrace -q -s string.d
ls is initiating a disk I/O
cat is initiating a disk I/O
fsflush is initiating a disk I/O
vi is initiating a disk I/O
^C

Creating D Scripts That Use Arguments

You can use the dtrace command to create executable interpreter files. The file must have execute permission. The initial line of the file must be #!/usr/sbin/dtrace -s. You can specify other options to the dtrace command on this line. You must specify the options with only one dash (-). List the s option last, as in the following example.


#!/usr/sbin/dtrace -qvs

You can specify options for the dtrace command by using #pragma lines in the D script, as in the following D fragment:


# cat -n mem2.d
     1  #!/usr/sbin/dtrace -s
     2
     3  #pragma D option quiet
     4  #pragma D option verbose
     5  
     6  vminfo:::
     ...

The following table lists the option names that you can use in #pragma lines.

Table 3–1 DTrace Consumer Options

Option Name 

Value 

dtrace Alias

Description 

aggrate

time

 

Rate of aggregation reading 

aggsize

size

 

Aggregation buffer size 

bufresize

auto or manual

 

Buffer resizing policy 

bufsize

size

-b

Principal buffer size 

cleanrate

time

 

Cleaning rate 

cpu

scalar

-c

CPU on which to enable tracing 

defaultargs

— 

 

Allow references to unspecified macro arguments 

destructive

— 

-w

Allow destructive actions 

dynvarsize

size

 

Dynamic variable space size 

flowindent

— 

-F

Indent function entry and prefix with ->; unindent function return and prefix with <-

grabanon

— 

-a

Claim anonymous state 

jstackframes

scalar

 

Number of default stack frames jstack()

jstackstrsize

scalar

 

Default string space size for jstack()

nspec

scalar

 

Number of speculations 

quiet

— 

-q

Output only explicitly traced data 

specsize

size

 

Speculation buffer size 

strsize

size

 

String size 

stackframes

scalar

 

Number of stack frames 

stackindent

scalar

 

Number of whitespace characters to use when indenting stack() and ustack() output

statusrate

time

 

Rate of status checking 

switchrate

time

 

Rate of buffer switching 

ustackframes

scalar

 

Number of user stack frames 

A D script can refer to a set of built in macro variables. These macro variables are defined by the D compiler.

$[0-9]+

Macro arguments

$egid

Effective group-ID

$euid

Effective user-ID

$gid

Real group-ID

$pid

Process ID

$pgid

Process group ID

$ppid

Parent process ID

$projid

Project ID

$sid

Session ID

$target

Target process ID

$taskid

Task ID

$uid

Real user-ID


Example 3–3 PID Argument Example

This example passes the PID of a running vi process to the syscalls2.d D script. The D script terminates when the vi command exits.


# cat -n syscalls2.d
     1  #!/usr/sbin/dtrace -qs
     2
     3  syscall:::entry
     4  /pid == $1/
     5  {
     6    @[probefunc] = count();
     7  }
     8  syscall::rexit:entry
     9  {
    10    exit(0);
    11  }

# pgrep vi
2208
# ./syscalls2.d 2208

  rexit                                               1
  setpgrp                                             1
  creat                                               1
  getpid                                              1
  open                                                1
  lstat64                                             1
  stat64                                              1
  fdsync                                              1
  unlink                                              1
  close                                               1
  alarm                                               1
  lseek                                               1
  sigaction                                           1
  ioctl                                               1
  read                                                1
  write                                               1
     

DTrace Built-in Variables

The following list includes all of the built-in variables for the DTrace framework.

int64_t arg0, ..., arg9

The first ten input arguments to a probe represented as raw 64-bit integers. If fewer than ten arguments are passed to the current probe, the remaining variables return zero.

args[]

The typed arguments to the current probe, if any. The args[] array is accessed using an integer index, but each element is defined to be the type corresponding to the given probe argument. For example, if the args[] array is referenced by a read(2) system call probe, args[0] is of type int, args[1] is of type void *, and args[2] is of type size_t.

uintptr_t caller

The program counter location of the current thread just before entering the current probe.

chipid_t chip

The CPU chip identifier for the current physical chip. See Chapter 26, sched Provider, in Solaris Dynamic Tracing Guide for more information.

processorid_t cpu

The CPU identifier for the current CPU. See Chapter 26, sched Provider, in Solaris Dynamic Tracing Guide for more information.

cpuinfo_t *curcpu

The CPU information for the current CPU. See Chapter 26, sched Provider, in Solaris Dynamic Tracing Guide for more information.

lwpsinfo_t *curlwpsinfo

The lightweight process (LWP) state of the LWP associated with the current thread. This structure is described in further detail in the proc(4) man page.

psinfo_t *curpsinfo

The process state of the process associated with the current thread. This structure is described in further detail in the This structure is described in further detail in the proc(4) man page.

kthread_t *curthread

The address of the operating system kernel's internal data structure for the current thread, the kthread_t. The kthread_t is defined in <sys/thread.h>. Refer to Solaris Internals for more information on this variable and other operating system data structures.

string cwd

The name of the current working directory of the process associated with the current thread.

uint_t epid

The enabled probe ID (EPID) for the current probe. This integer uniquely identifiers a particular probe that is enabled with a specific predicate and set of actions.

int errno

The error value returned by the last system call executed by this thread.

string execname

The name that was passed to exec(2) to execute the current process.

gid_t gid

The real group ID of the current process.

uint_t id

The probe ID for the current probe. This ID is the system-wide unique identifier for the probe as published by DTrace and listed in the output of dtrace -l.

uint_t ipl

The interrupt priority level (IPL) on the current CPU at the time that the probe fires. Refer to Solaris Internals for more information on interrupt levels and interrupt handling in the Solaris operating system kernel.

lgrp_id_t lgrp

The locality group ID for the latency group of which the current CPU is a member. See Chapter 26, sched Provider, in Solaris Dynamic Tracing Guide for more information on CPU management in DTrace. See Chapter 4, Locality Group APIs, in Programming Interfaces Guide for more information about locality groups.

pid_t pid

The process ID of the current process.

pid_t ppid

The parent process ID of the current process.

string probefunc

The function name portion of the current probe's description.

string probemod

The module name portion of the current probe's description.

string probename

The name portion of the current probe's description.

string probeprov

The provider name portion of the current probe's description.

psetid_t pset

The processor set ID for the processor set that contains the current CPU. See Chapter 26, sched Provider, in Solaris Dynamic Tracing Guide for more information.

string root

The name of the root directory of the process associated with the current thread.

uint_t stackdepth

The current thread's stack frame depth at probe firing time.

id_t tid

The thread ID of the current thread. For threads that are associated with user processes, this value is equal to the result of a call to pthread_self(3C).

uint64_t timestamp

The current value of a nanosecond timestamp counter. This counter increments from an arbitrary point in the past and should only be used for relative computations.

uid_t uid

The real user ID of the current process.

uint64_t uregs[]

The current thread's saved user-mode register values at probe firing time. Use of the uregs[] array is discussed in Chapter 33, User Process Tracing, in Solaris Dynamic Tracing Guide.

uint64_t vtimestamp

The current value of a nanosecond timestamp counter. The counter is virtualized to the amount of time that the current thread has been running on a CPU. The counter does not include the time that is spent in DTrace predicates and actions. This counter increments from an arbitrary point in the past and should only be used for relative time computations.

uint64_t walltimestamp

The current number of nanoseconds since 00:00 Universal Coordinated Time, January 1, 1970.