llvm学习(五):动态加载 pass 时问题汇总

昨天搞交叉编译,中间其实有些没解决的问题都跳过了,最近有小伙伴联系我说加载不上的问题,符号各种找不到。刚好今天在做选型的工作,必须要面对这个问题了。

一、Release 版的 clang 和 Debug 版的 clang 无法加载对方编译出来的pass

之前有个误区,相同版本号的 clang 可以加载相同版本号的 pass,但却不是这样的,操作如下:

  1. 编译 Release 版的 llvm+clang,安装在 /path/to/llvm/r 目录下
  2. 编译 Debug 版的 llvm+clang,安装在 /path/to/llvm/i 目录下
  3. 使用$LLVM_HOME=/path/to/llvm/i ,编译出 i/libSkeletonPass.so
  4. 使用$LLVM_HOME=/path/to/llvm/r ,编译出 r/libSkeletonPass.so

两个成功

Debug-clang + Debug-pass 成功

1
2
➜  ii bin/clang -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include -Xclang -load -Xclang /Users/leadroyal/CLion_code/llvm-pass-tutorial/ii/skeleton/libSkeletonPass.so -w /tmp/test.c -o test.bin
I saw a function called main!

Release-clang + Release-pass 成功

1
2
➜  r bin/clang -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include -Xclang -load -Xclang /Users/leadroyal/CLion_code/llvm-pass-tutorial/r/skeleton/libSkeletonPass.so -w /tmp/test.c -o test.bin
I saw a function called main!

两个失败的例子

Release-clang + Debug-pass 失败

1
2
3
4
5
6
➜  r clang -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include -Xclang -load -Xclang /Users/leadroyal/CLion_code/llvm-pass-tutorial/r/skeleton/libSkeletonPass.so -w /tmp/test.c -o test.bin
error: unable to load plugin '/Users/leadroyal/CLion_code/llvm-pass-tutorial/r/skeleton/libSkeletonPass.so':
'dlopen(/Users/leadroyal/CLion_code/llvm-pass-tutorial/r/skeleton/libSkeletonPass.so, 9): Symbol not found: __ZN4llvm24DisableABIBreakingChecksE
Referenced from: /Users/leadroyal/CLion_code/llvm-pass-tutorial/r/skeleton/libSkeletonPass.so
Expected in: flat namespace
in /Users/leadroyal/CLion_code/llvm-pass-tutorial/r/skeleton/libSkeletonPass.so'

Debug-clang + Release-pass 失败

1
2
3
4
5
6
➜  ii clang -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include -Xclang -load -Xclang /Users/leadroyal/CLion_code/llvm-pass-tutorial/ii/skeleton/libSkeletonPass.so -w /tmp/test.c -o test.bin
error: unable to load plugin '/Users/leadroyal/CLion_code/llvm-pass-tutorial/ii/skeleton/libSkeletonPass.so':
'dlopen(/Users/leadroyal/CLion_code/llvm-pass-tutorial/ii/skeleton/libSkeletonPass.so, 9): Symbol not found: __ZN4llvm23EnableABIBreakingChecksE
Referenced from: /Users/leadroyal/CLion_code/llvm-pass-tutorial/ii/skeleton/libSkeletonPass.so
Expected in: flat namespace
in /Users/leadroyal/CLion_code/llvm-pass-tutorial/ii/skeleton/libSkeletonPass.so'

稍微看一眼,这两个报错不是一模一样的报错么,都是找不到符号。但两个文件基本一模一样,源码一样,环境稍微有点区别,但符号为什么找不到。

在这里纠结了很久,突然想起来自己是个星际玩家,容易眼瞎,经过大量的思考后,发现有句话不一样。

1
2
Symbol not found: __ZN4llvm24DisableABIBreakingChecksE
Symbol not found: __ZN4llvm23EnableABIBreakingChecksE

一个是 Disable 一个是 Enable ,难道是这里的问题?

于是打开 IDA 和 010Editor 开始各种diff ,发现二者文件的导入函数个数、长度、文件大小基本都一模一样,只有一个细节不一致。

破案了,原来是 Release 版的 clang 和 Debug 版的 clang 符号表本来就不一致,能加载成功就奇怪了。

(2019.3.22更新,这里其实是 LLVM_ENABLE_ABI_BREAKING_CHECKS 的不一致导致的,详情看第九篇文章)

这时候测一下系统自带的那个 clang,因为它是最辣鸡的那个,从来没有成功运行过。

1
2
3
4
5
6
7
8
9
10
11
12
➜  darwin-x86_64 /usr/bin/clang -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include -Xclang -load -Xclang /Users/leadroyal/CLion_code/llvm-pass-tutorial/ii/skeleton/libSkeletonPass.so -w /tmp/test.c -o test.bin
error: unable to load plugin '/Users/leadroyal/CLion_code/llvm-pass-tutorial/ii/skeleton/libSkeletonPass.so':
'dlopen(/Users/leadroyal/CLion_code/llvm-pass-tutorial/ii/skeleton/libSkeletonPass.so, 9): Symbol not found: __ZN4llvm23EnableABIBreakingChecksE
Referenced from: /Users/leadroyal/CLion_code/llvm-pass-tutorial/ii/skeleton/libSkeletonPass.so
Expected in: flat namespace
in /Users/leadroyal/CLion_code/llvm-pass-tutorial/ii/skeleton/libSkeletonPass.so'
➜ darwin-x86_64 /usr/bin/clang -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include -Xclang -load -Xclang /Users/leadroyal/CLion_code/llvm-pass-tutorial/r/skeleton/libSkeletonPass.so -w /tmp/test.c -o test.bin
error: unable to load plugin '/Users/leadroyal/CLion_code/llvm-pass-tutorial/r/skeleton/libSkeletonPass.so':
'dlopen(/Users/leadroyal/CLion_code/llvm-pass-tutorial/r/skeleton/libSkeletonPass.so, 9): Symbol not found: __ZN4llvm24DisableABIBreakingChecksE
Referenced from: /Users/leadroyal/CLion_code/llvm-pass-tutorial/r/skeleton/libSkeletonPass.so
Expected in: flat namespace
in /Users/leadroyal/CLion_code/llvm-pass-tutorial/r/skeleton/libSkeletonPass.so'

哈哈,两个符号全都找不到,真丢人,赶紧退群吧。

再看看 NDK 自带的,报的是__ZN4llvm12FunctionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE 找不到,emmmmmmm,后面再看看怎么解决吧!

二、系统自带的clang加载编译出来的 Pass

1
2
3
4
5
➜  darwin-x86_64 /usr/bin/clang --version
Apple LLVM version 10.0.0 (clang-1000.11.45.5)
Target: x86_64-apple-darwin18.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

别想了,完全是两套体系。有大佬会的话,求教。

三、ndk的clang加载编译出来的 Pass

2019年11月15日16:08:34:可行,但需要条件请,阅读第十一篇文章。