KLEE源码解析之klee_make_symbolic跟踪

使用klee时,一般要利用klee_make_symbolic函数,将要跟踪的变量标记为symbolic,但是klee是如何找到这个函数,并且对应标记的呢。。。。。

把klee_make_symbolic使用的分为两个过程,1。绑定 2.调用

 

1.绑定

在main.cpp中

 

line:1303
  Interpreter *interpreter = 
    theInterpreter = Interpreter::create(IOpts, handler);//////////调用static函数创建了interpretor
  handler->setInterpreter(interpreter);  ////////////设置了interpreter输出文件的路径??
 
line:1313
  const Module *finalModule = 
    interpreter->setModule(mainModule, Opts);.////////////////////////////在setModule函数中,完成了klee_make_symbolic函数到SpecialFunctionHandler::handleMakeSymbolic的绑定
 
 
 
Executor.cpp
跟踪Executor::setModule(Executor作为Interpreter的子类,实现了setModule虚函数)
 
line:348行
  specialFunctionHandler = new SpecialFunctionHandler(*this);/////实现了Executor::specialFuntionHandler变量与包含它的类变量的相互绑定
 
line:352
  specialFunctionHandler->bind();///////////////////////////////继续绑定过程
 
 
 
 
 
SpecialFunctionHandler.cpp
 
line:149   
Function *f = executor.kmodule->module->getFunction(hi.name);/////////利用llvm提供的功能函数,查找到对应的hi.name(这里为klee_make_symbolic)的Function指针
 
line:151
    if (f && (!hi.doNotOverride || f->isDeclaration()))//代码中存在klee_make_symbolic函数
      handlers[f] = std::make_pair(hi.handler, hi.hasReturnValue);///////////////////////  建立klee_make_symbolic函数返回指针和hi的对应关系,对应klee::SpecialFunctionHandler::handleMakeSymbolic() 
        
                      handlers_ty handlers;                                                      typedef std::map<const llvm::Function*, 
                                                                                                   std::pair<Handler,bool> > handlers_ty;
 
至此绑定结束
 
 
 
 
 
 
 
 
2.运行klee_make_symbolicd对应的handleMakeSymbolic函数
 
main.cpp
 
  if (!ReplayOutDir.empty() || !ReplayOutFile.empty())///////////感觉一直都为真吧???
 {
line1365
      interpreter->runFunctionAsMain(mainFn, out->numArgs, out->args, pEnvp);
 
 }

 

Executor.cpp

 

进入runFunctionAsMain函数

line3257

 

  run(*state);////////////  ExecutionState *state = new ExecutionState(kmodule->functionMap[f]);生成state,并完成一系列的初始工作
 
 
 
 
 
 
进入run函数
line2402
    while (!seedMap.empty())对应论文里面提到的state没有运行完,则程序继续运行
   {
line2415
      executeInstruction(state, ki);
   }
 
 
 
 
 
 
 
进入 executeInstruction(state, ki)函数
line1547
  case Instruction::Call: ///////指令作用为函数调用,顾名思义。。。
 {
line:1604
      executeCall(state, ki, f, arguments);
 
  }
 
 
 
 
 
 
 
 
 
进入 executeCall(state, ki, f, arguments);
函数头::
void Executor::executeCall(ExecutionState &state, 
                           KInstruction *ki,
                           Function *f,
                           std::vector< ref<Expr> > &arguments) {
 
line1125
      callExternalFunction(state, ki, f, arguments);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
进入callExternalFunction(state, ki, f, arguments);
函数头:
void Executor::callExternalFunction(ExecutionState &state,
                                    KInstruction *target,
                                    Function *function,
                                    std::vector< ref<Expr> > &arguments) {
 
 
line2665
  if (specialFunctionHandler->handle(state, function, target, arguments))/////注意这里的Executor::specialFunctionHandler为Executore::setModule生成的
 
  
 
 
 
 
 
 
 
 
 
进入SpecialFunctionHandler::handle函数
SpecialFuntionHandler.cpp
line161-163
  handlers_ty::iterator it = handlers.find(f);
  if (it != handlers.end()) {    
    Handler h = it->second.first;/////////////找到对应的Handler
 
 
line170
   (this->*h)(state, target, arguments);调用klee_make_symbolic对应的处理函数handleMakeSymbolic(ExecutionState &state,
                                                KInstruction *target,
                                                std::vector<ref<Expr> > &arguments) 成功
 
 
 
 
 
 
 
下面,让我们看一下handleMakeSymbolic函数是如何实现symbolic的添加
 
void SpecialFunctionHandler::handleMakeSymbolic(ExecutionState &state,
                                                KInstruction *target,
                                                std::vector<ref<Expr> > &arguments) {
追踪下参数的来源
 
 
 
handleMakeSymbolic第三个参数::
Executor.cpp
executeInstruction()函数
line1559中
    std::vector< ref<Expr> > arguments;
line1563中
 arguments.push_back(eval(ki, j+1, state).value);
这是handleMakeSymbolic第三个参数的来源
 
 
 
 
第二个参数
 
Executor.cpp
run()函数中
2412行
KInstruction *ki = state.pc;////////当前状态,当前指令的位置
 
 
第一个参数
state也是在run()函数中选择出来的////论文里是两种方式interleave!!!有待考察!!!
 
 
 
 
 
SpecialFuntionHandler.cpp
line:683行
    if (res) {
      executor.executeMakeSymbolic(*s, mo, name);
       }
 
 
跟踪进入executeMakeSymbolic
Executor.cpp
line:3103
    const Array *array = new Array(uniqueName, mo->size);
    bindObjectInState(state, mo, false, array);
    state.addSymbolic(mo, array);
完成了符号symbolic的添加