[TOC]
MachO文件结构
单个架构的mach-O文件包含:
MachO Header
、Load Commands
、Data
。而通用Mach-O文件会在文件开始会多一个
Fat Header
的区域。
查看的Mach-O文件结构
- 指令:
$ otool -f WeChat
- MachOView工具,可以详细查看各种常量、类名、方法名等;
- 红苹果,黑苹果,
LLDB
LLDB:Low Lever Debug
在没有源代码的情况下,通过LLDB控制台进行断点下设置;
通过LLDB的Pause按钮暂停住程序,进行调试,设置断点;
在LLDB环境中使用
help
查看指令帮助,可以一级一级向下查找对应的子命令选项的意思;
代码断点
使用LLDB中breakpoint指令
相当于进行HOOK
通过指令设置断点时,页面也会显示断点当前状态;
-
根据函数名设置断点:
$breakpoint set -n test1
;set: 子命令;
-n: 选项,
--name
的简写;设置成功后会给断点设置分组,第几组第几个断点。
-
OC方法设置断点:
$breakpoint set -n "-[ViewController save:]" -n "-[ViewController continueGame:]" -n "-[ViewController pauseGame:]"
,同时设置多个OC方法;设置成功后,lldb提示
Breakpoint 1: 3 locations
。意思一组中有3个断点; 查看断点列表:
breakpoint list
。展示断点分组和排序情况详情,包括,断点所在分组、组内序号、文件、行号、方法/函数名、当前状态等;-
启用/禁用断点:
$breakpoint enable 1
,启用第一组所有;$breakpoint disable 1.1
,禁用第一组第一个断点;
-
删除断点:
$breakpoint delete 1
,删除第一组断点,成功后提示1 breakpoints deleted; 0 breakpoint locations disabled
。在使用删除时,如果编号写成1.1
则只会对1.1
的 进行禁用,并不会真正的删除掉。要删除需要对整个分组进行删除。-
$breakpoint delete
:删除所有断点分组;
-
查看帮助
help breakpoint
;根据方法名模糊设置:
$breakpoint set --selector touchesBegan:withEvent:
,所有相同方法都设置,包括对系统的方法进行设置。
-
$breakpoint set --file ViewController.m --selector touchesBegan:withEvent:
针对某个文件的某个方法设置,主要用于我自己工程中。
遍历整个项目中满足
Game:
这个字符的所有方法:$breakpoint set -r Game:
。简写:
break dis 1.1 :禁用
、break en 1.1 :启用
、break list :列表
进一步简写:
b set -n XX
或b XX
或b -[X X]
;
执行代码
编写执行代码进行动态调试等;
使用expression指令
demo: expression self.view.subviews
通过help expression
查看expression帮助,可知p
:expression的简写,并非print的简写;po中的o:object_descript;
所有在lldb环境中,p紧跟需要执行的代码,eg:p self.view.backgroundColor = [UIColor redColor]
- 调试改变参数,和创建调试环境;
- 使用$2时,需要在取出该对象时进行强转成指定类型变量
p (Person *)[self.models lastObject]
; - 在LLDB环境中换行编写多行代码时使用
control + enter
;
查看堆栈信息
调试寄存器
设置断点可以查看堆栈信息,代码调用顺序
bt:thread backtrace
查看当前断点处的方法调用栈;
up:查看上一条堆栈调用信息;
down:查看上一条堆栈调用信息;
frame select 3:跳转到指定编号的堆栈记录处;
frame variable:查看当前栈处的参数信息
修改内存数据:使用frame variable
查看到数据后,直接进行修改;
thread return:返回上一条记录处,后面的代码被返回后的数据不再进行执行;
流程控制:分源代码级别和汇编级别n/ni、n/s等;
内存断点
对属性、内存地址进行下断点
-
为对象属性设置断点:
$watchpoint set variable p1->_name
:为p1对象的name成员变量设置断点;当属性值发生变化时进入断点:
Watchpoint 1 hit:
old value: 0x0000000105f1b118
new value: 0x0000000105f1b178
- 为内存地址设断点:
$watchpoint set expression 0x1c40dec1cb
;需要找到具体对象的地址,如0x1c40dec1cb 是p1->_name 的地址。
其他指令
断点行为
为单个断点添加行为
-
为断点添加行为:
$ breakpoint command add 1 // 为第一组第一条添加行为 Enter your debugger command(s). Type 'DONE' to end. > po self.view > p self > DONE
查看断点行为:
$breakpoint command list 1
删除行为:
$breakpoint command delete 1
stop-hook
在每次pause时去执行一些指定的命令,只对breakpoint、watchpoint两种pause生效,其他xcode界面(pause、viewHierarchy)操作造成的pause不生效。
-
设置stop-hook
- 添加一行:
$target stop-hook add -o "frame variable"
,-o
表示一 行; - 添加一段
target stop-hook add 1 Enter your stop hook command(s). Type 'DONE' to end. > po self > frame variable > DONE Stop hook #3 added.
- 删除指定stop-hook:
$undisplay 1
,不能删除所有; - 删除所有:
$target stop-hook delete
;
- 添加一行:
-
配置.lldbinit
在lldb每次启动时都会加载.lldbinit文件。可以在里面配置一些执行的指令,但是该文件主要用于导入一些配置文件;
image
在无源码或真机调试时,无法查看到具体的崩溃处,此时使用image查看堆栈信息,查找崩溃位置
'image' is an abbreviation for 'target modules'
相当于Windows的镜像
- -a:
$image lookup -a image lookup -a 0x1000823c4
,通过该指令逐一查看栈地址即可找到问题代码; - -t:
$image lookup -a image lookup -t Person
:快速查看指定类,可以拿到指定类的头文件。 - image list:查看当前加载链接了的库、查看内存地址(真是物理地址);
常用LLDB指令
- image list
- p
- b -[xxx xxx]
- x
- register read
- po