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

Document Information

Preface

1.  Introduction

2.  Types, Operators, and Expressions

3.  Variables

4.  D Program Structure

5.  Pointers and Arrays

6.  Strings

7.  Structs and Unions

8.  Type and Constant Definitions

9.  Aggregations

10.  Actions and Subroutines

11.  Buffers and Buffering

12.  Output Formatting

13.  Speculative Tracing

14.  dtrace(1M) Utility

15.  Scripting

16.  Options and Tunables

17.  dtrace Provider

18.  lockstat Provider

19.  profile Provider

20.  fbt Provider

21.  syscall Provider

22.  sdt Provider

23.  sysinfo Provider

24.  vminfo Provider

25.  proc Provider

26.  sched Provider

27.  io Provider

28.  mib Provider

29.  fpuinfo Provider

30.  pid Provider

31.  plockstat Provider

32.  fasttrap Provider

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

34.  Statically Defined Tracing for User Applications

35.  Security

36.  Anonymous Tracing

37.  Postmortem Tracing

38.  Performance Considerations

39.  Stability

40.  Translators

41.  Versioning

Glossary

Index

pid Provider

The pid provider enables you to trace any instruction in a process. Unlike most other providers, pid probes are created on demand based on the probe descriptions found in your D programs. As a result, no pid probes are listed in the output of dtrace -l until you have enabled them yourself.

User Function Boundary Tracing

The simplest mode of operation for the pid provider is as the user space analogue 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 (the first operand on the command line) is the process ID for the process to trace. The $2 macro variable (the second operand on the command line) is the name of the function from which to trace all function calls.

Example 33-1 userfunc.d: Trace User Function Entry and Return

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 above example script and save it in a file named userfunc.d, and then chmod it to be executable. 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 (see Chapter 15, Scripting) and the dtrace -c and -p options to create and grab processes of interest and instrument them using 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(1) 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

Tracing Arbitrary Instructions

You can use the pid provider to trace any instruction in any user function. Upon demand, the pid provider will create a probe for every instruction in a function. The name of each probe is the offset of its corresponding instruction in the function expressed as a hexadecimal integer. For example, to enable a probe associated with the instruction at offset 0x1c in function foo of module bar.so in the process with PID 123, you can use the following command:

# dtrace -n pid123:bar.so:foo:1c

To enable all of the probes in the function foo, including the probe for each instruction, you can use the command:

# dtrace -n pid123:bar.so:foo:

This command demonstrates an extremely powerful technique for debugging and analyzing user applications. Infrequent errors can be difficult to debug because they can be difficult to reproduce. Often, you can identify a problem after the failure has occurred, too late to reconstruct the code path. The following example demonstrates how to combine the pid provider with speculative tracing (see Chapter 13, Speculative Tracing) to solve this problem by tracing every instruction in a function.

Example 33-2 errorpath.d: Trace User Function Call Error Path

pid$1::$2:entry
{
    self->spec = speculation();
    speculate(self->spec);
    printf("%x %x %x %x %x", arg0, arg1, arg2, arg3, arg4);
}

pid$1::$2:
/self->spec/
{
    speculate(self->spec);
}

pid$1::$2:return
/self->spec && arg1 == 0/
{
    discard(self->spec);
    self->spec = 0;
}

pid$1::$2:return
/self->spec && arg1 != 0/
{
    commit(self->spec);
    self->spec = 0;
}

Executing errorpath.d results in output similar to the following example:

# ./errorpath.d 100461 _chdir
dtrace: script './errorpath.d' matched 19 probes
CPU     ID                    FUNCTION:NAME
  0  25253                     _chdir:entry 81e08 6d140 ffbfcb20 656c73 0
  0  25253                     _chdir:entry
  0  25269                         _chdir:0
  0  25270                         _chdir:4
  0  25271                         _chdir:8
  0  25272                         _chdir:c
  0  25273                        _chdir:10
  0  25274                        _chdir:14
  0  25275                        _chdir:18
  0  25276                        _chdir:1c
  0  25277                        _chdir:20
  0  25278                        _chdir:24
  0  25279                        _chdir:28
  0  25280                        _chdir:2c
  0  25268                    _chdir:return