值得持續(xù)學(xué)習(xí)的LLDB技巧

一、概述

開發(fā)調(diào)試中,常常使用LLDB加快調(diào)試,更快速簡(jiǎn)單的定位到問(wèn)題點(diǎn)。
下面是之前收集并且整理的常用命令 、插件和 使用技巧。

二、命令

關(guān)于命令的詳細(xì)用法,使用help <command> <subcommand>進(jìn)行查看

2.0、關(guān)于~/.lldbinit

LLDB有了一個(gè)啟動(dòng)時(shí)加載的文件~/.lldbinit,每次啟動(dòng)都會(huì)加載。
可以添加一些自定義命令,加載插件等等。

cat ~/.lldbinit查看文件內(nèi)容,包含以下信息:

  • command script import /path/to/fblldb.py
    一般系統(tǒng),在~/.lldbinit默認(rèn)導(dǎo)入facebook的fblldb.py里面命令。
    當(dāng)然也可以自行安裝相關(guān)插件。

  • @import 導(dǎo)入第三方框架,可以把基礎(chǔ)框架放入到~/.lldbinit文件中
    例如 @import Foundation/UIKit/CoreGraphics 等系統(tǒng)框架,否則lldb調(diào)試相關(guān)框架會(huì)報(bào)錯(cuò),

2.1、打印命令

  • p 打印基礎(chǔ)數(shù)據(jù)類型;打印對(duì)象時(shí)會(huì)返回對(duì)象指針地址。
    p/x 變量名 打印變量的16進(jìn)制(x 代表十六進(jìn)制格式、t 代表二進(jìn)制格式)
    p/t:二進(jìn)制輸出
    p/c:字符編碼
    p/x:16進(jìn)制輸出

  • 查看對(duì)象內(nèi)存分配
    x 對(duì)象:對(duì)象內(nèi)存情況
    x/4gx 對(duì)象:按照四段16字節(jié)輸出對(duì)象內(nèi)存情況
    x/8gx 對(duì)象:按照八段16字節(jié)

  • po 打印對(duì)象的desc信息

  • frame variable 打印

  • exp 命令作用同p命令

2.2、堆棧

  • bt 打印當(dāng)前線程堆棧(backtrace的縮寫)
    bt all 打印所有線程的堆棧

  • frame select 層數(shù) 跳轉(zhuǎn)到某一層的堆棧
    frame variable 查看當(dāng)前堆棧的變量

  • up 向上查看堆棧

  • down 向下查看堆棧

2.3、線程

  • thread list 列出所有的線程
  • thread select 線程編號(hào) 切換線程
  • thread backtrace
  • thread backtrace all 打印所有線程的堆棧
  • thread return 各種原因,不想讓代碼執(zhí)行某個(gè)方法,或者要直接返回一個(gè)想要的值。

2.4、表達(dá)式

  • e、expr、expression 執(zhí)行表達(dá)式,常用的做法是,在不重新編譯的情況下,給變量賦值。
    self.view.backgroundColor = [UIColor redColor];

2.5、關(guān)于imageimage是LLDB給 target modules 取的別名 )

  • image list 列出當(dāng)前執(zhí)行的和依賴第三方的所有鏡像

  • image lookup -n 名字 查找項(xiàng)目中某個(gè)變量名、函數(shù)名等,包括第三方SDK或者靜態(tài)庫(kù)。
    例如,用來(lái)查找同名的Category方法。

  • image lookup --address 地址+偏移量 等價(jià)于 image lookup -a 地址+偏移量
    image lookup -v -a 地址+偏移量 查找完整的源代碼行信息

  • image lookup -type 類名 查看類的成員

2.6、斷點(diǎn)

調(diào)試技巧:斷點(diǎn)編輯,xcode中可以右鍵某個(gè)斷點(diǎn),可以進(jìn)行斷點(diǎn)編輯,可以設(shè)置某種條件下觸發(fā)斷點(diǎn),實(shí)際開發(fā)中蠻實(shí)用。

2.6.1、breakpoint set 斷點(diǎn)設(shè)置,其中breakpoint可以縮寫為b
  • -n 方法名 根據(jù)方法名給當(dāng)前類設(shè)置斷點(diǎn)。
    也可以根據(jù)方法名給指定類多個(gè)方法設(shè)置斷點(diǎn),如下
    breakpoint set -n "-[ViewController save:]" -n "-[ViewController continueGame:]" -n "-[ViewController pauseGame:]"

  • breakpoint set --selector 方法名 給整個(gè)項(xiàng)目某個(gè)指定方法設(shè)置斷點(diǎn)

  • -f 指定文件設(shè)定
    breakpoint set -f ViewController.m -n viewDidAppear:

  • -l 指定某一行設(shè)置斷點(diǎn)
    breakpoint set -f ViewController.m -l 33

  • -a 給某個(gè)內(nèi)存地址設(shè)置斷點(diǎn)

  • -c 設(shè)置條件斷點(diǎn)
    breadpoint set -n helloworld: -c flag==NO

  • -r 遍歷整個(gè)項(xiàng)目中的所有方法,設(shè)置斷點(diǎn)
    例如breakpoint set -r Game: 為項(xiàng)目所有包含 Game: 這個(gè)字符的所有方法,設(shè)置斷點(diǎn)

2.6.2、breakpoint command 給斷點(diǎn)設(shè)置一些命令
  • breakpoint command add 添加命令
    例如,breakpoint command add -o "po self.view" 3
    其中,-o完整寫法是–one-liner,表示增加一條命令。3表示對(duì)id為3的breakpoint增加命令。

  • breakpoint command list num 查看某個(gè)斷點(diǎn)的所有命令

  • breakpoint command delete num 刪除某個(gè)斷點(diǎn)的所有命令

2.6.3、其他
  • breakpoint list 查看斷點(diǎn)列表
  • breakpoint disable/enable num 開啟和禁止斷點(diǎn)
  • breakpoint delete num 刪除某個(gè)斷點(diǎn),沒(méi)有入?yún)t刪除所有斷點(diǎn)

2.7、watchpoint 內(nèi)存斷點(diǎn)

如果說(shuō)breakpoint是對(duì)方法生效的斷點(diǎn),watchpoint就是對(duì)地址生效的斷點(diǎn)。
想要知道某個(gè)屬性什么時(shí)候被篡改了,我們?cè)撛趺崔k呢?就可以使用watchpoint。

2.7.1、設(shè)置
  • watchpoint set variable 設(shè)置變量
    例如,watchpoint set variable self->name
    不接受方法,因此以下命令無(wú)效watchpoint set variable self.name ,因?yàn)镺C中點(diǎn)操作符調(diào)用setter和getter方法。

  • watchpoint set expression address 觀察某個(gè)地址

2.7.2、命令
  • watchpoint command add\delete\list 同breakpoint,斷點(diǎn)設(shè)置命令
2.7.3、其他
  • watchpoint list 查看當(dāng)前所有
  • watchpoint enable/disable num 開啟和禁止斷點(diǎn)
  • watchpoint delete num

2.8、流程控制語(yǔ)句

  • c 繼續(xù),continue
  • n next
  • s 進(jìn)入step in
  • finish 完成

2.9、targets

2.9.1、modules
  • target modules lookup 訪問(wèn)一個(gè)或多個(gè)目標(biāo)模塊的信息
    由于LLDB給target modules取了個(gè)別名image,所以這個(gè)命令我們又可以寫成image lookup。 如下
    詳見上面的image命令
2.9.2、stop-hook

breadpointwatchpoint 斷點(diǎn)停止的時(shí)候,去執(zhí)行一些命令。

  • target stop-hook list 查看所有的hook

  • target stop-hook add 添加的hook
    使用-o表示添加一條命令。

  • target stop-hook delete num 刪除指定編號(hào)的hook,沒(méi)有入?yún)um則表達(dá)式全部

  • target stop-hook disable/enable num 開啟和禁用hook,沒(méi)有入?yún)um則代表全部

2.9.3、target symbols add(add-dsym)

當(dāng)我們對(duì)接framework的時(shí)候,如果只有framework代碼,沒(méi)有工程代碼,能不能debug呢?其實(shí)我們只需要拿到工程的ipa和dSYM文件,就可以debug了,通過(guò)Attach to Process,使用命令add-dsym將dSYM文件加入target,即可只debug framework,不需要工程的代碼

2.10、其他

  • call 調(diào)用方法,不打印值;p、po也有該功能,并且會(huì)打印返回值

  • disassemble,縮寫為dis 打印當(dāng)前目標(biāo)的匯編代碼

使用例子demo
1、image list
讀取app的image進(jìn)程內(nèi)存首地址

[  0] 67EC1881-E7CC-38BC-A49E-D6FE5E755FB0 0x000000010ebe1000

2、memory read addr
addr-符號(hào)表的符號(hào)地址,可以通過(guò)mach-o查看。

1.png

addr = 第一步首地址 + mach-o的offset地址
0x10EBE9050 = 0x000000010ebe1000 + 0x00008048

2.png

  • 相關(guān)內(nèi)存命令:find、history、read、region、writer

3、dis -s addr
這一步的addr是上一步紅框的倒敘(由于iOS是小端模式,內(nèi)存地址8位倒著讀)。

3.png

輸出:HelloWorld/fxNSlog:,其中 fxNSlog: 是用fishhook NSLog的替換函數(shù)。

4、操作寄存器
register read/write

三、LLDB 和 Python

3.1、插件的原理

LLDB 有內(nèi)建的,完整的 Python 支持。在LLDB中輸入 script,會(huì)打開一個(gè) Python REPL。

3.2、Chisel插件(facebook開源調(diào)試?yán)?,原理同時(shí))

GitHub地址

常用的命令:
  • pviews self.view 遞歸打印所有的view,并能標(biāo)示層級(jí)

  • pvc 遞歸打印當(dāng)前ViewController的層級(jí)

  • visualize img_obj 使用Mac的預(yù)覽打開一個(gè) UIImage, CGImageRef, UIView, 或 CALayer。

  • fv & fvc var
    通過(guò)類名搜索當(dāng)前內(nèi)存中存在的view和viewController實(shí)例的命令,支持正則搜索。

  • show/hide 無(wú)需重新編譯,直接顯示和隱藏view或者layer

  • caflush 重新渲染繪制界面,相當(dāng)于執(zhí)行了 [CATransaction flush] 方法
    注意如果在動(dòng)畫過(guò)程中執(zhí)行這個(gè)命令,就直接渲染出動(dòng)畫結(jié)束的效果。
    在調(diào)試界面顏色、坐標(biāo)之類的時(shí)候,可以直接在控制臺(tái)修改屬性,然后caflush就可以看到效果啦。

  • mask/umask 和 border/unborder
    這兩組命令用來(lái)標(biāo)識(shí)一個(gè)view或layer的位置時(shí)用。
    mask用來(lái)在view上覆蓋一個(gè)半透明的矩形, border可以給view添加邊框。

  • presponder self.view 打印響應(yīng)者鏈

** 更多好用的用法,請(qǐng)參考help命令,值得你深入研究。 **

四、XCode調(diào)試

  • 顯示匯編相關(guān),Debug -> Debug Wokflow -> Always Show Disassembly 則會(huì)顯示匯編信息。
    例子:在NSLog打斷點(diǎn),如下
NSString *str = @"helloworld";
id __weak objc = str;
NSLog(@"%@", objc);
image.png

參考

LLDB調(diào)試小節(jié)
objc.io#19#與調(diào)試器共舞 - LLDB 的華爾茲
iOS中教你快速掌握LLDB調(diào)試技巧
Chisel-LLDB命令插件,讓調(diào)試更Easy

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

  • LLDB的Xcode默認(rèn)的調(diào)試器,它與LLVM編譯器一起,帶給我們更豐富的流程控制和數(shù)據(jù)檢測(cè)的調(diào)試功能。平時(shí)用Xc...
    小笨狼閱讀 20,803評(píng)論 31 186
  • 在上篇文章從fishhook看runtime,hook系統(tǒng)C函數(shù)中已經(jīng)提到了利用LLDB的部分命令。在我們玩逆向的...
    一縷清風(fēng)揚(yáng)萬(wàn)里閱讀 4,607評(píng)論 7 22
  • 較常用的命令都會(huì)帶 ?? ?? ?? 執(zhí)行命令 斷點(diǎn)命令 watchpoint 命令 查看變量 執(zhí)行表達(dá)式 檢查線...
    YxxxHao閱讀 10,837評(píng)論 0 3
  • ??LLDB的Xcode默認(rèn)的調(diào)試器,它與LLVM編譯器一起,帶給我們更豐富的流程控制和數(shù)據(jù)檢測(cè)的調(diào)試功能。平時(shí)用...
    Thinkdifferents閱讀 1,951評(píng)論 1 4
  • 推薦指數(shù): 6.0 書籍主旨關(guān)鍵詞:特權(quán)、焦點(diǎn)、注意力、語(yǔ)言聯(lián)想、情景聯(lián)想 觀點(diǎn): 1.統(tǒng)計(jì)學(xué)現(xiàn)在叫數(shù)據(jù)分析,社會(huì)...
    Jenaral閱讀 5,950評(píng)論 0 5

友情鏈接更多精彩內(nèi)容