GNU debugger
DS2040, Satyajit Das
February 6, 2025
1 GDB Debugging Tutorial
1.1 Overview
The GNU Debugger (GDB) is a portable debugger that runs on many Unix-like systems and works
for many programming languages, including Ada, Assembly, C, C++, D, Fortran, Haskell, Go,
Objective-C, OpenCL C, Modula-2, Pascal, Rust, and partially others. (Wikipedia).
For quick reference, please refer to https://users.ece.utexas.edu/ adnan/gdb-refcard.pdf
1.2 Part A: Basic GDB Usage
Hello GDB Example
// hello . c
# include < stdio .h >
int main () {
printf ( " Hello , GDB !\ n " ) ;
return 0;
}
Compile and Run in GDB:
gcc -g -o hello hello . c
gdb ./ hello
Commands
• run, break main, info breakpoints, delete <n>, continue
1.3 Part B: Debugging Pointers
pointer_bug.c
# include < stdio .h >
# include < stdlib .h >
int main () {
int * p = NULL ;
int x = 10;
p = &x; // correct pointer assignment
// Uncomment to see bug scenarios :
1
// p = NULL ;
// p = ( int *) 0 x1234 ;
printf ( " Value of * p is : % d \ n " , * p ) ;
return 0;
}
• gdb ./pointer_bug
• Break at main, step, print p, print *p
• Uncomment lines to cause segfault, use backtrace to see crash.
1.4 Part C: Debugging Arrays and Loops
array_loop.c
# include < stdio .h >
int main () {
int arr [5] = {1 , 2 , 3 , 4 , 5};
int sum = 0;
int i ;
for ( i = 0; i < 5; i ++) {
sum += arr [ i ];
}
printf ( " Sum is : % d \ n " , sum ) ;
return 0;
}
• Compile with -g, run in GDB
• break array_loop.c:10, step, inspect i, sum.
• Change loop to i <= 5 to force out-of-bounds.
1.5 Part D: Debugging Function Calls
multi_func.c
# include < stdio .h >
int multiply ( int a , int b ) {
return a * b ;
}
int sum_of_products ( int x , int y ) {
// Suppose there ’s a logic bug
return multiply (x , y ) + multiply (x , 2) ;
}
int main () {
int m = multiply (3 , 4) ;
printf ( " 3 * 4 = % d \ n " , m ) ;
2
int s = sum_of_products (2 , 5) ;
printf ( " sum_of_products (2 , 5) = % d \ n " , s ) ;
return 0;
}
• Break in main, step into multiply, check info args.
• backtrace to see call chain, finish to exit current function.
1.6 Bonus: Watchpoints & Advanced Features
• watch sum to break when sum changes.
• Conditional breakpoints: break array_loop.c:10 if i == 3.
• Examine memory: x/8w &arr.
1.7 Wrap-Up
• step, next, finish, backtrace, info locals, info args.
• Practice with real bugs, valgrind if memory issues suspected.
2 Debugging Stack Frames, Function Calls, Arguments, Returns
2.1 Overview
• Focus on stack frames, function call mechanics, arguments, return values.
• Demonstrates how to examine them in GDB.
2.2 Example 1: Basic Function Call / Return
basic_call.c
# include < stdio .h >
// multiply two numbers
int multiply ( int a , int b ) {
int result = a * b ;
return result ;
}
// calls multiply multiple times
int do_calculations ( int x ) {
int val1 = multiply (x , x + 1) ;
int val2 = multiply ( x + 2 , x + 3) ;
int sum = val1 + val2 ;
return sum ;
}
int main () {
int input = 3;
3
int output = do_calculations ( input ) ;
printf ( " Final result = % d \ n " , output ) ;
return 0;
}
• Break in main, step into do_calculations.
• info args, info locals, watch how %rax is used for returns.
• backtrace to see call hierarchy.
2.3 Example 2: Recursion and the Stack (factorial)
factorial.c
# include < stdio .h >
long factorial ( int n ) {
if ( n <= 1) {
return 1;
} else {
return n * factorial ( n - 1) ;
}
}
int main () {
int val = 5;
long fact = factorial ( val ) ;
printf ( " factorial (% d ) = % ld \ n " , val , fact ) ;
return 0;
}
• Multiple stack frames from recursion.
• break factorial, run, then backtrace.
• frame <n> or up/down to move among frames.
2.4 Example 3: Stack Corruption Demo
stack_corruption.c
# include < stdio .h >
# include < string .h >
void copy_data ( char * dest , const char * src , int size ) {
// ignoring bounds for demonstration
strcpy ( dest , src ) ; // potential overflow
}
int main () {
char buffer [8] = " OK " ;
int secret_value = 123;
printf ( " secret_value = % d \ n " , secret_value ) ;
4
// Overwrite the buffer with a bigger string
copy_data ( buffer , " AAAAAAAAAAAAAAAAAAAA " , 20) ;
// Did secret_value change ?
printf ( " secret_value ( after ) = % d \ n " , secret_value ) ;
return 0;
}
• Run in GDB, step into copy_data, watch memory near buffer.
• x/32bx &buffer, compare with &secret_value.
2.5 Wrap-Up
• Understand how stack frames store local vars, arguments, return address.
• GDB commands: info frame, info registers, disassemble /m.
• Navigating frames: bt, frame <n>, up, down.