HP WDB Tutorial

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:

Compiling for debugging

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.

Configuring vi editing commands

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.

Starting the debugger

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).

Executing a program

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:

  1. Set a breakpoint. Use the break command, abbreviated b:
    (gdb) b main
    Breakpoint 1 at 0x23e4: file average.c, line 32.
  2. Start the program. Use the 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.

Getting help

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.

Examining source code

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:

Disassembling code

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.

Stepping and continuing

Topics in this section are:

Basic stepping

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      }

Continuing to the end of a function

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);

Stepping over called functions

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 */

Continuing execution

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.

Restarting a program

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 previous run. To change the arguments, either specify new arguments to run or use the command set args to establish new arguments.

Using breakpoints and watchpoints

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:

Setting breakpoints

Use the break command (b) to set a breakpoint. The command takes several kinds of arguments:

Setting watchpoints

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.

Listing breakpoints and watchpoints

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.

Deleting breakpoints and watchpoints

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.

Attaching command sequences to breakpoints and watchpoints

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

Setting conditional breakpoints

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.

Examining variables

To inspect the values of variables, you have several options:

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:

Printing the value of a variable

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:

Displaying values at every stop

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.

Creating debugger variables

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

Changing the value of a variable

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

Examining memory

Particularly if you debug at the assembly level, you may want to look at data or instructions in memory. Topics in this section are:

Examining memory addresses

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.

Examining instructions

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

Examining registers

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

Navigating the stack

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:

Obtaining a stack traceback

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.

Moving up and down the stack

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];

Moving to a specific stack frame

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];

Finding information about a frame

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

Creating your own commands

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)

Ending a debugging session

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

Some more advanced debugging topics

The examples in these sections do not work with the sample program in the tutorial. They are provided as exhibits only.

Debugging a core file

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"

Attaching to a running process

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"

Privately mapping shared libraries

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:

Back to "Starting the debugger"

Finding source files

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

Back to "Examining source"

Printing other kinds of data

Both print and ptype work with all C and C++ data types. Here are some hypothetical examples:

Back to "Printing the value of a variable"