做你喜欢做的事情,任何时候都不会太迟

0%

动态调试的那些事儿

对于苹果开发者而言,LLDB 是无人不知的调试工具,然而此知非彼知,相信有相当规模的开发者对 LLDB 的了解仍然停留于几个基础命令的使用,今天让我们来重新认识一下既熟悉又陌生的 LLDB,看看它那些你不曾用过的强大功能,以及如何提高我们的开发效率。

一、什么叫动态调试

将程序运行起来,通过下断点、打印等⽅方式,查看参数、返回值、函数调⽤用流程等

二、Xcode 的动态调试原理

动态调试原理

  • 关于 GCC、LLVM、GDB、LLDB

    • Xcode 的 编译器 发展历程:GCCLLVM
    • Xcode 的 调试器 发展历程:GDBLLDB
  • debugserver一开始存放在Mac的Xcode⾥面

    1
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/9.1/DeveloperDiskImage.dmg/usr/bin/debugserver
  • 当Xcode识别到手机设备时,Xcode会自动将debugserver安装到iPhone上

    1
    /Developer/usr/bin/debugserver
  • Xcode调试的局限性

    • 一般情况下,只能调试通过 Xcode 安装的 App

三、动态调试任意 App

动态调试任意App

1、debugserver 的权限问题

  • 默认情况下,/Developer/usr/bin/debugserver 缺少一定的权限,只能调试通过 Xcode 安装的 APP,无法调试其他 App (⽐如来⾃自 App Store 的 App)
  • 如果希望调试其他App,需要对 debugserver 重新签名,签上2个调试相关的权限
    • get-task-allow
    • task_for_pid-allow

2、如何给 debugserver 签上权限

  • iPhone上的 /Developer ⽬录是只读的,无法直接对 /Developer/usr/bin/debugserver ⽂件签名,需要先把 debugserver 复制到 Mac 上
  • 通过 ldid 命令导出⽂件以前的签名权限
    1
    ldid -e debugserver > debugserver.entitlements
  • debugserver.plist 文件加上 get-task-allowtask_for_pid-allow 权限
    debugserver权限
  • 通过ldid命令重新签名
    1
    ldid -S debugserver.entitlements debugserver
  • 将已经签好权限的debugserver放到/usr/bin目录,便于找到debugserver指令
  • debugserver添加执行权限
    1
    xhmod +x /usr/bin/debugserver

3、让 debugserver 附加到某个 App 进程

  • 执行下面的命令:

    1
    debugserver *:端口号 -a 进程

    *:端口号:使用 iPhone 的某个端口启动 debugserver 服务(只要不是保留端⼝号就行)

    -a 进程:输入 App 的进程信息(进程 ID 或者进程名称)

4、在 Mac 上启动 LLDB,远程连接 iPhone 上的 debugserver 服务

  • 启动LLDB

    1
    2
    lldb
    (lldb)
  • 连接 debugserver 服务

    1
    (lldb) process connect connect://手机IP地址:debugserver服务端⼝号
  • 使用 LLDB 的 c 命令让程序先继续运⾏

    1
    (lldb) c
  • 接下来就可以使⽤用 LLDB 命令调试App

5、通过debugserver启动App

  • 执行下面的命令:

    1
    debugserver -x auto *:端⼝号 APP的可执⾏文件路径

四、常用LLDB指令

  • 指令的格式是

    1
    <command> [<subcommand> [<subcommand>...]] <action> [-options [option-value]] [argument [argument...]]

    <command>:命令

    <subcommand>:子命令

    <action>:命令操作,想在前面的命令序列的上下文中执行的一些操作

    <options>:命令选项,行为修改器(action modifiers),通常带有一些值。

    <argument>:命令参数,据使用的命令的上下文来表示各种不同的东西

    []:表示命令是可选的,可以有也可以没有。

    举个例子:给 test 函数设置断点

    1
    breakpoint set -n test

    breakpoint<command>, set<action>, -n<options>test<argument>

  • 可以查看指令的用法:help<command>,比如

    1
    2
    help breakpoint
    help breakpoint set
  • 执行⼀个表达式:expression<cmd-options> -- <expr>

    1
    expression self.view.backgroundColor = [UIColor redColor]
    • <cmd-options> : 命令选项
    • -- : 命令选项结束符,表示所有的命令选项已经设置完毕,如果没有命令选项,-- 可以省略
  • <expr> : 需要执⾏的表达式

    • expressionexpression -- 和指令 printpcall的效果一样
    • expression -O -- 和指令 po 的效果⼀样
  • 打印线程的堆栈信息,和指令 bt 的效果一样

    1
    thread backtrace
  • 让函数直接返回某个值,不会执行断点后面的代码

    1
    thread return [<expr>]
  • 打印当前栈帧的变量量

    1
    frame variable [<variable name>]
  • 程序继续运行

    1
    2
    3
    thread continue
    continue
    c
  • 单步运⾏,把子函数当做整体一步执⾏

    1
    2
    3
    thread step-over
    next
    n
  • 单步运行,遇到⼦函数会进入子函数

    1
    2
    3
    thread step-in
    step
    s
  • 直接执⾏完当前函数的所有代码,返回到上一个函数

    1
    2
    thread step-out
    finish
  • 设置断点

    1
    2
    3
    4
    5
    6
    7
    breakpoint set -a 函数地址
    breakpoint set -n 函数名
    breakpoint set -n test
    breakpoint set -n touchesBegan:withEvent:
    breakpoint set -n "-[ViewController-touchesBegan:withEvent:]"
    breakpoint set -r 正则表达式
    breakpoint set -s 动态库 -n 函数名
  • 列出所有的断点(每个断点都有⾃己的编号)

    1
    breakpoint list
  • 禁用、启用、删除断点

    1
    2
    3
    breakpoint disable 断点编号
    breakpoint enable 断点编号
    breakpoint delete 断点编号
  • 给断点预先设置需要执行的命令,到触发断点时,就会按顺序执行

    1
    breakpoint command add 断点编号
  • 查看某个断点设置的命令

    1
    breakpoint command list 断点编号*
  • 删除某个断点设置的命令

    1
    breakpoint command delete 断点编号
  • 查找某个类型的信息

    1
    image lookup -t 类型
  • 根据内存地址查找在模块中的位置

    1
    image lookup -a 地址
  • 查找某个符号或者函数的位置

    1
    image lookup -n 符号或者函数名
  • 列出所加载的模块信息

    1
    image list
  • 打印出模块的偏移地址、全路径

    1
    image list -o -f