LLDB使用篇(上)
LLDB是個開源的內置於XCode的具有REPL(read-eval-print-loop)特征的Debugger,其可以安裝C++或者Python插件。
本系列針對於已經知道何為debugger,且有gdb或者lldb使用經驗的讀者。對於lldb的嫻熟使用者,也可以用來作為查閱手冊。
這一篇,我們講述lldb內建的命令。
lldb與gdb命令名的對照表:http://lldb.llvm.org/lldb-gdb.html
1.help命令
單單執行help命令會列出所有命令列表,用戶加載的插件一般來說列在最後。
執行help 可以打印指定command的幫助信息,至於插件提供的命令,其幫助信息取決於插件本身的實現。
例如 help print會打印內建命令print的使用幫助。
2.print命令
print命令的簡化方式有prin pri p,唯獨pr不能用來作為檢查,因為會和process混淆,幸運的是p被lldb實現為特指print。
實際上你會發現,lldb對於命令的簡稱,是頭部匹配方式,只要不混淆,你可以隨意簡稱某個命令。
例如:
值得說明的是,返回的$0是命令結果的引用名,使用$0可以進行print $0 + 7這樣打印出106,當然,$0可以被用於任何其他表達式或者接收參數的命令。
3.expression命令
expression命令可以用來修改變量的值,當然大部分情況下,使用xcode提供的可視化編輯器更方便。
1 2 3 4 |
(lldb) p count
(NSUInteger) $4 = 12
(lldb)e count = 42
(NSUInteger) $5 = 42
|
實際上print相當於expression --,而--的意思是命令的參數終止,跟在--後面的都是命令的輸入數據。
要打印一個對象,則需要使用e -O -- anObj,而e -O -- 的縮寫正是我們常用的po命令:
1 2 3 4 5 |
(lldb) po $8
(
foo,
bar
)
|
要按特定格式來打印一個變量則使用p/
命令:
1 2 3 4 5 6 7 8 |
(lldb) p 16
16
(lldb)p/x 16
0x10
(lldb) p/t 16
0b00000000000000000000000000010000
(lldb) p/t ( char )16
0b00010000
|
或者使用p/c打印字符,p/s打印c字符串,詳細格式查閱這裏。
既然我們已經知道print實際上是expression --的簡寫,那麽在p(或者po)後面跟上復雜的表達式則可以先計算表達式再打印最後的計算結果。
1 2 3 4 5 6 7 8 9 10 11 |
(lldb) e int $a = 2
(lldb) p $a * 19
38
(lldb) e NSArray *$array = @[ @ "Saturday" , @ "Sunday" , @ "Monday" ]
(lldb) p [$array count]
3
(lldb) po [[$array objectAtIndex:0] uppercaseString]
SATURDAY
(lldb) p [[$array objectAtIndex:$a] characterAtIndex:0]
error: no known method ‘-characterAtIndex:‘ ; cast the message send to the method‘s return type
error: 1 errors parsing expression
|
值得註意的是,一旦出現了上述錯誤提示,說明lldb無法判定某一步的計算結果是什麽數據類型,這時需要強制類型轉換來告訴lldb:
1 2 3 4 |
(lldb) p ( char )[[$array objectAtIndex :$a] characterAtIndex : 0 ]
‘M‘
(lldb) p/d ( char )[[$array objectAtIndex :$a] characterAtIndex : 0 ]
77
|
4.流程控制命令
實際上使用xcode自帶的可視化工具來控制“繼續”“暫停”“下一步”“進入”“跳出”更簡單,但這裏還是列出其所對應的命令名:
繼續:process continue, continue, c
下一步:thread step-over, next, n
進入:thread step-in, step, s
跳出:thread step-out, finish, f
5.thread return命令
執行thread return命令可以使得當前函數立即返回,也就是說,後續代碼都不會執行了。當然執行此命令可能會使得arc的計數追蹤出現錯亂。
thread return命令需要一個參數來指明函數強制返回時的返回值。
6.斷點命令
一般來說,在xcode中新建/刪除“行斷點”是很容易的,但是斷點還有很多進階使用方法:
條件斷點、條件執行、記錄日誌、自動繼續、重復斷點跳過。
使用xcode提供的可視化工具來操作是很容易的:
7.在debugger中執行任意代碼
1 2 3 4 5 6 7 |
(lldb) e char *$str = ( char *)malloc( 128 )
(lldb) e ( void )strcpy($str, "wxrld of warcraft" )
(lldb) e $str[ 1 ] = ‘o‘
( char ) $ 0 = ‘o‘
(lldb) p $str
( char *) $str = 0x00007fd04a900040 "world of warcraft"
(lldb) e ( void )free($str)
|
所以,在debugger中可以修改view的顏色、尺寸、甚至創建controller來push。
8.watchpoint
watchpoint可以在某個變量被寫入/讀取時暫停程序運行:
1 2 3 4 5 6 7 8 9 10 11 |
(lldb) watchpoint set expression -- ( int *)&_abc4
Watchpoint created : Watchpoint 7 : addr = 0x15e36d3c size = 4 state = enabled type = w
new value : 0x00000000
(lldb) watchpoint set v -w read _abc4
Watchpoint created : Watchpoint 8 : addr = 0x15e36d3c size = 4 state = enabled type = r
watchpoint spec = ‘_abc4‘
new value : 0
(lldb) watchpoint set v -w read_write _abc3
Watchpoint created : Watchpoint 9 : addr = 0x15e36d38 size = 4 state = enabled type = rw
watchpoint spec = ‘_abc3‘
new value : 0
|
實際上可以使用watchpoint來監視任意一段內存的讀寫。
使用XCode也可以方便地創建watchpoint。
XCode的可視化debug工具中的watch是一個write類型watchpoint(也就是默認的)
另外,上述語句中 v是variable的簡寫,同樣的,set可以簡寫為s,watch可以簡寫為wa,而-w後面的參數是不可以簡寫的必須為read、write或者read_write。
當前在arm和x86上,我們一次最多創建4個watchpoint,繼續創建會提示錯誤。
9.符號斷點
用xcode的可視化工具創建符號斷點很簡單,在Add symbolic breakpoint中填入符號名即可,這裏給出objective-c的函數符號斷點的寫法:
1 2 |
-[MyViewController viewDidAppear :]
+[MyViewController sharedInstance ]
|
10.查看內存
使用XCode的可視化工具來查看memory,要註意watch memory of "p" 和watch memory of "*p"的區別。
手動執行命令可以help x或者 help memory。
小結
lldb的用法很靈活多樣,但是XCode的可視化調試工具覆蓋面有限,一些高級用法仍需手動輸入命令,甚至結合python腳本。
下一篇,我們將講解lldb中的python腳本使用。
http://www.dreamingwish.com/article/lldb-usage-a.html
LLDB使用篇(上)