Skip to content

Crash Dumps

Using GDB to examine Crash Dump Files

chacho-debug

1. What is GDB?

GDB (GNU Debugger) is one of the most widely used debuggers for C, C++, and Fortran programs, and it can also be used to analyze core dumps and perform memory analysis. It provides a command-line interface for inspecting program execution, understanding crashes, debugging code step by step, and analyzing memory.

It is often used on Linux, macOS, and other Unix-like systems for both debugging running programs and analyzing crash dumps.

2. Installation of GDB

Before you can use GDB, you need to ensure that it's installed on your system.

On Linux (Kali Linux, Ubuntu, etc.):

  • You can install GDB using your system's package manager:
    sudo apt-get update
    sudo apt-get install gdb
    

On macOS:

  • You can install GDB using Homebrew (a package manager for macOS):

    brew install gdb
    

  • Note: On macOS, GDB may require additional configuration for code-signing to work properly, due to Apple’s security requirements.


3. GDB Overview and Commands

GDB provides a rich set of commands to control program execution, inspect the state of the program, and analyze crashes. Below are the most commonly used commands when working with core dumps or debugging crashes.

4. Core Dump Basics

A core dump is a file that captures the memory contents of a running process at a specific point in time (usually when it crashes). The core dump can help you understand what was happening in the program at the time of the crash.

  • To generate a core dump in Linux, you can run:

    ulimit -c unlimited  # Allows the system to generate core dumps
    
    The core dump file is usually created in the current working directory with the filename core or core.[pid].

  • On macOS, core dumps are also generated when a program crashes, but you may need to enable them through system preferences.

5. Using GDB with Core Dumps

5.1 Start GDB with Core Dump

To analyze a core dump with GDB, you need two things: 1. The executable file (the program that crashed). 2. The core dump file (the memory dump generated by the crash).

To start GDB with these files:

gdb /path/to/executable /path/to/core

Example:

gdb ./my_program core

If you don’t specify the executable, GDB will attempt to load symbols from the core dump alone, but you’ll get limited information without the executable.

5.2 Inspecting Core Dump Information

Once you open the core dump in GDB, you'll be able to examine various aspects of the crash:

  • Backtrace: The backtrace (bt) command shows you the stack frames at the time of the crash, which can help you trace the function calls leading up to the crash.

    (gdb) bt
    

  • Stack Trace with Arguments: For a more detailed backtrace, you can use:

    (gdb) bt full
    
    This will show all function calls and arguments passed.

5.3 Inspecting Variables and Memory

Once inside GDB, you can inspect the values of local variables, global variables, and memory at the time of the crash.

  • Inspect Local Variables: To print the value of a local variable in the current function:

    (gdb) print variable_name
    
    Example:
    (gdb) print my_var
    

  • Inspect Memory at a Specific Address: You can also view memory at a particular address:

    (gdb) x/16xw 0xADDRESS
    
    This will examine 16 words (4 bytes each) at the memory address 0xADDRESS.

5.4 Navigating the Call Stack

You can navigate through the call stack to get a better sense of what was going on at the time of the crash.

  • Move Up or Down the Stack: You can use up and down to navigate through the stack frames.

    (gdb) up   # Move up to the previous stack frame
    (gdb) down # Move down to the next stack frame
    

  • Inspect Arguments of a Function: When you are inside a function in the stack trace, you can inspect the arguments:

    (gdb) info args
    

5.5 View Source Code

If you have the source code available, GDB can display the exact line of code where the crash occurred.

  • Display Source Code:

    (gdb) list
    
    This will display the source code surrounding the current execution point in the program.

  • Jump to a Specific Line in the Code: If you know the line number where the crash happened, you can use:

    (gdb) list 50
    
    This will show you lines 50 to 70 of the source code.

5.6 Inspecting Registers

You can inspect the CPU registers at the time of the crash, which can be useful for low-level debugging.

  • View Registers:
    (gdb) info registers
    

5.7 Checking Loaded Libraries

If the crash might be related to a specific library, you can list the libraries that are loaded into memory at the time of the crash:

  • List Loaded Libraries:
    (gdb) info sharedlibrary
    

6. Debugging a Running Program with GDB

While core dumps are useful, sometimes you want to debug a program that is actively running. Here’s how you can use GDB to debug live processes.

6.1 Attach GDB to a Running Process

You can attach GDB to a running process by specifying the PID (Process ID).

gdb -p [PID]

For example:

gdb -p 12345

Once attached, you can start issuing commands like bt, info locals, and others to inspect the running process.

6.2 Set Breakpoints

Breakpoints allow you to pause execution at specific lines or functions.

  • Set a Breakpoint at a Line of Code:

    (gdb) break filename.c:line_number
    

  • Set a Breakpoint at a Function:

    (gdb) break function_name
    

6.3 Run the Program Inside GDB

You can run a program under GDB to trace through it step by step.

  • Start Running the Program:

    (gdb) run [program_arguments]
    

  • Step Through the Program: Use step to execute one line of code at a time, stepping into functions:

    (gdb) step
    

Use next to step over functions:

(gdb) next

  • Continue Execution: If you’ve hit a breakpoint, use continue to let the program run until the next breakpoint or crash:
    (gdb) continue
    

7. Advanced GDB Techniques

  • Examine Heap or Stack Memory: If you suspect issues with memory allocation, such as a heap corruption, you can inspect heap or stack memory using the x command:

    (gdb) x/32xw [address]   # Examine 32 words at the address
    

  • Dumping Data: You can dump the contents of a register or memory to a file for later inspection:

    (gdb) dump memory /path/to/output [start_address] [end_address]
    


8. Common Troubleshooting Commands

  • Listing All Breakpoints:

    (gdb) info breakpoints
    

  • Removing a Breakpoint:

    (gdb) delete [breakpoint_number]
    

  • Examine Program State:

    (gdb) info locals       # View local variables
    (gdb) info threads      # View threads
    


9. Conclusion

GDB is a powerful tool for debugging and crash analysis on Linux and macOS. Whether you're analyzing a core dump, debugging a live program, or investigating memory issues, GDB provides a rich set of commands to inspect program state, investigate crashes, and perform advanced debugging.

To summarize: - Start GDB with the executable and core dump using

:

gdb /path/to/executable /path/to/core

  • Important Commands: bt (backtrace), print (variables), x (memory), info registers, step, continue.

  • For debugging live processes, you can attach to a running program with gdb -p [PID].