工欲善其事,必先利其器。程序猿最好的利器就是开发工具,iOS开发者最基本,最关键的一点就是熟练使用Xcode,而LLDB则是Xcode中至关重要的一环。 作为开发者,我们大部分的工作时间都用于调试,调试协议,调试UI,调试bug,用好LLDB,打遍iOS无敌手。
LLDB拥有大量有用的调试命令:
代码语言:javascript复制(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.)
bugreport -- Commands for creating domain-specific bug reports.
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.
script -- Invoke the script interpreter with provided code and
display any results. Start the interactive interpreter
if no code is supplied.
settings -- Commands for managing LLDB settings.
source -- Commands for examining source code described by debug
information for the current target process.
statistics -- Print statistics about a debugging session
target -- Commands for operating on debugger targets.
thread -- Commands for operating on one or more threads in the
current process.
type -- Commands for operating on the type system.
version -- Show the LLDB debugger version.
watchpoint -- Commands for operating on watchpoints.
Current command abbreviations (type 'help command alias' for more info):
add-dsym -- Add a debug symbol file to one of the target's 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.
b -- Set a breakpoint using one of several shorthand formats.
bt -- Show the current thread's call stack. Any numeric argument
displays at most that many frames. The argument 'all' displays
all threads.
c -- Continue execution of all threads in the current process.
call -- Evaluate an expression on the current thread. Displays any
returned value with LLDB's default formatting.
continue -- Continue execution of all threads in the current process.
detach -- Detach from the current target process.
di -- Disassemble specified instructions in the current target.
Defaults to the current function for the current thread and
stack frame.
dis -- Disassemble specified instructions in the current target.
Defaults to the current function for the current thread and
stack frame.
display -- Evaluate an expression at every stop (see 'help target
stop-hook'.)
down -- Select a newer stack frame. Defaults to moving one frame, a
numeric argument can specify an arbitrary number.
env -- Shorthand for viewing and setting environment variables.
exit -- Quit the LLDB debugger.
f -- Select the current stack frame by index from within the current
thread (see 'thread backtrace'.)
file -- Create a target using the argument as the main executable.
finish -- Finish executing the current stack frame and stop after
returning. Defaults to current thread unless specified.
image -- Commands for accessing information for one or more target
modules.
j -- Set the program counter to a new address.
jump -- Set the program counter to a new address.
kill -- Terminate the current target process.
l -- List relevant source code using one of several shorthand formats.
list -- List relevant source code using one of several shorthand formats.
n -- Source level single step, stepping over calls. Defaults to
current thread unless specified.
next -- Source level single step, stepping over calls. Defaults to
current thread unless specified.
nexti -- Instruction level single step, stepping over calls. Defaults to
current thread unless specified.
ni -- Instruction level single step, stepping over calls. Defaults to
current thread unless specified.
p -- Evaluate an expression on the current thread. Displays any
returned value with LLDB's default formatting.
parray -- Evaluate an expression on the current thread. Displays any
returned value with LLDB's default formatting.
po -- Evaluate an expression on the current thread. Displays any
returned value with formatting controlled by the type's author.
poarray -- Evaluate an expression on the current thread. Displays any
returned value with LLDB's default formatting.
print -- Evaluate an expression on the current thread. Displays any
returned value with LLDB's default formatting.
q -- Quit the LLDB debugger.
r -- Launch the executable in the debugger.
rbreak -- Sets a breakpoint or set of breakpoints in the executable.
repl -- Evaluate an expression on the current thread. Displays any
returned value with LLDB's default formatting.
run -- Launch the executable in the debugger.
s -- Source level single step, stepping into calls. Defaults to
current thread unless specified.
si -- Instruction level single step, stepping into calls. Defaults to
current thread unless specified.
sif -- Step through the current block, stopping if you step directly
into a function whose name matches the TargetFunctionName.
step -- Source level single step, stepping into calls. Defaults to
current thread unless specified.
stepi -- Instruction level single step, stepping into calls. Defaults to
current thread unless specified.
t -- Change the currently selected thread.
tbreak -- Set a one-shot breakpoint using one of several shorthand
formats.
undisplay -- Stop displaying expression at every stop (specified by stop-hook
index.)
up -- Select an older stack frame. Defaults to moving one frame, a
numeric argument can specify an arbitrary number.
x -- Read from the memory of the current target process.
先简单翻一下,做个大概了解
代码语言:javascript复制Debugger commands:
apropos 列出与Word或主题相关的调试器命令
breakpoint 操作断点的命令
bugreport 创建特定领域错误报告的命令
command 管理自定义LLDB命令的命令
disassemble 拆卸当前指定的指令,默认为当前函数为当前线程和堆栈帧
expression 评估当前线程上的表达式。任何返回值与LLDB的默认格式。
frame 命令选择和检查当前线程的堆栈帧,GDB远程通过远程GDB服务器连接到进程,如果没有主机指定localhost假设
gui 切换到基于诅咒的GUI模式。
kdp-remote 通过远程KDP服务器连接进程,如果没有UDP端口被指定,假定端口41139。
language 特定于源语言的命令log 控制LLDB内部记录命令。
memory 在当前目标上操作内存的命令过程
platform 管理和创建平台的命令
plugin 管理LLDB插件
process 与当前进程交互的命令平台
quit 退出LLDB调试器。
register 为当前线程访问寄存器的命令栈帧
script 使用提供的代码调用脚本解释器,显示任何结果。启动交互式解释器,如果没有提供代码。
settings 管理LLDB设置命令
source 检查由调试描述的源代码的命令,当前目标过程的信息。
target 在调试器对象上操作的命令
thread 中的一个或多个线程操作的命令目前的过程
type 在类型系统上操作的命令
version 显示LLDB调试器版本
watchpoint 操作上观察点的命令.当前命令缩写(类型“帮助命令别名”以获取更多信息)
add-dsym 将调试符号文件添加到目标当前模块中的一个通过指定调试符号文件的路径,或使用选项来指定下载符号的模块
attach 通过ID或名称附加到进程
b 使用几个速记格式中的一个设置断点
bt 显示当前线程的调用堆栈。任何数字参数最多显示许多帧。参数“所有”显示所有的线程
c 继续执行当前进程中的所有线程
call 评估当前线程上的表达式。显示任何返回值与LLDB的默认格式
continue 继续执行当前进程中的所有线程
detach 从当前目标进程分离
di 拆卸当前目标中指定的指令,默认为当前线程的当前功能和栈帧
dis 拆卸当前目标中指定的指令,默认为当前线程的当前功能和栈帧
display 在每一站评估表达式(参见“帮助目标”停止钩子)
down 选择一个较新的堆栈帧。默认为移动一帧数字参数可以指定任意数量
env 查看和设置环境变量的简写
exit 退出LLDB调试器
f 从当前范围内选择索引的当前堆栈帧线程(见螺纹回溯”。)
file 使用参数作为主要可执行文件创建目标
finish 完成执行当前堆栈帧后停止返回,默认为当前线程,除非指定
image 为一个或多个目标访问信息的命令模块
j 将程序计数器设置为新地址
jump 将程序计数器设置为新地址
kill 终止当前目标进程
l 使用几个速记中的一个列出相关的源代码格式
list 使用几个速记中的一个列出相关的源代码格式
n 源级单步,单步调用。默认为当前线程,除非指定
next 源级单步,单步调用。默认为当前线程,除非指定
nexti 单步单步执行指令,默认为当前线程,除非指定
ni 单步单步执行指令,默认为当前线程,除非指定
p 评估当前线程上的表达式。显示任何返回值与LLDB的默认格式
parray 评估当前线程上的表达式。显示任何返回值与LLDB的默认格式
po 评估当前线程上的表达式。显示任何由类型作者控制的格式返回值
poarray 评估当前线程上的表达式。显示任何返回值与LLDB的默认格式
print 评估当前线程上的表达式。显示任何返回值与LLDB的默认格式
q 退出LLDB调试器
r 在调试器中启动可执行文件
rbreak 在可执行文件中设置断点或断点集。
repl 评估当前线程上的表达式。显示任何返回值与LLDB的默认格式
run 在调试器中启动可执行文件
s 源级单步,单步调用。默认为当前线程,除非指定
si 单步单步执行指令,默认为当前线程,除非指定
sif 通过当前块,如果直接单步执行停止为一个函数的名称相匹配的targetfunctionname
step 源级单步,单步调用。默认为当前线程,除非指定
stepi 单步单步执行指令,默认为当前线程,除非指定
t 更改当前选定的线程
tbreak 使用一一个快捷键中的一个设置断点格式
undisplay 停止在每一站显示表达式(由停止钩子指定)指标。)
up 选择一个旧的堆栈帧。默认为移动一帧,一个数字参数可以指定任意数量
x 从当前目标进程的内存中读取
其中一些常见的重要命令我会提炼出来跟大家一起探讨:
- 获取变量值: expression , e , print , po , p
- 获取执行环境 特定语言命令: bugreport , frame , language
- 执行流程控制: process , breakpoint , thread , watchpoint
- 单步调试:n,s,finish,c
- 其他: command , platform , gui,image
基本功能:获取变量值和状态
调试最基本的功能是打印和修改变量的值,单步调试,确定是不是按照设定的方式运行,便于快速定位。 命令: expression , e , print , po , p
- expression、e指令: 既可以打印也可以赋值(后面有例子详解)
- print指令: 除了 print 命令没有可用选项无需传递参数外, print 和 expression -- 几乎一样。
- p指令: 可打印其对象类型、内存地址以及该对象的值等具体信息,print的简写
- po指令: 是打印其调用description方法得到的值。实际上,po指令就是 e -O -- 的别名
- expr指令: expression的简写
- call指令: 调用方法的意思
例如:
代码语言:javascript复制func sum(_ a: Int, _ b: Int) -> Int {
return a b
}
sum(5, 4)
p指令结果:
代码语言:javascript复制(lldb) p a
(Int) $R0 = 5
po指令结果:
代码语言:javascript复制(lldb) po a
5
e指令结果:
代码语言:javascript复制(lldb) e a
(Int) $R6 = 5
e赋值结果:
代码语言:javascript复制(lldb) e b = 10
(lldb) po a b
15
------分割线------ 看完基本指令,再来深入了解下expression指令。 expression命令拥有大约30个选项,可以调用help命令先大概了解下:
代码语言:javascript复制help expression
Evaluate an expression on the current thread. Displays any returned value
with LLDB's default formatting. Expects 'raw' input (see 'help
raw-input'.)
Syntax: expression <cmd-options> -- <expr>
Command Options Usage:
expression [-AFLORTgp] [-f <format>] [-G <gdb-format>] [-a <boolean>] [-i <boolean>] [-t <unsigned-integer>] [-u <boolean>] [-l <source-language>] [-X <boolean>] [-v[<description-verbosity>]] [-j <boolean>] [-d <none>] [-S <boolean>] [-D <count>] [-P <count>] [-Y[<count>]] [-V <boolean>] [-Z <count>] -- <expr>
expression [-AFLORTgp] [-a <boolean>] [-i <boolean>] [-t <unsigned-integer>] [-u <boolean>] [-l <source-language>] [-X <boolean>] [-j <boolean>] [-d <none>] [-S <boolean>] [-D <count>] [-P <count>] [-Y[<count>]] [-V <boolean>] [-Z <count>] -- <expr>
expression [-r] -- <expr>
expression <expr>
-A ( --show-all-children )
Ignore the upper bound on the number of children to show.
-D <count> ( --depth <count> )
Set the max recurse depth when dumping aggregate types (default is
infinity).
-F ( --flat )
Display results in a flat format that uses expression paths for
each variable or member.
-G <gdb-format> ( --gdb-format <gdb-format> )
Specify a format using a GDB format specifier string.
-L ( --location )
Show variable location information.
-O ( --object-description )
Display using a language-specific description API, if possible.
-P <count> ( --ptr-depth <count> )
The number of pointers to be traversed when dumping values (default
is zero).
-R ( --raw-output )
Don't use formatting options.
-S <boolean> ( --synthetic-type <boolean> )
Show the object obeying its synthetic provider, if available.
-T ( --show-types )
Show variable types when dumping values.
-V <boolean> ( --validate <boolean> )
Show results of type validators.
-X <boolean> ( --apply-fixits <boolean> )
If true, simple fix-it hints will be automatically applied to the
expression.
-Y[<count>] ( --no-summary-depth=[<count>] )
Set the depth at which omitting summary information stops (default
is 1).
-Z <count> ( --element-count <count> )
Treat the result of the expression as if its type is an array of
this many values.
-a <boolean> ( --all-threads <boolean> )
Should we run all threads if the execution doesn't complete on one
thread.
-d <none> ( --dynamic-type <none> )
Show the object as its full dynamic type, not its static type, if
available.
Values: no-dynamic-values | run-target | no-run-target
-f <format> ( --format <format> )
Specify a format to be used for display.
-g ( --debug )
When specified, debug the JIT code by setting a breakpoint on the
first instruction and forcing breakpoints to not be ignored (-i0)
and no unwinding to happen on error (-u0).
-i <boolean> ( --ignore-breakpoints <boolean> )
Ignore breakpoint hits while running expressions
-j <boolean> ( --allow-jit <boolean> )
Controls whether the expression can fall back to being JITted if
it's not supported by the interpreter (defaults to true).
-l <source-language> ( --language <source-language> )
Specifies the Language to use when parsing the expression. If not
set the target.language setting is used.
-p ( --top-level )
Interpret the expression as a complete translation unit, without
injecting it into the local context. Allows declaration of
persistent, top-level entities without a $ prefix.
-r ( --repl )
Drop into Swift REPL
-t <unsigned-integer> ( --timeout <unsigned-integer> )
Timeout value (in microseconds) for running the expression.
-u <boolean> ( --unwind-on-error <boolean> )
Clean up program state if the expression causes a crash, or raises
a signal. Note, unlike gdb hitting a breakpoint is controlled by
another option (-i).
-v[<description-verbosity>] ( --description-verbosity=[<description-verbosity>] )
How verbose should the output of this expression be, if the object
description is asked for.
Values: compact | full
Single and multi-line expressions:
The expression provided on the command line must be a complete expression
with no newlines. To evaluate a multi-line expression, hit a return after
an empty expression, and lldb will enter the multi-line expression editor.
Hit return on an empty line to end the multi-line expression.
Timeouts:
If the expression can be evaluated statically (without running code) then
it will be. Otherwise, by default the expression will run on the current
thread with a short timeout: currently .25 seconds. If it doesn't return
in that time, the evaluation will be interrupted and resumed with all
threads running. You can use the -a option to disable retrying on all
threads. You can use the -t option to set a shorter timeout.
User defined variables:
You can define your own variables for convenience or to be used in
subsequent expressions. You define them the same way you would define
variables in C. If the first character of your user defined variable is a
$, then the variable's value will be available in future expressions,
otherwise it will just be available in the current expression.
Continuing evaluation after a breakpoint:
If the "-i false" option is used, and execution is interrupted by a
breakpoint hit, once you are done with your investigation, you can either
remove the expression execution frames from the stack with "thread return
-x" or if you are still interested in the expression result you can issue
the "continue" command and the expression evaluation will complete and the
expression result will be available using the "thread.completed-expression"
key in the thread format.
Examples:
expr my_struct->a = my_array[3]
expr -f bin -- (index * 8) 5
expr unsigned int $foo = 5
expr char c[] = "foo"; c[0]
Important Note: Because this command takes 'raw' input, if you use any
command options you must use ' -- ' between the end of the command options
and the beginning of the raw input.
LLDB使用双破折号--分隔选项和表达式:
代码语言:javascript复制(lldb) expression <some flags> -- <variable></variable></some flags>
下面列出了几个比较常用的选项:
- D ( --depth ) - 设置打印聚合类型的递归深度(默认无限递归)。
- O ( --object-desctiption ) - 打印description方法。
- T ( --show-types ) - 显示每个变量的类型。
- f ( --format ) - 设置输出格式。
- i ( --ignore-breakpoints ) - 运行表达式时忽略表达式内的断点。
获取执行环境 特定语言命令
bugreport , frame , language
- bugreport LLDB的 bugreport 命令可以生成一份详细的app当前状态的报告。该命令对于想要延迟追踪定位问题非常有用。为了保存app的状态,你可以使用 bugreport 来生成报告。
help bugreport
Commands for creating domain-specific bug reports.
Syntax: bugreport <subcommand> [<subcommand-options>]
The following subcommands are supported:
unwind -- Create a bugreport for a bug in the stack unwinding code.
For more help on any particular subcommand, type 'help <command> <subcommand>'.
可以看到,bugreport的参数只有unwind,即:
代码语言:javascript复制(lldb) bugreport unwind --outfile <path to output file></path to output file>
- frame
- language
单步调试
单步调试,修改指针变量的值,观测程序不同变化 Xcode调试面板上实际已经有了按钮去实现,再这里简单介绍下: n 命令,代表 Step Over 操作。 s 命令,代表 Step Into 操作。 finish 命令,代表 Step Out 操作。 c 命令,代表恢复程序执行操作。
其他:
- command
- platform
- gui
- image 1、image lookup --address寻址,定位异常代码位置 举例说明,下面这段代码,执行的时候必然会出现异常,因为越界了:
NSString *str = @"245656";
[str substringFromIndex:10];
2、image lookup --type查看类型
------------------------------分割线------------------------------ ------------------------------分割线------------------------------ ------------------------------分割线------------------------------ --------------------------重要事情说三遍-------------------------
编辑断点
介绍完命令后,来个五星推荐必备技能:编辑断点!!编辑断点!!编辑断点!! 断点调试是一把刀,帮助我们披荆斩棘,而编辑断点则是磨刀石,能够让我们的刀更锋利,所向披靡。