This tutorial introduces you to the basic features of the HP WDB debugger, an HP-supported implementation of the GDB debugger.
The tutorial assumes that you are using the default line-mode user interface.
HP WDB (and therefore this tutorial) runs on any PA-RISC 1.x or PA-RISC 2.0 system running HP-UX Release 10.20, 10.30, or 11.00.
For more information about HP WDB and GDB, see the following:
This tutorial uses as an example the program average.c
. This program finds the average of an array of integers.
After you copy this program to a file, compile it for debugging by using the -g
option:
$ cc -Ae -g average.c
Now run the program:
$ a.out 4 3
The results should actually be 3 and 2, not 4 and 3.
To make command history understand your vi key bindings you need to create a `~/.inputrc' file with the following contents:
set editing-mode vi
The readline interface uses the `.inputrc' file to control the settings.
To begin debugging the program, enter the gdb
command in your shell. The debugger displays a banner and a command prompt after it starts.
$ gdb a.out Wildebeest is free software and you are welcome to distribute copies of it under certain conditions; type "show copying" to see the conditions. There is absolutely no warranty for Wildebeest; type "show warranty" for details. Hewlett-Packard Wildebeest 2.0 (based on GDB 4.17) (built for PA-RISC 1.1 or 2.0, HP-UX 10.20) Copyright 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. (gdb)
This command runs HP WDB with the default line-mode interface.
The directory where the gdb
executable resides must be in your PATH variable. (The standard installation procedure places it in /opt/langtools/bin.)
Some more advanced topics are:
Note: If at any time after starting the debugger you need to stop the tutorial, enter the
quit
command (q
).
Unlike some debuggers, HP WDB does not automatically set breakpoints at the beginning or end of your program. Before you can start debugging, you need to do the following:
break
command, abbreviated b
:
(gdb) b main Breakpoint 1 at 0x23e4: file average.c, line 32.
run
command, abbreviated r
:
(gdb) r Starting program: /home/smith/a.out Breakpoint 1, main () at average.c:32 32 print_average (my_list, first, last);
Note: You can abbreviate any command to its shortest unambiguous form.
For information about any command, use the help
command (h
). Using help
with no arguments gives you a list of topics for which help is available.
(gdb) help List of classes of commands: running -- Running the program stack -- Examining the stack data -- Examining data breakpoints -- Making program stop at certain points . . . Type "help" followed by a class name for a list of commands in that class. Type "help" followed by command name for full documentation. Command name abbreviations are allowed if unambiguous. (gdb) h b Set breakpoint at specified line or function. Argument may be line number, function name, or "*" and an address. If line number is specified, break at start of code for that line. If function is specified, break at start of code for that function. If an address is specified, break at that exact address. With no arg, uses current execution address of selected stack frame. This is useful for breaking on return to a stack frame. Multiple breakpoints at one place are permitted, and useful if conditional. Do "help breakpoints" for info on other commands dealing with breakpoints.
Use the list
command (l
) to look at the source in the immediate vicinity of the current line:
(gdb) l 27 } 28 29 int main(void) 30 { 31 /* Try two test cases. */ 32 print_average (my_list, first, last); 33 print_average (my_list, first, last - 3); 34 }
Subsequent l
commands display the next few lines of source. Since we're at the end of the program, we won't try that now.
A more advanced topic is:
To obtain a disassembly of the current function, use the disassemble
command (disas
):
(gdb) disas Dump of assembler code for function main: 0x23dc <main>: stw rp,-0x14(sr0,sp) 0x23e0 <main+4>: ldo 0x40(sp),sp 0x23e4 <main+8>: addil -0x800,dp 0x23e8 <main+12>: ldo 0x730(r1),r26 0x23ec <main+16>: ldi 9,r24 . . . End of assembler dump.
As an argument to the disas
command, you can give an address, a function name or a range of addresses. If you give a single address or a function name, you get a dump of the entire function. If you give a range of addresses, you get only those addresses.
(gdb) disas sum Dump of assembler code for function sum: 0x22c8 <sum>: ldo 0x40(sp),sp 0x22cc <sum+4>: stw r26,-0x64(sr0,sp) 0x22d0 <sum+8>: stw r25,-0x68(sr0,sp) 0x22d4 <sum+12>: stw r24,-0x6c(sr0,sp) 0x22d8 <sum+16>: stw r0,-0x24(sr0,sp) . . . End of assembler dump. (gdb) disas 0x22f4 0x2300 Dump of assembler code from 0x22f4 to 0x2300: 0x22f4 <sum+44>: ldw -0x28(sr0,sp),r21 0x22f8 <sum+48>: ldwx,s r21(sr0,r20),r22 0x22fc <sum+52>: ldw -0x24(sr0,sp),r1 End of assembler dump.
You can also use the x/i
command to examine instructions. We will describe this command later in the tutorial.
Topics in this section are:
To step through code, use the step
command (s
):
(gdb) s print_average (list=0x400010c0, low=0, high=9) at average.c:22 22 total = sum(list, low, high); (gdb) l 17 } 18 19 void print_average(int list[], int low, int high) 20 { 21 int total, num_elements, average; 22 total = sum(list, low, high); 23 num_elements = high - low; /* note this is an off-by-one bug */ 24 25 average = total / num_elements; 26 printf("%10.d\n", average);
The step
command steps into any called functions. You have stepped from main
into the print_average
function, and the next step
command puts you in the sum
function.
(gdb) s sum (list=0x400010c0, low=0, high=9) at average.c:13 13 int i, s = 0; (gdb) l 8 9 static int my_list[num] = {3,4,2,0,2,1,8,3,6,7}; 10 11 int sum(int list[], int low, int high) 12 { 13 int i, s = 0; 14 for (i = low; i <= high; i++) 15 s += list[i]; 16 return(s); 17 }
This function contains an uninteresting loop. To continue to the end of a function and avoid stepping through it, use the finish
command (fin
):
(gdb) fin Run till exit from #0 sum (list=0x400010c0, low=0, high=9) at average.c:13 0x2374 in print_average (list=0x400010c0, low=0, high=9) at average.c:22 22 total = sum(list, low, high); Value returned is $1 = 36
Now you can step to the end of the print_average
function and back into its second invocation. Use the [Return] key to repeat the previous command:
(gdb) s 23 num_elements = high - low; /* note this is an off-by-one bug */ (gdb) [Return] 25 average = total / num_elements; (gdb) [Return] 26 printf("%10.d\n", average); (gdb) [Return] 4 27 } (gdb) [Return] main () at average.c:33 33 print_average (my_list, first, last - 3); (gdb) [Return] print_average (list=0x400010c0, low=0, high=6) at average.c:22 22 total = sum(list, low, high);
If you want to step over a called function, use the next
command (n
):
(gdb) n 23 num_elements = high - low; /* note this is an off-by-one bug */
To continue running the program, use the continue
command (c
). In this case, because we have not set any breakpoints, the program runs to the end and exits:
(gdb) c Continuing. 3 Program exited with code 013.
To restart the program, use the run
command again:
(gdb) r Starting program: /home/smith/a.out Breakpoint 1, main () at average.c:32 32 print_average (my_list, first, last);
Note: If you have a program that takes command-line arguments,
run
with no arguments will use the same arguments as the previousrun
. To change the arguments, either specify new arguments torun
or use the commandset args
to establish new arguments.
Use breakpoints to stop execution at a particular location in your program.
Use watchpoints to stop execution when the value of a particular variable changes.
Topics in this section are:
Use the break
command (b
) to set a breakpoint. The command takes several kinds of arguments:
(gdb) b sum Breakpoint 2 at 0x22d8: file average.c, line 13.
(gdb) b 25 Breakpoint 3 at 0x2388: file average.c, line 25.
To set a breakpoint at the current line, use break
with no arguments.
(gdb) b -9 Breakpoint 4 at 0x2378: file average.c, line 23. (gdb) b +1 Breakpoint 5 at 0x2400: file average.c, line 33.
(gdb) b average.c:16 Breakpoint 6 at 0x2324: file average.c, line 16.
*
) to indicate an address:
(gdb) b *0x2324 Note: breakpoint 6 also set at pc 0x2324. Breakpoint 7 at 0x2324: file average.c, line 16.
Use the watch
command (wat
) to stop execution when the value of a given variable changes. If you step into the sum
function, you can set a watchpoint on a variable there.
(gdb) s print_average (list=0x400010c0, low=0, high=9) at average.c:22 22 total = sum(list, low, high); (gdb) s Breakpoint 2, sum (list=0x400010c0, low=0, high=9) at average.c:13 13 int i, s = 0; (gdb) watch s Watchpoint 8: s
The variable you use as an argument to watch
must be in scope at the time you issue the command. The debugger has no syntax for specifying variables that are not currently in scope.
Note: On HP-UX Releases 10.30 and 11.00, the debugger ordinarily sets a hardware watchpoint, which performs considerably faster than the software watchpoint set on Release 10.20 systems. If the debugger can set a hardware watchpoint, it reports it as follows:
(gdb) watch s Hardware watchpoint 8: s
When you continue, the debugger stops as soon as the value of the variable changes, and issues a message like the following:
(gdb) c Continuing. Watchpoint 8: s Old value = 0 New value = 3 sum (list=0x400010c0, low=0, high=9) at average.c:14 14 for (i = low; i <= high; i++)
If the watchpoint is on a variable that has stack storage (that is, not a global or static variable), the debugger automatically deletes the watchpoint as soon as the variable goes out of scope, and issues a message to that effect.
To observe variables with stack storage, you may find it more convenient to use the display
command. You will learn this command later in the tutorial.
Use either the info break
command (i b
) or the info watch
command (i wat
) to get a list of all current breakpoints and watchpoints:
(gdb) i b Num Type Disp Enb Address What 1 breakpoint keep y 0x000023e4 in main at average.c:32 2 breakpoint keep y 0x000022d8 in sum at average.c:13 3 breakpoint keep y 0x00002388 in print_average at average.c:25 4 breakpoint keep y 0x00002378 in print_average at average.c:23 5 breakpoint keep y 0x00002400 in main at average.c:33 6 breakpoint keep y 0x00002324 in sum at average.c:16 7 breakpoint keep y 0x00002324 in sum at average.c:16 8 watchpoint keep y s breakpoint already hit 1 time
The message breakpoint already hit 1 time
refers to the watchpoint, which has been hit once.
Use the delete
command (d
) with a breakpoint or watchpoint number to delete a breakpoint or watchpoint. The following command deletes breakpoint number 7:
(gdb) d 7 (gdb) i b Num Type Disp Enb Address What 1 breakpoint keep y 0x000023e4 in main at average.c:32 2 breakpoint keep y 0x000022d8 in sum at average.c:13 3 breakpoint keep y 0x00002388 in print_average at average.c:25 4 breakpoint keep y 0x00002378 in print_average at average.c:23 5 breakpoint keep y 0x00002400 in main at average.c:33 6 breakpoint keep y 0x00002324 in sum at average.c:16 8 watchpoint keep y s breakpoint already hit 1 time(gdb) i b
The following command deletes watchpoint number 8:
(gdb) d 8 (gdb) i wat Num Type Disp Enb Address What 1 breakpoint keep y 0x000023e4 in main at average.c:32 2 breakpoint keep y 0x000022d8 in sum at average.c:13 3 breakpoint keep y 0x00002388 in print_average at average.c:25 4 breakpoint keep y 0x00002378 in print_average at average.c:23 5 breakpoint keep y 0x00002400 in main at average.c:33 6 breakpoint keep y 0x00002324 in sum at average.c:16
To delete a breakpoint on the current line, use the clear
(cl
) command.
(gdb) c Continuing. Breakpoint 6, sum (list=0x400010c0, low=0, high=9) at average.c:16 16 return(s); (gdb) cl Deleted breakpoint 6
To delete all breakpoints and watchpoints, use delete
with no arguments. The debugger queries you to make sure that is what you want to do. Once you do this, it is a good idea to reset the breakpoint on main
.
(gdb) d Delete all breakpoints? (y or n) y (gdb) i b No breakpoints or watchpoints. (gdb) b main Breakpoint 10 at 0x23e4: file average.c, line 32.
To execute a given sequence of commands every time a breakpoint or watchpoint is encountered, use the commands
command (comm
), which instructs you on how to enter commands:
(gdb) b sum Breakpoint 11 at 0x22d8: file average.c, line 13. (gdb) comm 11 Type commands for when breakpoint 11 is hit, one per line. End with a line saying just "end". >watch s >end (gdb) i b Num Type Disp Enb Address What 10 breakpoint keep y 0x000023e4 in main at average.c:32 11 breakpoint keep y 0x000022d8 in sum at average.c:13 watch s
To remove the command sequence from the breakpoint, enter an empty command sequence:
(gdb) commands 11 Type commands for when breakpoint 11 is hit, one per line. End with a line saying just "end". >end (gdb) i b Num Type Disp Enb Address What 10 breakpoint keep y 0x000023e4 in main at average.c:32 11 breakpoint keep y 0x000022d8 in sum at average.c:13
You can set a breakpoint that triggers only if a given expression is true. To create a conditional breakpoint, attach an if
expression to a break
command:
(gdb) b 15 if i==3 Breakpoint 12 at 0x22f0: file average.c, line 15. (gdb) i b Num Type Disp Enb Address What 10 breakpoint keep y 0x000023e4 in main at average.c:32 11 breakpoint keep y 0x000022d8 in sum at average.c:13 12 breakpoint keep y 0x000022f0 in sum at average.c:15 stop only if i == 3 (gdb) c Continuing. 4 Breakpoint 11, sum (list=0x400010c0, low=0, high=6) at average.c:13 13 int i, s = 0; (gdb) c Continuing. #0 sum (list=0x400010c0, low=0, high=6) at average.c:15 15 s += list[i]; #0 sum (list=0x400010c0, low=0, high=6) at average.c:15 15 s += list[i]; #0 sum (list=0x400010c0, low=0, high=6) at average.c:15 15 s += list[i]; #0 sum (list=0x400010c0, low=0, high=6) at average.c:15 15 s += list[i]; Breakpoint 12, sum (list=0x400010c0, low=0, high=6) at average.c:15 15 s += list[i];
To attach a condition to a breakpoint that you created previously, use the cond
command:
(gdb) cond 11 low == 0 (gdb) i b Num Type Disp Enb Address What 10 breakpoint keep y 0x000023e4 in main at average.c:32 11 breakpoint keep y 0x000022d8 in sum at average.c:13 stop only if low == 0 12 breakpoint keep y 0x000022f0 in sum at average.c:15 stop only if i == 3
To remove a condition from a breakpoint, use the cond
command with no arguments:
(gdb) cond 11 Breakpoint 11 now unconditional.
To inspect the values of variables, you have several options:
print
)
display
)
watch
, described in Using breakpoints and watchpoints)
The variable or expression you use as an argument to these commands must be in scope at the time you issue the command. The debugger has no syntax for specifying variables that are not currently in scope. You can also:
To print the value of a variable or expression, use the print
command (p
). By default, the p
command prints the value in a format appropriate to the declared type of the variable, in this case an int
:
(gdb) p s $1 = 9
Every expression you print is assigned a number, prefixed by a dollar sign ($
), by which you can refer to it in subsequent commands. The current value of s
has the number $1
.
You can also use a slash (/
) and a format specifier to request another format. For example, you can use x
for hexadecimal, c
for character, d
for decimal, and t
for binary:
(gdb) p/x s $2 = 0x9 (gdb) p/c s $3 = 9 '\t' (gdb) p/t s $4 = 1001 (gdb) p/d s $5 = 9
You can also print expressions:
(gdb) p s+2 $6 = 11 (gdb) p s * 5 $7 = 45 (gdb) p $5 + $6 $8 = 20
You can print an array or array element as follows:
(gdb) p my_list $9 = {3, 4, 2, 0, 2, 1, 8, 3, 6, 7} (gdb) p my_list[5] $10 = 1
To find the type of a variable, use the ptype
command (pt
):
(gdb) ptype s type = int
The debugger also provides a printf
command that allows you to display formatted data. For example:
(gdb) printf "i is %d, s is %d\n", i, s i is 3, s is 9
You may find this command useful when you attach commands to breakpoints or create user-defined commands (see Creating your own commands). A more advanced topic is:
Instead of using a print
command every time you want to look at a variable, you can ask the debugger to show you one or more values automatically every time the debugger stops -- for example, when you step or reach a breakpoint. To do this, use the display
command (disp
).
Let's restart the program and continue it to the beginning of sum
before issuing the display
command.
(gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/smith/a.out Breakpoint 10, main () at average.c:32 32 print_average (my_list, first, last); (gdb) c Continuing. Breakpoint 11, sum (list=0x400010c0, low=0, high=9) at average.c:13 13 int i, s = 0; (gdb) display i 1: i = 0 (gdb) disp s 2: s = 0
Each displayed variable is assigned a number.
Now, let's remove the condition on breakpoint 12 so that we will stop every time we reach that line.
(gdb) i b Num Type Disp Enb Address What 10 breakpoint keep y 0x000023e4 in main at average.c:32 11 breakpoint keep y 0x000022d8 in sum at average.c:13 12 breakpoint keep y 0x000022f0 in sum at average.c:15 stop only if i == 3 (gdb) cond 12 Breakpoint 12 now unconditional.
Now, when we continue, the two values are displayed when we reach the breakpoint.
(gdb) c Continuing. Breakpoint 12, sum (list=0x400010c0, low=0, high=9) at average.c:15 15 s += list[i]; 2: s = 0 1: i = 0 (gdb) c Continuing. Breakpoint 12, sum (list=0x400010c0, low=0, high=9) at average.c:15 15 s += list[i]; 2: s = 3 1: i = 1
Use the info display
command (i disp
) to show the variables being displayed:
(gdb) i disp Auto-display expressions now in effect: Num Enb Expression 2: y s 1: y i
To stop displaying an expression, use the expression number as an argument to the undisplay
command (und
). To stop displaying all expressions, use undisplay
with no arguments:
(gdb) undisplay 2 (gdb) i disp Auto-display expressions now in effect: Num Enb Expression 1: y i (gdb) und Delete all auto-display expressions? (y or n) y (gdb) i disp There are no auto-display expressions now.
You can create your own variables to use within the debugger. The term for these is convenience variables.
To create a convenience variable, use the set var
command, and put a dollar sign ($
) before the name of the variable. Use the assignment operator (=
) to assign an expression to the variable:
(gdb) set var $myvar = high - low + 1 (gdb) p $myvar $1 = 10
You can use the print
command interchangeably with set var
to create convenience variables and assign values to them. The only difference between these commands is that set var
performs the assignment silently, while print
displays the value after performing the assignment:
(gdb) p $ix = 0 $2 = 0 (gdb) p list[$ix++] $3 = 3 (gdb) [Return] $4 = 4 (gdb) [Return] $5 = 2
The show convenience
command (sho conv
) lists all convenience variables currently in use. The variable $_
is automatically set to the last memory address examined.
(gdb) sho conv $ix = 3 $myvar = 10 $_ = (void *) 0x22f0
You can also use print
or set var
to change the value of a variable, either a convenience variable or a program variable. For example, you can change the value of high
(and then change it back):
(gdb) p high $6 = 9 (gdb) set var high = 34 (gdb) p high $7 = 34 (gdb) p high = 9 $8 = 9
Particularly if you debug at the assembly level, you may want to look at data or instructions in memory. Topics in this section are:
To see how the array my_list
is arranged in memory, first find the address of the array. You can use either the print
command or the info address
command to do this:
(gdb) p &my_list $9 = (int (*)[10]) 0x400010c0 (gdb) i addr my_list Symbol "my_list" is static storage at address 0x400010c0.
Then use the address as an argument to the x
command. The 10 tells the debugger to display 10 units of data. By default, the debugger displays the data using the last format specifier you used in either the x
or print
command, which in this tutorial was d
, for decimal.
(gdb) x/10 0x400010c0 0x400010c0 <DS$average>: 3 4 2 0 0x400010d0 <DS$average+16>: 2 1 8 3 0x400010e0 <DS$average+32>: 6 7
You may use any of the formats allowed by the print
command:
(gdb) x/10x 0x400010c0 0x400010c0 <DS$average>: 0x00000003 0x00000004 0x00000002 0x00000000 0x400010d0 <DS$average+16>: 0x00000002 0x00000001 0x00000008 0x00000003 0x400010e0 <DS$average+32>: 0x00000006 0x00000007
If you have not previously used a print format specifier, the default for the x
command is hexadecimal.
To display a more manageable number of instructions than the disas
command shows, use the x
command with the i
(for instruction) format specifier. The following x/i
command displays the instruction at a specified address:
(gdb) x/i 0x22d4 0x22d4 <sum+12>: stw r24,-0x6c(sr0,sp)
The following command displays ten instructions, starting with the program counter ($pc
):
(gdb) x/10i $pc 0x22f0 <sum+40>: ldw -0x64(sr0,sp),r20 0x22f4 <sum+44>: ldw -0x28(sr0,sp),r21 0x22f8 <sum+48>: ldwx,s r21(sr0,r20),r22 0x22fc <sum+52>: ldw -0x24(sr0,sp),r1 0x2300 <sum+56>: add r1,r22,r31 0x2304 <sum+60>: stw r31,-0x24(sr0,sp) 0x2308 <sum+64>: ldw -0x28(sr0,sp),r19 0x230c <sum+68>: ldo 1(r19),r20 0x2310 <sum+72>: stw r20,-0x28(sr0,sp) 0x2314 <sum+76>: ldw -0x28(sr0,sp),r21
To see the contents of the PA-RISC integer registers, use the info registers
command (i r
). Your shell window needs to be at least 81 characters wide for the display to look right.
(gdb) i r flags: 29000001 r18: 400155bc pcsqt: 3b52 ccr: 0 r1: 0 r19: 0 eiem: fffffffe cr12: ffffffff rp: 2377 r20: 1 iir: 10004 cr13: ffffffff r3: 7b03b250 r21: 1 isr: 3b52 cr24: 0 r4: 1 r22: 9 ior: 0 cr25: 1 . . .
To see the contents of both integer and floating-point registers, use the info all-registers
command (i al
).
To display the contents of a given register, use the register name as an argument to the info reg
command:
(gdb) i r rp rp 2377 (gdb) i r fr30 fr30 (single precision) 1.9375 fr30 (double precision) 1.5 (gdb) i r fr30R fr30R (single precision) 0
You can also use a register name in a print
command, prefixed by a dollar sign ($
):
(gdb) p/x $rp $10 = 0x2377 (gdb) p/x (void*)$fr30 $11 = 0x3ff80000 (gdb) p/x (void*)$fr30R $12 = 0x0
The debugger provides several commands that allow you to find out where you are in your program's call stack and to traverse the stack. Topics in this section are:
To find out where in the call stack your program has stopped, use the backtrace
command (bt
):
(gdb) bt #0 sum (list=0x400010c0, low=0, high=9) at average.c:15 #1 0x2374 in print_average (list=0x400010c0, low=0, high=9) at average.c:22 #2 0x2400 in main () at average.c:32
You can use where
as a synonym for bt
.
The command output begins with the number the debugger gives to each stack frame. The stack frame for the current program always has the number 0. The stack frame of the main
function has the highest number.
The bt
command output also includes the function name, its arguments, and the file and line to which the program will return. The program counter for the frame also appears, if the program counter is not at the beginning of the assembly code for the line number.
To move to a higher level of the stack (closer to main
), use the up
command. To move to a lower level, use down
. You can specify a numerical argument to either command to move more than one level at a time:
(gdb) up #1 0x2374 in print_average (list=0x400010c0, low=0, high=9) at average.c:22 22 total = sum(list, low, high); (gdb) up #2 0x2400 in main () at average.c:32 32 print_average (my_list, first, last); (gdb) down 2 #0 sum (list=0x400010c0, low=0, high=9) at average.c:15 15 s += list[i];
To move to a particular stack level, use the frame
command (f
) with the desired frame number as argument:
(gdb) f 1 #1 0x2374 in print_average (list=0x400010c0, low=0, high=9) at average.c:22 22 total = sum(list, low, high); (gdb) f 0 #0 sum (list=0x400010c0, low=0, high=9) at average.c:15 15 s += list[i];
To see a brief description of the current stack frame, use the frame
command (f
) with no arguments:
(gdb) f #0 sum (list=0x400010c0, low=0, high=9) at average.c:15 15 s += list[i];
For a more detailed description, use info frame
(i f
):
(gdb) i f Stack level 0, frame at 0x7b03b250: pcoqh = 0x22f0 in sum (average.c:15); saved pcoqh 0x2374 called by frame at 0x7b03b210 source language c. Arglist at 0x7b03b250, args: list=0x400010c0, low=0, high=9 Locals at 0x7b03b250, Previous frame's sp is 0x7b03b250
Use the define
command to create your own debugger commands (sometimes called macros), by using a sequence of one or more HP WDB commands.
(gdb) define spv Type commands for definition of "spv". End with a line saying just "end". >step >printf "list[%d] is %d, s is %d\n", i, list[i], s >end (gdb) spv 14 for (i = low; i <= high; i++) list[1] is 4, s is 7
The show user
command displays all current user-defined commands:
(gdb) show user User command spv: step printf "list[%d] is %d, s is %d\n", i, list[i], s
To remove a user-defined command, enter an empty command sequence:
(gdb) define spv Redefine command "spv"? (y or n) y Type commands for definition of "spv". End with a line saying just "end". >end (gdb) show user (gdb)
You have reached the end of this introductory tutorial.
To stop debugging the current program but stay within the debugger, use the kill
command (k
).
(gdb) k Kill the program being debugged? (y or n) y
To exit the debugger entirely, use the quit
command (q
):
(gdb) q
The examples in these sections do not work with the sample program in the tutorial. They are provided as exhibits only.
To debug a core file, specify first the executable name and then the core file name:
$ gdb a.out core
Back to "Starting the debugger"
To attach to a program that is already running, find out the process id (PID) of the program, then use that as the second argument to the gdb
command:
$ ps -ef | grep a.out haase 22883 14850 0 16:57:25 ttyp6 0:00 a.out haase 22887 14844 2 16:57:42 ttyp2 0:00 grep a.out $ gdb a.out 22883
If you are already in the debugger, you can use the attach
command (att
) to attach to a running process. Use the shell
command to run ps
from within the debugger:
(gdb) she ps -ef | grep a.out haase 22861 22859 5 16:52:36 ttyp2 0:00 grep a.out haase 22858 14850 0 16:52:26 ttyp6 0:00 a.out haase 22859 22839 30 16:52:35 ttyp2 0:00 csh -c ps -ef | grep a.out (gdb) att 22858
Back to "Starting the debugger"
In cases where you attach to a running program and you try to set a breakpoint in a shared library, GDB may generated the following message:
The shared libraries were not privately mapped; setting a breakpoint in a shared library will not work until you rerun the program.
GDB generates this message because the debugger sets breakpoints by replacing an instruction with a BREAK
instruction. The debugger can not set a breakpoint in a shared library because doing so can affect other processes on the system in addition to the process being debugged.
To set the breakpoint you must kill the program and then re-run it so that the dynamic linker will map a copy of the shared library. There are two ways to run the program:
dld
to map all shared libraries private, enabling breakpoint debugging.
pxdb -s on
command marks the executable so that dld
maps shared libraries private when the program starts up.
Back to "Starting the debugger"
If the source code for your program is not in the current directory, use the dir
command to tell the debugger where to find it.
For example, if your executable is in a different directory from your source code, you may receive the following message after a run
command:
(gdb) b main Breakpoint 1 at 0x23e4: file average.c, line 30. (gdb) r Starting program: /u/users/smith/a.out Breakpoint 1, main () at average.c:30 average.c:30: No such file or directory.
Use the dir
command to tell the debugger where to look for the source:
(gdb) dir /home/smith Source directories searched: /home/smith:$cdir:$cwd
Both print
and ptype
work with all C and C++ data types. Here are some hypothetical examples:
char
):
(gdb) p c1 $1 = 97 'a'
long long
), currently printed in hexadecimal:
(gdb) p ll7 $7 = 0x4000000000000000
enum
):
(gdb) ptype et9 type = enum {zero, one, two, three, four, five, six, seven, eight} (gdb) p et9 $9 = eight
float
, double
, long double
):
(gdb) p fl11 $10 = 6.5432098e+15 (gdb) p d12 $11 = 1.2345599999999999e-123 (gdb) ptype ld13 type = long double (gdb) p ld13 $12 = Can't deal with a floating point number of 16 bytes.
Note: HP WDB does not currently support
long double
data types.
(gdb) p iarr29 $43 = {33, 44, 55}
(gdb) pt s1 type = struct { int a; float b; } (gdb) p s1 $30 = {a = 55555, b = 3.5}
To make the print command format the structure output nicely, use the set print pretty on
command:
(gdb) set print pretty on (gdb) p s1 $31 = { a = 55555, b = 3.5 }
(gdb) ptype diy type = union { double y; struct { unsigned int ym; unsigned int yl; } i; } (gdb) p diy $1 = {y = 1, i = {ym = 1072693248, yl = 0}} (gdb) set print pretty on (gdb) p/x diy $3 = { y = 0x3ff0000000000000, i = { ym = 0x3ff00000, yl = 0x0 } }
(gdb) ptype account type = class account { private: char *name; protected: double balance; double rate; static int accts; static double assets; public: account (void); void ~account (int); void deposit (int); void withdraw (int); void display_balance (void); static void display_assets (void); virtual void update_balance (void); } (gdb) ptype my_checking_acct type = class checking_account : public account { private: double fee; public: checking_account (void); virtual void update_balance (void); } * (gdb) p *my_checking_acct $3 = {= { name = 0x400036c8 "Checking", balance = 0, rate = 0.050000000000000003, static accts = 2, static assets = 0 , Virtual table at 0x40001120 }, members of checking_account: fee = 2 }