DTrace User Guide

Using the copyin() and copyinstr() Subroutines

DTrace probes execute in the Solaris kernel. Probes use the copyin() or copyinstr() subroutines to copy user process data into the kernel's address space.

Consider the following write() system call:

ssize_t write(int fd, const void *buf, size_t nbytes);

The following D program illustrates an incorrect attempt to print the contents of a string that is passed to the write system call:

syscall::write:entry
{
	printf("%s", stringof(arg1)); /* incorrect use of arg1 */
}

When you run this script, DTrace produces error messages similar to the following example.


dtrace: error on enabled probe ID 1 (ID 37: syscall::write:entry): \
    invalid address (0x10038a000) in action #1

The arg1 variable is an address that refers to memory in the process that is executing the system call. Use the copyinstr() subroutine to read the string at that address. Record the result with the printf() action:

syscall::write:entry
{
	printf("%s", copyinstr(arg1)); /* correct use of arg1 */

The output of this script shows all of the strings that are passed to the write system call.

Avoiding Errors

The copyin() and copyinstr() subroutines cannot read from user addresses which have not yet been touched. A valid address might cause an error if the page that contains that address has not been faulted in by an access attempt. Consider the following example:


# dtrace -n syscall::open:entry'{ trace(copyinstr(arg0)); }'
dtrace: description 'syscall::open:entry' matched 1 probe
CPU     ID                    FUNCTION:NAME
dtrace: error on enabled probe ID 2 (ID 50: syscall::open:entry): invalid address
(0x9af1b) in action #1 at DIF offset 52

In the output from the previous example, the application was functioning properly and the address in arg0 was valid. However, the address in arg0 referred to a page that the corresponding process had not accessed. To resolve this issue, wait for the kernel or application to use the data before tracing the data. For example, you might wait until the system call returns to apply copyinstr(), as shown in the following example:


# dtrace -n syscall::open:entry'{ self->file = arg0; }' \
-n syscall::open:return'{ trace(copyinstr(self->file)); self->file = 0; }'
dtrace: description 'syscall::open:entry' matched 1 probe
CPU     ID                    FUNCTION:NAME
  2     51                      open:return   /dev/null