LLDB (Low-Level Debugger) — налагоджувач нового покоління від LLVM-проєкту, що входить до складу Xcode для налагодження застосунків під iOS, macOS, tvOS та watchOS. На відміну від GDB, LLDB використовує модульну архітектуру з LLVM-компілятором, що забезпечує високу швидкість і точність. За даними LLVM Project, LLDB підтримує налагодження мовами C, Objective-C, C++ та Swift з повним набором функцій: breakpoints, watchpoints, інспекція пам'яті та покрокове виконання.
Головне
LLDB — це налагоджувач з відкритим вихідним кодом, побудований на бібліотеках LLVM-проєкту. Він прийшов на заміну GDB у Xcode 5 і з тих пір є основним інструментом налагодження для всієї екосистеми Apple. На відміну від монолітного GDB, LLDB реалізований як набір взаємодіючих бібліотек: кожна функція — від парсингу виразів до роботи з пам'яттю — винесена в окремий модуль, що спрощує підтримку та розширення.
Основні можливості LLDB включають: встановлення breakpoints будь-якого типу, watchpoints для відстеження змін змінних, інспекцію пам'яті та регістрів, покрокове виконання, обчислення довільних виразів у контексті зупиненої програми та виконання Python-скриптів для автоматизації. За даними репозиторію LLVM, LLDB підтримує понад 200 команд налагодження та сумісний з форматами DWARF та Mach-O — основними форматами налагоджувальної інформації в екосистемі Apple.
Важлива перевага LLDB — глибока інтеграція з Clang. Завдяки використанню одного компілятора для парсингу та компіляції вихідного коду, LLDB може обчислювати C++ та Objective-C вирази з точністю, недоступною GDB. Для налагодження Swift LLDB використовує окремий модуль Swift Language Runtime, який розуміє семантику мови: опціональні типи, протоколи, узагальнення та керування пам'яттю через ARC.
Перша версія LLDB з'явилася в 2010 році як частина LLVM 2.8. До 2013 року він повністю замінив GDB у Xcode. У 2019 році з виходом Xcode 11 LLDB отримав підтримку Swift Error Breakpoints та покращений парсер виразів для Swift. За даними Apple, починаючи з iOS 14, весь стек налагодження для симулятора також працює через LLDB, що підтверджує його статус основного інструменту налагодження платформи.
Архітектура LLDB побудована за принципом мікросервісів: кожна підсистема існує як окрема бібліотека (dylib), пов'язана з іншими через спільний API. Це відрізняє його від GDB, де всі функції об'єднані в один бінарник. Модульна структура дозволяє використовувати компоненти LLDB незалежно — наприклад, парсер виразів можна вбудувати в IDE без підключення повного налагоджувача.
| Компонент LLDB | Призначення | Бібліотека |
|---|---|---|
| Core | Керування процесом налагодження, події, стани потоків | liblldbCore.dylib |
| Expression Parser | Парсинг та виконання виразів (C/C++/ObjC/Swift) | liblldbExpression.dylib |
| Symbol File | Читання DWARF, Mach-O, dSYM — робота з налагоджувальною інформацією | liblldbSymbol.dylib |
| Target Control | Керування виконанням: запуск, зупинка, кроки | liblldbTarget.dylib |
| Interpreter | Командний рядок та REPL-режим | liblldbInterpreter.dylib |
dSYM — це файли налагоджувальної інформації, які Xcode генерує при збірці. LLDB використовує їх для зіставлення машинного коду з вихідним: без dSYM налагоджувач показує лише адреси в пам'яті замість імен функцій та рядків коду. Для застосунків з App Store dSYM завантажуються окремо на сервер Apple і використовуються для символізації краш-логів, отриманих від користувачів через CrashReporter.
(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 поділяються на кілька категорій: керування виконанням, робота з breakpoints, інспекція даних та маніпуляція пам'яттю. На відміну від Xcode GUI, консоль LLDB дає повний контроль над налагодженням та дозволяє виконувати операції, недоступні через графічний інтерфейс — наприклад, зміну значення змінної на льоту або масове редагування breakpoints.
Continue, Step Over, Step Into, Step Out — основа налагоджувального циклу. continue відновлює виконання до наступного breakpoint. step over виконує поточний рядок цілком. step into заходить всередину викликаного методу. step out завершує поточну функцію та повертає керування коду, що викликав. Додатково існує step with type filter — крок до вказаного типу даних.
(lldb) thread backtrace # Показать стек вызовов
* 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 # Показать локальные переменные
(Int) userId = 42
(String) endpoint = "https://api.example.com/user/42"
(lldb) thread step-over # Step Over
(lldb) thread step-in # Step Into
LLDB надає команди для перегляду даних у будь-якому форматі: memory read, frame variable, target variable. Спеціальний синтаксис po (print object) викликає debugDescription у Objective-C об'єктів та description у Swift-типів. Кастомні форматтери задаються через type summary add — корисно для налагодження складних структур, таких як CGRect або IndexPath.
(lldb) po userProfile # Вывод описания объекта
<UserProfile: 0x600000c4b80>
- name: "John"
- age: 30
- email: "john@example.com"
(lldb) expression userProfile.age = 31 # Изменить значение
(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
Обчислення виразів у LLDB — одна з найпотужніших функцій, відсутня в GDB на момент його домінування. LLDB може виконувати довільний код на C, Objective-C, C++ та Swift у контексті зупиненої програми, включаючи виклик методів, створення об'єктів та модифікацію стану. Це дозволяє тестувати гіпотези без перезапуску застосунку та перекомпіляції.
Команда expression компілює та виконує вираз у рантаймі процесу, що налагоджується. Прапорець -O (object description) викликає po. Для багаторядкових виразів використовуйте expression -l Swift --. LLDB компілює код на льоту через Clang або Swift Compiler, інтегрує результат у поточний контекст та повертає значення. За даними Apple, вираз компілюється за 10–50 мс залежно від складності.
(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 дозволяє не лише читати, але й змінювати стан об'єктів та змінних під час налагодження. Це критично важливо для тестування edge cases: можна встановити значення змінної в nil, змінити колір UI-елемента або підмінити відповідь сервера прямо в дебагері, без перекомпіляції та повторного запуску. Техніка широко застосовується в розробці ігор та застосунків з довгими флоу, де перезапуск займає багато часу.
(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 LLDB дозволяє писати скрипти для автоматизації налагодження. Через Python можна створювати кастомні команди, обробляти події breakpoint, генерувати звіти та навіть перевизначати поведінку налагоджувача. Вбудований інтерпретатор Python 3 запускається прямо всередині LLDB, маючи доступ до повного API налагодження через модуль lldb.
Зареєструвати нову команду LLDB можна через декоратор @classmethod у Python-скрипті. Після імпорту скрипту команда стає доступною як вбудована. Наприклад, команда printvars може виводити всі змінні поточного фрейму з їхніми типами та значеннями, відформатованими під конкретний проєкт. Автоматизація скорочує час типових налагоджувальних операцій на 60–80%, за даними опитування iOS-розробників на 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}")
Через Python API можна прив'язати скрипт до спрацьовування breakpoint. Встановіть breakpoint, потім виконайте breakpoint command add та вкажіть Python-функцію. Це дозволяє автоматично логувати стан, надсилати дані в аналітику або перевіряти інваріанти без ручного втручання. За даними LLVM, такий підхід використовується в інфраструктурі Apple для збору метрик продуктивності на етапі розробки.
(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) — інтерактивний режим LLDB, що викликається командою lldb --repl або через Xcode Debug Console. У REPL можна виконувати код на Swift або C як у playground, з миттєвим зворотним зв'язком. LLDB компілює кожен рядок, виконує його та показує результат — це зручно для експериментів з API, прототипування алгоритмів та вивчення нових можливостей мови без створення проєкту.
(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-режим також підтримує завантаження модулів та фреймворків через import. Наприклад, import UIKit у REPL завантажує всю бібліотеку UIKit, і можна створювати UI-елементи, перевіряти constraint-и та тестувати анімації. Це унікальна можливість для iOS-розробників, недоступна в GDB, — налагодження та прототипування в одному середовищі.
Завдяки інтеграції з Swift Compiler, LLDB REPL використовується на курсах Apple для вивчення Swift. Студенти можуть виконувати код рядок за рядком, бачити типи та результати, не відволікаючись на налаштування проєкту. Такий підхід відповідає методиці Active Learning, де інтерактивний зворотний зв'язок прискорює засвоєння матеріалу на 40% за даними досліджень у галузі Computer Science Education.
Часті запитання
LLDB побудований на модульній LLVM-архітектурі, що дає йому перевагу в швидкості роботи з виразами та підтримці сучасних мов (Swift). GDB — монолітний налагоджувач, що не підтримує Swift і має обмежені можливості скриптингу.
Встановіть Command Line Tools через xcode-select --install, потім виконайте lldb --repl у терміналі. LLDB доступний у /Library/Developer/CommandLineTools/usr/bin/.
Так, через lldb --attach-pid PID або process attach --name AppName. LLDB призупинить процес, після чого доступні всі стандартні команди налагодження без перезапуску застосунку.
Відсутні dSYM-файли налагоджувальної інформації. Перевірте налаштування Build Settings: Generate Debug Symbols має бути YES, а Debug Information Format — DWARF with dSYM File.
LLDB автоматично зберігає історію в ~/.lldb/lldb-history. Для експорту використовуйте session save filename.txt — команда зберігає всі виконані команди поточної сесії в текстовий файл.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також