Skip to content

Linux gdb command (program debugging)

The gdb command in Linux is a very useful tool for debugging software compiled with GCC.

Using the gdb debugger for the first time

In order for the debugger to work, the software must be compiled with the gcc “-g” option, so the compiler will provide debugging information in the object code.

Example:

$ gcc —wall —g principal.c network.c interface.c —the new ping

The main idea for debugging a program is to enter a breakpoint at the point where you want to start debugging on a given N line of code.

The breakpoint stops the execution of the program at a certain point that you want to examine more carefully.

After entering the breakpoint, the program must be executed within gdb and proceed with the execution, checking the parameters passed to the functions, the type and content of the variables, until the error is found. The error in the source code is then corrected and the program is compiled again.

To use gdb it’s simple:

# gdb <br></br>GNU gdb 5.3.92 executable program <br></br>Copyright 2003 Free Software Foundation, Inc. <br></br>GDB is free software, covered by the GNU General Public License, and you are <br></br>welcome to change it and/or distribute copies of it under certain conditions. <br></br>Type 'show copying' to see the conditions. <br></br>There is absolutely no warranty for GDB. Type “show warranty” for details. <br></br>This GDB was configured as “i586-suse-linux”...

(gdb)

Its interface is based on Linux commands with relatively simple syntaxes.

Commands can be written in full or in a simplified form, where only the first letters are generally used. Parameters such as line numbers and variable names are passed immediately after the command name.

Let’s look at the most important commands:

To enter a breakpoint on a given line of code:

Break N or B N

Where N is the line of code that you want to stop running the program. To do this, it may be necessary to view the program’s source code.

To remove all breakpoints:

Delete or d

To run the program until the first breakpoint is found:

Run or r

To list the program’s source code:

List or l

To execute the next program instructions. An instruction can be understood as a function:

Next N or N N

Where N is the number of instructions.

To execute the next N lines after the breakpoint:

Step N or S N

To end the program:

Kill or K

To view information about the type of a variable:

What variable or w variable

To view the contents of a variable:

Variable print or variable p

To view the state of a variable at each execution step:

Variable display and l

To view the content of all instantiated variables:

Local info

To view the program registrars:

Info registers

To view the program’s assembly code:

Disassemble

To view the recursion stack:

backtrace or bt

To get help with a command:

Help command or h command

To exit gdb:

Quit or q

Example of debugging a program

Debugging programs without using appropriate tools can be an exhausting and often impossible task. To help with this task, the following is an example of the procedure for discovering problems using GDB.

The following sample program was designed to cause a floating-point calculation error:

#include <br></br>float calculation (int number1, int number2) <br></br>{<br></br>int difference; <br></br>float result; <br></br>difference = number1 - number2; <br></br>result = number1/difference; <br></br>return result;<br></br>} <br></br>int main (int argc, char *argv []) <br></br>{<br></br>& & nbsp; int value, divisor, i; <br></br>float result, total; <br></br>value = 10.1; <br></br>divisor = 6; <br></br>total = 0; <br></br>for (i = 0; i < 10; i++) <br></br>{<br></br>result = calculation (value, divisor); <br></br>total += result; <br></br>printf (“%d divided by %d is %f. The sum of the results is %f. n”, value, divisor value, result, total);

divisor++;
value—;
}
return 0;
}

To compile this program saved as “erro.c”:

$ gcc —g error.c —the error

The “-g” option compiles the program with the information needed for debugging.

This program should execute a loop ten times and calculate the cumulative value of successive divisions. However, when running it, an error will abort its execution:

$. /error <br></br>10 divided by 4 is 2,000000. The sum of the results is 2,000,000. <br></br>9 divided by 2 is 4,000,000. The sum of the results is 6,000,000.

Floating Point Exception

To perform the debugging it is necessary to run the program through GDB:

$ gdb <br></br>GNU error gdb 5.3.92 <br></br>Copyright 2003 Free Software Foundation, Inc. <br></br>GDB is free software, covered by the GNU General Public License, and you are <br></br>welcome to change it and/or distribute copies of it under certain conditions. <br></br>Type 'show copying' to see the conditions. <br></br>There is absolutely no warranty for GDB. Type “show warranty” for details. <br></br>This GDB was configured as “i586-suse-linux”...

(gdb)

The program can be run within the GDB with the “run” command:

(gdb) run <br></br>Starting program: /root/systems/error <br></br>10 divided by 4 is 2,000000. The sum of the results is 2,000,000. <br></br>9 divided by 2 is 4,000,000. The sum of the results is 6,000,000. <br></br>Program received SIGFPE signal, Arithmetic exception.

0x0804835e in calculation (number1=8, number2=8) at
gdb.c:7 7 result = number1/difference;

The GDB indicated that the program performed an illegal mathematical operation on line 7 precisely in the calculation function:

The values of the variables number1 and number2 are 8. We can list the program’s source code to see what it’s doing with the “list” command:

(gdb) list <br></br>2 float calculation (int number1, int number2) <br></br>3 {<br></br>4 int difference; <br></br>5 float result; <br></br>6 difference = number1 - number2;

7 result = number1/difference;
8 return result;
9}
10 int main (int argc, char *argv [])
11 {

The list command will list the code every 10 lines. It can be repeated until all of the code is displayed.

As a first step, it is interesting to examine the content of the variables with the “print” command:

(gdb) print number1 $1 = 8 (gdb) print number2 $2 = 8 (gdb) print difference $3 = 0

In line 7 of the program where the error occurred, it can be seen that the operation “result = number1/difference”. Analyzing the value of the variables and the instruction, it can be deduced that the program is trying to divide by zero.

We can continue processing the program with the “continue” command:

(gdb) continue <br></br>Continuing. <br></br>Program terminated with SIGFPE signal, Arithmetic exception. <br></br>The program no longer exists.

Because the division by zero error aborts execution, the program will not continue. It will be necessary to use the breakpoints and run the program again. It is interesting to install the breakpoint in the main function before the function calculus is called.

(gdb) list <br></br>10 int main (int argc, char *argv []) <br></br>11 {<br></br>12 int value, divisor, i; <br></br>13 float result, total; <br></br>14 value = 10.1; <br></br>15 & nbsp; divisor = 6; <br></br>16 total = 0; <br></br>17 for (i = 0; i < 10; i++) <br></br>18 {<br></br>19 result = calculation (value, divisor); <br></br>20 total += result; <br></br>21 & nbsp; printf (“%d divided by %d is %f. The sum of the results is %f. n”, = value, divisor value, result, total); <br></br>22 divisor++; <br></br>23 value--; <br></br>24} <br></br>25 return 0;

We can install the stop point on line 12 at the start of the main function and run the program again:

(gdb) break 12 <br></br>Breakpoint 1 at 0x8048384: gdb.c file, line 12.

(gdb) run
Starting program: /root/systems/error
Breakpoint 1, main (argc=1, argv=0xbfffd874) at gdb.c:14
14 value = 10.1;

The processing will stop at line 14 which contains significant instructions after line 12. We can advance the processing line by line with the “next” command:

(gdb) next 15 divisor = 6; (gdb) next 16 total = 0; (gdb) next 17 for (i = 0; i < 10; i++)

The contents of the variables can be displayed with the “print” command followed by the variable name:

(gdb) print value $5 = 10 (gdb) print divisor $6 = 6

The value of all the instantiated variables can be seen with the “info locals” command:

(gdb) info locals value = 10 divisor = 6 i = 0 result = -1.99878407 total = 0

The next step is to run the program line by line until the content of the value and divisor variables is 8. The “display” command allows the content of a variable to be displayed with each instruction processed:

(gdb) display value 1: value = 10 (gdb) display divisor 2: divisor = 6

The instructions can be advanced with the “next” command:

(gdb) next <br></br>20 total += result; <br></br>2: divisor = 6 <br></br>1: value = 10 <br></br>(gdb) next <br></br>21 printf (“%d divided by %d is %f. The sum of the results is %f. n”, value, divisor value, result, total); <br></br>2: divisor = 6 <br></br>1: value = 10 <br></br>(gdb) next <br></br>10 divided by 4 is 2,000,000. The sum of the results is 2,000,000. <br></br>22 divisor++; <br></br>2: divisor = 6 <br></br>1: value = 10 <br></br>(gdb) next <br></br>23 value--; <br></br>2: divisor = 7 <br></br>1: value = 10 <br></br>(gdb) next <br></br>17 for (i = 0; i < 10; i++) <br></br>2: divisor = 7 <br></br>1: value = 9 <br></br>(gdb) next <br></br>19 & nbsp; result = calculation (value, divisor); <br></br>2: divisor = 7 <br></br>1: value = 9 <br></br>(gdb) next <br></br>20 total += result; <br></br>2: divisor = 7 <br></br>1: value = 9 <br></br>(gdb) next <br></br>21 printf (“%d divided by %d is %f. The sum of the results is %f. n”, value, divisor value, result, total); <br></br>2: divisor = 7 <br></br>1: value = 9 <br></br>(gdb) next <br></br>9 divided by 2 is 4,000,000. The sum of the results is 6,000,000.

22 divisor++;
2: divisor = 7
1: value = 9
(gdb) next
23 value—;
2: divisor = 8
1: value = 9
(gdb) next
17 for (i = 0; i < 10; i++)
2: divisor = 8
1: value = 8

At this point, the calculation function will return dividing by zero. The value of the variable can be changed during execution to overcome the error with the “set” command:

(gdb) info locals value = 8 divisor = 8 i = 1 result = 4 total = 6 (gdb) set value = 10 (gdb) info locals value = 10 divisor = 8 i = 1 result = 4 total = 6

The program will continue processing until it finds another division by zero.

(gdb) next <br></br>19 result = calculation (value, divisor); <br></br>2: divisor = 8 <br></br>1: value = 10 <br></br>(gdb) next <br></br>20 total += result; <br></br>2: divisor = 8 <br></br>1: value = 10 <br></br>(gdb) next <br></br>21 & nbsp; printf (“%d divided by %d is %f. The sum of the results is %f. n”, value, divisor value, result, total); <br></br>2: divisor = 8 <br></br>1: value = 10 <br></br>(gdb) next <br></br>10 divided by 2 is 5,000,000. The sum of the results is 11,000,000. <br></br>22 divisor++; <br></br>2: divisor = 8 <br></br>1: value = 10 <br></br>(gdb) next <br></br>23 value--; <br></br>2: divisor = 9 <br></br>1: value = 10 <br></br>(gdb) next <br></br>17 for (i = 0; i < 10; i++) <br></br>2: divisor = 9 <br></br>1: value = 9 <br></br>(gdb) next <br></br>19 & nbsp; result = calculation (value, divisor); <br></br>2: divisor = 9 <br></br>1: value = 9 <br></br>(gdb) next <br></br>Program received SIGFPE signal, Arithmetic exception.

0x0804835e in calculation (number1=9, number2=9) at
gdb.c:7 7 result = number1/difference;

In the case of this example, the program declares variables as integers and does not allow the rest of a division.

GDB is a powerful program debugger. We encourage you to install a graphical interface for it to make it easier to use. Other scrubbers are also available.