7.Mach-O&LLDB

[TOC]

MachO文件结构

  • 单个架构的mach-O文件包含:MachO HeaderLoad CommandsData

  • 而通用Mach-O文件会在文件开始会多一个Fat Header的区域。

查看的Mach-O文件结构

  1. 指令:$ otool -f WeChat
  2. MachOView工具,可以详细查看各种常量、类名、方法名等;
  3. 红苹果,黑苹果,

LLDB

LLDB:Low Lever Debug

在没有源代码的情况下,通过LLDB控制台进行断点下设置;

通过LLDB的Pause按钮暂停住程序,进行调试,设置断点;

在LLDB环境中使用help 查看指令帮助,可以一级一级向下查找对应的子命令选项的意思;

代码断点

使用LLDB中breakpoint指令

相当于进行HOOK

通过指令设置断点时,页面也会显示断点当前状态;

  1. 根据函数名设置断点:$breakpoint set -n test1

    set: 子命令;

    -n: 选项,--name的简写;

    设置成功后会给断点设置分组,第几组第几个断点。

  2. OC方法设置断点:$breakpoint set -n "-[ViewController save:]" -n "-[ViewController continueGame:]" -n "-[ViewController pauseGame:]",同时设置多个OC方法;

    设置成功后,lldb提示Breakpoint 1: 3 locations。意思一组中有3个断点;

  3. 查看断点列表:breakpoint list。展示断点分组和排序情况详情,包括,断点所在分组、组内序号、文件、行号、方法/函数名、当前状态等;

  4. 启用/禁用断点:

    • $breakpoint enable 1,启用第一组所有;

    • $breakpoint disable 1.1,禁用第一组第一个断点;

  5. 删除断点:$breakpoint delete 1,删除第一组断点,成功后提示1 breakpoints deleted; 0 breakpoint locations disabled。在使用删除时,如果编号写成1.1则只会对1.1的 进行禁用,并不会真正的删除掉。要删除需要对整个分组进行删除。

    • $breakpoint delete:删除所有断点分组;
  6. 查看帮助help breakpoint;

  7. 根据方法名模糊设置:$breakpoint set --selector touchesBegan:withEvent: ,所有相同方法都设置,包括对系统的方法进行设置。

  • $breakpoint set --file ViewController.m --selector touchesBegan:withEvent:针对某个文件的某个方法设置,主要用于我自己工程中。
  1. 遍历整个项目中满足Game:这个字符的所有方法:$breakpoint set -r Game:

  2. 简写:break dis 1.1 :禁用break en 1.1 :启用break list :列表

  3. 进一步简写:b set -n XXb XXb -[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

你可能感兴趣的:(7.Mach-O&LLDB)