The
dbx
debugger
is a command-line program.
It is a tool for debugging programs at the source-code
level and machine-code level, and can be used with C, Fortran, Pascal, and
assembly language.
After invoking
dbx
, you can enter
dbx
commands that control and trace execution, display variable
and expression values, and display and edit source files.
The
ladebug
debugger, an alternate debugger, provides
both command-line and graphical user interfaces (GUIs) and supports some languages
that are not supported by
dbx
.
The
ladebug
debugger has better features than
dbx
for debugging multithreaded
programs.
For more information about
ladebug
, see the
Ladebug Debugger Manual
or
ladebug
(1).
This chapter provides information on the following topics:
General debugging considerations (Section 5.1)
How to run the
dbx
debugger (Section 5.2)
What you can specify in
dbx
commands (Section 5.3)
How to enter
dbx
commands using options
provided by the
dbx
monitor (Section 5.4)
How to control
dbx
(Section 5.5)
How to examine source code and machine code (Section 5.6)
How to control the execution of the program you are debugging (Section 5.7)
How to set breakpoints (Section 5.8)
How to examine the state of a program (Section 5.9)
How to preserve multiple core files (Section 5.10)
How to debug a running process (Section 5.11)
How to debug multithreaded processes (Section 5.12)
How to debug multiple asynchronous processes (Section 5.13)
Complete details on
dbx
command-line options,
dbx
commands, variables, and so on can be found in
dbx
(1).
You can also use Visual Threads (available on the Associated Products Volume 1 CDROM) to analyze multithreaded applications for potential logic and performance problems. You can use Visual Threads with POSIX Threads Library applications and with Java applications.
Examples in this chapter refer to a sample program called
sam
.
The C language source program (sam.c
) is
listed in
Example 5-1.
In addition to the conventions outlined in the preface of this manual,
an additional convention is used in the command descriptions in this chapter;
uppercase keywords are used to indicate variables for which specific rules
apply.
These keywords are described in
Table 5-1.
Table 5-1: Keywords Used in Command Syntax Descriptions
Keyword | Value |
ADDRESS |
Any expression specifying a machine address. |
COMMAND_LIST |
One or more commands, each separated by semicolons. |
DIR |
Directory name. |
EXP |
Any expression including program variable
names for the command.
Expressions can contain
dbx
variables,
for example,
($listwindow
+
2) .
If you want to use the variable names
in ,
to , or
at
in an expression, you must surround
them with parentheses; otherwise,
dbx
assumes that these
words are debugger keywords. |
FILE |
File name. |
INT |
Integer value. |
LINE |
Source-code line number. |
NAME |
Name of a
dbx
command. |
PROCEDURE |
Procedure name or an activation level on the stack. |
REGEXP |
Regular expression string.
See
ed (1). |
SIGNAL |
System signal.
See
signal (2). |
STRING |
Any ASCII string. |
VAR |
Valid program variable or
dbx
predefined variable (see Table 5-9).
For machine-level debugging,
VAR
can also be an address.
You must qualify program variables with
duplicate names as described in Section 5.3.2. |
The following example shows the use of the uppercase words in commands:
(dbx)
stop VAR in PROCEDURE if EXP
Enter
stop
,
in
, and
if
as shown.
Enter the values for
VAR
,
PROCEDURE
, and
EXP
as defined in
Table 5-1.
Note
Information on debugging multiple asynchronous processes, including extensions to the syntax of certain
dbx
commands to provide control of the asynchronous session, is contained in Section 5.13.
5.1 General Debugging Considerations
The following sections introduce the
dbx
debugger
and some debugging concepts.
They also give suggestions about how to approach
a debugging session, including where to start, how to isolate errors, and
how to avoid common pitfalls.
If you are an experienced programmer, you may
not need to read these sections.
5.1.1 Reasons for Using a Source-Level Debugger
The
dbx
debugger enables you to trace problems in
a program object at the source-code level or at the machine-code level.
With
dbx
, you control a program's execution, monitoring program control
flow, variables, and memory locations.
You can also use
dbx
to trace the logic and flow of control to become familiar with a program written
by someone else.
5.1.2 Explanation of Activation Levels
Activation levels define the currently active scopes (usually
procedures) on the stack.
An activation stack is a list of calls that starts
with the initial program, usually
main()
.
The most recently
called procedure or block is number 0.
The next procedure called is number
1.
The last activation level is always the main procedure (the procedure that
controls the whole program).
Activation levels can also consist of blocks
that define local variables within procedures.
You see activation levels in
stack traces (see the
where
and
tstack
debugger commands), and when moving around the activation stack (see the
up
,
down
, and
func
debugger
commands).
The following example shows a stack trace produced by a
where
command:
> 0 prnt(pline = 0x11ffffcb8) ["sam.c":52, 0x120000c04] [1] 1 main(argc = 2, argv = 0x11ffffe08) ["sam.c":45, 0x120000bac] [2] | | | | | | [3] [4] [5] [6] [7] [8]
The most recently called procedure is
prnt
.
The activation level of
prnt
is
0
; this function is at the top of the stack.
[Return to example]
The main program is
main
.
[Return to example]
Activation level number.
The angle bracket
( >
) indicates the activation level that
is currently under examination.
[Return to example]
Procedure name. [Return to example]
Procedure arguments. [Return to example]
Source file name. [Return to example]
Current line number. [Return to example]
Current program counter. [Return to example]
Because the
dbx
debugger finds only run-time errors, you should fix compiler
errors before starting a debugging session.
Run-time errors can cause a program
to fail during execution (resulting in the creation of a core dump file) or
to produce incorrect results.
The approach for debugging a program that fails
during execution differs from the approach for debugging a program that executes
to completion but produces incorrect results.
(See
Section 5.1.4
for information on how to debug programs that produce incorrect results.)
If a program fails during execution, you can usually save time by using the following approach to start a debugging session instead of blindly debugging line by line:
Invoke the program under
dbx
, specifying
any appropriate options and the names of the executable file and the core
dump file on the
dbx
command line.
Get a stack trace using the
where
command
to locate the point of failure.
Note
If you have not stripped symbol table information from the object file, you can get a stack trace even if the program was not compiled with the
-g
debug option.
Set breakpoints to isolate the error using the
stop
or
stopi
commands.
Display the values of variables using the
print
command to see where a variable might have been assigned an incorrect value.
If you still cannot find the error, other
dbx
commands
described in this chapter might be useful.
5.1.4 Diagnosing Incorrect Output Results
If a program executes to completion but produces incorrect values or output, follow these steps:
Set a breakpoint where you think the problem is happening -- for example, in the code that generates the value or output.
Run the program.
Get a stack trace using the
where
command.
Display the values for the variables that might be causing
the problem using the
print
command.
Repeat this procedure until the problem is found.
The debugger cannot solve all problems. For example, if your program contains logic errors, the debugger can only help you find the problem, not solve it. When information displayed by the debugger appears confusing or incorrect, taking the following actions might correct the situation:
Separate lines of source code into logical units wherever
possible (for example, after
if
conditions).
The debugger
may not recognize a source statement written with several others on the same
line.
If executable code appears to be missing, it might have been contained in an included file. The debugger treats an included file as a single line of code. If you want to debug this code, remove it from the included file and compile it as part of the program.
Make sure you recompile the source code after changing it. If you do not do this, the source code displayed by the debugger will not match the executable code. The debugger warns you if the source file is more recent than the executable file.
If you stop the debugger by pressing Ctrl/Z and then resume the same debugging session, the debugger continues with the same object module specified at the start of the session. This means that if you stop the debugger to fix a problem in the code, recompile, and resume the session, the debugger will not reflect the change. You must start a new session.
Similarly,
dbx
will not reflect changes you have
made if you edit and recompile your program in one window on a workstation
while running the debugger in another window.
You must stop and restart
dbx
each time you want it to recognize changes you have made.
When entering a command to display an expression that has
the same name as a
dbx
keyword, you must enclose the expression
within parentheses.
For example, to display the value of
output
(a keyword in the
playback
and
record
commands, discussed in
Section 5.9.4), you must specify the
following command:
(dbx)
print (output)
If the debugger does not display any variables or executable
code, make sure you compiled the program with the
-g
option.
Before invoking
dbx
, you need to compile the program
for debugging.
You might also want to create a
dbx
initialization
file that will execute commands when the debugger is started.
5.2.1 Compiling a Program for Debugging
To prepare a program for
debugging, specify the
-g
option at compilation time.
With this option set, the compiler inserts into the program symbol table information
that the debugger uses to locate variables.
With the
-g
option set, the compiler also sets its optimization level to
-O0
.
When you use different levels of optimizing, for example
-O2
, the optimizer does not alter the flow of control within
a program, but it might move operations around so that the object code and
source code do not correspond.
These changed sequences of code can create
confusion when you use the debugger.
You can do limited debugging on code compiled without the
-g
option.
For example, the following commands work properly
without recompiling for debugging:
stop in PROCEDURE
stepi
cont
conti
(ADDRESS)/<COUNT><MODE>
tracei
Although you can do limited debugging, it is usually more advantageous
to recompile the program with the
-g
option.
Note
that the debugger does not warn you if an object file was compiled without
the
-g
option.
Complete symbol table information is available only for programs in
which all modules have been compiled with the
-g
option.
Other programs will have symbol table information only for symbols
that are either referenced by or defined in modules compiled with the
-g
option.
Note
Any routines in shared library applications in which breakpoints are to be set must be compiled with the
-g
option. If the-g
option is not specified, the symbol table information thatdbx
needs to set breakpoints is not generated anddbx
will not be able to stop the application.
5.2.2 Creating a dbx Initialization File
You can create a
dbx
initialization file that
contains commands you normally enter at the beginning of each
dbx
session.
For example, the file could contain the following commands:
set $page = 5 set $lines = 20 set $prompt = "DBX> " alias du dump
The initialization file must have the name
.dbxinit
.
Each time you invoke the debugger,
dbx
executes the commands in
.dbxinit
.
The debugger looks first
for
.dbxinit
in the current directory and then in your
home directory (the directory assigned to the
$HOME
environment
variable).
5.2.3 Invoking and Terminating dbx
You invoke
dbx
from the shell command
line by entering the
dbx
command and any necessary parameters.
After invocation,
dbx
sets the current function to
the first procedure of the program.
The
dbx
command has the following syntax:
dbx
[ options ] [ objfile [ corefile ] ]
Several of
the most important options supported by the
dbx
command
line are shown in
Table 5-2.
The name of
the executable file of the program that you want to debug.
If
objfile
is not specified,
dbx
uses
a.out
by default.
Name of a core dump file.
If you specify
corefile,
dbx
lists the point of program failure.
The dump file holds an image of memory at the time the program failed.
Use
dbx
commands to get a stack trace and look at the core file code.
The debugger displays information from the core file, not from memory as it
usually does.
See also
Section 5.10.
The maximum number of arguments accepted by
dbx
is
1000; however, system limits on your machine might reduce this number.
Table 5-2: dbx Command Options
Option | Function |
-cfilename |
Selects an initialization command file other
than your
.dbxinit
file. |
-Idirname |
Tells
dbx
to look in the
specified directory for source files.
To specify multiple directories, use
a separate
-I
for each directory.
Unless you specify
this option when you invoke
dbx , the debugger looks for
source files in the current directory and in the object file's directory.
You can change directories with the
use
command (see
Section 5.6.1). |
-i |
Invokes
dbx
in interactive
mode.
With this option set,
dbx
does not treat source lines
beginning with number signs ( # ) as comments. |
-k |
Maps memory addresses. This option is useful for kernel debugging. (For information on kernel debugging, see the Kernel Debugging manual.) |
-module_path |
Specifies the directory path where
dbx
should search for shared libraries (or loadable kernel modules).
This option is useful if, for example, you are debugging a core dump (or a
kernel crash dump) and the version of a shared library (or module) that was
running when the dump occurred has been moved to a different location.
(For
information on kernel debugging, see the
Kernel Debugging
manual.) |
-module_verbose |
Causes
dbx
to print the
path of shared libraries (or loadable kernel modules, if you are debugging
a kernel) as they are being loaded.
By default,
dbx
does
not print the path.
(For information on kernel debugging, see the
Kernel Debugging
manual.) |
-pid
process-id |
Attaches
dbx
to a currently
running process. |
-r |
Immediately executes the object file that
you specify on the command line.
If program execution terminates with an error,
dbx
displays the message that describes the error.
You can then
either invoke the debugger or allow the program to continue exiting.
The
dbx
debugger reads from
/dev/tty
when you specify
the
-r
option and standard input is not a terminal.
If the program executes successfully,
dbx
prompts you for
input. |
The following example invokes
dbx
with no options.
Because an object file name is not specified,
dbx
prompts
for one.
In this case, the user responds with
sam
.
The
default debugger prompt is
(dbx)
.
%
dbx
enter object file name (default is 'a.out'):
sam
dbx version 3.12 Type 'help' for help. main: 23 if (argc < 2) { (dbx)
Use
the
quit
or
q
command to end a debugging
session.
The
quit
command accepts no arguments.
5.3 Using dbx Commands
You can enter up to 10,240 characters on an input line.
Long lines can
be continued with a backslash ( \
).
If a
line exceeds 10,240 characters,
dbx
displays an error message.
The maximum string length is also 10,240.
The following sections describe scoping and the use of qualified variable
names,
dbx
expressions and precedence, and
dbx
data types and constants.
5.3.1 Qualifying Variable Names
Variables in
dbx
are qualified
by file, procedure, block, or structure.
When using commands like
print
to display a variable's value,
dbx
indicates
the scope of the variable when the scope could be ambiguous (for example,
you have a variable by the same name in two or more procedures).
If the scope
is wrong, you can specify the full scope of the variable by separating scopes
with periods.
For example:
sam.main.i | | | [1] [2] [3]
Current file [Return to example]
Procedure name [Return to example]
Variable name [Return to example]
The
dbx
debugger recognizes expression operators from C; these operators
can also be used for debugging any other supported language.
(Note that
dbx
uses brackets ( [ ]
) for
array subscripts even in Fortran, whose natural subscript delimiters are parentheses.)
In addition to the standard C operators,
dbx
uses the
number sign ( #
) as shown in
Table 5-3.
Table 5-3: The dbx Number-Sign Expression Operator
Syntax | Description |
("FILE" #EXP) |
Uses the line number specified by
#EXP
in the file named by
FILE . |
(PROCEDURE #EXP) |
Uses the relative line number specified by
#EXP
in the procedure named by
PROCEDURE . |
(#EXP) |
Returns the address for the line specified
by
(#EXP) . |
Operators follow the C language precedence.
Table 5-4
shows the language operators recognized by
dbx
in order
of precedence from top to bottom and from left to right, with the
dbx
-specific number-sign operator included among the unary operators
to show its place in the precedence hierarchy.
Table 5-4: Expression Operator Precedence
Unary: | & ,
+ ,
- ,
*
(pointer),
# ,
sizeof()
[Footnote 2]
, ~,
/ ,
(type) ,
(type *) |
Binary: | << ,
>> ,
" ,
! ,
== ,
!= ,
<= ,
>= ,
< ,
> ,
& ,
&& ,
| ,
|| ,
+ ,
- ,
* ,/
[Footnote 3]
, %,
[] ,
-> |
5.3.3 dbx Data Types and Constants
Table 5-5
lists the built-in data types that
dbx
commands can use.
Table 5-5: Built-in Data Types
Data Type | Description | Data Type | Description | |
$address |
Pointer | $real |
Double-precision real | |
$boolean |
Boolean | $short |
16-bit integer | |
$char |
Character | $signed |
Signed integer | |
$double |
Double-precision real | $uchar |
Unsigned character | |
$float |
Single-precision real | $unsigned |
Unsigned integer | |
$integer |
Signed integer | $void |
Empty |
You can use the built-in data types for type coercion -- for
example, to display the value of a variable in a type other than the type
specified in the variable's declaration.
The
dbx
debugger
understands C language data types, so that you can refer to data types without
the dollar sign ($
).
The types of constants that are acceptable
as input to
dbx
are shown in
Table 5-6.
Constants are displayed by default as decimal values in
dbx
output.
Table 5-6: Input Constants
Constant | Description |
false |
0 |
true |
Nonzero |
nil |
0 |
0xnumber |
Hexadecimal |
0tnumber |
Decimal |
0number |
Octal |
number | Decimal |
number.[ number][e|E][+|-]EXP |
Float |
Notes:
Overflow on nonfloat uses the rightmost digits. Overflow on float uses the leftmost digits of the mantissa and the highest or lowest exponent possible.
The
$octin
variable changes the default
input expected to octal.
The
$hexin
variable changes the
default input expected to hexadecimal (see
Section 5.5.2).
The
$octints
variable changes the default
output to octal.
The
$hexints
variable changes the default
output to hexadecimal (see
Section 5.5.2).
5.4 Working with the dbx Monitor
The
dbx
debugger provides a command history, command-line
editing, and symbol name completion.
The
dbx
debugger also
allows multiple commands on an input line.
These features can reduce the amount
of input required or allow you to repeat previously executed commands.
5.4.1 Repeating dbx Commands
The
dbx
debugger keeps a command
history that allows you to repeat debugger commands without retyping them.
You can display these commands by using the
history
command.
The
$lines
variable controls the number of history lines
saved.
The default is 20 commands.
You can use the
set
command to modify the
$lines
variable (see
Section 5.5.1).
To repeat a command, use the Return key or one of the exclamation point
(!
) commands.
The
history
command has the following forms:
history
Displays the commands in the history list.
Repeats the last command that you entered.
You can disable this feature by setting the
$repeatmode
variable to 0 (see
Section 5.5.1).
!string
Repeats the most recent command that starts with the specified string.
!integer
Repeats the command associated with the specified integer.
!-integer
Repeats the command that occurred the specified number of commands (integer) before the most recent command.
The following example displays the history list and then repeats execution of the twelfth command in the list:
(dbx)
history
10 print x 11 print y 12 print z(dbx)
!12
(!12 = print z) 123 (dbx)
5.4.2 Editing the dbx Command Line
The
dbx
debugger provides
support for command-line editing.
You can edit a command line to correct mistakes
without reentering the entire command.
To enable command-line editing, set
the
EDITOR
,
EDITMODE
, or
LINEEDIT
environment variable before you invoke
dbx
.
For example, to set
LINEEDIT
from the C shell, enter the
following command:
%
setenv LINEEDIT
From the Bourne or Korn shells, enter this command:
$
export LINEEDIT
The debugger offers the following modes of command-line editing:
If the environment variable
LINEEDIT
is
not set and either of the environment variables
EDITMODE
or
EDITOR
contains a path ending in
vi
,
the debugger uses a command-line editing mode that resembles the Korn shell's
vi
mode, in which the following editing keys are recognized:
$ + - 0 A B C D E F I R S W X ^ a b c d e f h i j k l r s w x ~ Ctrl/D Ctrl/H Ctrl/J Ctrl/L Ctrl/M Ctrl/V
See
ksh
(1)
for more information.
If the environment variable
LINEEDIT
is
set to any value, even the null string, or if
LINEEDIT
is not set and either of the environment variables
EDITMODE
or
EDITOR
contains a path ending in
emacs
,
the debugger uses a command-line editing mode that resembles the Korn shell's
emacs
mode.
This mode behaves slightly differently depending on
whether it is enabled by
LINEEDIT
or by
EDITOR
or
EDITMODE
.
Table 5-7
lists the
emacs
-mode command-line editing commands.
Table 5-7: Command-Line Editing Commands in emacs mode
Command | Function |
Ctrl/A | Moves the cursor to the beginning of the command line. |
Ctrl/B | Moves the cursor back one character. |
Ctrl/C | Clears the line. |
Ctrl/D | Deletes the character at the cursor. |
Ctrl/E | Moves the cursor to the end of the line. |
Ctrl/F | Moves the cursor ahead one character. |
Ctrl/H | Deletes the character immediately preceding the cursor. |
Ctrl/J | Executes the line. |
Ctrl/K | (When enabled by
EDITOR
or
EDITMODE ) Deletes from the cursor to the end of
the line.
If preceded by a numerical parameter whose value is less than the
current cursor position, deletes from the given position up to the cursor.
If preceded by a numerical parameter whose value is greater than the current
cursor position, deletes from the cursor up to the given position. |
Ctrl/K
char |
(When enabled by
LINEEDIT ) Deletes
characters until the cursor rests on the next occurrence of
char. |
Ctrl/L | Redisplays the current line. |
Ctrl/M | Executes the line. |
Ctrl/N | Moves to the next line in the history list. |
Ctrl/P | Moves to the previous line in the history list. |
Ctrl/R
char |
Searches back in the current line for the specified character. |
Ctrl/T | Interchanges the two characters immediately preceding the cursor. |
Ctrl/U | Repeats the next character four times. |
Ctrl/W | Deletes the entire line. |
Ctrl/Y | Inserts immediately before the cursor any text cut with Ctrl/K. |
Ctrl/Z | Tries to complete a file or symbol name. |
Escape | Tries to complete a file or symbol name. |
Down Arrow | Moves to the next line in the history list. |
Up Arrow | Moves to the previous line in the history list. |
Left Arrow | Moves the cursor back one character. |
Right Arrow | Moves the cursor ahead one character. |
5.4.3 Entering Multiple Commands
You can enter multiple commands on the command
line by using a semicolon ( ;
) as a separator.
This feature is useful when you are using the
when
command
(see
Section 5.8.4).
The following example has two commands on one command line; the first command stops the program and the second command reruns it:
(dbx)
stop at 40; rerun
[2] stop at "sam.c":40 [2] stopped at [main:40 ,0x120000b40] i=strlen(line1.string); (dbx)
The
dbx
debugger provides symbol name completion.
When you enter a partial symbol name and press Ctrl/Z,
dbx
attempts to complete the name.
If a unique completion is found,
dbx
redisplays the input with the unique completion added; otherwise,
all possible completions are shown, and you can choose one.
To enable symbol name completion, you must enable command-line editing
as described in
Section 5.4.2.
The following
example displays all names beginning with the letter
i
:
(dbx)
i [Ctrl/Z]
ioctl.ioctl .ioctl isatty.isatty .isatty i int
[1](dbx) i
[2]
The display might include data types and library symbols. [Return to example]
After listing all names beginning with the
partial name,
dbx
prompts again with the previously specified
string, giving you an opportunity to specify additional characters and repeat
the search.
[Return to example]
(dbx)
print file [Ctrl/Z]
(dbx) print file_header_ptr 0x124ac (dbx)
The
dbx
debugger provides commands for setting and
removing
dbx
variables, creating and removing aliases,
invoking a subshell, checking and deleting items from the status list, displaying
a list of object files associated with an application, and recording and playing
back input.
5.5.1 Setting and Removing Variables
The
set
command defines a
dbx
variable, sets an existing
dbx
variable to a different value, or displays a list of existing
dbx
predefined variables.
The
unset
command removes
a
dbx
variable.
Use the
print
command
to display the values of program and debugger variables.
The
dbx
predefined variables are listed in
Table 5-8.
You cannot define a debugger variable with the same name as a program variable.
The
set
and
unset
commands have
the following forms:
set
Displays a list of
dbx
predefined variables.
set VAR = EXP
Assigns a new value to a variable or defines a new variable.
unset VAR
Unsets the value
of a
dbx
variable.
The following example shows the use of the
set
and
unset
commands:
(dbx)
set
[1] $listwindow 10 $datacache 1 $main "main" $pagewindow 22 test 5 $page 1 $maxstrlen 128 $cursrcline 24more (n if no)?
n
(dbx)
set test = 12
[2](dbx)
set
$listwindow 10 $datacache 1 $main "main" $pagewindow 22 test 12 $page 1 $maxstrlen 128 $cursrcline 24more (n if no)?
n
(dbx)
unset test
[3](dbx)
set
$listwindow 10 $datacache 1 $main "main" $pagewindow 22 $page 1 $maxstrlen 128 $cursrcline 24more (n if no)?
n
(dbx)
Display a list of
dbx
predefined variables.
[Return to example]
Assign a new value to a variable. [Return to example]
Remove a variable. [Return to example]
The
predefined
dbx
variables are shown in
Table 5-8.
Each variable is labeled I for integer, B for Boolean, or S for string.
Variables
that you can examine but cannot modify are indicated by an R.
Table 5-8: Predefined dbx Variables
Type | Name | Default | Description |
S | $addrfmt |
"0x%lx" |
Specifies the format for addresses.
Can be
set to anything you can format with a C language
printf
statement. |
B | $assignverify |
1 | Specifies whether new values are displayed when assigning a value to a variable. |
B | $asynch_interface |
0 | Controls whether
dbx
is,
or can be, configured to control multiple asynchronous processes.
Incremented
by 1 when a process is attached; decremented by 1 when a process terminates
or is detached.
Can also be set by the user.
If 0 or negative, asynchronous
debugging is disabled. |
B | $break_during_step |
0 | Controls whether breakpoints are checked
while processing
step/stepi ,
next/nexti ,
call ,
return , and so on. |
B | $casesense |
0 | Specifies whether source searching and variables are case sensitive. A nonzero value means case sensitive; a 0 means not case sensitive. |
I R | $curevent |
0 | Shows the last event number as reported by
the
status
command. |
I R | $curline |
0 | Shows the current line in the source code. |
I R | $curpc |
- | Shows the current address.
Used with the
wi
and
li
aliases. |
I R | $cursrcline |
1 | Shows the last line listed plus 1. |
B | $datacache |
1 | Caches information from the data space so
that
dbx
only has to check the data space once.
If you
are debugging the operating system, set this variable to 0; otherwise, set
it to a nonzero value. |
S R | $defaultin |
Null string | Shows the name of the file that
dbx
uses to store information when using the
record
input
command. |
S R | $defaultout |
Null string | Shows the name of the file that
dbx
uses to store information when using the
record
output
command. |
B | $dispix |
0 | When set to 1, specifies the display of only
real instructions when debugging in
pixie
mode. |
B | $hexchars |
Not defined | A nonzero value indicates that character values are shown in hexadecimal. |
B | $hexin |
Not defined | A nonzero value indicates that input constants are hexadecimal. |
B | $hexints |
Not defined | A nonzero value indicates that output constants are shown in hexadecimal; a nonzero value overrides octal. |
B | $hexstrings |
Not defined | A nonzero value indicates that strings are displayed in hexadecimal; otherwise, strings are shown as characters. |
I R | $historyevent |
None | Shows the current history number. |
I | $lines |
20 | Specifies the size of the
dbx
history list. |
I | $listwindow |
$pagewindow/2 |
Specifies the number of lines shown by the
list
command. |
S | $main |
"main" |
Specifies the name of the procedure where
execution begins.
The debugger starts the program at
main()
unless otherwise specified. |
I | $maxstrlen |
128 | Specifies the maximum number of characters
that
dbx
prints for pointers to strings. |
S | $module_path
|
Null string | Specifies the directory path where
dbx
should search for shared libraries (or loadable kernel modules).
This variable is useful if, for example, you are debugging a core dump (or
a kernel crash dump) and the version of a shared library (or module) that
was running when the dump occurred has been moved to a different location.
For information on kernel debugging, see the
Kernel Debugging
manual. |
I | $module_verbose
|
0 | When set to a nonzero value, causes
dbx
to print the location of shared libraries (or loadable kernel
modules, if debugging a kernel) as they are being loaded.
By default, or when
this variable is set to 0,
dbx
does not print the location.
For information on kernel debugging, see the
Kernel Debugging
manual. |
B | $octin |
Not defined | Changes the default input constants to octal when set to a nonzero value. Hexadecimal overrides octal. |
B | $octints |
Not defined | Changes the default output constants to octal when set to a nonzero value. Hexadecimal overrides octal. |
B | $page |
1 | Specifies whether to page long information. A nonzero value enables paging; a 0 disables it. |
I | $pagewindow |
Various | Specifies the number of lines displayed when viewing information that is longer than one screen. This variable should be set to the number of lines on the terminal. A value of 0 indicates a minimum of 1 line. The default value depends on the terminal type; for a standard video display, the default is 24. |
B | $pimode |
0 | Displays input when using the
playback
input
command. |
I | $printdata |
0 | A nonzero value indicates that the values of registers are displayed when instructions are disassembled; otherwise, register values are not displayed. |
B | $printtargets |
1 | If set to 1, specifies that displayed disassembly listings are to include the labels of targets for jump instructions. If set to 0, disables this label display. |
B | $printwhilestep |
0 | For use with the
step
[n] and
stepi
[n] instructions.
A nonzero value specifies that all
n
lines or instructions should be displayed.
A 0 value specifies
that only the last line and/or instruction should be displayed. |
B | $printwide |
0 | Specifies wide (useful for structures or arrays) or vertical format for displaying variables. A nonzero value indicates wide format; 0 indicates vertical format. |
S | $prompt |
"(dbx)" |
Sets the prompt for
dbx . |
B | $readtextfile |
1 | When set to a value of 1,
dbx
tries to read instructions from the object file instead of from the process.
This variable should always be set to 0 when the process being debugged copies
in code during the debugging process.
However, performance is better when
$readtextfile
is set to 1. |
B | $regstyle |
1 | Specifies the type of register names to be
used.
A value of 1 specifies hardware names.
A 0 specifies software names
as defined by the file
regdefs.h .
|
B | $repeatmode |
1 | Specifies whether
dbx
should repeat the last command when the Return key is pressed.
A nonzero value
indicates that the command is repeated; otherwise, it is not repeated. |
B | $rimode |
0 | Records input when using the
record
output
command. |
S | $sigvec |
"sigaction" |
Tells
dbx
the name of
the code called by the system to set signal handlers. |
S | $sigtramp |
"_sigtramp" |
Tells
dbx
the name of
the code called by the system to invoke user signal handlers. |
B | $stopall_on_step |
1 | Specifies whether
dbx
should stop every child process that is forked (1) or ignore many of the forks
generated by various system and library calls (0).
If
$stop_all_forks
is not set, the value of
$stop_on_fork
determines
dbx 's behavior with forks.
$stop_all_forks
traps
forks in libraries and system calls that are usually ignored by
$stop_on_fork . |
B | $stop_in_main |
N/A | Not used.
This variable is displayed by the
set
command, but it presently has no effect on
dbx
operation. |
B | $stop_on_exec |
1 | Specifies whether
dbx
should detect calls to
execl( )
and
execv( ) , and stop the newly activated images at the first line of executable
code. |
B | $stop_on_fork |
1 | Specifies whether
dbx
should advance a new image activated by a
fork( )
or
vfork( )
call to its main activation point and
then stop (1) or continue until stopped by a breakpoint or event (0).
The
dbx
program tries to avoid stopping on forks from system or library
calls unless
$stop_all_forks
is set. |
S | $tagfile |
"tags" |
Contains a file name indicating the file
in which the
tag
command and the
tagvalue
macro are to search for tags. |
I | $traploops |
3 | Specifies the number of consecutive calls
to a
SIGTRAP
handler that will be made before
dbx
assumes that the program has fallen into a trap-handling loop. |
5.5.3 Defining and Removing Aliases
The
alias
command defines a new alias or displays
a list of all current aliases.
The
alias
command allows you to rename any debugger
command.
Enclose commands containing spaces within double- or single-quotation
marks.
You can also define a macro as part of an alias.
The
dbx
debugger has a group of predefined aliases.
You can modify these aliases or add new aliases.
You can also include aliases
in your
.dbxinit
file for use in future debugging sessions.
The
unalias
command removes an alias from a command.
You must specify
the alias to remove.
The alias is removed only for the current debugging session.
The
alias
and
unalias
commands
have the following forms:
alias
Displays a list of all aliases.
alias NAME1[(ARG1,...,ARGN)] "NAME2"
Defines a new alias.
NAME1
is the new name.
NAME2
is the command to string to rename.
ARG1,...,ARGN
are the command arguments.
unalias NAME
Removes an alias
from a command, where
NAME
is the alias name.
The following example shows the use of the
alias
and
unalias
commands:
(dbx)
alias
[1] h history si stepi Si nexti
.
.
.
g goto s stepMore (n if no) ?
n
(dbx)
alias ok(x) "stop at x"
[2](dbx)
ok(52)
[3] [2] Stop at "sam.c":52 [4] (dbx)(dbx)
unalias h
[5](dbx)
alias
si stepi Si nexti
.
.
.
g goto s stepMore (n if no)?
n
(dbx)
Display aliases. [Return to example]
Define an alias for setting a breakpoint. [Return to example]
Set a breakpoint at line 52. [Return to example]
Debugger acknowledges breakpoint set at line 52. [Return to example]
Remove the
h
alias.
(Note
that it disappears from the alias list.)
[Return to example]
The
status
command checks which, if any, of the following commands are
currently set:
stop
or
stopi
commands
for breakpoints
trace
or
tracei
commands
for line-by-line variable tracing
when
command
record
input
and
record
output
commands for saving information
in a file
The
status
command accepts no arguments.
For example:
(dbx)
status
[2] trace i in main [3] stop in prnt [4] record output /tmp/dbxt0018898 (0 lines)(dbx)
The numbers in brackets (for example,
[2]
) indicate
status item numbers.
5.5.5 Deleting and Disabling Breakpoints
The
delete
command deletes breakpoints and stops the recording of input
and output.
Deleting a breakpoint or stopping recording removes the pertinent
items from the status list produced by the
status
command.
The
disable
command disables breakpoints without
deleting them.
The
enable
command reenables disabled events.
The
delete
command has the following forms:
delete EXP1[,...,EXPN]
Deletes the specified status items.
delete all
delete *
Deletes all status items.
The following example shows the use of the
delete
command:
(dbx)
status
[2] record output /tmp/dbxt0018898 (0 lines) [3] trace i in main [4] print pline at "sam.c": [5] stop in prnt(dbx)
delete 4
(dbx)
status
[2] record output /tmp/dbxt0018898 (0 lines) [3] trace i in main [5] stop in prnt(dbx)
The
disable
and
enable
commands have the following forms:
disable EVENT1[,EVENT2,...]
enable EVENT1[,EVENT2,...]
Disables or enables the specified events.
disable all
enable all
Disables or enables all events.
5.5.6 Displaying the Names of Loaded Object Files
The
listobj
command displays the names of all
object files that have been loaded by
dbx
, together with
their sizes and the address at which they were loaded.
These objects include
the main program and all of the shared libraries that are used in an application.
The
listobj
command accepts no arguments.
For example:
(dbx)
listobj
sam addr: 0x120000000 size: 0x2000 /usr/shlib/libc.so addr: 0x3ff80080000 size: 0xbc000(dbx)
5.5.7 Specifying the Location of Shared Libraries for Core Dumps
When a core dump occurs, the location of any shared libraries used by
the program is recorded in the core file, enabling
dbx
to find the libraries.
If the version of a shared library that was running
when the dump occurred is moved to a different location,
dbx
will not find it.
You can specify the directory path where
dbx
should look for shared libraries by using any one of the following methods
(see
dbx
(1)
for complete details):
On the
dbx
command line, specify the directory
path with the
-module_path
option.
For example:
%
dbx a.out core -module_path /usr/project4/lib_dir
Before invoking
dbx
, set the environment
variable
DBX_MODULE_PATH
.
For example:
%
setenv DBX_MODULE_PATH /usr/project4/lib_dir
During the
dbx
session, if you want to
load a shared library dynamically, first set the
$module_path
dbx
variable and then use
the
addobj
command to load the library, as in the following
example:
(dbx)
set $module_path /usr/project4/lib_dir
(dbx)
addobj libdef.so
To verify that modules are being loaded from the correct location, turn on verbose module-loading using any one of the following methods:
Specify the
-module_verbose
dbx
command option.
Set the
DBX_MODULE_VERBOSE
environment
variable to any integer value.
Set the
$module_verbose
dbx
variable to a nonzero value.
5.5.8 Invoking a Subshell from Within dbx
To invoke an interactive subshell at the
dbx
prompt, enter
sh
.
To return to
dbx
from
a subshell, enter
exit
or press Ctrl/D.
To invoke a subshell
that performs a single command and returns to
dbx
, enter
sh
and the desired shell command.
For example:
(dbx)
sh
%
date
Tue Aug 9 17:25:15 EDT 1998
%
exit
.
.
.(dbx)
sh date
Tue Aug 9 17:29:34 EDT 1998
(dbx)
The following sections describe how to list and edit source code, change
directories, change source files, search for strings in source code, display
qualified symbol names, and display type declarations.
5.6.1 Specifying the Locations of Source Files
If you did not specify the
-I
option when invoking
dbx
(see
Section 5.2.3),
the debugger looks for source files in the current directory or the object
file's directory.
The
use
command has two functions:
Change the directory or list of directories in which the debugger looks
List the directory or directories currently in use
The command recognizes absolute and relative pathnames (for example,
./
), but it does not recognize the C shell tilde ( ~
).
The
use
command has the following forms:
use
Lists the current directories.
use DIR1 ...
DIRN
Replaces the current list of directories with a new set.
For example:
(dbx)
use
.
[1](dbx)
use /usr/local/lib
(dbx)
use
/usr/local/lib
[2](dbx)
Current directory [Return to example]
New directory [Return to example]
As
described in
Section 5.1.2, the debugger maintains
a stack of activation levels.
To find the name or activation number for a
specific procedure, get a stack trace with the
where
or
tstack
command.
You can move through the activation stack by using
the
up
,
down
, and
func
commands.
5.6.2.1 Using the where and tstack Commands
The
where
command displays a stack trace showing the current activation
levels (active procedures) of the program being debugged.
The
tstack
command displays a stack trace for all threads.
See
Section 5.12
for more information about debugging threads.
The
where
and
tstack
commands
have the following form:
where [EXP]
tstack [EXP]
Displays a stack trace.
If
EXP
is specified,
dbx
displays only the top
EXP
levels of the stack; otherwise,
the entire stack is displayed.
If a breakpoint is set in
prnt
in the sample program
sam.c
, the program runs and stops in the procedure
prnt()
.
If you enter
where
, the debugger's stack trace
provides the information shown in the following example:
(dbx)
stop in prnt
[1] stop in prnt
(dbx)
run
.
.
.(dbx)
where 1
> 0 prnt(pline = 0x11ffffcb8) ["sam.c":52, 0x120000c04] | | | | | | [1] [2] [3] [4] [5] [6](dbx)
Activation level [Return to example]
Procedure name [Return to example]
Current value of the argument
pline
[Return to example]
Source file name [Return to example]
Line number [Return to example]
Program counter [Return to example]
The
up
and
down
commands move you directly up or down in the stack;
they are useful when tracking a call from one level to another.
The
func
command can move you up or down incrementally
or to a specific activation level or procedure.
The
func
command changes the current line, the current file, and the current procedure,
which changes the scope of the variables you can access.
You can also use
the
func
command to examine source code when a program
is not executing.
The
up
,
down
, and
func
commands have the following forms:
up [EXP]
Moves up the specified number of activation levels in the stack. The default is one level.
down [EXP]
Moves down the specified number of activation levels in the stack. The default is one level.
func
Displays the current activation levels.
func PROCEDURE
Moves to the
activation level specified by
PROCEDURE
.
func EXP
Moves to the activation level specified by the expression.
The following example shows the use of these commands:
(dbx)
where
> 0 prnt(pline = 0x11ffffcb8) ["sam.c":52, 0x120000c04] 1 main(argc = 2, argv = 0x11ffffe08) ["sam.c":45, 0x120000bac](dbx)
up
main: 45 prnt(&line1);
[1](dbx)
where
0 prnt(pline = 0x11ffffcb8) ["sam.c":52, 0x120000c04] > 1 main(argc = 2, argv = 0x11ffffe08) ["sam.c":45, 0x120000bac](dbx)
down
prnt: 52 fprintf(stdout,"%3d. (%3d) %s",
[2](dbx)
where
> 0 prnt(pline = 0x11ffffcb8) ["sam.c":52, 0x120000c04] 1 main(argc = 2, argv = 0x11ffffe08) ["sam.c":45, 0x120000bac](dbx)
func 1
main 47 prnt(&line1)
[3](dbx)
Move up one level. [Return to example]
Move down one level. [Return to example]
Move directly to
main
.
[Return to example]
The
file
command displays the current source file name or changes the
current source file.
Note
Before setting a breakpoint or trace on a line number, use the
func
command to get the correct procedure. Thefile
command cannot be specific enough for the debugger to access the information necessary to set a breakpoint.
The
file
command has the following forms:
file
Displays the name of the file currently in use.
file FILE
Changes the current file to the specified file.
For example:
(dbx)
file
sam.c
[1](dbx)
file data.c
(dbx)
file
data.c
[2](dbx)
Current file [Return to example]
New file [Return to example]
The
list
command displays lines of source code.
The
dbx
variable
$listwindow
defines the number of lines that
dbx
lists by default.
The
list
command uses the
current file, procedure, and line, unless otherwise specified.
The
list
command has the following forms:
list
Lists the number of lines
specified by
$listwindow
, starting at the current line.
list EXP
Lists the number of
lines specified by
EXP
, starting at the current line.
list EXP1,EXP2
List lines from
EXP1
to
EXP2
.
list EXP:INT
Starting at the
specified line (EXP
), lists the specified number of lines
(INT
), overriding
$listwindow
.
list PROCEDURE
Lists the specified
procedure for
$listwindow
lines.
The following example specifies a two-line list starting at line 49:
(dbx)
list 49:2
49 void prnt(pline) 50 LINETYPE *pline;
If you use the
list
command's predefined alias
w
, the output is as follows:
(dbx)
w
45 prnt(&line1); 46 } 47 } 48 49 void prnt(pline) > 50 LINETYPE *pline; 51 { * 52 fprintf(stdout,"%3d. (%3d) %s",pline->linenumber, 53 pline->length, pline->string); 54 fflush(stdout);
The right angle bracket in column 1 ( >
)
indicates the current line, and the asterisk in column 2 ( *
) indicates the location of the program counter (PC) at
this activation level.
5.6.5 Searching for Text in Source Files
The slash ( /
)
and question mark ( ?
) commands search for
regular expressions in source code.
The slash searches forward from the current
line, and the question mark searches backward.
Both commands wrap around at
the end of the file if necessary, searching the entire file from the point
of invocation back to the same point.
By default,
dbx
does
not distinguish uppercase letters from lowercase when searching.
If you set
the
dbx
variable
$casesense
to any nonzero
value, the search is case sensitive.
The
/
and
?
commands have the
following form:
/[REGEXP]
Searches forward for the specified regular expression or, if no expression is specified, for the regular expression associated with the last previous search command.
?[REGEXP]
Searches backward in the same manner as the slash command's forward search.
For example:
(dbx)
/lines
no match
(dbx)
/line1
16 LINETYPE line1;
(dbx)
/
39 while(fgets(line1.string, sizeof(line1.string), fd) != NULL){ (dbx)
5.6.6 Editing Source Files from Within dbx
The
edit
command enables you to change source files from within
dbx
.
To make the changes effective, you must quit from
dbx
, recompile the program, and restart
dbx
.
The
edit
command has the following forms:
edit
Invokes an editor on the current file.
edit FILE
Invokes an editor on the specified file.
The
edit
command loads the editor indicated
by the environment variable
EDITOR
or, if
EDITOR
is not set, the
vi
editor.
To return to
dbx
, exit normally from the editor.
5.6.7 Identifying Variables that Share the Same Name
The
which
and
whereis
commands
display program variables.
These commands are useful for debugging programs
that have multiple variables with the same name occurring in different scopes.
The commands follow the rules described in
Section 5.3.1.
The
which
and
whereis
commands
have the following forms:
which VAR
Displays the default version of the specified variable.
whereis VAR
Displays all versions of the specified variable.
In the following example, the user checks to see where the
default variable named
i
is and then verifies that this
is the only instance of
i
in the program by observing that
whereis
shows only the one occurrence:
(dbx)
which i
sam.main.i
(dbx)
whereis i
sam.main.i
5.6.8 Examining Variable and Procedure Types
The
whatis
command
lists the type declaration for variables and procedures in a program.
The
whatis
command has the following form:
whatis VAR
Displays the type declaration for the specified variable or procedure.
For example:
(dbx)
whatis main
int main(argc,argv) int argc; unsigned char **argv;(dbx)
whatis i
int i;
(dbx)
The following sections describe the
dbx
commands
used to run a program, step through source code, return from a procedure call,
start at a specified line, continue after stopping at a breakpoint, assign
values to program variables, patch an executable disk file, execute a particular
routine, set an environment variable, and load shared libraries.
5.7.1 Running and Rerunning the Program
The
run
and
rerun
commands start program execution.
Each command accepts program arguments and passes those arguments to the
program.
If no arguments are specified for a
run
command,
dbx
runs the program with no arguments.
If no arguments are specified
for a
rerun
command,
dbx
defaults to
the arguments used with the previous
run
or
rerun
command.
You can specify arguments in advance of entering a
rerun
command by using the
args
command.
Arguments
set by the
args
command are ignored by a subsequent
run
command.
You can also use these commands to redirect program input and output in a manner similar to redirection in the C shell:
The optional parameter
<FILE1
redirects
input to the program from the specified file.
The optional parameter
>FILE2
redirects
output from the program to the specified file.
The optional parameter
>&FILE2
redirects
both
stderr
and
stdout
to the specified
file.
Note
The redirected output differs from the output saved with the
record
output
command (see Section 5.9.4.2), which saves debugger output, not program output.
The
run
,
args
, and
rerun
commands have the following forms:
run [ARG1 ...
ARGN] [<FILE1] [>FILE2]
run [ARG1 ...
ARGN] [<FILE1] [>&FILE2]
Runs the program with the specified arguments and redirections.
args [ARG1 ...
ARGN] [<FILE1] [>FILE2]
args [ARG1 ...
ARGN] [<FILE1] [>&FILE2]
Sets the specified arguments and redirections for use by subsequent
commands; the specified values remain in effect until explicitly altered by
new values given with a
run
or
rerun
command.
rerun [ARG1 ...
ARGN] [<FILE1] [>FILE2]
rerun [ARG1 ...
ARGN] [<FILE1] [>&FILE2]
Reruns the program with the specified arguments and redirections.
(dbx)
run sam.c
[1] 0. (19)#include <stdio.h> 1. (14) struct line { 2. (19) char string[256];
.
.
.
Program terminated normally(dbx)
rerun
[2] 0. (19)#include <stdio.h> 1. (14) struct line { 2. (19) char string[256];
.
.
.
Program terminated normally(dbx)
The argument is
sam.c
.
[Return to example]
Reruns the program with the previously specified arguments. [Return to example]
For debugging programs written in high-level
languages, the
step
and
next
commands
execute a fixed number of source-code lines as specified by
EXP
.
For debugging programs written in assembly language, the
stepi
and
nexti
commands work the same as
step
and
next
except that they step by machine instructions
instead of by program lines.
If
EXP
is not specified,
dbx
executes one source-code line or machine instruction; otherwise,
dbx
executes the source-code lines or machine instructions as follows:
The
dbx
debugger does not take comment
lines into consideration in interpreting
EXP
.
The program
executes
EXP
source-code lines, regardless of the number
of comment lines interspersed among them.
For
step
and
stepi
,
dbx
considers
EXP
to apply both to the current
procedure and to called procedures.
Program execution stops after
EXP
source lines in the current procedure and any called procedures.
For
next
and
nexti
,
dbx
considers
EXP
to apply only to the current
procedure.
Program execution stops after executing
EXP
source lines in the current procedure, regardless of the number of source
lines executed in any called procedures.
The
step/stepi
and
next/nexti
commands have the following form:
step [EXP]
stepi [EXP]
Executes the specified number of lines or instructions in both the current procedure and any called procedures. The default is 1.
next [EXP]
nexti [EXP]
Executes the specified number of source-code lines or machine instructions in only the current procedure, regardless of the number of lines executed in any called procedures. The default is 1.
For example:
(dbx)
rerun
[7] stopped at [prnt:52,0x120000c04] fprintf(stdout,"%3d.(%3d) %s",
(dbx)
step 2
0. ( 19) #include <stdio.h> [prnt:55 ,0x120000c48] }(dbx)
step
[main:40 ,0x120000b40] i=strlen(line1.string);
(dbx)
The
$break_during_step
and
$printwhilestep
variables affect stepping.
See
Table 5-8
for more information.
5.7.3 Using the return Command
The
return
command is used in a called procedure to execute the remaining
instructions in the procedure and return to the calling procedure.
The
return
command has the following forms:
return
Executes the rest of the current procedure and stops at the next sequential line in the calling procedure.
return PROCEDURE
Executes the
rest of the current procedure and any calling procedures intervening between
the current procedure and the procedure named by
PROCEDURE
.
Stops at the point of the call in the procedure that is named.
For example:
(dbx)
rerun
[7] stopped at [prnt:52,0x120000c04] fprintf(stdout,"%3d.(%3d) %s",
(dbx)
return
0. (19) #include <stdio.h> stopped at [main:45 +0xc,0x120000bb0] prnt(&line1); (dbx)
5.7.4 Going to a Specific Place in the Code
The
goto
command shifts to the specified line and continues execution.
This command is useful in a
when
statement -- for
example, to skip a line known to cause problems.
The
goto
command has the following form:
goto LINE
Goes to the specified source line when you continue execution.
For example:
(dbx)
when at 40 {goto 43}
[8] start sam.c:43 at "sam.c":40 (dbx)
5.7.5 Resuming Execution After a Breakpoint
For
debugging programs written in high-level languages, the
cont
command resumes program execution after a breakpoint.
For debugging programs
written in assembly language, the
conti
command works the
same as
cont
.
The
cont
and
conti
commands have the following forms:
cont
conti
Continues from the current source-code line or machine-code address.
cont to LINE
conti to ADDRESS
Continues until the specified source-code line or machine-code address.
cont in PROCEDURE
conti in PROCEDURE
Continues until the specified procedure.
cont SIGNAL
conti SIGNAL
After receiving the specified signal, continues from the current line or machine instruction.
cont SIGNAL to LINE
conti SIGNAL to ADDRESS
After receiving the specified signal, continues until the specified line or address.
cont SIGNAL in PROCEDURE
conti SIGNAL in PROCEDURE
Continues until the specified procedure and sends the specified signal.
The following example shows the use of the
cont
command in a C program:
(dbx)
stop in prnt
[9] stop in prnt
(dbx)
rerun
[9] stopped at [prnt:52,0x120000c04] fprintf(stdout,"%3d.(%3d) %s",(dbx)
cont
0. ( 19) #include <stdio.h> [9] stopped at [prnt:52,0x120000c04] fprintf(stdout,"%3d.(%3d) %s",(dbx)
The following example shows the use of the
conti
command in an assembly-language program:
(dbx)
conti
0. ( 19) #include <stdio.h> [4] stopped at >*[prnt:52 ,0x120000c04] ldq r16,-32640(gp) (dbx)
5.7.6 Changing the Values of Program Variables
The
assign
command changes the
value of a program variable.
The
assign
command has the
following form:
assign VAR = EXP
assign EXP1 = EXP2
Assigns
a new value to the program variable named by
VAR
or the
address represented by the resolution of
EXP1
.
For example:
(dbx)
print i
19
[1](dbx)
assign i = 10
10
[2](dbx)
assign *(int *)0x444 = 1
[3]1
(dbx)
The value of
i
.
[Return to example]
The new value of
i
.
[Return to example]
Coerce the address to be an integer and assign a value of 1 to it. [Return to example]
The
patch
command
patches an executable disk file to correct bad data or instructions.
Only
text, initialized data, or read-only data areas can be patched.
The
bss
segment cannot be patched because it does not exist in disk
files.
The
patch
command fails if it is entered against
a program that is executing.
The
patch
command has the following form:
patch VAR = EXP
patch EXP1 = EXP2
Assigns a
new value to the program variable named by
VAR
or the address
represented by the resolution of
EXP1
.
The patch is applied to the default disk file; you can use qualified variable names to specify a patch to a file other than the default. Applying a patch in this way also patches the in-memory image of the file being patched.
For example:
(dbx)
patch &main = 0
(dbx)
patch var = 20
(dbx)
patch &var = 20
(dbx)
patch 0xnnnnn = 0xnnnnn
5.7.8 Running a Specific Procedure
It is possible for you to set the current
line pointer to the beginning of a procedure, place a breakpoint at the end
of the procedure, and run the procedure.
However, it is usually easier to
use the
call
or
print
command to execute
a procedure in your program.
The
call
or
print
command executes the procedure you specify on the command line.
You can pass parameters to the procedure by specifying them as arguments
to the
call
or
print
command.
The
call
or
print
command does
not alter the flow of your program.
When the procedure returns, the program
remains stopped at the point where you entered the
call
or
print
command.
The
print
command
displays values returned by called procedures; the
call
command does not.
The
call
and
print
commands have
the following forms:
call PROCEDURE([parameters
])
print PROCEDURE([parameters
])
Executes the object code associated with the named procedure or function. Specified parameters are passed to the procedure or function.
(dbx)
stop in prnt
[1][11] stop in prnt
(dbx)
call prnt(&line1)
[2] [11] stopped at [prnt:52,0x120000c] fprintf(stdout,"%3d.(%3d) %s",(dbx)
status
[3] [11] stop in prnt [12] stop at "sam.c":40 [2] record output example2 (126 lines)(dbx)
delete 11,12
[4](dbx)
The
stop
command sets
a breakpoint in the
prnt()
function.
[Return to example]
The
call
command begins
executing the object code associated with
prnt()
.
The
line1
argument passes a string by reference to
prnt
.
[Return to example]
The
status
command displays
the currently active breakpoints.
[Return to example]
The
delete
command deletes
the breakpoints at lines 52 and 40.
[Return to example]
The
print
command allows you to include a procedure
as part of an expression to be printed.
For example:
(dbx)
print sqrt(2.)+sqrt(3.)
5.7.9 Setting Environment Variables
Use the
setenv
command
to set an environment variable.
You can use this command to set the value
of an existing environment variable or create a new environment variable.
The environment variable is visible to both
dbx
and the
program you are running under
dbx
control, but it is not
visible after you exit the
dbx
environment.
However, if
you start a shell with the
sh
command within
dbx
, that shell can see
dbx
environment variables.
To change an environment variable for a process, you must enter the
setenv
command before starting up the process within
dbx
with the
run
command.
The
setenv
command has the following form:
setenv VAR "STRING"
Changes the value of an existing environment variable or creates a new one. To reset an environment variable, specify a null string.
(dbx)
setenv TEXT "sam.c"
[1](dbx)
run
[2] [4] stopped at [prnt:52,0x120000e34] fprintf(stdout,"%3d.(%3d) %s",(dbx)
setenv TEXT ""
[3](dbx)
run
[4] Usage: sam filename Program exited with code 1
The
setenv
command sets
the environment variable
TEXT
to the value
sam.c
.
[Return to example]
The
run
command executes
the program from the beginning.
The program reads input from the file named
in the the environment variable
TEXT
.
Program execution
stops at the breakpoint at line 52.
[Return to example]
The
setenv
command sets
the environment variable
TEXT
to null.
[Return to example]
The
run
command executes
the program.
Because the
TEXT
environment variable contains
a null value, the program must get input.
[Return to example]
A breakpoint stops program execution and lets you examine the program's
state at that point.
The following sections describe the
dbx
commands to set a breakpoint at a specific line or in a procedure and to stop
for signals.
5.8.1 Overview
When a program stops at a breakpoint, the debugger displays an informational
message.
For example, if a breakpoint is set in the sample program
sam.c
at line 23 in the
main()
procedure, the
following message is displayed:
[4] stopped at [main:40, 0x120000b18] i=strlen(line1.string); | | | | | [1] [2] [3] [4] [5]
Breakpoint status number. [Return to example]
Procedure name. [Return to example]
Line number. [Return to example]
Current program counter. Use this number to display the assembly-language instructions from this point. (See Section 5.7.5 for more information.) [Return to example]
Source line. [Return to example]
Use the
file
command to select the source
file.
Use the
func
command to specify a procedure
name.
List the lines of the file or procedure using the
list
command (see
Section 5.6.4).
Use a
stop
at
command
to set a breakpoint at the desired line.
5.8.2 Setting Breakpoints with stop and stopi
For
debugging programs written in high-level languages, the
stop
command sets breakpoints to stop execution as follows: at a source line, in
a procedure, when a variable changes, or when a specified condition is true.
For debugging programs written in assembly language, the
stopi
command works the same as
stop
, except that it traces by
machine instructions instead of by program lines.
You can also instruct
dbx
to stop when it enters a new image invoked by an
exec( \)
call by setting the
$stop_on_exec
predefined
variable (see
Table 5-8).
The
stop
at
and
stopi
at
commands set a breakpoint at a specific
source-code line or machine-code address, as applicable.
The
dbx
debugger stops only at lines or addresses that have executable
code.
If you specify a nonexecutable stopping point,
dbx
sets the breakpoint at the next executable point.
If you specify the
VAR
parameter, the debugger displays the variable and stops only
when
VAR
changes; if you specify
if
EXP
, the debugger stops only when
EXP
is true.
The
stop
in
and
stopi
in
commands set a breakpoint at the beginning
or, conditionally, for the duration of a procedure.
The
stop
if
and
stopi
if
commands cause
dbx
to stop program execution under specified conditions.
Because
dbx
must check the condition after
the execution of each line, this command slows program execution markedly.
Whenever possible, use
stop/stopi
at
or
stop/stopi
in
instead of
stop/stopi
if
.
If the
$stop_on_exec
predefined variable is
set to 1, an
exec( )
call causes
dbx
to stop and read in the new image's symbol table, then advance to the image's
main activation point and stop for user input.
The
delete
command removes breakpoints established
by the
stop
or
stopi
command.
The
stop
and
stopi
commands have
the following forms:
stop VAR
stopi VAR
Stops when
VAR
changes.
stop VAR at LINE
stopi VAR at ADDRESS
Stops
when
VAR
changes at a specified source-code line or machine-code
address.
stop VAR at LINE if EXP
stopi VAR at ADDRESS if EXP
Stops when
VAR
changes at a specified line or address only
if the expression is true.
stop if EXP
stopi if EXP
Stops if
EXP
is true.
stop VAR if EXP
stopi VAR if EXP
Stops when
VAR
changes if
EXP
is true.
stop in PROCEDURE
stopi in PROCEDURE
Stops at the beginning of the procedure.
stop VAR in PROCEDURE
Stops
in the specified procedure when
VAR
changes.
stop VAR in PROCEDURE if EXP
stopi VAR in PROCEDURE if EXP
Stops when
VAR
changes in the specified procedure if
EXP
is true.
Note
Specifying both
VAR
andEXP
causes stops anywhere in the procedure, not just at the beginning. Using this feature is time consuming because the debugger must check the condition before and after each source line is executed. (When both arguments are specified,EXP
is always checked beforeVAR
.)
The following example shows the use of
stop
in
a C program:
(dbx)
stop at 52
[3] stop at "sam.c":52
(dbx)
rerun
[3] stopped at [prnt:52,0x120000fb0] fprintf(stdout,"%3d.(%3d) %s",(dbx)
stop in prnt
[15] stop in prnt
(dbx)
The following example shows
the use of
stopi
in an assembly-language program:
(dbx)
stopi at 0x120000c04
[4] stop at 0x120000c04
(dbx)
rerun
[7] stopped at >*[prnt:52 ,0x120000c04] ldq r16, -32640(gp)
5.8.3 Tracing Variables During Execution
For
debugging programs written in high-level languages, the
trace
command lists the value of a variable while the program is executing and determines
the scope of the variable being traced.
For debugging programs written in
assembly language, the
tracei
command works the same as
trace
, except that it traces by machine instructions instead of
by program lines.
The
trace
and
tracei
commands
have the following forms:
trace LINE
Lists the specified source line each time it is executed.
trace VAR
tracei VAR
Lists the specified variable after each source line or machine instruction is executed.
trace [VAR] at LINE
tracei [VAR] at ADDRESS
Lists the specified variable at the specified line or instruction.
trace [VAR] in PROCEDURE
tracei [VAR] in PROCEDURE
Lists the specified variable in the specified procedure.
trace [VAR] at LINE if EXP
tracei [VAR] at ADDRESS if EXP
Lists the variable at the specified source-code line or machine-code address
when the expression is true and the value of the variable has changed.
(EXP
is checked before
VAR
.)
trace [VAR] in PROCEDURE if EXP
tracei [VAR] in PROCEDURE if EXP
Lists the variable in the specified procedure when the expression is
true and the value of the variable has changed.
(EXP
is
checked before
VAR
.)
For example:
(dbx)
trace i
[5] trace i in main
(dbx)
rerun sam.c
[4] [main:25 ,0x400a50]
(dbx)
c
[5] i changed before [main: line 41]: new value = 19; [5] i changed before [main: line 41]: old value = 19; new value = 14; [5] i changed before [main: line 41]: old value = 14; new value = 19; [5] i changed before [main: line 41]: old value = 19; new value = 13; [5] i changed before [main: line 41]: old value = 13; new value = 17; [5] i changed before [main: line 41]: old value = 17; new value = 3; [5] i changed before [main: line 41]: old value = 3; new value = 1; [5] i changed before [main: line 41]: old value = 1; new value = 30;
5.8.4 Writing Conditional Code in dbx
The
when
command controls the conditions under which certain
dbx
commands that you specify will be executed.
The
when
command has the following forms:
when VAR [if EXP] {COMMAND_LIST}
Executes the command list when
EXP
is true and
VAR
changes.
when [VAR] at LINE [if EXP] {COMMAND_LIST}
Executes the command list when
EXP
is true,
VAR
changes, and the debugger encounters
LINE
.
when in PROCEDURE {COMMAND_LIST}
Executes the command list upon entering
PROCEDURE
.
when [VAR] in PROCEDURE [if EXP] {COMMAND_LIST}
Executes the specified commands on each line of
PROCEDURE
when
EXP
is true and
VAR
changes.
(EXP
is checked before
VAR
.)
For example:
(dbx)
when in prnt {print line1.length}
[6] print line1.length in prnt
(dbx)
rerun
19 [1] 14 19
.
.
.
17 59 45 12More (n if no)?
(dbx)
delete 6
(dbx)
when in prnt {stop}
[7] stop in prnt
(dbx)
rerun
[7] stopped at [prnt:52,0x12000fb0] fprintf(stdout,"%3d.(%3d) %s") [2]
Value of
line1.length
.
[Return to example]
Stops in the procedure
prnt
.
[Return to example]
The
catch
command either lists
the signals that
dbx
catches or specifies a signal for
dbx
to catch.
If the process encounters a specified signal,
dbx
stops the process.
The
ignore
command either lists the signals that
dbx
does not catch or specifies a signal for
dbx
to add to
the ignore list.
The
catch
and
ignore
commands
have the following forms:
catch
Displays a list of all
signals that
dbx
catches.
catch SIGNAL
Adds a signal to the catch list.
ignore
Displays a list of all
signals that
dbx
does not catch.
ignore SIGNAL
Removes a signal from the catch list and adds it to the ignore list.
(dbx)
catch
[1] INT QUIT ILL TRAP ABRT EMT FPE BUS SEGV SYS PIPE TERM URG \ STOP TTIN TTOU IO XCPU XFSZ VTALRM PROF WINCH INFO USR1 USR2(dbx)
ignore
[2]HUP KILL ALRM TSTP CONT CHLD
(dbx)
catch kill
[3](dbx)
catch
INT QUIT ILL TRAP ABRT EMT FPE KILL BUS SEGV SYS PIPE TERM URG \ STOP TTIN TTOU IO XCPU XFSZ VTALRM PROF WINCH INFO USR1 USR2(dbx)
ignore
HUP ALRM TSTP CONT CHLD
(dbx)
Displays the catch list. [Return to example]
Displays the ignore list. [Return to example]
Adds
KILL
to the catch list
and removes
KILL
from the ignore list.
[Return to example]
The backslashes in the preceding example represent line continuation.
The actual output from
catch
and
ignore
is a single line.
5.9 Examining Program State
When
dbx
is stopped at a breakpoint, the program
state can be examined to determine what might have gone wrong.
The debugger
provides commands for displaying stack traces, variable values, and register
values.
The debugger also provides commands to display information about the
activation levels shown in the stack trace and to move up and down the activation
levels (see
Section 5.6.2).
5.9.1 Printing the Values of Variables and Expressions
The
print
command displays the values of one
or more expressions.
The
printf
command lists information in a specified
format and supports all formats of the
printf()
function
except strings (%s
).
For a list of formats, see
printf
(3).
You can use the
printf
command to see a variable's value
in a different number base.
The default command alias list (see
Section 5.5.3)
provides some useful aliases for displaying the value of variables in different
bases -- octal (po
), decimal (pd
),
and hexadecimal (px
).
The default number base is decimal.
You can specify either the real machine register names or the software
names from the include file
regdef.h
.
A prefix before the
register number specifies the type of register; the prefix can be either
$f
or
$r
, as shown in the following list of registers:
Register Name(s) | Register Type |
$f00-$f31 |
Floating-point register (1 of 32) |
$r00-$r31 |
Machine register (1 of 32) |
$fpcr |
Floating-point control register |
$pc |
Program counter value |
$ps |
Program status register [Footnote 4] |
You can also specify prefixed registers in the
print
command to display a register value or the program counter.
The following
commands display the values of machine register 3 and the program counter:
(dbx)
print $r3
(dbx)
print $pc
The
print
command has the following forms:
print EXP1,...,EXPN
Displays the value of the specified expressions.
printf "STRING", EXP1,...,EXPN
Displays the value of the specified expressions in the format specified by the string.
Note
If the expression contains a name that is the same as a
dbx
keyword, you must enclose the name within parentheses. For example, to printoutput
, a keyword in theplayback
andrecord
commands, specify the name as follows:(dbx)
print (output)
For example:
(dbx)
print i
14
[1](dbx)
po i
016
[2](dbx)
px i
0xe
[3](dbx)
pd i
14
[4](dbx)
Decimal [Return to example]
Octal [Return to example]
Hexadecimal [Return to example]
Decimal [Return to example]
The
printregs
command displays a complete list
of register values; it accepts no arguments.
As with the
print
command, the default base for display by
printregs
is decimal.
To display values in hexadecimal with the
printregs
command,
set the
dbx
variable
$hexints
.
For example:
(dbx)
printregs
$vfp= 4831837712 $r0_v0=0 $r1_t0=0 $r2_t1=0 $r3_t2=18446744069416926720 $r4_t3=18446744071613142936 $r5_t4=1 $r6_t5=0
.
.
.
$f25= 0.0 $f26= 0.0 $f27= 2.3873098155006918e-314 $f28= 2.6525639909000367e-314 $f29= 9.8813129168249309e-324 $f30= 2.3872988413145664e-314 $f31= 0.0 $pc= 4831840840
5.9.2 Displaying Activation-Level Information with the dump Command
The
dump
command displays
information about activation levels, including values for all variables that
are local to a specified activation level.
To see what activation levels are
currently active in the program, use the
where
command
to get a stack trace.
The
dump
command has the following forms:
dump
Displays information about the current activation level.
dump .
Displays information about all activation levels.
dump PROCEDURE
Displays information about the specified procedure (activation level).
For example:
(dbx)
where
> 0 prnt(pline = 0x11ffffcb8) ["sam.c":52, 0x120000c04] 1 main(argc = 2, argv = 0x11ffffe08) ["sam.c":45, 0x120000bac](dbx)
dump
prnt(pline = 0x11ffffcb8) ["sam.c":52, 0x120000c04]
(dbx)
dump .
> 0 prnt(pline = 0x11ffffcb8) ["sam.c":52, 0x120000c04] 1 main(argc = 2, argv = 0x11ffffe08) ["sam.c":45, 0x120000bac] line1 = struct { string = "#include <stdio.h>" length = 19 linenumber = 0 } fd = 0x140000158 fname = 0x11ffffe9c = "sam.c" i = 19 curlinenumber = 1(dbx)
dump main
main(argc = 2, argv = 0x11ffffe08) ["sam.c":45, 0x120000bac] line1 = struct { string = "#include <stdio.h>" length = 19 linenumber = 0 } fd = 0x140000158 fname = 0x11ffffe9c = "sam.c" i = 19 curlinenumber = 1 (dbx)
5.9.3 Displaying the Contents of Memory
You can display memory contents by specifying the address and the format of the display. Use the following form, with no spaces between the three parts of the command:
address/count mode
The address portion of the command is the address of the first item to be displayed, count is the number of items to be shown, and mode indicates the format in which the items are to be displayed. For example:
prnt/20i
This example displays the contents of
20 machine instructions, beginning at the address of the
prnt
function.
The values for
mode
are shown in
Table 5-9.
Table 5-9: Modes for Displaying Memory Addresses
Mode | Display Format |
b |
Displays a byte in octal. |
c |
Displays a byte as a character. |
D |
Displays a long word (64 bits) in decimal. |
d |
Displays a short word (16 bits) in decimal. |
dd |
Displays a word (32 bits) in decimal. |
f |
Displays a single-precision real number. |
g |
Displays a double-precision real number. |
i |
Displays machine instructions. |
O |
Displays a long word in octal. |
o |
Displays a short word in octal. |
oo |
Displays a word (32 bits) in octal. |
s |
Displays a string of characters that ends in a null byte. |
X |
Displays a long word in hexadecimal. |
x |
Displays a short word in hexadecimal. |
xx |
Displays a word (32 bits) in hexadecimal. |
The following example shows the output when displaying memory addresses as instructions:
(dbx)
&prnt/20i
[prnt:51, 0x120000bf0] ldah gp, 8193(r27) [prnt:51, 0x120000bf4] lda gp, -25616(gp) [prnt:51, 0x120000bf8] lda sp, -64(sp) [prnt:51, 0x120000bfc] stq r26, 8(sp) [prnt:51, 0x120000c00] stq r16, 16(sp) [prnt:52, 0x120000c04] ldq r16, -32640(gp) >*[prnt:52, 0x120000c08] addq r16, 0x38, r16 [prnt:52, 0x120000c0c] ldq r17, -32552(gp) [prnt:52, 0x120000c10] ldq r1, 16(sp) [prnt:52, 0x120000c14] ldl r18, 260(r1) [prnt:52, 0x120000c18] ldl r19, 256(r1) [prnt:52, 0x120000c1c] bis r1, r1, r20 [prnt:52, 0x120000c20] ldq r27, -32624(gp) [prnt:52, 0x120000c24] jsr r26, (r27), 0x4800030a0 [prnt:52, 0x120000c28] ldah gp, 8193(r26) [prnt:52, 0x120000c2c] lda gp, -25672(gp) [prnt:54, 0x120000c30] ldq r16, -32640(gp) [prnt:54, 0x120000c34] addq r16, 0x38, r16 [prnt:54, 0x120000c38] ldq r27, -32544(gp) [prnt:54, 0x120000c3c] jsr r26, (r27), 0x480003100
5.9.4 Recording and Playing Back Portions of a dbx Session
The
dbx
debugger allows you to capture and replay portions of your input
to the program and also portions of its output.
Recorded information is written
to a file so that you can reuse or re-examine it.
Recording input can be useful for creating command files containing
sequences that you want to repeat many times; you can even use recorded input
to control
dbx
for purposes such as regression testing.
Recording output is useful for capturing large volumes of information that
are inconvenient to deal with on the screen, so that you can analyze them
later.
To look at recorded output later, you can read the saved file directly
or you can play it back with
dbx
.
5.9.4.1 Recording and Playing Back Input
The
record input
command records debugger input.
The
playback input
command repeats a recorded sequence.
The
record input
and
playback input
commands have the following forms:
record input [FILE]
Begins
recording
dbx
commands in the specified file or, if no
file is specified, in a file placed in
/tmp
and given a
generated name.
playback input [FILE]
source [FILE]
Executes the commands from the specified file or, if no file is specified, from the temporary file. The two forms are identical in function.
The name given to the temporary file, if used, is contained
in the debugger variable
$defaultin
.
To display the temporary
file name, use the
print
command:
(dbx)
print $defaultin
Use a temporary file when you need to refer to the saved output only
during the current debugging session; specify a file name to save information
for reuse after you end the current debugging session.
Use the
status
command to see whether recording is active.
Use the
delete
command to stop recording.
Note that these commands will appear
in the recording; if you are creating a file for future use, you will probably
want to edit the file to remove commands of this type.
Use the
playback
input
command
to replay the commands recorded with the
record
input
command.
By default, playback is silent; you do not see the
commands as they are played.
If the
dbx
variable
$pimode
is set to 1,
dbx
displays commands as
they are played back.
The following example records input and displays the resulting file:
(dbx)
record input
[1][2] record input /tmp/dbxtX026963 (0 lines)
(dbx)
status
[2] record input /tmp/dbxtX026963 (1 lines)
(dbx)
stop in prnt
[3] stop in prnt
(dbx)
when i = 19 {stop}
[4] stop ifchanged i = 19
(dbx)
delete 2
[2](dbx)
playback input
[3] [3] stop in prnt [4] stop ifchanged i = 19 [5] stop in prnt [6] stop ifchanged i = 19 /tmp/dbxtX026963: 4: unknown event 2 [4](dbx)
Start recording. [Return to example]
Stop recording. [Return to example]
Play back the recorded input. As events 3 and 4 are played, they create duplicates of themselves, numbered 5 and 6, respectively. [Return to example]
The debugger displays this error message because event 2, the command to begin recording, was deleted when recording was stopped. [Return to example]
The temporary file resulting from the preceding
dbx
commands contains the following text:
status stop in prnt when i = 19 {stop} delete 2
5.9.4.2 Recording and Playing Back Output
Use
the
record
output
command to record
dbx
output during a debugging session.
To produce a complete record
of activity by recording input along with the output, set the
dbx
variable
$rimode
.
You can use the debugger's
playback
output
command to look at the recorded
information, or you can use any text editor.
The
record
output
and
playback
output
commands have the following forms:
record output [FILE]
Begins
recording
dbx
output in the specified file or, if no file
is specified, in a file placed in
/tmp
and given a generated
name.
playback output [FILE]
Displays recorded output from the specified file or, if no file is specified, from the temporary file.
The name given to the temporary file, if used, is contained
in the debugger variable
$defaultout
.
To display the temporary
file name, use the
print
command:
(dbx)
print $defaultout
The
playback
output
command works the same as the
cat
command; a display from the
record
output
command is identical to the contents of the recording file.
Use a temporary file when you need to refer to the saved output only
during the current debugging session; specify a file name to save information
for reuse after you end the current debugging session.
Use the
status
command to see whether recording is active.
Use the
delete
command to stop recording.
The following example shows a sample
dbx
interaction
and the output recorded for this interaction in a file named
code
:
(dbx)
record output code
[3] record output code (0 lines)
(dbx)
stop at 25
[4] stop at "sam.c":25
(dbx)
run sam.c
[4] stopped at [main:25 ,0x120000a48] if (argc < 2) {
(dbx)
delete 3
(dbx)
playback output code
[3] record output code (0 lines) (dbx) [4] stop at "sam.c":25 (dbx) [4] stopped at [main:25 ,0x120000a48] if (argc < 2) {(dbx)
5.10 Enabling Core-Dump File Naming
This section explains how to enable the operating system's core-dump file naming feature so that you can preserve multiple core files.
When you enable core-file naming, the system produces core files with names in the following format:
core.prog-name.host-name.tag
The name of the core file has four parts separated by periods:
The literal string
core
.
Up to 16 characters of the program name, as displayed by the
ps
command.
Up to 16 characters of the system's network host name, as derived from the part of the host name that precedes the first dot in the host name format.
A numeric tag that is assigned to the core file to make it unique among all of the core files generated by a program on a host. The maximum value for this tag, and therefore the maximum number of core files for this program and host, is set by a system configuration parameter (see Section 5.10.1).
The tag is not a literal version number. The system selects the first available unique tag for the core file. For example, if a program's core files have tags 0, 1, and 3, the system uses tag 2 for the next core file it creates for that program. If the system-configured limit for core-file instances is reached, no further core files are created for that program and host combination. By default, up to 16 versions of a core file can be created.
To conserve disk space, be sure to remove core files after you have examined them. This is necessary because named core files are not overwritten.
You can enable core-file naming at either the system level (Section 5.10.1)
or the individual application level (Section 5.10.2).
5.10.1 Enabling Core-File Naming at the System Level
You can enable core-file naming at the system level by using the
dxkerneltuner
(8X)
(graphical interface) or
sysconfig
(8)
utility.
To enable
core-file naming, set the
enhanced-core-name
process subsystem
attribute to 1.
To limit the number of unique core-file versions that a program
can create on a specific host system, set the process subsystem attribute
enhanced-core-max-versions
to the desired value.
For example:
proc: enhanced-core-name = 1 enhanced-core-max-versions = 8
The minimum, maximum, and default numbers
of versions are 1, 99999, and 16, respectively.
5.10.2 Enabling Core-File Naming at the Application Level
To enable core-file naming at the application level, your program should
use the
uswitch
system call with the
UWS_CORE
flag set, as in the following example:
#include <signal.h> #include <xsys/uswitch.h> /* * Request enhanced core-file naming for * this process, then create a core file. */ main() { long uval = uswitch(USC_GET, 0); uval = uswitch(USC_SET, uval | USW_CORE); if (uval < 0) { perror("uswitch"); exit(1); } raise(SIGQUIT); }
5.11 Debugging a Running Process
You can use the
dbx
debugger to debug running processes
that are started outside the
dbx
environment.
It supports
the debugging of such processes, both parent and child, by using the
/proc
file system.
The debugger can debug running processes only
if the
/proc
file system is mounted.
If
/proc
is not already mounted, the superuser can mount it with the following
command:
#
mount -t procfs /proc /proc
You can add the following
entry to the
/etc/fstab
file to mount
/proc
upon booting:
/proc /proc procfs rw 0 0
The
dbx
debugger checks first to see
if
/proc
is mounted, but it will still function if this
is not the case.
To attach to a running process, use the
dbx
command
attach
, which has the following form:
attach
process-idThe process-id argument is the process ID of the process you want to attach to.
You can also attach to a process for debugging by using the
command-line option
-pid process id
.
To detach from a running process, use the
dbx
command
detach
, which has the following form:
detach [process-id
]
The optional
process-id
argument is the process ID of the process you want to detach from.
If no argument
is given,
dbx
detaches from the current process.
To change from one process to another, use the
dbx
command
switch
, which has the following form:
switch
process-idThe
process-id
argument is the
process ID of the process you want to switch to.
You must already have attached
to a process before you can switch to it.
You can use the alias
sw
for the
switch
command.
The
attach
command first checks to see
whether
/proc
is mounted;
dbx
gives
a warning that tells you what to do if it is not mounted.
If
/proc
is mounted,
dbx
looks for the process ID in
/proc
.
If the process ID is in
/proc
,
dbx
attempts to open the process and issues a
stop
command.
If the process is not there or if the permissions do not allow attaching
to it,
dbx
reports this failure.
When the
stop
command takes effect,
dbx
reports the current position, issues a prompt, and waits for user
commands.
The program probably will not be stopped directly in the user code;
it will more likely be stopped in a library or system call that was called
by user code.
The
detach
command deletes all current breakpoints,
sets up a "run on last close" flag, and closes ("releases")
the process.
The program then continues running if it has not been explicitly
terminated inside
dbx
.
To see a summary of all active processes under the control of
dbx
, use the
plist
command, which has the following
form:
plist
Displays a list of active
processes and their status.
Indicates the current process with a marker:
Ÿ
5.12 Debugging Multithreaded Applications
The
dbx
debugger provides three basic commands to
assist in the debugging of applications that use threads:
The
tlist
command displays a quick list of all threads and where they
are currently positioned in the program.
This command accepts no arguments.
Using the
tlist
command, you can see all of the threads,
with their IDs, that are currently in your program.
The
tset
command sets the current thread.
The debugger maintains one
thread as the current thread; this thread is the one that hits a breakpoint
or receives a signal that causes it to stop and relinquish control to
dbx
.
Use
tset
to choose a different thread as the current
thread so that you can examine its state with the usual
dbx
commands.
Note that the selected thread remains the current thread until you
enter another
tset
command.
Note also that the
continue
,
step
, or
next
commands
might be inappropriate for a given thread if it is blocked or waiting to join
with another thread.
The
tstack
command lists the stacks of all threads in your application.
It is similar to the
where
command and, like
where
, takes an optional numeric argument to limit the number of
stack levels displayed.
The
tset
and
tstack
commands have
the following forms:
tset [EXP]
Choose a thread
to be the current thread.
The
EXP
argument is the hexadecimal
ID of the desired thread.
tstack [EXP]
Display stack
traces for all threads.
If
EXP
is specified,
dbx
displays only the top
EXP
levels of the stacks;
otherwise, the entire stacks are displayed.
If the POSIX Threads Library product is installed on your system, you
can gain access to the POSIX Threads Library pthread debugger by issuing a
call
cma_debug()
command within your
dbx
session.
The pthread debugger can provide a great deal of useful information about
the threads in your program.
For information on using the pthread debugger,
enter a
help
command at its
debug>
prompt.
A sample threaded program,
twait.c
, is shown in
Example 12-1.
The following example shows a
dbx
session using that program.
Long lines in this example have all been folded
at 72 characters to represent display on a narrow terminal.
%
dbx twait
dbx version 3.11.6 Type 'help' for help. main: 50 pthread_t me = pthread_self(), timer_thread;(dbx)
stop in do_tick
[2] stop in do_tick
(dbx)
stop at 85
[3] stop at "twait.c":85
(dbx)
stop at 35
[4] stop at "twait.c":35
(dbx)
run
1: main thread starting up 1: exit lock initialized 1: exit lock obtained 1: exit cv initialized 1: timer_thread 2 created 1: exit lock released [2] thread 0x81c62e80 stopped at [do_tick:21 ,0x12000730c] pthread_ t me = pthread_self();(dbx)
tlist
thread 0x81c623a0 stopped at [msg_receive_trap:74 +0x8,0x3ff808edf04] Source not available thread 0x81c62e80 stopped at [do_tick:21 ,0x12000730c] pthread_ t me = pthread_self();(dbx)
where
> 0 do_tick(argP = (nil)) ["twait.c":21, 0x12000730c] 1 cma__thread_base(0x0, 0x0, 0x0, 0x0, 0x0) ["../../../../../src/usr/ ccs/lib/DECthreads/COMMON/cma_thread.c":1441, 0x3ff80931410](dbx)
tset 0x81c623a0
thread 0x81c623a0 stopped at [msg_receive_trap:74 +0x8,0x3ff808edf04] Source not available(dbx)
where
> 0 msg_receive_trap(0x3ff8087b8dc, 0x3ffc00a2480, 0x3ff8087b928, 0x181 57f0d0d, 0x3ff8087b68c) ["/usr/build/osf1/goldos.bld/export/alpha/usr/in clude/mach/syscall_sw.h":74, 0x3ff808edf00] 1 msg_receive(0x61746164782e, 0x3ffc009a420, 0x3ffc009a420, 0x3c20, 0 xe0420) ["../../../../../src/usr/ccs/lib/libmach/msg.c":95, 0x3ff808e474 4] 2 cma__vp_sleep(0x280187f578, 0x3990, 0x7, 0x3ffc1032848, 0x0) ["../. ./../../../src/usr/ccs/lib/DECthreads/COMMON/cma_vp.c":1471, 0x3ff809375 cc] 3 cma__dispatch(0x7, 0x3ffc1032848, 0x0, 0x3ffc100ee08, 0x3ff80917e3c ) ["../../../../../src/usr/ccs/lib/DECthreads/COMMON/cma_dispatch.c":967 , 0x3ff80920e48] 4 cma__int_wait(0x11ffff228, 0x140009850, 0x3ffc040cdb0, 0x5, 0x3ffc0 014c00) ["../../../../../src/usr/ccs/lib/DECthreads/COMMON/cma_condition .c":2202, 0x3ff80917e38] 5 cma_thread_join(0x11ffff648, 0x11ffff9f0, 0x11ffff9e8, 0x60aaec4, 0 x3ff8000cf38) ["../../../../../src/usr/ccs/lib/DECthreads/COMMON/cma_thr ead.c":825, 0x3ff80930a58] 6 pthread_join(0x140003110, 0x40002, 0x11ffffa68, 0x3ffc040cdb0, 0x0) ["../../../../../src/usr/ccs/lib/DECthreads/COMMON/cma_pthread.c":2193, 0x3ff809286c8] 7 main() ["twait.c":81, 0x12000788c](dbx)
tlist
thread 0x81c623a0 stopped at [msg_receive_trap:74 +0x8,0x3ff808edf04] Source not available thread 0x81c62e80 stopped at [do_tick:21 ,0x12000730c] pthread_ t me = pthread_self();(dbx)
tset 0x81c62e80
thread 0x81c62e80 stopped at [do_tick:21 ,0x12000730c] pthread_ t me = pthread_self();(dbx)
cont
2: timer thread starting up, argP=0x0 [4] thread 0x81c62e80 stopped at [do_tick:35 ,0x120007430] printf(" %d: wait for next tick\n", THRID(&me));(dbx)
cont
2: wait for next tick 2: TICK #1 [4] thread 0x81c62e80 stopped at [do_tick:35 ,0x120007430] printf(" %d: wait for next tick\n", THRID(&me));(dbx)
tstack
Thread 0x81c623a0: > 0 msg_receive_trap(0x3ff8087b8dc, 0x3ffc00a2480, 0x3ff8087b928, 0x181 57f0d0d, 0x3ff8087b68c) ["/usr/build/osf1/goldos.bld/export/alpha/usr/in clude/mach/syscall_sw.h":74, 0x3ff808edf00] 1 msg_receive(0x61746164782e, 0x3ffc009a420, 0x3ffc009a420, 0x3c20, 0 xe0420) ["../../../../../src/usr/ccs/lib/libmach/msg.c":95, 0x3ff808e474 4] 2 cma__vp_sleep(0x280187f578, 0x3990, 0x7, 0x3ffc1032848, 0x0) ["../. ./../../../src/usr/ccs/lib/DECthreads/COMMON/cma_vp.c":1471, 0x3ff809375 cc] 3 cma__dispatch(0x7, 0x3ffc1032848, 0x0, 0x3ffc100ee08, 0x3ff80917e3c ) ["../../../../../src/usr/ccs/lib/DECthreads/COMMON/cma_dispatch.c":967 , 0x3ff80920e48] 4 cma__int_wait(0x11ffff228, 0x140009850, 0x3ffc040cdb0, 0x5, 0x3ffc0 014c00) ["../../../../../src/usr/ccs/lib/DECthreads/COMMON/cma_condition .c":2202, 0x3ff80917e38] 5 cma_thread_join(0x11ffff648, 0x11ffff9f0, 0x11ffff9e8, 0x60aaec4, 0 x3ff8000cf38) ["../../../../../src/usr/ccs/lib/DECthreads/COMMON/cma_thr ead.c":825, 0x3ff80930a58] 6 pthread_join(0x140003110, 0x40002, 0x11ffffa68, 0x3ffc040cdb0, 0x0) ["../../../../../src/usr/ccs/lib/DECthreads/COMMON/cma_pthread.c":2193, 0x3ff809286c8] 7 main() ["twait.c":81, 0x12000788c] Thread 0x81c62e80: > 0 do_tick(argP = (nil)) ["twait.c":35, 0x120007430] 1 cma__thread_base(0x0, 0x0, 0x0, 0x0, 0x0) ["../../../../../src/usr/ ccs/lib/DECthreads/COMMON/cma_thread.c":1441, 0x3ff80931410] More (n if no)?(dbx)
tstack 3
Thread 0x81c623a0: > 0 msg_receive_trap(0x3ff8087b8dc, 0x3ffc00a2480, 0x3ff8087b928, 0x181 57f0d0d, 0x3ff8087b68c) ["/usr/build/osf1/goldos.bld/export/alpha/usr/in clude/mach/syscall_sw.h":74, 0x3ff808edf00] 1 msg_receive(0x61746164782e, 0x3ffc009a420, 0x3ffc009a420, 0x3c20, 0 xe0420) ["../../../../../src/usr/ccs/lib/libmach/msg.c":95, 0x3ff808e474 4] 2 cma__vp_sleep(0x280187f578, 0x3990, 0x7, 0x3ffc1032848, 0x0) ["../. ./../../../src/usr/ccs/lib/DECthreads/COMMON/cma_vp.c":1471, 0x3ff809375 cc] Thread 0x81c62e80: > 0 do_tick(argP = (nil)) ["twait.c":35, 0x120007430] 1 cma__thread_base(0x0, 0x0, 0x0, 0x0, 0x0) ["../../../../../src/usr/ ccs/lib/DECthreads/COMMON/cma_thread.c":1441, 0x3ff80931410](dbx)
cont
2: wait for next tick 2: TICK #2 [4] thread 0x81c62e80 stopped at [do_tick:35 ,0x120007430] printf(" %d: wait for next tick\n", THRID(&me));(dbx)
assign ticks = 29
29
(dbx)
cont
2: wait for next tick 2: TICK #29 [4] thread 0x81c62e80 stopped at [do_tick:35 ,0x120007430] printf(" %d: wait for next tick\n", THRID(&me));(dbx)
cont
2: wait for next tick 2: TICK #30 2: exiting after #31 ticks 1: joined with timer_thread 2 [3] thread 0x81c623a0 stopped at [main:85 ,0x1200078ec] if (errn o != 0) printf("errno 7 = %d\n",errno);(dbx)
tlist
thread 0x81c623a0 stopped at [main:85 ,0x1200078ec] if (errno != 0) printf("errno 7 = %d\n",errno); thread 0x81c62e80 stopped at [msg_rpc_trap:75 +0x8,0x3ff808edf10] Source not available(dbx)
cont
Program terminated normally(dbx)
tlist
(dbx)
quit
5.13 Debugging Multiple Asynchronous Processes
The
dbx
debugger can debug multiple simultaneous
asynchronous processes.
While debugging asynchronous processes,
dbx
can display status and accept commands asynchronously.
When
running asynchronously, the debugger might exhibit confusing behavior because
a running process can display output on the screen while you are entering
commands to examine a different process that is stopped.
The debugger automatically enters asynchronous mode in either of the following circumstances:
You command it to attach to a new process while a previous process is still attached.
The process to which
dbx
is attached forks
off a child process, and the debugger automatically attaches to the child
process without detaching from the parent.
The debugger uses several predefined variables to define the behavior
of asynchronous debugging.
(See
Table 5-8.) The
variable
$asynch_interface
can be viewed as a counter that
is incremented by 1 when a new process is attached and decremented by 1 when
a process terminates or is detached.
The default value is 0.
When
$asynch_interface
has a positive nonzero value,
asynchronous debugging is enabled; when the variable is 0 (zero) or negative,
asynchronous debugging is disabled.
To prevent
dbx
from
entering asynchronous mode, set the
$asynch_interface
variable
to a negative value.
(Note that disabling asynchronous mode might make debugging
more difficult if a parent is waiting on a child that is stopped.)
When a process executes a
fork( )
or
vfork( )
call to spawn a child process,
dbx
attaches to the child process and automatically enters asynchronous mode (if
permitted by
$asynch_interface
).
The default behavior is
to stop the child process right after the fork.
You can change this default
by setting the variable
$stop_on_fork
to 0; in this case,
dbx
will attach to the child process but not stop it.
The
dbx
debugger attempts to apply a degree of intelligence
to the handling of forks by filtering out many of the fork calls made by various
system and library calls.
If you want to stop the process on these forks also,
you can set the predefined variable
$stop_all_forks
to
1.
This variable's default value is 0.
Stopping on all forks can be particularly
useful when you are debugging a library routine.
You can use the debugger's
plist
and
switch
commands to monitor and switch between processes.
5.14 Sample Program
Example 5-1
is the sample C program (sam.c
) that is referred to in examples throughout this chapter.
Example 5-1: Sample Program Used in dbx Examples
#include <stdio.h> struct line { char string[256]; int length; int linenumber; }; typedef struct line LINETYPE; void prnt(); main(argc,argv) int argc; char **argv; { LINETYPE line1; FILE *fd; extern FILE *fopen(); extern char *fgets(); extern char *getenv(); char *fname; int i; static curlinenumber=0; if (argc < 2) { if((fname = getenv("TEXT")) == NULL || *fname == ' ') { fprintf(stderr, "Usage: sam filename\n"); exit(1); } } else fname = argv[1]; fd = fopen(fname,"r"); if (fd == NULL) { fprintf(stderr, "cannot open %s\n",fname); exit(1); } while(fgets(line1.string, sizeof(line1.string), fd) != NULL){ i=strlen(line1.string); if (i==1 && line1.string[0] == '\n') continue; line1.length = i; line1.linenumber = curlinenumber++; prnt(&line1); } } void prnt(pline) LINETYPE *pline; { fprintf(stdout,"%3d. (%3d) %s", pline->linenumber, pline->length, pline->string); fflush(stdout); }