Debugging Segmentation Faults using GEF and GDB

This tutorial will give you some help debugging segmentation faults in GDB using GEF.

This assumes:

  1. You are using your a Raspberry Pi
  2. 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.

  1. 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
    
  2. Load the file in gdb

    gdb ./segfault
    
  3. 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:

  1. Edit the file .gef.rc in your home directory (nano ~/.gef.rc).
  2. Look for the line that starts with layout
  3. Put a minus sign (-) in front of the word code on that line (It should look like: "-trace stack -memory regs code source".
  4. Save and quit your editor (^X in nano)
  5. Load the program in GDB and cause the segfault.

If GDB still crashes, you can disable all of the context view.

  1. Edit the same .gef.rc file.
  2. Look for the enable = True line and change it to enable = False
  3. 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:

  1. Look at the comment GEF added above the current line. It shows you the value of P.
  2. 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:

  1. type up and hit enter. (This climbs "up" the call stack to whatever called the current function).
  2. type context and hit enter to get registers and code information.
  3. To continue moving up the call stack, type up and hit enter again. To go back down, use down.

(To see the entire call stack, type "backtrace" and hit enter.)