Chasing Invisible Code: Exploring Breakpoints in LLDB
· 3 min read
I used to think breakpoints were… boring.
You drop one on a line, run the app, execution pauses, you inspect stuff, move on. That was the entire mental model.
But then I stumbled into something weird: what if the code you want to observe isn’t yours?
Like deep inside UIKit. Or buried in some framework. Or triggered indirectly where you don’t even know which line to put a breakpoint on.
That’s when LLDB started feeling less like a debugger… and more like a search engine for running code.
The Moment It Clicked#
I was trying to understand when viewDidLoad actually fires across different view controllers.
Not just mine. All of them.
And I realized: I don’t care about lines of code. I care about a function being called.
That’s where symbolic breakpoints come in.
Instead of saying “pause here,” you say:
“Pause whenever this thing is called.”
For example: -[UIViewController viewDidLoad]
That’s a symbol. And LLDB can hook into it.
More on symbolic breakpoints in Xcode.
Hunting for Symbols#
Before setting a breakpoint, you sometimes need to confirm the symbol exists.
LLDB gives you a way to search for it:
The -n flag tells LLDB to look for a function or symbol by name.
This command basically answers:
“Hey LLDB, where does this thing live in memory?”
Once you know it exists, you’re ready to trap it.
Setting Your First Symbolic Breakpoint#
The simplest form:
And just like that, your app will pause every time any view controller loads.
Not just yours. Everything.
That’s when it starts to feel powerful… and slightly dangerous.
When Typing Gets Annoying: Regex Breakpoints#
Typing full symbol names can get painful pretty quickly.
Imagine something like:
Yeah… no thanks.
This is where regex breakpoints feel like cheating.
Instead, you can do:
Or go even broader:
Now LLDB will stop at anything matching that pattern.
It’s like saying:
“I don’t know exactly what I’m looking for, but I’ll know it when I see it.”
Going Wide: Breakpoint Scope#
Then I discovered you don’t even have to target a specific function.
You can target an entire file:
This sets breakpoints on:
- getters and setters
- functions and methods
- closures and blocks
Basically everything in that file.
Or even a whole framework:
Now you’re stepping into Apple’s world.
You can also filter by language:
Or something more experimental:
That last one blew my mind a bit.
It pauses execution anywhere "if let" appears.
Not always practical… but definitely fun to try.
Breakpoints That Do Things#
Then comes the part that made me pause for a second.
Breakpoints don’t just stop execution. They can run commands.
For example:
Let’s unpack that:
-n→ target function-C→ command to executepo $arg1→ print the first argument (the view controller instance)-G1→ continue execution automatically
So now, instead of stopping, it logs every viewDidLoad call and keeps going.
You’ve basically turned a breakpoint into a logging system.
And without touching your code.
Cleaning Up#
At some point, things get messy.
Too many breakpoints, too many triggers, too much chaos.
Thankfully:
Clean slate.
