如何用 Swift 编写自定义的 LLDB 命令?

474 阅读3分钟

「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战」。

对于大多数的 iOS 开发者来说,日常中用到的最多的 LLDB 的命令应该就是 po。但大家可能不知道的是,其实我们可以使用纯 Swift 代码来自定义 LLDB 命令。

关于 LLDB 的一些基本使用,也可以看一下我的这篇文章

本文主要会讲解以下的三部分内容:

  • 添加你的第一条 LLDB 命令。
  • 添加带有参数的 LLDB 命令。
  • 如何将 Swift 代码转为 LLDB 命令。

废话不多说,let's go!

添加你的第一条 LLDB 命令

在添加命令之前,需要先讲解一下 command alias 这个命令。下面是它的格式:

command alias [command_name] expr -l Swift -O -- [swift_code]

该命令的详细介绍:

  • command alias:将你编写的 Swift 代码进行重命名。
  • [command_name]:自定义的名字。
  • expr -l Swift -O --:告诉 LLDB 调试器,将后面的内容都按照 Swift 代码进行解释。
  • [swift_code]:实现某项功能的代码。

举个栗子,如果我们想执行 hello 命令来输出 hello,world,可以这样写:

command alias hello expr -l Swift -O -- print("hello,world")

现在,你已经有了自己自定义的 LLDB 命令。现在,在 debug 的区域输入 hello 应该就会打印了: 截屏2022-02-21 下午3.29.06.png

但是,需要注意的是:这样,只会将这个命令存在当前的这次 debug 中。如果,想永久的保存这个命令,还需要再去做以下操作:

  • 打开终端,执行 cd 进入根目录。
  • 执行 vi .lldbinit 命令,将上述的命令输入到文件中,保存退出。

这样, 命令就会永久的存在 LDDB 中了。

现在,你学会了如何添加不带参数的命令。下面,让我们更进一步,看一下带参数的如何写。

添加带有参数的 LLDB 命令

带参数的命令,需要使用到 LLDB 的 command regex 命令。下面是它的结构:

command regex [command_name] 's/[regex]/expr -l Swift -O -- [swift_code]/'

对于我们来说,主要的就是将 [regex] 替换为表达式(.+)。然后使用 %1 来代表我们的参数:

command regex greet 's/(.+)/expr -l Swift -O -- print("hello (%1)")/'

假设,name 为 张三,下面为执行结果:

(lldb) hello name
hello,张三

如果我们需要多个参数,在相应的位置添加 (.+) 和 %x 就可以了。比如 3 个参数:

command regex greet 's/(.+) (.+) (.+)/expr -l Swift -O -- print("hello (%1) and (%2) and (%3)")/'

下面为执行示例:

hello name1 name2 name3
hello xxx and xxx and xxx

如何将 Swift 代码转为 LLDB 命令

现在,我们有一个函数,函数的作用就是将 RGB 转为 hex。代码如下:

func hex(r: Int, g: Int, b: Int) {

    /* Make sure RGB value within range */
    if (r >= 0 && r <= 255) && (g >= 0 && g <= 255) && (b >= 0 && b <= 255) {

        let rgb:Int = r<<16 | g<<8 | b<<0
        let hex = String(format:"#%06x", rgb)

        print(hex)
    } else {
        print("Invalid input value")
    }
}

我们需要通过以下三步将其转为 LLDB 命令:

  • 为函数的每一个参数定义变量。
  • 将 %1、%2。。。分配给每一个变量。
  • 为每一句代码后面添加 ;

下面为转化后的代码:

let r = %1;
let g = %2;
let b = %3;

/* Make sure RGB value within range */
if (r >= 0 && r <= 255) && (g >= 0 && g <= 255) && (b >= 0 && b <= 255) {

    let rgb:Int = r<<16 | g<<8 | b<<0;
    let hex = String(format:"#%06x", rgb);

    print(hex);
} else {
    print("Invalid input value");
}

得到上面的代码后,再将其转为一行代码添加到命令中:

command regex hex 's/(.+) (.+) (.+)/expr -l Swift -O -- let r = %1; let g = %2; let b = %3; if (r >= 0 && r <= 255) && (g >= 0 && g <= 255) && (b >= 0 && b <= 255) { let rgb:Int = r<<16 | g<<8 | b<<0; let hex = String(format:"#%06x", rgb); print(hex); } else { print("Invalid input value"); }/'

最后一步,将其添加到 .lldbinit 中,就可以愉快地使用了。

截屏2022-02-21 下午3.53.30.png