二、在LLVM中編寫pass的詳細教程
阿新 • • 發佈:2019-02-11
.../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 ,重新編譯下,你會發現函式名就原原本本的打印出來了。