Chapter 7. A Sample Debug Session

You can use this manual at your leisure to read all about the debugger. However, a handful of commands are enough to get started using the debugger. This chapter illustrates those commands.

The benchmark program Whetstone is frequently used to measure the performance of floating-point operations. We run Whetstone on the target to compare its performance with other computers. The workings of Whetstone are a bit of a mystery, but by using the debugger we can get an insight.

The first step is to compile the Whetstone source with the debug option switched on. There is no need to compile with minimal optimization since the debugger is able to cope with most optimizations.

$ erc-coff-gcc -O2 -g whetstone.c -o whetstone

The code we wish to look at starts on line 373, just after the array e1 has been set up. Here is part of the C source file showing line 373 and some of the surrounding lines.

   368        /* Module 2: computations with array elements */
   369        e1 [1] = 1.0;
   370        e1 [2] = -1.0;
   371        e1 [3] = -1.0;
   372        e1 [4] = -1.0;
   373        for (i = 1; i <= n2; i++)
   374          {
   375            e1 [1] = (e1 [1] + e1 [2] + e1 [3] - e1 [4]) * t;
   376            e1 [2] = (e1 [1] + e1 [2] - e1 [3] + e1 [4]) * t;
   377            e1 [3] = (e1 [1] - e1 [2] + e1 [3] + e1 [4]) * t;
   378            e1 [4] = (-e1 [1] + e1 [2] + e1 [3] + e1 [4]) * t;
   379          }

We start the debugger using the following command. You may use the -q option to suppress the banner:

$ erc-coff-gdb whetstone
XGC Debugger Version 4.17.gnat.3.11 for erc-coff
Copyright (c) 1998 Free Software Foundation, Inc.
(gdb)

The easiest way to get to line 373 is to set a breakpoint on that line, then use the run command. Breakpoints are set using the break command. We can check what breakpoints are set using the info command.

(gdb) break 373
Breakpoint 1 at 0x105a2: file whetstone.c, line 373.
(gdb) info breakpoints
Num Type           Disp Enb Address    What
1   breakpoint     keep y   0x000105a2 in main at whetstone.c:373
(gdb)

So far we have been working with the exec target. This is the executable file whetstone cited on the comand line that invoked the debugger. Using just this file, and no target at all, we can look at the values of symbols, inspect the source code, and the generated code, and check the values of static variables.

In order to run the program we must switch to a real or simulated target. The debugger supports both. The simulator target is called sim and a real target is called remote. The debugger will automatically switch to the simulator and load the program into the simulator if we enter the run command at this point.

(gdb) run
Starting program: benchmarks/whetstone
Loading section .text, size 0x2304 vma 0x10000
Loading section .data, size 0x90 vma 0x12304
Loading section .rodata, size 0x7b0 vma 0x12394
,.,. whetstone GTS Version 0.1
---- whetstone Whetstone floating-point benchmark.
Breakpoint 1, main () at whetstone.c:373
373           for (i = 1; i <= n2; i++)
(gdb)

What we want to do now is see how the value of e1 changes as we go round the loop. We can print the initial value using the print command. Note that arrays (and structures) may be printed with a single command.

(gdb) print e1[1]
$1 = 1
(gdb) print e1[2]
$2 = -1
(gdb) print e1
$3 = {0, 1, -1, -1, -1}
(gdb)

We can then step through the program one line at a time using the next command. Like many other commands, the next command repeats when we press Enter. Therefore, after the first next command, we just hit Enter.

(gdb) next
375               e1 [1] = (e1 [1] + e1 [2] + e1 [3] - e1 [4]) * t;
(gdb) Enter
376               e1 [2] = (e1 [1] + e1 [2] - e1 [3] + e1 [4]) * t;
(gdb) Enter
377               e1 [3] = (e1 [1] - e1 [2] + e1 [3] + e1 [4]) * t;
(gdb) Enter
378               e1 [4] = (-e1 [1] + e1 [2] + e1 [3] + e1 [4]) * t;
(gdb)

Let's check the value of e1. This time we'll use the abbreviation.

(gdb) p e1
$4 = {0, 0, -0.499975026, -0.749975085, -1}

If we need to check the value of e1 each time round the loop, it is tedious to have to step through each line then type the print command at the end of the loop. Instead we can place a breakpoint at the end of the loop and use the continue command to execute to the end of the loop. Furthermore, we can use the display command to print the value of e1 each time the program stops.

(gdb) br
Breakpoint 2 at 0x105f6: file whetstone.c, line 378.
(gdb) display e1
1: e1 = {0, 0, -0.499975026, -0.749975085, -1}

Use the continue command to run the program to the next breakpoint. Then press Enter to repeat the continue command. Note that continue may be abbreviated to c.

(gdb) c
Continuing.
Breakpoint 2, main () at whetstone.c:378
378               e1 [4] = (-e1 [1] + e1 [2] + e1 [3] + e1 [4]) * t;
1: e1 = {0, -0.0625123829, -0.468692422, -0.734320521, -1.12491918}
(gdb) Enter
Continuing.
Breakpoint 2, main () at whetstone.c:378
378               e1 [4] = (-e1 [1] + e1 [2] + e1 [3] + e1 [4]) * t;
1: e1 = {0, -0.0664326251, -0.466705739, -0.733313918, -1.13265347}
(gdb)

To finish the debugging session use the quit command. You may abbreviate quit to q.

(gdb) q
The program is running.  Quit anyway (and kill it)? (y or n) y
$