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. The Linux system manages many address spaces: one for the operating system kernel and one for each user process. Because 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()
, 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 kernel address space access, which would result in an
invalid address error or in returning unexpected data to your D
program, depending on 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 that are described in Chapter 4, Actions and Subroutines to
the user address space pointer. To avoid confusion, take care
when writing your D programs to name and comment variables
storing user addresses appropriately. You can also store user
addresses as uintptr_t
so that you do not
accidentally compile D code that dereferences them. Techniques
for using DTrace on user processes are described in
Chapter 12, User Process Tracing.