十二 iOS逆向-動態調試

  • 動態調試概念
  • Xcode動態調試原理
  • 調試任意第三方App
  • LLDB簡介
一 動態調試概念

就是在程序運行的過程中,通過打斷點,或者log輸出等方式,查看函數調用流程,以及一些變量,參數,返回值等等這一系列流程. 在iOS開發中,直觀上來講我們經常利用Xcode來進行App的動態調試。


Xcode調試界面

我們平時利用Xcode調試,只要點一下右面的箭頭,運行程序,在我們想要斷點的數字列表點一下,然后程序運行到這個地方的時候就會自行斷點了,用起來非常方便,但是Xcode這個動態調試是怎么實現的呢,讓我們一起來深入了解一下。

二 Xcode動態調試原理

要想了解Xcode動態調試原理,我們需要了解兩個東西 LLDB,debugserver。Xcode就是利用這兩個工具進行動態調試的。

2.1 什么是LLDB,debugserver

1 LLDB是Mac OS X上Xcode的默認調試器,支持在桌面和iOS設備和模擬器上調試C,Objective-C和C ++
2 debugserver是運行在iOS上作為服務端,接收和執行LLDB傳過來的命令,再把執行結果反饋給LLDB,顯示給用戶。

2.2 Xcode動態調試流程
Xcode動態調試流程圖

Xcode通過LLDB調試器把調試指令發送到手機上的debugserver,debugserver將命令轉給相應的app,app將反饋信息給debugserver , 最后debugserver將命令執行結果返回給lldb,然后Xcode在界面進行結果展示。

2.3 debugserver細節的一些講解
1 debugserver是手機內置的么?

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,那么如何調試手機上已經安裝的App呢,通過Xcode肯定不行了。我們只能用LLDB終端來進行了,下面看我們該如何做。

三 調試任意第三方App

上面我們知道,要想動態調試一個App只能通過Xcode安裝運行的,為什么會這樣呢,那是因為debugserver權限被限制了,那么要想調試別的App,就需要給debugserver附加額外的權限,我們主要添加下面兩個權限:
get-task-allow:布爾類型,是否允許其他進程(比如調試器),附加到你的應用程序上。
task_for_pid-allow:布爾類型,是否允許通過進程ID獲取任務
加上這兩個權限之后我們的debugserver就能夠訪問任何App的權限了,如何附加這兩個權限,主要有這幾步。

1 利用ldid導出debugeserver權限描述文件

把手機/Developer/usr/bin/debugserver拷貝一份到到電腦桌面,然后調用如下命令

 xmldeMacBook-Pro:Desktop xml$ ldid -e debugserver  >  debugserver.entitlements
2 打開導出的描述文件添加權限
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>

我們看剛添加的權限已經添加上了,添加權限就這么幾步,我們把接下來的流程走完,看看如何去動態調試第三方App

5 把重簽權限的debugserver放到手機/Device/usr/bin目錄下
6 給debugserver執行權限
applede-iPhone:/ root# chmod +x /usr/bin/debugserver
7 通過USB轉接debugserver的連接端口

連接debugserver,需要指定一個端口號,我們跟ssh遠程登錄手機一樣,我們也用usbmuxd做一下轉接

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,我們說一下命令的兩個參數。
端口號:就是使用手機的某個端口啟動debugserver,剛才我們用usbmuxd映射的是11111這個端口,那么這里我們也用11111這個端口來啟動debugserver.
進程:這里的進程就是App的進程ID或者進程名稱

9 Mac上個啟動LLDB,遠程連接iPhone上的debugserver服務。
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

到此調試任意App的整個環境流程就完了,接下來就是輸入LLDB命令開始調試了,一開始連接好,是要在LLDB終端輸入c命令才能繼續調試。
最后補充下,如何通過debugserver直接啟動一個App

$ debugserver -x auto *:端口號 APP的可執行文件路徑
 applede-iPhone:/ root# debugserver -x auto *:11111 
四 LLDB簡介

LLDB是Mac OS X上Xcode的默認調試器,支持在桌面和iOS設備和模擬器上調試C,Objective-C和C ++,這里我們主要講解一些它的常用命令。

LLDB指令格式
<command> [<subcommand> [<subcommand>...]] <action> [-options [option-
value]] [argument [argument...]]

<command>: 命令
[<subcommand> [<subcommand>...]] : 子命令
<action>: 命令操作
[-options [option-value]]: 命令選項
[argument [argument...]]:命令參數

下面是一個使用示例



breakpoint: 命令
list : 子命令
-v : 命令操作
2:命令參數
LLDB命令格式基本格式都是這樣的,命令的子命令,命令操作,命令選項,命令參數都是可選項,那么格式就是這樣的,接下來我們看一下,常用的一些命令。

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 --

執行一個表達式,任何可執行的OC代碼行
-- :是命令選項結束符,標示所有命令選項已經設置完畢,如果沒有命令選項,--可以不用寫

(lldb) expression NSLog(@"已經越獄")
2019-03-09 16:16:01.565070+0800 test[3156:116239] 已經越獄
(lldb) expression -A -- self.view
(UIView *) $1 = 0x00007f9655c04060 
(lldb) expression self.view.backgroundColor = [UIColor redColor]
(UICachedDeviceRGBColor *) $0 = 0x00006000013004c0

使用表達式命令,我們就可以動態添加代碼執行,比如我們有兩個視圖疊加一塊了,但是我們想知道一個視圖有沒有被遮擋,我們就可以使用表達式命令,給其中一個視圖添加一個顏色,這樣我們就能區分了,再也不用手動寫一下代碼,然后再重新執行一下了。

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) 

我們經常用p 來執行表達式命令,比寫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) 

顯示線程調用堆棧。 默認為當前線程,線程索引可以指定為參數。使用thread-index“all”查看所有線程。使用thread-index“unique”查看按唯一調用堆棧分組的線程。

4 thread return [] 讓函數直接返回某個值,不會在執行斷點后的代碼

我們在27行斷點處執行 thread return 命令,那么即使29行有代碼斷點,他也不會執行,而是直接跳到19行斷點處,thread return應該是當前函數體內下面的代碼不會執行了,但是函數體外的流程還是會接著執行的。

5 frame variable [] 打印當前棧幀的變量
(lldb) frame variable
(ViewController *) self = 0x00007fa4e970ce90
(SEL) _cmd = "viewDidLoad"

如果想了解此命令的其他用法,可以調用幫助命令查看一下,
** help frame variable **

6斷點執行的一些命令

上面Xcode一些斷點調試的按鈕我們應該很熟悉吧,那么它具體執行的是LLDB的什么命令呢,我們來看一下。

命令 命令簡寫 功能描述
thread continue continue,c 程序繼續運行
thread step-over next,n 單步執行,遇到函數不會進入到函數里面
thread step-in step,s 單步執行,遇到函數會進到函數從里面
thread step-out finish 在這個函數體內,當前斷點的代碼不在執行,直接跳過
thread step-inst-over nexti,ni 類似與thread step-over的功能,不過它是匯編級別的
thread step-inst stepi,si 類似thread step-in的功能,它也是匯編級別的

什么是匯編級別的,一行源代碼,編譯成匯編有可能有好幾行,調試這行源代碼的匯編代碼時,是一行一行的執行,還是一次性執行完這幾行呢,那么就用到thread step-inst-over,thread step-inst命令了。

7 斷點的查找添加刪除禁用啟用等操作
命令 功能描述
breakpoint set 設置斷點
breakpoint list 列出所有斷點
breakpoint disable 斷點編號 禁用斷點
breakpoint enable 斷點編號 啟用斷點
breakpoint delete 斷點編號 刪除斷點
breakpoint command add 斷點編號 給斷點預先設置需要執行的命令,到觸發點時,就會安順序執行
breakpoint command delete 斷點編號 查看某個斷點設置的命令
breakpoint command delete 斷點編號 刪除某個斷點設置的命令

操作命令用法跟下面的內存斷點示例差不多,在此就不演示了。

8 內存斷點

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 地址:根據內存地址查找在模塊中的位置
image lookup -n 符號或者函數名:查找某個符號或者函數的位置
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
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。