158 – LLDB实用 – 其它指令及应用

26. 六月 2019 iOS 0

这篇文章是LLDB实用的第三篇文章,前两篇是164165,分别记录了breakpoint和watchpoint两兄弟的使用和一些特性。
这篇文章会记录LLDB的其它一些常用指令,有frame、thread、image、memory、register。

还会有一些组合使用的方法(持续更新)。

常用指令

frame

栈帧指令。我们使用这个来查看和选择(位于当前断点的)栈帧。

  1. frame info ,展示当前线程的当前栈帧
  2. frame select ,选择当前线程的某一帧
  3. frame variable ,当前帧的变量有哪些

thread

线程指令。可以用来进行线程控制

  1. thread backtrace ,AKA “bt”,展示所有调用栈,配合frame可以看到不同的线程里的栈帧
  2. thread continue ,继续执行
  3. thread jump ,跳过这一行执行,170文章中有具体介绍
  4. thread step-in ,源码级别的下一个调用,停在调用开始
  5. thread step-out ,结束当前的调用栈
  6. thread step-over , 源码级别的下一个调用,停在调用结束
  7. thread until , 直到某一行或者某一地址(方法)停止

image(target module)

  1. image lookup –address +地址 ,查找地址代表的代码(如果是方法地址,会找到调用的代码文件及行数)
  2. image lookup –name +方法名称 , 查找出所有的该方法名称所在的库及文件、地址行数
  3. image lookup -t  + 类名,查看头文件类的头文件

memory

  1. memory read ,读取地址内存数据

register

  1. register read ,读取当前的寄存器数据
  2. register write , 寄存器写入

一些使用方法:(持续更新)

  1. 符号断点在”-[NSObject doesNotRecognizeSelector:]”,捕捉未实现的方法调用崩溃,配合‘bt’,查看调用栈
    breakpoint set --selector doesNotRecognizeSelector:设置断点(或者使用Xcode断点添加)
  2. 悬垂指针(野指针)的生成调用栈查看
    一般来说,通过“bt”指令,可以看到最后的调用栈。
    如果没有看到,我们可以通过开启scheme中的Diagnostic -> Zombie Objects来获取野指针地址。
    然后,使用LLDB进行调试:
    command script import lldb.macosx.heap指令,加入额外的指令"malloc_info", "ptr_refs", "cstr_refs", "find_variable", and "objc_refs"
    最后可以通过指令malloc_info --stack-history 野指针地址可以看到这个地址的malloc的调用栈历史,我们关心最后一次在我们程序中出现的调用栈就行。
    如果需要查询代码文件,使用image lookup --address
  3. 查看寄存器中的值
    我们可以通过register read看到当前寄存器的值
    通过frame select我们选择想要观察的栈帧,可以看到具体的寄存器里存储的 消息参数
  4. 查看objc的消息及参数
    理解消息转发机制,可以知道所有的方法调用全部会转化为objc_msgSend
    而且第一个参数是receiver(消息的发送者),第二个参数是调用的方法(SEL),第三个及以后的参数是原本方法中的形参。
    我们可以通过LLDB打印出当前帧的消息:
    po (NSObject *)$arg1 —-> 发送者
    po (SEL)$arg2 —-> 消息
    po $arg3 —-> 消息的形参
  5. 代码注入
    LLDB代码注入, 使用 expression 命令更改变量的值即可