十二 iOS逆向-動態(tài)調(diào)試

  • 動態(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)試界面

我們平時利用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動態(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目錄下瓦呼。

debugserver在Xcode里的位置

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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末休雌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蛔趴,更是在濱河造成了極大的恐慌挑辆,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孝情,死亡現(xiàn)場離奇詭異鱼蝉,居然都是意外死亡,警方通過查閱死者的電腦和手機箫荡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門魁亦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人羔挡,你說我怎么就攤上這事洁奈〖浒Γ” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵利术,是天一觀的道長呈野。 經(jīng)常有香客問我,道長印叁,這世上最難降的妖魔是什么被冒? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮轮蜕,結(jié)果婚禮上昨悼,老公的妹妹穿的比我還像新娘。我一直安慰自己跃洛,他們只是感情好率触,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著汇竭,像睡著了一般葱蝗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上韩玩,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天垒玲,我揣著相機與錄音,去河邊找鬼找颓。 笑死合愈,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的击狮。 我是一名探鬼主播佛析,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼彪蓬!你這毒婦竟也來了寸莫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤档冬,失蹤者是張志新(化名)和其女友劉穎膘茎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酷誓,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡披坏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了盐数。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片棒拂。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出帚屉,到底是詐尸還是另有隱情谜诫,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布攻旦,位于F島的核電站喻旷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏牢屋。R本人自食惡果不足惜掰邢,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伟阔。 院中可真熱鬧,春花似錦掰伸、人聲如沸皱炉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽合搅。三九已至,卻和暖如春歧蕉,著一層夾襖步出監(jiān)牢的瞬間灾部,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工惯退, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留赌髓,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓催跪,卻偏偏與公主長得像锁蠕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子懊蒸,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353