LLDB调试相关

2020-10-12  本文已影响0人  a_只羊

平时开发过程中,需要在运行的时候对运行时候的函数的执行、一些对象或者变量的执行情况进行相关的内容调试,在XCode中可以通过打断点来进行调试以及相关信息的查看,而XCode断点调试的本质是通过LLDB来实现的,LLDB是什么?存在于什么地方?除了通过XCode进行调试还有其他的方法吗?这是我对于LLDB所产生的一些疑问。

LLDB全称是Low Level Debugger,它是存在于Mac下的一个调试工具,在XCode进行断点动态调试的时候,LLDB通过向iOS的debugserver发送调试指令,进而达到动态断点调试的目的。既然LLDB存在于Mac中,所以我们不仅仅可以通过XCode进行动态调试,实质上我们只要有LLDB环境,就可以进行动态调试了。所以除了使用XCode进行相关的内容调试,也可以使用终端来进行相关调试工作。

lldb动态调试过程

由于XCode提供了一系列的可视化断点操作调试,所以通常很少使用到LLDB的指令,使用最多的可能就是po/p指令了。然而XCode图形界面所能操控的调试功能毕竟有限,而且有些情况下不太适合工作流式的调试工作,况且最终是通过LLDB进行命令调试,所以决定还是自学一下LLDB的相关的一些指令,以便在以后的调试过程中提升工作效率。

常见的LLDB的指令

breakpoint set -n test
#查询指令用法 
help <command-name>
#demo 
help breakpoint

expression指令可以执行一些我们在调试过程中想要加入的一些代码,比如在一次Debug中,当前断点时候的变量值刚好是我们需要的一些测试值,此时想要通过加入代码来查看相关的执行情况,就可以通过expression来进行代码的添加。

注:
expression、expression --p、print和call的效果一样
expression -o --po效果一样
执行一个表达式,下面的--是命令选项结束符号标志,如果没有命令选项,--可以省略

expression <cmd-option>--<expr>
#demo 
expression self.view.backgroundColor = [UIColor redColor]
#输出view的相关信息内容 
expression -o -- self.view 
#p的使用,同样是进行相关的表达式的执行以及相关对象信息的输出等 
p <expr> 
#demo 
p self.view.backgroundColor = [UIColor redColor]

总结来说,后续调试的时候可以统一使用p指令(可以当成expression的简称),po指令用于打印对象信息。

线程函数调用堆栈信息可以使用thread backtrace来进行输出,在打印出来的结果有一个关键字叫做frame(栈桢),一个栈桢默认存储一个函数。

注:
如果执行到某个代码想让其立即返回,可以使用thread return进行返回,这样能够直接略去后续的代码执行

#thread backtrace 
可以用于线程打印堆栈信息内容,和指令bt的效果一样,bt可以当成其缩写
#demo 
thread backtrace 
#可以使用frame命令进行栈桢内的变量内容输出
frame variable
线程堆栈打印
thread continue、continue、c :程序继续执行
thread step-over、 next、n:单步执行、把子函数当成整体一步执行完成
thread step-in、step、s:单步执行、遇到子函数会进入子函数中
thread step-out、finish:直接执行完成当前的函数的所有代码,返回上一个函数

注:
执行finish指令的时候,如果函数体中含有其他断点,这时候依旧会略过其他断点直接执行完成函数中所有的代码,返回到调用当前函数的地方。

#使用方法与代码的单步类似
thread step-inst-over、nexti、ni
thread step-inst、stepi、si

注:该指令与上面的调试指令区别在于调试源

1. n、s是对于源码级别的单步,
2. 而加i的ni、si是汇编指令级别的单步

  1. 添加断点
breakpoint set -a 函数地址
breakpoint set -n 函数名
breakpoint set -r 正则表达式
breakpoint set -s 动态库 -n 函数名
  1. 禁用断点
breakpoint disable 断点编号
  1. 启用断点
breakpoint enable 断点编号
  1. 删除断点
breakpoint delete 断点编号
  1. 在执行到某个断点的时候进行调试指令
breakpoint command add 断点编号
#列举断点处添加的相关指令
breakpoint command list 断点编号
#添加某个控制器的方法断点 
breakpoint set -n "-[ViewController touchsBegan:withEvent:]"
#添加当前控制器的某个方法断点 
breakpoint set -n test 
#依据正则表达式进行匹配打点
breakpoint set -r touchBegan 
#动态库某个函数添加断点 
breakpoint set --shlib libate.dylib -n xxx breakpoint set --s libate.dylib -n xxx 
#执行到某个断点的时候操作一些相关的调试指令 
breakpoint set -n test 
#当前调试命令执行成功之后,会进入指令添加的输入交互 
breakpoint command add 编号

内存断点使用场景在于监控某个变量改变的时候的堆栈输出,便于你能找出当前变量修改的时候的一些过程,进而找出一些修改变量过程出现的问题,当你在进行数据调试的时候,非常实用。

触发场景:在内存改变的时候会触发当前的内存断点

#依据变量设置内存断点
1. watchpoint set variable 变量名字 
#依据变量地址设置内存断点
2. watchpoint set expression 地址 
#列举所有的内存断点
3. watchpoint list 
#禁用某个内存断点
4. watchpoint disable 断点编号 
#启用某个内存断点
5. watchpoint enable 断点编号 
#删除某个内存断点
6. watchpoint delete 断点编号 
#执行到内存断点时候进行相关的指令操作
7. watchpoint command add 断点编号 
#列举内存断点处所有的指令操作
8. watchpoint command list 断点编号 
#demo
watchpoint set variable self->_demoPoint

系统通过dyld进行程序运行的时候的image的加载,在断点可以进行相关的信息查询。这里有个操作在调试bug的时候特别好定位问题崩溃代码,比如数组越界的异常的时候,会崩溃到main函数里面,此时我们没办法定位到具体的问题代码在哪一行,所以此时的崩溃可以通过image lookup -a 地址 来进行相关的信息内容。

#列举所加载的模块信息
1. image list 
#查找某个类型的信息
2. image lookup -t 类型 
#根据内存地址查找到模块中的位置
3. image lookup -a 地址 
#查找某个符号或者函数的位置
4. image lookup -n 符号或者函数名 
#打印模块的偏移地址、全路径
5. image list -o -f 
崩溃堆栈信息 通过image命令找到崩溃具体位置
上一篇下一篇

猜你喜欢

热点阅读