- 動態(tài)調(diào)試概念
- Xcode動態(tài)調(diào)試原理
- 調(diào)試任意第三方App
- LLDB簡介
一 動態(tài)調(diào)試概念
就是在程序運行的過程中爸黄,通過打斷點滞伟,或者log輸出等方式,查看函數(shù)調(diào)用流程炕贵,以及一些變量梆奈,參數(shù),返回值等等這一系列流程. 在iOS開發(fā)中称开,直觀上來講我們經(jīng)常利用Xcode來進行App的動態(tài)調(diào)試亩钟。
我們平時利用Xcode調(diào)試乓梨,只要點一下右面的箭頭,運行程序清酥,在我們想要斷點的數(shù)字列表點一下扶镀,然后程序運行到這個地方的時候就會自行斷點了,用起來非常方便总处,但是Xcode這個動態(tài)調(diào)試是怎么實現(xiàn)的呢狈惫,讓我們一起來深入了解一下。
二 Xcode動態(tài)調(diào)試原理
要想了解Xcode動態(tài)調(diào)試原理鹦马,我們需要了解兩個東西 LLDB胧谈,debugserver。Xcode就是利用這兩個工具進行動態(tài)調(diào)試的荸频。
2.1 什么是LLDB菱肖,debugserver
1 LLDB是Mac OS X上Xcode的默認調(diào)試器,支持在桌面和iOS設(shè)備和模擬器上調(diào)試C旭从,Objective-C和C ++
2 debugserver是運行在iOS上作為服務(wù)端稳强,接收和執(zhí)行LLDB傳過來的命令,再把執(zhí)行結(jié)果反饋給LLDB,顯示給用戶和悦。
2.2 Xcode動態(tài)調(diào)試流程
Xcode通過LLDB調(diào)試器把調(diào)試指令發(fā)送到手機上的debugserver,debugserver將命令轉(zhuǎn)給相應(yīng)的app,app將反饋信息給debugserver , 最后debugserver將命令執(zhí)行結(jié)果返回給lldb退疫,然后Xcode在界面進行結(jié)果展示。
2.3 debugserver細節(jié)的一些講解
1 debugserver是手機內(nèi)置的么鸽素?
debugserver一開始是不在iPhone手機上的褒繁,當我們Xcode第一次連接手機時,Xcode會自動將debugserver安裝到手機上馍忽,所以當Xcode連接手機時棒坏,會很慢,其實它要做很多初始化配置工作的遭笋。
2 debugserver存在哪個目錄坝冕?
一開始是存在Mac的Xcode里面的/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/De viceSupport/9.0/DeveloperDiskImage.dmg/usr/bin/debugserver的,安裝到手機上后會放到手機的/Developer/usr/bin/debugserver目錄下瓦呼。
目前Xcode只能連接它所運行的App喂窟,那么如何調(diào)試手機上已經(jīng)安裝的App呢,通過Xcode肯定不行了。我們只能用LLDB終端來進行了央串,下面看我們該如何做谎替。
三 調(diào)試任意第三方App
上面我們知道,要想動態(tài)調(diào)試一個App只能通過Xcode安裝運行的蹋辅,為什么會這樣呢,那是因為debugserver權(quán)限被限制了挫掏,那么要想調(diào)試別的App侦另,就需要給debugserver附加額外的權(quán)限,我們主要添加下面兩個權(quán)限:
get-task-allow:布爾類型,是否允許其他進程(比如調(diào)試器)褒傅,附加到你的應(yīng)用程序上弃锐。
task_for_pid-allow:布爾類型,是否允許通過進程ID獲取任務(wù)
加上這兩個權(quán)限之后我們的debugserver就能夠訪問任何App的權(quán)限了殿托,如何附加這兩個權(quán)限霹菊,主要有這幾步。
1 利用ldid導出debugeserver權(quán)限描述文件
把手機/Developer/usr/bin/debugserver拷貝一份到到電腦桌面支竹,然后調(diào)用如下命令
xmldeMacBook-Pro:Desktop xml$ ldid -e debugserver > debugserver.entitlements
2 打開導出的描述文件添加權(quán)限
3 利用codesign重新給debugserver簽名
xmldeMacBook-Pro:Desktop xml$ codesign -s - --entitlements debugserver.entitlements -f debugserver
debugserver: replacing existing signature
4 查看是否簽名成功
xmldeMacBook-Pro:Desktop xml$ ldid -e debugserver
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "[http://www.apple.com/DTDs/PropertyList-1.0.dtd](http://www.apple.com/DTDs/PropertyList-1.0.dtd)">
<plist version="1.0">
<dict>
<key>get-task-allow</key>
<true/>
<key>task_for_pid-allow</key>
<true/>
<key>com.apple.developer.ubiquity-container-identifiers</key>
<string></string>
<key>com.apple.backboardd.debugapplications</key>
<true/>
<key>com.apple.backboardd.launchapplications</key>
<true/>
<key>com.apple.diagnosticd.diagnostic</key>
<true/>
<key>com.apple.frontboard.debugapplications</key>
<true/>
<key>com.apple.frontboard.launchapplications</key>
<true/>
<key>[com.apple.security.network.client](http://com.apple.security.network.client/)</key>
<true/>
<key>[com.apple.security.network.server](http://com.apple.security.network.server/)</key>
<true/>
<key>com.apple.springboard.debugapplications</key>
<true/>
<key>run-unsigned-code</key>
<true/>
<key>seatbelt-profiles</key>
<array>
<string>debugserver</string>
</array>
</dict>
</plist>
我們看剛添加的權(quán)限已經(jīng)添加上了旋廷,添加權(quán)限就這么幾步,我們把接下來的流程走完礼搁,看看如何去動態(tài)調(diào)試第三方App
5 把重簽權(quán)限的debugserver放到手機/Device/usr/bin目錄下
6 給debugserver執(zhí)行權(quán)限
applede-iPhone:/ root# chmod +x /usr/bin/debugserver
7 通過USB轉(zhuǎn)接debugserver的連接端口
連接debugserver饶碘,需要指定一個端口號,我們跟ssh遠程登錄手機一樣馒吴,我們也用usbmuxd做一下轉(zhuǎn)接
xmldeMacBook-Pro:~ xml$ python /Users/xml/Desktop/python-client/tcprelay.py -t 22:10001 11111:11111
Forwarding local port 10001 to remote port 22
Forwarding local port 11111 to remote port 11111
Incoming connection to 10010
Waiting for devices...
Connecting to device <MuxDevice: ID 7 ProdID 0x12a8 Serial 'e567d7aa5cc942955b30d0d95128c964cdfacc01' Location 0x14200000>
Connection established, relaying data
10001是我們映射的遠程登錄手機的端口扎运,11111是我們映射的連接debugserver的端口。
8 把debugserver附加的某個APP進程上
debugserver *:端口號 -a 進程
applede-iPhone:/ root# debugserver *:11111 -a WeChat
debugserver-@(#)PROGRAM:debugserver PROJECT:debugserver-360.0.26.1
for arm64.
Attaching to process WeChat...
Listening to port 11111 for a connection from *…
我把它附加到微信的進程上饮戳,注意這里你的手機要打開微信App豪治,我們說一下命令的兩個參數(shù)。
端口號:就是使用手機的某個端口啟動debugserver扯罐,剛才我們用usbmuxd映射的是11111這個端口负拟,那么這里我們也用11111這個端口來啟動debugserver.
進程:這里的進程就是App的進程ID或者進程名稱
9 Mac上個啟動LLDB,遠程連接iPhone上的debugserver服務(wù)篮赢。
xmldeMacBook-Pro:~ xml$ lldb
(lldb) process connect [connect://localhost:11111](connect://localhost:11111)
Process 23254 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
frame #0: 0x0000000184e89188 libsystem_kernel.dylib`mach_msg_trap + 8
libsystem_kernel.dylib`mach_msg_trap:
-> 0x184e89188 <+8>: ret
libsystem_kernel.dylib`mach_msg_overwrite_trap:
0x184e8918c <+0>: mov x16, #-0x20
0x184e89190 <+4>: svc #0x80
0x184e89194 <+8>: ret
Target 0: (WeChat) stopped.
(lldb) c
Process 23254 resuming
到此調(diào)試任意App的整個環(huán)境流程就完了齿椅,接下來就是輸入LLDB命令開始調(diào)試了,一開始連接好启泣,是要在LLDB終端輸入c命令才能繼續(xù)調(diào)試涣脚。
最后補充下,如何通過debugserver直接啟動一個App
$ debugserver -x auto *:端口號 APP的可執(zhí)行文件路徑
applede-iPhone:/ root# debugserver -x auto *:11111
四 LLDB簡介
LLDB是Mac OS X上Xcode的默認調(diào)試器寥茫,支持在桌面和iOS設(shè)備和模擬器上調(diào)試C遣蚀,Objective-C和C ++,這里我們主要講解一些它的常用命令。
LLDB指令格式
<command> [<subcommand> [<subcommand>...]] <action> [-options [option-
value]] [argument [argument...]]
<command>: 命令
[<subcommand> [<subcommand>...]] : 子命令
<action>: 命令操作
[-options [option-value]]: 命令選項
[argument [argument...]]:命令參數(shù)
下面是一個使用示例
breakpoint: 命令
list : 子命令
-v : 命令操作
2:命令參數(shù)
LLDB命令格式基本格式都是這樣的纱耻,命令的子命令芭梯,命令操作,命令選項弄喘,命令參數(shù)都是可選項玖喘,那么格式就是這樣的,接下來我們看一下蘑志,常用的一些命令累奈。
1 幫助命令 help
如果遇到一個指令你不知道怎么用,那么就使用help命令查看它的一些詳細用法
(lldb) help breakpoint
Commands for operating on breakpoints (see 'help b' for shorthand.)
Syntax: breakpoint <subcommand> [<command-options>]
The following subcommands are supported:
clear -- Delete or disable breakpoints matching the specified source
file and line.
command -- Commands for adding, removing and listing LLDB commands
executed when a breakpoint is hit.
delete -- Delete the specified breakpoint(s). If no breakpoints are
specified, delete them all.
disable -- Disable the specified breakpoint(s) without deleting them. If
none are specified, disable all breakpoints.
enable -- Enable the specified disabled breakpoint(s). If no breakpoints
are specified, enable all of them.
list -- List some or all breakpoints at configurable levels of detail.
modify -- Modify the options on a breakpoint or set of breakpoints in
the executable. If no breakpoint is specified, acts on the
last created breakpoint. With the exception of -e, -d and -i,
passing an empty argument clears the modification.
name -- Commands to manage name tags for breakpoints
read -- Read and set the breakpoints previously saved to a file with
"breakpoint write".
set -- Sets a breakpoint or set of breakpoints in the executable.
write -- Write the breakpoints listed to a file that can be read in
with "breakpoint read". If given no arguments, writes all
breakpoints.
For more help on any particular subcommand, type 'help <command> <subcommand>'.
(lldb) help po
Evaluate an expression on the current thread. Displays any returned value
with formatting controlled by the type's author. Expects 'raw' input (see
'help raw-input'.)
Syntax: po <expr>
Command Options Usage:
po <expr>
'po' is an abbreviation for 'expression -O --'
(lldb)
2 表達式命令 expression --
執(zhí)行一個表達式贬派,任何可執(zhí)行的OC代碼行
-- :是命令選項結(jié)束符,標示所有命令選項已經(jīng)設(shè)置完畢澎媒,如果沒有命令選項搞乏,--可以不用寫
(lldb) expression NSLog(@"已經(jīng)越獄")
2019-03-09 16:16:01.565070+0800 test[3156:116239] 已經(jīng)越獄
(lldb) expression -A -- self.view
(UIView *) $1 = 0x00007f9655c04060
(lldb) expression self.view.backgroundColor = [UIColor redColor]
(UICachedDeviceRGBColor *) $0 = 0x00006000013004c0
使用表達式命令,我們就可以動態(tài)添加代碼執(zhí)行戒努,比如我們有兩個視圖疊加一塊了请敦,但是我們想知道一個視圖有沒有被遮擋,我們就可以使用表達式命令储玫,給其中一個視圖添加一個顏色侍筛,這樣我們就能區(qū)分了,再也不用手動寫一下代碼缘缚,然后再重新執(zhí)行一下了勾笆。
expression,expression --和指令print桥滨,p窝爪,call效果都是一樣的
(lldb) expression self.view.backgroundColor = [UIColor redColor]
(UICachedDeviceRGBColor *) $0 = 0x00006000013004c0
(lldb) expression self.view
(UIView *) $1 = 0x00007fb7f3703700
(lldb) p self.view
(UIView *) $2 = 0x00007fb7f3703700
(lldb) print self.view
(UIView *) $3 = 0x00007fb7f3703700
(lldb) call self.view
(UIView *) $4 = 0x00007fb7f3703700
(lldb)
我們經(jīng)常用p 來執(zhí)行表達式命令,比寫expression要少好多字符是吧齐媒。
expression -O --和指令po的效果都是一樣的用來打印對象本身
(lldb) expression -o -- self.view
<UIView: 0x7fb7f3703700; frame = (0 0; 414 896); autoresize = W+H; layer = <CALayer: 0x600000677500>>
(lldb) po self.view
<UIView: 0x7fb7f3703700; frame = (0 0; 414 896); autoresize = W+H; layer = <CALayer: 0x600000677500>>
為什么效果都是一樣蒲每,因為他們都是expression命令一些操作的別名,本身就是一個東西喻括,相當于起了個外號邀杏,方便好記好用。
3 thread backtrace 打印線程的堆棧信息唬血,別名bt
(lldb) thread backtrace
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x00000001010e9884 test`-[ViewController viewDidLoad](self=0x00007fb7f37023f0, _cmd="viewDidLoad") at ViewController.m:16
frame #1: 0x0000000104cb64e1 UIKitCore`-[UIViewController loadViewIfRequired] + 1186
frame #2: 0x0000000104cb6940 UIKitCore`-[UIViewController view] + 27
frame #3: 0x000000010530dc53 UIKitCore`-[UIWindow addRootViewControllerViewIfPossible] + 122
frame #4: 0x000000010530e36e UIKitCore`-[UIWindow _setHidden:forced:] + 294
frame #5: 0x00000001053215c0 UIKitCore`-[UIWindow makeKeyAndVisible] + 42
frame #6: 0x00000001052ce833 UIKitCore`-[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4595
frame #7: 0x00000001052d3c2f UIKitCore`-[UIApplication _runWithMainScene:transitionContext:completion:] + 1623
frame #8: 0x0000000104af24e9 UIKitCore`__111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke + 866
frame #9: 0x0000000104afb29c UIKitCore`+[_UICanvas _enqueuePostSettingUpdateTransactionBlock:] + 153
frame #10: 0x0000000104af2126 UIKitCore`-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:] + 233
frame #11: 0x0000000104af2ae0 UIKitCore`-[__UICanvasLifecycleMonitor_Compatability activateEventsOnly:withContext:completion:] + 1085
frame #12: 0x0000000104af0cb5 UIKitCore`__82-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:]_block_invoke + 795
frame #13: 0x0000000104af095f UIKitCore`-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:] + 435
frame #14: 0x0000000104af5a90 UIKitCore`__125-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:]_block_invoke + 584
frame #15: 0x0000000104af680e UIKitCore`_performActionsWithDelayForTransitionContext + 100
frame #16: 0x0000000104af57ef UIKitCore`-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:] + 221
frame #17: 0x0000000104afa93a UIKitCore`-[_UICanvas scene:didUpdateWithDiff:transitionContext:completion:] + 392
frame #18: 0x00000001052d244e UIKitCore`-[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 515
frame #19: 0x0000000104e76d09 UIKitCore`-[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 357
frame #20: 0x000000010db0f2da FrontBoardServices`-[FBSSceneImpl _didCreateWithTransitionContext:completion:] + 448
frame #21: 0x000000010db1a443 FrontBoardServices`__56-[FBSWorkspace client:handleCreateScene:withCompletion:]_block_invoke_2 + 271
frame #22: 0x000000010db19b3a FrontBoardServices`__40-[FBSWorkspace _performDelegateCallOut:]_block_invoke + 53
frame #23: 0x0000000103d6d602 libdispatch.dylib`_dispatch_client_callout + 8
frame #24: 0x0000000103d70b78 libdispatch.dylib`_dispatch_block_invoke_direct + 301
frame #25: 0x000000010db4eba8 FrontBoardServices`__FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
frame #26: 0x000000010db4e860 FrontBoardServices`-[FBSSerialQueue _performNext] + 457
frame #27: 0x000000010db4ee40 FrontBoardServices`-[FBSSerialQueue _performNextFromRunLoopSource] + 45
frame #28: 0x00000001023d4721 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
frame #29: 0x00000001023d3f93 CoreFoundation`__CFRunLoopDoSources0 + 243
frame #30: 0x00000001023ce63f CoreFoundation`__CFRunLoopRun + 1263
frame #31: 0x00000001023cde11 CoreFoundation`CFRunLoopRunSpecific + 625
frame #32: 0x0000000109a661dd GraphicsServices`GSEventRunModal + 62
frame #33: 0x00000001052d581d UIKitCore`UIApplicationMain + 140
frame #34: 0x00000001010e99c0 test`main(argc=1, argv=0x00007ffeeeb16088) at main.m:14
frame #35: 0x0000000103de3575 libdyld.dylib`start + 1
frame #36: 0x0000000103de3575 libdyld.dylib`start + 1
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x00000001010e9884 test`-[ViewController viewDidLoad](self=0x00007fb7f37023f0, _cmd="viewDidLoad") at ViewController.m:16
frame #1: 0x0000000104cb64e1 UIKitCore`-[UIViewController loadViewIfRequired] + 1186
frame #2: 0x0000000104cb6940 UIKitCore`-[UIViewController view] + 27
frame #3: 0x000000010530dc53 UIKitCore`-[UIWindow addRootViewControllerViewIfPossible] + 122
frame #4: 0x000000010530e36e UIKitCore`-[UIWindow _setHidden:forced:] + 294
frame #5: 0x00000001053215c0 UIKitCore`-[UIWindow makeKeyAndVisible] + 42
frame #6: 0x00000001052ce833 UIKitCore`-[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4595
frame #7: 0x00000001052d3c2f UIKitCore`-[UIApplication _runWithMainScene:transitionContext:completion:] + 1623
frame #8: 0x0000000104af24e9 UIKitCore`__111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke + 866
frame #9: 0x0000000104afb29c UIKitCore`+[_UICanvas _enqueuePostSettingUpdateTransactionBlock:] + 153
frame #10: 0x0000000104af2126 UIKitCore`-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:] + 233
frame #11: 0x0000000104af2ae0 UIKitCore`-[__UICanvasLifecycleMonitor_Compatability activateEventsOnly:withContext:completion:] + 1085
frame #12: 0x0000000104af0cb5 UIKitCore`__82-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:]_block_invoke + 795
frame #13: 0x0000000104af095f UIKitCore`-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:] + 435
frame #14: 0x0000000104af5a90 UIKitCore`__125-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:]_block_invoke + 584
frame #15: 0x0000000104af680e UIKitCore`_performActionsWithDelayForTransitionContext + 100
frame #16: 0x0000000104af57ef UIKitCore`-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:] + 221
frame #17: 0x0000000104afa93a UIKitCore`-[_UICanvas scene:didUpdateWithDiff:transitionContext:completion:] + 392
frame #18: 0x00000001052d244e UIKitCore`-[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 515
frame #19: 0x0000000104e76d09 UIKitCore`-[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 357
frame #20: 0x000000010db0f2da FrontBoardServices`-[FBSSceneImpl _didCreateWithTransitionContext:completion:] + 448
frame #21: 0x000000010db1a443 FrontBoardServices`__56-[FBSWorkspace client:handleCreateScene:withCompletion:]_block_invoke_2 + 271
frame #22: 0x000000010db19b3a FrontBoardServices`__40-[FBSWorkspace _performDelegateCallOut:]_block_invoke + 53
frame #23: 0x0000000103d6d602 libdispatch.dylib`_dispatch_client_callout + 8
frame #24: 0x0000000103d70b78 libdispatch.dylib`_dispatch_block_invoke_direct + 301
frame #25: 0x000000010db4eba8 FrontBoardServices`__FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
frame #26: 0x000000010db4e860 FrontBoardServices`-[FBSSerialQueue _performNext] + 457
frame #27: 0x000000010db4ee40 FrontBoardServices`-[FBSSerialQueue _performNextFromRunLoopSource] + 45
frame #28: 0x00000001023d4721 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
frame #29: 0x00000001023d3f93 CoreFoundation`__CFRunLoopDoSources0 + 243
frame #30: 0x00000001023ce63f CoreFoundation`__CFRunLoopRun + 1263
frame #31: 0x00000001023cde11 CoreFoundation`CFRunLoopRunSpecific + 625
frame #32: 0x0000000109a661dd GraphicsServices`GSEventRunModal + 62
frame #33: 0x00000001052d581d UIKitCore`UIApplicationMain + 140
frame #34: 0x00000001010e99c0 test`main(argc=1, argv=0x00007ffeeeb16088) at main.m:14
frame #35: 0x0000000103de3575 libdyld.dylib`start + 1
frame #36: 0x0000000103de3575 libdyld.dylib`start + 1
(lldb)
顯示線程調(diào)用堆棧望蜡。 默認為當前線程,線程索引可以指定為參數(shù)拷恨。使用thread-index“all”查看所有線程脖律。使用thread-index“unique”查看按唯一調(diào)用堆棧分組的線程。
4 thread return [] 讓函數(shù)直接返回某個值腕侄,不會在執(zhí)行斷點后的代碼
我們在27行斷點處執(zhí)行 thread return 命令小泉,那么即使29行有代碼斷點,他也不會執(zhí)行冕杠,而是直接跳到19行斷點處微姊,thread return應(yīng)該是當前函數(shù)體內(nèi)下面的代碼不會執(zhí)行了,但是函數(shù)體外的流程還是會接著執(zhí)行的分预。
5 frame variable [] 打印當前棧幀的變量
(lldb) frame variable
(ViewController *) self = 0x00007fa4e970ce90
(SEL) _cmd = "viewDidLoad"
如果想了解此命令的其他用法兢交,可以調(diào)用幫助命令查看一下,
** help frame variable **
6斷點執(zhí)行的一些命令
上面Xcode一些斷點調(diào)試的按鈕我們應(yīng)該很熟悉吧笼痹,那么它具體執(zhí)行的是LLDB的什么命令呢配喳,我們來看一下飘诗。
命令 | 命令簡寫 | 功能描述 |
---|---|---|
thread continue | continue,c | 程序繼續(xù)運行 |
thread step-over | next界逛,n | 單步執(zhí)行,遇到函數(shù)不會進入到函數(shù)里面 |
thread step-in | step纺座,s | 單步執(zhí)行息拜,遇到函數(shù)會進到函數(shù)從里面 |
thread step-out | finish | 在這個函數(shù)體內(nèi),當前斷點的代碼不在執(zhí)行净响,直接跳過 |
thread step-inst-over | nexti少欺,ni | 類似與thread step-over的功能,不過它是匯編級別的 |
thread step-inst | stepi馋贤,si | 類似thread step-in的功能赞别,它也是匯編級別的 |
什么是匯編級別的鳞骤,一行源代碼凤粗,編譯成匯編有可能有好幾行,調(diào)試這行源代碼的匯編代碼時槐瑞,是一行一行的執(zhí)行犹芹,還是一次性執(zhí)行完這幾行呢崎页,那么就用到thread step-inst-over,thread step-inst命令了腰埂。
7 斷點的查找添加刪除禁用啟用等操作
命令 | 功能描述 |
---|---|
breakpoint set | 設(shè)置斷點 |
breakpoint list | 列出所有斷點 |
breakpoint disable 斷點編號 | 禁用斷點 |
breakpoint enable 斷點編號 | 啟用斷點 |
breakpoint delete 斷點編號 | 刪除斷點 |
breakpoint command add 斷點編號 | 給斷點預先設(shè)置需要執(zhí)行的命令飒焦,到觸發(fā)點時,就會安順序執(zhí)行 |
breakpoint command delete 斷點編號 | 查看某個斷點設(shè)置的命令 |
breakpoint command delete 斷點編號 | 刪除某個斷點設(shè)置的命令 |
操作命令用法跟下面的內(nèi)存斷點示例差不多屿笼,在此就不演示了牺荠。
8 內(nèi)存斷點
watchpoint set variable 變量
watchpoint set variable self->age
watchpoint set expression 地址
watchpoint set expression &(self->_age)
watchpoint list
watchpoint disable 斷點編號
watchpoint enable 斷點編號
watchpoint delete 斷點編號
watchpoint command add 斷點編號
watchpoint command list 斷點編號
watchpoint command delete 斷點編號
示例代碼
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
int i = 10;
NSString *str = @"hello";
[self sayHello];
if([[NSFileManager defaultManager] fileExistsAtPath:@"/Applications/Cydia.app"]) {
NSLog(@"手機已越獄");
}else {
NSLog(@"手機未越獄");
}
}
- (void) sayHello{
NSLog(@"hello");
NSLog(@"world");
}
@end
操作命令
(lldb) watchpoint list
Number of supported hardware watchpoints: 4
No watchpoints currently set.
(lldb) watchpoint set variable i
Watchpoint created: Watchpoint 1: addr = 0x7ffeeadaaa7c size = 4 state = enabled type = w
declare @ '/Users/xml/Documents/cocoaPodStudy/test/test/ViewController.m:17'
watchpoint spec = 'i'
new value: 10
(lldb) watchpoint set variable &str
Watchpoint created: Watchpoint 2: addr = 0x7ffeeadaaa70 size = 8 state = enabled type = w
declare @ '/Users/xml/Documents/cocoaPodStudy/test/test/ViewController.m:18'
watchpoint spec = '&str'
new value: 0x0000000104e56210
(lldb) watchpoint list
Number of supported hardware watchpoints: 4
Current watchpoints:
Watchpoint 1: addr = 0x7ffeeadaaa7c size = 4 state = enabled type = w
declare @ '/Users/xml/Documents/cocoaPodStudy/test/test/ViewController.m:17'
watchpoint spec = 'i'
new value: 10
Watchpoint 2: addr = 0x7ffeeadaaa70 size = 8 state = enabled type = w
declare @ '/Users/xml/Documents/cocoaPodStudy/test/test/ViewController.m:18'
watchpoint spec = '&str'
new value: 0x0000000104e56210
(lldb) watchpoint disable 1
1 watchpoints disabled.
(lldb) watchpoint enable 2
1 watchpoints enabled.
(lldb) watchpoint delete 1
1 watchpoints deleted.
(lldb) watchpoint list
Number of supported hardware watchpoints: 4
Current watchpoints:
Watchpoint 2: addr = 0x7ffeeadaaa70 size = 8 state = enabled type = w
declare @ '/Users/xml/Documents/cocoaPodStudy/test/test/ViewController.m:18'
watchpoint spec = '&str'
new value: 0x0000000104e56210
(lldb) watchpoint command add 2
Enter your debugger command(s). Type 'DONE' to end.
> po self
> DONE
(lldb) watchpoint command list 2
Watchpoint 2:
watchpoint commands:
po self
(lldb) watchpoint command delete 2
(lldb) watchpoint command list
error: No watchpoint specified for which to list the commands
(lldb)
9 鏡像/模塊操作
image lookup
image lookup -t 類型:查找某個類型的信息
image lookup -a 地址:根據(jù)內(nèi)存地址查找在模塊中的位置
image lookup -n 符號或者函數(shù)名:查找某個符號或者函數(shù)的位置
image list 列出所加載的模塊信息
image list -o -f 打印出模塊的偏移地址,全路徑驴一。
代碼
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
int i = 10;
NSString *str = @"hello";
[self sayHello];
if([[NSFileManager defaultManager] fileExistsAtPath:@"/Applications/Cydia.app"]) {
NSLog(@"手機已越獄");
}else {
NSLog(@"手機未越獄");
}
}
- (void) sayHello{
NSLog(@"hello");
NSLog(@"world");
}
@end
操作命令示例
(lldb) image lookup -t int
Best match found in /Users/xml/Library/Developer/Xcode/DerivedData/test-gkdxuwrmexrlikdlqtxkfhhftvpq/Build/Products/Debug-iphonesimulator/test.app/test:
id = {0x10000011b}, name = "int", byte-size = 4, compiler_type = "int"
(lldb) image lookup -a 0x0000000104e56210
Address: test[0x0000000100005210] (test.__DATA.__cfstring + 0)
Summary: @"hello"
(lldb) image lookup -n sayHello
1 match found in /Users/xml/Library/Developer/Xcode/DerivedData/test-gkdxuwrmexrlikdlqtxkfhhftvpq/Build/Products/Debug-iphonesimulator/test.app/test:
Address: test[0x0000000100001900] (test.__TEXT.__text + 288)
Summary: test`-[ViewController sayHello] at ViewController.m:27
(lldb) image list
[ 0] D57D8BF5-6F5D-3693-8C31-F36213F33C8B 0x0000000104e51000 /Users/xml/Library/Developer/Xcode/DerivedData/test-gkdxuwrmexrlikdlqtxkfhhftvpq/Build/Products/Debug-iphonesimulator/test.app/test
[ 1] D6387150-2FB8-3066-868D-72E1B1C43982 0x000000010a7eb000 /usr/lib/dyld
[ 2] C3514384-926E-3813-BF0C-69FFC704E283 0x0000000104e62000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/dyld_sim
[ 3] E5391C7B-0161-33AF-A5A7-1E18DBF9041F 0x000000010514b000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/Foundation.framework/Foundation
[ 4] 177A61B3-9E02-3A09-9A98-C1C3C9AB7958 0x0000000105771000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libobjc.A.dylib
[ 5] C89C657A-9BD2-3C7D-AD2E-ACF00916BF7D 0x00000001060a8000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libSystem.B.dylib
(lldb) image list -o -f
[ 0] 0x0000000004e51000 /Users/xml/Library/Developer/Xcode/DerivedData/test-gkdxuwrmexrlikdlqtxkfhhftvpq/Build/Products/Debug-iphonesimulator/test.app/test
[ 1] 0x000000010a7eb000 /usr/lib/dyld
[ 2] 0x0000000104e62000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/dyld_sim
[ 3] 0x000000010514b000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/Foundation.framework/Foundation
[ 4] 0x0000000105771000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libobjc.A.dylib
[ 5] 0x00000001060a8000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libSystem.B.dylib
[ 6] 0x00000001060b0000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation