一、目的:
分析 LLVM 自带的符号重写Pass
二、分析执行流程:
- LLVM原生的文件
lib/Transforms/Utils/SymbolRewriter.cpp
-
入口首先有 RewriteSymbolPass 类对象创建,该构造函数内首先解析输入的map文件;
-
一路跟踪 parse 函数,可以看到解析文件内容;
-
读取内容将对象指针存储到容器中:
ExplicitRewriteFunctionDescriptor 表示显示名称替换,就是全名替换;
PatternRewriteFunctionDescriptor 表示正则名称替换;
-
文件解析完后,进入 runOnModule 开始执行;
-
循环list对象 Descriptors ,栈结构;
-
符号替换,看起来并不复杂,核心逻辑使用setName将source替换为Target:
Comdat组件被 rewriteComdat 提前处理,老实说,Comdat 的来源和作用并不是很理解,官网以及一些网站的解释还是不懂,有大佬可以留言解释一下。QAQ
两个命令行参数:
static cl::list<std::string> RewriteMapFiles("rewrite-map-file",
cl::desc("Symbol Rewrite Map"),
cl::value_desc("filename"),
cl::Hidden);
INITIALIZE_PASS(RewriteSymbolsLegacyPass, "rewrite-symbols", "Rewrite Symbols",
false, false)
rewrite-map-file 需要跟一个yaml格式的文件,显示指明了需要重命名的符号
三、调试运行:
-
在xcode中可以直接使用opt调试,命令行参数如下:
我这里使用llvm自带的例子,参数输入ll文件和map文件,map文件的格式在cpp文件里有注释解释:
// Currently, the following descriptor types are supported:
//
// - function: (function rewriting)
// + Source (original name of the function)
// + Target (explicit transformation)
// + Transform (pattern transformation)
// + Naked (boolean, whether the function is undecorated)
// - global variable: (external linkage global variable rewriting)
// + Source (original name of externally visible variable)
// + Target (explicit transformation)
// + Transform (pattern transformation)
// - global alias: (global alias rewriting)
// + Source (original name of the aliased name)
// + Target (explicit transformation)
// + Transform (pattern transformation)
-
查看生成的IR:
可以看到map文件配置的函数名都被更改了,
四、示例,自己写一个测试下:
- c文件:
#include <stdio.h>
int a = 100;
static int add(int x, int y)
{
return x + y;
}
int sub(int x, int y)
{
return x - y;
}
int main()
{
printf("%d\n", add(3, 4));
printf("%d\n", sub(5, 4));
printf("%d\n", a);
return 0;
}
生成IR:
clang -c test_symbolobf.c -o test_symbolobf.ll -emit-llvm -S
-
配置yaml文件:
使用opt:
../bin/opt -rewrite-symbols -rewrite-map-file /xxx/test_symbolobf/test_symbolobf_map.yaml /xxx/test_symbolobf/test_symbolobf.ll -o /xxx/test_symbolobf/test_symbolobf.ll.bc
bc to ll:
llvm-dis /xxx/test_symbolobf/test_symbolobf.ll.bc
-
查看新生成IR,正常: