Project 2: The Crash - Crash Report Analysis

Build a tiny crashing program and learn post-mortem debugging with core files.

Quick Reference

Attribute Value
Difficulty Beginner
Time Estimate 1-2 hours
Language C (LLDB commands)
Prerequisites Project 1, stack frames, signals
Key Topics Core files, stop reasons, registers

1. Learning Objectives

By completing this project, you will:

  1. Generate a core file from a crash.
  2. Load a core file in LLDB and inspect the stop reason.
  3. Identify the faulting instruction and bad address.
  4. Trace the root cause through the call stack.

2. Theoretical Foundation

2.1 Core Concepts

  • Crash: Program terminated by a signal (SIGSEGV, SIGBUS, etc.).
  • Stop reason: LLDB’s explanation of why execution stopped.
  • Core file: A frozen snapshot of process memory at crash time.

2.2 Why This Matters

In the real world, you often debug crashes that already happened. A core file is your only window into the past.

2.3 Common Misconceptions

  • “Frame #0 is the bug.” (Often it’s only where the symptom appeared.)
  • “Core files contain everything.” (They do not include live system state.)

3. Project Specification

3.1 What You Will Build

A minimal C program that dereferences a null pointer, producing a reproducible crash.

3.2 Functional Requirements

  1. Produce a core file on crash.
  2. Load the core file into LLDB.
  3. Identify the faulting address.
  4. Confirm the root cause with variable inspection.

3.3 Non-Functional Requirements

  • Repeatability: The crash must always happen.
  • Clarity: Your notes must state the stop reason and root cause.

3.4 Example Usage / Output

ulimit -c unlimited
./crash
lldb ./crash -c core

3.5 Real World Outcome

$ clang -g -O0 -o crash crash.c
$ ulimit -c unlimited
$ ./crash
Segmentation fault (core dumped)
$ lldb ./crash -c core
(lldb) target create "./crash" --core "core"
Core file '/path/to/core' successfully loaded.
Process 5312 stopped
* thread #1, stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
    frame #0: 0x000055555555513d crash`crash_me() at crash.c:3
(lldb) bt
* thread #1, stop reason = signal SIGSEGV
  * frame #0: 0x000055555555513d crash`crash_me at crash.c:3
    frame #1: 0x0000555555555152 crash`main at crash.c:5
(lldb) register read
(lldb) frame variable p
(char *) p = 0x0000000000000000

4. Solution Architecture

4.1 High-Level Design

Crash -> Core File -> LLDB -> Stop Reason -> Root Cause

4.2 Key Components

Component Responsibility Key Decisions
Crash program Produce deterministic fault Null dereference
Core file Snapshot state Enable core dumps
LLDB session Analyze crash Inspect stop reason + stack

5. Implementation Guide

5.1 Development Environment Setup

ulimit -c unlimited
clang -g -O0 -o crash crash.c

5.2 Project Structure

project-root/
|-- crash.c
`-- notes.md

5.3 The Core Question You’re Answering

“Given a crash that already happened, how do I reconstruct what went wrong from the frozen state?”

5.4 Concepts You Must Understand First

  1. Stop reasons and signals
    • Book: The Art of Debugging with GDB, DDD, and Eclipse - Ch. 3
  2. Core files
    • Book: The Linux Programming Interface - Ch. 6
  3. Stack frames
    • Book: Computer Systems: A Programmer’s Perspective - Ch. 3

5.5 Questions to Guide Your Design

  1. How do you load a core file in LLDB?
  2. Which register holds the faulting address?
  3. How do you determine if frame #0 is the root cause?

5.6 Thinking Exercise

Predict which instruction will fault and what the stop reason will say.

5.7 The Interview Questions They’ll Ask

  1. What is a core file and when is it created?
  2. How do you identify the faulting address?
  3. Why might the crash frame be misleading?
  4. What is the difference between SIGSEGV and SIGBUS?

5.8 Hints in Layers

Hint 1: Check the stop reason

(lldb) thread info

Hint 2: Inspect registers

(lldb) register read

Hint 3: Walk the stack

(lldb) bt

5.9 Books That Will Help

Topic Book Chapter
Crash analysis The Art of Debugging with GDB, DDD, and Eclipse Ch. 3
Core files The Linux Programming Interface Ch. 6
Stack frames Computer Systems: A Programmer’s Perspective Ch. 3

5.10 Implementation Phases

Phase 1: Crash Setup (15 min)

  • Write crash program and enable core dumps.

Phase 2: Core Inspection (30-45 min)

  • Load core file and inspect stop reason.

Phase 3: Root Cause (15-30 min)

  • Confirm the bad pointer and write a short analysis.

5.11 Key Implementation Decisions

Decision Options Recommendation Rationale
Core enabling ulimit vs system config ulimit -c unlimited Fast for dev

6. Testing Strategy

6.1 Test Categories

Category Purpose Examples
Crash reproducibility Ensure core file created Crash always yields core
Debug inspection Verify stop reason SIGSEGV reported

6.2 Critical Test Cases

  1. Core file exists after crash.
  2. Stop reason indicates SIGSEGV and address 0x0.

7. Common Pitfalls & Debugging

Pitfall Symptom Solution
Core not generated No core file ulimit -c unlimited
Mismatched binary Wrong line numbers Use the exact binary that crashed

8. Extensions & Challenges

  • Trigger a SIGBUS and compare the stop reason.
  • Add a second function to deepen the backtrace.

9. Real-World Connections

  • Production crashes are often debugged only from a core file or crash report.
  • This workflow mirrors incident response in production systems.

10. Resources

  • LLDB Command Reference: https://lldb.llvm.org/use/commandref.html
  • LLDB Tutorial: https://lldb.llvm.org/use/tutorial.html

11. Self-Assessment Checklist

  • I can load a core file and read the stop reason.
  • I can identify the faulting instruction and address.
  • I can explain the root cause in one sentence.

12. Submission / Completion Criteria

Minimum Viable Completion:

  • Core file generated.
  • Stop reason identified.

Full Completion:

  • Root cause explained and written in notes.

Excellence (Going Above & Beyond):

  • Compare two crash types and document differences.

This guide was generated from LEARN_LLDB_DEEP_DIVE.md. For the full learning path, see the parent directory README.