把LLVM Pass 添加到clang的命令行参数

前言

编写LLVM的自定义混淆Pass后,每次使用都需要用opt 工具加载Pass的so,混淆BC文件,这个步骤麻烦又很累!

而OLLVM的混淆Pass可以直接用clang的特定参数启动,为了让我编写的自定义混淆Pass也能直接用clang启动,就有

了这篇文章。 虽然网上有一些参考资料,但是使用的却是非常老的LLVM3.5及其以下版本,OLLVM使用的是LLVM4.0 。

添加到clang参数的流程

其实并没有很难,只是网上几乎没有资料,让人很头痛……因为毕竟这么大一个项目,没那么好搞。但是有OLLVM

作为参考,真的很棒啊……

1.创建头文件,并添加创建Pass的函数声明(我是直接在混淆器的include目录下添加的):

//文件MyObfPass.h

namespace llvm{
	Pass *createMyObfPass ();
	Pass *createMyObfPass (bool);
}

2.在混淆源码cpp文件中,实现这两个创建Pass的函数:

//MyObfPass.cpp文件

struct MyObfPass : public ModulePass {
    static char ID; // Pass identification, replacement for typeid
    bool flag;
    MyObfPass() : ModulePass(ID) {}
    MyObfPass(bool flag) : ModulePass(ID) {this->flag = flag; MyObfPass();}
}

Pass *createMyObfPass() {
  return new MyObfPass();
}

Pass *createMyObfPass(bool flag) {
  return new MyObfPass(flag);
}

3.修改Obfuscation目录下的CMakeList.txt文件,添加源码:

add_llvm_library(LLVMObfuscation
  CryptoUtils.cpp
  Substitution.cpp
  BogusControlFlow.cpp
  Utils.cpp
  SplitBasicBlocks.cpp
  Flattening.cpp
  MyObfPass.cpp    #自定义的混淆源码
  
  )

add_dependencies(LLVMObfuscation intrinsics_gen)

4.修改lib/Transform/IPO/PassManagerBuilder.cpp文件,添加启动参数识别:

//定义一个 bool 类型的参数选项,参数名myobf:
static cl::opt MyObf("myobf",cl::init(false),
                                      cl::desc("Enable my Obfuscation pass!"));

//创建Pass并添加到Pass Manager
void PassManagerBuilder::populateModulePassManager(
    legacy::PassManagerBase &MPM){
//....... 忽略其他的代码
MPM.add(createMyObfPass(MyObf));

}

 

遇到的问题:

I.一开始的时候,我是在其他目录定义我的混淆器,并且编写了LLVMBuild.txt文件,然后修改了

PassManagerBuilder.cpp 添加Pass,但是会遇到问题:

../../lib/libLLVMipo.a(PassManagerBuilder.cpp.obj):PassManagerBuilder.cpp:(.text+0x2043): undefined reference to `createMyObfPass(bool)'
collect2.exe: error: ld returned 1 exit status
tools\bugpoint\CMakeFiles\bugpoint.dir\build.make:242: recipe for target 'bin/bugpoint.exe' failed
mingw32-make[2]: *** [bin/bugpoint.exe] Error 1
CMakeFiles\Makefile2:20310: recipe for target 'tools/bugpoint/CMakeFiles/bugpoint.dir/all' failed
mingw32-make[1]: *** [tools/bugpoint/CMakeFiles/bugpoint.dir/all] Error 2

这个问题真的把我搞崩溃了,一晚上没睡好觉…… 明明所有东西都和OLLVM做的一样了,为啥不行呢?

一天以后,我用一个思路,找到了这个问题的原因…… 思路是:把OLLVM创建Pass的函数的头文件去掉,看下会出什么错。

结果:

P:\ollvm\ollvm\lib\Transforms\IPO\PassManagerBuilder.cpp: In member function 'void llvm::PassManagerBuilder::populateModulePassManager(llvm::legacy::PassManagerBase&)':


P:\ollvm\ollvm\lib\Transforms\IPO\PassManagerBuilder.cpp:434:32: error: 'createMyObfPass' was not declared in this scope
   MPM.add(createMyObfPass(MyObf));
                                ^
P:\ollvm\ollvm\lib\Transforms\IPO\PassManagerBuilder.cpp:436:39: error: 'createBogus' was not declared in this scope
   MPM.add(createBogus(BogusControlFlow));
                                       ^
lib\Transforms\IPO\CMakeFiles\LLVMipo.dir\build.make:398: recipe for target 'lib/Transforms/IPO/CMakeFiles/LLVMipo.dir/PassManagerBuilder.cpp.obj' failed

提示的是  was not declared in this scope . 和之前的  undefined reference to `createMyObfPass(bool)'.

是不一样的! 一个是没有声明,另一个是没有定义的引用……  诶! 都怪自己菜! 现在真的要记住这些区别了!

没有声明就是因为没有头文件声明函数,然后直接调用了函数,就会出 was not declared in this scope 

没有定义的引用是啥意思呢? 个人理解是,这个函数声明了,但是没有找到对应的实现代码,导致“没有定义的引用”。

OK,那么怎么解决这个问题呢? 其实于PassManagerBuilder.cpp同一个目录下,有一个LLVMBuild.txt文件!

这个文件声明了当前目录的一些信息,其中包含了 引用库 的名字! 所以,只需要在自定义的混淆器目录下,

新建一个LLVMBuild.txt , 设置库的名字等信息,然后在 PassManagerBuilder.cpp 同目录下的LLVMBuild.txt文件

中,添加该库的名字即可! 真的被这个问题搞得很无奈……不过还好,自己最后还是搞出来了,欣慰……菜鸟……

最后附上一张使用截图,刚刚编译好,第一次使用!

把LLVM Pass 添加到clang的命令行参数_第1张图片

再来一张混淆效果:

把LLVM Pass 添加到clang的命令行参数_第2张图片

你可能感兴趣的:(把LLVM Pass 添加到clang的命令行参数)