User Function Boundary Tracing

The simplest mode of operation for the pid provider is as the user space, analogous to the fbt provider. The following example program traces all function entries and returns that are made from a single function. The $1 macro variable, that is the first operand on the command line, is the process ID for the process to trace. The $2 macro variable, that is the second operand on the command line, is the name of the function from which all function calls are traced.

Example 12-1 Tracing User Function Entry and Return With userfunc.d

#!/usr/sbin/dtrace -s

#pragma D option flowindent

pid$1::$2:entry
{
        self->trace = 1;
}

pid$1::$2:return
/self->trace/
{
        self->trace = 0;
}

pid$1:::entry,
pid$1:::return
/self->trace/
{
}

Type in the preceding example script and save it in a file named userfunc.d, and then use the chmod command to set the execute permission. This script produces output similar to the following example:

# ./userfunc.d 15032 execute
dtrace: script './userfunc.d' matched 11594 probes
  0  -> execute                               
  0    -> execute                             
  0      -> Dfix                              
  0      <- Dfix                              
  0      -> s_strsave                         
  0        -> malloc                          
  0        <- malloc                          
  0      <- s_strsave                         
  0      -> set                               
  0        -> malloc                          
  0        <- malloc                          
  0      <- set                               
  0      -> set1                              
  0        -> tglob                           
  0        <- tglob                           
  0      <- set1                              
  0      -> setq                              
  0        -> s_strcmp                        
  0        <- s_strcmp                        
...

The pid provider can only be used on processes that are already running. You can use the $target macro variable and the dtrace -c and -p options to create and grab processes of interest and instrument them using DTrace. For more information about macro variables, see Scripting in DTrace. For example, the following D script can be used to determine the distribution of function calls made to libc by a particular subject process:

pid$target:libc.so::entry
{
        @[probefunc] = count();
}

To determine the distribution of such calls made by the date command, save the script in a file named libc.d and execute the following command:

# dtrace -s libc.d -c date
dtrace: script 'libc.d' matched 2476 probes
Fri Jul 30 14:08:54 PDT 2004
dtrace: pid 109196 has exited

  pthread_rwlock_unlock                                             1
  _fflush_u                                                         1
  rwlock_lock                                                       1
  rw_write_held                                                     1
  strftime                                                          1
  _close                                                            1
  _read                                                             1
  __open                                                            1
  _open                                                             1
  strstr                                                            1
  load_zoneinfo                                                     1

...
  _ti_bind_guard                                                   47
  _ti_bind_clear                                                   94