什么是 LLDB?
LLDB(Low Level Debugger)是新一代高性能调试器,其是一组可重用组件的集合,这些组件大多是 LLVM 项目中的现有库,例如:Clang 表达式解析器,LLVM 反汇编程序,等等
LLDB 是 macOS 上 Xcode 中的默认调试器,Xcode 主窗口底部的控制台便是开发者与 LLDB 交互的区域。LLDB 允许开发者在程序运行的特定时刻暂停进程,查看变量的值,执行自定义的指令,控制代码的执行流程,等等
LLDB 的本质
上面说到 LLDB 已经被内置在 Xcode 中,它其实是作为一个共享库,存放在 Xcode 的
/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework
目录下的
也就是说,共享库 LLDB.framework
为 Xcode 提供了底层调试环境,LLDB 命令行工具会链接到此共享库并使用此共享库中的 API
LLDB 的 API 在共享库中是作为面向 C++ 的接口公开的。此外,LLDB 还通过 Python 脚本绑定公开了整个 API,该绑定允许在 LLDB 嵌入式脚本解释器中,以及任何导入 lldb.py 模块的标准 Python 文件中使用这些 API。共享的 LLDB API 不仅使 LLDB 可以用于调试,而且使 LLDB 可以用于符号化,反汇编,对象和符号文件自省,等等
命令语法(Command Syntax)
LLDB 命令语法自始至终都是结构化和规则的,LLDB 的命令都是以下形式:
<command> [<subcommand> [<subcommand>...]] <action> [-options [option-value]] [argument [argument...]]
其中:
command
)和子命令(subcommand
):调试命令的名称。命令和子命令按照层级结构排列:一个命令对象为跟随其的子命令对象创建一个上下文,子命令对象又为下一个跟随其的子命令对象创建一个上下文,依此类推action
):要在命令和子命令序列的上下文中执行的操作options
):是行为的修饰符,通常带有一个值argument
):根据当前所使用的命令和子命令的上下文表示各种不同的东西[ ]
):用于表示可选项LLDB 命令行解析会在命令执行之前完成。命令(command
)、子命令(subcommand
)、选项(options
)、选项值(option-value
)、参数(argument
)都是用空格分隔的,双引号(" "
)用于保护选项值(option-value
)和参数(argument
)中的空格。如果需要将反斜杠(\
)或者双引号("
)放入参数(argument
)中,则需要在参数中该字符前加上反斜杠(\
)。LLDB 等效地使用单引号('
)和双引号("
),以允许轻松编写命令行中的双引号部分。例如:
(lldb) command [subcommand] -option "some \"quoted\" string"
# 也可以写成:
(lldb) command [subcommand] -option 'some "quoted" string'
这种命令解析的设计,有助于使所有 LLDB 命令的语法变得规则和统一
作为一个简单的 LLDB 命令示例,在 test.c
文件的第 12
行设置断点,请输入:
(lldb) breakpoint set --file test.c --line 12
与上述命令的语法模式不同的命令(例如:p
、po
、print
、b
)通常是由命令别名机制所创建的自定义命令,会在接下来 命令别名(Command Aliases) 这一小节中进行讨论
命令选项(Command Options)
LLDB 中的命令选项具有:规范形式(discoverable / canonical)和缩写形式(abbreviated)。例如,下面是 breakpoint set
命令的命令选项的部分列表,在括号中列出的是命令选项的规范形式:
breakpoint set
-M <method> ( --method <method> )
-S <selector> ( --selector <selector> )
-b <function-name> ( --basename <function-name> )
-f <filename> ( --file <filename> )
-l <linenum> ( --line <linenum> )
-n <function-name> ( --name <function-name> )
...
命令选项(options
)可以在命令和子命令之后的命令行中以任何顺序放置。如果参数(argument
)以连字符(-
)开头,则可以通过(在命令选项之后 && 在参数之前)添加命令选项终止信号:双连字符(--
),向 LLDB 指示已完成当前命令的命令选项
例如,如果要使用 process launch
命令启动一个进程并提供 --stop-at-entry
选项,同时希望使用参数 -program_arg_1 value
和 -program_arg_2 value
作为该进程的启动参数,则请输入:
(lldb) process launch --stop-at-entry -- -program_arg_1 value -program_arg_2 value
原始命令(Raw Commands)
LLDB 命令解析器支持不带命令选项(options
)的原始命令,原始命令会将命令(command + subcommand
)后面的所有部分当做参数(argument
)传递给命令。这对于参数可能是一些复杂表达式的命令很方便,因为这些表达式用反斜杠保护起来会很笨拙。不过很多原始命令也可以带命令选项(options
),当在原始命令中使用命令选项(options
)时,需要(在命令选项之后 && 在参数之前)添加选项终止信号:双连字符(--
),以区分命令选项(options
)和参数(argument
)
例如,expression
命令就是一个原始命令:
# 一般情况下,使用 expression 命令打印一个基本数据类型的变量是这样的:
(lldb) expression count
(int) $0 = 10
# 当需要打印的变量是对象类型时,可以使用 -O 选项,此时需要使用 -- 区分命令选项和参数:
(lldb) expression -O -- self
<ViewController: 0x109e0a920>
当你通过 help
查找命令时,命令的输出信息会告诉你该命令是否为原始命令,以便你知道会发生什么:
(lldb) help po
Evaluate an expression on the current thread. Displays any returned value with formatting controlled by the type s author.
Expects 'raw' input (see 'help raw-input'.)
# 在当前线程上执行给定的表达式,并以该类型的作者控制的格式显示返回值
# 期望原始输入(请参阅 'help raw-input')
Syntax: po <expr>
Command Options Usage:
po <expr>
'po' is an abbreviation for 'expression -O --'
# 'po' 是 'expression -O --' 的别名
关于原始命令输入的解释,如下所示:
(lldb) help raw-input
<raw-input> -- Free-form text passed to a command without prior interpretation, allowing spaces without requiring quotes.
To pass arguments and free form text put two dashes ' -- ' between the last argument and any raw input.
# raw-input 是无需事先经过解释而直接传递给命令的自由形式的文本,允许空格而不需要引号
# 为了传递参数(这里说的参数指的是命令选项)和自由形式的文本,在最后一个参数(这里说的参数指的是命令选项)和任何原始输入之间放置两个破折号 "--"
命令补全(Command Completion)
LLDB 支持源文件名(source file names
)、符号名(symbol names
)、文件名(file names
)等的命令补全
通过在命令行上输入制表符来启动终端窗口中的命令补全
Xcode 控制台中的命令补全与源代码编辑器中的代码补全的工作方式相同:
在输入第三个字符后会自动弹出补全窗口,并且可以通过 Esc (Escape)
键手动调用命令补全弹出窗口。此外,Xcode 控制台中的命令补全遵循 Editing
面板中指定的 Xcode Text Editing
首选项
命令中的各个选项可以有不同的补全符。例如,breakpoint
中的 --file <path>
选项会补全源文件路径,--shlib <path>
选项会补全当前加载的共享库路径,等等。该命令补全行为可能非常具体,例如:如果你指定了 --shlib <path>
,并且正在 --file <path>
上进行命令补全,则 LLDB 只会列出 --shlib <path>
指定的共享库中的源文件
唯一匹配原则
LLDB 的命令遵循唯一匹配原则:
假如根据前 n 个字母已经能够唯一匹配到某个命令,则只写前 n 个字母等效于写下完整的命令
例如,下面的命令是等效的:
(lldb) expression -O -- self
<ViewController: 0x104608520>
(lldb) expressi -O -- self
<ViewController: 0x104608520>
(lldb) express -O -- self
<ViewController: 0x104608520>
(lldb) expres -O -- self
<ViewController: 0x104608520>
(lldb) expre -O -- self
<ViewController: 0x104608520>
(lldb) expr -O -- self
<ViewController: 0x104608520>
(lldb) exp -O -- self
<ViewController: 0x104608520>
(lldb) ex -O -- self
<ViewController: 0x104608520>
(lldb) e -O -- self
<ViewController: 0x104608520>
注意,LLDB 的命令不支持模糊匹配,下面的这种写法是错误的:
(lldb) expn -O -- self
error: 'expn' is not a valid command.
命令别名(Command Aliases)
LLDB 中的命令别名机制可以为常用命令构造别名。例如,如果你经常重复输入:
(lldb) breakpoint set --file foo.c --line 12
则你可以使用 command alias
命令构造命令别名:
(lldb) command alias bfl breakpoint set -f %1 -l %2
之后,你可以这样使用该命令别名:
(lldb) bfl foo.c 12
因为命令别名在各种不同情况下都很有用,所以你应该熟悉命令别名的构造。有关命令别名构造、限制和语法的完整说明,请使用 LLDB 帮助系统。输入:
(lldb) help command alias
# 根据现有的命令定义一个自定义命令。期望使用原始输入(请参阅 '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> )
# 此命令别名的详细帮助文档
-h <help-text> ( --help <help-text> )
# 此命令别名的帮助文档
# 命令别名允许用户为:长命令、多单词命令、拥有特定选项的命令,创建一个快捷方式或者缩写
# 下面是一些关于如何使用 'command alias' 命令的简单例子:
# 为 'script' 命令创建命令别名 'sc'
(lldb) command alias sc script
# 为 'breakpoint' 命令创建命令别名 'bp'
# 因为 'breakpoint' 命令是多单词命令,所以用户仍然需要在 'bp' 之后输入第二个单词,例如:
# 'bp enable' 或者 'bp delete'
(lldb) command alias bp breakpoint
# 为两个单词的命令 'breakpoint list' 创建命名别名 'bpl'
(lldb) command alias bpl breakpoint list
# 命令别名可以包含该命令的一些选项,这些选项的值可以在创建命令别名时填充,也可以将其指定为位置参数(将在调用命令别名时进行填充)
# 以下示例展示了如何创建带有选项的命令别名:
# 使用选项 -f 和 -l 创建命令别名 'bfl'(用于 break-file-line),其中选项已经是命令别名的一部分了
# 因此,如果用户想要按文件名和行号设置一个断点,但是又不想显式地使用 -f 和 -l 选项,则现在用户可以使用 'bfl' 来代替
# '%1' 和 '%2'是在使用命令别名时将传递的实际参数的位置占位符
# 位置占位符中的数字表示在使用命令别名时,实际值所占据的位置或者顺序
# 命令别名中所有出现的 '%1' 将替换为第一个参数,命令别名中所有出现的 '%2' 将替换为第二个参数,以此类推
# 这也允许在命令别名中多次使用同一个实际参数(请参阅下面的 'process launch' 示例)
(lldb) command alias bfl breakpoint set -f %1 -l %2
# 注意:因为位置参数必须在命令别名中替换整个单词,所以目前还不能以如下方式拼接文件扩展名 ".cpp"
(lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
# 对于特别复杂的命令别名,请使用 "command regex" 命令替代
# 在上面的 'bfl' 例子中,实际的文件名将用 'bfl' 后面的第一个参数填充,实际的行号将用 'bfl' 后面的第二个参数填充
# 用户可以使用以下的命令别名
(lldb) command alias bfl breakpoint set -f %1 -l %2
(lldb) bfl my-file.c 137
# 这就像用户输入了
(lldb) breakpoint set -f my-file.c -l 137
# 另一个例子:
(lldb) command alias pltty process launch -s -o %1 -e %1
(lldb) pltty /dev/tty0
# 这就像用户输入了
(lldb) process launch -s -o /dev/tty0 -e /dev/tty0
# 如果用户总是希望将相同的值传递给特定的选项,则可以在命令别名中直接使用该值作为一个常量来定义该命令别名,而不是使用位置占位符
# 总是在指定的文件的第 3 行设置一个断点
(lldb) command alias bl3 breakpoint set -f %1 -l 3
# 重要提示:
# 因为这个命令需要原始输入,所以如果您使用任何命令选项,则您必须在命令选项的末尾和原始输入的开始之间使用 ' -- ' 分隔
LLDB 在交付时包括许多与 GDB 命令相同的命令别名。如果你已经有使用 GDB 命令的经验,则你可以使用提供的表来查找 GDB 命令并找到 LLDB 对应的等效项,包括规范形式和速记形式
注意:在 LLDB 的默认配置中,一些常用命令的别名已经被添加到 LLDB 中(例如:step
、next
、continue
),但并未尝试构建详尽的别名集。根据 LLDB 开发团队的经验,将基本命令设置为唯一的一两个字母,然后学习这些基本命令,会比用大量别名填充命名空间来的更方便
然而,用户可以按照自己喜欢的任何方式自由自定义 LLDB 命令集。LLDB 在启动时会读取初始化文件 ~/.lldbinit
。该文件可以用于存储使用 command alias
命令创建的别名。 LLDB 帮助系统会读取此初始化文件并显示别名,以便你可以轻松提醒自己已经设置的内容。要查看所有当前已经定义的别名及其定义,请使用 help -a
命令并在帮助输出的末尾找到当前已经定义的别名,从以下内容开始:
...
The following is a list of your current command abbreviations (see 'help command alias' for more info): ...
探索 LLDB 的帮助系统,以更广泛地了解 LLDB 所提供的内容,并查看 LLDB 命令构造的细节。熟悉帮助命令后,你可以访问帮助系统中的大量命令文档
help 命令
① 对 help
命令的简单调用将返回所有顶级 LLDB 命令的列表。例如,这里是部分顶级命令列表:
(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.)
...
Current command abbreviations (type 'help command alias' for more info):
add-dsym -- Add a debug symbol file to one of the target current modules
by specifying a path to a debug symbols file, or using the
options to specify a module to download symbols for.
attach -- Attach to process by ID or name.
...
For more information on any command, type 'help <command-name>'.
② 调用 help
后面跟任何命令,会列出该命令的帮助条目以及任何子命令、选项和参数。通过在所有命令上迭代调用 help <command> <subcommand> [<subcommand>…]
,可以遍历整个 LLDB 的命令层次结构。例如,调用 help help
命令,可以查看 help
命令的帮助文档:
(lldb) help help
# 显示所有调试器命令的列表,或者提供有关特定命令的详细信息
Syntax: help [<cmd-name>]
Command Options Usage:
help [-ahu] [<cmd-name> [<cmd-name> [...]]]
-a ( --hide-aliases )
# 在命令列表中隐藏命令别名
-h ( --show-hidden-commands )
# 显示所有命令(包括前面带有下划线的命令)
-u ( --hide-user-commands )
# 在命令列表中隐藏用户自定义的命令
# help 命令接受命令选项(options)和自由格式的参数(free-form arguments)
# 如果你的参数类似于命令选项(options)说明符(例如,它们以 - 或者 -- 开头),则你必须在命令选项(options)的结尾和参数的开头之间使用 '--' 分隔
# 即当一个命令即有选项也有参数时,选项要放在前面,参数要放在后面,并且在选项的结尾与参数的开头之间插入 '--' 将选项与参数分隔开
③ 调用 help 命令别名
,可以用来了解命令别名的构造。例如,输入 help b
以查看所提供的对 GDB b
命令的仿真及其实现的说明:
(lldb) help b
# 使用以下几种速记格式之一设置断点
# 期望原始输入(请参阅 'help raw-input')
Syntax:
_regexp-break <filename>:<linenum>
main.c:12 # 在 main.c 文件的第 12 行设置断点
_regexp-break <linenum>
12 # 在当前文件的第 12 行设置断点
_regexp-break 0x<address>
0x1234000 # 在内存地址 0x1234000 处设置断点
_regexp-break <name>
main # 在名为 main 的函数上设置断点
_regexp-break &<name>
&main # 在名为 main 的函数的第一条汇编指令处设置断点
_regexp-break <module>`<name>
libc.so`malloc # 在 libc.so 库中名为 malloc 的函数上设置断点
_regexp-break /<source-regex>/
/break here/ # 在当前源文件中包含文本 break here 的行设置断点
# 'b' 是 '_regexp-break' 的命令别名
④ help
命令的输出信息中在尖括号中指定的命令参数(例如下面的 <breakpt-id>
)表明该参数是通用参数类型,通过查询命令系统可以获得进一步的帮助。例如,要了解有关 <breakpt-id>
的更多信息:
(lldb) help breakpoint enable
# 启用指定的断点。如果没有指定任何断点,则启用全部断点
Syntax: breakpoint enable [<breakpt-id | breakpt-id-list>]
(lldb) help <breakpt-id>
# 断点使用主要编号和次要编号来标识
# 主要编号对应于使用 'breakpoint set' 命令创建的单个实体
# 次要编号对应于根据主要编号的断点实际发现和设置的所有位置
# 一个完整的断点编号可能看起来类似于 3.14,这意味着为第 3 个断点设置的第 14 个位置
# 仅通过指示断点的主要编号,即可指定断点的所有位置
# 有效的断点编号只包含(主要编号),或者(主要编号.次要编号)。例如,3 或者 3.2 都可以是有效的断点编号
apropos 命令
探索 LLDB 中可用内容的一种更直接的方法是使用 apropos
命令:
它在 LLDB 帮助文档中搜索指定的单词,并为每个匹配的命令转储一个摘要字符串。例如:
(lldb) apropos file
The following commands may relate to 'file':
...
log enable -- Enable logging for a single log channel.
memory read -- Read from the memory of the process being debugged.
memory write -- Write to the memory of the process being debugged.
platform process launch -- Launch a new process on a remote platform.
platform select -- Create a platform if needed and select it as the current platform.
plugin load -- Import a dylib that implements an LLDB plugin.
process launch -- Launch the executable in the debugger.
process load -- Load a shared library into the current process.
source -- A set of commands for accessing source file information
... and so forth ...
命令分类
LLDB 把所有的命令分为 3 组:
Debugger commands
,LLDB 原始支持的几大块调试命令。例如:breakpoint
(断点相关)、process
(进程相关)、thread
(线程相关)、watchpoint
(内存断点相关)Current command abbreviations
,Debugger commands
中一些常用的命令或者子命令的别名或者缩写Current user-defined commands
,用户自定义的调试命令。如果当前机器上已经安装了 Chisel,则这里会直接列出 Chisel 提供的调试命令命令总览
(lldb) help -h
Debugger commands:
_regexp-attach # 根据进程 ID 或进程名称,附加到指定的进程
_regexp-break # 使用几种速记格式之一设置断点
_regexp-bt # 显示当前线程的调用栈
# 数字参数用于指定要显示的帧数,all 参数用于指定显示所有线程的调用栈
_regexp-display # 在每次程序暂停时,执行指定的表达式(请参阅 'help target stop-hook')
_regexp-down # 选择一个较新的栈帧
# 默认情况下移动一帧,指定数字参数以控制要移动的帧数
_regexp-env # 用于查看和设置环境变量
_regexp-jump # 将程序计数器(PC 寄存器)设置为新地址
_regexp-list # 使用几种速记格式之一列出相关源代码
_regexp-tbreak # 使用几种速记格式之一设置一次性断点
_regexp-undisplay # 在每次程序暂停时,停止执行指定的表达式(通过 stop-hook 索引指定,请参阅 'help target stop-hook')
_regexp-up # 选择一个较旧的栈帧
# 默认情况下移动一帧,指定数字参数以控制要移动的帧数
apropos # 用于列出与给定单词或者给定主题相关的调试命令
breakpoint # 用于操作断点的命令(参见 'help b' 以查看速记格式)
command # 用于管理自定义 LLDB 命令的命令
disassemble # 反汇编当前 target 中的指定指令
# 默认为当前线程的当前栈帧中的当前函数
expression # 用于在当前线程上执行给定的表达式,并以 LLDB 的默认格式显示返回值
frame # 用于选择和检视当前线程的栈帧的命令
gdb-remote # 用于通过远程 GDB server 连接到一个进程
# 如果没有指定 host,则假设为 localhost
gui # 用于切换到基于 curses 的 GUI 模式
help # 用于显示所有调试器命令的列表,或者提供有关特定命令的详细信息
kdp-remote # 用于通过远程 KDP server 连接到一个进程
# 如果没有指定 UDP 的端口,则假设为该端口为 41139
language # 用于指定要在运行时操作的语言(C++、OC、RenderScript、Swift)
log # 用于控制 LLDB 内部日志记录的命令
memory # 用于操作当前目标进程中的内存的命令
platform # 用于管理和创建操作系统平台的命令
plugin # 用于管理 LLDB 插件的命令
process # 用于与当前平台上的进程进行交互的命令
quit # 用于退出 LLDB 调试器
register # 用于访问当前线程和栈帧的寄存器的命令
reproducer # 用于操作复制器的命令
# 复制器可以捕获具有所有依赖项的完整调试会话
# resulting 复制器用于在调试调试器时重放调试会话
# 因为复制器需要从头到尾的整个调试会话,所以需要以捕获模式(capture mode)或者重放模式(replay mode)启动调试器,通常通过命令行驱动程序
# 因为复制器是不相关的记录-重放调试,所以在重放期间您不能与调试器交互
script # 使用所提供的代码调用脚本解释器,并显示调用结果
# 如果没有提供任何代码,则启动交互式解释器
settings # 用于管理 LLDB 设置的命令
source # 用于检查由当前目标进程的调试信息所描述的源代码的命令
statistics # 用于打印有关调试会话的统计信息
target # 用于对调试器 target 进行操作的命令
thread # 用于操作当前进程中的一个或者多个线程的命令
type # 用于在类型系统(type system)上操作的命令
version # 用于显示 LLDB 调试器的版本
watchpoint # 用于操作内存断点的命令
Current command abbreviations (type 'help command alias' for more info):
# 当前已经存在的命令别名(输入 'help command alias' 以获取更多信息):
add-dsym # 通过指定调试符号文件的路径,或使用选项指定要下载符号的模块,将调试符号文件添加到 target 的当前模块之一
attach # 通过进程 ID 或者进程名称附加到进程
b # 使用几种速记格式之一设置断点
bt # 显示当前线程的调用栈
# 指定数字参数将用于控制要显示的调用栈的数量,指定 all 参数将显示所有线程的调用栈
c # 继续执行当前进程中的所有线程
call # 在当前线程上执行给定的表达式,并以 LLDB 的默认格式显示返回值
continue # 继续执行当前进程中的所有线程
detach # 脱离当前的目标进程
di # 反汇编当前 target 中指定的汇编指令
# 默认为当前线程的当前栈帧中的当前函数
dis # 分解当前 target 中指定的汇编指令
# 默认为当前线程的当前栈帧中的当前函数
display # 在每次进程暂停时都执行一个给定的表达式(请参阅 'help target stop-hook')
down # 选择一个较新的栈帧
# 默认情况下移动一帧,指定数字参数以控制要移动的帧数
env # 用于查看和设置环境变量
exit # 退出 LLDB 调试器
f # 通过给定的索引在当前线程中选择当前栈帧(请参阅 'thread backtrace')
file # 使用给定的参数作为主可执行文件(main executable)来创建一个 target
finish # 完成当前栈帧的执行,并在返回后暂停
# 除非指定,否则默认为当前线程
image # 用于访问一个或者多个目标模块的信息的命令
j # 将程序计数器(pc 寄存器)设置为一个新的地址
jump # 将程序计数器(pc 寄存器)设置为一个新的地址
kill # 终止当前的目标进程
l # 使用几种速记格式之一列出相关的源代码
list # 使用几种速记格式之一列出相关的源代码
n # 源码级别的单步执行,以黑盒的方式执行一行代码
# 除非指定,否则默认为当前线程
# 遇到子函数不会进入,而是会执行这个子函数,然后继续
next # 源码级别的单步执行,以黑盒的方式执行一行代码
# 除非指定,否则默认为当前线程
# 遇到子函数不会进入,而是会执行这个子函数,然后继续
nexti # 汇编指令级别的单步执行,以黑盒的方式执行一条汇编指令
# 除非指定,否则默认为当前线程
# 遇到汇编函数不会进入,而是会执行这个汇编函数,然后继续
ni # 汇编指令级别的单步执行,以黑盒的方式执行一条汇编指令
# 除非指定,否则默认为当前线程
# 遇到汇编函数不会进入,而是会执行这个汇编函数,然后继续
p # 在当前线程上执行给定的表达式,并以 LLDB 的默认格式显示返回值
parray # parray <COUNT> <EXPRESSION>
# LLDB 会执行 EXPRESSION 所标识的表达式以在内存中获取一个指向数组的类型指针
# 并将显示数组中 COUNT 个该类型的元素
po # 在当前线程上执行给定的表达式,并以 LLDB 的默认格式显示返回值
poarray # poarray <COUNT> <EXPRESSION>
# LLDB 会执行 EXPRESSION 所标识的表达式以在内存中获取数组中 COUNT 个元素的地址
# 并且对获取到的这些元素调用 po 命令
print # 在当前线程上执行给定的表达式,并以 LLDB 的默认格式显示返回值
q # 退出 LLDB 调试器
r # 在调试器中启动可执行文件
rbreak # 在可执行文件中设置一个或者一组断点
re # 用于访问当前线程和栈帧的寄存器的命令
repl # 在当前线程上执行给定的表达式,并以 LLDB 的默认格式显示返回值
run # 在调试器中启动可执行文件
s # 源码级别的单步执行,以白盒的方式执行一行代码
# 除非指定,否则默认为当前线程
# 遇到子函数就进入并且继续单步执行
shell # 在主机上执行 shell 命令
si # 汇编指令级别的单步执行,以白盒的方式执行一条汇编指令
# 除非指定,否则默认为当前线程
# 遇到汇编函数就进入并且继续单步执行
sif # 单步执行当前的 block,如果直接进入名称与 TargetFunctionName 匹配的函数,则暂停
step # 源码级别的单步执行,以白盒的方式执行一行代码
# 除非指定,否则默认为当前线程
# 遇到子函数就进入并且继续单步执行
stepi # 汇编指令级别的单步执行,以白盒的方式执行一条汇编指令
# 除非指定,否则默认为当前线程
# 遇到汇编函数就进入并且继续单步执行
t # 更改当前选定的线程
tbreak # 使用几种速记格式之一设置一次性断点
undisplay # 取消 stop-hook(通过 stop-hook index 指定)
# hcg 注:stop-hook 用于在每次进程暂停时都执行一个给定的表达式(请参阅 'help target stop-hook')
up # 选择一个较旧的栈帧
# 默认情况下移动一帧,指定数字参数以控制要移动的帧数
v # 显示当前栈帧中的变量
# 默认为作用域内的所有参数和局部变量
# 可以指定参数、局部变量、文件静态变量和文件全局变量的名称
# 可以指定聚合变量的子变量,例如:'var->child.x'
# 'frame variable' 指令中的操作符 -> 和 [] 不会调用操作符重载,而是直接访问指定的元素
# 如果要触发操作符的重载,则请使用 expression 命令来打印变量
# 值得注意的是,除了重载操作符外,当打印局部变量时,'expr local_var' 和 'frame var local_var' 会产生相同的结果
# 然而,'frame variable' 更具效率,因为它使用调试信息和直接读取内存,而不是解析和执行一个表达式(这可能涉及 JITing 和在目标程序中运行代码)
var # 显示当前栈帧中的变量
# 默认为作用域内的所有参数和局部变量
# 可以指定参数、局部变量、文件静态变量和文件全局变量的名称
# 可以指定聚合变量的子变量,例如:'var->child.x'
# 'frame variable' 指令中的操作符 -> 和 [] 不会调用操作符重载,而是直接访问指定的元素
# 如果要触发操作符的重载,则请使用 expression 命令来打印变量
# 值得注意的是,除了重载操作符外,当打印局部变量时,'expr local_var' 和 'frame var local_var' 会产生相同的结果
# 然而,'frame variable' 更具效率,因为它使用调试信息和直接读取内存,而不是解析和执行一个表达式(这可能涉及 JITing 和在目标程序中运行代码)
vo # 显示当前栈帧中的变量
# 默认为作用域内的所有参数和局部变量
# 可以指定参数、局部变量、文件静态变量和文件全局变量的名称
# 可以指定聚合变量的子变量,例如:'var->child.x'
# 'frame variable' 指令中的操作符 -> 和 [] 不会调用操作符重载,而是直接访问指定的元素
# 如果要触发操作符的重载,则请使用 expression 命令来打印变量
# 值得注意的是,除了重载操作符外,当打印局部变量时,'expr local_var' 和 'frame var local_var' 会产生相同的结果
# 然而,'frame variable' 更具效率,因为它使用调试信息和直接读取内存,而不是解析和执行一个表达式(这可能涉及 JITing 和在目标程序中运行代码)
x # 从当前目标进程的内存中读取数据
For more information on any command, type 'help <command-name>'.
# 有关任何命令的更多信息,请输入 'help <command-name>'