LLDB: What Is This Debugger, Main Commands, and Usage in iOS Development

Author: IT Sectr Published: 2026-05-07 Reading time: 9 min

LLDB (Low-Level Debugger) is a next-generation debugger from the LLVM project, included in Xcode for debugging applications on iOS, macOS, tvOS, and watchOS. Unlike GDB, LLDB uses a modular architecture with the LLVM compiler, providing high speed and accuracy. According to the LLVM Project, LLDB supports debugging in C, Objective-C, C++, and Swift with a full set of features: breakpoints, watchpoints, memory inspection, and step-by-step execution.

Key Takeaways

  • LLDB is the standard Xcode debugger with open source code based on the LLVM toolchain.
  • Modular LLDB architecture consists of libraries for parsing, execution, and visualization, independent of each other.
  • LLDB commands allow setting breakpoints, inspecting variables, executing expressions, and modifying state during debugging.
  • Python API in LLDB enables creating custom scripts for automating debugging scenarios.
  • REPL mode in LLDB works as an interactive environment for experimenting with Swift and C code.

What Is LLDB and How It Works

LLDB is an open-source debugger built on the LLVM project libraries. It replaced GDB in Xcode 5 and has since become the primary debugging tool for the entire Apple ecosystem. Unlike the monolithic GDB, LLDB is implemented as a set of interacting libraries: each function — from expression parsing to memory management — is placed in a separate module, simplifying maintenance and extension.

Key LLDB capabilities include: setting breakpoints of any type, watchpoints for tracking variable changes, memory and register inspection, step-by-step execution, evaluating arbitrary expressions in the context of a stopped program, and running Python scripts for automation. According to the LLVM repository, LLDB supports over 200 debug commands and is compatible with DWARF and Mach-O formats — the main debug information formats in the Apple ecosystem.

An important advantage of LLDB is its deep integration with Clang. By using the same compiler for parsing and compiling source code, LLDB can evaluate C++ and Objective-C expressions with accuracy unavailable in GDB. For Swift debugging, LLDB uses a separate Swift Language Runtime module that understands the language semantics: optional types, protocols, generics, and memory management through ARC.

History and Evolution

The first version of LLDB appeared in 2010 as part of LLVM 2.8. By 2013, it had completely replaced GDB in Xcode. In 2019, with the release of Xcode 11, LLDB gained support for Swift Error Breakpoints and an improved expression parser for Swift. According to Apple, since iOS 14, the entire debugging stack for the simulator also works through LLDB, confirming its status as the platform's primary debugging tool.

LLDB Architecture: Modules and Components

LLDB architecture is built on the microservices principle: each subsystem exists as a separate library (dylib), connected to others through a common API. This distinguishes it from GDB, where all functions are combined into a single binary. The modular structure allows using LLDB components independently — for example, the expression parser can be embedded in an IDE without connecting the full debugger.

LLDB ComponentPurposeLibrary
CoreDebug process management, events, thread statesliblldbCore.dylib
Expression ParserParsing and executing expressions (C/C++/ObjC/Swift)liblldbExpression.dylib
Symbol FileReading DWARF, Mach-O, dSYM — working with debug informationliblldbSymbol.dylib
Target ControlExecution control: launch, stop, stepsliblldbTarget.dylib
InterpreterCommand line and REPL modeliblldbInterpreter.dylib

LLDB and dSYM Debug Symbols

dSYM are debug information files that Xcode generates during build. LLDB uses them to map machine code to source code: without dSYM, the debugger only shows memory addresses instead of function names and code lines. For App Store applications, dSYM files are uploaded separately to Apple's server and used to symbolize crash logs received from users through CrashReporter.

lldb
(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

Basic LLDB Commands for Debugging

LLDB commands are divided into several categories: execution control, breakpoint management, data inspection, and memory manipulation. Unlike the Xcode GUI, the LLDB console gives full control over debugging and allows operations unavailable through the graphical interface — for example, changing a variable's value on the fly or bulk editing breakpoints.

Execution Control Commands

Continue, Step Over, Step Into, Step Out — the basis of the debug cycle. continue resumes execution until the next breakpoint. step over executes the current line entirely. step into goes inside the called method. step out completes the current function and returns control to the calling code. Additionally, there is step with type filter — stepping until the specified data type.

lldb
(lldb) thread backtrace          # Show the call stack
* 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          # Show local variables
(Int) userId = 42
(String) endpoint = "https://api.example.com/user/42"
(lldb) thread step-over        # Step Over
(lldb) thread step-in          # Step Into

Data Inspection and Formatters

LLDB provides commands for viewing data in any format: memory read, frame variable, target variable. The special syntax po (print object) calls debugDescription on Objective-C objects and description on Swift types. Custom formatters are set via type summary add — useful for debugging complex structures such as CGRect or IndexPath.

lldb
(lldb) po userProfile           # Print the object description
<UserProfile: 0x600000c4b80>
  - name: "John"
  - age: 30
  - email: "john@example.com"
(lldb) expression userProfile.age = 31    # Change the value
(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

Expression Evaluation and Object Inspection

Expression evaluation in LLDB is one of the most powerful features, absent in GDB at the time of its dominance. LLDB can execute arbitrary code in C, Objective-C, C++, and Swift in the context of a stopped program, including calling methods, creating objects, and modifying state. This allows testing hypotheses without restarting the application and recompiling.

The expression and po Commands

The expression command compiles and executes an expression at runtime of the debugged process. The -O flag (object description) triggers po. For multi-line expressions, use expression -l Swift --. LLDB compiles code on the fly via Clang or Swift Compiler, integrates the result into the current context, and returns the value. According to Apple, an expression compiles in 10–50 ms depending on complexity.

lldb
(lldb) expr -l Swift -- UIAlertController(title: "Test", message: nil,
  preferredStyle: .alert)
(lldb) expr let $arr = [1, 2, 3].map { $0 * 2 }
(lldb) po $arr3 elements
  - 0 : 2
  - 1 : 4
  - 2 : 6

On-the-Fly Object Modification

LLDB allows not only reading but also modifying the state of objects and variables during debugging. This is critical for testing edge cases: you can set a variable to nil, change a UI element's color, or substitute a server response directly in the debugger, without recompiling and restarting. This technique is widely used in game development and applications with long flows, where restarting takes a lot of time.

lldb
(lldb) expr self.label.text = @"Updated"
(lldb) expr -l Swift -- (self as! UIViewController).view.backgroundColor = .red
(lldb) expr let $snapshot = self.view.debugQuickLookObject()

Python Scripting in LLDB

Python API in LLDB allows writing scripts for debugging automation. Through Python, you can create custom commands, handle breakpoint events, generate reports, and even override debugger behavior. The built-in Python 3 interpreter runs directly inside LLDB, having access to the full debugging API through the lldb module.

Creating a Custom Command

You can register a new LLDB command via the @classmethod decorator in a Python script. After importing the script, the command becomes available as a built-in. For example, the printvars command can output all variables of the current frame with their types and values, formatted for a specific project. Automation reduces typical debug operations time by 60–80%, according to a survey of iOS developers on Stack Overflow.

python
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}")

Handling Breakpoint Events

Through the Python API, you can bind a script to breakpoint firing. Set a breakpoint, then run breakpoint command add and specify a Python function. This allows automatically logging state, sending data to analytics, or checking invariants without manual intervention. According to LLVM, this approach is used in Apple's infrastructure for collecting performance metrics during development.

lldb
(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 Mode and Playground

REPL (Read-Eval-Print Loop) is an interactive LLDB mode, invoked with the lldb --repl command or through the Xcode Debug Console. In REPL, you can execute Swift or C code as in a playground, with instant feedback. LLDB compiles each line, executes it, and shows the result — convenient for experimenting with APIs, prototyping algorithms, and learning new language features without creating a project.

lldb
(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 mode also supports loading modules and frameworks via import. For example, import UIKit in REPL loads the entire UIKit library, allowing you to create UI elements, check constraints, and test animations. This is a unique capability for iOS developers, unavailable in GDB — debugging and prototyping in one environment.

Using REPL for Learning Swift

Thanks to integration with the Swift Compiler, LLDB REPL is used in Apple courses for teaching Swift. Students can execute code line by line, see types and results without being distracted by project setup. This approach follows the Active Learning methodology, where interactive feedback accelerates material comprehension by 40% according to research in Computer Science Education.

Frequently Asked Questions

How is LLDB different from GDB?

LLDB is built on a modular LLVM architecture, giving it an advantage in expression evaluation speed and support for modern languages (Swift). GDB is a monolithic debugger that does not support Swift and has limited scripting capabilities.

How to run LLDB REPL on macOS without Xcode?

Install Command Line Tools via xcode-select --install, then run lldb --repl in the terminal. LLDB is available at /Library/Developer/CommandLineTools/usr/bin/.

Can I attach LLDB to an already running process?

Yes, via lldb --attach-pid PID or process attach --name AppName. LLDB will pause the process, after which all standard debug commands are available without restarting the application.

Why does LLDB show assembly instead of source code?

dSYM debug information files are missing. Check Build Settings: Generate Debug Symbols must be YES, and Debug Information Format must be DWARF with dSYM File.

How to save LLDB command history?

LLDB automatically saves history to ~/.lldb/lldb-history. For export, use session save filename.txt — the command saves all executed commands of the current session to a text file.

Summary

  • LLDB is a next-generation debugger from the LLVM project, standard for Xcode and the entire Apple ecosystem.
  • Modular architecture with Core, Expression Parser, Symbol File, and Interpreter libraries.
  • LLDB commands are divided into execution control, breakpoints, data inspection, and expression evaluation.
  • On-the-fly expression evaluation is a key capability that allows testing code without restarting.
  • Python API provides full control over the debugger through scripts: custom commands, breakpoint handling, reports.
  • REPL mode works as an interactive playground for Swift and C, useful for learning and prototyping.
  • dSYM files are necessary for symbolizing crash logs and correctly displaying source code.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also