lldb

lldb 調(diào)試實(shí)戰(zhàn)

0x0 命令結(jié)構(gòu)

<noun> <verb> [-options [option-value]] [argument [argument...]]

其中options和argument是可選的.

0x1 常用命令

1,設(shè)置斷點(diǎn):

(lldb) br set --file ViewController.m --line 20
Breakpoint 4: where = LLDB`-[ViewController viewDidLoad] + 54 at ViewController.m:20, address = 0x000000010a8f3696

2 ,查看當(dāng)前thread 的backtrace

thread backtrace 縮寫為 bt

* thread #1: tid = 0x82ccc, 0x000000010885d954 LLDB`-[Object init](self=0x000060800000f0f0, _cmd="init") + 20 at main.m:18, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x000000010885d954 LLDB`-[Object init](self=0x000060800000f0f0, _cmd="init") + 20 at main.m:18
    frame #1: 0x000000010885da27 LLDB`main(argc=1, argv=0x00007fff573a26a8) + 71 at main.m:27
    frame #2: 0x000000010c23268d libdyld.dylib`start + 1
    frame #3: 0x000000010c23268d libdyld.dylib`start + 1

3,查詢變量
po的作用為打印對象 ,p即是print,也是expression --的縮寫,與po不同,它不會(huì)打出對象的詳細(xì)信息,只會(huì)打印出一個(gè)$符號,數(shù)字,再加上一段地址信息。由于po命令下,對象的description 有可能被隨便亂改,沒有輸出地址消息。

2.png

$符號在LLDB中代表著變量的分配。每次使用p后,會(huì)自動(dòng)為你分配一個(gè)變量,后面再次想使用這個(gè)變量時(shí),就可以直接使用。我們可以直接使用這個(gè)地址做一些轉(zhuǎn)換,獲取對象的信息

4, watchpoint的作用是監(jiān)控某一塊內(nèi)存的內(nèi)容是否發(fā)生改變, 如果發(fā)生改變則斷點(diǎn)斷住.

 watchpoint set self->testVar     //為該變量地址設(shè)置watchpoint
 
 watchpoint set expression 0x00007fb27b4969e0 //為該內(nèi)存地址設(shè)置
 
 watchpoint,內(nèi)存地址可從前文提及的`p`命令獲取
 
 watchpoint command add -o 'frame info' 1  //為watchpoint 1號加上子命令 `frame info`
 
 watchpoint list //列出所有watchpoint
 
 watchpoint delete // 刪除所有watchpoint

0x2 Thread && Frame

用bt 打印出當(dāng)前線程的堆棧信息,

(lldb) bt
* thread #1: tid = 0x82ccc, 0x000000010885d954 LLDB`-[Object init](self=0x000060800000f0f0, _cmd="init") + 20 at main.m:18, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x000000010885d954 LLDB`-[Object init](self=0x000060800000f0f0, _cmd="init") + 20 at main.m:18
    frame #1: 0x000000010885da27 LLDB`main(argc=1, argv=0x00007fff573a26a8) + 71 at main.m:27
    frame #2: 0x000000010c23268d libdyld.dylib`start + 1
    frame #3: 0x000000010c23268d libdyld.dylib`start + 1

這段backtrace信息中有兩種不同類型的信息, 分別是thread 和 frame. 其中thread的格式如下:

(lldb) settings show thread-format
thread-format (format-string) = "thread #${thread.index}: tid = ${thread.id%tid}{, ${frame.pc}}{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}{ at ${line.file.basename}:${line.number}}{, name = '${thread.name}'}{, queue = '${thread.queue}'}{, activity = '${thread.info.activity.name}'}{, ${thread.info.trace_messages} messages}{, stop reason = ${thread.stop-reason}}{\nReturn value: ${thread.return-value}}{\nCompleted expression: ${thread.completed-expression}}\n"

其中關(guān)注下thread.index也就是當(dāng)前的thread索引;frame.pc也就是frame停留位置的指令的地址(pc代表pc寄存器, 存放的是當(dāng)前指令的地址); thread.queue當(dāng)前queue的名字.

frame的格式如下:

(lldb) settings show frame-format
frame-format (format-string) = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}{ at ${line.file.basename}:${line.number}}{${function.is-optimized} [opt]}\n"

其中關(guān)注下frame.index也就是frame的索引;frame.pc也就是停留位置的指令的地址;還有就是方法名稱和參數(shù).

上面截出來的信息中, thread #1和frame #1前面有一個(gè)*, 代表當(dāng)前選中的thread和frame.可以通過frame variable命令(縮寫fr v)查看當(dāng)前frame的變量:

0x3 常用的指令

bt // 打出當(dāng)前thread的backtrace
bt all // 打出所有thread的backtrace
po [SomeClass returnAnObject] // 執(zhí)行代碼并打印出返回值的description
po $x9 = 0 // 直接寫寄存器, 不要后面的`= 0`則是把寄存器`x9`的內(nèi)容打出來
fr v // 打出frame的變量
fr s 1 // 選擇frame
br s -n main // 在main方法處下斷點(diǎn)
br s -f test.c -l 12 // 在test.c的第12行下斷點(diǎn)
b -[NSString stringWithFormat:] // 在這個(gè)方法下斷點(diǎn)
br s -S count // 給所有的selector是count的方法下斷點(diǎn)
br s -n foo -c '(int)strcmp(y,"hello") == 0' // 條件斷點(diǎn)
br s -a 0x10002ab0c // 在地址上下斷點(diǎn)
br l // 列出所有斷點(diǎn)
br del 1 // 刪除1號斷點(diǎn), 可以通過 br l查斷點(diǎn)號
w s v global_var // 對變量下watchpoint
w s e -- my_ptr // 對指針下watchpoint
w s e 0x10002ab0c //  對地址下watchpoint
w l // 打出watchpoint
w de // 刪除watchpoint
ta v foo // 打印全局變量foo
reg re // 打出常用寄存器的內(nèi)容
x -s4 -fx -c4 0xbffff3c0 // 打出內(nèi)存內(nèi)容. 完整命令是: memory read --size 4 --format x --count 4 0xbffff3c0
im list // 列出鏡像
im lookup -a 0x00000001875b60fe // 從鏡像中查地址對應(yīng)的內(nèi)容
im lookup -r -n <FUNC_REGEX> // 從鏡像中用正則查出debug符號, 不帶-r是不用正則
im lookup -r -s <FUNC_REGEX> // 從鏡像中用正則查出非debug符號, 不帶-r是不用正則
im lookup -t NSString // 從鏡像中查找類型NSString

0x4 參考

LLDB - GETTING STARTED

LLDB - GDB TO LLDB COMMAND MAP

LLDB - STACK FRAME AND THREAD FORMAT

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載 與調(diào)試器共舞 - LLDB 的華爾茲: https://objccn.io/issue-19-2/ 推薦:i...
    F麥子閱讀 3,357評論 0 10
  • [轉(zhuǎn)]淺談LLDB調(diào)試器文章來源于:http://www.cocoachina.com/ios/20150126/...
    loveobjc閱讀 2,591評論 2 6
  • 前言 LLDB是個(gè)開源的內(nèi)置于XCode的具有REPL(read-eval-print-loop)特征的Debug...
    Noskthing閱讀 18,565評論 10 89
  • LLDB的Xcode默認(rèn)的調(diào)試器,它與LLVM編譯器一起,帶給我們更豐富的流程控制和數(shù)據(jù)檢測的調(diào)試功能。平時(shí)用Xc...
    小笨狼閱讀 20,605評論 31 186
  • 網(wǎng)頁布局基礎(chǔ) 什么是網(wǎng)頁布局?網(wǎng)頁布局是網(wǎng)頁制作的基礎(chǔ)(DIV+CSS網(wǎng)頁布局) 分類:流式布局,浮動(dòng)布局,絕對定...
    單純的土豆閱讀 1,869評論 0 6