LLDB (Low-Level Debugger) — een debugger van de nieuwe generatie van het LLVM-project, onderdeel van Xcode voor het debuggen van applicaties voor iOS, macOS, tvOS en watchOS. In tegenstelling tot GDB gebruikt LLDB een modulaire architectuur met LLVM-compiler, wat zorgt voor hoge snelheid en nauwkeurigheid. Volgens LLVM Project ondersteunt LLDB het debuggen in C, Objective-C, C++ en Swift met een volledige reeks functies: breakpoints, watchpoints, geheugeninspectie en stapsgewijze uitvoering.
Belangrijkste punten
LLDB — is een debugger met open source, gebouwd op de bibliotheken van het LLVM-project. Het verving GDB in Xcode 5 en is sindsdien het belangrijkste debug-instrument voor het gehele Apple-ecosysteem. In tegenstelling tot monolithische GDB is LLDB geïmplementeerd als een set samenwerkende bibliotheken: elke functie — van het parseren van expressies tot het werken met geheugen — is ondergebracht in een aparte module, wat onderhoud en uitbreiding vereenvoudigt.
De belangrijkste mogelijkheden van LLDB omvatten: het instellen van breakpoints van elk type, watchpoints voor het volgen van variabelewijzigingen, inspectie van geheugen en registers, stapsgewijze uitvoering, evaluatie van willekeurige expressies in de context van een gestopt programma en uitvoering van Python-scripts voor automatisering. Volgens de LLVM-repository ondersteunt LLDB meer dan 200 debug-commando's en is het compatibel met DWARF en Mach-O — de belangrijkste formaten voor debuginformatie in het Apple-ecosysteem.
Een belangrijk voordeel van LLDB is de diepe integratie met Clang. Door het gebruik van dezelfde compiler voor het parseren en compileren van broncode, kan LLDB C++ en Objective-C-expressies evalueren met een nauwkeurigheid die niet beschikbaar is voor GDB. Voor Swift-debugging gebruikt LLDB een aparte module Swift Language Runtime, die de semantiek van de taal begrijpt: optionele typen, protocollen, generics en geheugenbeheer via ARC.
De eerste versie van LLDB verscheen in 2010 als onderdeel van LLVM 2.8. In 2013 verving het GDB volledig in Xcode. In 2019 met de release van Xcode 11 kreeg LLDB ondersteuning voor Swift Error Breakpoints en een verbeterde expressieparser voor Swift. Volgens Apple werkt vanaf iOS 14 de volledige debug-stack voor de simulator ook via LLDB, wat de status als primair debug-instrument van het platform bevestigt.
LLDB architectuur is gebouwd volgens het microservices-principe: elk subsysteem bestaat als een aparte bibliotheek (dylib), verbonden met andere via een gemeenschappelijke API. Dit onderscheidt het van GDB, waar alle functies in één binair bestand zijn samengevoegd. De modulaire structuur maakt onafhankelijk gebruik van LLDB-componenten mogelijk — bijvoorbeeld, de expressieparser kan in een IDE worden ingebouwd zonder de volledige debugger aan te sluiten.
| LLDB component | Doel | Bibliotheek |
|---|---|---|
| Core | Beheer van het debugproces, gebeurtenissen, thread-statussen | liblldbCore.dylib |
| Expression Parser | Parser en uitvoering van expressies (C/C++/ObjC/Swift) | liblldbExpression.dylib |
| Symbol File | Lezen van DWARF, Mach-O, dSYM — werken met debuginformatie | liblldbSymbol.dylib |
| Target Control | Beheer van uitvoering: starten, stoppen, stappen | liblldbTarget.dylib |
| Interpreter | Commandoregel en REPL-modus | liblldbInterpreter.dylib |
dSYM — zijn bestanden met debuginformatie die Xcode genereert tijdens het compileren. LLDB gebruikt ze om machinecode te koppelen aan broncode: zonder dSYM toont de debugger alleen geheugenadressen in plaats van functienamen en coderegels. Voor App Store-applicaties worden dSYM-bestanden apart geüpload naar de Apple-server en gebruikt voor symbolisatie van crash-logs die via CrashReporter van gebruikers zijn ontvangen.
(lldb) target create MyApp.app
(lldb) image list MyApp
MyApp - "/path/to/MyApp.app/MyApp" (arm64)
(lldb) image lookup -n fetchUserData
Address: MyApp[0x1000a3b40] (MyApp.__TEXT.__text + 12352)
Summary: `ViewController.fetchUserData()` at ViewController.swift:42
LLDB commando's zijn onderverdeeld in verschillende categorieën: uitvoeringsbeheer, werken met breakpoints, data-inspectie en geheugenmanipulatie. In tegenstelling tot de Xcode GUI biedt de LLDB-console volledige controle over het debuggen en maakt het uitvoeren van bewerkingen mogelijk die niet beschikbaar zijn via de grafische interface — bijvoorbeeld het wijzigen van een variabelewaarde ter plekke of het bulksgewijs bewerken van breakpoints.
Continue, Step Over, Step Into, Step Out — de basis van de debug-cyclus. continue hervat de uitvoering tot het volgende breakpoint. step over voert de huidige regel volledig uit. step into gaat in de aangeroepen methode. step out beëindigt de huidige functie en geeft de controle terug aan de aanroepende code. Daarnaast bestaat step with type filter — stap tot een gespecificeerd gegevenstype.
(lldb) thread backtrace # Callstack tonen
* thread #1, queue = 'com.apple.main-thread'
frame #0: 0x1000a3b40 ViewController`fetchUserData()
frame #1: 0x1000a2000 ViewController`viewDidLoad()
frame #2: 0x1a2b345 UIKit`UIViewController.loadView()
(lldb) frame variable # Lokale variabelen tonen
(Int) userId = 42
(String) endpoint = "https://api.example.com/user/42"
(lldb) thread step-over # Step Over
(lldb) thread step-in # Step Into
LLDB biedt commando's voor het bekijken van gegevens in elk formaat: memory read, frame variable, target variable. Speciale syntax po (print object) roept debugDescription aan voor Objective-C-objecten en description voor Swift-typen. Aangepaste formatters worden ingesteld via type summary add — handig voor het debuggen van complexe structuren zoals CGRect of IndexPath.
(lldb) po userProfile # Objectbeschrijving weergeven
<UserProfile: 0x600000c4b80>
- name: "John"
- age: 30
- email: "john@example.com"
(lldb) expression userProfile.age = 31 # Waarde wijzigen
(Int) $R0 = 31
(lldb) memory read 0x600000c4b80 0x600000c4bc0
0x600000c4b80: 6a 6f 68 6e 00 00 00 00 1e 00 00 00 00 00 00 00
Expressies evalueren in LLDB is een van de krachtigste functies die ontbrak in GDB tijdens zijn dominantie. LLDB kan willekeurige code uitvoeren in C, Objective-C, C++ en Swift in de context van een gestopt programma, inclusief het aanroepen van methodes, het maken van objecten en het wijzigen van de status. Dit maakt het mogelijk hypotheses te testen zonder de applicatie opnieuw te starten en te hercompileren.
Het commando expression compileert en voert een expressie uit tijdens de runtime van het gedebugde proces. De vlag -O (object description) roept po aan. Voor meerregelige expressies gebruikt u expression -l Swift --. LLDB compileert code ter plekke via Clang of Swift Compiler, integreert het resultaat in de huidige context en retourneert de waarde. Volgens Apple wordt een expressie gecompileerd in 10–50 ms, afhankelijk van de complexiteit.
(lldb) expr -l Swift -- UIAlertController(title: "Test", message: nil,
preferredStyle: .alert)
(lldb) expr let $arr = [1, 2, 3].map { $0 * 2 }
(lldb) po $arr
▿ 3 elements
- 0 : 2
- 1 : 4
- 2 : 6
LLDB maakt het niet alleen mogelijk om te lezen, maar ook om de status van objecten en variabelen te wijzigen tijdens het debuggen. Dit is essentieel voor het testen van randgevallen: u kunt de waarde van een variabele op nil zetten, de kleur van een UI-element wijzigen of het serverantwoord direct in de debugger vervangen, zonder hercompileren en opnieuw opstarten. Deze techniek wordt veel gebruikt bij de ontwikkeling van games en applicaties met lange workflows, waar opnieuw opstarten veel tijd kost.
(lldb) expr self.label.text = @"Updated"
(lldb) expr -l Swift -- (self as! UIViewController).view.backgroundColor = .red
(lldb) expr let $snapshot = self.view.debugQuickLookObject()
Python API van LLDB maakt het mogelijk scripts te schrijven voor het automatiseren van debugging. Via Python kunnen aangepaste commando's worden gemaakt, breakpoint-gebeurtenissen worden afgehandeld, rapporten worden gegenereerd en zelfs het gedrag van de debugger worden overschreven. De ingebouwde Python 3-interpreter start direct in LLDB en heeft via de module lldb toegang tot de volledige debug-API.
Een nieuw LLDB-commando kan worden geregistreerd via de decorator @classmethod in een Python-script. Na het importeren van het script is het commando beschikbaar als een ingebouwd commando. Bijvoorbeeld, het commando printvars kan alle variabelen van het huidige frame weergeven met hun typen en waarden, geformatteerd voor een specifiek project. Automatisering vermindert de tijd van typische debug-bewerkingen met 60–80%, volgens een enquête onder iOS-ontwikkelaars op Stack Overflow.
import lldb
class PrintVarsCommand:
@classmethod
def register_class(cls, debugger, _):
handler = PrintVarsCommand()
debugger.HandleCommand('command script add -c \
print_vars.PrintVarsCommand printvars')
def __call__(self, debugger, command, exe_ctx, result):
frame = exe_ctx.frame
for var in frame.variables:
result.AppendMessage(f"{var.name}: {var.type} = {var.value}")
Via Python API kan een script worden gekoppeld aan het activeren van een breakpoint. Stel een breakpoint in, voer vervolgens breakpoint command add uit en geef een Python-functie op. Dit maakt het mogelijk automatisch de status te loggen, gegevens naar analytics te sturen of invarianten te controleren zonder handmatige interventie. Volgens LLVM wordt deze aanpak gebruikt in de infrastructuur van Apple voor het verzamelen van prestatiemetingen tijdens de ontwikkelingsfase.
(lldb) breakpoint set -f Model.swift -l 100
(lldb) breakpoint command add 1 -s python -o "frame = exe_ctx.frame;
print([var.name for var in frame.variables])"
REPL (Read-Eval-Print Loop) — de interactieve modus van LLDB, opgeroepen met het commando lldb --repl of via de Xcode Debug Console. In REPL kan code in Swift of C worden uitgevoerd zoals in een playground, met directe feedback. LLDB compileert elke regel, voert deze uit en toont het resultaat — handig voor het experimenteren met API's, het prototypen van algoritmen en het leren van nieuwe taalfuncties zonder een project aan te maken.
(lldb) --repl
1> let numbers = [1, 2, 3, 4, 5]
2> numbers.filter { $0 % 2 == 0 }
$R0: [Int] = 2 values {
[0] = 2
[1] = 4
}
3> let result = numbers.reduce(0, +)
$R1: Int = 15
REPL-modus ondersteunt ook het laden van modules en frameworks via import. Bijvoorbeeld, import UIKit in REPL laadt de volledige UIKit-bibliotheek, waarmee UI-elementen kunnen worden gemaakt, constraints kunnen worden gecontroleerd en animaties kunnen worden getest. Dit is een unieke mogelijkheid voor iOS-ontwikkelaars die niet beschikbaar is in GDB — debuggen en prototypen in één omgeving.
Dankzij de integratie met Swift Compiler wordt LLDB REPL gebruikt in Apple-cursussen voor het leren van Swift. Studenten kunnen code regel voor regel uitvoeren, types en resultaten zien, zonder afleiding door projectconfiguratie. Deze aanpast is in lijn met de Active Learning-methode, waar interactieve feedback de opname van materiaal versnelt met 40% volgens onderzoek in Computer Science Education.
Veelgestelde vragen
LLDB is gebouwd op een modulaire LLVM-architectuur, wat het een voordeel geeft in snelheid bij het werken met expressies en ondersteuning van moderne talen (Swift). GDB is een monolithische debugger die Swift niet ondersteunt en beperkte scriptmogelijkheden heeft.
Installeer Command Line Tools via xcode-select --install en voer vervolgens lldb --repl uit in de terminal. LLDB is beschikbaar in /Library/Developer/CommandLineTools/usr/bin/.
Ja, via lldb --attach-pid PID of process attach --name AppName. LLDB onderbreekt het proces, waarna alle standaard debug-commando's beschikbaar zijn zonder de applicatie opnieuw te starten.
dSYM-bestanden met debuginformatie ontbreken. Controleer de Build Settings: Generate Debug Symbols moet YES zijn en Debug Information Format moet DWARF with dSYM File zijn.
LLDB slaat automatisch de geschiedenis op in ~/.lldb/lldb-history. Voor export gebruikt u session save filename.txt — het commando slaat alle uitgevoerde commando's van de huidige sessie op in een tekstbestand.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook