1. 程式人生 > >二、在LLVM中編寫pass的詳細教程

二、在LLVM中編寫pass的詳細教程

.../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 ,重新編譯下,你會發現函式名就原原本本的打印出來了。