ustack Action

void ustack(int nframes, int strsize)
void ustack(int nframes)
void ustack(void)

The ustack action records a user stack trace to the directed buffer. The user stack will be nframes in depth. If nframes is not provided, the number of stack frames recorded is the number specified by the ustackframes option. The ustack action determines the frame's program counters at the point that the probe fires. These program counters are translated once the action is processed at user-level by the DTrace consumer. The translation can be modified by using the uresolve option. For more information, see DTrace User Address Symbol Resolution.

If strsize is specified and non-zero, ustack allocates the specified amount of string space, and uses it to perform address-to-symbol translation directly from the kernel. This direct user symbol translation is currently available only for Java Virtual Machines, version 1.5 and higher. Java address-to-symbol translation annotates user stacks that contain Java frames with the Java class and method name. If such frames cannot be translated, the frames will appear only as hexadecimal addresses.

The following example traces a stack with no string space, and therefore no Java address-to-symbol translation:

# dtrace -n syscall::write:entry'/pid == $target/{ustack(50, 0); 
    exit(0)}' -c "java -version"
dtrace: description 'syscall::write:entry' matched 1 probe
java version "1.5.0-beta3"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta3-b58)
Java HotSpot(TM) Client VM (build 1.5.0-beta3-b58, mixed mode)
dtrace: pid 5312 has exited
CPU     ID                    FUNCTION:NAME
  0     35                      write:entry 
              libc.so.1`_write+0x15
              libjvm.so`__1cDhpiFwrite6FipkvI_I_+0xa8
              libjvm.so`JVM_Write+0x2f
              d0c5c946
              libjava.so`Java_java_io_FileOutputStream_writeBytes+0x2c
              cb007fcd
              cb002a7b
              cb002a7b
              cb002a7b
              cb002a7b
              cb002a7b
              cb002a7b
              cb002a7b
              cb002a7b
              cb002a7b
              cb002a7b
              cb002a7b
              cb002a7b
              cb002a7b
              cb000152
              libjvm.so`__1cJJavaCallsLcall_helper6FpnJJavaValue_
                          pnMmethodHandle_pnRJavaCallArguments_
                          pnGThread__v_+0x187
              libjvm.so`__1cCosUos_exception_wrapper6FpFpnJJavaValue_
                          pnMmethodHandle_pnRJavaCallArguments_
                          pnGThread__v2468_v_+0x14
              libjvm.so`__1cJJavaCallsEcall6FpnJJavaValue_nMmethodHandle_
                          pnRJavaCallArguments_pnGThread __v_+0x28
              libjvm.so`__1cRjni_invoke_static6FpnHJNIEnv__pnJJavaValue_
                          pnI_jobject_nLJNICallType_pnK_jmethodID_pnSJNI_
                          ArgumentPusher_pnGThread__v_+0x180
              libjvm.so`jni_CallStaticVoidMethod+0x10f
              java`main+0x53d

Notice that the C and C++ stack frames from the Java virtual machine are presented symbolically using C++ "mangled" symbol names, and the Java stack frames are presented only as hexadecimal addresses. The following example shows a call to ustack with a non-zero string space:

# dtrace -n syscall::write:entry'/pid == $target/{ustack(50, 500); exit(0)}' -c "java -version"
dtrace: description 'syscall::write:entry' matched 1 probe
java version "1.5.0-beta3"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta3-b58)
Java HotSpot(TM) Client VM (build 1.5.0-beta3-b58, mixed mode)
dtrace: pid 5308 has exited
CPU     ID                    FUNCTION:NAME
  0     35                      write:entry 
              libc.so.1`_write+0x15
              libjvm.so`__1cDhpiFwrite6FipkvI_I_+0xa8
              libjvm.so`JVM_Write+0x2f
              d0c5c946
              libjava.so`Java_java_io_FileOutputStream_writeBytes+0x2c
              java/io/FileOutputStream.writeBytes
              java/io/FileOutputStream.write
              java/io/BufferedOutputStream.flushBuffer
              java/io/BufferedOutputStream.flush
              java/io/PrintStream.write
              sun/nio/cs/StreamEncoder$CharsetSE.writeBytes
              sun/nio/cs/StreamEncoder$CharsetSE.implFlushBuffer
              sun/nio/cs/StreamEncoder.flushBuffer
              java/io/OutputStreamWriter.flushBuffer
              java/io/PrintStream.write
              java/io/PrintStream.print
              java/io/PrintStream.println
              sun/misc/Version.print
              sun/misc/Version.print
              StubRoutines (1)
              libjvm.so`__1cJJavaCallsLcall_helper6FpnJJavaValue_
                          pnMmethodHandle_pnRJavaCallArguments_pnGThread
                          __v_+0x187
              libjvm.so`__1cCosUos_exception_wrapper6FpFpnJJavaValue_
                          pnMmethodHandle_pnRJavaCallArguments_pnGThread
                          __v2468_v_+0x14
              libjvm.so`__1cJJavaCallsEcall6FpnJJavaValue_nMmethodHandle
                          _pnRJavaCallArguments_pnGThread__v_+0x28
              libjvm.so`__1cRjni_invoke_static6FpnHJNIEnv__pnJJavaValue_pnI
                          _jobject_nLJNICallType_pnK_jmethodID_pnSJNI
                          _ArgumentPusher_pnGThread__v_+0x180
              libjvm.so`jni_CallStaticVoidMethod+0x10f
              java`main+0x53d
              8051b9a

The previous example output demonstrates symbolic stack frame information for Java stack frames. There are still some hexadecimal frames in this output because some functions are static and do not have entries in the application symbol table. Translation is not possible for these frames.

The ustack symbol translation for non-Java frames occurs after the stack data is recorded. Therefore, the corresponding user process might exit before symbol translation can be performed, making stack frame translation impossible. If the user process exits before symbol translation is performed, dtrace will emit a warning message, followed by the hexadecimal stack frames, as shown in the following example:

  dtrace: failed to grab process 100941: no such process
                c7b834d4
                c7bca85d
                c7bca1a4
                c7bd4374
                c7bc2628
                8047efc

Techniques for mitigating this problem are described in User Process Tracing.

Finally, because the postmortem DTrace debugger commands cannot perform the frame translation, using ustack with a ring buffer policy always results in raw ustack data.

The following D program shows an example of ustack that leaves strsize unspecified:

syscall::brk:entry
/execname == $$1/
{
        @[ustack(40)] = count();
}

To run this example for the Oracle Solaris prstat command use the following command:

# dtrace -s brk.d prstat
dtrace: script 'brk.d' matched 1 probe
^C


              libc.so.1`_brk_unlocked+0xa
              libc.so.1`sbrk+0x2d
              libc.so.1`_morecore+0x116
              libc.so.1`_malloc_unlocked+0x193
              libc.so.1`malloc+0x32
              libcurses.so.1`_makenew+0x95
              libcurses.so.1`newwin+0x51
              libcurses.so.1`newscreen+0x593
              libcurses.so.1`initscr32+0x53
              prstat`curses_on+0x2a
              prstat`main+0x7c9
              prstat`0x4057f4
                1

              libc.so.1`_brk_unlocked+0xa
              libc.so.1`sbrk+0x2d
              libc.so.1`_morecore+0x116
              libc.so.1`_malloc_unlocked+0x193
              libc.so.1`malloc+0x32
              libc.so.1`calloc+0x59
              libc.so.1`textdomain+0x36
              prstat`main+0x3d
              prstat`0x4057f4
                1

If the load object contains suitable DWARF then ustack can append the file name and line number of the corresponding source code to the frame description. For the following example, prstat, libcurses, and libc have been built with DWARF:

# dtrace -x uresolve=basename -s brk.d prstat
dtrace: script 'brk.d' matched 1 probe
^C


              libc.so.1`_brk_unlocked+0xa
              libc.so.1`sbrk+0x2d (sbrk.c:48)
              libc.so.1`_morecore+0x116 (malloc.c:730)
              libc.so.1`_malloc_unlocked+0x193 (malloc.c:260)
              libc.so.1`malloc+0x32 (malloc.c:158)
              libcurses.so.1`_makenew+0x95 (makenew.c:53)
              libcurses.so.1`newwin+0x51 (newwin.c:41)
              libcurses.so.1`newscreen+0x593 (newscreen.c:236)
              libcurses.so.1`initscr32+0x53 (initscr.c:58)
              prstat`curses_on+0x2a (prstat.c:1314)
              prstat`main+0x7c9 (prstat.c:1770)
              prstat`0x4057f4
                1

              libc.so.1`_brk_unlocked+0xa
              libc.so.1`sbrk+0x2d (sbrk.c:48)
              libc.so.1`_morecore+0x116 (malloc.c:730)
              libc.so.1`_malloc_unlocked+0x193 (malloc.c:260)
              libc.so.1`malloc+0x32 (malloc.c:158)
              libc.so.1`calloc+0x59 (calloc.c:36)
              libc.so.1`textdomain+0x36 (gettext.c:88)
              prstat`main+0x3d (prstat.c:1564)
              prstat`0x4057f4
                1