12.6.7 Address Spaces

DTrace executes D programs within the address space of the operating system kernel. Your entire Oracle Linux system manages one address space for the operating system kernel, and one for each user process. As each address space provides the illusion that it can access all of the memory on the system, the same virtual address might be used in different address spaces, but it would translate to different locations in physical memory. If your D programs use pointers, you need to be aware which address space corresponds to those pointers.

For example, if you use the syscall provider to instrument entry to a system call such as pipe() that takes a pointer to an integer or to an array of integers as an argument, it is not valid to use the * or [] operators to dereference that pointer or array. The address is in the address space of the user process that performed the system call, and not in the address space of the kernel. Dereferencing the address in D accesses the kernel's address space, which would result in an invalid address error or return unexpected data to your D program.

To access user process memory from a DTrace probe, use one of the copyin(), copyinstr(), or copyinto() functions with an address in user space.

The following D programs show two alternate and equivalent ways to print the file descriptor, string, and string length arguments that a process passed to the write() system call:

syscall::write:entry
{
  printf("fd=%d buf=%s count=%d", arg0, stringof(copyin(arg1, arg2)), arg2);
}

syscall::write:entry
{
  printf("fd=%d buf=%s count=%d", arg0, copyinstr(arg1, arg2), arg2);
}

The arg0, arg1 and arg2 variables contain the value of the fd, buf, and count arguments to the system call. Note that the value of arg1 is an address in the address space of the process, and not in the address space of the kernel.

In this example, it is necessary to use the stringof() function with copyin() so that DTrace converts the retrieved user data to a string. The copyinstr() function always returns a string.

To avoid confusion, you should name and comment variables that store user addresses appropriately. You should also store user addresses as variables of type uintptr_t so that you do not accidentally compile D code that dereferences them.