Project 2: The Crash - Core Dump Analysis
Build a crashing C program and perform a post-mortem GDB analysis with a core file.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Beginner |
| Time Estimate | 1-2 hours |
| Language | GDB commands (C target) |
| Prerequisites | Project 1, basic pointers |
| Key Topics | SIGSEGV, core dumps, backtrace, memory inspection |
1. Learning Objectives
By completing this project, you will:
- Enable and locate core dumps on your system.
- Load a core dump into GDB and identify the crash site.
- Inspect registers, locals, and memory at the moment of failure.
- Explain the root cause of a crash without re-running the program.
2. Theoretical Foundation
2.1 Core Concepts
- Signals and SIGSEGV: A segmentation fault occurs when a process accesses invalid memory; the kernel delivers SIGSEGV and may write a core file.
- Core Files: A snapshot of memory, registers, and process state at the time of the crash.
- Post-mortem Debugging: You analyze a frozen state, not a running process.
2.2 Why This Matters
Many production crashes are non-reproducible. Core files are often the only evidence you get. Learning to read them is a real-world debugging superpower.
2.3 Historical Context / Background
Core dumps have existed since early Unix to help developers diagnose fatal errors after the fact. Modern systems can route them to custom paths or crash-reporting services.
2.4 Common Misconceptions
- “Core dumps are optional”: They are essential for post-mortem debugging.
- “You need a live process”: Core files contain enough information to pinpoint the crash.
3. Project Specification
3.1 What You Will Build
A minimal C program that dereferences a NULL pointer. You will capture a core dump and analyze it in GDB.
3.2 Functional Requirements
- Enable core dumps for the shell session.
- Reproduce a SIGSEGV and capture a core file.
- Use
backtrace,frame, andprintto identify the root cause.
3.3 Non-Functional Requirements
- Performance: Not relevant.
- Reliability: Crash should reproduce consistently.
- Usability: Core file should be easy to locate.
3.4 Example Usage / Output
$ ulimit -c unlimited
$ ./crash
Segmentation fault (core dumped)
$ gdb ./crash core
(gdb) backtrace
3.5 Real World Outcome
You should see a clear GDB report of the faulting line and variable state:
$ gcc -g -O0 -o crash crash.c
$ ulimit -c unlimited
$ ./crash
Segmentation fault (core dumped)
$ gdb ./crash core
GNU gdb (GDB) 14.1
Core was generated by './crash'.
Program terminated with signal SIGSEGV, Segmentation fault.
(gdb) backtrace
#0 crash_me () at crash.c:5
#1 main () at crash.c:9
(gdb) frame 0
5 *p = 'A';
(gdb) print p
$1 = (char *) 0x0
4. Solution Architecture
4.1 High-Level Design
┌────────────┐ ┌──────────────┐ ┌──────────────┐
│ crash.c │────▶│ core file │────▶│ gdb session │
└────────────┘ └──────────────┘ └──────────────┘
4.2 Key Components
| Component | Responsibility | Key Decisions |
|---|---|---|
| Crashing target | Produce deterministic SIGSEGV | Keep code minimal |
| Core file | Snapshot crash state | Ensure ulimit allows it |
| GDB session | Analyze snapshot | Use backtrace + locals |
4.3 Data Structures
struct CoreFindings {
const char *function;
int line;
void *fault_addr;
};
4.4 Algorithm Overview
Key Algorithm: Post-mortem analysis loop
- Load core file with matching binary.
- Identify faulting frame.
- Inspect variables and registers.
Complexity Analysis:
- Time: O(F) for number of frames inspected.
- Space: O(1) within the debugger.
5. Implementation Guide
5.1 Development Environment Setup
ulimit -c unlimited
5.2 Project Structure
project-root/
├── crash.c
├── crash
└── core (generated)
5.3 The Core Question You’re Answering
“How do I debug a crash that happened when I was not watching?”
5.4 Concepts You Must Understand First
Stop and research these before coding:
- SIGSEGV
- What causes it?
- How does the kernel report it?
- Core dump generation
ulimit -candcore_pattern- Where core files are stored
- Pointer basics
- NULL vs garbage pointers
- Dereference behavior
5.5 Questions to Guide Your Design
- How do you confirm you are using the exact binary that produced the core?
- Which frame tells you the most about the crash?
- What does the faulting address indicate (NULL vs non-NULL)?
5.6 Thinking Exercise
If the backtrace shows malloc as the top frame, list three possible causes that are not a NULL pointer.
5.7 The Interview Questions They’ll Ask
- How do you load a core file in GDB?
- What does the top frame in a backtrace represent?
- Why might a core file be missing?
5.8 Hints in Layers
Hint 1: Enable core
ulimit -c unlimited
Hint 2: Load core
gdb ./crash core
Hint 3: Inspect
backtrace,frame 0,print p
5.9 Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| Core dumps | TLPI | Ch. 23 |
| Signals | TLPI | Ch. 20 |
| Debugging | “The Art of Debugging with GDB” | Ch. 4-5 |
5.10 Implementation Phases
Phase 1: Foundation (30 minutes)
Goals:
- Generate a core dump.
Tasks:
- Compile
crash.cwith symbols. - Run the binary and confirm core file exists.
Checkpoint: Core file created in expected location.
Phase 2: Core Functionality (30 minutes)
Goals:
- Analyze the crash.
Tasks:
- Load core file in GDB.
- Run
backtraceand inspectframe 0.
Checkpoint: Identify exact crashing line.
Phase 3: Polish & Edge Cases (20 minutes)
Goals:
- Inspect memory and registers.
Tasks:
- Use
info registersandx/10x $rsp. - Explain why the crash occurred.
Checkpoint: Clear root-cause explanation.
5.11 Key Implementation Decisions
| Decision | Options | Recommendation | Rationale |
|---|---|---|---|
| Core file location | cwd or system path | cwd | Easier to find |
| Optimization level | -O0 vs -O2 |
-O0 |
Clearer variable info |
6. Testing Strategy
6.1 Test Categories
| Category | Purpose | Examples |
|---|---|---|
| Setup | Verify core generation | ulimit -c reports unlimited |
| Analysis | Confirm GDB reads core | backtrace shows source lines |
| Root cause | Validate pointer value | print p is NULL |
6.2 Critical Test Cases
- Core file exists after crash.
- Backtrace points to
crash_me(). - Pointer inspection shows
0x0.
6.3 Test Data
NULL dereference in crash.c
7. Common Pitfalls & Debugging
7.1 Frequent Mistakes
| Pitfall | Symptom | Solution |
|---|---|---|
| Core not generated | No core file |
Set ulimit -c unlimited |
| Wrong binary | Line numbers wrong | Rebuild and rerun |
| Stripped symbols | Only addresses shown | Compile with -g |
7.2 Debugging Strategies
- Compare build timestamp with core generation time.
- Use
info filesto confirm symbol loading.
7.3 Performance Traps
Not applicable here.
8. Extensions & Challenges
8.1 Beginner Extensions
- Trigger a crash via stack overflow.
- Use
info registersto interpretrip.
8.2 Intermediate Extensions
- Analyze a core from an optimized build.
- Inspect memory around the faulting address.
8.3 Advanced Extensions
- Configure
core_patternto route core files. - Practice with a multi-threaded crash.
9. Real-World Connections
9.1 Industry Applications
- Production incidents: Core dumps are often required for root-cause analysis.
- Security: Core analysis can reveal exploit paths and corrupted states.
9.2 Related Open Source Projects
- coredumpctl (systemd) - manages core files on Linux.
- gdb - primary tool for inspection.
9.3 Interview Relevance
- Shows you can debug crashes without reproduction.
- Demonstrates understanding of signals and memory errors.
10. Resources
10.1 Essential Reading
- “The Linux Programming Interface” - Signals and core dumps.
- GDB Manual - “Debugging Programs”.
10.2 Video Resources
- Search: “GDB core dump analysis”.
10.3 Tools & Documentation
- GDB: https://sourceware.org/gdb/
- man 5 core: Format details.
10.4 Related Projects in This Series
11. Self-Assessment Checklist
11.1 Understanding
- I can explain why SIGSEGV happens.
- I can load a core and read a backtrace.
- I can interpret a faulting address.
11.2 Implementation
- I generated a core file successfully.
- I found the crashing line.
- I explained the root cause.
11.3 Growth
- I can debug a crash from a production core.
12. Submission / Completion Criteria
Minimum Viable Completion:
- Generate a core file and locate the crashing line in GDB.
Full Completion:
- Inspect registers and memory to explain the crash mechanism.
Excellence (Going Above & Beyond):
- Analyze a crash in optimized code or multi-threaded code.
This guide was generated from LEARN_GDB_DEEP_DIVE.md. For the complete learning path, see the parent directory README.