lldb 調(diào)試實戰(zhàn)
0x0 命令結構
<noun> <verb> [-options [option-value]] [argument [argument...]]
其中options和argument是可選的.
0x1 常用命令
1峻仇,設置斷點:
(lldb) br set --file ViewController.m --line 20
Breakpoint 4: where = LLDB`-[ViewController viewDidLoad] + 54 at ViewController.m:20, address = 0x000000010a8f3696
2 计技,查看當前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不同,它不會打出對象的詳細信息尾组,只會打印出一個$符號忙芒,數(shù)字示弓,再加上一段地址信息。由于po命令下呵萨,對象的description 有可能被隨便亂改奏属,沒有輸出地址消息。
$符號在LLDB中代表著變量的分配潮峦。每次使用p后囱皿,會自動為你分配一個變量,后面再次想使用這個變量時忱嘹,就可以直接使用铆帽。我們可以直接使用這個地址做一些轉換,獲取對象的信息
4, watchpoint的作用是監(jiān)控某一塊內(nèi)存的內(nèi)容是否發(fā)生改變, 如果發(fā)生改變則斷點斷住.
watchpoint set self->testVar //為該變量地址設置watchpoint
watchpoint set expression 0x00007fb27b4969e0 //為該內(nèi)存地址設置
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 打印出當前線程的堆棧信息爹橱,
(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"
其中關注下thread.index也就是當前的thread索引;frame.pc也就是frame停留位置的指令的地址(pc代表pc寄存器, 存放的是當前指令的地址); thread.queue當前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"
其中關注下frame.index也就是frame的索引;frame.pc也就是停留位置的指令的地址;還有就是方法名稱和參數(shù).
上面截出來的信息中, thread #1和frame #1前面有一個*, 代表當前選中的thread和frame.可以通過frame variable命令(縮寫fr v)查看當前frame的變量:
0x3 常用的指令
bt // 打出當前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方法處下斷點
br s -f test.c -l 12 // 在test.c的第12行下斷點
b -[NSString stringWithFormat:] // 在這個方法下斷點
br s -S count // 給所有的selector是count的方法下斷點
br s -n foo -c '(int)strcmp(y,"hello") == 0' // 條件斷點
br s -a 0x10002ab0c // 在地址上下斷點
br l // 列出所有斷點
br del 1 // 刪除1號斷點, 可以通過 br l查斷點號
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 // 從鏡像中查地址對應的內(nèi)容
im lookup -r -n <FUNC_REGEX> // 從鏡像中用正則查出debug符號, 不帶-r是不用正則
im lookup -r -s <FUNC_REGEX> // 從鏡像中用正則查出非debug符號, 不帶-r是不用正則
im lookup -t NSString // 從鏡像中查找類型NSString