Sun Studio 12 Update 1: Debugging a Program With dbx

Appendix B Event Management

Event management refers to the capability of dbx to perform actions when events take place in the program being debugged. When an event occurs, dbx allows you to stop a process, execute arbitrary commands, or print information. The simplest example of an event is a breakpoint. Examples of other events are faults, signals, system calls, calls to dlopen(), and data changes (see Setting Data Change Breakpoints).

This appendix is organized into the following sections:

Event Handlers





when event-specification {action; ... }


Event Safety





dbx protects itself by:



Creating Event Handlers

Use the when command, stop command, and trace command to create event handlers. (For detailed information, see when Command, stop Command, and trace Command.)

stop is shorthand for a common when idiom.

when event-specification { stop -update; whereami; }

An event-specification is used by the event management commands stop, when, and trace to specify an event of interest. (see Setting Event Specifications).

Most of the trace commands can be handcrafted using the when command, ksh functionality, and event variables. This is especially useful if you want stylized tracing output.

Every command returns a number known as a handler id (hid). You can access this number using the predefined variable $newhandlerid.

Manipulating Event Handlers

You can use the following commands to manipulate event handlers. For more information on each command, see the cited section.

Using Event Counters

An event handler has a trip counter, which has a count limit. Whenever the specified event occurs, the counter is incremented. The action associated with the handler is performed only if the count reaches the limit, at which point the counter is automatically reset to 0. The default limit is 1. Whenever a process is rerun, all event counters are reset.

You can set the count limit using the -count modifier with a stop command, when command, or trace command (see -count n-count infinity). Otherwise, use the handler command to individually manipulate event handlers.

handler [ -count | -reset ] hid new-count new-count-limit

Setting Event Specifications

Event specifications are used by the stop command, stopi command, when command, wheni command, trace command, and tracei command to denote event types and parameters. The format consists of a keyword representing the event type and optional parameters. The meaning of an event specification is generally identical for all three commands; exceptions are documented in the command descriptions (see stop Command, trace Command, and when Command).

Breakpoint Event Specifications


in function


 stop in mumble(int, float, struct Node *)

Note –

Do not confuse in function with the-in function modifier.

at [filename:]line_number


at address_expression


infile filename








infunction function


inmember function inmethod function


inclass classname [-recurse | -norecurse]


inobject object-expression [-recurse | -norecurse]


stop inclass dynamic_type(ox) -if this==ox

Data Change Event Specifications

The following are event specifications for events that involve access or change to the contents of a memory address.


The memory specified by address-expression has been accessed.

mode specifies how the memory was accessed. It can be composed of one or all of the letters:


The memory at the specified address has been read.


The memory has been written to.


The memory has been executed.

mode can also contain either of the following:


Stops the process after the access (default).


Stops the process before the access.

In both cases the program counter will point at the offending instruction. The “before” and “after” refer to the side effect.

address-expression is any expression that can be evaluated to produce an address. If you give a symbolic expression, the size of the region to be watched is automatically deduced; you can override it by specifying byte-size-expression. You can also use nonsymbolic, typeless address expressions; in which case, the size is mandatory. For example:

stop access w 0x5678, sizeof(Complex)

The access command has the limitation that no two matched regions may overlap.

Note –

The access event specification is a replacement for the modify event specification.

change variable

The value of variable has changed. The change event is roughly equivalent to:

when step { if [ $last_value !=$[variable]] 

This event is implemented using single-stepping. For faster performance, use the access event (see access mode address-expression [, byte-size-expression]).

The first time variable is checked causes one event, even though no change is detected. This first event provides access to the initial value of variable. Subsequent detected changes in the value of variable trigger additional events.

cond condition-expression

The condition denoted by condition-expression evaluates to true. You can specify any expression for condition-expression, but it must evaluate to an integral type. The cond event is roughly equivalent to:

stop step -if conditional_expression

System Event Specifications

The following are event specifications for system events.

dlopen [ lib-path ] dlclose [ lib-path ]

These events occur after a dlopen()() call or a dlclose()() call succeeds. A dlopen()() call or dlclose()() call can cause more than one library to be loaded. The list of these libraries is always available in the predefined variable $dllist. The first shell word in $dllist is a “+” or a “-”, indicating whether the list of libraries is being added or deleted.

lib-path is the name of a shared library. If it is specified, the event occurs only if the given library was loaded or unloaded. In that case, $dlobj contains the name of the library. $dllist is still available.

If lib-path begins with a /, a full string match is performed. Otherwise, only the tails of the paths are compared.

If lib-path is not specified, then the events always occur whenever there is any dl-activity. In this case, $dlobj is empty but $dllist is valid.

fault fault

The fault event occurs when the specified fault is encountered. The faults are architecture-dependent. The following set of faults known to dbx is defined in the proc(4) man page.




Illegal instruction 


Privileged instruction 


Breakpoint trap 


Trace trap (single step) 


Memory access (such as alignment) 


Memory bounds (invalid address) 


Integer overflow 


Integer zero divide 


Floating-point exception 


Irrecoverable stack fault 


Recoverable page fault 


Watchpoint trap 


CPU performance counter overflow 

Note –

BPT, TRACE, and BOUNDS are used by dbx to implement breakpoints and single-stepping. Handling them might interfere with how dbx works.

Note –

FLTBPT and FLTTRACE are ignored because they would interfere with basic dbx functionality such as breakpoints and single-stepping (see Event Safety).

These faults are taken from /sys/fault.h. fault can be any of those listed above, in uppercase or lowercase, with or without the FLT- prefix, or the actual numerical code.

Note –

The fault event is not available on Linux platforms.


The lwp_exit event occurs when lwp has been exited. $lwp contains the id of the exited LWP (lightweight process) for the duration of the event handler.

Note –

The lwpexit event is not available on Linux platforms.

sig signal

The sig signal event occurs when the signal is first delivered to the program being debugged. signal can be either a decimal number or the signal name in uppercase or lowercase; the prefix is optional. This is completely independent of the catch command and ignore command, although the catch command can be implemented as follows:

function simple_catch {
    when sig $1 {
            echo Stopped due to $sigstr $sig

Note –

When the sig event is received, the process has not seen it yet. Only if you continue the process with the specified signal is the signal forwarded to it.

sig signal sub-code

When the specified signal with the specified sub-code is first delivered to the child, the sig signal sub-code event occurs. As with signals, you can type the sub-code as a decimal number, in uppercase or lowercase; the prefix is optional.

sysin code | name

The specified system call has just been initiated, and the process has entered kernel mode.

The concept of system call supported by dbx is that provided by traps into the kernel as enumerated in /usr/include/sys/syscall.h.

This is not the same as the ABI notion of system calls. Some ABI system calls are partially implemented in user mode and use non-ABI kernel traps. However, most of the generic system calls (the main exception being signal handling) are the same between syscall.h and the ABI.

Note –

The sysin event is not available on Linux platforms.

Note –

The list of kernel system call traps in /usr/include/sys/syscall.h is part of a private interface in the Solaris OS that changes from release to release. The list of trap names (codes) and trap numbers that dbx accepts includes all of those supported by any of the versions of the Solaris OS that dbx supports. It is unlikely that the names supported by dbx exactly match those of any particular release of the Solaris OS, and some of the names in syscall.h might not be available. Any trap number (code) is accepted by dbx and works as expected, but a warning is issued if it does not correspond to a known system call trap.

sysout code | name

The specified system call is finished, and the process is about to return to user mode.

Note –

The sysout event is not available on Linux platforms.

sysin | sysout

Without arguments, all system calls are traced. Certain dbx features, for example, the modify event and runtime checking, cause the child to execute system calls for its own purposes and show up if traced.

Execution Progress Event Specifications

The following are event specifications for events pertaining to execution progress.

exit exitcode

The exit event occurs when the process has exited.





returns function


SPARC based systems


x86 based systems


x64 based systems

$rax, $rdx

The event is roughly equivalent to:

when in func { stop returns; }





Note –


Other Event Specifications

The following are event specifications for other types of events.


dbx has successfully attached to a process.


dbx has successfully detached from the program being debugged.




Note –

The lastrites event is not available on Linux platforms.





Note –

Handlers for this event are always permanent.



display x
when stop {print x;}




Note –

The sync event is not available on Linux platforms.




thr_create [thread_id]


stop thr_create t@5 -thread t@1



stop thr_exit -thread t@5



Note –

The throw event is not available on Linux platforms.

throw type


throw -unhandled


throw -unexpected


timer seconds


Event Specification Modifiers


-if condition





-in function



The-disable modifier creates the handler in the disabled state.

-count n-count infinity






Use the delete -temp command to delete all temporary handlers.



-thread thread_id


-lwp lwp_id






Parsing and Ambiguity

The syntax for event specifications and modifiers is:

Expressions can have spaces embedded in them, causing ambiguous situations. For example, consider the following two commands:

when a -temp
when a-temp

In the first example, even though the application might have a variable named temp, the dbx parser resolves the event specification in favor of-temp being a modifier. In the second example, a-temp is collectively passed to a language-specific expression parser. There must be variables named a and temp or an error occurs. Use parentheses to force parsing.

Using Predefined Variables

Certain read-only ksh predefined variables are provided. The following variables are always valid:




Disassembly of the current instruction. 


Current line number in decimal. 


Current “visiting” line number in decimal. 


Contents of the current line. 


Name of the current function. 


Name of the current “visiting” function. 


Name of the class to which $func belongs.


Name of the class to which $vfunc belongs.


Name of the current file. 


Name of the current file being visited. 


Name of the current loadable object. 


Name of the current loadable object being visited. 


Scope of the current PC in back-quote notation. 


Scope of the visited PC in back-quote notation. 


Address of $func in hex.


Name of the function calling $func.


After a dlopen or dlclose event, contains the list of load objects just loaded or unloaded. The first word of dllist is a “+” or a “-” depending on whether a dlopen or a dlclose has occurred.


ID of the most recently created handler. This variable has an undefined value after any command that deletes handlers. Use the variable immediately after creating a handler. dbx cannot capture all of the handler IDs for a command that creates multiple handlers.


List of handler ids that caused the most recent stoppage. The handlers on the list are marked with “*” in the output of the status command.


Process ID of the current process being debugged. 


Lwp ID of the current LWP. 


Thread ID of the current thread. 


lwp ID of a newly created LWP. 


Thread ID of a newly created thread. 


Full path name of the program being debugged. 


Previous value of $prog, which is used to get back to what you were debugging following an exec(), when $prog reverts to “-”. While $prog is expanded to a full path name, $oprog contains the program path as specified on the command line or to the debug command. If exec() is called more than once, there is no way to return to the original program.


True if the dbx binary is 32–bit.


Exit status from the last run of the program. The value is an empty string if the process has not exited. 


Set to true if the event occurs during the “boot” process. Whenever a new program is debugged, it is first booted so that the list and location of shared libraries can be ascertained. The process is then killed. This sequence is termed booting.

While booting is occurring, all events are still available. Use this variable to distinguish, for example, the sync and syncrtld events occurring during a debugging run and the ones occurring during a normal run.

As an example, consider that whereami can be implemented as:

function whereami {
  echo Stopped in $func at line $lineno in file $(basename $file)
  echo "$lineno\t$line"

Variables Valid for when Command

The following variables are valid only within the body of a when command.


During the execution of the body, $handlerid is the id of the when command to which the body belongs. These commands are equivalent:

when X -temp { do_stuff; }
when X  { do_stuff; delete $handlerid; }

Variables Valid for when Command and Specific Events

Certain variables are valid only within the body of a when command and for specific events as shown in the following tables.

Table B–1 Variables Valid for sig Event




Signal number that caused the event 


Name of $sig


Subcode of $sig if applicable


Name of $sigcode


Process ID of sender of the signal, if appropriate 

Table B–2 Variable Valid for exit Event




Value of the argument passed to _exit(2) or exit(3) or the return value of main

Table B–3 Variable Valid for dlopen and dlclose Events




Pathname of the load object dlopened or dlclosed 

Table B–4 Variables Valid for sysin and sysout Events




System call number 


System call name 

Table B–5 Variable Valid for proc_gone Events




One of signal, exit, kill, or detach 

Table B–6 Variables Valid for thr_create Event




Id of the newly created thread (for example, t@5)


Id of the newly created LWP (for example, l@4)

Table B–7 Variables Valid for watch Event




The address being written to, read from, or executed 


One of the following: r for read, w for write, x for execute; followed by one of the following: a for after, b for before 

Event Handler Examples

The following are some examples of setting event handlers.

Setting a Breakpoint for Store to an Array Member

To set a data change breakpoint on array[99], type:

(dbx) stop access w &array[99]
(2) stop access w &array[99], 4
(dbx) run
Running: watch.x2
watchpoint array[99] (0x2ca88[4]) at line 22 in file "watch.c"    
   22    array[i] = i;

Implementing a Simple Trace

To implement a simple trace, type:

(dbx) when step { echo at line $lineno; }

Enabling a Handler While Within a Function (in function)

To enable a handler while within a function, type:

<dbx> trace step -in foo

This is equivalent to:

    # create handler in disabled state
    when step -disable { echo Stepped to $line; }
    t=$newhandlerid    # remember handler id
    when in foo {
    # when entered foo enable the trace
    handler -enable "$t"
    # arrange so that upon returning from foo,
    # the trace is disabled.
    when returns { handler -disable "$t"; };

Determining the Number of Lines Executed

To see how many lines have been executed in a small program, type:

(dbx) stop step -count infinity     # step and stop when count=inf
(2) stop step -count 0/infinity
(dbx) run
(dbx) status
(2) stop step -count 133/infinity

The program never stops, the program terminates. The number of lines executed is 133. This process is very slow. It is most useful with breakpoints on functions that are called many times.

Determining the Number of Instructions Executed by a Source Line

To count how many instructions a line of code executes, type:

(dbx) ...                        # get to the line in question
(dbx) stop step -instr -count infinity
(dbx) step ...
(dbx) status
(3) stop step -count 48/infinity # 48 instructions were executed

If the line you are stepping over makes a function call, the lines in the function are counted as well. You can use the next event instead of step to count instructions, excluding called functions.

Enabling a Breakpoint After an Event Occurs


(dbx) when in lookup -count 1300 {
    stop in hash
    when proc_gone -temp { delete $hash_bpt; }

Note –

$newhandlerid is referring to the just executed stop incommand.

Resetting Application Files for replay

If your application processes files that need to be reset during a replay, you can write a handler to do that each time you run the program:

(dbx) when sync { sh regen ./database; }
(dbx) run < ./database...    # during which database gets clobbered
(dbx) save
...              # implies a RUN, which implies the SYNC event which
(dbx) restore       # causes regen to run

Checking Program Status

To see quickly where the program is while it is running, type:

(dbx) ignore sigint
(dbx) when sig sigint { where; cancel; }

Then type ^C to see a stack trace of the program without stopping it.

This is basically what the collector hand sample mode does (and more). Use SIGQUIT (^\) to interrupt the program because ^C is now used up.

Catch Floating Point Exceptions

To catch only specific floating point exceptions, for example, IEEE underflow, type:

(dbx) ignore FPE               # turn off default handler
(dbx) help signals | grep FPE  # can’t remember the subcode name
(dbx) stop sig fpe FPE_FLTUND