Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

instrument a call to function in LLVM IR

Tags:

llvm

I want to instrument a call to every function of the program in the bitcode level. Suppose there is a function void f(int a), I need to instrument the following code at the start of the main function.

int a;
klee_make_symbolic(&a, sizeof(a), "a");
f(a);

I wrote a pass to achieve that.

 for (Module::iterator f = M.begin(), fe = M.end(); f != fe; ++f) {
  std::vector<llvm::Value*> args;
  for(Function::arg_iterator ai = f->arg_begin(), ae = f->arg_end(); ai != ae; ++ai){
   Type* tp = ai->getType();   
    AllocaInst* arg = new AllocaInst(tp, "name", firstInst);
    args.push_back(arg);
    LLVM_TYPE_Q llvm::Type *i8Ty = Type::getInt8Ty(getGlobalContext());
    Constant *fc = M.getOrInsertFunction("klee_make_symbolic",
                                               PointerType::getUnqual(i8Ty),
                                               Type::getInt64Ty(getGlobalContext()),
                                               PointerType::getUnqual(i8Ty),
                                               NULL);
    Function* kleeMakeSymbolic = cast<Function>(fc);

    std::vector<Value* > klee_args;
    klee_args.push_back(arg);
    klee_args.push_back(ConstantInt::get(Type::getInt64Ty(getGlobalContext()),
                       dl->getTypeAllocSizeInBits(tp)));// dl is DataLayout
    klee_args.push_back(arg);//I dont't know how to pass a argument of "const char *"

    // Inject a call to klee_make_symbolic
    CallInst::Create(kleeMakeSymbolic, klee_args, "", firstInst);

  }

  // Inject a call to the function
  CallInst::Create(f, args, "", firstInst);

}

}

But I got an assertion failure:

 llvm::CallInst::init(llvm::Value*, llvm::ArrayRef<llvm::Value*>, const llvm::Twine&): Assertion `(Args.size() == FTy->getNumParams() || (FTy->isVarArg() && Args.size() > FTy->getNumParams())) && "Calling a function with bad signature!"' failed.

I am new to LLVm, can anyone tell me what's wrong in my implementation?

like image 438
Dingbao Xie Avatar asked Oct 11 '25 15:10

Dingbao Xie


1 Answers

You are passing the pointer of a to the function f. Thats the problem with your implementation.

In your code:

for (Module::iterator f = M.begin(), fe = M.end(); f != fe; ++f) {
  std::vector<llvm::Value*> args;
  for(Function::arg_iterator ai = f->arg_begin(), ae = f->arg_end(); ai != ae; ++ai){
   Type* tp = ai->getType();   
    AllocaInst* arg = new AllocaInst(tp, "name", firstInst);
    args.push_back(arg);
    ...

  }

  // Inject a call to the function
  CallInst::Create(f, args, "", firstInst);
}

your are pushing arg in your args vector. arg is the value of the AllocaInst, therefore it is a pointer. You need the value to fit your functions signature. You need to emit a LoadInst that loads from the AllocaInst and push the LoadInst into your vector.

For your problem:

 klee_args.push_back(arg);//I dont't know how to pass a argument of "const char *"

Have a look at the CreateGlobalStringPtr function from IRBuilder. Documentation here. IRBuilder is a nice helper class, which makes life with LLVM IR a little bit easier.

like image 135
Michael Haidl Avatar answered Oct 14 '25 05:10

Michael Haidl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!