Debugging Segmentation Faults using GEF and GDB
This tutorial will give you some help debugging segmentation faults in GDB using GEF.
This assumes:
- You are using your a Raspberry Pi
- You ran the GDB setup script provided in CSSE 132.
Step 1: Cause the segfault inside GDB
An example segfault-causing file can be found here.
Be sure you compiled with debugging enabled (
-g
flag should be part of the gcc line). To compile the example:gcc -g -o segfault segfault.c
Load the file in gdb
gdb ./segfault
Make the code cause the segfault. For the sample code, just type "run" and hit enter at the GDB prompt:
gef➤ run
Your program should halt when the segmentation fault occurs:
gef➤ run Starting program: /home/pi/segfault Program received signal SIGSEGV, Segmentation fault. ──────────────────────────────────────────────────────────────────[ source:segfault.c+6 ]──── 3 4 void fillPointer(char* p) 5 { // p=0x7efff1a4 → 0x00000000 → 6 *p = 'A'; 7 } 8 9 int main(void) ───────────────────────────────────────────────────────────────────────────────────────────── 0x00010420 in fillPointer (p=0x0) at segfault.c:6 6 *p = 'A'; gef➤
If GDB crashes/exits
Sometimes GDB will exit/crash when it tries to show you segmentation fault context. If GDB exits, you may need to disable the assembly view. To do this:
- Edit the file .gef.rc in your home directory (
nano ~/.gef.rc
). - Look for the line that starts with
layout
- Put a minus sign (
-
) in front of the wordcode
on that line (It should look like: "-trace stack -memory regs code source
". - Save and quit your editor (
^X
in nano) - Load the program in GDB and cause the segfault.
If GDB still crashes, you can disable all of the context view.
- Edit the same
.gef.rc
file. - Look for the
enable = True
line and change it toenable = False
- Try again.
Step 2: Find the function call that caused the problem
If GDB stopped at a place where you have source code, look at the line of code that's highlighted
Program received signal SIGSEGV, Segmentation fault. ──────────────────────────────────────────────────────────────────[ source:segfault.c+6 ]──── 3 4 void fillPointer(char* p) 5 { // p=0x7efff1a4 → 0x00000000 → 6 *p = 'A'; 7 } 8 9 int main(void) ─────────────────────────────────────────────────────────────────────────────────────────────
In this example, the segmentation fault occurred on line 6 of segfault.c. This is in the fillPointer
function.
Step 3: Inspect variables and values until you find a bad pointer or typo
In the example above, it's pretty clear that something is wrong with the use of p
. You have a few ways to figure out what's wrong:
- Look at the comment GEF added above the current line. It shows you the value of P.
- Try printing some variables (
print *p
). Look carefully at the current line highlighted inside GDB.
If you want to see what called the current function:
- type
up
and hit enter. (This climbs "up" the call stack to whatever called the current function). - type
context
and hit enter to get registers and code information. - To continue moving up the call stack, type
up
and hit enter again. To go back down, usedown
.
(To see the entire call stack, type "backtrace" and hit enter.)