copyin() and copyinstr() Subroutines

DTrace's
interaction with processes is a little different than most traditional debuggers
or observability tools. Many such tools appear to execute within the scope
of the process, letting users dereference pointers to program variables directly.
Rather than appearing to execute within or as part of the process itself,
DTrace probes execute in the Solaris kernel. To access process data, a probe
needs to use the copyin() or copyinstr() subroutines
to copy user process data into the address space of the kernel.

The arg1 variable, containing the value of the buf parameter, is an address that refers to memory in the process
executing the system call. To read the string at that address, use the copyinstr() subroutine and record its result with the printf() action:

The output of this script shows all of the strings being passed to the write(2) system call. Occasionally,
however, you might see irregular output similar to the following example:

0 37 write:entry madaï¿½ï¿½ï¿½

The copyinstr() subroutine acts on an input argument
that is the user address of a null-terminated ASCII string. However, buffers
passed to the write(2) system
call might refer to binary data rather than ASCII strings. To print only as
much of the string as the caller intended, use the copyin() subroutine,
which takes a size as its second argument:

syscall::write:entry
{
printf("%s", stringof(copyin(arg1, arg2)));
}

Notice that the stringof operator is necessary so
that DTrace properly converts the user data retrieved using copyin() to
a string. The use of stringof is not necessary when using copyinstr() because this function always returns type string.

Avoiding Errors

The copyin() and copyinstr() subroutines
cannot read from user addresses which have not yet been touched so even a
valid address may cause an error if the page containing that address has not
yet been faulted in by being accessed. Consider the following example:

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