GDB is an essential tool for programmers to debug their code.
Breakpoints are the way to tell GDB to stop or pause the program execution at certain line, or function, or address. Once the program is stopped you can examine and change the variable values, continue the program execution from that breakpoint, etc.
Similar to breakpoints, backtrace is also helpful during debugging process to view and navigate the stack frame as explained in this tutorial
This tutorial requires some basic understanding of stack frame that we discussed in our memory layout of a process article.
C Code Example for GDB Backrace
The following C program code example will be used in this tutorial to explain GDB backtrace.
#include<stdio.h> void func1(); void func2(); int main() { int i=10; func1(); printf("In Main(): %d\n",i); } void func1() { int n=20; printf("In func1(): %d\n",n); func2(); } void func2() { int n = 30; printf("In func2() : %d\n",n); } # cc -g stack.c
In a above code, main() will call func1() which inturn calls func2(). We will show how to examine the stack at each stage.
Getting a Backtrace in GDB
In this example, we had set a breakpoint at line number 20. So, the code stopped at func2() line 20 when we use gdb.
You can get the backtrace using ‘bt’ command as shown below.
# gdb (gdb) file ./a.out Reading symbols from /home/lakshmanan/a.out...done. (gdb) b 20 Breakpoint 1 at 0x400579: file stack.c, line 20. (gdb) run Starting program: /home/lakshmanan/./a.out In func1(): 20 Breakpoint 1, func2 () at stack.c:20 20 printf("In func2() : %d\n",n);
We already discussed how we can use GDB breakpoints to pause and continue a program execution from a particular point for debugging purpose.
From the output below, we know that currently we are in func2(), which is called by func1(), which was inturn called by main().
(gdb) bt #0 func2 () at stack.c:20 #1 0x0000000000400568 in func1 () at stack.c:15 #2 0x0000000000400525 in main () at stack.c:9
Moving from one Frame to Another
You can move between the stack frames using ‘frame [number]’ as shown below.
In the below snippet, still the func2() is not returned, but we are able to move to frame 1 (which is func1) and examine the variable n’s value which is present inside func1().
(gdb) bt #0 func2 () at stack.c:20 #1 0x0000000000400568 in func1 () at stack.c:15 #2 0x0000000000400525 in main () at stack.c:9 (gdb) p n $1 = 30 (gdb) frame 1 #1 0x0000000000400568 in func1 () at stack.c:15 15 func2(); (gdb) p n $2 = 20
In the snippet below, we have executed the next 2 instructions using ‘n 2’, and func2 is returned.
Now ‘bt’ tells you that you are currently in func1() which is called from main(), and the stack frame for func2 is gone.
(gdb) n 2 In func2() : 30 func1 () at stack.c:16 16 } (gdb) bt #0 func1 () at stack.c:16 #1 0x0000000000400525 in main () at stack.c:9
Get Information about a Stack Frame
You can get the information about a particular frame using ‘info frame [number]’ as shown below.
(gdb) info frame 0 Stack frame at 0x7fffffffe150: rip = 0x400568 in func1 (stack.c:16); saved rip 0x400525 called by frame at 0x7fffffffe170 source language c. Arglist at 0x7fffffffe140, args: Locals at 0x7fffffffe140, Previous frame's sp is 0x7fffffffe150 Saved registers: rbp at 0x7fffffffe140, rip at 0x7fffffffe148
Comments on this entry are closed.
p n shows this value instead of the value of n…. $2 = 32767 do you know why? 🙂
func2 is in line 14… not 20… whole program is 18 lines long
Why did you not show the compiler options to compile for debug? It would have helped to be able to duplicate your example.
Perhaps I could find an example from youtube. If I do, I will reference it here.,
since you covering setting breakpoint at line 20, b 20, it’s better if you add row number to your “C program code example”…thx a lot for your efforts on TGS…