A pointer is an address that provides a translation within some virtual address space to a piece of physical memory. DTrace executes your D programs within the address space of the operating system kernel itself. Your entire Solaris system manages many address spaces: one for the operating system kernel, and one for each user process. Since each address space provides the illusion that it can access all of the memory on the system, the same virtual address pointer value can be reused across address spaces but translate to different physical memory. Therefore, when writing D programs that use pointers, you must be aware of the address space corresponding to the pointers you intend to use.
For example, if you use the syscall
provider to instrument entry to a system call that takes a pointer to an integer or array of integers as an argument (for example,
pipe
(
2
)
), it would not be valid to dereference that pointer or array using the *
or []
operators because the address in question is an address in the address space of the user process that performed the system call. Applying the *
or []
operators to this address in D would result in a kernel address space access, which would result in an invalid address error or in returning unexpected data to your D program depending upon whether the address happened to match a valid kernel address.
To access user process memory from a DTrace probe, you must apply one of the copyin
, copyinstr
, or copyinto
functions described in Chapter 10, Actions and Subroutines to the user address space pointer. Take care when writing your D programs to name and comment variables storing user addresses appropriately to avoid confusion. You can also store user addresses as uintptr_t
so you don't accidentally compile D code that dereferences them. Techniques for using DTrace on user processes are described in Chapter 33, User Process Tracing.