Debugging a Program With dbx

Setting Event Specifications

Event specifiers are used by the stop, when and trace commands to denote event types and parameters. The format is that of a keyword to represent the event type and optional parameters.

Breakpoint Event Specifications

The following are event specifications, syntax and descriptions for breakpoint events.

in func

The function has been entered and the first line is about to be executed. If the -instr modifier is used, it is the first instruction of the function about to be executed. (Do not confuse in func with the -in func modifier.) The func specification can take a formal parameter signature to help with overloaded function names, or template instance specification. For example, you can say:


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

at lineno

The designated line is about to be executed. If filename is specified, then the designated line in the specified file is about to be executed. The file name can be the name of a source file or an object file. Although quote marks are not required, they may be necessary if the file name contains odd characters.


at filename:lineno

If the designated line is in template code, a breakpoint is placed on all instances of that template.

infunction func

Equivalent to in func for all overloaded functions named func, or all template instantiations thereof.

inmember funcinmethod func

Equivalent to in func for the member function named func for every class.

inclass classname

Equivalent to in func for all member functions that are members of classname.

inobject obj-expr

A member function called on the specific object at the address denoted by obj-expr has been called.

Watchpoint Event Specifications

The following are event specifications, syntax, and descriptions for watchpoint events.

access mode addr-exp, [byte-size-exp]

The memory specified by addr-exp has been accessed.

addr-exp is any expression that can be evaluated to produce an address. If a symbolic expression is used, the size of the region to be watched is automatically deduced, or you can override that with the `,` syntax. You can also use nonsymbolic, typeless address expressions; in which case, the size is mandatory. For example:


stop modify 0x5678, sizeof(Complex)

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

r

The memory has been read. 

w

The memory has been written to. 

x

The memory has been executed. 

mode can also contain one of:

a

Stops the process after the access (default). 

b

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.

access is a replacement for modify. While both syntaxes work on Solaris 2.4, 2.5, 2.5.1, 2.6, and Solaris 7, on all of these operating environments except Solaris 2.6, access suffers the same limitations as modify and accepts only a mode of wa.

Limitations of access

No two matched regions may overlap.

change variable

The value of variable has changed.

cond cond-expr

The condition denoted by cond-expr evaluates to true. Any expression can be used for cond-expr, but it has to evaluate to an integral type.

modify addr-exp [ , byte-size ]

The specified address range has been modified. This is the older watchpoint facility.

addr-exp is any expression that can be evaluated to produce an address. If a symbolic expression is used, the size of the region to be watched is automatically deduced, or you can override that with the `,` syntax. You can also use nonsymbolic, typeless address expressions; in which case, the size is mandatory. For example:


stop modify 0x5678, sizeof(Complex)

Limitations of modify event-spec on Solaris 2.5.1

Addresses on the stack cannot be watched.

The event does not occur if the address being watched is modified by a system call.

Shared memory (MAP_SHARED) cannot be watched, because dbx cannot catch the other processes stores into shared memory. Also, dbx cannot properly deal with SPARC swap and ldstub instructions.

Addresses that do not exist at the time a handler for this event is created cannot be watched.


Note -

Multithreaded applications are prone to deadlock so mt watchpoints are nominally disallowed. They can be turned on by setting the dbx environment variable mt_watchpoints.


System Event Specifications

The following are event specifications, syntax, and descriptions for system events.

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

These events are fired after a dlopen() or a dlclose() call succeeds. A dlopen() 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 word in $dllist is actually a "+" or a "-", indicating whether the list of libraries is being added or deleted.

lib-path is the name of a shared library you are interested in. If it is specified, the event only fires 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

This event fires when the specified fault occurs. The faults are architecture dependent, but a set of them is known to dbx as defined by proc(4):

FLTILL

Illegal instruction 

FLTPRIV

Privileged instruction 

FLTBPT

Breakpoint instruction 

FLTTRACE*

Trace trap (single step) 

FLTACCESS*

Memory access (such as alignment) 

FLTBOUNDS*

Memory bounds (invalid address) 

FLTIOVF

Integer overflow 

FLTIZDIV

Integer zero divide 

FLTPE

Floating-point exception 

FLTSTACK

Irrecoverable stack fault 

FLTPAGE

Recoverable page fault 


Note -

Be aware that BPT, TRACE, and BOUNDS are used by dbx to implement breakpoints, single-stepping, and watchpoints. Handling them may interfere with the inner workings of dbx.


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

lwp_exit

Fired when lwp has been exited. $lwp contains the id of the exited LWP.

sig sig

This event occurs when the signal is first delivered to the debugee. sig can either be a decimal number or the signal name in upper or lower case; the prefix is optional. This is completely independent of the catch/ignore commands, although the catch command can be implemented as follows:


function simple_catch {
	when sig $1 {
			stop;
			echo Stopped due to $sigstr $sig
			whereami
	}
}


Note -

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


sig sig sub-code

When the specified signal with the specified sub-code is first delivered to the child, this event fires. Just as with signals, the sub-code can be entered as a decimal number, in capital or lower case; 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 procfs(4). These are 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.

sysout code | name

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

sysin | sysout

Without arguments, all system calls are traced. Note that certain dbx features, for example modify event and RTC, cause the child to execute system calls for their own purposes and show up if traced.

Execution Progress Event Specifiers

The following are event specifications, syntax, and descriptions for events pertaining to execution progress.

next

Similar to step except that functions are not stepped into.

returns

This event is just a breakpoint at the return point of the current visited function. The visited function is used so that you can use the returns event spec after doing a number of up's. The plain returns event is always -temp and can only be created in the presence of a live process.

returns func

This event executes each time the given function returns to its call site. This is not a temporary event. The return value is not provided, but you can find integral return values by accessing:

Sparc 

$o0

Intel 

$eax

It is another way of saying:


when in func { stop returns; }

step

The step event occurs when the first instruction of a source line is executed. For example, you can get simple tracing with:


when step { echo $lineno: $line; }

When enabling a step event you instruct dbx to single-step automatically next time cont is used. The step command can be implemented as follows:


alias step="when step -temp { whereami; stop; }; cont"

Other Event Specifications

The following are event specificatons, syntax, and descriptions for other types of events.

attach

dbx has successfully attached to a process.

detach

The debugee has been detached from.

lastrites

The process being debugged is about to expire. There are only three reasons this can happen:

proc_gone

Fired when dbx is no longer associated with a debugged process. The predefined variable $reason will be signal, exit, kill, or detach.

prog_new

Fired when a new program has been loaded as a result of follow exec.


Note -

Handlers for this event are always permanent.


stop

The process has stopped. Whenever the process stops such that the user gets a prompt, particularly in response to a stop handler, this event occurs. For example, the following are equivalent:


display x
when stop {print x;}

sync

The process being debugged has just been executed with exec(). All memory specified in a.out is valid and present but pre-loaded shared libraries have not been loaded yet. For example, printf, although known to dbx, has not been mapped into memory yet.

A stop on this event is ineffective; however, you can use this event with the when command.

syncrtld

This event occurs after a sync (or attach if the process being debugged has not yet processed shared libraries). It executes after the dynamic linker startup code has executed and the symbol tables of all preloaded shared libraries have been loaded, but before any code in the .init section has run.

A stop on this event is ineffective; however, you can use this event with the when command.

throw

This event occurs whenever any exception that is not unhandled or unexpected is thrown by the application.

throw type

If an exception type is specified, only exceptions of that type cause the throw event to occur.

throw -unhandled

-unhandled is a special exception type signifying an exception that is thrown but for which there is no handler.

throw -unexpected

-unexpected is a special exception type signifying an exception that does not satisfy the exception specification of the function that throw it.

timer seconds

Occurs when the debugee has been running for seconds. The timer used with this is shared with collector command. The resolution is in milliseconds, so a floating point value for seconds is acceptable.

Event Specification Modifiers

An event specification modifier sets additional attributes of a handler, the most common kind being event filters. Modifiers have to appear after the keyword portion of an event spec. They all begin with a dash (-), preceded by blanks. Modifiers consist of the following:

-if cond

The condition is evaluated when the event specified by the event-spec occurs. The side effect of the handler is allowed only if the condition evaluates to nonzero.

If -if is used with an event that has an associated singular source location, such as in or at, cond is evaluated in the scope corresponding to that location, otherwise it should be properly qualified with the desired scope.

-in func

The handler is active only while within the given function, or any function called from func. The number of times the function is entered is reference counted so as to properly deal with recursion.

-disable

Create the handler in the disabled state.

-count n-count infinity

Have the handler count from 0. Each time the event occurs, the count is incremented until it reaches n. Once that happens, the handler fires and the counter is reset to zero.

Counts of all enabled handlers are reset when a program is run or rerun. More specifically, they are reset when the sync event occurs.

-temp

Create a temporary handler. Once the event is fired it is automatically deleted. By default, handlers are not temporary. If the handler is a counting handler, it is automatically deleted only when the count reaches 0 (zero).

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

-instr

Makes the handler act at an instruction level. This replaces the traditional 'i' suffix of most commands. It usually modifies two aspects of the event handler.

-thread tid

The event is executed only if the thread that caused it matches tid.

-lwp lid

The event is executed only if the thread that caused it matches lid.

-hidden

Makes the handler not show up in a regular status command. Use status -h to see hidden handlers.

-perm

Normally all handlers get thrown away when a new program is loaded. Using this modifier causes the handler to be retained across debuggings. A plain delete command will not delete a permanent handler. Use delete -p to delete a permanent handler.