4.3 Data Recording Actions

4.3.1 freopen
4.3.2 ftruncate
4.3.3 func
4.3.4 mod
4.3.5 printa
4.3.6 printf
4.3.7 stack
4.3.8 sym
4.3.9 trace
4.3.10 tracemem
4.3.11 ustack
4.3.12 uaddr
4.3.13 usym

The data recording actions comprise the core DTrace actions. Each of these actions records data to the principal buffer by default, but each action may also be used to record data to speculative buffers. See Chapter 5, Buffers and Buffering for more details on the principal buffer. See Chapter 7, Speculative Tracing for more details on speculative buffers. The descriptions in this section refer only to the directed buffer, indicating that data is recorded either to the principal buffer or to a speculative buffer if the action follows a speculate.

4.3.1 freopen

void freopen(const char *pathname)

freopen changes the file that is associated with stdout to the file specified by pathname.

Caution

freopen is potentially destructive, because you can use it to overwrite arbitrary files.

4.3.2 ftruncate

void ftruncate(void)

ftruncate truncates the output stream on stdout.

4.3.3 func

_symaddr func(uintptr_t address)

func prints the symbol that corresponds to a specified kernel-space address, for example: vmlinux'max_pfn. func is an alias for sym.

4.3.4 mod

_symaddr mod(uintptr_t address)

mod prints the name of the module that corresponds to a specified kernel-space address, for example: vmlinux.

4.3.5 printa

void printa(aggregation)
void printa(string format, aggregation)

The printa action enables you to display and format aggregations. See Chapter 3, Aggregations for more detail on aggregations. If a format is not specified, printa traces only a directive to the DTrace consumer that the specified aggregation should be processed and displayed using the default format. If a format is specified, the aggregation is formatted. See Section 6.2, “printa” for a more detailed description of the printa format string.

printa traces only a directive that the aggregation should be processed by the DTrace consumer. It does not process the aggregation in the kernel. Therefore, the time between the tracing of the printa directive and the actual processing of the directive depends on the factors that affect buffer processing. These factors include the aggregation rate, the buffering policy and, if the buffering policy is switching, the rate at which buffers are switched. See Chapter 3, Aggregations and Chapter 5, Buffers and Buffering for detailed descriptions of the factors.

4.3.6 printf

void printf(string format, ...)

Like trace, the printf action traces D expressions. However, printf allows for elaborate printf-style formatting. Like printf, 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 dtrace according to the specified format string. For example, the first two examples of trace from Chapter 1, About DTrace could be combined in a single printf:

printf("execname is %s; priority is %d", execname, curlwpsinfo->pr_pri);

For more information on printf, see Section 6.1, “printf”.

4.3.7 stack

void stack(int nframes)
void stack(void)

The stack action records a kernel stack trace to the directed buffer. The kernel stack will be nframes in depth. If nframes is not specified, the number of stack frames recorded is the number specified by the stackframes option. For example:

# dtrace -n gettimeofday:entry'{stack()}'
dtrace: description 'gettimeofday:entry' matched 1 probe
CPU     ID                    FUNCTION:NAME
  0    196               gettimeofday:entry 
              vmlinux`pollwake
              vmlinux`dtrace_stacktrace+0x30
              vmlinux`__brk_limit+0x1e1832d7
              vmlinux`__brk_limit+0x1e1913a1
              vmlinux`pollwake
              vmlinux`do_gettimeofday+0x1a
              vmlinux`ktime_get_ts+0xad
              vmlinux`systrace_syscall+0xde
              vmlinux`audit_syscall_entry+0x1d7
              vmlinux`system_call_fastpath+0x16

  0    196               gettimeofday:entry 
              vmlinux`dtrace_stacktrace+0x30
              vmlinux`__brk_limit+0x1e1832d7
              vmlinux`__brk_limit+0x1e1913a1
              vmlinux`security_file_permission+0x8b
              vmlinux`systrace_syscall+0xde
              vmlinux`audit_syscall_entry+0x1d7
              vmlinux`system_call_fastpath+0x16

...

The stack action is different from other actions in that it can also be used as the key to an aggregation:

# dtrace -n execve:entry'{@[stack()] = count()}'
dtrace: description 'execve:entry' matched 1 probe
^C


              vmlinux`dtrace_stacktrace+0x30
              vmlinux`__brk_limit+0x1e1832d7
              vmlinux`__brk_limit+0x1e1913a1
              vmlinux`dtrace_execve+0xcd
              vmlinux`audit_syscall_entry+0x1d7
              vmlinux`dtrace_stub_execve+0x6c
                2

              vmlinux`dtrace_stacktrace+0x30
              vmlinux`__brk_limit+0x1e1832d7
              vmlinux`__brk_limit+0x1e1913a1
              vmlinux`do_sigaction+0x13a
              vmlinux`dtrace_execve+0xcd
              vmlinux`audit_syscall_entry+0x1d7
              vmlinux`dtrace_stub_execve+0x6c
               13

...

4.3.8 sym

_symaddr sym(uintptr_t address)

sym prints the symbol that corresponds to a specified kernel-space address, for example: vmlinux'max_pfn. sym is an alias for func.

4.3.9 trace

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 following statements are examples of trace actions:

trace(execname);

trace(curlwpsinfo->pr_pri);

trace(timestamp / 1000);

trace(‘lbolt);

trace("somehow managed to get here");

4.3.10 tracemem

void tracemem(address, size_t nbytes)

The tracemem action takes a D expression as its first argument, address, and a constant as its second argument, nbytes. tracemem copies the memory from the address specified by address into the directed buffer for the length specified by nbytes.

The output format depends on the data printed. If dtrace decides that the data looks like an ASCII string, it prints it as text, and terminates the output with a null character (0). When dtrace decides that the data is binary, it prints it in hexadecimal form.

0      342                      write:entry
             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
         0: c0 de 09 c2 4a e8 27 54 dc f8 9f f1 9a 20 4b d1  ....J.’T..... K.
        10: 9c 7a 7a 85 1b 03 0a fb 3a 81 8a 1b 25 35 b3 9a  .zz.....:...%5..
        20: f1 7d e6 2b 66 6d 1c 11 f8 eb 40 7f 65 9a 25 f8  .}.+fm....@.e.%.
        30: c8 68 87 b2 6f 48 a2 a5 f3 a2 1f 46 ab 3d f9 d2  .h..oH.....F.=..
        40: 3d b8 4c c0 41 3c f7 3c cd 18 ad 0d 0d d3 1a 90  =.L.A<.<........

You can force tracemem to use always binary format by using the rawbytes option.

4.3.11 ustack

Note

If you want to perform symbol lookup in a stripped executable, you must specify the --export-dynamic option when linking the program. This option causes the linker to add all symbols to the dynamic symbol table (that is, the set of symbols which are visible from dynamic objects at run time). If you use gcc to link the objects, specify the option as -Wl,--export-dynamic to pass the correct option to the linker.

If you want to look up symbols in shared libraries or unstripped executables, the --export-dynamic option is not required.

DTrace supports the use of ustack with both 32-bit and 64-bit binaries.

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 user stack is nframes in depth. If nframes is not specified, the number of stack frames recorded is the number specified by the ustackframes option. While ustack is able to determine the address of the calling frames when the probe fires, the stack frames are not translated into symbols until the ustack action is processed at user level by the DTrace consumer. If strsize is specified and non-zero, ustack allocates the specified amount of string space, and use it to perform address-to-symbol translation directly from the kernel. Such direct user symbol translation is only used with stacktrace helpers that support this usage with DTrace. If such frames cannot be translated, the frames appear only as hexadecimal addresses.

The following example traces a stack with no address-to-symbol translation:

# dtrace -n syscall::write:entry'/pid == $target/{ustack(); \
exit(0)}' -c "./mytestprog -v"
dtrace: description 'syscall::write:entry' matched 1 probe
mytestprog (Version 1.0)
CPU     ID                    FUNCTION:NAME
  2      6                      write:entry 
              mytestprog`printver+0x2f
              mytestprog`0x401338
              mytestprog`main+0xc7
              mytestprog`0x401338
              libc.so.6`__libc_start_main+0xfd
              mytestprog`main
              mytestprog`0x400ad0
              mytestprog`__libc_csu_init
              mytestprog`0x400ad0
              mytestprog`0x400af9

The ustack symbol translation occurs after the stack data is recorded. Therefore, the corresponding user process might exit before symbol translation can be performed, making stack frame translation impossible. If the user process exits before symbol translation is performed, dtrace outputs a warning message, followed by the hexadecimal stack frames.

4.3.12 uaddr

DTrace supports the use of uaddr with both 32-bit and 64-bit binaries.

_usymaddr uaddr(uintptr_t address)

uaddr prints the symbol for a specified address, including hexadecimal offset. This allows for the same symbol resolution that ustack provides.

4.3.13 usym

DTrace supports the use of usym with both 32-bit and 64-bit binaries.

_usymaddr usym(uintptr_t address)

usym prints the symbol for a specified address. This is analogous to how uaddr works, but without the hexadecimal offsets.