Project 4: The Corruption - Using Watchpoints

Find the exact instruction that corrupts memory using hardware watchpoints.

Quick Reference

Attribute Value
Difficulty Intermediate
Time Estimate 2-3 hours
Language C (LLDB commands)
Prerequisites Projects 1-3, pointer arithmetic
Key Topics Watchpoints, memory inspection

1. Learning Objectives

By completing this project, you will:

  1. Set a watchpoint on a variable or address.
  2. Trigger the watchpoint and identify the exact write.
  3. Understand hardware watchpoint limits.
  4. Use watchpoint conditions to reduce noise.

2. Theoretical Foundation

2.1 Core Concepts

  • Watchpoint: Stops when memory at an address changes.
  • Hardware watchpoint: Implemented by CPU debug registers.
  • Memory corruption: Writes that change unrelated data.

2.2 Why This Matters

Watchpoints are the fastest way to catch “who wrote this” bugs. They are often the only practical way to find memory corruption in complex code.

2.3 Common Misconceptions

  • “Watchpoints are unlimited.” (CPU hardware limits them.)
  • “They always work on optimized code.” (Optimizations can move or eliminate variables.)

3. Project Specification

3.1 What You Will Build

A small program with an off-by-one write that corrupts adjacent memory. You will use a watchpoint to stop exactly at the write.

3.2 Functional Requirements

  1. Create a corruption bug.
  2. Set a watchpoint on the corrupted variable.
  3. Run until the watchpoint triggers.
  4. Identify the instruction that caused the corruption.

3.3 Non-Functional Requirements

  • Precision: Watchpoint triggers on the correct write.
  • Clarity: Notes include the offending line and why it corrupts.

3.4 Example Usage / Output

(lldb) watchpoint set variable local_value
(lldb) continue

3.5 Real World Outcome

$ clang -g -O0 -o corrupt corrupt.c
$ lldb ./corrupt
(lldb) b main
(lldb) run
(lldb) watchpoint set variable local_value
Watchpoint created: Watchpoint 1: addr = 0x7ffeefbff5ec size = 4
(lldb) continue
Process 7777 resuming
Watchpoint 1 hit:
old value: 200
new value: 0
* thread #1, stop reason = watchpoint 1
    frame #0: 0x0000000100003f48 corrupt`buggy_function at corrupt.c:5

4. Solution Architecture

4.1 High-Level Design

Corruption -> Watchpoint -> Trigger -> Offending Instruction

4.2 Key Components

Component Responsibility Key Decisions
Corrupting program Produce off-by-one write Simple pointer arithmetic
Watchpoint Detect write Variable vs address
LLDB analysis Identify culprit Backtrace + frame

5. Implementation Guide

5.1 Development Environment Setup

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

5.2 Project Structure

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

5.3 The Core Question You’re Answering

“Who changed this memory, and what exact line caused it?”

5.4 Concepts You Must Understand First

  1. Pointer arithmetic
    • Book: Understanding and Using C Pointers - Ch. 1-3
  2. Stack vs global memory
    • Book: Computer Systems: A Programmer’s Perspective - Ch. 3
  3. Watchpoints
    • Book: The Art of Debugging with GDB, DDD, and Eclipse - Ch. 5

5.5 Questions to Guide Your Design

  1. Which variable should you watch and why?
  2. How do you confirm the address being watched?
  3. How would you add a condition to only stop on specific values?

5.6 Thinking Exercise

Draw the memory layout around global_value and local_value. Predict where the bad write lands.

5.7 The Interview Questions They’ll Ask

  1. How are watchpoints implemented in hardware?
  2. What is the difference between a read and a write watchpoint?
  3. Why might a watchpoint fail to trigger?
  4. How many watchpoints can your CPU support?

5.8 Hints in Layers

Hint 1: Watch the corrupted variable

(lldb) watchpoint set variable local_value

Hint 2: Inspect the address

(lldb) frame variable &local_value

Hint 3: Add a condition

(lldb) watchpoint modify -c 'new_val == 0'

5.9 Books That Will Help

Topic Book Chapter
Pointer arithmetic Understanding and Using C Pointers Ch. 1-3
Memory layout Computer Systems: A Programmer’s Perspective Ch. 3
Watchpoints The Art of Debugging with GDB, DDD, and Eclipse Ch. 5

5.10 Implementation Phases

Phase 1: Setup (30 min)

  • Build the corrupt program and reproduce the issue.

Phase 2: Watchpoint (60 min)

  • Set a watchpoint and trigger it.

Phase 3: Diagnosis (30 min)

  • Explain the off-by-one bug and fix it.

5.11 Key Implementation Decisions

Decision Options Recommendation Rationale
Watchpoint target Variable vs address Variable Clearer for beginners

6. Testing Strategy

6.1 Test Categories

Category Purpose Examples
Watchpoint trigger Ensure it fires Old/new value reported

6.2 Critical Test Cases

  1. Watchpoint triggers on the corrupted write.
  2. Backtrace points to buggy_function.

7. Common Pitfalls & Debugging

Pitfall Symptom Solution
Watchpoint never hits No stop Rebuild with -O0, verify address
Too many watchpoints Error or missing triggers Delete unused watchpoints

8. Extensions & Challenges

  • Use a conditional watchpoint to stop only on certain values.
  • Corrupt memory inside a loop and confirm multiple triggers.

9. Real-World Connections

  • Memory corruption bugs in C/C++ are common in systems code.
  • Watchpoints are a core technique used in security debugging.

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 set and trigger a watchpoint.
  • I can explain why the write is corrupting memory.
  • I can reduce watchpoint noise with conditions.

12. Submission / Completion Criteria

Minimum Viable Completion:

  • Watchpoint triggers and shows the offending line.

Full Completion:

  • You can explain the memory layout and fix the bug.

Excellence (Going Above & Beyond):

  • You create a watchpoint on a raw address.

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