Three Steps to Master GDB

Three Steps to Master GDB

Debugging C programs used to confuse me. However, when I was writing my operating system, I had many bugs to debug. I was fortunate to use the QEMU emulator, which allowed me to attach a debugger to my operating system. This debugger is gdb.
— Julia Evans
This article navigation
Compiled from | https://jvns.ca/blog/2014/02/10/three-steps-to-learning-gdb/ Author | Julia Evans Translator | Torival

Debugging C programs used to confuse me. However, when I was writing my operating system[1], I had many bugs to debug. I was fortunate to use the QEMU emulator, which allowed me to attach a debugger to my operating system. This debugger is gdb.

I need to explain that you can start with some small things using gdb, as I found it really confusing when I first learned it. We will set breakpoints and inspect memory in a small program.

1. Set Breakpoints

If you have ever used a debugger, you might already know how to set breakpoints.

Below is a program we are going to debug (although it has no bugs):

#include <stdio.h>
void do_thing() {
    printf("Hi!\n");
}
int main() {
    do_thing();
}

Save it as hello.c. We can debug it like this:

bork@kiwi ~> gcc -g hello.c -o hello
bork@kiwi ~> gdb ./hello

The above compiles hello.c with debug information (so that gdb can work better), and it gives us a prominent prompt like this:

(gdb)

We can use the break command to set breakpoints and then use run to start debugging the program.

(gdb) break do_thing 
Breakpoint 1 at 0x4004f8
(gdb) run
Starting program: /home/bork/hello 

Breakpoint 1, 0x00000000004004f8 in do_thing ()

The program pauses at the start of do_thing.

We can use where to see where we are in the call stack.

(gdb) where
#0  do_thing () at hello.c:3
#1  0x08050cdb in main () at hello.c:6
(gdb) 

2. Read Assembly Code

Using the disassemble command, we can see the assembly code for this function. Awesome, this is x86 assembly code. Although I don’t understand it very well, the line callq is the call to the printf function.

(gdb) disassemble do_thing
Dump of assembler code for function do_thing:
   0x00000000004004f4 <+0>:     push   %rbp
   0x00000000004004f5 <+1>:     mov    %rsp,%rbp
=> 0x00000000004004f8 <+4>:     mov    $0x40060c,%edi
   0x00000000004004fd <+9>:     callq  0x4003f0 
   0x0000000000400502 <+14>:    pop    %rbp
   0x0000000000400503 <+15>:    retq 

You can also use the abbreviation disas for disassemble.

3. Inspect Memory

When debugging my kernel, the main reason I used gdb was to ensure that the memory layout was as I expected. The command for inspecting memory is examine, or you can use the abbreviation x. We will use x.

By looking at the assembly code above, it seems that 0x40060c might be the address of the string we want to print. Let’s try it.

(gdb) x/s 0x40060c
0x40060c:        "Hi!"

Indeed. In x/s, the /s part means “display it as a string”. I can also “display 10 characters” like this:

(gdb) x/10c 0x40060c
0x40060c:       72 'H'  105 'i' 33 '!'  0 '\000'        1 '\001'        27 '\033'       3 '\003'        59 ';'
0x400614:       52 '4'  0 '\000'

You can see the first four characters are H, i, !, and \0, and what follows are some unrelated things.

I know gdb has many other features, but I still don’t understand it very well. However, x and break have helped me a lot. You can also read the documentation for examining memory[2].

via: https://jvns.ca/blog/2014/02/10/three-steps-to-learning-gdb/

Author: Julia Evans[4] Translator: Torival Proofreader: wxy

This article is originally compiled by LCTT and proudly presented by Linux China

LCTT Translator
Three Steps to Master GDB

Torival 🌟 🌟
Total translations: 2 articles
Contribution time: 151 days
Recommended Articles

< Swipe left and right to view related articles >

Three Steps to Master GDBThree Steps to Master GDBThree Steps to Master GDBThree Steps to Master GDBThree Steps to Master GDBThree Steps to Master GDB

Click the image, enter the article ID, or scan the QR code to go directly

Leave a Comment