JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
Oracle Solaris Dynamic Tracing Guide     Oracle Solaris 11 Information Library
search filter icon
search icon

Document Information


1.  About DTrace

2.  D Programming Language

3.  Aggregations

4.  Actions and Subroutines

5.  Buffers and Buffering

6.  Output Formatting

7.  Speculative Tracing

8.  dtrace(1M) Utility

9.  Scripting

10.  Options and Tunables

11.  Providers

12.  User Process Tracing

copyin and copyinstr Subroutines

Avoiding Errors

Eliminating dtrace(1M) Interference

syscall Provider

ustack Action

uregs[] Array

pid Provider

User Function Boundary Tracing

Tracing Arbitrary Instructions

13.  Statically Defined Tracing for User Applications

14.  Security

15.  Anonymous Tracing

16.  Postmortem Tracing

17.  Performance Considerations

18.  Stability

19.  Translators

20.  Versioning

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

For example, consider the following write(2) 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 passed to the write(2) system call:

        printf("%s", stringof(arg1)); /* incorrect use of arg1 */

If you try to run this script, DTrace will produce 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, 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:

        printf("%s", copyinstr(arg1)); /* correct use of arg1 */

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 or to ASCII strings which don't include a terminating null byte. To print only as much of the string as the caller intended, use the two parameter version of the copyinstr subroutine which includes the size of the targeted string buffer:

        printf("%s", copyinstr(arg1, arg2));

An alternate way to accomplish the same end would be to use the copyin subroutine which takes an address and size:

        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:

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

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:

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