From 3c2bacc7a9fb95caef07d87d9b6220712b7d613f Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Mon, 1 Aug 2011 02:26:27 +0000 Subject: Make the Executor capable of handling bitcasts of aliases, by rewriting the direct function call logic. git-svn-id: https://llvm.org/svn/llvm-project/klee/trunk@136605 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Core/Executor.cpp | 79 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 31 deletions(-) (limited to 'lib/Core/Executor.cpp') diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 1a37498f..87e70a4c 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -54,6 +54,7 @@ #include "llvm/LLVMContext.h" #endif #include "llvm/Module.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/CommandLine.h" @@ -1287,25 +1288,46 @@ void Executor::printFileLine(ExecutionState &state, KInstruction *ki) { std::cerr << " [no debug info]:"; } +/// Compute the true target of a function call, resolving LLVM and KLEE aliases +/// and bitcasts. +Function* Executor::getTargetFunction(Value *calledVal, ExecutionState &state) { + SmallPtrSet Visited; -Function* Executor::getCalledFunction(CallSite &cs, ExecutionState &state) { - Function *f = cs.getCalledFunction(); - - if (f) { - std::string alias = state.getFnAlias(f->getName()); - if (alias != "") { - llvm::Module* currModule = kmodule->module; - Function* old_f = f; - f = currModule->getFunction(alias); - if (!f) { - llvm::errs() << "Function " << alias << "(), alias for " - << old_f->getName() << " not found!\n"; - assert(f && "function alias not found"); + Constant *c = dyn_cast(calledVal); + if (!c) + return 0; + + while (true) { + if (GlobalValue *gv = dyn_cast(c)) { + if (!Visited.insert(gv)) + return 0; + + std::string alias = state.getFnAlias(gv->getName()); + if (alias != "") { + llvm::Module* currModule = kmodule->module; + GlobalValue *old_gv = gv; + gv = currModule->getNamedValue(alias); + if (!gv) { + llvm::errs() << "Function " << alias << "(), alias for " + << old_gv->getName() << " not found!\n"; + assert(0 && "function alias not found"); + } } - } + + if (Function *f = dyn_cast(gv)) + return f; + else if (GlobalAlias *ga = dyn_cast(gv)) + c = ga->getAliasee(); + else + return 0; + } else if (llvm::ConstantExpr *ce = dyn_cast(c)) { + if (ce->getOpcode()==Instruction::BitCast) + c = ce->getOperand(0); + else + return 0; + } else + return 0; } - - return f; } static bool isDebugIntrinsic(const Function *f, KModule *KM) { @@ -1526,7 +1548,8 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { CallSite cs(i); unsigned numArgs = cs.arg_size(); - Function *f = getCalledFunction(cs, state); + Value *fp = cs.getCalledValue(); + Function *f = getTargetFunction(fp, state); // Skip debug intrinsics, we can't evaluate their metadata arguments. if (f && isDebugIntrinsic(f, kmodule)) @@ -1539,19 +1562,15 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { for (unsigned j=0; j(cast(f->getType())->getElementType()); + const FunctionType *fpType = + dyn_cast(cast(fp->getType())->getElementType()); + // special case the call with a bitcast case - Value *fp = cs.getCalledValue(); - llvm::ConstantExpr *ce = dyn_cast(fp); - - if (ce && ce->getOpcode()==Instruction::BitCast) { - f = dyn_cast(ce->getOperand(0)); - assert(f && "XXX unrecognized constant expression in call"); - const FunctionType *fType = - dyn_cast(cast(f->getType())->getElementType()); - const FunctionType *ceType = - dyn_cast(cast(ce->getType())->getElementType()); - assert(fType && ceType && "unable to get function type"); + if (fType != fpType) { + assert(fType && fpType && "unable to get function type"); // XXX check result coercion @@ -1581,9 +1600,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { terminateStateOnExecError(state, "inline assembly is unsupported"); break; } - } - if (f) { executeCall(state, ki, f, arguments); } else { ref v = eval(ki, 0, state).value; -- cgit 1.4.1