當前位置:
首頁 >
LLDB 调试
發布時間:2025/6/17
39
豆豆
LLDB是 XCode 內置的為我們開發者提供的調試工具。 LLDB 可以提供的服務: print
- 允許你在程序的特定時刻暫停它;
- 允許你查看變量的值;
- 執行自定的指令;
- 按照你所認為合適的步驟來操作程序的進展。
語法
<command> [<subcommond>] 唯一匹配原則:假如根據前n個字母已經能唯一匹配到某個命令,則只寫前n個字母等效于寫下完整的命令。 每一個 LLDB 命令都包含著 0 個到多個子命令,并且可能具有一個到多個可選參數。 --:表示命令(或子命令)的結束,以及輸入的開始。 express -h +17,讓人很困惑,到底是以 -h 為標識,僅僅執行 +17,還是計算 17 和 h 的差值。所以用 -- 表示標識的結束和輸入的開始。如果想要 -h 作為標識,就用 express -h -- +17。如果是要計算他們的差值,就使用 express -- -h +17。因為一般不使用標識的情況比較多,所以 express -- 就有了一個簡寫方式,那就是 print。 輸入 help print 可以看到。 []:表示可選。常用命令
help
列舉出所有的命令,可以通過 help <command> 來了解更多細節。 例如:help thread help print 等。apropos
有的時候,可能并不能完全記得某個命令,只記得某個關鍵詞。就可以使用 apropos 搜索到相關命令信息。 例如:(lldb) apropos stop-hook- 打印值
- 打印對象
- 打印變量
expression
執行指定表達式,并將結果打印出來。常用于改變調試器中的值,即改變程序中的值。 完整語法: express <cmd -options> -- <expr> <cmd -options>:命令選項,使用默認即可; <expr >:要執行的表達式 調試過程中,我們經常用到假設某個變量是某個值,就不需要代碼寫死了;只需打個斷點,執行如下即可,非常方便。 例:expr a = 10 在 lldb 中聲明一個對象,為了下文中可以使用聲明的變量,變量必須以 美元符開頭。 (lldb) e int $a = 2 (lldb) p $a * 19 -> 38 (lldb) e NAArray *$array = @[@"Sturday", @"Sunday"] (lldb) p [$array count] ->2 (lldb) po [[$array objectAtIndex:0] uppercaseString] -> SATURDAY 注:lldb 無法確定返回的類型thread backtrace & bt
打印線程堆棧信息 完整語法: thread backtrace [-c <count>] [-s <frame-index>] [-e <boolean>] -c:設置打印堆棧的幀數 -s:設置從哪個幀開始打印 -e:是否顯示額外的回溯 實際上這些命令選項一般不需要使用。 當發生 crash 時,可以使用 (lldb) thread backtrace //查看棧幀信息 該命令還有一個別名:bt bt all:打印所有的 thread 堆棧thread return
thread return [<expr>] 該命令可以接受一個表達式,調用命令后直接從當前的 frame 返回表達式的值。 //它有一個可選參數,在執行時它會把可選參數加載進返回寄存器里,然后立刻執行返回命令,跳出當前棧幀。這意味這函數剩余的部分不會被執行。這會給 ARC 的引用計數造成一些問題,或者會使函數內的清理部分失效。但是在函數的開頭執行這個命令,是個非常好的隔離這個函數,偽造返回值的方式 。 thread 還有一些不常用的命令 thread jump:直接讓程序跳到某一行。ARC 下編譯器實際插入了不少 retain,release命令,跳過一些代碼不執行很可能會造成對象內存混亂發生 crash。 thread list:列出所有的線程。 thread select:選擇某個線程。 thread until:傳入一個 line 參數,讓程序執行到這行的時候暫停。 thread info:輸出當前線程的信息。watchpoint
觀察變量或者屬性
這是一個非常有用的東西,我們經常遇到,某一個變量,不知道什么時候值被改掉了,就可以使用這個東西去定位: (lldb) watchpoint set variable self->_string 不能使用點語法watchpoint set expression (觀察地址)
如果想觀察某個地址,可以使用 watchpoint set expression 例如:先拿到 _model 的地址,然后對地址設置一個 watchpoint (lldb) p &_model (Modek **) $3 = 0x00007fe0dbf23280 (lldb) watchpoint set expression 0x00007fe0dbf23280 Watchpoint created: Watchpoint 1: addr = 0x7fe0dbf23280 size = 8 state = enabled type = w ????new value: 0 watchpoint command 跟 breakpoint 類似,watchpoint 也可以添加命令 watchpoint command add (添加觀察點) 例如: (lldb) watchpoint set variable xxx Watchpoint created: Watchpoint 1: addr = 0x7fe4e1444760 size = 8 state = enabled type = w ????watchpoint spec = '_string' ????new value: 0x0000000000000000 watchpoint 的 id 是1. watchpoint command add -o 'bt' 1 在 watchpoint 停下來時,打印了它的線程信息 也可以添加多條命令: (lldb) watchpoint command add 1 Enter your debugger command(s).??Type 'DONE' to end. > bt > continue > DONE watchpoint command list (某觀察點所有命令) watchpoint command list 1 列出某個 watchpoint 的所有 command watchpoint command delete (觀察點刪除) watchpoint command delete 1 刪除某個 watchpoint 所有的 command watchpoint list (觀察點列表) 查看當前所有的 watchpoint,使用 watchpoint list watchpoint disable (觀察點失效) 讓某個 watchpoint 失效 watchpoint enable (觀察點生效) 使某個 watchpoint 生效 watchpoint delete index 刪除某個 watchpoint。 不指定 index,則刪除所有的 watchpoint。target modules & image:查找地址對應的文件位置
LLDB 給 target modules 取了個別名 image。 image lookup -address 查找這個地址具體對應的文件位置。 比如: TLLDB[25086:246169] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 1 beyond bounds for empty NSArray' *** First throw call stack: ( 0?? CoreFoundation??????????????????????0x000000010accde65 __exceptionPreprocess + 165 1?? libobjc.A.dylib???????????????????? 0x000000010a746deb objc_exception_throw + 48 2?? CoreFoundation??????????????????????0x000000010ac7c395 -[__NSArray0 objectAtIndex:] + 101 3?? TLLDB?????????????????????????????? 0x000000010a1c3e36 -[ViewController viewDidLoad] + 86 4?? UIKit?????????????????????????????? 0x000000010b210f98 -[UIViewController loadViewIfRequired] + 1198 5?? UIKit?????????????????????????????? 0x000000010b2112e7 -[UIViewController view] + 27 ) 我們可以看到數組越界了,但是 objectAtIndex: 的代碼在哪呢? 使用 image lookup (lldb) image lookup -a 0x000000010a1c3e36 ??????Address: TLLDB[0x0000000100000e36] (TLLDB.__TEXT.__text + 246) ??????Summary: TLLDB`-[ViewController viewDidLoad] + 86 at ViewController.m:32 image lookup -name 查找一個方法 或者 符號的信息 例如: 第三方 SDK 有一個 Dictionary 的 catagory,和我們自己的 catagory 沖突了,但是不知道在哪個 .a 里面。 使用 image lookup -n dictionaryWithXMLString: 即可。 image lookup -type 查看一個類型 image lookup -t Model 所有的屬性,實例變量都會打出來 target stop-hook 使用 LLDB debug,大多數時候需要讓程序 stop。該命令可以在每次 stop 的時候去執行一些命令。 target stop-hook add & display 例如:每次程序 stop 時,都用命令打印當前 frame 的所有變量。可以添加一個 stop-hook (lldb) target stop-hook add -o "frame variable" -o:--one-liner,表示添加一條命令。 LLDB 提供了一個更簡便的命令:display。下面這兩條等同 (lldb) target stop-hook add -o "p self.view" (lldb) display self.view target stop-hook list 可以查看所有的 stop-hook target stop-hook delete & undisplay 刪除某個 stop-hook (lldb) target stop-hook delete index (lldb) undisplay index target stop-hook disable/enable 使某個 stop-hook 失效/生效。 參考文章 與調試器共舞 - LLDB 的華爾茲 dSYM詳細資料 iOS中framework的聯調轉載于:https://www.cnblogs.com/lion-witcher/p/10405205.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
- 上一篇: css学习笔记2--多重边框
- 下一篇: 265. To B 端 Web 页面上线