一、简介
LLDB
全称是Low Lever Debug
。
下断点快捷键
command + \
二、LLDB断点设置
2.1 设置断点
breakpoint set -n XXX
set
是子命令,-n
是选项 是--name
的缩写。
Breakpoint 2: where = 001--LLDB`test1 + 8 at ViewController.m:19, address = 0x00000001000766d8
解释:
项目中的第二个断点,即为编号。
where = 001--LLDB test1 + 8 at ViewController.m:19:断点的位置,
工程名为001--LLDB,
在 ViewController.m中的第19行,
方法名为test1,
address = 0x00000001000766d8:内存地址。
2.2 OC方法设置断点
breakpoint set -n "[控制器名称 方法名称]"
Breakpoint 1: 3 locations.
解释:
1:第一组断点
3:三个地方
2.3 查看断点列表
breakpoint list
2.4 禁用/启用断点
breakpoint disable
禁用
breakpoint enable
启用
2.4.1 禁用/启用一组
breakpoint enable 组号
2.4.2 禁用/启用某一个断点
2.5 删除断点
2.5.1 删除某组的某一个
breakpoint delete 组号
注意:可以看出它只是把它禁用了,并没有删除
2.5.2 删除某组
breakpoint delete 组号
2.5.3 删除所有组
breakpoint delete
2.6 查看指令
2.6.1 查看lldb
所有指令
help
2.6.2 查看lldb
中子指令的所有指令
help breakpoint
2.7 遍历整个项目中所有方法名为 touchesBegan:withEvent:
breakpoint set --selector touchesBegan:withEvent:
我们点击一下,可以看出第一个断点地方是系统方法,并非是我们自己写的方法
2.8 遍历特定文件中所有方法名为 touchesBegan:withEvent:
breakpoint set --file ViewController.m --selector touchesBegan:withEvent:
2.9 遍历整个项目中满足Game:这个字符的所有方法
breakpoint set -r Game:
2.10 流程控制
2.10.1 继续执行
$c(continue)
2.10.2 单步运行,将子函数当做整体一步执行
$n(next)
2.10.3 单步运行,遇到子函数会进去
$s
三、LLDB代码执行
3.1 查看子控件
expression self.view.subviews
问题1:指令
p
与expression
的关系如何呢?答案:不难看出
p
是expression
的简写形式问题2:指令
po
又是啥呢?help expression
答案:
po
其实就是调用了OC
的description
方法
3.2 p
和po
的应用
四、查看堆栈信息
4.1 查看堆栈信息
bt
(lldb) b test4
Breakpoint 1: where = 001--LLDB调试`-[ViewController test4] + 20 at ViewController.m:54:5, address = 0x000000010017e064
(lldb) c
Process 10967 resuming
2019-12-07 21:33:15.468965+0800 001--LLDB调试[10967:3499830] -[ViewController test1]
2019-12-07 21:33:15.469210+0800 001--LLDB调试[10967:3499830] -[ViewController test2]
2019-12-07 21:33:15.469313+0800 001--LLDB调试[10967:3499830] -[ViewController test3]
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x000000010017e064 001--LLDB调试`-[ViewController test4](self=0x000000010072db50, _cmd="test4") at ViewController.m:54:5
frame #1: 0x000000010017e044 001--LLDB调试`-[ViewController test3](self=0x000000010072db50, _cmd="test3") at ViewController.m:50:5
frame #2: 0x000000010017dfe8 001--LLDB调试`-[ViewController test2](self=0x000000010072db50, _cmd="test2") at ViewController.m:45:5
frame #3: 0x000000010017df8c 001--LLDB调试`-[ViewController test1](self=0x000000010072db50, _cmd="test1") at ViewController.m:41:5
frame #4: 0x000000010017e3a0 001--LLDB调试`-[ViewController touchesBegan:withEvent:](self=0x000000010072db50, _cmd="touchesBegan:withEvent:", touches=1 element, event=0x00000002839e0640) at ViewController.m:86:5
frame #5: 0x000000019053eb64 UIKitCore`forwardTouchMethod + 328
frame #6: 0x000000019053ea08 UIKitCore`-[UIResponder touchesBegan:withEvent:] + 60
frame #7: 0x000000019054caf0 UIKitCore`-[UIWindow _sendTouchesForEvent:] + 1692
frame #8: 0x000000019054e0a8 UIKitCore`-[UIWindow sendEvent:] + 3352
frame #9: 0x000000019052aae8 UIKitCore`-[UIApplication sendEvent:] + 336
frame #10: 0x00000001905a223c UIKitCore`__dispatchPreprocessedEventFromEventQueue + 5880
frame #11: 0x00000001905a4798 UIKitCore`__handleEventQueueInternal + 4924
frame #12: 0x000000019059d60c UIKitCore`__handleHIDEventFetcherDrain + 108
frame #13: 0x000000018c4827e0 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
frame #14: 0x000000018c482738 CoreFoundation`__CFRunLoopDoSource0 + 80
frame #15: 0x000000018c481ed0 CoreFoundation`__CFRunLoopDoSources0 + 180
frame #16: 0x000000018c47d01c CoreFoundation`__CFRunLoopRun + 1080
frame #17: 0x000000018c47c8bc CoreFoundation`CFRunLoopRunSpecific + 464
frame #18: 0x00000001962e8328 GraphicsServices`GSEventRunModal + 104
frame #19: 0x00000001905126d4 UIKitCore`UIApplicationMain + 1936
frame #20: 0x000000010017e4d0 001--LLDB调试`main(argc=1, argv=0x000000016fc878a8) at main.m:14:16
frame #21: 0x000000018c307460 libdyld.dylib`start + 4
(lldb)
4.2 查看上下方法
4.2.1 断点断住test3
方法,这里的frame #0
是方法编号,之后会用到。
4.2.2 up
上一个方法
4.2.3 down
下一个方法
4.2.4 frame select 编号
直接跳转到某个方法
4.2.5 frame variable
打印方法参数
4.2.6 thread return
代码回滚,回到上一个方法
四、内存断点
4.1 给属性增加断点
watchpoint set variable p1->_name
给p1
对象的name
属性下断点
4.2 通过内存地址设置
watchpoint set expression 内存地址
五、其他指令
5.1 在断点时设置一些默认指令
break command add 组号
5.2 每次stop
时执行一些命令
注意:只对breadpoint,watchpoint
target stop-hook add -o "frame variable"
5.2.1 查看当前所有的stop-hook
target stop-hook list
5.2.2 删除某一组的hook
undisplay 组号
5.3 image
5.3.1 数组越界错误定位到函数
image lookup -a 0x1bd10580c
5.3.2 快速查看某个类
image lookup -t 类名