LLDB 學(xué)習(xí)筆記

Advanced.Apple.Debugging.&.Reverse.Engineering.v2.0 學(xué)習(xí)筆記

1. 入門

1.1 禁用Rootless 與開啟調(diào)試功能

為了提高系統(tǒng)的安全性,Mac OS X 10.11開始引入了Rootless,在Rootless開啟的情況下,LLDB無法調(diào)試到其它進(jìn)程(模擬器內(nèi)的進(jìn)程除外).如果想調(diào)試其它進(jìn)程,需要關(guān)閉Rootless,如下:

  1. 重啟系統(tǒng)
  2. 開機(jī)后按下 Command + R 直到進(jìn)入恢復(fù)模式
  3. 從頂部菜單中找到 Utilities 菜單并選擇 Terminal
  4. 輸入以下命令禁用Rootless
csrutil disable
reboot

1.2 使用LLDB基本流程-使用LLDB 調(diào)試Xcode

實(shí)現(xiàn)如下功能

  1. 使用LLDB調(diào)試Xcode
  2. 將Xcode的輸出重定向到終端

1.2.1 創(chuàng)建重定向終端(tty)

使用tty命令創(chuàng)建重定向終端,此時(shí)生成的終端名為ttys002

~ tty
/dev/ttys001

1.2.2 使用LLDB啟動(dòng)Xcode

  1. 使用lldb 命令進(jìn)入LLDB
  2. 設(shè)置可執(zhí)行目標(biāo)文件路徑(file 命令):
(lldb) file /Applications/Xcode.app/Contents/MacOS/Xcode
Current executable set to '/Applications/Xcode.app/Contents/MacOS/Xcode' (x86_64).

其中/Applications/Xcode.app/Contents/MacOS/Xcode為Xcode的可執(zhí)行路徑,在Xcode打開的情況下可以通過以下命令獲取

~ ps -ef `pgrep -x Xcode`
  UID   PID  PPID   C STIME   TTY           TIME CMD
  501 29508     1   0  8:29下午 ??         0:14.03 /Applications/Xcode.app/Contents/MacOS/Xcode
  1. 啟動(dòng)并重定向到終端(之前創(chuàng)建的重定向終端:ttys001)
(lldb) process launch -e /dev/ttys001 --
Process 92898 launched: '/Applications/Xcode.app/Contents/MacOS/Xcode' (x86_64)
  1. Ctrl + C 暫停調(diào)試器
  2. 設(shè)置斷點(diǎn)(b):
(lldb) b -[NSView hitTest:]
Breakpoint 1: where = AppKit`-[NSView hitTest:], address = 0x00007fff31e25f9b
  1. 繼續(xù)調(diào)試(continue)
(lldb) continue
Process 34209 resuming
  1. 觸發(fā)斷點(diǎn): 點(diǎn)擊Xcode任意區(qū)域
Process 92898 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x00007fff31e25f9b AppKit`-[NSView hitTest:]
AppKit`-[NSView hitTest:]:
->  0x7fff31e25f9b <+0>: pushq  %rbp
    0x7fff31e25f9c <+1>: movq   %rsp, %rbp
    0x7fff31e25f9f <+4>: pushq  %r15
    0x7fff31e25fa1 <+6>: pushq  %r14
Target 0: (Xcode) stopped.
  1. 查看那個(gè)視圖被點(diǎn)擊(po 命令):
(lldb) po $rdi
<NSThemeFrame: 0x1651174c0>
(lldb) po [$rdi superclass]
NSTitledFrame
(lldb) po [[$rdi superclass] superclass]
NSFrameView
(lldb) po [[[$rdi superclass] superclass] superclass]
NSView

$rdi 寄存器包含調(diào)用hitTest:方法的子類NSView的實(shí)例

1.3 常用快捷鍵

  1. Ctrl + C :暫停調(diào)試器
  2. Ctrl + D :結(jié)束調(diào)試
  3. Command + K: 清空debug區(qū)域輸出

2. LLDB 幫助與查詢

2.1 LLDB命令格式

<noun> <verb> [-options [option-value]] [argument [argument...]]
即:<關(guān)鍵字> <動(dòng)作> [-可選項(xiàng) [可選項(xiàng)的值]] [參數(shù)1 [參數(shù)2···]]
  1. 所有命令使用同一的格式
  2. 參數(shù),可選項(xiàng)和選項(xiàng)值都用空格分隔
  3. 使用雙引號(hào)保護(hù)參數(shù)中的空格內(nèi)容
  4. \" 使用\進(jìn)行轉(zhuǎn)義,如\"表示",\\表示\
  5. 如果參數(shù)以-開始,需要在可選項(xiàng)和參數(shù)之間使用--加以分隔
  6. 可選項(xiàng)的順序可以不固定
(lldb) process launch --stop-at-entry -- -program_arg_1 value -program_arg_2 value
關(guān)鍵字:process
動(dòng)作:launch
可選項(xiàng):-stop-at-entry
參數(shù):-program_arg_1、-program_arg_2 value
作用:啟動(dòng)程序并傳入 `-program_arg value` 作為參數(shù)

2.2 help 命令獲取幫助

2.2.1 help 命令概覽:help

(lldb) help
Debugger commands:
  apropos           -- List debugger commands related to a word or subject.
  breakpoint        -- Commands for operating on breakpoints (see 'help b' for shorthand.)
  command           -- Commands for managing custom LLDB commands.
  disassemble       -- Disassemble specified instructions in the current target.  Defaults to the current function for the current thread and stack frame.
  expression        -- Evaluate an expression on the current thread.  Displays any returned value with LLDB's default formatting.
  frame             -- Commands for selecting and examing the current thread's stack frames.
  gdb-remote        -- Connect to a process via remote GDB server.  If no host is specifed, localhost is assumed.
  gui               -- Switch into the curses based GUI mode.
  help              -- Show a list of all debugger commands, or give details about a specific command.
  kdp-remote        -- Connect to a process via remote KDP server.  If no UDP port is specified, port 41139 is assumed.
  language          -- Commands specific to a source language.
  log               -- Commands controlling LLDB internal logging.
  memory            -- Commands for operating on memory in the current target process.
  platform          -- Commands to manage and create platforms.
  plugin            -- Commands for managing LLDB plugins.
  process           -- Commands for interacting with processes on the current platform.
  quit              -- Quit the LLDB debugger.
  register          -- Commands to access registers for the current thread and stack frame.

2.2.2 help 命令格式:help help

通過help help客戶獲取help的命令格式

(lldb) help help
     Show a list of all debugger commands, or give details about a specific command.
Syntax: help [<cmd-name>]
Command Options Usage:
  help [-ahu] [<cmd-name> [<cmd-name> [...]]]
       -a ( --hide-aliases )
            Hide aliases in the command list.
       -h ( --show-hidden-commands )
            Include commands prefixed with an underscore.
       -u ( --hide-user-commands )
            Hide user-defined commands from the list.
     This command takes options and free-form arguments.  If your arguments resemble option specifiers (i.e., they start with a - or --), you must use ' -- ' between the end of the command options and the beginning of the arguments.

2.2.3查詢斷點(diǎn)的幫助文檔:help breakpoint

(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>'.

2.3 查詢命令:apropos

在不知道具體命令但知道相應(yīng)關(guān)鍵字的時(shí)候,可以用apropos命令進(jìn)行查詢,語法如下

apropos <search-word>

比如查詢跟Objective-C相關(guān)的命令

(lldb) apropos Objective-C
The following commands may relate to 'Objective-C':
  objc           -- Commands for operating on the Objective-C language runtime.
  class-table    -- Commands for operating on the Objective-C class table.
  dump           -- Dump information on Objective-C classes known to the current process.
  tagged-pointer -- Commands for operating on Objective-C tagged pointers.

查詢引用計(jì)數(shù)相關(guān)的命令

(lldb) apropos "reference count"
The following commands may relate to 'reference count':
  refcount -- Inspect the reference count data for a Swift object

3. 使用LLDB附加到進(jìn)程

3.1 附加到現(xiàn)有進(jìn)程

  1. 通過進(jìn)程名,相當(dāng)于:process attach --name
 ~ lldb -n Xcode
(lldb) process attach --name "Xcode"
  1. 通過進(jìn)程ID,相當(dāng)于:process attach --pid
~ pgrep -x Xcode
2253
~ lldb -p 2253
(lldb) process attach --pid 2253

3.2 附加到即將啟動(dòng)的進(jìn)程

上面的命令只能附加到正在運(yùn)行的進(jìn)程翔试。如果Xcode沒有運(yùn)行恕洲,或者已經(jīng)附加到調(diào)試器委乌,前面的命令將失敗精置。在不知道PID的情況下夭织,如何捕捉即將啟動(dòng)的進(jìn)程呢?

3.2.1 通過添加 -w 參數(shù)附加到即將啟動(dòng)的進(jìn)程: lldb -n <進(jìn)程名> -w

lldb -n <進(jìn)程名> -w
相當(dāng)于: (lldb) process attach --name <進(jìn)程名> --waitfor

比如我們想附加到即將啟動(dòng)的Finder進(jìn)程,可如下實(shí)現(xiàn)

  1. 在終端1 輸入如下命令等待附加到即將啟動(dòng)的Finder進(jìn)程
~ lldb -n Finder -w
(lldb) process attach --name "Finder" --waitfor
  1. 在終端2 輸入如下命令,該命令將關(guān)閉所有Finder
~ pkill Finder
  1. 系統(tǒng)將自動(dòng)啟動(dòng)Finder,等系統(tǒng)啟動(dòng)Finder后,終端1 LLDB將附加到Finder進(jìn)程,如下輸出:
Process 4476 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x00007fff6ebabdfa libsystem_kernel.dylib`mach_msg_trap + 10
libsystem_kernel.dylib`mach_msg_trap:
->  0x7fff6ebabdfa <+10>: retq
    0x7fff6ebabdfb <+11>: nop

libsystem_kernel.dylib`mach_msg_overwrite_trap:
    0x7fff6ebabdfc <+0>:  movq   %rcx, %r10
    0x7fff6ebabdff <+3>:  movl   $0x1000020, %eax          ; imm = 0x1000020
Target 0: (Finder) stopped.

Executable module set to "/System/Library/CoreServices/Finder.app/Contents/MacOS/Finder".
Architecture set to: x86_64h-apple-macosx-.

3.2.2 通過指定可執(zhí)行文件路徑附加到即將啟動(dòng)的進(jìn)程: lldb -f <進(jìn)程路徑>

  1. 通過lldb -f <進(jìn)程路徑>命令指定可執(zhí)行文件
~ lldb -f /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder
  1. 運(yùn)行 process launch命令啟動(dòng)進(jìn)程

注意:直接使用process launch 命令啟動(dòng)進(jìn)程,被調(diào)試進(jìn)程的stderr輸出會(huì)自動(dòng)發(fā)送到當(dāng)前終端窗口.我們可以通過 -e 參數(shù)將輸出重定向到其它終端

process launch -e /dev/ttys001 --

3.3 process launch 詳解

以調(diào)試 ls命令為例子

3.3.1 修改被調(diào)試進(jìn)程工作路徑: process launch -w

默認(rèn)情況下,被調(diào)試進(jìn)程會(huì)工作在當(dāng)前目錄,在當(dāng)前目錄執(zhí)行ls,輸出的是當(dāng)前目錄下的文件列表.

~ lldb -f /bin/ls
(lldb) target create "/bin/ls"
Current executable set to '/bin/ls' (x86_64).
(lldb) process launch
Process 6375 launched: '/bin/ls' (x86_64)
Applications            Music
Applications (Parallels)    Parallels
Desktop             Pictures
Documents           Public
Downloads           markdown.md
Library             sslkeylog.log
Movies
Process 6375 exited with status = 0 (0x00000000)

如果想改變被調(diào)試進(jìn)程的工作目錄路徑,我們可以通過添加-w參數(shù)實(shí)現(xiàn),如:

~ lldb -f /bin/ls
(lldb) target create "/bin/ls"
Current executable set to '/bin/ls' (x86_64).
(lldb) process launch -w /Users/Shared
Process 7130 launched: '/bin/ls' (x86_64)
Parallels           SC Info
Previously Relocated Items  adi
Process 7130 exited with status = 0 (0x00000000)

輸出/Users/Shared,跟上面列出的文件列表一樣

?  Shared pwd
/Users/Shared
?  Shared ls
Parallels                  Previously Relocated Items SC Info                    adi

3.3.2 傳遞啟動(dòng)參數(shù)給目標(biāo)進(jìn)程

我們也可以將參數(shù)傳遞給目標(biāo)進(jìn)程,注意中間的--,用以區(qū)分選項(xiàng)和參數(shù)

?  ~ pwd
/Users/sammylan
?  ~ ls /Users/Shared
Parallels                  Previously Relocated Items SC Info                    adi
?  ~ lldb -f /bin/ls
(lldb) target create "/bin/ls"
Current executable set to '/bin/ls' (x86_64).
(lldb) process launch -- /Users/Shared
Process 8074 launched: '/bin/ls' (x86_64)
Parallels           SC Info
Previously Relocated Items  adi
Process 8074 exited with status = 0 (0x00000000)

3.3.3 啟動(dòng)參數(shù)環(huán)境變量展開: process launch -X true

如果傳遞的參數(shù)里面有環(huán)境變量,如~,則無法將參數(shù)正確傳遞過去,如下,ls無法展開~/Public

~ lldb -f /bin/ls
(lldb) target create "/bin/ls"
Current executable set to '/bin/ls' (x86_64).
(lldb) process launch -- ~/Public
Process 8464 launched: '/bin/ls' (x86_64)
ls: ~/Public: No such file or directory
Process 8464 exited with status = 1 (0x00000001)

這時(shí)候需要傳遞-X true參數(shù)給process launch

(lldb) process launch -Xtrue -- ~/Public
Process 8654 launched: '/bin/ls' (x86_64)
Drop Box
Process 8654 exited with status = 0 (0x00000000)

X選項(xiàng)擴(kuò)展您提供的任何shell參數(shù)孟辑,例如波浪號(hào)计露。在LLDB中有一個(gè)快捷命令run可實(shí)現(xiàn)類似功能,如

(lldb) run ~/Public
Process 8792 launched: '/bin/ls' (x86_64)
Drop Box
Process 8792 exited with status = 0 (0x00000000)

查看其幫助文檔可發(fā)現(xiàn),它等價(jià)于process launch -X true --命令

(lldb) help run
     Launch the executable in the debugger.
Syntax: run [<run-args>]
Command Options Usage:
  run [<run-args>]
'run' is an abbreviation for 'process launch -X true --'

3.3.4 輸出重定向:process launch -o

  • 重定向到文件:
(lldb)  process launch -o /tmp/ls_output.txt -- /Applications
Process 9397 launched: '/bin/ls' (x86_64)
Process 9397 exited with status = 0 (0x00000000)
  • 重定向到終端
(lldb) process launch -o /dev/ttys001 --
Process 9647 launched: '/bin/ls' (x86_64)
Process 9647 exited with status = 0 (0x00000000)

執(zhí)行上述命令后,將會(huì)輸出到終端ttys001,如下


終端 ttys001

3.3.5 輸入重定向:process launch -i

  1. 將文件內(nèi)容輸出到文件
~ echo "hello world" > /tmp/wc_input.txt

通過wc統(tǒng)計(jì)

target create /usr/bin/wc
Current executable set to '/usr/bin/wc' (x86_64).
(lldb) process launch -i /tmp/wc_input.txt
Process 10159 launched: '/usr/bin/wc' (x86_64)
       1       2      12

對(duì)于需要輸入的程序,如wc,如果沒有設(shè)置輸入重定向,程序啟動(dòng)后會(huì)掛在那里等待輸入,如下啟動(dòng),當(dāng)執(zhí)行run后,會(huì)一直停在那里等待輸入.輸入"helloworld"并按回車,然后按Ctrl + D,結(jié)束輸入,之后wc將結(jié)束輸入并退出,如下

(lldb) target create /usr/bin/wc
Current executable set to '/usr/bin/wc' (x86_64).
(lldb) run
Process 12287 launched: '/usr/bin/wc' (x86_64)
hello world
       1       2      12
Process 12287 exited with status = 0 (0x00000000)

3.3.7 不創(chuàng)建標(biāo)準(zhǔn)輸入:process launch -n

n 選項(xiàng)告訴LLDB不要?jiǎng)?chuàng)建stdin;因此wc沒有要處理的數(shù)據(jù)添履,并立即退出屁倔。

(lldb) target create /usr/bin/wc
Current executable set to '/usr/bin/wc' (x86_64).
(lldb)  process launch -n
Process 12623 launched: '/usr/bin/wc' (x86_64)
Process 12623 exited with status = 0 (0x00000000)

3.3.8 錯(cuò)誤重定向:process launch -e

將錯(cuò)誤重定向到其它終端

process launch -e /dev/ttys001 --

4. 斷點(diǎn)

4.1 image lookup: 查找符號(hào)

  1. image lookup -a: 根據(jù)地址查找符號(hào)信息
  2. image lookup -n: 根據(jù)符號(hào)名字查找符號(hào)信息
  3. image lookup -r: 啟用正則表達(dá)式查找符號(hào)
image lookup -rn "UIViewController"  ;查找UIViewController相關(guān)的全部符號(hào)
image lookup -rn "-\[UIViewController" ;查找UIViewController的實(shí)例方法
image lookup -rn "\+\[UIViewController"; 查找UIViewController的類方法
image lookup -rn "-\[UIViewController\sset" ; 查找UIViewController的所有set方法
image lookup -rn "-\[UIViewController\(\w+\)" 查找UIViewController的所有分類的方法

注意,以下字符需要轉(zhuǎn)義:
[,],(,),(空格,也可以用\s代替),+,-

image lookup 的詳細(xì)命令參數(shù)如下:

(lldb) help image lookup
     Look up information within executable and dependent shared library images.
     Syntax: target modules lookup <cmd-options> [<filename> [<filename> [...]]]

Command Options Usage:
  target modules lookup [-Av] -a <address-expression> [-o <offset>] [<filename> [<filename> [...]]]
  target modules lookup [-Arv] -s <symbol> [<filename> [<filename> [...]]]
  target modules lookup [-Aiv] -f <filename> [-l <linenum>] [<filename> [<filename> [...]]]
  target modules lookup [-Airv] -F <function-name> [<filename> [<filename> [...]]]
  target modules lookup [-Airv] -n <function-or-symbol> [<filename> [<filename> [...]]]
  target modules lookup [-Av] -t <name> [<filename> [<filename> [...]]]

       -A ( --all )
            Print all matches, not just the best match, if a best match is
            available.

       -F <function-name> ( --function <function-name> )
            Lookup a function by name in the debug symbols in one or more
            target modules.

       -a <address-expression> ( --address <address-expression> )
            Lookup an address in one or more target modules.

       -f <filename> ( --file <filename> )
            Lookup a file by fullpath or basename in one or more target
            modules.

       -i ( --no-inlines )
            Ignore inline entries (must be used in conjunction with --file or
            --function).

       -l <linenum> ( --line <linenum> )
            Lookup a line number in a file (must be used in conjunction with
            --file).

       -n <function-or-symbol> ( --name <function-or-symbol> )
            Lookup a function or symbol by name in one or more target modules.

       -o <offset> ( --offset <offset> )
            When looking up an address subtract <offset> from any addresses
            before doing the lookup.

       -r ( --regex )
            The <name> argument for name lookups are regular expressions.

       -s <symbol> ( --symbol <symbol> )
            Lookup a symbol by name in the symbol tables in one or more target
            modules.

       -t <name> ( --type <name> )
            Lookup a type by name in the debug symbols in one or more target
            modules.

       -v ( --verbose )
            Enable verbose lookup information.

4.2 屬性名字重整

4.2.1 Objective-C 屬性名字重整

在Objective-C中如下定義一個(gè)屬性: name

@interface TestClass : NSObject
@property (nonatomic, strong) NSString *name;
@end

會(huì)生成如下兩個(gè)settergetter方法:

-[TestClass name];
-[TestClass setName:];

4.2.2 Swift 屬性名字重整

在Swift中如下定義一個(gè)屬性: name

class SwiftTestClass: NSObject { 
  var name: String!
}

會(huì)生成如下兩個(gè)settergetter方法,其中Signals是模塊名

Signals.SwiftTestClass.name.getter;
Signals.SwiftTestClass.name.setter;

通過如下命令查詢會(huì)發(fā)現(xiàn)還有其它一些不常用的方法,這里不做詳細(xì)討論:

image lookup -rn Signals.SwiftTestClass.name
7 matches found in /Users/sammylan/Library/Developer/Xcode/DerivedData/Signals-efbmlrmvuqjbiyfptsisstosyqdx/Build/Products/Debug-iphonesimulator/Signals.app/Signals:
        Address: Signals[0x000000010000e500] (Signals.__TEXT.__text + 44608)
        Summary: Signals`variable initialization expression of Signals.SwiftTestClass.name : Swift.Optional<Swift.String> at <compiler-generated>        Address: Signals[0x000000010000e510] (Signals.__TEXT.__text + 44624)
        Summary: Signals`key path getter for Signals.SwiftTestClass.name : Swift.Optional<Swift.String> : Signals.SwiftTestClass at <compiler-generated>        Address: Signals[0x000000010000e580] (Signals.__TEXT.__text + 44736)
        Summary: Signals`key path setter for Signals.SwiftTestClass.name : Swift.Optional<Swift.String> : Signals.SwiftTestClass at <compiler-generated>        Address: Signals[0x000000010000e620] (Signals.__TEXT.__text + 44896)
        Summary: Signals`Signals.SwiftTestClass.name.getter : Swift.Optional<Swift.String> at SwiftTestClass.swift:28        Address: Signals[0x000000010000e6c0] (Signals.__TEXT.__text + 45056)
        Summary: Signals`Signals.SwiftTestClass.name.setter : Swift.Optional<Swift.String> at SwiftTestClass.swift:28        Address: Signals[0x000000010000e780] (Signals.__TEXT.__text + 45248)
        Summary: Signals`Signals.SwiftTestClass.name.modify : Swift.Optional<Swift.String> at SwiftTestClass.swift:28        Address: Signals[0x000000010000e7d0] (Signals.__TEXT.__text + 45328)
        Summary: Signals`Signals.SwiftTestClass.name.modify : Swift.Optional<Swift.String> at SwiftTestClass.swift:28

4.3 創(chuàng)建斷點(diǎn)

4.3.1 創(chuàng)建斷點(diǎn):b(_regexp-break)

(lldb) help b
     Set a breakpoint using one of several shorthand formats.  Expects 'raw'
     input (see 'help raw-input'.)

Syntax: 
_regexp-break <filename>:<linenum>
              main.c:12             // Break at line 12 of main.c

_regexp-break <linenum>
              12                    // Break at line 12 of current file

_regexp-break 0x<address>
              0x1234000             // Break at address 0x1234000

_regexp-break <name>
              main                  // Break in 'main' after the prologue

_regexp-break &<name>
              &main                 // Break at first instruction in 'main'

_regexp-break <module>`<name>
              libc.so`malloc        // Break in 'malloc' from 'libc.so'

_regexp-break /<source-regex>/
              /break here/          // Break on source lines in current file
                                    // containing text 'break here'.


'b' is an abbreviation for '_regexp-break'

4.3.2創(chuàng)建斷點(diǎn):rb(breakpoint set -r %1)

使用正則表達(dá)式方式創(chuàng)建斷點(diǎn),如過使用b創(chuàng)建前面的斷點(diǎn),需要如下方式創(chuàng)建

(lldb) b  Signals.SwiftTestClass.name.setter : Swift.Optional<Swift.String>
Breakpoint 15: where = Signals`Signals.SwiftTestClass.name.setter : Swift.Optional<Swift.String> + 174 at SwiftTestClass.swift:28:7, address = 0x000000010da5376e

(lldb) b SwiftTestClass.name.setter : Swift.Optional<Swift.String>
Breakpoint 16: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.

如果使用rb命令,可以簡化成如下命令

(lldb) rb SwiftTestClass.name.setter
Breakpoint 14: where = Signals`Signals.SwiftTestClass.name.setter : Swift.Optional<Swift.String> + 174 at SwiftTestClass.swift:28:7, address = 0x000000010da5376e

常用選項(xiàng):(詳細(xì)命令請參考:help rb)

  • -s:限定某個(gè)庫的符號(hào),如:rb . -s UIKit UIKit的所有符號(hào)設(shè)置一個(gè)斷點(diǎn)
  • -o: 斷點(diǎn)只執(zhí)行一次,執(zhí)行后就刪除
  • -L: 按照語言來篩選,如: rb . -L swift -s Commons,這將在Commons模塊中的每個(gè)Swift方法上設(shè)置一個(gè)斷點(diǎn)

4.3.3 創(chuàng)建斷點(diǎn):breakpoint set

  • -p 選項(xiàng):源碼正則選項(xiàng),在符合特定源碼規(guī)則的地方停止
  1. breakpoint set -A -p "if let": 在包含if-let的每個(gè)源代碼位置上創(chuàng)建一個(gè)斷點(diǎn)
  2. breakpoint set -p "if let" -s Signals -A: 在Signals里包含if-let的每個(gè)源代碼位置上創(chuàng)建一個(gè)斷點(diǎn)
  • -c 選項(xiàng):條件斷點(diǎn):
  1. breakpoint set -n "-[UIViewController viewDidLoad]" -c "*(uintptr_t*)$rsp >= 0x0000000102573000 && *(uintptr_t*)$rsp <= 0x0000000102587000" 只有從Signals模塊調(diào)用-[UIViewController viewDidLoad]
  • 獲取模塊地址:
(lldb) image dump sections Signals
image.png

4.4 管理斷點(diǎn):

  • breakpoint list: 列出斷點(diǎn)
  • breakpoint delete: 刪除斷點(diǎn)
  • breakpoint set: 設(shè)置斷點(diǎn)
(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>'.

5. 表達(dá)式

5.1 po 格式化輸出與修改值

  • po 輸出的是debugDescription的內(nèi)容
  • debugDescription 默認(rèn)調(diào)用 description
  • 可以通過(lldb) image lookup -rn '\ debugDescription\]'命令查找實(shí)現(xiàn)了debugDescription 的類
(lldb) po self
debugDescription of <ViewController: 0x7f801bc05770>

(lldb) po [self description]
description of ViewController

(lldb) po [self debugDescription]
debugDescription of <ViewController: 0x7f801bc05770>

(lldb) po self.view.layer
<CALayer:0x600001c3c760; name = "VC:ViewController"; position = CGPoint (207 368); bounds = CGRect (0 0; 414 736); delegate = <UIView: 0x7fe813c09da0; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x600001c3c760>>; allowsGroupOpacity = YES; name = VC:ViewController; backgroundColor = <CGColor 0x600003f232f0> [<CGColorSpace 0x60000382c840> (kCGColorSpaceICCBased; kCGColorSpaceModelMonochrome; Generic Gray Gamma 2.2 Profile; extended range)] ( 1 1 )>

(lldb) po self.view.layer.description
<CALayer: 0x600001c3c760>

(lldb) po self.view.layer.debugDescription
<CALayer:0x600001c3c760; name = "VC:ViewController"; position = CGPoint (207 368); bounds = CGRect (0 0; 414 736); delegate = <UIView: 0x7fe813c09da0; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x600001c3c760>>; allowsGroupOpacity = YES; name = VC:ViewController; backgroundColor = <CGColor 0x600003f232f0> [<CGColorSpace 0x60000382c840> (kCGColorSpaceICCBased; kCGColorSpaceModelMonochrome; Generic Gray Gamma 2.2 Profile; extended range)] ( 1 1 )>
  • 使用po命令修改值
(lldb) po self.titleLabel.text
快來占領(lǐng)榜單第一名吧
(lldb) po self.titleLabel.text = @"Test"
Test
(lldb) po self.titleLabel.text
Test

5.2 p 命令:

5.2.1 使用p命令輸出所有成員信息

(lldb) p self
(Signals.MasterViewController) $R0 = 0x00007f9e03f05060 {
  UIKit.UITableViewController = {
    baseUIViewController@0 = {
      baseUIResponder@0 = {
        NSObject = {
          isa = Signals.MasterViewController
        }
      }
      _overrideTransitioningDelegate = nil
      _view = 0x00007f9e04033400
      _tabBarItem = nil
      _navigationItem = 0x00007f9e03f03de0
      _toolbarItems = nil
      _title = nil
      _nibName = 0x000060000044def0 "7bK-jq-Zjz-view-r7i-6Z-zg0"
      _nibBundle = 0x000060000009d240 "/Users/sammylan/Library/Developer/CoreSimulator/Devices/B9ABA4CA-3F98-4607-898B-254D9351490C/data/Containers/Bundle/Application/D1011E4B-2BDF-4820-AC4B-E9DBE7EFC1CF/Signals.app"
      _parentViewController = nil
      _childModalViewController = nil
      _parentModalViewController = nil
      _previousRootViewController = nil
      _modalTransitionView = nil
      _modalPreservedFirstResponder = nil
      _dimmingView = nil
      _dropShadowView = nil
      _currentAction = nil
      _storyboard = 0x0000604000268740
      _externalObjectsTableForViewLoading = 0x0000600000464940 2 key/value pairs
      _topLevelObjectsToKeepAliveFromStoryboard = nil
      _savedHeaderSuperview = nil
      _savedFooterSuperview = nil
      _editButtonItem = nil
      _searchDisplayController = nil
      _strongSearchDisplayController = nil
      _modalTransitionStyle = 0
      _modalPresentationStyle = 0
      _lastKnownInterfaceOrientation = 0
      _popoverController = nil
      _containerViewInSheet = nil
      _recordedContentScrollView = nil
      _afterAppearance = nil
      _explicitAppearanceTransitionLevel = 0
      _interfaceBuilderKeyCommands = nil
      _addedKeyCommands = nil
      _overrideTraitCollectionsForChildren = nil
      _previewSourceViews = nil
      _retainCount = 18
      _ignoreAppSupportedOrientations = false
      _viewHostsLayoutEngine = false
      _storyboardIdentifier = 0x0000604000269580 "UITableViewController-7bK-jq-Zjz"
      _transitioningDelegate = nil
      _frozenTraitCollection = nil
      _overrideTraitCollection = nil
      _accessibilityHUD = nil
      overrideUseCustomPresentation = false
      _modalPresentationCapturesStatusBarAppearance = false
      _ignoresParentMargins = false
      _childViewControllers = nil
      _customNavigationInteractiveTransitionDuration = 0
      _customNavigationInteractiveTransitionPercentComplete = 0
      _customTransitioningView = nil
      _lastNotifiedTraitCollection = nil
      _presentationController = nil
      _navigationControllerContentOffsetAdjustment = 0
      _leftContentMargin = 0
      _rightContentMargin = 0
      _contentMargin = 0
      _topLayoutGuide = nil
      _bottomLayoutGuide = nil
      _topBarInsetGuideConstraint = nil
      _bottomBarInsetGuideConstraint = nil
      _storyboardSegueTemplates = 0x000060000000d070 1 element
      _segueResponsibleForModalPresentation = nil
      _sourceViewControllerIfPresentedViaPopoverSegue = nil
      _modalSourceViewController = nil
      _expectedWindow = nil
      _presentedStatusBarViewController = nil
      _presentedUserInterfaceStyleViewController = nil
      _edgesForExtendedLayout = 15
      __childControllerToIgnoreWhileLookingForTransitionCoordinator = nil
      _presentingFocusedItem = nil
      _navigationInsetAdjustment = nil
      _storyboardPreviewSegueTemplates = nil
      _storyboardCommitSegueTemplates = nil
      _storyboardPreviewingRegistrants = nil
      __embeddedView = nil
      __embeddingView = nil
      __embeddedDelegate = nil
      _originalPresentationController = nil
      _temporaryPresentationController = nil
      _preferredFocusedItem = nil
    }
    _tableViewStyle = 0
    _keyboardSupport = nil
    _staticDataSource = nil
    _filteredDataSource = 0x000060000044d9e0
    _filteredDataType = 0
  }
  detailViewController = nil
}

5.2.2 使用p命令格式化輸出

兼容C的格式化輸出: https://sourceware.org/gdb/onlinedocs/gdb/輸出-格式.html

  • x:十六進(jìn)制,如 p/x 10
  • d:十進(jìn)制,如 p/x 10
  • u:無符號(hào)十進(jìn)制數(shù)
  • o:八進(jìn)制
  • t:二進(jìn)制, 如p/t 10
  • a:地址,
  • c:字符常數(shù)
  • f:浮動(dòng)
  • s:字符串

LLDB 提供的格式化輸出(取自):http://lldb.llvm.org/varformats.html

  • B:布爾值
  • b:二進(jìn)制
  • y:字節(jié)
  • Y:帶ASCII的字節(jié)
  • c:字符
  • C:可打印字符
  • F:復(fù)雜浮動(dòng)
  • s:c型管柱
  • i:十進(jìn)制
  • E:枚舉
  • x:十六進(jìn)制
  • f:浮動(dòng)
  • o:八進(jìn)制
  • O: 十進(jìn)制
  • U:unicode16
  • u:無符號(hào)十進(jìn)制數(shù)
  • p:指針

5.3 Swift與Objective-C調(diào)試上下文

5.3.1 默認(rèn)調(diào)試上下文

在調(diào)試程序時(shí)有兩個(gè)調(diào)試上下文:非Swift調(diào)試上下文Swift調(diào)試上下文:

  1. 當(dāng)你在Objective-C代碼中停止時(shí),LLDB將使用非Swift(Objective-C)上下文
  2. 當(dāng)你在Swift代碼中停止暮胧,LLDB將使用Swift調(diào)試上下文锐借。
  3. 如果您突然停止調(diào)試器问麸,默認(rèn)情況下LLDB將選擇Objective-C調(diào)試上下文
    如在swift代碼中設(shè)置斷點(diǎn)并停下,執(zhí)行以下命令將出錯(cuò)
(lldb) po [UIApplication sharedApplication]
error: <EXPR>:3:16: error: expected ',' separator
[UIApplication sharedApplication]
               ^
              ,

5.3.2 指定調(diào)試上下文: expression -l

在swift調(diào)試上下文下,可以通過-l命令指定上下文,如下:

(lldb) expression -l objc -O -- [UIApplication sharedApplication]
<UIApplication: 0x7fe7d2c015d0>

注意:po 被映射為expression-O-,無法使用po 顯式指定上下文.
方然也可以使用swift語法打印相應(yīng)值:

(lldb) po UIApplication.shared
<UIApplication: 0x7fe7d2c015d0> 

突然停止調(diào)試器,會(huì)默認(rèn)進(jìn)入非swift調(diào)試上下文,此時(shí)使用swift語法打印相應(yīng)值也會(huì)出錯(cuò),使用objective-c語法則會(huì)成功,如下:

(lldb) po UIApplication.shared
error: property 'shared' not found on object of type 'UIApplication'

(lldb) po [UIApplication sharedApplication]
<UIApplication: 0x7fe7d2c015d0>

(lldb) expression -l swift -O -- UIApplication.shared
<UIApplication: 0x7fe7d2c015d0>

5.4 用戶自定義變量

在調(diào)試的時(shí)候,可以創(chuàng)建一些變量供后面使用,注意:變量名必需是$開頭的,如下,直接創(chuàng)建變量(test)無法給后面使用,需要$開頭的變量($test)才能在后面繼續(xù)使用.

(lldb) po id test = [NSObject new]
(lldb) po test
error: use of undeclared identifier 'test'
(lldb) po id $test = [NSObject new]
(lldb) po $test
<NSObject: 0x60400000e7f0>

注意:在Objective-C上下文中創(chuàng)建的LLDB用戶自定義變量钞翔,轉(zhuǎn)到Swift上下文后严卖,不一定能正常工作(尚未實(shí)現(xiàn)的功能)
在swift調(diào)試上下文下,執(zhí)行p obj后,會(huì)自動(dòng)生成一個(gè)簡短的LLDB用戶自定義變量,可以在后續(xù)使用,如下,生成了個(gè)簡短的$R0變量

(lldb) p self
(Signals.MasterViewController) $R0 = 0x00007f9e03f05060 {
...
      _nibName = 0x000060000044def0 "7bK-jq-Zjz-view-r7i-6Z-zg0"
...
(lldb) po $R0.nibName
? Optional<String>
  - some : "7bK-jq-Zjz-view-r7i-6Z-zg0"

(lldb) p $R0.nibName
(String?) $R10 = "7bK-jq-Zjz-view-r7i-6Z-zg0"

(lldb) po  $R10
? Optional<String>
  - some : "7bK-jq-Zjz-view-r7i-6Z-zg0"

6. 線程與堆棧

6.1 xcode 單步調(diào)試基本命令

  • 如上圖,從左到右依次為:
  1. continue / pause : 繼續(xù)運(yùn)行(或者遇到下一個(gè)斷點(diǎn)停止)/ 暫停運(yùn)行
  2. step over: 單步執(zhí)行,在函數(shù)內(nèi)遇到子函數(shù)時(shí)不會(huì)進(jìn)入子函數(shù).
  3. step into: 單步執(zhí)行,遇到子函數(shù)就進(jìn)入并且繼續(xù)單步執(zhí)行.
  4. step out: 在單步執(zhí)行到子函數(shù)內(nèi)時(shí),按 step out 就可以執(zhí)行完子函數(shù)余下部分并返回上一層函數(shù).
  • 指令級(jí)單步調(diào)試:Ctrl +
    按住 Ctrl 執(zhí)行step overstep into功能,將執(zhí)行匯編指令級(jí)別的單步調(diào)試,按住Ctrl + step into 可進(jìn)入無源碼函數(shù)進(jìn)行單步調(diào)試
  • 多線程單步調(diào)試:Ctrl + Shift
    Ctrl + Shift 執(zhí)行step overstep into功能時(shí)將只單步調(diào)試當(dāng)前線程(其它線程進(jìn)入暫停狀態(tài))

6.2 查看堆棧信息

6.2.1 thread backtrace: 查看堆棧信息

(lldb) thread backtrace
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
  * frame #0: 0x000000010556d7c2 Signals`MasterViewController.viewDidLoad(self=0x00007fd887c0a9a0) at MasterViewController.swift:38:5
    frame #1: 0x000000010556e03b Signals`@objc MasterViewController.viewDidLoad() at <compiler-generated>:0
    frame #2: 0x000000010fe400f7 UIKitCore`-[UIViewController loadViewIfRequired] + 1183
    frame #3: 0x000000010fe40524 UIKitCore`-[UIViewController view] + 27
    frame #4: 0x00000001105dd4b5 UIKitCore`__67-[UIStoryboardEmbedSegueTemplate newDefaultPerformHandlerForSegue:]_block_invoke + 180
    frame #5: 0x00000001105df4d3 UIKitCore`-[UIStoryboardSegueTemplate _performWithDestinationViewController:sender:] + 276
    frame #6: 0x00000001105df391 UIKitCore`-[UIStoryboardSegueTemplate _perform:] + 82
    frame #7: 0x00000001105df653 UIKitCore`-[UIStoryboardSegueTemplate perform:] + 157
    frame #8: 0x000000010fe3fee3 UIKitCore`-[UIViewController loadViewIfRequired] + 651
    frame #9: 0x000000010fe40524 UIKitCore`-[UIViewController view] + 27
    frame #10: 0x000000010fdb1690 UIKitCore`-[UINavigationController preferredContentSize] + 197
    frame #11: 0x000000010fdd745b UIKitCore`-[UIViewController(UIPopoverController_Internal) _resolvedPreferredContentSize] + 62
    frame #12: 0x000000010fdde97f UIKitCore`-[UIPopoverController _transitionFromViewController:toViewController:animated:] + 141
    frame #13: 0x000000010fdd7c0b UIKitCore`-[UIPopoverController _initWithContentViewController:popoverControllerStyle:] + 699
    frame #14: 0x000000010fe1463b UIKitCore`-[UISplitViewControllerClassicImpl _setupHiddenPopoverControllerWithViewController:] + 188
    frame #15: 0x000000010fe1323e UIKitCore`-[UISplitViewControllerClassicImpl _addOrRemovePopoverPresentationGestureRecognizer] + 121
    frame #16: 0x000000010fe128db UIKitCore`-[UISplitViewControllerClassicImpl loadView] + 339
    frame #17: 0x000000010fe3fd04 UIKitCore`-[UIViewController loadViewIfRequired] + 172
    frame #18: 0x000000010fe40524 UIKitCore`-[UIViewController view] + 27

6.2.2 frame 命令: 棧幀操作

frame 常用命令

  • frame info : 列出當(dāng)前棧幀信息
  • frame select: 選擇某一層棧幀作為當(dāng)前棧幀
  • frame variable: 查看當(dāng)前棧幀變量,默認(rèn)為展開方式輸出, -F 選項(xiàng)用平鋪方式輸出
(lldb) frame info
frame #0: 0x000000010556d7c2 Signals`MasterViewController.viewDidLoad(self=0x00007fd887c0a9a0) at MasterViewController.swift:38:5
(lldb) frame select 1
frame #1: 0x000000010556e03b Signals`@objc MasterViewController.viewDidLoad() at <compiler-generated>:0
(lldb) frame info
frame #1: 0x000000010556e03b Signals`@objc MasterViewController.viewDidLoad() at <compiler-generated>:0
(lldb) frame variable     #默認(rèn)展開方式輸出
(Bool) animated = false
(Signals.MasterViewController) self = 0x00007f9d4fd076b0 {
  UIKit.UITableViewController = {
    baseUIViewController@0 = {
      baseUIResponder@0 = {
        baseNSObject@0 = {
          isa = Signals.MasterViewController
        }
      }
# 其它未列出
(lldb) frame variable -F self      # -F參數(shù),平鋪方式輸出
self = 0x00007f9d4fd076b0
self =
self.isa = Signals.MasterViewController
self._overrideTransitioningDelegate = nil
self._view = some
self._view.some = 0x00007f9d5a034000
self._view.some.isa = UITableView
# 其它未列出
  • 詳細(xì)幫助信息如下:
(lldb) help fram
     Commands for selecting and examing the current thread's stack frames.

Syntax: frame <subcommand> [<subcommand-options>]

The following subcommands are supported:

      info       -- List information about the current stack frame in the
                    current thread.
      recognizer -- Commands for editing and viewing frame recognizers.
      select     -- Select the current stack frame by index from within the
                    current thread (see 'thread backtrace'.)
      variable   -- Show variables for the current stack frame. Defaults to all
                    arguments and local variables in scope. Names of argument,
                    local, file static and file global variables can be
                    specified. Children of aggregate variables can be specified
                    such as 'var->child.x'.  The -> and [] operators in 'frame
                    variable' do not invoke operator overloads if they exist,
                    but directly access the specified element.  If you want to
                    trigger operator overloads use the expression command to
                    print the variable instead.
                    It is worth noting that except for overloaded operators,
                    when printing local variables 'expr local_var' and 'frame
                    var local_var' produce the same results.  However, 'frame
                    variable' is more efficient, since it uses debug
                    information and memory reads directly, rather than parsing
                    and evaluating an expression, which may even involve JITing
                    and running code in the target program.

For more help on any particular subcommand, type 'help <command> <subcommand>'.

6.1 LLDB中的 單步調(diào)試基本命令

Xcode LLDB 描述
continue continue 繼續(xù)運(yùn)行(或者遇到下一個(gè)斷點(diǎn)停止)
step over next 單步執(zhí)行,在函數(shù)內(nèi)遇到子函數(shù)時(shí)不會(huì)進(jìn)入子函數(shù).
step into step 單步執(zhí)行,遇到子函數(shù)就進(jìn)入(有源碼才可以)并且繼續(xù)單步執(zhí)行.
Ctrl + step into step -a0 單步執(zhí)行,遇到子函數(shù)就進(jìn)入(無源碼也可以)并且繼續(xù)單步執(zhí)行.
step out finish 執(zhí)行完當(dāng)前棧幀并返回上一層調(diào)用
  1. continue / pause : 繼續(xù)運(yùn)行(或者遇到下一個(gè)斷點(diǎn)停止)/ 暫停運(yùn)行
  2. step over: 單步執(zhí)行,在函數(shù)內(nèi)遇到子函數(shù)時(shí)不會(huì)進(jìn)入子函數(shù).
  3. step into: 單步執(zhí)行,遇到子函數(shù)就進(jìn)入并且繼續(xù)單步執(zhí)行.
  4. step out: 在單步執(zhí)行到子函數(shù)內(nèi)時(shí),按 step out 就可以執(zhí)行完子函數(shù)余下部分并返回上

7. image: 進(jìn)程模塊信息

7.1 image 常用命令

  • image list: 列出所有模塊信息,
  • image list 模塊名: 列出指定模塊信息
  • image dump symtab : 輸出符號(hào)信息
  • image dump symtab 模塊名 :輸出特定模塊的符號(hào)信息
  • image lookup :查找符號(hào)信息
(lldb) image list Foundation
[  0] 30153EA5-45E2-334A-99DF-6E79D88AB4D0 0x000000010303d000 /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.4.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/Foundation.framework/Foundation 

(lldb) image lookup -n "-[UIViewController viewDidLoad]"
1 match found in /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.4.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore:
        Address: UIKitCore[0x000000000034cab5] (UIKitCore.__TEXT.__text + 3451269)
        Summary: UIKitCore`-[UIViewController viewDidLoad]

(lldb) image dump symtab UIKit -s address
Symtab, file = /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.4.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/UIKit.framework/UIKit, num_symbols = 3 (sorted by address):
               Debug symbol
               |Synthetic symbol
               ||Externally Visible
               |||
Index   UserID DSX Type            File Address/Value Load Address       Size               Flags      Name
------- ------ --- --------------- ------------------ ------------------ ------------------ ---------- ----------------------------------
[    0]      0     Data            0x0000000000000fd0 0x0000000104715fd0 0x0000000000000028 0x001e0000 UIKitVersionString
[    1]      1     Data            0x0000000000000ff8 0x0000000104715ff8 0x0000000000000008 0x001e0000 UIKitVersionNumber

其中:

  1. 模塊的UUID: UUID對(duì)于尋找符號(hào)信息和唯一標(biāo)識(shí)基礎(chǔ)模塊,30153EA5-45E2-334A-99DF-6E79D88AB4D0
  2. 加載地址: 0x000000010303d000
  3. 模塊路徑: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.4.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/Foundation.framework/Foundation

7.2 image lookup: 查找符號(hào)

  1. image lookup -a: 根據(jù)地址查找符號(hào)信息
  2. image lookup -n: 根據(jù)符號(hào)名字查找符號(hào)信息
  3. image lookup -r: 啟用正則表達(dá)式查找符號(hào)
image lookup -rn "UIViewController"  ;查找UIViewController相關(guān)的全部符號(hào)
image lookup -rn "-\[UIViewController" ;查找UIViewController的實(shí)例方法
image lookup -rn "\+\[UIViewController"; 查找UIViewController的類方法
image lookup -rn "-\[UIViewController\sset" ; 查找UIViewController的所有set方法
image lookup -rn "-\[UIViewController\(\w+\)" 查找UIViewController的所有分類的方法

注意,以下字符需要轉(zhuǎn)義:
[,],(,),(空格,也可以用\s代替),+,-

7.3 給所有Block下斷點(diǎn)

  1. 在一個(gè)Block中打斷點(diǎn),執(zhí)行到Block的時(shí)候,輸入以下命令查看Block的命名規(guī)范.block 都是包含 _block_invoke_ 的函數(shù)調(diào)用
(lldb) frame info
frame #0: 0x000000010b9f1440 Commons`__34+[UnixSignalHandler sharedHandler]_block_invoke(.block_descriptor=0x000000010b9f9348) at UnixSignalHandler.m:68:28
  1. 查找特定模塊的所有Block: image lookup -rn _block_invoke <模塊名>
(lldb) image lookup -rn _block_invoke Commons
6 matches found in /Users/sammylan/Library/Developer/Xcode/DerivedData/Signals-efbmlrmvuqjbiyfptsisstosyqdx/Build/Products/Debug-iphonesimulator/Signals.app/Frameworks/Commons.framework/Commons:
        Address: Commons[0x0000000000004830] (Commons.__TEXT.__text + 1152)
        Summary: Commons`__32-[UnixSignalHandler initPrivate]_block_invoke at UnixSignalHandler.m:78        Address: Commons[0x0000000000004430] (Commons.__TEXT.__text + 128)
        Summary: Commons`__34+[UnixSignalHandler sharedHandler]_block_invoke at UnixSignalHandler.m:67        Address: Commons[0x0000000000004bc0] (Commons.__TEXT.__text + 2064)
        Summary: Commons`__38-[UnixSignalHandler appendSignal:sig:]_block_invoke at UnixSignalHandler.m:119        Address: Commons[0x0000000000004c00] (Commons.__TEXT.__text + 2128)
        Summary: Commons`__38-[UnixSignalHandler appendSignal:sig:]_block_invoke_2 at UnixSignalHandler.m:123        Address: Commons[0x0000000000004f70] (Commons.__TEXT.__text + 3008)
        Summary: Commons`__38-[UnixSignalHandler appendSignal:sig:]_block_invoke_3 at UnixSignalHandler.m:135        Address: Commons[0x0000000000004a70] (Commons.__TEXT.__text + 1728)
        Summary: Commons`__32-[UnixSignalHandler initPrivate]_block_invoke.24 at UnixSignalHandler.m:105
  1. 給特定模塊的所有Block下斷點(diǎn):rb appendSignal.*_block_invoke -s Commons
    該斷點(diǎn)是在Commons里的appendSignal函數(shù)下的所有Block下斷點(diǎn)
(lldb)  rb appendSignal.*_block_invoke -s Commons
Breakpoint 6: 3 locations.

8 自定義命令及持久化"command alias

lldb 可以使用command alias自定義命令

(lldb) help command alias
     Define a custom command in terms of an existing command.  Expects 'raw' input (see 'help raw-input'.)

Syntax: command alias <cmd-options> -- <alias-name> <cmd-name> [<options-for-aliased-command>]

Command Options Usage:
  command alias [-h <help-text>] [-H <help-text>] -- <alias-name> <cmd-name> [<options-for-aliased-command>]
  command alias <alias-name> <cmd-name> [<options-for-aliased-command>]

       -H <help-text> ( --long-help <help-text> )
            Long help text for this command

       -h <help-text> ( --help <help-text> )

command alias -- Yay_Autolayout expression -l objc -O -- [[[[[UIApplication sharedApplication] keyWindow] rootViewController] view] recursiveDescription]
command alias cpo expression -l objc -O --
command alias sc script
command alias bp breakpoint
command alias bpl breakpoint list
command alias bcppfl breakpoint set -f %1.cpp -l %2
command alias bfl breakpoint set -f %1 -l %2

需要持久化的自定義命令需要保存到 ~/.lldbinit.
~/.lldbinit中新增的命令在LLDB中無法立刻使用,需要重啟LLDB或者執(zhí)行以下命令加載新增命令

(lldb) command source ~/.lldbinit
Executing commands in '/Users/sammylan/.lldbinit'.
(lldb)  command alias -- Yay_Autolayout expression -l objc -O -- [[[[[UIApplication sharedApplication] keyWindow] rootViewController] view] recursiveDescription]
warning: Overwriting existing definition for 'Yay_Autolayout'.
command alias cpo expression -l objc -O --
command alias sc script
command alias bp breakpoint
command alias bpl breakpoint list
command alias bcppfl breakpoint set -f %1.cpp -l %2
command alias bfl breakpoint set -f %1 -l %2

輸入?yún)?shù)可以用%1,%2,...定義,可以直接在LLDB中使用自定義命令,如下:

(lldb) bfl KSDataNodeManager.m 30
Breakpoint 15: where = QQKSong`-[KSDataNodeManager init] + 36 at KSDataNodeManager.m:30:12, address = 0x0000000102fa0e8c
(lldb) 

命令別名: command regex

我們發(fā)現(xiàn),無法使用command aliasimage lookup提供別名,如:

(lldb) command alias rnlook image lookup -rn
(lldb) rnlook viewWillAppear
warning: Unable to find an image that matches 'lookup'.

這時(shí)候就需要用到 command regex來定義別名,command regex的語法如下:
regex <cmd-name> [s/<regex>/<subst>/ ...]
該命令定義<regex>部分的內(nèi)容由

(lldb) help command regex
     Define a custom command in terms of existing commands by matching regular expressions.

Syntax: command regex <cmd-name> [s/<regex>/<subst>/ ...]

Command Options Usage:
  command regex [-h <none>] [-s <none>]

       -h <none> ( --help <none> )
            The help text to display for this command.

       -s <none> ( --syntax <none> )
            A syntax string showing the typical usage syntax.

image lookup -rn定義別名,如下

(lldb) command regex rlook 's/(.+)/image lookup -rn %1/'
(lldb) rlook viewWillAppear
2 matches found in /Users/sammylan/Library/Developer/Xcode/DerivedData/Signals-efbmlrmvuqjbiyfptsisstosyqdx/Build/Products/Debug-iphonesimulator/Signals.app/Signals:
        Address: Signals[0x0000000100004050] (Signals.__TEXT.__text + 3216)
        Summary: Signals`Signals.MasterViewController.viewWillAppear(Swift.Bool) -> () at MasterViewController.swift:51        Address: Signals[0x0000000100004780] (Signals.__TEXT.__text + 5056)
        Summary: Signals`@objc Signals.MasterViewController.viewWillAppear(Swift.Bool) -> () at <compiler-generated>

命令速查

查看內(nèi)存 x

x/nuf <addr>

n 表示要顯示的內(nèi)存單元的個(gè)數(shù)
------------------------
u 表示一個(gè)地址單元的長度
b 表示單字節(jié)
h 表示雙字節(jié)
w 表示4字節(jié)
g 表示8字節(jié)
------------------------
f 表示顯示方式趟济,可取以下值:
x 按十六進(jìn)制格式顯示變量
d 按十進(jìn)制格式顯示變量
u 按十進(jìn)制格式顯示無符號(hào)整型
o 按八進(jìn)制格式顯示變量
t 按二進(jìn)制格式顯示變量
a 按十六進(jìn)制格式顯示變量
i 按指令地址格式顯示變量
c 按字符格式顯示變量
f 按浮點(diǎn)數(shù)格式顯示變量
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末默色,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子嗡午,更是在濱河造成了極大的恐慌汰扭,老刑警劉巖稠肘,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異萝毛,居然都是意外死亡启具,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門珊泳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鲁冯,“玉大人,你說我怎么就攤上這事色查∈硌荩” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵秧了,是天一觀的道長跨扮。 經(jīng)常有香客問我,道長验毡,這世上最難降的妖魔是什么衡创? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮晶通,結(jié)果婚禮上璃氢,老公的妹妹穿的比我還像新娘。我一直安慰自己狮辽,他們只是感情好一也,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著喉脖,像睡著了一般椰苟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上树叽,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天舆蝴,我揣著相機(jī)與錄音,去河邊找鬼。 笑死洁仗,一個(gè)胖子當(dāng)著我的面吹牛层皱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播京痢,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼篷店!你這毒婦竟也來了祭椰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤疲陕,失蹤者是張志新(化名)和其女友劉穎方淤,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蹄殃,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡携茂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了诅岩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片讳苦。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖吩谦,靈堂內(nèi)的尸體忽然破棺而出鸳谜,到底是詐尸還是另有隱情,我是刑警寧澤式廷,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布咐扭,位于F島的核電站,受9級(jí)特大地震影響滑废,放射性物質(zhì)發(fā)生泄漏蝗肪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一蠕趁、第九天 我趴在偏房一處隱蔽的房頂上張望薛闪。 院中可真熱鬧,春花似錦俺陋、人聲如沸逛绵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽术浪。三九已至,卻和暖如春寿酌,著一層夾襖步出監(jiān)牢的瞬間胰苏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國打工醇疼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留硕并,地道東北人法焰。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像倔毙,于是被迫代替她去往敵國和親埃仪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355