当前位置: 首页 > 工具软件 > LLDB > 使用案例 >

LLDB(一):入门指南

胡承悦
2023-12-01

LLDB 简介

  • 什么是 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 可以用于符号化,反汇编,对象和符号文件自省,等等

LLDB 入门

  • 命令语法(Command Syntax)

    LLDB 命令语法自始至终都是结构化和规则的,LLDB 的命令都是以下形式:

    <command> [<subcommand> [<subcommand>...]] <action> [-options [option-value]] [argument [argument...]]
    

    其中:

    1. 命令(command)和子命令(subcommand):调试命令的名称。命令和子命令按照层级结构排列:一个命令对象为跟随其的子命令对象创建一个上下文,子命令对象又为下一个跟随其的子命令对象创建一个上下文,依此类推
    2. 行为(action):要在命令和子命令序列的上下文中执行的操作
    3. 选项(options):是行为的修饰符,通常带有一个值
    4. 参数(argument):根据当前所使用的命令和子命令的上下文表示各种不同的东西
    5. 方括号([ ]):用于表示可选项

    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
    

    与上述命令的语法模式不同的命令(例如:ppoprintb)通常是由命令别名机制所创建的自定义命令,会在接下来 命令别名(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 中(例如:stepnextcontinue),但并未尝试构建详尽的别名集。根据 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): ...
    

帮助命令与搜索命令:help 与 apropos

探索 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 组:

    1. Debugger commands,LLDB 原始支持的几大块调试命令。例如:breakpoint(断点相关)、process(进程相关)、thread(线程相关)、watchpoint(内存断点相关)
    2. Current command abbreviationsDebugger commands 中一些常用的命令或者子命令的别名或者缩写
    3. 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>'
    
 类似资料: