diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2011-08-01 02:26:27 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2011-08-01 02:26:27 +0000 |
commit | 3c2bacc7a9fb95caef07d87d9b6220712b7d613f (patch) | |
tree | 7aee0c72179d88a3a7adf6f6984d962d9f9fba48 /lib | |
parent | 179a8930253e7e81dda77fda1db11a6d11b22f14 (diff) | |
download | klee-3c2bacc7a9fb95caef07d87d9b6220712b7d613f.tar.gz |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Core/Executor.cpp | 79 | ||||
-rw-r--r-- | lib/Core/Executor.h | 3 |
2 files changed, 50 insertions, 32 deletions
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<const GlobalValue*, 3> 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<Constant>(calledVal); + if (!c) + return 0; + + while (true) { + if (GlobalValue *gv = dyn_cast<GlobalValue>(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<Function>(gv)) + return f; + else if (GlobalAlias *ga = dyn_cast<GlobalAlias>(gv)) + c = ga->getAliasee(); + else + return 0; + } else if (llvm::ConstantExpr *ce = dyn_cast<llvm::ConstantExpr>(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<numArgs; ++j) arguments.push_back(eval(ki, j+1, state).value); - if (!f) { + if (f) { + const FunctionType *fType = + dyn_cast<FunctionType>(cast<PointerType>(f->getType())->getElementType()); + const FunctionType *fpType = + dyn_cast<FunctionType>(cast<PointerType>(fp->getType())->getElementType()); + // special case the call with a bitcast case - Value *fp = cs.getCalledValue(); - llvm::ConstantExpr *ce = dyn_cast<llvm::ConstantExpr>(fp); - - if (ce && ce->getOpcode()==Instruction::BitCast) { - f = dyn_cast<Function>(ce->getOperand(0)); - assert(f && "XXX unrecognized constant expression in call"); - const FunctionType *fType = - dyn_cast<FunctionType>(cast<PointerType>(f->getType())->getElementType()); - const FunctionType *ceType = - dyn_cast<FunctionType>(cast<PointerType>(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<Expr> v = eval(ki, 0, state).value; diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index 3df4cc88..a296051b 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -170,7 +170,8 @@ private: /// The maximum time to allow for a single stp query. double stpTimeout; - llvm::Function* getCalledFunction(llvm::CallSite &cs, ExecutionState &state); + llvm::Function* getTargetFunction(llvm::Value *calledVal, + ExecutionState &state); void executeInstruction(ExecutionState &state, KInstruction *ki); |