llvm学习(十五):lldb脚本开发基础
从零开始的 lldb 脚本开发。系列第一篇,讲环境搭建和 demo,优雅地开发 lldb 脚本。
编译和安装(非常详细)
作为 llvm 的忠实拥护者,当然要坚持拥护 lldb,但由于它上面实在是没什么插件,只能自己动手丰衣足食。
apt 简易版(限ubuntu)
sudo apt install lldb
或者
sudo apt install lldb-10 python3-lldb-10
根据依赖关系,lldb 这个包会自动定位到某个比较稳定的版本上,例如我的 ubuntu 20 在2021年09月05日,在安装时会安装一堆 llvm10 相关的东西(包括 python3-lldb-10)
1202年了,求求各位别再用 python2 了,也别再用 llvm6 了。
从源码编译
官方资料:https://lldb.llvm.org/resources/build.html , 非常靠谱。
1202年了,编译 llvm 越来越方便了,简要记录:
从
https://github.com/llvm/llvm-project/releases
随便下载一份llvm-project-12.0.0.src.tar.xz
,解压。执行命令,仅编译lldb和clang(官方说 lldb 依赖 clang),开启对 python 的支持
cmake ../llvm-project-12.0.0/llvm -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS='clang;lldb' -DLLDB_ENABLE_PYTHON=1
这里我测试了一下,我本来想要 py3 结果编出了 py2,改了 PATH 后变成 py3 了,好像是和编译
python
这个命令本身的版本有关,编译时就确认好了,编译结束后无法修改解释器,不大确定细节。
仅编译 lldb
参考 https://lldb.llvm.org/resources/build.html#standalone-builds 。
假设你拥有了编译好了 llvm+clang 工程,可以让 lldb 使用这个 build 目录或者 release 目录,不需要从头再来,省时省力。
我使用的命令是:(好像这个会自动把 python 插件也编译了)
1 | mkdir lldb-build |
或者
1 | mkdir lldb-build |
MacOS存在的问题
mac上的 debugger 需要是被签名过的文件,并且该签名被系统信任,所以自己编译出来的 lldb 是损坏的,整得挺麻烦的,爱折腾的自己去官方翻,我是不爱折腾这个东西。
仅生成 python 接口文件(无需编译 c 代码)
上文描述的方式,会得到一个 lldb/__init__.py
文件,但它不大好用,可能是出于对 py2 兼容的考虑,函数的参数和返回值都没有数据类型,用起来还是不够爽,经过一番探索,找到了 python3 的支持方式。
lldb python 拓展的编译过程,通过阅读 cmake 文件可以略知端倪。
1 |
|
经过阅读,根据是否开启 python 来确定下文执行内容,最终会调用到 swig 这个工具,并且有大量的命令行参数,生成 python 接口文件。
lldb 的 python 其实是调用底层 cpp 的实现,使用 swig 这个工具描述接口并且生成 API 文件。
swig 在生成 python 时有额外选项,参考下方 help:
1 | swig -python --help |
而包括 llvm13 在内的全部版本,都是没有主动带有 py3 这个参数的,因此生成的文件没有 py3 的参数类型和函数类型。
官方在 https://github.com/llvm/llvm-project/commit/e5228ef556e5a4cb40c6c7936aada636e1b7be10 该次 commit 中将 py3 加入了命令行参数,并且在 llvm14 中落地。
为了解决手头的问题,我们可以选择手动执行这句 swig 来生成文件,经过尝试后,如下:
1 | cd /tmp/lldb/bindings/python |
会在 python.swig
的同目录下生成 lldb.py
,就是我们要找的文件了。
然后在里面加上 -py3
这个选项,就可以生成 py3 的文件了。
简单测试
lldb 和 gdb 的命令和用法差不多,绝大部分情况下都能正确执行插件。
输入 script
可以进入交互模式,import lldb
已经被执行过了,可以直接访问 lldb.debugger
这种对象。
输入 script print("Hello")
可以直接执行 python。
反面教材:
从源码编译时,如果忘了开 LLDB_ENABLE_PYTHON
,这里 script
就会弹一句什么报错,暗示没有支持的脚本语言,需要重新编译。
为IDE提供代码补全索引
老生常谈,本人作为没了 IDE 就活不下去的开发者,一定要做到类型推断和代码补全。(这也是我常年诟病 py2 的原因)
无论是从 apt 安装,还是从源码编译,在目录里都可以翻到这个 lldb/__init__.py
文件,附近还必有一个 lldb.so
文件:
输入 `script print(lldb)` 能找到这个 module。
例如:
1
2
<module 'lldb' from '/usr/lib/python3/dist-packages/lldb/__init__.py'>
<module 'lldb' from '/Library/Developer/CommandLineTools/Library/PrivateFrameworks/LLDB.framework/Resources/Python/lldb/__init__.py'>
或者直接生成 lldb.py
,参考上文描述的内容。
将 lldb/__init__.py
复制粘贴(或者软连接)到第三方库的路径下,相当于:
1 | ln -s /Library/Developer/CommandLineTools/Library/PrivateFrameworks/LLDB.framework/Resources/Python/lldb /path/to/lldb |
1 | mkdir /path/to/lldb |
调用 import lldb
后,相关的数据结构就都有了,注释很多,省的到官网去查了。
以官方的 demo 为例,成功后如图:
1 | def __lldb_init_module(debugger, internal_dict): |
好,终于可以动手写代码了!
结语
预告:下一篇介绍 lldb 模块提供的 API,介绍插件的整体设计。