From 17ec611bb5ada13350a72f2e1de439499128c62f Mon Sep 17 00:00:00 2001 From: Martin Nowack Date: Wed, 13 Nov 2013 23:53:46 +0100 Subject: Allow to specify KLEE-internal functions KLEE provides runtime library functions to do detection of bugs (e.g. overflow). This runtime functions are not the location of the bugs but it is the next non-runtime library function from the stack. Use the caller inside that function to indicate where the bug is. --- lib/Core/Executor.cpp | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'lib/Core/Executor.cpp') diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index ef55f21f..f01fa4ee 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -2729,16 +2729,54 @@ void Executor::terminateStateOnExit(ExecutionState &state) { terminateState(state); } +const InstructionInfo & Executor::getLastNonKleeInternalInstruction(const ExecutionState &state, + Instruction ** lastInstruction) { + // unroll the stack of the applications state and find + // the last instruction which is not inside a KLEE internal function + ExecutionState::stack_ty::const_reverse_iterator it = state.stack.rbegin(), + itE = state.stack.rend(); + + // don't check beyond the outermost function (i.e. main()) + itE--; + + const InstructionInfo * ii = 0; + if (kmodule->internalFunctions.count(it->kf->function) == 0){ + ii = state.prevPC->info; + *lastInstruction = state.prevPC->inst; + } + + // wind up the stack and check if we are in a KLEE internal function + for (;it != itE; ++it) { + // check calling instruction and if it is contained in a KLEE internal function + const Function * f = (*it->caller).inst->getParent()->getParent(); + if (kmodule->internalFunctions.count(f)){ + ii = 0; + continue; + } + if (!ii){ + ii = (*it->caller).info; + *lastInstruction = (*it->caller).inst; + } + } + + if (!ii) { + // something went wrong, play safe and return the current instruction info + *lastInstruction = state.prevPC->inst; + return *state.prevPC->info; + } + return *ii; +} void Executor::terminateStateOnError(ExecutionState &state, const llvm::Twine &messaget, const char *suffix, const llvm::Twine &info) { std::string message = messaget.str(); static std::set< std::pair > emittedErrors; - const InstructionInfo &ii = *state.prevPC->info; + Instruction * lastInst; + const InstructionInfo &ii = getLastNonKleeInternalInstruction(state, &lastInst); if (EmitAllErrors || - emittedErrors.insert(std::make_pair(state.prevPC->inst, message)).second) { + emittedErrors.insert(std::make_pair(lastInst, message)).second) { if (ii.file != "") { klee_message("ERROR: %s:%d: %s", ii.file.c_str(), ii.line, message.c_str()); } else { -- cgit 1.4.1 From 92a6ba10d2c125f5301613369a0f17856e637808 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Wed, 11 Dec 2013 16:39:35 +0000 Subject: If error location information is missing be explicit about it. This is more helpful because often the next message is "Now ignoring error at this location". Which is slightly confusing when no location is shown. --- lib/Core/Executor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/Core/Executor.cpp') diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index f01fa4ee..371aa7f1 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -2780,7 +2780,7 @@ void Executor::terminateStateOnError(ExecutionState &state, if (ii.file != "") { klee_message("ERROR: %s:%d: %s", ii.file.c_str(), ii.line, message.c_str()); } else { - klee_message("ERROR: %s", message.c_str()); + klee_message("ERROR: (location information missing) %s", message.c_str()); } if (!EmitAllErrors) klee_message("NOTE: now ignoring this error at this location"); -- cgit 1.4.1 From cca3536a76d877c5441e54e093a5808cd05c4f86 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Wed, 11 Dec 2013 16:45:42 +0000 Subject: When writing stack traces for bugs write the location in the assembly.ll file as well. --- lib/Core/Executor.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/Core/Executor.cpp') diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 371aa7f1..767a5602 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -2790,6 +2790,7 @@ void Executor::terminateStateOnError(ExecutionState &state, if (ii.file != "") { msg << "File: " << ii.file << "\n"; msg << "Line: " << ii.line << "\n"; + msg << "assembly.ll line: " << ii.assemblyLine << "\n"; } msg << "Stack: \n"; state.dumpStack(msg); -- cgit 1.4.1 From 5b2dcbbcf91062e463a040d58302706c612f03bd Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Fri, 13 Dec 2013 19:07:30 +0000 Subject: Added a few comments to Executor::getLastNonKleeInternalInstruction() emphasising that the function cannot be returned from early. --- lib/Core/Executor.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib/Core/Executor.cpp') diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 767a5602..bf672bb7 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -2743,9 +2743,14 @@ const InstructionInfo & Executor::getLastNonKleeInternalInstruction(const Execut if (kmodule->internalFunctions.count(it->kf->function) == 0){ ii = state.prevPC->info; *lastInstruction = state.prevPC->inst; + // Cannot return yet because even though + // it->function is not an internal function it might of + // been called from an internal function. } - // wind up the stack and check if we are in a KLEE internal function + // Wind up the stack and check if we are in a KLEE internal function. + // We visit the entire stack because we want to return a CallInstruction + // that was not reached via any KLEE internal functions. for (;it != itE; ++it) { // check calling instruction and if it is contained in a KLEE internal function const Function * f = (*it->caller).inst->getParent()->getParent(); -- cgit 1.4.1