Project 1: The Basics - First Steps

Build a tiny C program and use LLDB to step, inspect, and understand the call stack.

Quick Reference

Attribute Value
Difficulty Beginner
Time Estimate 1-2 hours
Language C (LLDB commands)
Prerequisites Basic C, stack frames, compiling with -g
Key Topics Breakpoints, stepping, frames, locals

1. Learning Objectives

By completing this project, you will:

  1. Set breakpoints by name and by file/line.
  2. Step through code with step, next, and finish.
  3. Inspect local variables, arguments, and the call stack.
  4. Explain how LLDB’s target/process/thread/frame hierarchy works.

2. Theoretical Foundation

2.1 Core Concepts

  • Breakpoints: Stop execution at a precise line or function.
  • Stepping: Walk execution line-by-line or function-by-function.
  • Frames: Each function call is a frame on the stack.
  • Debug symbols: -g provides source mapping and variable info.

2.2 Why This Matters

Every debugging session starts here. If you can reliably stop at the right line and read state correctly, you can solve real bugs later.

2.3 Common Misconceptions

  • “Stepping shows every machine instruction.” (It shows source-level steps, which can be grouped by the compiler.)
  • “Frames are threads.” (A thread has many frames.)

3. Project Specification

3.1 What You Will Build

A small C program with a loop and a function call that you will step through in LLDB. The goal is not the program itself, but the debugger workflow.

3.2 Functional Requirements

  1. Compile with -g -O0 and run in LLDB.
  2. Set a breakpoint at main and step into greet.
  3. Inspect the value of i at multiple points.
  4. View the call stack with bt.

3.3 Non-Functional Requirements

  • Clarity: Your notes should capture what you saw and why.
  • Repeatability: You should be able to reproduce the same session.

3.4 Example Usage / Output

(lldb) b main
(lldb) run
(lldb) frame variable
(lldb) bt

3.5 Real World Outcome

You will see a clean LLDB session that proves you understand where execution is and what state looks like:

$ clang -g -O0 -o target target.c
$ lldb ./target
(lldb) target create "./target"
Current executable set to '/path/to/target' (x86_64).
(lldb) breakpoint set --name main
Breakpoint 1: where = target`main at target.c:8, address = 0x0000000100003f70
(lldb) run
Process 4242 launched: '/path/to/target' (x86_64)
Process 4242 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100003f70 target`main at target.c:8
(lldb) thread step-over
(lldb) frame variable i
(int) i = 0
(lldb) thread step-in
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = step in
  * frame #0: 0x0000000100003f44 target`greet(count=0) at target.c:4
    frame #1: 0x0000000100003f7a target`main at target.c:9

4. Solution Architecture

4.1 High-Level Design

This project is a workflow, not an app. The architecture is the debugging loop:

Compile -> Launch -> Break -> Inspect -> Step -> Verify

4.2 Key Components

Component Responsibility Key Decisions
C program Provide deterministic execution Keep it simple and repeatable
LLDB session Control + inspect execution Use -g -O0
Debug log Capture observations Write down commands + output

4.3 Data Structures

Not applicable beyond basic C variables.

4.4 Algorithm Overview

Core Algorithm: Debugging Loop

  1. Set a breakpoint.
  2. Run to it.
  3. Inspect state.
  4. Step and re-inspect.

5. Implementation Guide

5.1 Development Environment Setup

clang -g -O0 -o target target.c
lldb ./target

5.2 Project Structure

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

5.3 The Core Question You’re Answering

“How do I freeze a running program at the exact line I care about and prove what the variables and call stack look like?”

5.4 Concepts You Must Understand First

  1. Targets, processes, and frames
    • Book: Computer Systems: A Programmer’s Perspective - Ch. 3
  2. Stack frames and backtraces
    • Book: The Art of Debugging with GDB, DDD, and Eclipse - Ch. 1-2
  3. Debug symbols (-g)
    • Book: Computer Systems: A Programmer’s Perspective - Ch. 7

5.5 Questions to Guide Your Design

  1. How do you set a breakpoint by name and by file/line?
  2. When do you use step vs next?
  3. What is the difference between frame variable and register read?

5.6 Thinking Exercise

Draw the call stack just after greet() is entered. Label each frame and the value of count.

5.7 The Interview Questions They’ll Ask

  1. What is a frame in LLDB?
  2. Why compile with -g -O0?
  3. What does a stop reason tell you?
  4. What is the difference between next and finish?

5.8 Hints in Layers

Hint 1: Use aliases

(lldb) b main
(lldb) n
(lldb) s

Hint 2: Always inspect after stepping

(lldb) n
(lldb) frame variable

Hint 3: Use the backtrace to orient

(lldb) bt

5.9 Books That Will Help

Topic Book Chapter
Debugging workflow The Art of Debugging with GDB, DDD, and Eclipse Ch. 1-2
Stack frames Computer Systems: A Programmer’s Perspective Ch. 3
Symbols Computer Systems: A Programmer’s Perspective Ch. 7

5.10 Implementation Phases

Phase 1: Setup (15-30 min)

  • Compile with -g -O0.
  • Launch LLDB and verify symbols.

Phase 2: Core Flow (30-45 min)

  • Set a breakpoint and step into the function.
  • Inspect locals and the call stack.

Phase 3: Confidence (15-30 min)

  • Repeat the session without notes.
  • Write down what each command proves.

5.11 Key Implementation Decisions

Decision Options Recommendation Rationale
Breakpoint type Name vs file:line Start with name Easier while learning
Optimization -O0 vs -O2 -O0 Preserves variables

6. Testing Strategy

6.1 Test Categories

Category Purpose Examples
Session checks Verify behavior Breakpoint hit, correct frame

6.2 Critical Test Cases

  1. Breakpoint hits main at line 8.
  2. frame variable shows i = 0 on the first loop iteration.

7. Common Pitfalls & Debugging

Pitfall Symptom Solution
Missing debug symbols Locals missing Rebuild with -g -O0
Wrong breakpoint No stop Verify with breakpoint list

8. Extensions & Challenges

Beginner Extensions

  • Add a second function and step between them.
  • Set a breakpoint by address instead of name.

Intermediate Extensions

  • Use a conditional breakpoint on i == 3.

9. Real-World Connections

  • This workflow is identical to debugging production services, just smaller.
  • These steps map directly to triaging crashes and hangs later.

10. Resources

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

11. Self-Assessment Checklist

  • I can set breakpoints and step through code.
  • I can inspect locals and the call stack.
  • I can explain the LLDB object model.

12. Submission / Completion Criteria

Minimum Viable Completion:

  • Breakpoint at main works.
  • You can print a local variable.
  • You can show a backtrace.

Full Completion:

  • You can step into and out of functions.
  • You can explain stop reasons.

Excellence (Going Above & Beyond):

  • You create a tiny command alias for your most-used command.

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