LLDB是我们开发中都会使用到的调试工具,我们今天来总结一下常见的用法以及一些好用的LLDB插件。
LLDB
断点
断点是LLDB中最常用的功能了,平时都是在代码中手动设置断点,今天通过LLDB来添加断点。
当程序在运行过程中,我们可以点击暂停或者view debug是程序进入到LLDB状态,这时我们就可以进行LLDB调试。
添加断点
br set -n test1 //给函数添加断点, br是breakpoint的简写
br set -n '-[ViewController test:]' //OC方法添加断点
br set -r swwtest //整个项目中,方法名字包含swwtest的都添加断点
br set --selector test: //整个项目中,test:的方法添加断点,无论对象方法还是类方法
br set --file ViewController.m --selector test: //在某个文件中添加断点
复制代码
查看所有断点
br list
复制代码
禁用/启用断点
br disable 1 //可以禁用一组,也可以某一个,比如,1.2
br enable 1 //启用
复制代码
删除断点
br delete 1 //只能删除1组断点,不能删除某一个
复制代码
代码执行
expression
或者它的简写p
是执行后面代码的指令。在调试的过程中,我们可以用来修改某个值,使程序进入不同的流程。
流程控制
$continue/c 继续
$next/n 单步执行
$s 单步执行,遇到子函数会进去
复制代码
$thread return 本函数中不往下执行,直接返回
复制代码
thread return
可以用来绕过函数执行,例如在- (void)test
中加上断点,使用thread return
可以不执行里面代码,继续向下执行。
查看堆栈
$bt 查看堆栈信息
$frame variable 查看参数
$up 切换当前frame, 向上
$down 向下
复制代码
内存断点
br -a 0x123456 设置内存断点,这个地址如果是方法,那么进入方法的时候就会进入断点
复制代码
有时候我们需要监听某个值的变化,可以使用内存断点,原理类似于OC的KVO。当值发生变化时,就会触发断点,并且可以查看新值和旧值。
$watchpoint set variable p1->_name 给p1对象的name属性添加断点。
复制代码
$watchpoint set expression 0x0000000283b81bd0 给这块内存添加断点,监听内存中值当变化。
复制代码
stop-hook
给整个程序下一个断点指令,当程序被断住时,会触发我们下的命令。
target stop-hook add -o "frame variable" 当程序进入断点时,就会执行frame variable指令
复制代码
target stop-hook list 查看所有stop-hook
target stop-hook delete 1 删除1组
复制代码
.lldbinit
在用户文件夹下cd ~
,有一个.lldbinit的隐藏文件(没有就创建一个),这个文件是每次lldb启动时,都会加载这个文件,我们可以在这个文件中添加指令,一劳永逸。
chisel
chisel是facebook开发的lldb插件,地址是chisel,今天我们看看常用的方法。
pvc 打印所有控制器
pviews 打印所有view
pviews 0x1234321 打印这个view的子view
pclass 0x100b06370 打印这个类的继承链
pmethods 0x100b06370 打印这个类包含的方法
复制代码
简单的写了一个页面,使用chisel来找到页面中的控价
(lldb) pviews
<UIWindow: 0x100b0cf20; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x2823ae130>; layer = <UIWindowLayer: 0x282dd13c0>>
| <UIView: 0x100b13920; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x282dd29a0>>
| | <UIButton: 0x100b0dbb0; frame = (87.5 169; 200 60); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x282dd1a40>>
| | | <UIButtonLabel: 0x100a14df0; frame = (73 19.5; 54 21.5); text = 'Button'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280ed4690>>
| | <UIButton: 0x100b115c0; frame = (87.5 249; 200 60); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x282dd22e0>>
| | | <UIButtonLabel: 0x100a14af0; frame = (73 19.5; 54 21.5); text = 'Button'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280ed9900>>
| | <UITextField: 0x101830200; frame = (87.5 328.5; 200 30); text = ''; opaque = NO; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x2823aebe0>; layer = <CALayer: 0x282dd2440>>
| | | <_UITextFieldRoundedRectBackgroundViewNeue: 0x100b12db0; frame = (0 0; 200 30); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x282dd26e0>>
| | | <_UITextFieldContentView: 0x100b12690; frame = (7 2; 186 26); opaque = NO; userInteractionEnabled = NO; layer = <__UITextTiledLayer: 0x2809c5c80>>
| | | | <__UITileLayer: 0x282385d70> (layer)
(lldb) pviews 0x100b13920
<UIView: 0x100b13920; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x282dd29a0>>
| <UIButton: 0x100b0dbb0; frame = (87.5 169; 200 60); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x282dd1a40>>
| | <UIButtonLabel: 0x100a14df0; frame = (73 19.5; 54 21.5); text = 'Button'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280ed4690>>
| <UIButton: 0x100b115c0; frame = (87.5 249; 200 60); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x282dd22e0>>
| | <UIButtonLabel: 0x100a14af0; frame = (73 19.5; 54 21.5); text = 'Button'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x280ed9900>>
| <UITextField: 0x101830200; frame = (87.5 328.5; 200 30); text = ''; opaque = NO; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x2823aebe0>; layer = <CALayer: 0x282dd2440>>
| | <_UITextFieldRoundedRectBackgroundViewNeue: 0x100b12db0; frame = (0 0; 200 30); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x282dd26e0>>
| | <_UITextFieldContentView: 0x100b12690; frame = (7 2; 186 26); opaque = NO; userInteractionEnabled = NO; layer = <__UITextTiledLayer: 0x2809c5c80>>
| | | <__UITileLayer: 0x282385d70> (layer)
(lldb) pvc
<ViewController 0x100b06370>, state: appeared, view: <UIView 0x100b13920>
(lldb) pclass 0x100b06370
ViewController
| UIViewController
| | UIResponder
| | | NSObject
(lldb) pmethods 0x100b06370
Class Methods:
+ (void)load
Instance Methods:
- (id)btn1
- (id)btn2
- (id)tf
- (void)btn2Click:(id)arg0
- (id)matchString:(id)arg0 toRegexString:(id)arg1
- (void)swwTest1
- (void)swwTest2
- (void)swwTest3
- (void)swwTest4
- (void)setBtn1:(id)arg0
- (void)setBtn2:(id)arg0
- (void)setTf:(id)arg0
- (void)setT:(id)arg0
- (id)t
- (void).cxx_destruct
- (void)touchesBegan:(id)arg0 withEvent:(id)arg1
- (void)viewDidLoad
- (id)manager
- (void)setManager:(id)arg0
(lldb) pinternals 0x100b06370
(ViewController) $24 = {
UIViewController = {
UIResponder = {
NSObject = {
isa = ViewController
}
}
}
_btn1 = 0x0000000100b0dbb0
_btn2 = 0x0000000100b115c0
_tf = 0x0000000101830200
_t = nil
_manager = nil
}
(lldb)
复制代码
找到所属的控制器和控件
fvc -v 0x0000000100b0dbb0 找到一个空间所属控制器
fv UIButton 通过类名找控件
复制代码
找到对应的控件
flicker 0x139e0aca0 使这个控件闪烁一下
vs 0x139e0aca0 定位到这个控件,并可以调试其关联的控件
复制代码
DSLLDB
把DSLLDB下载到本地,我把文件放在了/opt文件夹下了,然后配置.lldbinit文件command script import /opt/LLDB/lldb_commands/dslldb.py
当app被脱去符号,只用bt不能看到方法名字了,DSLLDB
可以使用sbt
,把脱去的符号恢复
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END