gpt4 book ai didi

c - LLVM Pass 插入一个外部函数调用到 LLVM 位码

转载 作者:太空宇宙 更新时间:2023-11-03 23:59:19 58 4
gpt4 key购买 nike

我正在编写一个 LLVM 传递来检测一个 C 源程序。我想在每个调用外部函数的分支指令之前插入一个函数调用:

void print(int x){
printf("x = %d\n", x);

return;
}

我想使用 llvm-link 工具将此外部函数链接到 C 源代码,然后使用 opt 工具检测代码。

我实现的pass是这样的:

#include "llvm/Pass.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/IRBuilder.h"
#include <vector>

using namespace llvm;

namespace{
struct ir_instrumentation : public ModulePass{
static char ID;
Function *monitor;

ir_instrumentation() : ModulePass(ID) {}

virtual bool runOnModule(Module &M)
{
std::vector<Type *> args;
args.push_back(Type::getInt32Ty(M.getContext()));
ArrayRef<Type*> argsRef(args);
FunctionType *FT = FunctionType::get(Type::getVoidTy(M.getContext()), args, false);
Constant* myFunc = M.getOrInsertFunction("print", FT, NULL);
minitor = cast<Function>(myFunc);


for(Module::iterator F = M.begin(), E = M.end(); F!= E; ++F)
{
for(Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
{
for(BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; ++BI)
{
if(isa<BranchInst>(&(*BI)) )
{
errs() << "found a branch instruction!\n";
ArrayRef< Value* > arguments(ConstantInt::get(Type::getInt32Ty(M.getContext()), 5, true));
Instruction *newInst = CallInst::Create(monitor, arguments, "");
BB->getInstList().insert(BI, newInst);
errs() << "Inserted the function!\n";
}

}
}
}

return true;
}
};
char ir_instrumentation::ID = 0;
static RegisterPass<ir_instrumentation> X("ir-instrumentation", "LLVM IR Instrumentation Pass");

}

LLVM 使用此 channel 配置和构建良好,但当我使用 opt 时,我得到此错误:

opt: /llvm/lib/IR/Type.cpp:281:

llvm::FunctionType::FunctionType(llvm::Type*, llvm::ArrayRefllvm::Type*, bool):

Assertion `isValidReturnType(Result) && "invalid return type for function"' failed.

我认为问题出在我声明的函数类型与外部函数(如上下文)之间不匹配。

LLVM 版本:LLVM 版本 7.0.0svn

到现在我还没有解决这个问题。

谢谢

最佳答案

我终于可以解决这个问题并成功检测 LLVM 位码。在使用函数 getOrInsertFunction 遇到很多麻烦之后,我发现在我的案例中并没有必要使用这个方法。我只是简单地将通行证更改为:

#include "llvm/Pass.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/raw_ostream.h"

#include "llvm/IR/IRBuilder.h"

#include <vector>

using namespace llvm;

namespace{
struct ir_instrumentation : public ModulePass{
static char ID;
Function *monitor;

ir_instrumentation() : ModulePass(ID) {}

virtual bool runOnModule(Module &M)
{
errs() << "====----- Entered Module " << M.getName() << ".\n";

int counter = 0;

for(Module::iterator F = M.begin(), E = M.end(); F!= E; ++F)
{
errs() << "Function name: " << F->getName() << ".\n";
if(F->getName() == "print"){
monitor = cast<Function>(F);
continue;
}

for(Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
{
for(BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; ++BI)
{
if(isa<BranchInst>(&(*BI)) )
{
errs() << "found a brach instruction!\n";
ArrayRef< Value* > arguments(ConstantInt::get(Type::getInt32Ty(M.getContext()), counter, true));
counter++;
Instruction *newInst = CallInst::Create(monitor, arguments, "");
BB->getInstList().insert(BI, newInst);
errs() << "Inserted the function!\n";
}

}
}
}

return true;
}
};
char ir_instrumentation::ID = 0;
static RegisterPass<ir_instrumentation> X("ir-instrumentation", "LLVM IR Instrumentation Pass");

}

因为我知道外部函数的名称,所以我可以通过遍历模块的所有函数来简单地找到它,然后以所需的方式使用它。

很明显问题是由调用 module->getOrInsertFunction 和函数类型引起的。我的经验表明,当您想插入一个新函数并声明您自己的函数的原型(prototype)时,这种方法更有用。使用它来获得现有功能具有挑战性(例如设置正确的原型(prototype),...)

谢谢

关于c - LLVM Pass 插入一个外部函数调用到 LLVM 位码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51082081/

58 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com