Xcode 探讨之 LLDB的基本使用

来源:互联网 发布:com域名注册 万维网 编辑:程序博客网 时间:2024/05/01 16:20
阐述
在LLVM中有一段对LLDB的介绍:
  1. The LLDB project builds on libraries provided by LLVM and Clang to provide a great native debugger. It uses the Clang ASTs and expression parser, LLVM JIT, LLVM disassembler, etc so that it provides an experience that "just works". It is also blazing fast and much more memory efficient than GDB at loading symbols.
从这段话中,我们可以看出LLDV是基于LLVM和Clang库形成的,它比GDB更快更效率。

在LLDB文章中,也有一段介绍:
LLDB is a next generation, high-performance debugger. It is built as a set of reusable components which highly leverage existing libraries in the larger LLVM Project, such as the Clang expression parser and LLVM disassembler.
LLDB is the default debugger in Xcode on Mac OS X and supports debugging C, Objective-C and C++ on the desktop and iOS devices and simulator.

LLDB默认就集成中Xcode(4.3+)中,它可以在macOS桌面程序、iOS设备以及模拟器环境下调试C、Objective-C、C++代码,但如果你正在使用老一点版本的Xcode的话,那就是GDB调试器。

探讨
基础前提
LLDB基本语法格式
     <command> [<subcommand> [<subcommand>...]] <action> [-options [option-value]] [argument [argument…]]
 1.  <command>(命令)和<subcommand>(子命令):LLDB调试命令的名称。命令和子命令按层级结构来排列:一个命令对象为跟随其的子命令对象创建一个上下文,子命令又为其子命令创建一个上下文,依此类推。
 2. <action>:执行命令的操作
 3. <options>:命令选项
 4. <arguement>:命令的参数
 5. []:表示命令是可选的,可以有也可以没有.

例如 $ breakpoint set -n main 
1. command: breakpoint 表示断点命令
2. action: set 表示设置断点
3. option: -n 表示根据函数name设置断点
4. arguement: mian 表示方法名为mian

原始命令(raw命令)
LLDB支持不带命令选项<options>的原始命令(raw命令),原始命令会将命令后面的所有东西当做参数传递。不过很多原始命令也可以带命令选项,当你使用命令选项的时候,需要在命令选项后面添加 ‘--' 区分命令选项和参数。
例如 $ expression -O -- self 


'唯一匹配' 原则
LLDB的命令遵循唯一匹配原则: 假如根据前n个字母已经能唯一匹配到某个命令,则只写前n个字母等效于写下完整的命令。举个例子:


基础命令
expression 命令
expression 命令的作用是执行一个表达式,并将表达式返回的结果输出。
expression 完整语法:
expression <cmd-options> -- <expr>
1. <cmd-options>: 命令选项,一般情况下使用默认的即可,不需要特别标明。
2. --: 命令选项结束符,表示所有的命令选项已经设置完毕,如果没有命令选项,--可以省略 ,它其实就是命令选项和表达式之间的分隔符
3. <expr>: 要执行的表达式 说expression是LLDB里面最重要的命令都不为过。因为他能实现2个功能。

1   执行表达式某个表达式,在运行代码过程中,可以听过执行某个表达式来动态改变程序执行的轨迹。
    例如我们在运行过程中想把self.view的背景颜色变为红色,我们可以不必编辑代码再次Run一下,只需在合适的地方添加断点,让程序进入暂停状态,用expression修改颜色,再刷新一界面,就能看到效果。
    代码:     $ expression -- self.view.backgroundColor = [UIColor redColor]       // 改变颜色
                $ expression -- (void)[CATransaction flush]     // 刷新界面

2   将返回值输出,通过expression打印东西
     例如我们想打印 self.view
     代码:    $ expression -- self.view

p & print & call 命令
我们很少直接使用expression,毕竟有点长,更多的时候我们使用 p、print、call三个命令。这三个命令其实都是  expression -- 的别名。
1. print:  打印某个东西,可以是变量和表达式
2. p:      可以看做是print的简写
3. call:   调用某个方法。
表明上看起来不一样,实际上都是执行某个表达式,将执行的结果输出到控制台上。上述名字不同,我猜应该是习惯问题,毕竟开发者都有点懒,不愿多想...

在官方文档中我们可以看见


po 命令
Objective-C里所有的对象都是用指针表示的,所以一般打印的时候,打印出来的是对象的指针,而不是对象本身。如果我们想打印对象,需要使用命名选项 -O, 为了更方便的使用,LLDB为expression -O -- 定义了一个别名 po


thread系列命令
thread backtrace & bt
有时候我们想要了解线程堆栈信息,可以使用thread backtrace 将线程堆栈信息打印出来
thread backtrace [-c <count>] [-s <frame-index>] [-e <boolean>]
-c:设置打印堆栈的帧数(frame)
-s:设置从哪个帧(frame)开始打印
-e:是否显示额外的回溯

bt的效果与thread backtrace效果一直,可以用bt命令来代替thread backtrace。


thread return
thread return 只要勇用于调试时我们不希望让代码执行某个方法,或者想直接返回一个想要的值这样的场景
thread return [<expr>]


c & n & s & finish
在调试模式下,我们通常使用鼠标点击按钮来控制执行顺序,我们现在可以使用 c & n & s & finish 这些命令解放鼠标了。

1. c / continue / thread continue: 这三个命令效果都等同于上图中第一个按钮的。表示程序继续运行
2. n / next / thread step-over: 这三个命令效果等同于上图第二个按钮。表示单步运行
3. s / step / thread step-in: 这三个命令效果等同于上图第三个按钮。表示进入某个方法
4. finish / step-out: 这两个命令效果等同于第四个按钮。表示直接走完当前方法,返回到上层frame

thread其它命令
1. thread jump: 直接让程序跳到某一行。由于ARC下编译器实际插入了不少retain,release命令。跳过一些代码不执行很可能会造成对象内存混乱发生crash。
2. thread list: 列出所有的线程
3. thread select: 选择某个线程
4. thread until: 传入一个line的参数,让程序执行到这行的时候暂停
5. thread info: 输出当前线程的信息

frame系列
frame(帧) 代表某一时刻程序执行的状态,与游戏与电影帧的概念相似。
通过观察红色区域的调用堆栈和右侧蓝色bt命令显示的所有frame,我们发现是一一对应的,可以推测: 事件一次调用对应一个frame。


frame variable
通过frame variable命令,可以打印出当前frame所有的变量。
如果需要打印指定变量,可以给frame variable传入参数,如:
$ frame variable self->_stirng
注意: frame variable 只接受变量作为参数,不接收表达式,也就是说我们无法使用getter方法来获取属性值,只能直接使用对应的_成员变量。

frame 其它命令
frame info: 查看当前frame的信息
frame select: 选择某个frame

breakpoint 系列
breakpoint 提供了许多针对断点的功能强大的子命令。
breakpoint set
breakpoint set命令用于设置断点,配合命令选项<options>可以进行多种方式设置断点。

使用 -n 指定函数名称 ( --name <function-name> )
例如: 我们想给所有类中的viewWillAppear: 设置一个断点:


使用 -f 指定文件 ( --file <filename> )
例如: 我们只需要给ViewController.m文件中的viewDidLoad设置断点:
注意: 如果函数是写在对应类cateogory中的,那么-f 后面的文件名应该写 catogory文件。

使用 -l 指定文件指定某一行 ( --line <linenum> )
例如: 我们需要给ViewController.m文件中第23行设置断点:
注意: 此处的行数是Xcode代码区左侧的行数指示器标识的,请不要手动计数。

使用-c 设置条件断点 ( --condition <expr> )
例如: convertIntValue:方法接收一个参数,当参数value大于10的时候中断,设置断点:


使用-o设置单次断点 ( --one-shot )
例如:我们需要在convertIntValue:方法只中断一次


breakpoint command 子系列
当我们需要给断点添加一些指令,例如每次走到这个断点的时候,我们都需要打印self对象,那么只需要给这个断点添加po self命令即可。
breakpoint command add
作用就是给断点添加命令。
例如:  给上方的断点添加一个命令,可以看出上方的命令Id为2,故


-o ( --one-liner)表示增加一条命令。 2表示对id为2的断点添加命令。
如果让我们想一次性增加多条命令,可以直接使用add。

用DONE来结束代码书写,注意DONE的编写,并且多次对同一个断点添加命令,后面命令会将前面命令覆盖。

breakpoint command list
用来查看某个断点已有的命令


breakpoint command delete
用来删除某个断点已有的命令


breakpoint list 
用来查看当前已经设置的断点列表


breakpoint disable/enable
用来失效/启动某个断点


breakpoint delete
用来删除删除指令的,如果指定指令id,那么就针对这个指令,如果不加则是删除全部指令


watchpoint 系列
watchpoint与breakpoint有点相似,不过breakpoint是针对方法生效的断点,watchpoint是针对地址生效的断点。
应用场景: 想知道某个属性什么时候被篡改
watchpoint set
用于添加一个watchpoint, 只要这个地址中的内容变化了,程序就会中断。
watchpoint set variable
用来观察变变量或者属性,传入的参数是变量名,注意参数不接收方法


watchpoint set expression
用来直接观察返回方法的地址


watchpoint command 子系列
与breakpoint 类似,在watchpoint中也可以添加命令
watchpoint command add
作用就是给断点添加命令。
例如:  给上方的断点添加一个命令,可以看出上方的命令Id为3,故


-o ( --one-liner)表示增加一条命令。 3表示对id为3的断点添加命令。
如果让我们想一次性增加多条命令,可以直接使用add。

用DONE来结束代码书写,注意DONE的编写,并且多次对同一个断点添加命令,后面命令会将前面命令覆盖。

watchpoint command list
用来查看某个断点已有的命令


watchpoint command delete
用来删除某个断点已有的命令


watchpoint list 
用来查看当前已经设置的断点列表


watchpoint disable/enable
用来失效/启动某个断点


watchpoint delete
用来删除删除指令的,如果指定指令id,那么就针对这个指令,如果不加则是删除全部指令


help 命令
在LLDB中输入help可以查看所有命名的帮助问文档,如果想查询具体的指令,可以在后面跟着指令


apropos命令
根据命令中的关键字,大概搜索相关命令信息


常用的Debug快捷键
功能                                 命令
暂停/继续                         CMD + Ctrl + Y
断点失效/生效                   CMD + Y
控制台显示/隐藏                CMD + Shift + Y
光标切换到控制台              CMD + Shift + C
清空控制台                       CMD + K
Step Over                         F6
Step Into                          F7
Step Out                          F8

参考文献
- http://lldb.llvm.org/index.html  LLDB官方文档
- http://blog.csdn.net/quanqinyang/article/details/51321338
- http://blog.csdn.net/super_ZJ_iOS/article/details/71859468?locationNum=2&fps=1
- http://blog.csdn.net/u014600626/article/details/77650683