CDB(1) — HP-UX
Series 300 Only
NAME
cdb, fdb, pdb − C, FORTRAN, Pascal symbolic debugger
SYNOPSIS
cdb [−d dir] [−r file] [−p file] [−S num] [objectfile [corefile]]
fdb [ cdb options ]
pdb [ cdb options ]
TABLE OF CONTENTS
DESCRIPTION
SMART TERMINAL SUPPORT
DUMB TERMINAL SUPPORT
CONVENTIONS
Notational Conventions
Variable Name Conventions
Expression Conventions
Procedure Call Conventions
COMMANDS
Window Mode Commands
File Viewing Commands
Display Formats
Data Viewing Commands
Stack Viewing Commands
Job Control Commands
Breakpoint Commands
Assertion Control Commands
Signal Control Commands
Record and Playback Commands
Macro Definition Commands
Miscellaneous Commands
DIAGNOSTICS
WARNINGS
DEPENDENCIES
AUTHOR
FILES
SEE ALSO
INTERNATIONAL SUPPORT
DESCRIPTION
Cdb, fdb, and pdb are alternate names for a source level debugger for C, HP FORTRAN, and HP Pascal programs. It provides a controlled environment for their execution.
Objectfile is an executable program file having one or more of its component modules compiled with the −g option. The support module /usr/lib/end.o must be included as the last object file in the list of those linked, except for libraries included with the −l option to ld(1) (done automatically with -g option to cc(1), fc(1), and pc(1)). The default for objectfile is a.out.
Corefile is a core image from a failed execution of objectfile. The default corefile is core.
Options
−d dir Specify dir as an alternate directory where source files are located. (The current directory is searched last.)
−r file Specify a record file which is invoked immediately (for overwrite, not for append). Used with Record and Playback Commands.
−p file Specify a playback file which is invoked immediately. Used with Record and Playback Commands.
−S num Set the size of the string cache to num bytes (default is 1024). The string cache holds data read from objectfile.
Only one objectfile and one corefile are allowed per debugging session. The program (objectfile) is not invoked as a child process until an appropriate job control command is given (see Job Control Commands). The same program can be restarted many times (as different child processes) during a single debugging session.
SMART TERMINAL SUPPORT
This is the user interface supported on most HP terminals. The top of the screen is a "window" into the current source file, and the bottom of the screen is for debugger and user program input and output. Separating the two areas is a line (in inverse video) indicating the current file, procedure, and line number. Within the source file window, a ">" points to the current location (which may or may not be the location at which the user program is currently stopped).
DUMB TERMINAL SUPPORT
This is the user interface on non-HP or unsupported terminal types. It does not support windows. The source file is displayed one line at a time. Some commands supply more information with this interface than with the "window" interface to help the user keep track of what is happening.
CONVENTIONS
The debugger remembers the current file, current procedure, current line, and current data location. They are a function of what you have been viewing (not necessarily executing) most recently. Many commands use these current locations as defaults, and many commands set them as a side effect. It is important to keep this in mind when deciding what a command does in any particular situation.
For example, if you stop in procedure "abc", then view procedure "def", then ask for the value of local variable "xyz", the debugger assumes that the variable belongs to procedure "def".
Notational Conventions
Most commands are of the form "[modifier] command-letter [options]". Numeric modifiers before and after commands can be any numeric expression. They need not be just simple numbers. A blank is required before any numeric option. Multiple commands on one line must be separated by ";".
These are common modifiers and other special notations:
(A | B | C) Any one of A or B or C is required.
[A | B | C] Any one of A or B or C is optional.
file A file name.
proc A procedure (or function, or subroutine) name.
var A variable name.
number A specific, constant number (e.g. "9", not "4+5"). Floating point (real) numbers can be used any place a constant is allowed.
expr Any expression, but with limitations stated below.
depth A stack depth, as printed by the "t" command. The top procedure is at a depth of zero. A negative depth acts like a depth of zero. Stack depth usually means "exactly at the specified depth", not "the first instance at or above the specified depth".
format A style for printing data. Used with Data Viewing Commands.
commands A series of debugger commands, separated by ";", entered on the command line or saved with a breakpoint or assertion. Semicolons are ignored (as commands) so they can be freely used as command separators. Commands can be grouped with "{}" for the "a", "b", "if", and "!" commands. In all other cases commands inside "{}" are ignored.
Variable Name Conventions
Variables are referenced exactly as they are named in your source file(s). Case sensitivity is controlled by the "Z" command. Be careful with one letter variable names, since they can be confused with commands. If an expression begins with a variable that might be mistaken for a command, just enclose the expression in "()" (e.g. "(k)"), or eliminate any white space between the variable and the first operator (use "k= 9" instead of "k = 9").
If you are interested in the value of some variable var, there are a number of ways of getting it, depending on where and what it is:
var Search the stack for the most recent instance of the current procedure. If found, see if var is a parameter or local variable of that procedure. If not, search for a global variable named either var or _var, in that order.
proc.var Search the stack for the most recent instance of proc. If found, see if it has a parameter or local variable named var, as before.
proc.depth.var Use the instance of proc that is at depth depth (exactly), instead of the most recent instance. This is very useful for debugging recursive procedures where there are multiple instances on the stack.
:var Search for a global (not local) variable named either var or _var, in that order.
. Dot is shorthand for the last thing you viewed. It has the same size it did when you last viewed it. For example, if you look at a long as a char, then "." is considered to be one byte long. This is useful for treating things in unconventional ways, like changing the second highest byte of a long without changing the rest of the long. Dot can be treated like any other variable.
NOTE: "." is the name of this magic location. If you use it, it is dereferenced like any other name. If you want the address of something that is, say, 30 bytes farther on in memory, do not say ".+30". That would take the contents of dot and add 30 to it. Instead, say "&.+30", which adds 30 to the address of dot.
Special variables are names for things that are not normally directly accessible. Special variables include:
$var The debugger has room in its own address space for a number of user-created special variables. They are all of type long, and they do not take on the type of any expression to which they are assigned. Names are defined when they are first seen. For example, saying "$xyz = 3∗4" creates special symbol "$xyz", and assigns to it the value 12. Special variables can be used just like any other variables.
$pc, $fp, $sp, $d0, etc.
These are the names of the program counter, the frame pointer, the stack pointer, the registers, etc. To find out which names are available on your system, use the "l r" (list registers) command. All registers act as type integer.
$result This is used to reference the return value from the last command-line procedure call. Where possible, it takes on the type of the procedure. $short and $long are available as alternate ways of looking at $result.
$signal This lets you see and modify the current child process signal number.
$lang This lets you see and modify the current language (0 for C, 1 for FORTRAN, or 2 for Pascal).
$line This lets you see and modify the current source line number, which is also settable with a number of different commands.
$malloc This lets you see the current amount of memory (bytes) allocated at run-time for use by the debugger itself.
$cBad This lets you see and modify the number of machine instructions the debugger will step while in a non-debuggable procedure before setting an up-level breakpoint and free-running to it. Setting it to a small value can improve debugger performance, at the risk of taking off free-running after missing the up-level break for some reason.
$pagelines This lets you set the number of lines per "page" of debugger output. The prompt "Hit RETURN for more..." occurs between pages. Values of zero or less turn off paging.
$fpa If this is set to a non-zero value, any sequence of machine instructions which effectively constitute a single floating point accelerator instruction will be treated as a single instruction for machine level single-stepping and display.
$fpa_reg If $fpa is set to a non-zero value, $fpa_reg indicates which address register is used in floating point accelerator instruction sequences. A 0 corresponds to register a0, 1 to a1, etc. The default value is 2.
To see all the special variables, including the predefined ones, use the "l s" (list specials) command.
You can also look up code addresses with
proc#line
which searches for the given procedure name and line number (which must be an executable line within proc) and uses the code address of that line. Just referring to a procedure proc by name uses the code address of the entry point to that procedure.
Expression Conventions
Every expression has a value, even simple assignment statements, as in C. "Naked" expression values (those which aren’t command modifiers) are always printed unless the next token is ";" (command separator) or "}" (command block terminator). Thus breakpoint and assertion commands are normally silent. To force an expression result to be printed, follow the expression with "/n" (print in normal format).
Integer constants might begin with "0" for octal or "0x" or "0X" for hexadecimal (the forms are equivalent). They are int (which might be the same as long) if they fit in two bytes, long otherwise. If followed immediately by "l" or "L", they are forced to be of type long (this is useful on systems where int is two bytes).
Floating point constants must be of the form digits.digits[e|E|d|D[+|-]digits], for example, "1.0", "3.14e8", or "26.62D-31". One or more leading digits is required to avoid confusion with "." (dot). A decimal point and one or more following digits is required to avoid confusion for some command formats. If the exponent doesn’t exactly fit the pattern shown, it is not taken as part of the number, but as separate token(s). The "d" and "D" exponent forms are allowed for compatibility with FORTRAN. However, all floating point constants are taken as doubles, regardless.
Character constants must be entered in ” and are treated as integers. String constants must be entered in "" and are treated like "char *" (i.e. pointer to char). Character and string constants can contain the standard backslashed escapes understood by the C compiler and the echo(1) command, including "\b", "\f", "\n", "\r", "\t", "\\", "\′", and "\nnn". However, "\<newline>" is not supported, neither in quotes nor at the end of a command line.
Expressions are composed of any combination of variables, constants, and C operators. If the debugger is invoked as cdb, the C operator "sizeof" is also available. If the debugger is invoked as fdb, FORTRAN operators are also available and FORTRAN meanings take precedence where there is a conflict. The same is true for Pascal if the debugger is invoked as pdb.
If there is no active child process and no corefile, you can only evaluate expressions containing constants.
Expressions approximately follow the C rules of promotion, e.g. char, short, and int become long, and float becomes double. If either operand is a double, floating math is used. If either operand is unsigned, unsigned math is used. Otherwise, normal (integer) math is used. Results are then cast to proper destination types for assignments.
If a floating point number is used with an operator that doesn’t normally permit it, the number is cast to long and used that way. For example, the C binary operator "~" (bit invert) applied to the constant "3.14159" is the same as "~3".
Note that "=" means "assign" except for Pascal; use "==" or ".EQ." for FORTRAN. In Pascal, "=" is a comparison operator; use ":=" for assignments. For example, if you invoke the debugger as cdb, then set "$lang = 2" (Pascal), you must say "$lang := 0" to return to C.
Use "//" for division, instead of "/", to distinguish from display formatting (see Data Viewing Commands).
The special unary operator "$in" (not to be confused with debugger local variables) evaluates to 1 (true) if the operand is an address inside a debuggable procedure and $pc (the current child process program location) is also in that procedure, else it is 0 (false). For example, "$in main" is true if the child process is stopped in main().
If the first expression on a line begins with "+" or "−", use "()" around it to distinguish from the "+" and "−" commands (see Data Viewing Commands). Parentheses might also be needed to distinguish an expression from a command it modifies.
You can attempt to dereference any constant, variable, or expression result using the C "∗" operator. If the address is invalid, an error is given.
Whenever an array variable is referenced without giving all its subscripts, the result is the address of the lowest element referenced. For example, consider an array declared as "x[5][6][7]" in C, "x(5,6,7)" in FORTRAN, or "x[1..5,2..6,3..7]" in Pascal. Referencing it simply as "x" is the same as just "x" in C, the address of "x(1,1,1)" in FORTRAN, or the address of "x[1,2,3]" in Pascal. Referencing it as "x[4]" is the same as "& (x[4][0][0])" in C, the address of "x(1,1,4)" in FORTRAN, or the address of "x[4,2,3]" in Pascal.
If a not-fully-qualified array reference appears on the left side of an assignment, the value of the right-hand expression is stored into the element at the address specified.
Array indices are not checked against declared bounds.
String constants are stored in a magic buffer in the file /usr/lib/end.o, which you link with your program. The debugger starts storing strings at the beginning of this buffer, and moves along as more assignments are made. If the debugger reaches the end of the buffer, it goes back and reuses it from the beginning. In general this doesn’t cause any problems. However, if you use very long strings, or if you assign a string constant to a global pointer, problems could arise. To fix them, you can edit and compile a personal copy of /usr/lib/end.c to increase the size of the buffer. (Some systems don’t support this; see the DEPENDENCIES section below.)
Procedure Call Conventions
Procedures can be invoked from the command line, even within expressions. For example:
xyz = $abc ∗ (3 + def (ghi − 1, jkl, "Hi Mom"))
calls procedure "def" when its value is needed in the expression.
Any breakpoints encountered during command line procedure invocation are handled as usual. However, the debugger has only one active command line at a time. If it stops in a called procedure for any reason, the remainder (if any) of the old command line is tossed, with notice given.
If you attempt to call a procedure when there is no active child process, one is started for you as if you gave a single-step command first. Unfortunately, this means that the data in corefile (if any) might disappear or be reinitialized.
If you send signal SIGINT (e.g., hit the BREAK key) while in a called procedure, the debugger aborts the procedure call and returns to the previous stopping point (the start of the main program for a new process).
You can call any procedure that is in your objectfile, even if it is not debuggable (was not compiled with debug on). For example, assume that you reference "printf()" in your program, so the code for it is in your objectfile. Then you can enter on the command line:
printf ("This works! %d %c\n", 9, ′?′);
If you wonder what procedures are available, do a list labels command ("l l"). If you want to have some library routines available for debugging, but they aren’t referenced anywhere in your code (so they aren’t linked), you can modify a personal copy of /usr/lib/end.c to reference them. (Some systems don’t support this; see the DEPENDENCIES section below.) It is not necessary to have correct calls. For example, just "printf()" works fine, since you never execute the statements in end.c.
Note that procedure name "_end_" is declared in end.c.
COMMANDS
The debugger has various commands for viewing and manipulating the program being debugged. The command line editing and history features from ksh(1) are available during command input. The CDBEDIT, EDITOR, or VISUAL environment variables are checked (in that order) to determine which of the three available editing modes (vi, emacs, or gmacs) is used. The command history file is specified by the CDBHIST environment variable and its size is derived from HISTSIZE. If any of these environment variables is not set, its default is the same as with ksh(1) except that CDBHIST defaults to "$HOME/.cdbhist".
Window Mode Commands
These commands control what is displayed in the source window. The source window has three different modes. In source mode, the window is filled with source lines from the user program. In disassembly mode, the top five lines of the source window display one of three sets of registers (see the gr and fr commands), and the remainder of the window contains assembly language instructions. In split-screen mode, the top half of the window is source code, and the bottom half is the corresponding assembly instructions.
td Toggle disassembly mode. When in disassembly mode, the source window displays a set of registers (see gr and fr) and the code in assembly language. The assembly language display consists of the source line number, the address in hex, the address in the form of nearest label plus offset, and the assembly instruction.
ts Toggle split screen mode. When in split-screen mode, half the source window displays source code and half assembly instructions.
gr Display general registers when the debugger is in assembly (non-split screen) mode. When the value of a register changes, the register is highlighted until after the next command is executed. These registers can be modified by using the debugger special variables $d0 through $a7. When displaying the general registers or floating point registers, the line dividing the registers from the assembly code displays corresponding special registers. For registers containing flags, each flag is represented by a letter. A lowercase letter indicates that the flag is off, while uppercase means on.
fr Display floating point registers when the debugger is in assembly (non-split screen) mode. When the value of a register changes, that register is highlighted until after the next command. If more than one set of floating-point registers exist, you will be queried about which you want displayed.
+r Scroll the floating-point register display forward four lines.
-r Scroll the floating-point register display back four lines.
ws size Set the size of the source viewing window. It is normally set to fifteen lines for a twenty-four line terminal.
u Update the screen to reflect the current location. This command is best used as part of an assertion: the assertion a u will show step-by-step progress through the program.
U Clear and redraw the screen.
File Viewing Commands
These commands might change the current viewing position, but they do not affect the next statement to be executed in the child process, if any.
dir directory Add directory to the list of alternate source directories. Same as using -d invocation option. Main procedure file must reside in the current directory or be specified with the -d option.
e Show the current file, procedure, line number, and source line.
e (file | proc) Enter (view) file or proc and print its first executable line. File can be any file, but must not be object code.
[depth] E Like "e", but sets viewing location to the current location in proc on the stack at depth (not necessarily the first executable line in the procedure). Default depth is zero (where program is currently stopped).
L This is a synonym for 0E.
line Print source line number line in the current file.
[line] p [count] Print one (or count) lines starting at current line (or line number line). If multiple lines are printed, current line is marked with "=" in leftmost column.
+[lines] Move to lines (default one) lines after current line.
−[lines] Move to lines (default one) lines before current line.
[line] w [size] Print window of text containing size (default 11) lines centered around current line (or line). Target line is marked with "=" in leftmost column if multiple lines printed.
[line] W [size] Same as "w", but size defaults to 21 lines.
+w [size]
+W [size] Print window of text of given or default size, beginning at end of previous window if the previous command was a window command; otherwise at current line.
−w [size]
−W [size] Print window of text of given or default size, ending at beginning of previous window if previous command was a window command; otherwise at current line.
/[string] Search forward through the current file for string, starting at the line after the current line.
?[string] Search backward for string, starting with the line before the current line.
Searches wrap around the end or beginning of the file, respectively. If string is not specified, the previous one is used. Wild cards and regular expressions are not supported; string must be literal.
n Repeat previous "/" or "?" command using same string as before.
N The same as "n", but search goes in opposite direction from that specified by previous "/" or "?" command.
Display Formats
A format is of the form "[∗][count]formchar[size]". Display formats apply only to Data Viewing Commands, described in the next sub−section.
"∗" means "use alternate address map" (if maps are supported).
Count is the number of times to apply the format style formchar (must be a number).
Size is the number of bytes to be formatted for each count (overrides the default size for the format style); must be positive decimal number (except short hand notations). Size is disallowed with formchars where it makes no sense.
For example, "abc/4x2" prints, starting at the location of "abc", four two-byte numbers in hexadecimal.
The formats which print numbers allow an uppercase character to be used instead, for the same results as appending "l" (see below). For example, "O" prints in long octal. These formats, which are useful on systems where integer is shorter than long, are noted below. The following formats are available:
n Print in the "normal" format, based on the type. Arrays of char and pointers to char are interpreted as strings, and structures are fully dumped.
(d | D) Print in decimal (as integer or long).
(u | U) Print in unsigned decimal (as integer or long).
(o | O) Print in octal (as integer or long).
(x | X) Print in hexadecimal (as integer or long).
(b | B) Print a byte in decimal (either way).
(c | C) Print a character (either way).
(e | E) Print in "e" floating point notation (as float or double) (see printf(3S)). Remember that floating point constants are always doubles!
(f | F) Print in "f" floating point notation (as float or double).
(g | G) Print in "g" floating point notation (as float or double).
i Print a machine instruction.
a Print a string using expr as the address of the first byte.
s Print a string using expr as the address of a pointer to the first byte (same as "∗expr/a", except for arrays).
t Show the type of expr (usually a variable or procedure name). For true procedure types you must actually call the procedure, e.g. "def(arg)/t".
p Print the name of the procedure containing address expr.
S Do a formatted dump of a structure. expr must be the address of a structure, not the address of a pointer to a structure.
There are some short hand notations for size:
b 1 byte (char).
s 2 bytes (short).
l 4 bytes (long).
These can be appended to formchar instead of a numeric size. For example, "abc/xb" prints one byte in hexadecimal.
If you view an object with a size (explicitly or implicitly) less than or equal to the size of a long, the debugger changes the basetype to something appropriate for that size. This is so "." (dot) works correctly for assignments. For example, "abc/c2" sets the type of "." to short. One side effect is that if you look at a double using a float format, dot loses accuracy or has the wrong value.
Data Viewing Commands
expr If expr does not resemble anything else (such as a command), it is handled as "expr/n" (print expression in normal format), unless followed by ";" or "}", in which case nothing is printed.
expr/format Print the contents (value) of expr using format.
expr?format Print the address of expr using format.
^[[/]format] Back up to the preceding memory location (based on the size of the last thing displayed). Use format if supplied, or the previous format if not. No "/" is needed after the "^". To reverse direction again (e.g. start going forward), enter "." (dot) (always an alias for the current location) followed by carriage return.
l [proc[.depth]] List all parameters and local variables for current procedure (or proc, if given, at the specified depth, if any). Data display uses "/n" format, except arrays and pointers are shown as addresses; only the first word of a structure is shown.
l (a | b | d | z) List all assertions, breakpoints, directories (where to search for files), or zignals (signal actions).
l (f | g | l | m | p | r | s) [string]
List all files (source files which built objectfile), global variables, labels (program entry points known to the linker), macros, procedure names, registers, or special variables (except registers). If string is present, only those things with the same initial characters are listed.
Stack Viewing Commands
[depth] t Trace the stack for the first depth (default 20) levels.
[depth] T The same as "t", but local variables are also displayed using "/n" format (except that arrays and pointers are shown as addresses; structures show first word only).
Job Control Commands
The parent (debugger) and child (objectfile) processes take turns running. The debugger is only active while the child process is stopped due to a signal (includes hitting a breakpoint) or terminated for whatever reason.
r [arguments] Run a new child process with given argument list, if any (an existing child process is terminated first). If no arguments are given, those used with the last "r" command are used again (none if "R" was used last).
Arguments can contain "<" and ">" for redirecting standard input and standard output. ("<" does an open(2) of file descriptor 0 for read-only; ">" does a creat(2) of file descriptor 1 with mode 0666; ">>" is not supported.) Arguments can contain shell variables, quote marks, or other special syntax (expanded by Bourne shell). "{}" are shell metacharacters, so "r" cannot be safely saved in a breakpoint or assertion command list.
R Run a new child process with no argument list.
k Terminate (kill) the current child process, if any.
[count] c [line] Continue after a breakpoint or a signal, ignoring the signal, if any. If count is given, the current breakpoint, if any, has its count set to that value. If line is given, a temporary breakpoint is set at that line number, with a count of −1 (see Breakpoint Commands).
[count] C [line] Continue like "c", but allow the signal (if any) to be received.
[count] s Single step 1 (or count) statements (successive carriage-returns repeat with a count of 1). If count is less than one, the child process is not stepped. The child process continues with the current signal, if any (set "$signal = 0" to prevent).
[count] S Single step like "s", but treat procedure calls as single statements (don’t follow them down). If a breakpoint is hit in such a procedure, or in one that it calls, its commands are executed. (This is usually acceptable unless there is a "c" command in that breakpoint’s command list.)
[count] j Single step 1 (or count) machine instructions. Successive carriage-returns repeat with a count of 1. If count is less than one, the child process is not stepped. The child process continues with the current signal, if any. (Set "$signal = 0" to prevent the signal.)
[count] J Single step like "j", but treat procedure calls as single instructions (Don’t follow them down.) If a breakpoint is hit in such a procedure, or in one that it calls, its commands are executed. (This is usually all right unless there is a "c" command in that breakpoint’s command list.)
The debugger has no knowledge of or control over child processes forked in turn by the process being debugged. Programs being debugged should not execute a different program via exec(2).
Child process output might be buffered, so it might not appear immediately after you step through an output statement such as printf(3S). It might not appear at all if you kill the process.
Breakpoint Commands
A breakpoint has three attributes associated with it:
address All the commands which set a breakpoint are simply alternate ways to specify the breakpoint address. The breakpoint is encountered whenever address is about to be executed, regardless of the path taken to get there. Only one breakpoint at a time (of any type or count) can be set at a given address. Setting a new breakpoint at address replaces the old one, if any.
count The number of times the breakpoint is encountered prior to recognition. If count is positive, the breakpoint is "permanent", and count decrements with each encounter. Each time count goes to zero, the breakpoint is recognized and count is reset to one (so it stays there until explicitly set to a different value by "c" or "C").
If count is negative, the breakpoint is "temporary", and count increments with each encounter. Once count goes to zero, the breakpoint is recognized, then deleted.
commands Actions to be taken upon recognition of a breakpoint before waiting for command input. These are separated by ";" and can be enclosed in "{}" to delimit the list saved with the breakpoint from other commands on the same line.
Results of expressions followed by ";" or "}" are not printed unless you specify a print format.
Saved commands are not parsed until the breakpoint is recognized. If there are no commands, the debugger will wait for command input when the breakpoint is recognized. For immediate continuation, finish the command list with "c".
Breakpoint commands:
l b
B Both forms list all breakpoints in the format:
num: count: nnn proc: ln: contents
{commands}
The leftmost number num is an index number for use with the "d" (delete) command.
[line] b [commands]
Set a permanent breakpoint at the current line (or at line in the current procedure).
[expr] d Delete breakpoint number expr. If expr is absent, delete the breakpoint at the current line, if any. If there is none, the debugger executes a "B" command instead.
bp [commands] Set permanent breakpoints at the beginning (first executable line) of every debuggable procedure. When any procedure breakpoint is hit, commands are executed.
D [b] Delete all breakpoints (including "procedure" breakpoints). The "b" is optional.
D p Delete all "procedure" breakpoints. All breakpoints set by commands other than "bp" remain set.
For the following commands, if the second character is uppercase, for example, "bU" instead of "bu", the breakpoint is temporary (count is −1), not permanent (count is 1).
[depth] bb [commands]
[depth] bB [commands]
Set a breakpoint at the beginning (first executable line) of the procedure at the specified stack depth. If depth is not specified, use the current procedure (might not be the same as the one at depth zero).
[depth] bx [commands]
[depth] bX [commands]
Set a breakpoint at the exit (last executable line) of the procedure at the given stack depth. If depth is not specified, use the current procedure (might not be the same as the one at depth zero). The breakpoint is set such that all returns of any kind go through it.
[depth] bu [commands]
[depth] bU [commands]
Set an up-level breakpoint. The breakpoint is set immediately after the return to the procedure at the specified stack depth (default one, not zero). Zero depth means "current location".
[depth] bt [proc] [commands]
[depth] bT [proc] [commands]
Trace current procedure (or procedure at depth, or proc). Set breakpoints at entrance and exit of a procedure. Default entry breakpoint commands are "Q;2t;c" (show top two procedures on stack and continue). The exit breakpoint always executes "Q;L;c" (print current location and continue).
If depth is given, proc must be absent or it is taken as part of commands. If depth is missing but proc is specified, the named procedure is traced. If both depth and proc are omitted, the current procedure is traced, which might not be the same as the one at depth zero.
If commands are present, they are used for the entrance breakpoint, instead of the default shown above.
address ba [commands]
address bA [commands]
Set a breakpoint at the given code address. address can be the name of a procedure or an expression containing such a name. If the child process is stopped in a non-debuggable procedure, or in prologue code (before the first executable line of a procedure), results might seem a little strange.
The next few commands are not strictly part of the breakpoint group, but are used almost exclusively as arguments to breakpoints (or assertions).
if [expr] {commands}[{commands}]
If expr evaluates to a non-zero value, the first group of commands (the first "{}" block) is executed, otherwise it (and the following "{", if any) is skipped. All other "{}" blocks are always ignored (skipped), except when given as an argument to an "a", "b", or "!" command. The "if" command is nestable, and can be abbreviated to "i".
Q If the "quiet" command appears as the first command in a breakpoint’s command list, the normal announcement of "proc: line: text" is not made. This allows quiet checks of variables, etc. to be made without cluttering up the screen with unwanted output. The "Q" command is ignored if it appears anywhere else.
"any string you like"
Print the given string. String can contain standard backslashed character escapes, including "\n" for newline. Useful for labelling output from breakpoint commands.
Assertion Control Commands
Assertions are command lists that are executed before every statement. Thus, if there is even one active assertion, the program is single stepped at the machine instruction level (runs very slowly). They are primarily used for tracking down nasty bugs (such as the corruption of a global variable).
Assertions can be activated or suspended individually, plus there is an overall mode.
a commands Create new assertion with given command list. List is not parsed until execution time. Command list can be enclosed in "{}" to delimit it from other commands on the same line. The "l a" command lists all current assertions and the overall mode.
expr a (a | d | s)
Modify the assertion numbered expr: activate it, delete it, or suspend it. Suspended assertions continue to exist, but do nothing until reactivated.
A Toggle the overall state of the assertions mechanism between active and suspended.
D a Delete all assertions.
[flag] x Force exit from assertions mode. If flag is absent or evaluates to zero, exit immediately. Otherwise, finish executing the current assertion first. If an assertion executes an "x" command, the child process stops and the assertion doing the "x" is identified.
The debugger has only one active command line at a time. The current command line is discarded when assertion execution begins.
Commands "r", "R", "c", "C", "s", "S", and "k" are not allowed while assertions are running. They must appear after the "x", if at all.
Signal Control Commands
The debugger catches all signals bound for a child process before the child process sees them (a function of the ptrace(2) mechanism).
[signal] z [i][r][s][Q]
Maintains the "zignal" (signal) handling table. Signal is a valid signal number (default is the current signal). The options (which must be all one word) toggle the state of the appropriate flag: ignore, report, or stop. If "Q" is present, the new signal state is not printed.
"l z" lists the current handling of all signals. "z" (with no options) shows the state of the current or selected signal.
For example, assuming a start up state of (don’t ignore, don’t report, don’t stop), the command "14z sr" sets the alarm clock signal to stop (but still don’t ignore) and report that it occurred. Doing "14z sr" again toggles the flags back to the original state.
When the child process stops or terminates on a signal it is always reported, except for the breakpoint signal when the breakpoint commands start with "Q".
When the debugger ignores a signal, the "c" command does not know about it. A signal is never ignored when the child process terminates, only when it stops.
Record and Playback Commands
The debugger supports a record/playback feature to help recreate program states and to record all debugger output.
Commands are:
>file Set or change recordfile to file and turn recording on. This rewrites file from the start. Only commands are recorded to this file.
>>file Same as >>file but appends to file instead of overwriting.
>@file
>>@file Set or change record-all file to file, for overwriting or appending. The record-all file can be opened or closed independent of the recordfile. All debugger standard output is copied to the record-all file, including prompts, commands entered, and command output (does not capture child process output).
>(t | f | c) Turn recording on ("t") or off ("f"), or close the recording file ("c"). When recording is resumed, new commands are appended to previous file contents. In this context, ">>" is equivalent to ">".
>@(t | f | c) Turn record-all on, off, or close the record-all file. In this context, ">>@" is equivalent to ">@".
> Tell the current recording status (same as ">>").
>@ Tell the current record-all status (same as ">>@").
<file Start playback from file.
<<file Start playback from file, using the single-step feature of playback.
Only command lines read from the keyboard or a playback file are recorded in the recordfile.
Command lines beginning with ">", "<", or "!" are not copied to the current recordfile (they are copied to the record-all file). To override this, begin such lines with blanks.
NOTE: The debugger can be invoked with standard input, standard output, and/or standard error redirected, independent of record and playback. If the debugger encounters an end-of-file while standard input is redirected from anything other than a terminal, it prints a message to standard output and exits, returning zero.
Macro Definition Commands
def name [replacement-text]
Define name as the macro whose value is replacement-text. Name can be any string of letters or digits. Replacement-text can be any string of letters, digits, blanks, tabs, or other printing characters; however, it cannot be continued onto a new line.
undef name Remove the macro definition from name, causing name to cease existing as a replacement string macro. As a special case "*" can be entered for name to undefine all macros.
tm Toggle the macro substitution mechanism between active and suspended states. When macro substitution is suspended, the currently defined macros continue to exist, but they are not replaced in the command line by their definitions. Additional macros can be defined while macro substitution is suspended.
Miscellaneous Commands
<carriage-return>
~ An empty line or a "~" command causes the debugger to repeat the last command, if possible, with an appropriate increment, if any. Repeatable commands are those which print a line, print a window of lines, print a data value, single step, and single step over procedures. <carriage-return> is saved in a record file as a "~" command, to distinguish from ^D.
^D Control-D is like <carriage-return>, but repeats the previous command ten times. This command is saved in a record file as an empty line.
! [command-line]
This shell escape invokes a shell program. If command-line is present, it is executed via system(3S). Otherwise, the environment variable SHELL gives the name of the shell program to invoke with a −i option, also using system(3S). If SHELL is not found, the debugger executes "/bin/sh −i". In any case, the debugger then waits for the shell or command-line to complete.
As with breakpoints, command-line can be enclosed in "{}" to delimit it from other (debugger) commands on the same line. For example,
14b {!{date};c}; t; l a
sets a breakpoint at line 14 that calls date(1), then continues; then (after setting the breakpoint), the debugger does a stack trace, then lists assertions.
f ["printf-style-format"]
Set address printing format, using printf(3S) format specifications (not debugger format styles). Only the first 19 characters are used. If there is no argument, the format is set to a system-dependent default. All addresses are assumed to be of type long, so you should handle all four bytes to get something meaningful.
F Find and fix bug (a useless but humorous command).
g line Go to an address in the procedure on the stack at depth zero (not necessarily the current procedure). Changes the program counter so line is the next line to be executed.
h
help Print the debugger help file (command summary) using more(1).
I Print information (inquire) about the state of the debugger.
M Print the current text (objectfile) and core (corefile) address maps.
M (t | c) [expr; [expr;...]]
Set the text (objectfile) or core (corefile) address map. The first zero to six map values are set to the exprs given.
q Quit the debugger. Requests confirmation.
Z Toggle case sensitivity in searches. This affects everything: File names, procedure names, variables, and string searches! The debugger starts out as not case sensitive.
DIAGNOSTICS
Most errors cause a reasonably accurate message to be given. Normal debugger exits return zero and error exits return one. All debugger output goes to standard output except error messages given just before non-zero exits, which go to standard error.
Debugger errors are preceded by "panic: ", while user errors are not. If any error occurs during initialization, the debugger then prints "cannot continue" and quits. If any error happens after initialization, the debugger attempts to reset itself to an idle state, waiting for command input. If any error occurs while executing a procedure call from the command line, the context is reset to that of the normal program.
Child process (program) errors result in signals which are communicated to the debugger via the ptrace(2) mechanism. If a program error occurs while executing a procedure call from the command line, it is handled like any other error (i.e. you can investigate the called procedure). To recover from this, or to abort a procedure call from the command line, type DEL, BREAK, ^C, or whatever your interrupt character is.
For more information, see the text file /usr/lib/cdb.errors.
WARNINGS
Code that is not debuggable or does not have a corresponding source file is dealt with in a half-hearted manner. The debugger shows "unknown" for unknown file and procedure names, cannot show code locations or interpret parameter lists, etc. However, the linker symbol table provides procedure names for most procedures, even if not debuggable. The main procedure (main program) must be debuggable and have a corresponding source file.
If the address given to a "ba" command is a not a code address in the child process, strange results or errors might ensue.
If you set the address printing format to something printf(3S) doesn’t like, you might get an error (usually memory fault) each time you try to print an address, until you fix the format with another "f" command.
Do not use the "z" command to manipulate the SIGTRAP signal. If you change its state you had better know what you are doing or be a very good sport!
If you single step or run with assertions through a call to longjmp(3C), the child process will probably take off free-running as the debugger sets but never hits an up-level breakpoint.
Do not modify any file while the debugger has it open. If you do, the debugger gets confused and might display garbage.
Although the debugger tries to do things reasonably, it is possible to confuse the recording mechanism. Be careful about trying to playback from a file currently open for recording, or vice versa; strange things can happen.
Many compilers only issue source line symbols at the end of each logical statement or physical line, whichever is greater. This means that, if you are in the habit of saying "a = 0; b = 1;" on one line, there is no way to put a breakpoint after the assignment to "a" but before the assignment to "b".
Some statements do not emit code where you would expect it. For example, assume:
99:for (i = 0; i < 9; i++) {
100:xyz (i);
101:}
A breakpoint placed on line 99 will be hit only once in some cases. The code for incrementing is placed at line 101. Each compiler is a little different; you must get used to what your particular compiler does. A good way of finding out is to use single stepping to see in what order the source lines are executed.
The output of some program generators, such as yacc(1), have compiler line number directives in them that can confuse the debugger. It expects source line entries in the symbol table to appear in sorted order. Removal of line directives fixes the problem, but makes it more difficult to find error locations in the original source file. The following script, run after yacc(1) and before cc(1), comments out line number changes in C programs:
sed "/# ∗line/s/^.∗$/\/∗&∗\//" y.tab.c >temp.c
yacc(1) will leave out line directives if invoked with the −l option. In general, line number directives (or compiler options) are only safe so long as they never set the number backwards.
The C operators "++", "−−", and "?:" are not available. The debugger always understands all the other C operators, except "sizeof", if the default language is FORTRAN or Pascal.
For FORTRAN, only the additional operators ".NE.", ".EQ.", ".LT.", ".LE.", ".GT.", and ".GE." are supported.
For Pascal, only the operators ":=", "<>", "^", "^." (as in "x^.y"), "and", "or", "not", "div", "mod", "addr", and "sizeof" are added.
There is no support for FORTRAN complex variables, except as a series of two separate floats or doubles.
The debugger doesn’t understand C type casts.
The C operators "&&" and "||" aren’t short circuit evaluated as in the compiler. All parts of expressions involving them are evaluated, with any side-effects, even if it’s not necessary.
The debugger doesn’t understand C pointer arithmetic. "∗(a+n)" is not the same as "a[n]" unless "a" has an element size of 1.
There is no support for C local variables declared in nested blocks, nor for any local overriding a parameter with the same name. When looking up a local by name, parameters come first, then locals in the order of the "}"s of the blocks in which they are declared. When listing all locals, they are shown in the same order. When there is a name overlap, the address or data shown is that of the first variable with that name.
CDB does not support identically-named procedures (legal in Pascal if the procedures are in different scopes). CDB will always use the first procedure with the given name.
There is no support for Pascal packed arrays where the element size is not a whole number of bytes. Any reference into such an array might produce garbage or a bad access.
Pascal WITH statements are not understood. To access any variable you must specify the complete "path" to it.
The debugger supports call-by-reference only for known parameters of known (debuggable) procedures. If the object to pass lives in the child process, you can fake such a call by passing "& object", i.e. the address of the object.
Array parameters are always passed to command-line procedure calls by address. This is correct except for Pascal call-by-value parameters. Structure parameters are passed by address or value, as appropriate, but only a maximum of eight bytes is passed, which can totally confuse the called procedure. Functions which return complex numbers are not called correctly; insufficient stack space is allocated for the return area, which can lead to overwriting the parameter values.
Assignments into objects greater than four bytes in size, from debugger special variables, result in errors or invalid results.
Command lines longer than 1024 bytes are broken into pieces of that size. This might be relevant if you run the debugger with playback or with input redirected from a file.
DEPENDENCIES
The "bx" (break on exit) command requires that compilers support it by funneling all exits through one point. The breakpoint is always set at the last line of the procedure, which should be, but might not be, the sole exit point.
Series 300
When a C parameter is declared as an array of anything, the highest type qualifier (array) shows up as a pointer instead. For example, "int x[]" looks like "int *x", and "char (*x)[]" looks like "char **x", but "char *x[]" is treated correctly as "pointer to array of char".
There is limited support for command-line calls of functions which return structures. The debugger interprets the start of heap as a structure of the return type. However, a call such as "abc()/t" displays the return type correctly.
$short and $long are available in addition to $result. If command-line procedure call returns a double, $result is set to the value cast to long.
The source file end.c is not supported, so you can’t customize /usr/lib/end.o. The buffer size is fixed at 200 bytes. To force linking of library routines not otherwise referenced, use the −u option to ld(1).
Procedures in FORTRAN and Pascal can have alias names in addition to normal names. Aliases are shown by the "l p" (list procedures) command. They can be used in place of the normal name, as desired.
The procedure name "_MAIN_" is used as the alias name for the main program (main procedure) in all supported languages. Do not use it for any debuggable procedures.
FORTRAN ENTRY points are flagged "ENTRY" by the "l p" command.
When a compiler does not know array dimensions, such as for some C and FORTRAN array parameters, it uses 0:MAXINT or 1:MAXINT, as appropriate. The "/t" format shows such cases with "[]" (no bounds specified), and subscripts from 0 (or 1) to MAXINT are allowed in expressions.
There is no support for: C structure, union, and enumeration tags, C typedefs, and Pascal types.
Some variables are indirect, so a child process must exist in order for the debugger to know their addresses. When there is no child process, the address of any such variable is shown as 0xfffffffe.
The optional pattern given with the "l g" (list globals) command must be an exact match, not just a leading pattern.
Symbol names in the Value Table are never preceded by underscores, so the debugger never bothers to search for names of that form. The only time a prefixed underscore is expected is when searching the Linker Symbol Table for names of non-debuggable procedures.
Series 300 supports two types of string formats in addition to null-terminated C strings. FORTRAN character variables consist of a string of bytes (no null terminator). Pascal string variables consist of a length byte, followed by the string characters. The "\s" and "\a" formats will display these types correctly, only if the current language is FORTRAN or Pascal.
AUTHOR
Cdb was developed by Third Eye Software.
FILES
| a.out | Default objectfile to debug. |
| core | Default corefile to debug. |
| /usr/lib/cdb.help | Text file listed by the "help" command. |
| /usr/lib/cdb.errors | Text file which explains debugger |
| error and warning messages. | |
| /usr/lib/end.o | Object file to link with all debuggable |
| programs. |
SEE ALSO
cc(1), echo(1), fc(1), pc(1), ld(1), more(1), creat(2), exec(2), fork(2), open(2), setjmp(3C), printf(3S), system(3S), a.out(4).
On some systems any of the following might exist: adb(1), ptrace(2), core(4), ksh(1).
C Debugger (cdb), tutorial in HP-UX Concepts and Tutorials: Programming Environment.
INTERNATIONAL SUPPORT
cdb: 8-bit file names, messages.
Hewlett-Packard Company — May 11, 2021