C语言编译插桩,LLVM - Pass 实现 C函数 插桩 - LLVM/release_90

#include

#include

#include

#include "llvm/Support/raw_ostream.h"

#include "llvm/Pass.h"

#include "llvm/IR/Module.h"

#include "llvm/IR/Function.h"

#include "llvm/IR/Instructions.h"

#include "llvm/IR/LegacyPassManager.h"

#include "llvm/IR/IRBuilder.h"

#include "llvm/Transforms/IPO/PassManagerBuilder.h"

using namespace llvm;

namespace

{

const char* HOOK_FUNC_PREFIX = "_ly_fun";

const char* HOOK_BEGIN_FUNC = "_ly_fun_b";

const char* HOOK_END_FUNC = "_ly_fun_e";

struct MyPlacementPass : public FunctionPass

{

static char ID;

MyPlacementPass() : FunctionPass(ID){}

bool runOnFunction(Function &F) override{

printf("------------- runOnFunction --------------\n");

// 1.

if (F.getName().startswith(HOOK_FUNC_PREFIX))

return false;

// 2.

Value* beginTime = nullptr;

if (!insert_begin_inst(F, beginTime))

return false;

// 3.

insert_return_inst(F, beginTime);

return false;

}

bool insert_begin_inst(Function &F, Value*& beginTime){

LLVMContext &context = F.getParent()->getContext();

BasicBlock &bb = F.getEntryBlock();

/**

* 1. create begin function

*

* https://bugs.freebsd.org/bugzilla/attachment.cgi?bugid=239175&action=viewall&hide_obsolete=1

* https://bugs.freebsd.org/bugzilla/attachment.cgi?id=206326&action=diff#b/lang/beignet/files/patch-llvm9_sec1

* https://bugs.freebsd.org/bugzilla/attachment.cgi?bugid=239175&action=viewall

*/

#if LLVM_VERSION_MAJOR * 10 + LLVM_VERSION_MINOR >= 90

FunctionCallee beginFun = F.getParent()->getOrInsertFunction(

#else

Constant *beginFun = F.getParent()->getOrInsertFunction(

#endif

HOOK_BEGIN_FUNC,

FunctionType::get(Type::getInt64Ty(context), {}, false)

);

// 2. create CallInst(struction)

// Value *beginTime = nullptr;

CallInst *inst = nullptr;

#if LLVM_VERSION_MAJOR * 10 + LLVM_VERSION_MINOR >= 90

IRBuilder<> builder(context);

inst = builder.CreateCall(beginFun);

#else

if (Function *fun = dyn_cast(beginFun))

inst = CallInst::Create(fun);

#endif

if (!inst) {

llvm::errs() << "Create First CallInst Failed\n";

return false;

}

// 3. 获取 main() 开始的第一条指令

Instruction *beginInst = dyn_cast(bb.begin());

// 4. insert before inst

inst->insertBefore(beginInst);

beginTime = inst;

return true;

}

void insert_return_inst(Function &F, Value* beginTime)

{

LLVMContext &context = F.getParent()->getContext();

for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)

{

BasicBlock &BB = *I;

for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)

{

ReturnInst *IST = dyn_cast(I);

if (!IST)

continue;

// end func type

FunctionType *endFuncType = FunctionType::get(

Type::getVoidTy(context),

{Type::getInt8PtrTy(context),Type::getInt64Ty(context)},

false

);

// end func

#if LLVM_VERSION_MAJOR * 10 + LLVM_VERSION_MINOR >= 90

FunctionCallee endFunc = BB.getModule()->getOrInsertFunction(

#else

Constant *endFunc = BB.getModule()->getOrInsertFunction(

#endif

HOOK_END_FUNC, endFuncType

);

// end func inst(struction)

IRBuilder<> builder(&BB);

#if LLVM_VERSION_MAJOR * 10 + LLVM_VERSION_MINOR >= 90

CallInst* endCI = builder.CreateCall(

#else

CallInst* endCI = CallInst::Create(

#endif

endFunc,

{

builder.CreateGlobalStringPtr(BB.getParent()->getName()),

beginTime

}

);

// insert end func(struction)

endCI->insertBefore(IST);

}

}

}

};

}

char MyPlacementPass::ID = 0;

// Automatically enable the pass.

// http://adriansampson.net/blog/clangpass.html

static void registerSkeletonPass(const PassManagerBuilder &, legacy::PassManagerBase &PM)

{

PM.add(new MyPlacementPass());

}

static RegisterStandardPasses RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, registerSkeletonPass);

复制代码

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值