美文网首页
LLDB 学习笔记

LLDB 学习笔记

作者: 蓝天白云_Sam | 来源:发表于2020-10-16 09:36 被阅读0次

    Advanced.Apple.Debugging.&.Reverse.Engineering.v2.0 学习笔记

    1. 入门

    1.1 禁用Rootless 与开启调试功能

    为了提高系统的安全性,Mac OS X 10.11开始引入了Rootless,在Rootless开启的情况下,LLDB无法调试到其它进程(模拟器内的进程除外).如果想调试其它进程,需要关闭Rootless,如下:

    1. 重启系统
    2. 开机后按下 Command + R 直到进入恢复模式
    3. 从顶部菜单中找到 Utilities 菜单并选择 Terminal
    4. 输入以下命令禁用Rootless
    csrutil disable
    reboot
    

    1.2 使用LLDB基本流程-使用LLDB 调试Xcode

    实现如下功能

    1. 使用LLDB调试Xcode
    2. 将Xcode的输出重定向到终端

    1.2.1 创建重定向终端(tty)

    使用tty命令创建重定向终端,此时生成的终端名为ttys002

    ~ tty
    /dev/ttys001
    

    1.2.2 使用LLDB启动Xcode

    1. 使用lldb 命令进入LLDB
    2. 设置可执行目标文件路径(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的可执行路径,在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. 启动并重定向到终端(之前创建的重定向终端:ttys001)
    (lldb) process launch -e /dev/ttys001 --
    Process 92898 launched: '/Applications/Xcode.app/Contents/MacOS/Xcode' (x86_64)
    
    1. Ctrl + C 暂停调试器
    2. 设置断点(b):
    (lldb) b -[NSView hitTest:]
    Breakpoint 1: where = AppKit`-[NSView hitTest:], address = 0x00007fff31e25f9b
    
    1. 继续调试(continue)
    (lldb) continue
    Process 34209 resuming
    
    1. 触发断点: 点击Xcode任意区域
    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. 查看那个视图被点击(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 寄存器包含调用hitTest:方法的子类NSView的实例

    1.3 常用快捷键

    1. Ctrl + C :暂停调试器
    2. Ctrl + D :结束调试
    3. Command + K: 清空debug区域输出

    2. LLDB 帮助与查询

    2.1 LLDB命令格式

    <noun> <verb> [-options [option-value]] [argument [argument...]]
    即:<关键字> <动作> [-可选项 [可选项的值]] [参数1 [参数2···]]
    
    1. 所有命令使用同一的格式
    2. 参数,可选项和选项值都用空格分隔
    3. 使用双引号保护参数中的空格内容
    4. \" 使用\进行转义,如\"表示",\\表示\
    5. 如果参数以-开始,需要在可选项和参数之间使用--加以分隔
    6. 可选项的顺序可以不固定
    (lldb) process launch --stop-at-entry -- -program_arg_1 value -program_arg_2 value
    关键字:process
    动作:launch
    可选项:-stop-at-entry
    参数:-program_arg_1、-program_arg_2 value
    作用:启动程序并传入 `-program_arg value` 作为参数
    

    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查询断点的帮助文档: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

    在不知道具体命令但知道相应关键字的时候,可以用apropos命令进行查询,语法如下

    apropos <search-word>
    

    比如查询跟Objective-C相关的命令

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

    查询引用计数相关的命令

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

    3. 使用LLDB附加到进程

    3.1 附加到现有进程

    1. 通过进程名,相当于:process attach --name
     ~ lldb -n Xcode
    (lldb) process attach --name "Xcode"
    
    1. 通过进程ID,相当于:process attach --pid
    ~ pgrep -x Xcode
    2253
    ~ lldb -p 2253
    (lldb) process attach --pid 2253
    

    3.2 附加到即将启动的进程

    上面的命令只能附加到正在运行的进程。如果Xcode没有运行,或者已经附加到调试器,前面的命令将失败。在不知道PID的情况下,如何捕捉即将启动的进程呢?

    3.2.1 通过添加 -w 参数附加到即将启动的进程: lldb -n <进程名> -w

    lldb -n <进程名> -w
    相当于: (lldb) process attach --name <进程名> --waitfor
    

    比如我们想附加到即将启动的Finder进程,可如下实现

    1. 在终端1 输入如下命令等待附加到即将启动的Finder进程
    ~ lldb -n Finder -w
    (lldb) process attach --name "Finder" --waitfor
    
    1. 在终端2 输入如下命令,该命令将关闭所有Finder
    ~ pkill Finder
    
    1. 系统将自动启动Finder,等系统启动Finder后,终端1 LLDB将附加到Finder进程,如下输出:
    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 通过指定可执行文件路径附加到即将启动的进程: lldb -f <进程路径>

    1. 通过lldb -f <进程路径>命令指定可执行文件
    ~ lldb -f /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder
    
    1. 运行 process launch命令启动进程

    注意:直接使用process launch 命令启动进程,被调试进程的stderr输出会自动发送到当前终端窗口.我们可以通过 -e 参数将输出重定向到其它终端

    process launch -e /dev/ttys001 --
    

    3.3 process launch 详解

    以调试 ls命令为例子

    3.3.1 修改被调试进程工作路径: process launch -w

    默认情况下,被调试进程会工作在当前目录,在当前目录执行ls,输出的是当前目录下的文件列表.

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

    如果想改变被调试进程的工作目录路径,我们可以通过添加-w参数实现,如:

    ~ 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 传递启动参数给目标进程

    我们也可以将参数传递给目标进程,注意中间的--,用以区分选项和参数

    ➜  ~ 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 启动参数环境变量展开: process launch -X true

    如果传递的参数里面有环境变量,如~,则无法将参数正确传递过去,如下,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)
    

    这时候需要传递-X true参数给process launch

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

    X选项扩展您提供的任何shell参数,例如波浪号。在LLDB中有一个快捷命令run可实现类似功能,如

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

    查看其帮助文档可发现,它等价于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)
    

    执行上述命令后,将会输出到终端ttys001,如下


    终端 ttys001

    3.3.5 输入重定向:process launch -i

    1. 将文件内容输出到文件
    ~ echo "hello world" > /tmp/wc_input.txt
    

    通过wc统计

    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
    

    对于需要输入的程序,如wc,如果没有设置输入重定向,程序启动后会挂在那里等待输入,如下启动,当执行run后,会一直停在那里等待输入.输入"helloworld"并按回车,然后按Ctrl + D,结束输入,之后wc将结束输入并退出,如下

    (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 不创建标准输入:process launch -n

    n 选项告诉LLDB不要创建stdin;因此wc没有要处理的数据,并立即退出。

    (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 错误重定向:process launch -e

    将错误重定向到其它终端

    process launch -e /dev/ttys001 --
    

    4. 断点

    4.1 image lookup: 查找符号

    1. image lookup -a: 根据地址查找符号信息
    2. image lookup -n: 根据符号名字查找符号信息
    3. image lookup -r: 启用正则表达式查找符号
    image lookup -rn "UIViewController"  ;查找UIViewController相关的全部符号
    image lookup -rn "-\[UIViewController" ;查找UIViewController的实例方法
    image lookup -rn "\+\[UIViewController"; 查找UIViewController的类方法
    image lookup -rn "-\[UIViewController\sset" ; 查找UIViewController的所有set方法
    image lookup -rn "-\[UIViewController\(\w+\)" 查找UIViewController的所有分类的方法
    

    注意,以下字符需要转义:
    [,],(,),(空格,也可以用\s代替),+,-

    image lookup 的详细命令参数如下:

    (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中如下定义一个属性: name

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

    会生成如下两个settergetter方法:

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

    4.2.2 Swift 属性名字重整

    在Swift中如下定义一个属性: name

    class SwiftTestClass: NSObject { 
      var name: String!
    }
    

    会生成如下两个settergetter方法,其中Signals是模块名

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

    通过如下命令查询会发现还有其它一些不常用的方法,这里不做详细讨论:

    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 创建断点

    4.3.1 创建断点: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创建断点:rb(breakpoint set -r %1)

    使用正则表达式方式创建断点,如过使用b创建前面的断点,需要如下方式创建

    (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
    

    常用选项:(详细命令请参考:help rb)

    • -s:限定某个库的符号,如:rb . -s UIKit UIKit的所有符号设置一个断点
    • -o: 断点只执行一次,执行后就删除
    • -L: 按照语言来筛选,如: rb . -L swift -s Commons,这将在Commons模块中的每个Swift方法上设置一个断点

    4.3.3 创建断点:breakpoint set

    • -p 选项:源码正则选项,在符合特定源码规则的地方停止
    1. breakpoint set -A -p "if let": 在包含if-let的每个源代码位置上创建一个断点
    2. breakpoint set -p "if let" -s Signals -A: 在Signals里包含if-let的每个源代码位置上创建一个断点
    • -c 选项:条件断点:
    1. breakpoint set -n "-[UIViewController viewDidLoad]" -c "*(uintptr_t*)$rsp >= 0x0000000102573000 && *(uintptr_t*)$rsp <= 0x0000000102587000" 只有从Signals模块调用-[UIViewController viewDidLoad]
    • 获取模块地址:
    (lldb) image dump sections Signals
    
    image.png

    4.4 管理断点:

    • breakpoint list: 列出断点
    • breakpoint delete: 删除断点
    • breakpoint set: 设置断点
    (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. 表达式

    5.1 po 格式化输出与修改值

    • po 输出的是debugDescription的内容
    • debugDescription 默认调用 description
    • 可以通过(lldb) image lookup -rn '\ debugDescription\]'命令查找实现了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
    快来占领榜单第一名吧
    (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:十六进制,如 p/x 10
    • d:十进制,如 p/x 10
    • u:无符号十进制数
    • o:八进制
    • t:二进制, 如p/t 10
    • a:地址,
    • c:字符常数
    • f:浮动
    • s:字符串

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

    • B:布尔值
    • b:二进制
    • y:字节
    • Y:带ASCII的字节
    • c:字符
    • C:可打印字符
    • F:复杂浮动
    • s:c型管柱
    • i:十进制
    • E:枚举
    • x:十六进制
    • f:浮动
    • o:八进制
    • O: 十进制
    • U:unicode16
    • u:无符号十进制数
    • p:指针

    5.3 Swift与Objective-C调试上下文

    5.3.1 默认调试上下文

    在调试程序时有两个调试上下文:非Swift调试上下文Swift调试上下文:

    1. 当你在Objective-C代码中停止时,LLDB将使用非Swift(Objective-C)上下文
    2. 当你在Swift代码中停止,LLDB将使用Swift调试上下文
    3. 如果您突然停止调试器,默认情况下LLDB将选择Objective-C调试上下文
      如在swift代码中设置断点并停下,执行以下命令将出错
    (lldb) po [UIApplication sharedApplication]
    error: <EXPR>:3:16: error: expected ',' separator
    [UIApplication sharedApplication]
                   ^
                  ,
    

    5.3.2 指定调试上下文: expression -l

    在swift调试上下文下,可以通过-l命令指定上下文,如下:

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

    注意:po 被映射为expression-O-,无法使用po 显式指定上下文.
    方然也可以使用swift语法打印相应值:

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

    突然停止调试器,会默认进入非swift调试上下文,此时使用swift语法打印相应值也会出错,使用objective-c语法则会成功,如下:

    (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 用户自定义变量

    在调试的时候,可以创建一些变量供后面使用,注意:变量名必需是$开头的,如下,直接创建变量(test)无法给后面使用,需要$开头的变量($test)才能在后面继续使用.

    (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上下文中创建的LLDB用户自定义变量,转到Swift上下文后,不一定能正常工作(尚未实现的功能)
    在swift调试上下文下,执行p obj后,会自动生成一个简短的LLDB用户自定义变量,可以在后续使用,如下,生成了个简短的$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 单步调试基本命令

    • 如上图,从左到右依次为:
    1. continue / pause : 继续运行(或者遇到下一个断点停止)/ 暂停运行
    2. step over: 单步执行,在函数内遇到子函数时不会进入子函数.
    3. step into: 单步执行,遇到子函数就进入并且继续单步执行.
    4. step out: 在单步执行到子函数内时,按 step out 就可以执行完子函数余下部分并返回上一层函数.
    • 指令级单步调试:Ctrl +
      按住 Ctrl 执行step overstep into功能,将执行汇编指令级别的单步调试,按住Ctrl + step into 可进入无源码函数进行单步调试
    • 多线程单步调试:Ctrl + Shift
      Ctrl + Shift 执行step overstep into功能时将只单步调试当前线程(其它线程进入暂停状态)

    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 : 列出当前栈帧信息
    • frame select: 选择某一层栈帧作为当前栈帧
    • frame variable: 查看当前栈帧变量,默认为展开方式输出, -F 选项用平铺方式输出
    (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     #默认展开方式输出
    (Bool) animated = false
    (Signals.MasterViewController) self = 0x00007f9d4fd076b0 {
      UIKit.UITableViewController = {
        baseUIViewController@0 = {
          baseUIResponder@0 = {
            baseNSObject@0 = {
              isa = Signals.MasterViewController
            }
          }
    # 其它未列出
    (lldb) frame variable -F self      # -F参数,平铺方式输出
    self = 0x00007f9d4fd076b0
    self =
    self.isa = Signals.MasterViewController
    self._overrideTransitioningDelegate = nil
    self._view = some
    self._view.some = 0x00007f9d5a034000
    self._view.some.isa = UITableView
    # 其它未列出
    
    • 详细帮助信息如下:
    (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中的 单步调试基本命令

    Xcode LLDB 描述
    continue continue 继续运行(或者遇到下一个断点停止)
    step over next 单步执行,在函数内遇到子函数时不会进入子函数.
    step into step 单步执行,遇到子函数就进入(有源码才可以)并且继续单步执行.
    Ctrl + step into step -a0 单步执行,遇到子函数就进入(无源码也可以)并且继续单步执行.
    step out finish 执行完当前栈帧并返回上一层调用
    1. continue / pause : 继续运行(或者遇到下一个断点停止)/ 暂停运行
    2. step over: 单步执行,在函数内遇到子函数时不会进入子函数.
    3. step into: 单步执行,遇到子函数就进入并且继续单步执行.
    4. step out: 在单步执行到子函数内时,按 step out 就可以执行完子函数余下部分并返回上

    7. image: 进程模块信息

    7.1 image 常用命令

    • image list: 列出所有模块信息,
    • image list 模块名: 列出指定模块信息
    • image dump symtab : 输出符号信息
    • image dump symtab 模块名 :输出特定模块的符号信息
    • image lookup :查找符号信息
    (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对于寻找符号信息和唯一标识基础模块,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: 查找符号

    1. image lookup -a: 根据地址查找符号信息
    2. image lookup -n: 根据符号名字查找符号信息
    3. image lookup -r: 启用正则表达式查找符号
    image lookup -rn "UIViewController"  ;查找UIViewController相关的全部符号
    image lookup -rn "-\[UIViewController" ;查找UIViewController的实例方法
    image lookup -rn "\+\[UIViewController"; 查找UIViewController的类方法
    image lookup -rn "-\[UIViewController\sset" ; 查找UIViewController的所有set方法
    image lookup -rn "-\[UIViewController\(\w+\)" 查找UIViewController的所有分类的方法
    

    注意,以下字符需要转义:
    [,],(,),(空格,也可以用\s代替),+,-

    7.3 给所有Block下断点

    1. 在一个Block中打断点,执行到Block的时候,输入以下命令查看Block的命名规范.block 都是包含 _block_invoke_ 的函数调用
    (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下断点:rb appendSignal.*_block_invoke -s Commons
      该断点是在Commons里的appendSignal函数下的所有Block下断点
    (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或者执行以下命令加载新增命令

    (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
    

    输入参数可以用%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

    我们发现,无法使用command aliasimage lookup提供别名,如:

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

    这时候就需要用到 command regex来定义别名,command regex的语法如下:
    regex <cmd-name> [s/<regex>/<subst>/ ...]
    该命令定义<regex>部分的内容由

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

    相关文章

      网友评论

          本文标题:LLDB 学习笔记

          本文链接:https://www.haomeiwen.com/subject/waiopktx.html