Debugging a Program With dbx

Appendix C User Tips

This appendix includes the following tips:

Using dbx Equivalents for Common GDB Commands

Table C-1 lists approximate equivalent dbx commands for some common GNU Debugging (GDB) commands:

Table C-1 dbx Equivalents for Common GDB Commands

GDB

DBX

break line

stop at line

break func

stop in func

break *addr

stopi at addr

break ... if expr

stop ... -if expr

cond n

stop ... -if expr

tbreak

stop ... -temp

watch expr

stop expr [slow]

watch var

stop modify &var [fast]

catch x

intercept x

info break

status

info watch

status

clear

clear

clear fun

delete n

delete

delete all

disable

handler -disable all

disable n

handler -disable n

enable

handler -enable all

enable n

handler -enable n

ignore n cnt

handler -count n cnt

commands n

when ... { cmds; }

backtrace n

where n

frame n

frame n

info reg reg

print $reg

finish

step up

signal num

cont sig num

jump line

cont at line

set var=expr

assign var=expr

x/fmt addr

x addr/fmt

disassem addr

dis addr

shell cmd

sh cmd [if needed]

info func regex

funcs regexp

ptype type

whatis -t type

define cmd

function cmd

handle sig

stop sig sig

info signals

status; catch

attach pid

debug - pid

attach pid

debug a.out pid

file file

[unnecessary]

exec file

debug file

core file

debug a.out corefile

set editing on

set -o emacs

set language x

language x

set prompt x

PS1=x

set history size x

HISTSIZE=x

set print object on

dbxenv output_dynamic_type on

show commands

history

dir name

pathmap name

show dir

pathmap

info line <n

listi n

info source

file

info sources

files; modules

forw regex

search regexp

rev regex

bsearch regexp

Changes in dbx Since Release 2.0.1

A number of features have been added and changed in dbx since release 2.0.1. For lists of the changes from release to release, type help changes on the dbx command line or see the What's Changed in dbx section of the Sun WorkShop online help

Some of the differences between the current release and release 2.0.1 (or other vendors'variations of dbx) are described in the following sections.

Using the .dbxinit File

Long-time users of dbx might be using the .dbxinit file instead of the newer .dbxrc file. If you have a .dbxrc file, dbx reads it and ignores any .dbxinit file present. If necessary, you can get dbx to read both by adding the following lines to your .dbxrc file:


kalias alias=dalias
source ~/.dbxinit
kalias alias=kalias

If you don't have a .dbxrc file, but do have a .dbxinit file, you should see the warning message:


Using .dbxinit compatibility mode. See `help .dbxrc' for more information.

Currently, dbx still reads your .dbxinit file, although this feature may disappear in a future release.

If you still use a .dbxinit file, see Chapter 2, Customizing dbx" for information about using the .dbxrc file instead.

Alias Definition

The alias command is now a pre-defined alias for dalias or kalias.

The Symbols / and ?

With the introduction of a KornShell-based parser, the / (forward slash) command had to be renamed because it cannot be distinguished from a UNIX pathname. Use search instead.

This example


(dbx) /abc

now means to execute the file abc from the root directory.

Similarly, ? (question mark) had to be renamed because it is now a shell metacharacter. Use bsearch instead.

This example reads expand the pattern that matches all files in the current directory with a four-character filename having abc as the last three characters, then execute the resulting command.


(dbx) ?abc

If you use these commands frequently, you may wish to create aliases for them

alias ff=search

find forward 

alias fb=bsearch

find backward 

Embedded Slash Command

The embedded slash command was renamed. This is no longer valid:


0x1234/5X

Use the examine command or its alias, x:


examine 0x1234/5X
x 0x1234/5X

Using assign Instead of set

set is now the KornShell set command, and is no longer an alias for assign.

Enabling Command-Line Editing

You can enable command-line editing in several ways. First, if $FCEDIT, $EDITOR, or $VISUAL is set in the shell from which dbx is started, its value is checked. If the last component, the component after the last slash, contains the string emacs, then emacs-mode is enabled. If it contains vi, vi-mode is enabled. If none of the three environment variables is set or if the first one in the list that is set does not contain emacs or vi, then command-line editing is disabled.

You can enable emacs mode or vi mode from the command line or in your .dbxrc file:


set -o emacs
set -o vi

To disable command-line editing:


set +o emacs +o vi

Being In Scope

If dbx claims that abc is not defined in the current scope, it means that no symbol named abc is accessible from the current location. See Chapter 3, Viewing and Visiting Code" for details. The current location is usually where the program has stopped at a breakpoint

Locating Files

All files created by dbx are placed in the directory /tmp unless the environment variable TMPDIR is set, in which case the directory $TMPDIR is used.

If your source files are not where they were when they were compiled, or if you compiled on a different machine than you are debugging on and the compile directory is not mounted as the same pathname, dbx cannot find them. See the pathmap command in Chapter 1, Starting dbx" for a solution.

Reaching Breakpoints

If you do not reach the breakpoint you expected to reach, consider the following possibilities:

In this situation, the breakpoint you put on the while amounts to putting a breakpoint only on the outer if, because dbx cannot deal with source lines that map to two or more different addresses.

C++ members and whatis Command

Sometimes the type of a C++ member is missing in the output of whatis. In the following example, the type of member stackcount is missing:


(dbx) whatis stack
class stack {
...
static stackcount;       /* Never defined or allocated */
...
};

When a static class member is not defined or allocated, dbx cannot determine its type so there is no type to print.

Runtime Checking Eight Megabyte Limit

Only access checking has this limit. Leak checking is not affected by this limit.


Note -

On V9, you can work around the eight megabyte limit by using the setenv command to set the USE_FASTTRAPS environment variable to 1. This workaround makes dbx run more slowly and use more memory.


For access checking, RTC replaces each load and store instruction with a branch instruction that branches to a patch area. This branch instruction has an eight megabyte range. If the debugged program has used up all the address space within eight megabytes of the particular load/store instruction being replaced, there is no place to put the patch area. If RTC can't intercept all loads and stores to memory it cannot provide accurate information and so disables access checking completely.

dbx internally applies some strategies when it runs into this limitation and continues if it can rectify this problem. In some cases dbx cannot proceed; it turns off access checking after printing an error message. For workarounds, see Chapter 9, Using Runtime Checking." For more information on the eight megabyte limit, see "RTC's Eight Megabyte Limit".

Using dbx to Locate Floating-Point Exceptions

You need to do two things. First, to stop the process whenever an FP exception occurs, type:


(dbx) catch FPE

Next, add the following to your Fortran application:


integer ieeer, ieee_handler, myhandler
ieeer = ieee_handler('set', 'all', myhandler)
...
        
integer function myhandler(sig, code, context)
integer sig, code(5)
call abort()
end

This is necessary because the ieee software typically sets all errors to be silent (not raising signals). This causes all ieee exceptions to generate a SIGFPE as appropriate, which is probably too much.

You can further tailor which exceptions you see by adjusting the parameters of ieee_handler() or by using an alternative to the dbx catch command:


stop sig FPE

which acts just like catch FPE, or


stop sig FPE subcode

For finer control, subcode can be one of the following:

FPE_INTDIV 

 1 integer divide by zero

FPE_INTOVF 

integer overflow 

FPE_FLTDIV 

floating point divide by zero 

FPE_FLTOVF 

floating point overflow 

FPE_FLTUND 

floating point underflow 

FPE_FLTRES 

floating point inexact result 

FPE_FLTINV 

invalid floating point operation 

FPE_FLTSUB 

subscript out of range 

Note that stop and catch are independent and that if you use stop FPE you should also ignore FPE.

Using dbx with Multithreaded Programs

Multithreaded features are an inherent part of the standard dbx.

The major multithreaded features offered by dbx are:

You can limit your scope to a specific thread. dbx maintains a cursor to the "current" or "active" thread. It is manipulable by the thread command. The only commands that use the current thread as the default thread are where and thread -info.

Thread Numbering

dbx knows the id of each thread (the type thread_t) as returned by thr_create(). The syntax is t@number.

LWP Numbering

dbx knows the id of each LWP (the type lwpid_t) as presented by the /proc (man procfs(4)) interface. The syntax is l@number.

Breakpoints on a Specific Thread

You can have a breakpoint on a specific thread by filtering a regular breakpoint:


stop in foo -thread t@4

Where the t@4 refers to the thread with id 4.

When a thread hits a breakpoint, all threads stop. This is knows as "sympathetic stop," or "stop the world".

From the point of view of /proc and LWPs this is synchronous debugging.

To ease thread navigation, put this in your .dbxrc.


_cb_prompt() {
        if [ $mtfeatures = "true"]
        then
                PS1='[$thread $lwp]: '
        else
                PS1="(dbx-$proc) "
        fi
}

dbx Identification of Multithreaded Applications

If an application is linked with -lthread, dbx assumes it is multithreaded.

The Collector, RTC, fix and continue, and Watchpoints

The collector and fix and continue work with multithreaded applications. RTC works with multithreaded applications, however a libthread patch is needed.

In the Solaris 2.5.1 operating environment, the implementation of watchpoints does not depend on the operating system, and has the potential of too easily getting the multithreaded application into a deadlock or other obscure problems.

Multithreaded Pitfalls

It is very easy to get your program to deadlock by resuming only a specific thread while other threads are still and hold a resource that the resumed thread might need.

libthread data structures are in user space and might get corrupted by bugs involving rogue pointers. In such cases one suggestion is to work at the LWP level with commands like lwps and lwp, which are analogous to their thread equivalents.

Sleeping Threads

You cannot "force" a sleeping thread to run. In general, when debugging multithreaded applications it is recommended that you take a "stand back and watch" approach rather than trying to alter the program's natural execution flow.

thr_join, thr_create(), and thr_exit

Starting from the threads list, you can determine which thread id came from which start function. The "base function" as it is known, is printed in the thread listing.

When you attach to an existing multithreaded process, it is non-deterministic which thread becomes the active thread.

When the active thread does a thr_create, the current threads stays with the "creating thread". In the follow_fork analogy, it would be parent.

The Sun multithreaded model doesn't have true fork semantics for threads. There is no thread tree, and no parent-child relationships as there is with processes. thr_join() is only a simplified veneer.

When the active thread does a thr_exit, dbx makes a dummy "dead" thread as the active thread. This thread is represented as t@X.