Project 5: LLDB Python Scripting
Write a Python module that adds a custom LLDB command.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Advanced |
| Time Estimate | ~1 week |
| Language | Python (LLDB SB API) |
| Prerequisites | Projects 1-4, Python basics |
| Key Topics | SB API, command scripts, automation |
1. Learning Objectives
By completing this project, you will:
- Write and import a Python module into LLDB.
- Access the target, process, thread, and frame objects.
- Register a custom LLDB command.
- Print a structured summary of the current frame.
2. Theoretical Foundation
2.1 Core Concepts
- SB API: LLDB’s object-oriented interface for scripts.
- Custom command: A Python function mapped to a command name.
- Initialization:
__lldb_init_moduleauto-load hook.
2.2 Why This Matters
Automation turns 10 manual commands into 1. It is the difference between a slow investigation and a repeatable workflow.
2.3 Common Misconceptions
- “Scripts are only for huge projects.” (Even a tiny command saves time.)
- “The SB API is too complex.” (You only need a handful of objects to start.)
3. Project Specification
3.1 What You Will Build
A Python module (myscripts.py) that adds a frame_summary command to LLDB. It prints the current function, source location, and local variables.
3.2 Functional Requirements
- The module imports without errors.
frame_summaryprints function name + file:line.- The command lists local variables with values.
- The command handles invalid frames gracefully.
3.3 Non-Functional Requirements
- Robustness: Handle missing targets or frames.
- Readability: Output should be clean and consistent.
3.4 Example Usage / Output
(lldb) command script import myscripts.py
(lldb) frame_summary
3.5 Real World Outcome
$ lldb ./target
(lldb) command script import myscripts.py
(lldb) b main
(lldb) run
(lldb) frame_summary
Function: main
Location: /path/to/target.c:8
Locals:
- i = 0
4. Solution Architecture
4.1 High-Level Design
LLDB -> Python Script -> SB API -> Custom Command Output
4.2 Key Components
| Component | Responsibility | Key Decisions |
|---|---|---|
| Python module | Implement command | Clean error handling |
| SB API objects | Access state | Target -> Process -> Thread -> Frame |
| LLDB command | User entry point | frame_summary |
5. Implementation Guide
5.1 Development Environment Setup
# Ensure LLDB has Python support
lldb
5.2 Project Structure
project-root/
|-- myscripts.py
`-- notes.md
5.3 The Core Question You’re Answering
“How can I turn repetitive inspection steps into a single LLDB command?”
5.4 Concepts You Must Understand First
- SB API object model
- Book: Building a Debugger - Ch. 1-2
- Python functions and modules
- Book: Fluent Python - Ch. 7-9
- Debugger scripting
- Book: The Art of Debugging with GDB, DDD, and Eclipse - Ch. 7
5.5 Questions to Guide Your Design
- Which SB objects do you need to reach the current frame?
- What should you do if no target is selected?
- What output format is easiest to scan under pressure?
5.6 Thinking Exercise
List the three LLDB commands you type most often. Could you replace them with one command?
5.7 The Interview Questions They’ll Ask
- What does
SBDebuggerrepresent? - How do you register a Python function as a command?
- What is
__lldb_init_moduleused for? - How do you access locals in a frame?
5.8 Hints in Layers
Hint 1: Use the standard function signature
def mycmd(debugger, command, result, internal_dict):
pass
Hint 2: Guard against invalid state
if not debugger.GetSelectedTarget():
result.SetError("Invalid target")
Hint 3: Register the command
def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand('command script add -f mymod.mycmd mycmd')
5.9 Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| Debugger internals | Building a Debugger | Ch. 1-2 |
| Python scripting | Fluent Python | Ch. 7-9 |
| Debugging mindset | The Art of Debugging with GDB, DDD, and Eclipse | Ch. 7 |
5.10 Implementation Phases
Phase 1: Minimal Command (1-2 hours)
- Print the current function name only.
Phase 2: Rich Output (2-4 hours)
- Add file:line and local variables.
Phase 3: Polish (1-2 hours)
- Handle errors and improve output formatting.
5.11 Key Implementation Decisions
| Decision | Options | Recommendation | Rationale |
|---|---|---|---|
| Output format | Plain vs structured | Structured | Faster to read |
6. Testing Strategy
6.1 Test Categories
| Category | Purpose | Examples |
|---|---|---|
| Import tests | Ensure module loads | No errors on import |
| Command tests | Validate output | Function + line shown |
6.2 Critical Test Cases
frame_summaryworks when stopped inmain.- The command handles missing targets gracefully.
7. Common Pitfalls & Debugging
| Pitfall | Symptom | Solution |
|---|---|---|
| Module not found | Import fails | Use correct path or current directory |
| Wrong function signature | Command errors | Use LLDB signature |
8. Extensions & Challenges
- Add register output to your summary.
- Add an option flag for verbose output.
9. Real-World Connections
- Teams often maintain custom LLDB command sets for their codebases.
- Scripted debugging is common in large systems and kernel work.
10. Resources
- LLDB Python Reference: https://lldb.llvm.org/use/python-reference.html
- LLDB Command Reference: https://lldb.llvm.org/use/commandref.html
11. Self-Assessment Checklist
- I can load a Python module in LLDB.
- I can access the current frame via the SB API.
- I can register a custom command.
12. Submission / Completion Criteria
Minimum Viable Completion:
- Command prints the current function name.
Full Completion:
- Command prints file, line, and local variables.
Excellence (Going Above & Beyond):
- Add a
--verboseflag and handle it in your command.
This guide was generated from LEARN_LLDB_DEEP_DIVE.md. For the full learning path, see the parent directory README.