二、在LLVM中编写pass的详细教程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ab6326795/article/details/81358247

.../llvm/lib/Transforms 中创建一个子文件夹,例如名字叫做MyPass。然后在此文件夹下创建如下三个文件:CMakeLists.txt、MyPass.exports、MyPass.cpp

CMakeLists.txt内容如下:

# If we don't need RTTI or EH, there's no reason to export anything
# from the hello plugin.
if( NOT LLVM_REQUIRES_RTTI )
  if( NOT LLVM_REQUIRES_EH )
    set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/MyPass.exports)
  endif()
endif()

if(WIN32 OR CYGWIN)
  set(LLVM_LINK_COMPONENTS Core Support)
endif()

add_llvm_loadable_module( LLVMMyPass
  MyPass.cpp

  DEPENDS
  intrinsics_gen
  PLUGIN_TOOL
  opt
  )

MyPass.cpp内容如下:

#include"llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

#define DEBUG_TAG "MyPass"

namespace{
   struct MyPass : public FunctionPass{
	   static char ID;
	   MyPass():FunctionPass(ID){

	   }

	   bool runOnFunction(Function &F) override{
		   errs() << DEBUG_TAG<<": ";
		   errs() << F.getName() << "\n";
		   return false;
	   }
   };
}

char MyPass::ID = 0;
static RegisterPass<MyPass> TTT("mypass", "this is mypass!");

MyPass.exports 暂时什么都不写。

在MyPass的上一级目录的CMakeLists.txt里增加 MyPass文件夹,完整内容如下:

好,这里一个超简单的pass我们已经写好了,那么准备一个.cpp文件做测试吧,我这里的Test.cpp内容如下:

#include<stdio.h>
#include<string.h>

int add(int a, int b) {
	return a + b;
}

void dump() {
	printf("dump entry ...");
}

char* getSoName() {
	return strdup("xx.so");
}

然后使用 编译下llvm项目。进入build目录:

cmake -DCMAKE_BUILD_TYPE=Release ../obfuscator/

成功后

make -j7

然后使用clang编译下Test.cpp

llvm-obfuscator/build/bin/clang Test.cpp  -O0 -S -emit-llvm -o Test.ll

调用下我们的MyPass

llvm-obfuscator/build/bin/opt' -load llvm-obfuscator/build/lib/LLVMMyPass.so -mypass Test.ll 

成功打印了函数名!有人可能会问了,为什么函数名都加了_ZXX,那是因为我们的Test.cpp是C++文件,函数支持重载,C++避免函数冲突就会加前缀 和后缀参数缩写。 改成Test.c ,重新编译下,你会发现函数名就原原本本的打印出来了。

猜你喜欢

转载自blog.csdn.net/ab6326795/article/details/81358247