前言
学如逆水行舟,不进则退。共勉!!!
闲来无事,一篇lldb详解送给大家了。
lldb详解
lldb命令
t:以二进制格式输出
x:以十六进制格式输出
o:以八进制格式输出
b:1-byte
w:2-byte
l:4-byte
-
q:8-byte您可能会看到一个对话框,显示开发人员工具访问需要控制另一个过程才能继续调试。如果出现此提示, 则必须输入用户名和密码才能进行调试。
如果您希望永久关闭此提示,则可以在终端中运行以下命令:
1|sudo DevToolsSecurity --enable
使用说明
- --attach-name :告诉调试器以给定名称附加到进程
- --attach-pid :告诉调试器使用给定的pid附加到进程
- -n :--attach-name的别名
- -p :--attach-pid的别名。
- --wait-for : 告诉调试器在附加之前等待具有给定pid或名称的进程启动。
- -w : --wait-for的别名
- --batch :告诉调试器从-s -S -o和-D运行命令,然后退出
- -b : --batch别名
- -K : --source-on-crash的别名
- -k : --one-on-on-crash的别名
- --local-lldbinit 允许调试器解析当前工作目录中的.lldbinit文件,除非传递了--no-lldbinit
- --no-lldbinit : 不要自动解析任何 .lldbinit 文件
- --one-line-before-file :告诉调试器在加载命令行上提供的任何文件之前执行此单行 lldb命令
- --one-line-on-crash :在批处理模式下,如果目标崩溃,则告诉调试器运行此单行lldb命令
- --one-line :告诉调试器在加载命令行上提供的任何文件后执行此单行lldb命令
- -O : --one-line-before-file :的别名
- -o : --one行的别名
- -Q --source-quietly:别名
- --source-before-file :告诉调试器在加载任何文件之前读入并执行给定文件中的lldb命令。
- --source-on-crash :在批处理模式下,如果目标崩溃,则告诉调试器为lldb命令提供此文件。
- --source-quietly :告诉调试器在加载任何文件之前执行此单行lldb命令
- -S : --source-before-file的别名
- -s : --source的别名
- -x : --no-lldbinit别名
- --arch : 告诉调试器在启动和运行程序时使用指定的体系结构
- -a : --arch的别名
- --capture-path :告诉调试器将给定的文件名用于复制器
- --capture :告诉调试器捕获复制器
- --core :告诉调试器将 的完整路径用作核心文件
- -c : --core 的别名
- --debug :告诉调试器打印出更多信息以进行调试
- -d : --debug别名
- --editor:告诉调试器使用主机的“外部编辑器”机制打开源文件。
- -e : --editor别名
- --file : 告诉调试器将文件 用作要调试的程序
- -f : --file的别名
- --help : 输出LLDB调试器的使用信息
- -h : --help 的别名
- --no-use-colors :不要使用颜色
- --replay : 告诉调试器从重放再现器
- --reproducer-auto-generate : 退出时生成复制器
- --reproducer-skip-version-check : 跳过复制器版本检查
- --version :打印出LLDB调试器的当前版本号
- -v : --version的别名
- -X : --no-use-color
- -r= : --repl=的别名
- --repl-language :选择REOL的语言
- --repl = :使用带有给定标志的存根进程以REPL模式运行lldb
- --repl :使用存根进程以REPL模式运行lldb
- -R : --reps-language 的别名
- -r : --repl别名
- -l : --script-language的别名
- --python-path : 输出此版本lldb的lldb.py文件的路径
- -P : --python-path的别名
- --script-language : 告诉调试器将指定的脚本语言用于用户定义的脚本
打印
1|#查询指定类实现
2|(lldb) type lookup<类名>
3|#获取指定命令帮助
4|(lldb) help <command> <subcommand>
复制代码
设置log输出
1|(lldb) log enable lldb -v -- all
复制代码
设置行号
// The following are the various types of breakpoints that could be set: // 1). -f -l -p -s -g // 2). -a -s -g // 3). -n -s -g // 4). -r -s -g // 5). -p -f (setting a breakpoint by comparing a reg-exp // to source text) // 6). -E -w -h
(lldb) breakpoint set --file test.c --line 12
(lldb) br s -f test.c -l 12
(lldb) b test.c:12
#列出已设置的断点
(lldb) breakpoint list
(lldb) br l
#禁用breakpoint 1 的所有位置
(lldb) break disable 1.*
(lldb) break enable 1.1
# 删除一个断点
(lldb) breakpoint delete 1
(lldb) br del 1
#禁用一个断点
(lldb) breakpoint disable 1
(lldb) br dis 1
# 启用一个断点
(lldb) breakpoint enable 1
(lldb) br en 1
#对指定的函数名下断点
(lldb) breakpoint set --name main
(lldb) br s -n main
(lldb) b main
# 对指定的C++函数名下断点
(lldb) breakpoint set --method main
(lldb) br s -M main
#通过字符串对指定的OC方法函数下断点
(lldb) breakpoint set --name "-[NSString stringWithFormat:]"
(lldb) b -[NSString stringWithFormat:]
#对指定名称的OC Selector下断点
(lldb) breakpoint set --selector count
(lldb) br s -S count
#对符合指定的正则表达式的函数下断点
(lldb) breakpoint set --func-regex regular-expression
(lldb) br s -r regular-expression
(lldb) rb regular-expression
#对指定库中的符合指定的正则表达式的函数下断点
(lldb) breakpoint set --func-regex=. --shlib=libfoo.dylib
#打开行号断点开关
(lldb) settings set target.inline-breakpoint-strategy always
(lldb) br s -f foo.c -l 12
#通过对指定的正则表达式对文件内容设置断点
(lldb) breakpoint set --source-pattern regular-expression --file SourceFile
(lldb) br s -p regular-expression -f file
#设置条件断点
(lldb) breakpoint set --name foo --condition '(int)strcmp(y,"hello") == 0'
(lldb) br s -n foo -c '(int)strcmp(y,"hello") == 0
#### register
显示当前线程的通用寄存器
(lldb) register read
显示指定的寄存器的内容 (lldb) register read rax rsp rbp
指定寄存器以指定格式显示内容
(lldb) register read --format binary rax (lldb) re r -f b rax (lldb) register read/t rax (lldb) p/t $rax
向指定寄存器写入指定数据 (lldb) register write rax 123
在当前程序计数器(指令指针)之前跳过8个字节 (lldb) register write pc $pc+8
显示格式为带符号十进制的当前线程的通用寄存器 (lldb) register read --format i (lldb) re r -f i (lldb) register read/d
显示当前线程所有的寄存器内容 (lldb) register read --all (lldb) re r -a
#### 启动运行
复制代码
(lldb) process launch (lldb) run (lldb) r
启动附加参数 (lldb) process launch -- (lldb) run (lldb) r % lldb -- a.out 1 2 3 (lldb) run (lldb) run lldb) settings set target.run-args 1 2 3 (lldb) run (lldb) run
#### 设置环境变量
复制代码
在启动之前,设置环境变量 (lldb) settings target.disable-aslr (lldb) settings set target.env-vars DYLD_PRINT_APIS=YES (lldb) set se target.env-vars DYLD_PRINT_APIS=YES (lldb) env DYLD_PRINT_APIS=YES (lldb) settings set target.env-vars DYLD_PRINT_LIBRARIES=1
在启动之前,删除环境变量
(lldb) settings remove target.env-vars DEBUG (lldb) set rem target.env-vars DEBUG
显示将在运行时传递给程序的环境变量 (lldb) settings show target.run-args
通过一个命令为进程和启动进程设置环境变量 (lldb) process launch -v DEBUG=1
附加到进程到指定的ID的进程 (lldb) process attach --pid 123 (lldb) attach -p 123
附加到指定名称的进程 (lldb) process attach --name a.out (lldb) pro at -n a.out
等待指定名称的进程启动并附加 (lldb) process attach --name a.out --waitfor (lldb) pro at -n a.out -w
memory
当前目标进程用于在内存上运行的命令。x是memory read的缩写
#-s(--size):指定内存块(block/item)的大小,默认为1byte̶
# -c( --count)指定内存块(block/item)的个数,可配合起始地址使用
# -f( --format)指定内容显示格式,格式符同printғc-char҅s-string҅d-decimal҅x-hex。
#从指定地址读取内存,并且按格式显示
(lldb) memory read --size 4 --format x --count 4 0xbffff3c0
(lldb) me r -s4 -fx -c4 0xbffff3c0
(lldb) x -s4 -fx -c4 0xbffff3c0
# LLDB now supports the GDB shorthand format syntax but there can't be space after the command:
(lldb) memory read/4xw 0xbffff3c0
(lldb) x/4xw 0xbffff3c0
(lldb) memory read --gdb-format 4xw 0xbffff3c0
# 从指定表达式读取内存
(lldb) memory read `argv[0]`
# NOTE: any command can inline a scalar expression result (as long as the target is stopped) using backticks around any expression:
(lldb) memory read --size `sizeof(int)` `argv[0]`
#从指定地址读取指定大小的内存,并且保存到指定的文件
(lldb) memory read --outfile /tmp/mem.txt --count 512 0xbffff3c0
(lldb) me r -o/tmp/mem.txt -c512 0xbffff3c0
(lldb) x/512bx -o/tmp/mem.txt 0xbffff3c0
# 保存指定范围的内存
(lldb) memory read --outfile /tmp/mem.bin --binary 0x1000 0x2000
(lldb) me r -o /tmp/mem.bin -b 0x1000 0x2000
复制代码
别名
#起别名
(lldb) command alias poc expression -l objc -O --
复制代码
打印数组
# 打印int a[4] = {1,2,3,4};(
lldb) parray 1 &a
复制代码
expression
#启动多行调试命令输出
(lldb) expr
#执行单行命令
(lldb) expr char c[] = "foo"; c[0]
#执行表达式,别名`p <expression>`
(lldb) expression -- <expression>
#`-i <boolean> ( --ignore-breakpoints <boolean> )当表达式在运行时忽略断点
(lldb) expr -i 0 -- function_with_a_breakpoint()
#-u <boolean> ( --unwind-on-error <boolean> )表达式导致崩溃或引发信号
(lldb) expr -u 0 -- function_which_crashes()
#` -l <source-language> ( --language <source-language> )`指定解析表达式时要使用的语言,如果未设置,则使用`target.language`中的设置。`-O ( --object-description )`打印设置API`
(lldb) expression -l objc -O -- [`self.view` recursiveDescription]
# `-L ( --location )`显示变量的位置信息
(lldb) expression -L -- I
# `-f <format> ( --format <format> )`指定显示格式
(lldb) expr -f bin -- (4 * 8) + 5
# `-t <unsigned-integer> ( --timeout <unsigned-integer> )`设置超时时间,默认情况下,表达式在当前线程超时时间为:0.25s。如果在这个时间内不返回,该表达式将中断并恢复线程运行
(lldb) expr -t -- <expression>
# `-Z <count> ( --element-count <count> )`打印数组
(lldb) 'expression -Z 3 -- <value>
#### 汇编
#显示当前函数当前帧的汇编信息
(lldb) disassemble --frame
(lldb) di -f
#显示指定函数的汇编信息
(lldb) disassemble --name main
(lldb) di -n main
#显示指定地址范围的汇编信息
(lldb) disassemble --start-address 0x1eb8 --end-address 0x1ec3
(lldb) di -s 0x1eb8 -e 0x1ec3
#显示指定数量的汇编信息
(lldb) disassemble --start-address 0x1eb8 --count 20
(lldb) di -s 0x1eb8 -c 20
#显示当前函数的当前帧的汇编与源码
(lldb) disassemble --frame --mixed
(lldb) di -f -m
# 显示当前函数的当前帧的汇编与操作码
(lldb) disassemble --frame --bytes
(lldb) di -f -b
# 显示当前帧的当前源码
(lldb) disassemble --line
(lldb) di -l
复制代码
逐行调试
继续执行代码 (lldb) continue (lldb) c( lldb) thread continue
step-over单步调试
(lldb) next (lldb) n (lldb) thread step-over
step-in跳进源码
(lldb) step (lldb) s (lldb) thread step-in #step-out跳出 (lldb) finish (lldb) f (lldb) thread step-out #每次代码停止时,执行固定调试步骤 (lldb) target stop-hook add Enter your stop hook command(s). Type 'DONE' to end.
bt disassemble --pc DONEStop hook #1 added
删除指定的stop-hook
target stop-hook delete 1 #获取stop-hook list target stop-hook list #每次代码停止时,执行指定调试 (lldb) target stop-hook add --one-liner "frame variable argc argv" (lldb) ta st a -o "fr v argc argv" (lldb) display argc (lldb) display argv #只有当停止到指定方法或函数的时候,才执行固定调试 (lldb) target stop-hook add --name main --one-liner "frame variable argc argv" (lldb) ta st a -n main -o "fr v argc argv" #只有当停止到指定类名的时候,才执行固定调试 (lldb) target stop-hook add --classname MyClass --one-liner "frame variable *this" #指定文件 (lldb) target stop-hook add -f main.cpp -l %d -e %d (lldb) ta st a -c MyClass -o "fr v *this" #显示当前源文件中定义的全局/静态变量 (lldb) target variable (lldb) ta v #显示指定的全局变量 (lldb) target variable baz (lldb) ta v baz #显示当前帧的参数和局部变量 (lldb) frame variable (lldb) fr v #显示当前帧的局部变量 (lldb) frame variable --no-args (lldb) fr v -a #显示指定的的局部变量 (lldb) frame variable bar (lldb) fr v bar (lldb) p bar #显示指定输出类型的局部变量 (lldb) frame variable --format x bar (lldb) fr v -f x bar
#### 其他语言
#执行Shell
(lldb) platform shell <cmd>
#指定断点触发时,执行相应python脚本,支持ғ"command", "python", "lua", "default-script
(lldb) breakpoint command add --script-type python 1
#指定断点触发时,执行相应调试命令
(lldb) breakpoint command add 1
# 命名断点,创建断点组`-N <breakpoint-name> ( --breakpoint-name <breakpoint-name> )`
将断点加入一个断点组
(lldb) br set -n testStepCommands -N group1
(lldb) br set -n testBreakpoints -N group1
(lldb) breakpoint disable group1
复制代码
观察点
#无需停止代码即可记录对变量所做的任何更改的方法
#监视变量的赋值操作
(lldb) watchpoint set variable global_var
(lldb) wa s v global_var
#监视某个内存区域的变化。如果未指定监视区域的大小,通过'-x byte_size',则监视区域大小为指针默认的大小
(lldb) watchpoint set expression -- &a
(lldb) wa s e -- &a
#通过条件监视
(lldb) watch set var global(lldb) watchpoint modify -c '(global==5)'
# 显示所有的监视列表
(lldb) watchpoint list
(lldb) watch l
# 删除一个监视点
(lldb) watchpoint delete 1
(lldb) watch del 1
# 指定监视点,执行设置的调试命令
(lldb) watchpoint command add 1
#禁用监视点
(lldb) watchpoint disable
复制代码
福利
分享记录就到这里了 如需iOS资料 请关注主页加入圈子免费获取