一、列印輸出、變量修改
1. print:簡化指令:p
1.1 如果列印的是簡單類型,則會列出簡單類型的類型和值。如果是對象,還會列印出對象指針位址。
1.2 如果我們隻想檢視對象的值的資訊,則可以使用po(print object的縮寫)指令。
1.3 我們還可以為其指定不同的列印格式,其指令格式是print/格式。p/x代表16進制;p/t代表2進制等等。
兩個指令實際都是expression指令的縮寫。p列印的是目前對象的位址而po則會調用對象的description方法
2. expression:簡化指令:exp、e
2.1 expression 指令不僅能輸出某個變量的值(對象的類型和位址),還能改變程式中的實際值。比如:
(lldb) exp var (結果能輸出var這個變量的值)
(lldb) exp self.view.backgroundColor = UIColor.red (将背景變成紅色)
2.2 下面三行指令是建立一個Controller并present
(lldb) exp let $newController = UIViewController()
(lldb) exp $newController.view.backgroundColor = UIColor.green.withAlphaComponent(0.4)
(lldb) exp self.present($newController, animated: true, completion: nil)
2.3 控制台臨時增加的變量,需要在變量前面增加符号:$。如下:
(lldb) exp $var = 10
(lldb) exp $var (也可以用print檢視:p $var)
二、擷取狀态
1. frame:
1.1 frame info:擷取目前斷點位址、代碼行數以及函數的相關參數
(lldb) frame info (touchesBegan内設定的斷點)
frame #0: 0x000000010392ca34 LLDBTestDemo`ViewController.touchesBegan(touches=Swift.Set<UIKit.UITouch> @ 0x00007ffeec2d12e8, event=0x000060000010ea90, self=0x00007fc217d0cc70) at ViewController.swift:27
1.2 frame variable:展示目前作用域下的參數和局部變量
(lldb) frame variable 等價于 (lldb)fr v
效果和打斷點在’控制台’開啟Variables view(控制台區域左側區域)看到的一樣
(lldb) frame variable --no-args 等價于 (lldb) fr v -a
1.3 frame variable 變量:展示指定變量var的具體内容
(lldb) frame variable 變量
2. bug日志儲存
(lldb) bugreport unwind --outfile Users/ming/Desktop/bugreport/日志檔案名稱
3. refcount 能獲得指定對象的引用數量(調試某些記憶體洩露問題時)
(lldb) language swift refcount 對象a
三、應用的執行流程
1. 擷取目前斷點的狀态:列印斷點所在的位址、代碼塊以及停在哪一行
(lldb) process status
2. process 其它指令:attach、connect、kill、load、lanuch、continue
3. 斷點
3.1 輸出所有斷點
(lldb) breakpoint list
3.2 設定新斷點
(lldb) breakpoint set -f ViewController.swift -l 17 (等價于下面的簡寫)(-f 是你想要放置斷點處的檔案名,-l 是新斷點的行數。)
(lldb) b ViewController.swift 17
3.3 根據位址設定斷點
(lldb) br set -a 0x00000001039edf2d 等價于:
(lldb) b -a 0x00000001039edf2d
3.4 使用正則來設定斷點
(lldb) breakpoint set --func-regex 函數名
(lldb) b -r 函數名
3.5 為斷點增加指令:
第一步設定一個斷點如下:
(lldb) breakpoint set -f ViewController.swift -l 27
設定後控制台會輸出:Breakpoint 3: where = …… (其中3 是這個斷點的’序号index’)
第二步準備斷點指令:
(lldb) breakpoint command add 3 (其中3 是這個斷點的’序号index’)
然後控制台會進入指令輸入模式,最終以輸入DONE作為結束辨別。
第三步檢視剛剛輸入的指令:
(lldb) breakpoint command list 3
第四步,使得程式進入這個斷點,檢視是否執行’斷點指令’
嘗試:在剛剛輸入DONE前一行輸入continue
4. 線程操作
4.1 控制台斷點流程執行
(lldb) process continue 繼續 等價于 continue 等價于 c
(lldb) thread step-over 單步 等價于 next 等價于 n
(lldb) thread step-in 進入 等價于 step 等價于 s
(lldb) thread step-out 跳出 等價于 finish 等價于 f
4.2 擷取目前線程函數的調用棧:
指令:frame info、frame variable、target variable等指令,這些操作都有一個局限:我們檢視的各個變量都是目前作用域的。這意味着程式遇到斷點的時候暫停,所有的操作都是局限于目前函數以及目前函數所線上程的内部。
指令:thread backtrace可以擷取目前線程函數的調用棧
(lldb) thread backtrace (輸出一系列帶序号的frame)
輸入frame select指令,我們可以任意的去選擇一個作用域去檢視
(lldb) frame select 2 (2:前一步輸出的序号)
通過上面的指令,我們可以在斷點發生的時候跳轉到目前存在的任一線程裡的任一作用域去進行操作。
4.3 image指令:是target module指令的縮寫,借助它我們能夠檢視目前的Binary Images相關的資訊。
在日常開發的過程中,我們會收集到使用者各式各樣的crash log。log中會為我們提供崩潰前函數棧的運作情況,每一個函數都會對應一個函數位址。
要解決問題首先我們需要确定的是程式最後調用了什麼函數。由于ALSR的原因crash log中的函數位址我們不能夠直接的去使用,我們需要在測試的機器上自己去計算出對應的函數位址。一般情況下crash log中會附帶一個Binary Images。我們要利用這個來計算出每一個函數位址相對于所在架構的偏移量。
首先:利用 image list 指令來檢視本機的Binary Images
(lldb) image list
有了本機的Binary Images我們就可以通過之前計算出的偏移量來擷取本機對應函數的位址。
然後:通過image lookup指令查找對應位址的函數就可以确定崩潰前究竟執行了哪些函數
(lldb) image lookup -a 0x1025dd00a
tip:可以通過frame info來擷取一個位址,使用image lookup來試一試
5. watchpoint:監視某個變量或某一塊記憶體的讀寫情況
(lldb) watchpoint set variable 變量名稱 (功能:監控變量)
(lldb) watchpoint set expression 0x位址 (功能:監控記憶體塊。操作未成功,參考target stop-hook add的格式)
6. register :指令能夠擷取和修改各個寄存器的資訊
一個典型的CPU是由運算器、控制器、寄存器等器件構成的,而寄存器進行的就是資訊存儲。
(lldb) register read (功能:檢視指令)
(lldb) register write x2 0x位址 (還沒實踐)
四、腳本
推薦使用Facebook開源的腳本:https://github.com/facebook/chisel
自己寫的腳本可以用下面的指令導入:
(lldb) command script import /Users/XXX/Desktop/腳本.py
還可以加入到lldbinit中,讓Xcode啟動就調用。
在終端(terminal)中輸入下面的兩條指令:
touch .lldbinit
open .lldbinit
然後在彈出的界面加入下面的代碼:
command script import ‘Python檔案的實際目錄位址’
五 GDB to LLDB command map
六 異常情況處理
error: no known method '-func:'; cast the message send to the method's return type
解決方法:在前面添加傳回類型,如下
po (BOOL)[NSDecimalNumber isAGreaterThanB:@323.434432432 valueB:@323.4340000005]