LLDB (Low-Level Debugger) เป็นดีบักเกอร์รุ่นใหม่จากโปรเจกต์ LLVM ซึ่งรวมอยู่ใน Xcode สำหรับการดีบักแอปพลิเคชันบน iOS, macOS, tvOS และ watchOS แตกต่างจาก GDB ตรงที่ LLDB ใช้สถาปัตยกรรมแบบโมดูลาร์กับคอมไพเลอร์ LLVM ซึ่งให้ความเร็วและความแม่นยำสูง ตามข้อมูลจาก โปรเจกต์ LLVM นั้น LLDB รองรับการดีบักในภาษา C, Objective-C, C++ และ Swift พร้อมชุดคุณสมบัติครบถ้วน: เบรกพอยต์, วอตช์พอยต์, การตรวจสอบหน่วยความจำ และการดำเนินการทีละขั้นตอน
ประเด็นสำคัญ
LLDB เป็นดีบักเกอร์โอเพนซอร์สที่สร้างขึ้นบนไลบรารีของโปรเจกต์ LLVM มันแทนที่ GDB ใน Xcode 5 และตั้งแต่นั้นมาก็กลายเป็นเครื่องมือดีบักหลักสำหรับระบบนิเวศ Apple ทั้งหมด แตกต่างจาก GDB แบบโมโนลิธิก LLDB ถูกนำไปใช้เป็นชุดของไลบรารีที่โต้ตอบกัน: แต่ละฟังก์ชัน — ตั้งแต่การแยกวิเคราะห์นิพจน์ไปจนถึงการจัดการหน่วยความจำ — อยู่ในโมดูลแยกต่างหาก ซึ่งช่วยลดความซับซ้อนในการบำรุงรักษาและขยาย
ความสามารถหลักของ LLDB ได้แก่: การตั้งค่าเบรกพอยต์ทุกประเภท, วอตช์พอยต์สำหรับติดตามการเปลี่ยนแปลงของตัวแปร, การตรวจสอบหน่วยความจำและรีจิสเตอร์, การดำเนินการทีละขั้นตอน, การประเมินนิพจน์ตามอำเภอใจในบริบทของโปรแกรมที่หยุดชั่วคราว และการเรียกใช้สคริปต์ 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 แบ่งออกเป็นหลายหมวดหมู่: การควบคุมการดำเนินการ, การจัดการเบรกพอยต์, การตรวจสอบข้อมูล, และการจัดการหน่วยความจำ แตกต่างจาก GUI ของ Xcode คอนโซล LLDB ให้การควบคุมการดีบักอย่างสมบูรณ์และช่วยให้ดำเนินการที่ไม่สามารถทำได้ผ่านอินเทอร์เฟซกราฟิก — ตัวอย่างเช่น การเปลี่ยนค่าของตัวแปรทันทีหรือการแก้ไขเบรกพอยต์จำนวนมาก
Continue, Step Over, Step Into, Step Out — พื้นฐานของวงจรการดีบัก continue ดำเนินการต่อจนถึงเบรกพอยต์ถัดไป 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 ไม่เพียงแต่อนุญาตให้อ่าน แต่ยัง ปรับเปลี่ยน สถานะของออบเจ็กต์และตัวแปรระหว่างการดีบักอีกด้วย สิ่งนี้สำคัญอย่างยิ่งสำหรับการทดสอบกรณีขอบ: สามารถตั้งค่าตัวแปรเป็น 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 คุณสามารถสร้างคำสั่งแบบกำหนดเอง จัดการเหตุการณ์เบรกพอยต์ สร้างรายงาน และแม้กระทั่งแทนที่พฤติกรรมของดีบักเกอร์ ตัวแปลภาษา Python 3 ในตัวทำงานภายใน LLDB โดยตรง พร้อมการเข้าถึง API การดีบักแบบเต็มรูปแบบผ่านโมดูล lldb
สามารถลงทะเบียนคำสั่ง LLDB ใหม่ผ่านเดคอเรเตอร์ @classmethod ในสคริปต์ Python หลังจากนำเข้าสคริปต์ คำสั่งจะพร้อมใช้งานเหมือนคำสั่งในตัว ตัวอย่างเช่น คำสั่ง printvars สามารถแสดงตัวแปรทั้งหมดของเฟรมปัจจุบันพร้อมชนิดและค่าของมัน ซึ่งจัดรูปแบบสำหรับโปรเจกต์เฉพาะ ตามการสำรวจนักพัฒนา iOS บน Stack Overflow ระบบอัตโนมัติช่วยลดเวลาของการดำเนินการดีบักทั่วไปลง 60–80%
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 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 ใน REPL คุณสามารถดำเนินการโค้ด Swift หรือ C ได้เหมือนในเพลย์กราวด์ พร้อมผลตอบรับทันที 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 ตรวจสอบข้อจำกัด และทดสอบแอนิเมชันได้ นี่คือความสามารถพิเศษสำหรับนักพัฒนา iOS ที่ไม่มีใน GDB — การดีบักและการสร้างต้นแบบในสภาพแวดล้อมเดียวกัน
ด้วยการผสานรวมกับ Swift Compiler ทำให้ LLDB REPL ถูกใช้ในหลักสูตรของ Apple สำหรับการสอน Swift นักเรียนสามารถดำเนินการโค้ดทีละบรรทัด ดูชนิดและผลลัพธ์ โดยไม่ถูกรบกวนจากการตั้งค่าโปรเจกต์ แนวทางนี้เป็นไปตามวิธีการเรียนรู้แบบ Active Learning ซึ่งผลตอบรับแบบโต้ตอบช่วยเร่งความเข้าใจเนื้อหาได้ถึง 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 สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม