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 ساخته شده است. این دیباگر در Xcode 5 جایگزین GDB شد و از آن زمان به عنوان ابزار اصلی دیباگ برای کل اکوسیستم Apple محسوب میشود. برخلاف GDB یکپارچه، LLDB به عنوان مجموعهای از کتابخانههای همکار پیادهسازی شده است: هر تابع — از پارس عبارات تا کار با حافظه — در یک ماژول جداگانه قرار گرفته است که نگهداری و گسترش را آسانتر میکند.
قابلیتهای اصلی LLDB عبارتند از: تنظیم breakpoints از هر نوع، watchpoints برای ردیابی تغییرات متغیرها، بازرسی حافظه و ثباتها، اجرای گامبهگام، ارزیابی عبارات دلخواه در زمینه برنامه متوقف شده و اجرای اسکریپتهای پایتون برای خودکارسازی. طبق دادههای مخزن 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 آپلود میشوند و برای نمادسازی crash-logهای دریافت شده از کاربران از طریق 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، کنسول LLDB کنترل کامل بر دیباگ را فراهم میکند و امکان انجام عملیاتی را میدهد که از طریق رابط گرافیکی در دسترس نیستند — برای مثال، تغییر مقدار متغیر در لحظه یا ویرایش دستهای breakpoints.
Continue, Step Over, Step Into, Step Out — اساس چرخه دیباگ هستند. continue اجرا را تا breakpoint بعدی از سر میگیرد. step over خط جاری را به طور کامل اجرا میکند. step into وارد متد فراخوانیشده میشود. step out تابع جاری را پایان میدهد و کنترل را به کد فراخوان بازمیگرداند. علاوه بر این، step with type filter وجود دارد — گام تا نوع داده مشخصشده.
(lldb) thread backtrace # نمایش 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 # نمایش متغیرهای محلی
(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 نه تنها خواندن، بلکه تغییر وضعیت اشیاء و متغیرها را در حین دیباگ امکانپذیر میکند. این برای آزمایش موارد مرزی حیاتی است: میتوان مقدار متغیر را به 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 امکان نوشتن اسکریپتهایی برای خودکارسازی دیباگ را فراهم میکند. از طریق پایتون میتوان دستورات سفارشی ایجاد کرد، رویدادهای breakpoint را پردازش کرد، گزارشها تولید کرد و حتی رفتار دیباگر را تغییر داد. مفسر داخلی پایتون 3 مستقیماً درون LLDB اجرا میشود و از طریق ماژول lldb به API کامل دیباگ دسترسی دارد.
میتوان یک دستور جدید LLDB را از طریق دکوراتور @classmethod در اسکریپت پایتون ثبت کرد. پس از وارد کردن اسکریپت، دستور مانند یک دستور داخلی در دسترس میشود. برای مثال، دستور 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 را اجرا کرده و تابع پایتون را مشخص کنید. این امکان ثبت خودکار وضعیت، ارسال دادهها به تحلیل یا بررسی تغییرناپذیریها را بدون دخالت دستی فراهم میکند. طبق دادههای 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 مطابقت دارد، جایی که بازخورد تعاملی طبق تحقیقات در زمینه Computer Science Education جذب مطالب را 40٪ تسریع میکند.
سوالات متداول
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 از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید