lldb是llvm的一个子项目,用于调试llvm编译的程序,做iOS调试时,和lldb
打交道应该是最多的,本文对lldb常用的一些命令做一些整理,以便后续查阅
lldb常用操作
lldb的指令格式
1 | <command> [<subcommand> [<subcommand>...]] <action> [-options [optionvalue]] [argument [argument...]] |
- 命令
- 子命令
- 命令操作
- 命令选项
- 命令参数
例如给函数test设置短点
1 | (lldb) breakpoint set -n test |
我们常用的命令有
- expression:表达式
- thread:线程
- frame:
- breakpoint:符号断点
- watchpoint:内存断点
- image:镜像
- register:寄存器
- memory:内存
- help:查看命令帮助
所有命令可以通过help <command> [<subcommand>]
查看详细文档
1 | (lldb) help breakpoint |
expression
expression
命令是执行一个表达式,并将表达式返回的结果输出
调用方法
expression
1
2
3(lldb) expression self.view.hidden = 1
(lldb) expression [self.view layoutIfNeeded]添加一个本地变量
expression
1
2
3
4# 命名以$开头
(lldb) expression int $a = 10
(lldb) p $a
(int) $a = 1我们可以通过添加本地变量实现页面跳转
1
2
3
4
5
6
7
8# 定义变量并赋值
(lldb) expression id $navVC = self.navigationController;
# 定义变量
(lldb) expression id $vc
# 创建vc
(lldb) expression $vc = [[ViewController alloc] init];
# push跳转
(lldb) expression [$navVC pushViewController:$vc animated:YES]打印变量地址
expression --
,p
1
2
3
4
5
6
7
8
9(lldb) expression button
(UIButton *) $4 = 0x00007f9d1ea05b50
# `--`表示选项结束
(lldb) expression -- button
(UIButton *) $5 = 0x00007f9d1ea05b50
(lldb) p button
(UIButton *) $6 = 0x00007f9d1ea05b50expression --
可以简写成expression
,print
,p
打印变量值
expression -o --
,po
1
2
3
4
5
6# `--` 表示选项结束,`-o`表示按对象输出
(lldb) expression -o -- button
<UIButton: 0x7f9d1ea05b50; frame = (184 433; 46 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x600003a54ba0>>
(lldb) po button
<UIButton: 0x7f9d1ea05b50; frame = (184 433; 46 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x600003a54ba0>>expression -o --
可以简写成po
,实际是调用对象的description
方法,输出返回值
thread
打印调用堆栈信息
thread backtrace
,bt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = step over
* frame #0: 0x00000001087d1bbf Test`-[ViewController viewDidLoad](self=0x00007fba7cc0ce10, _cmd="viewDidLoad") at ViewController.m:101:1
frame #1: 0x00007fff4856c066 UIKitCore`-[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] + 83
frame #2: 0x00007fff48570f84 UIKitCore`-[UIViewController loadViewIfRequired] + 1084
frame #3: 0x00007fff485713a1 UIKitCore`-[UIViewController view] + 27
frame #4: 0x00007fff48c51ae1 UIKitCore`-[UIWindow addRootViewControllerViewIfPossible] + 326
frame #5: 0x00007fff48c5110a UIKitCore`-[UIWindow _updateLayerOrderingAndSetLayerHidden:actionBlock:] + 219
frame #6: 0x00007fff48c52195 UIKitCore`-[UIWindow _setHidden:forced:] + 362
frame #7: 0x00007fff48c655bc UIKitCore`-[UIWindow _mainQueue_makeKeyAndVisible] + 42
frame #8: 0x00007fff48e84d2c UIKitCore`-[UIWindowScene _makeKeyAndVisibleIfNeeded] + 202
frame #9: 0x00007fff48177720 UIKitCore`+[UIScene _sceneForFBSScene:create:withSession:connectionOptions:] + 1405
frame #10: 0x00007fff48c15561 UIKitCore`-[UIApplication _connectUISceneFromFBSScene:transitionContext:] + 1019
frame #11: 0x00007fff48c15898 UIKitCore`-[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 291
frame #12: 0x00007fff4876a160 UIKitCore`-[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 361
frame #13: 0x00007fff36c6091e FrontBoardServices`-[FBSSceneImpl _callOutQueue_agent_didCreateWithTransitionContext:completion:] + 419
frame #14: 0x00007fff36c869b1 FrontBoardServices`__86-[FBSWorkspaceScenesClient sceneID:createWithParameters:transitionContext:completion:]_block_invoke.154 + 102
frame #15: 0x00007fff36c6b347 FrontBoardServices`-[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 220
frame #16: 0x00007fff36c86642 FrontBoardServices`__86-[FBSWorkspaceScenesClient sceneID:createWithParameters:transitionContext:completion:]_block_invoke + 355
frame #17: 0x0000000108a81e8e libdispatch.dylib`_dispatch_client_callout + 8
frame #18: 0x0000000108a84da2 libdispatch.dylib`_dispatch_block_invoke_direct + 300
frame #19: 0x00007fff36cac2d9 FrontBoardServices`__FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
frame #20: 0x00007fff36cabfc7 FrontBoardServices`-[FBSSerialQueue _queue_performNextIfPossible] + 441
frame #21: 0x00007fff36cac4d6 FrontBoardServices`-[FBSSerialQueue _performNextFromRunLoopSource] + 22
frame #22: 0x00007fff23da1c71 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
frame #23: 0x00007fff23da1b9c CoreFoundation`__CFRunLoopDoSource0 + 76
frame #24: 0x00007fff23da13cc CoreFoundation`__CFRunLoopDoSources0 + 268
frame #25: 0x00007fff23d9bf6e CoreFoundation`__CFRunLoopRun + 974
frame #26: 0x00007fff23d9b884 CoreFoundation`CFRunLoopRunSpecific + 404
frame #27: 0x00007fff38b5ac1a GraphicsServices`GSEventRunModal + 139
frame #28: 0x00007fff48c19220 UIKitCore`UIApplicationMain + 1605
frame #29: 0x00000001087d2072 Test`main(argc=1, argv=0x00007ffee742dd98) at main.m:18:12
frame #30: 0x00007fff519b910d libdyld.dylib`start + 1
frame #31: 0x00007fff519b910d libdyld.dylib`start + 1frame variable [value]
打印当前调用栈的变量1
2
3
4
5
6
7
8
9- (int)a:(NSSet *)a b:(NSString *)b c:(long)c d:(int)d e:(int)e {
NSString *f = @"v";
NSUInteger g = f.length;
g += 1;
return 10;
}
// 调用
[self a:nil b:@"fdd" c:1231 d:2123 e:23];在函数里面查看
1
2
3
4
5
6
7
8
9
10(lldb) frame variable
(ViewController *) self = 0x00007ffe4f4090b0
(SEL) _cmd = "a:b:c:d:e:"
(NSSet *) a = nil
(__NSCFConstantString *) b = 0x0000000101b41088 @"fdd"
(long) c = 1231
(int) d = 2123
(int) e = 23
(__NSCFConstantString *) f = 0x0000000101b410a8 @"v"
(NSUInteger) g = 2流程控制
thread continue̵
/continue̵
/c
: 程序继续运行thread step-over
/next
/n
:单步运行(源码),不会进入子函数thread step-in
/step
/s
: 单步运行(源码),会进入子函数thread step-out
/finish
: 直接执行完当前函数的所有代码,返回到调用的地方thread return [value]
/thread r
:让当前函数直接返回,不执行当前断点后面代码thread step-inst-over
/nexti
/ni
:单步运行(汇编),不会进入子函数thread step-inst
/stepi
/si
:单步运行(汇编),会进入子函数
前面四个对应Xcode工具栏的前四个
调用栈回退和前进
up
/down
breakpoint
设置断点
breakpoint set
breakpoint set -a 函数地址
breakpoint set -n 函数符号
1
2
3
4
5
6(lldb) breakpoint set -a 0x0000000101b3eab3
Breakpoint 6: where = Test`-[ViewController viewDidLoad] + 147 at ViewController.m:101:5, address = 0x0000000101b3eab3
(lldb) breakpoint set -n "-[ViewController viewDidLoad]"
(lldb) breakpoint set -n touchesBegan:withEvent:列出所有的断点:
breakpoint list
1
2
3
4
5
6
7
8
9
10
11
12
13(lldb) breakpoint list
Current breakpoints:
1: file = '/Users/bomo/Desktop/Test/Test/ViewController.m', line = 116, exact_match = 0, locations = 1, resolved = 1, hit count = 0
1.1: where = Test`-[ViewController test:] + 60 at ViewController.m:116:21, address = 0x0000000101b3ebec, resolved, hit count = 0
2: file = '/Users/bomo/Desktop/Test/Test/ViewController.m', line = 114, exact_match = 0, locations = 1, resolved = 1, hit count = 0
2.1: where = Test`-[ViewController test:] + 36 at ViewController.m:114:21, address = 0x0000000101b3ebd4, resolved, hit count = 0
3: file = '/Users/bomo/Desktop/Test/Test/ViewController.m', line = 109, exact_match = 0, locations = 1, resolved = 1, hit count = 1
3.1: where = Test`-[ViewController a:b:c:d:e:] + 162 at ViewController.m:110:1, address = 0x0000000101b3eb72, resolved, hit count = 1
4: address = 0x00000001007f1cac, locations = 1
4.1: address = 0x00000001007f1cac, unresolved, hit count = 0上面有4个断点,每个断点都有一个整数编号
设置断点状态
breakpoint disable 断点编号
: 禁用断点breakpoint enable 断点编号
: 启用断点breakpoint delete 断点编号
: 删除断点
断点命令:
breakpoint command add 断点编号
: 给断点预先设置需要执行的命令,当触发断点时候,就会执行breakpoint command list 断点编号
: 列出断点的绑定的命令breakpoint command delete 断点编号
: 删除断点绑定的命令1
2
3
4
5
6(lldb) breakpoint command add 1
Enter your debugger command(s). Type 'DONE' to end.
> print "断点命中了"
> print "断点参数为"
> po sender
> DONE当断点命中的时候时候
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21print "断点命中了"
(const char [16]) $0 = "断点命中了"
print "断点参数为"
(const char [16]) $1 = "断点参数为"
po sender
<UIButton: 0x7fa86f80bf10; frame = (184 433; 46 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x600001826580>>
# 查看断点的命令
(lldb) breakpoint command list 1
1: file = '/Users/bomo/Desktop/Test/Test/ViewController.m', line = 105, exact_match = 0, locations = 1, resolved = 1, hit count = 4
Breakpoint commands:
print "断点命中了"
print "断点参数为"
po sender
1.1: where = Test`-[ViewController test:] + 36 at ViewController.m:105:20, address = 0x000000010375ed24, resolved, hit count = 4
# 删除断点的命令
(lldb) breakpoint command delete 1
内存断点
内存断点与符号断点用法类似
watchpoint set variable 变量
1
(lldb) watchpoint set variable self->age
watchpoint set expression 地址
1
(lldb) watchpoint set expression 0x0000000101b3eab3
watchpoint list
watchpoint diable 断点编号
watchpoint enable 断点编号
watchpoint delete 断点编号
watchpoint command add 断点编号
watchpoint command list 断点编号
watchpoint command delete 断点编号
image
列出所加载的模块信息
image list -o -f
1
2
3
4
5
6
7(lldb) image list -o -f
[ 0] 0x000000000375d000 /Users/bomo/Library/Developer/Xcode/DerivedData/Test-frsrzegtqyfuthfhcjefdlbaqmgi/Build/Products/Debug-iphonesimulator/Test.app/Test
[ 1] 0x0000000108ca5000 /usr/lib/dyld
[ 2] 0x000000010376c000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/dyld_sim
[ 3] 0x00000001039c7000 /Users/bomo/Library/Developer/Xcode/DerivedData/Test-frsrzegtqyfuthfhcjefdlbaqmgi/Build/Products/Debug-iphonesimulator/Test.app/Frameworks/AppOrderFiles.framework/AppOrderFiles
[ 4] 0x00007fff2587b000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/Foundation.framework/Foundation
...可以使用
grep
过滤1
2
3
4
5(lldb) image list -o -f Test
[ 0] /Users/bomo/Library/Developer/Xcode/DerivedData/Test-frsrzegtqyfuthfhcjefdlbaqmgi/Build/Products/Debug-iphoneos/Test.app/Test 0x0000000004a2c000
(lldb) image list -o -f | grep Test
[ 0] /Users/bomo/Library/Developer/Xcode/DerivedData/Test-frsrzegtqyfuthfhcjefdlbaqmgi/Build/Products/Debug-iphoneos/Test.app/Test 0x0000000004a2c000可以使用
image list
命令查看ASLR偏移地址
,上面表示Test文件的偏移地址为0x0000000004a2c000
,MachO的TEXT段的偏移地址为0x0000000104a2c000
(ASLR+PAGEZERO)查找模块
image lookup
image lookup -t 类型
image lookup -a 地址
image lookup -n 符号
1
2
3
4
5
6
7
8
9
10
11
12
13(lldb) image lookup -t AppDelegate
Best match found in /Users/bomo/Library/Developer/Xcode/DerivedData/Test-frsrzegtqyfuthfhcjefdlbaqmgi/Build/Products/Debug-iphonesimulator/Test.app/Test:
id = {0x20000002b}, name = "AppDelegate", byte-size = 8, decl = AppDelegate.h:11, compiler_type = "@interface AppDelegate : UIResponder
@end"
(lldb) image lookup -n test:
1 match found in /Users/bomo/Library/Developer/Xcode/DerivedData/Test-frsrzegtqyfuthfhcjefdlbaqmgi/Build/Products/Debug-iphonesimulator/Test.app/Test:
Address: Test[0x0000000100001d00] (Test.__TEXT.__text + 688)
Summary: Test`-[ViewController test:] at ViewController.m:103
(lldb) image lookup -a 0x000000010375ed24
Address: Test[0x0000000100001d24] (Test.__TEXT.__text + 724)
Summary: Test`-[ViewController test:] + 36 at ViewController.m:105:20其中
image lookup -a 地址
经常用于查询崩溃位置,通过地址查询崩溃的地方位于哪个模块哪个文件哪个位置
register
register
指令能够获取和修改各个寄存器的信息
读取所有寄存器信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36(lldb) register read
General Purpose Registers:
x0 = 0x0000000000000000
x1 = 0x00000001bcf641e4
x2 = 0x000000010536d050
x3 = 0x000000028283b840
x4 = 0x000000028283b840
x5 = 0x000000028283b840
x6 = 0x0000000000000000
x7 = 0x0000000000000403
x8 = 0x0000000104dd1568 (void *)0x0000000104dd15b8: ABC
x9 = 0x0000000000000006
x10 = 0x0000000000000008
x11 = 0x0000000000000000
x12 = 0x000000010a811840
x13 = 0x000005a1ce8843c7 (0x00000001ce8843c7) (void *)0x000001ce88448800
x14 = 0x00000001bd054dde
x15 = 0x0000000104dd0220 (void *)0x00000001bd054dde
x16 = 0x00000001818daa90 libobjc.A.dylib`objc_release
x17 = 0x0000000186100418 UIKitCore`-[UIView(UIKitManual) retain]
x18 = 0x0000000000000000
x19 = 0x000000028283b840
x20 = 0x000000010536d050
x21 = 0x00000001be56b4fe
x22 = 0x0000000106c04bd0
x23 = 0x0000000000000001
x24 = 0x00000001ce893fe8 UIKitCore`UIApp
x25 = 0x0000000000000000
x26 = 0x00000001bcf656b4
x27 = 0x0000000106c04bd0
x28 = 0x00000002813adfe0
fp = 0x000000016b039390
lr = 0x0000000104dc9d1c Test`-[ViewController test:] + 40 at ViewController.m:104
sp = 0x000000016b039340
pc = 0x0000000104dc9d24 Test`-[ViewController test:] + 48 at ViewController.m:106:20
cpsr = 0x00000000
register read/格式 寄存器名称
1
2# 读取寄存器x0的值
registe read $x0register write 寄存器名称 数值
1
registe write $x1 10
查看内存
memory read/数量+格式+字节数 内存地址
格式:x
为16进制,f
位浮点数,d
为10进制
字节数:b
为1个字节,h
为2个字节,w
为4个字节,g
为8个字节
1 | (lldb) memory read 0x00006000001600b0 |
也可以直接使用x
查看内存,用法和memory read
一样
1 | (lldb) x/4xg 0x00006000001600b0 |
写内存
1 | memory write 内存地址 述职 |
缩写
lldb大部分命令都支持缩写
命令 | 缩写 |
---|---|
expression | exp |
thread backtrace | bt |
breakpoint list | br l |
process continue | continue , c |
thread step-over | next , n |
thread step-in | step , s |
thread step-out | finish , f |
thread step-inst-over | nexti , ni |
thread step-inst | stepi , si |