aboutsummaryrefslogtreecommitdiffhomepage
path: root/lib/Solver
diff options
context:
space:
mode:
authorFrank Busse <bb0xfb@gmail.com>2019-01-23 00:29:08 +0000
committerCristian Cadar <c.cadar@imperial.ac.uk>2019-03-20 19:15:35 +0000
commit8234aca4486e03b887ee9bec9bf192339cb4b2ff (patch)
tree7e5505849ef22e0380c5e2090af49fd7bb60feb9 /lib/Solver
parente4cfe53809f4bd06a7fa91b9936e454b921c0b9d (diff)
downloadklee-8234aca4486e03b887ee9bec9bf192339cb4b2ff.tar.gz
STPSolver: C++11, add missing free, refactoring
Diffstat (limited to 'lib/Solver')
-rw-r--r--lib/Solver/STPSolver.cpp182
1 files changed, 85 insertions, 97 deletions
diff --git a/lib/Solver/STPSolver.cpp b/lib/Solver/STPSolver.cpp
index b058a9cb..e8b9222f 100644
--- a/lib/Solver/STPSolver.cpp
+++ b/lib/Solver/STPSolver.cpp
@@ -7,27 +7,25 @@
//
//===----------------------------------------------------------------------===//
#include "klee/Config/config.h"
+
#ifdef ENABLE_STP
-#include "STPSolver.h"
#include "STPBuilder.h"
-#include "klee/Solver.h"
-#include "klee/SolverImpl.h"
+#include "STPSolver.h"
#include "klee/Constraints.h"
-#include "klee/Internal/Support/ErrorHandling.h"
#include "klee/OptionCategories.h"
+#include "klee/SolverImpl.h"
+#include "klee/Internal/Support/ErrorHandling.h"
#include "klee/util/Assignment.h"
#include "klee/util/ExprUtil.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Errno.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <errno.h>
+#include <csignal>
#include <unistd.h>
-#include <signal.h>
-#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
+#include <sys/wait.h>
namespace {
@@ -44,7 +42,7 @@ llvm::cl::opt<bool> IgnoreSolverFailures(
#define vc_bvBoolExtract IAMTHESPAWNOFSATAN
-static unsigned char *shared_memory_ptr;
+static unsigned char *shared_memory_ptr = nullptr;
static int shared_memory_id = 0;
// Darwin by default has a very small limit on the maximum amount of shared
// memory, which will quickly be exhausted by KLEE running its tests in
@@ -73,25 +71,25 @@ private:
SolverRunStatus runStatusCode;
public:
- STPSolverImpl(bool _useForkedSTP, bool _optimizeDivides = true);
- ~STPSolverImpl();
+ explicit STPSolverImpl(bool useForkedSTP, bool optimizeDivides = true);
+ ~STPSolverImpl() override;
- char *getConstraintLog(const Query &);
- void setCoreSolverTimeout(time::Span timeout) { this->timeout = timeout; }
+ char *getConstraintLog(const Query &) override;
+ void setCoreSolverTimeout(time::Span timeout) override { this->timeout = timeout; }
- bool computeTruth(const Query &, bool &isValid);
- bool computeValue(const Query &, ref<Expr> &result);
+ bool computeTruth(const Query &, bool &isValid) override;
+ bool computeValue(const Query &, ref<Expr> &result) override;
bool computeInitialValues(const Query &,
const std::vector<const Array *> &objects,
- std::vector<std::vector<unsigned char> > &values,
- bool &hasSolution);
- SolverRunStatus getOperationStatusCode();
+ std::vector<std::vector<unsigned char>> &values,
+ bool &hasSolution) override;
+ SolverRunStatus getOperationStatusCode() override;
};
-STPSolverImpl::STPSolverImpl(bool _useForkedSTP, bool _optimizeDivides)
+STPSolverImpl::STPSolverImpl(bool useForkedSTP, bool optimizeDivides)
: vc(vc_createValidityChecker()),
- builder(new STPBuilder(vc, _optimizeDivides)),
- useForkedSTP(_useForkedSTP), runStatusCode(SOLVER_RUN_STATUS_FAILURE) {
+ builder(new STPBuilder(vc, optimizeDivides)),
+ useForkedSTP(useForkedSTP), runStatusCode(SOLVER_RUN_STATUS_FAILURE) {
assert(vc && "unable to create validity checker");
assert(builder && "unable to create STPBuilder");
@@ -113,17 +111,17 @@ STPSolverImpl::STPSolverImpl(bool _useForkedSTP, bool _optimizeDivides)
shmget(IPC_PRIVATE, shared_memory_size, IPC_CREAT | 0700);
if (shared_memory_id < 0)
llvm::report_fatal_error("unable to allocate shared memory region");
- shared_memory_ptr = (unsigned char *)shmat(shared_memory_id, NULL, 0);
+ shared_memory_ptr = (unsigned char *)shmat(shared_memory_id, nullptr, 0);
if (shared_memory_ptr == (void *)-1)
llvm::report_fatal_error("unable to attach shared memory region");
- shmctl(shared_memory_id, IPC_RMID, NULL);
+ shmctl(shared_memory_id, IPC_RMID, nullptr);
}
}
STPSolverImpl::~STPSolverImpl() {
// Detach the memory region.
shmdt(shared_memory_ptr);
- shared_memory_ptr = 0;
+ shared_memory_ptr = nullptr;
shared_memory_id = 0;
delete builder;
@@ -135,10 +133,9 @@ STPSolverImpl::~STPSolverImpl() {
char *STPSolverImpl::getConstraintLog(const Query &query) {
vc_push(vc);
- for (std::vector<ref<Expr> >::const_iterator it = query.constraints.begin(),
- ie = query.constraints.end();
- it != ie; ++it)
- vc_assertFormula(vc, builder->construct(*it));
+
+ for (const auto &constraint : query.constraints)
+ vc_assertFormula(vc, builder->construct(constraint));
assert(query.expr == ConstantExpr::alloc(0, Expr::Bool) &&
"Unexpected expression in query!");
@@ -152,7 +149,7 @@ char *STPSolverImpl::getConstraintLog(const Query &query) {
bool STPSolverImpl::computeTruth(const Query &query, bool &isValid) {
std::vector<const Array *> objects;
- std::vector<std::vector<unsigned char> > values;
+ std::vector<std::vector<unsigned char>> values;
bool hasSolution;
if (!computeInitialValues(query, objects, values, hasSolution))
@@ -164,7 +161,7 @@ bool STPSolverImpl::computeTruth(const Query &query, bool &isValid) {
bool STPSolverImpl::computeValue(const Query &query, ref<Expr> &result) {
std::vector<const Array *> objects;
- std::vector<std::vector<unsigned char> > values;
+ std::vector<std::vector<unsigned char>> values;
bool hasSolution;
// Find the object used in the expression, and compute an assignment
@@ -184,36 +181,28 @@ bool STPSolverImpl::computeValue(const Query &query, ref<Expr> &result) {
static SolverImpl::SolverRunStatus
runAndGetCex(::VC vc, STPBuilder *builder, ::VCExpr q,
const std::vector<const Array *> &objects,
- std::vector<std::vector<unsigned char> > &values,
+ std::vector<std::vector<unsigned char>> &values,
bool &hasSolution) {
// XXX I want to be able to timeout here, safely
hasSolution = !vc_query(vc, q);
- if (hasSolution) {
- values.reserve(objects.size());
- for (std::vector<const Array *>::const_iterator it = objects.begin(),
- ie = objects.end();
- it != ie; ++it) {
- const Array *array = *it;
- std::vector<unsigned char> data;
-
- data.reserve(array->size);
- for (unsigned offset = 0; offset < array->size; offset++) {
- ExprHandle counter =
- vc_getCounterExample(vc, builder->getInitialRead(array, offset));
- unsigned char val = getBVUnsigned(counter);
- data.push_back(val);
- }
+ if (!hasSolution)
+ return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE;
+
+ values.reserve(objects.size());
+ unsigned i = 0; // FIXME C++17: use reference from emplace_back()
+ for (const auto object : objects) {
+ values.emplace_back(object->size);
- values.push_back(data);
+ for (unsigned offset = 0; offset < object->size; offset++) {
+ ExprHandle counter =
+ vc_getCounterExample(vc, builder->getInitialRead(object, offset));
+ values[i][offset] = static_cast<unsigned char>(getBVUnsigned(counter));
}
+ ++i;
}
- if (true == hasSolution) {
- return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE;
- } else {
- return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE;
- }
+ return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE;
}
static void stpTimeoutHandler(int x) { _exit(52); }
@@ -221,47 +210,46 @@ static void stpTimeoutHandler(int x) { _exit(52); }
static SolverImpl::SolverRunStatus
runAndGetCexForked(::VC vc, STPBuilder *builder, ::VCExpr q,
const std::vector<const Array *> &objects,
- std::vector<std::vector<unsigned char> > &values,
+ std::vector<std::vector<unsigned char>> &values,
bool &hasSolution, time::Span timeout) {
unsigned char *pos = shared_memory_ptr;
unsigned sum = 0;
- for (std::vector<const Array *>::const_iterator it = objects.begin(),
- ie = objects.end();
- it != ie; ++it)
- sum += (*it)->size;
+ for (const auto object : objects)
+ sum += object->size;
if (sum >= shared_memory_size)
llvm::report_fatal_error("not enough shared memory for counterexample");
fflush(stdout);
fflush(stderr);
+
+ // fork solver
int pid = fork();
+ // - error
if (pid == -1) {
klee_warning("fork failed (for STP) - %s", llvm::sys::StrError(errno).c_str());
if (!IgnoreSolverFailures)
exit(1);
return SolverImpl::SOLVER_RUN_STATUS_FORK_FAILED;
}
-
+ // - child (solver)
if (pid == 0) {
if (timeout) {
::alarm(0); /* Turn off alarm so we can safely set signal handler */
::signal(SIGALRM, stpTimeoutHandler);
::alarm(std::max(1u, static_cast<unsigned>(timeout.toSeconds())));
}
- unsigned res = vc_query(vc, q);
+ int res = vc_query(vc, q);
if (!res) {
- for (std::vector<const Array *>::const_iterator it = objects.begin(),
- ie = objects.end();
- it != ie; ++it) {
- const Array *array = *it;
- for (unsigned offset = 0; offset < array->size; offset++) {
+ for (const auto object : objects) {
+ for (unsigned offset = 0; offset < object->size; offset++) {
ExprHandle counter =
- vc_getCounterExample(vc, builder->getInitialRead(array, offset));
- *pos++ = getBVUnsigned(counter);
+ vc_getCounterExample(vc, builder->getInitialRead(object, offset));
+ *pos++ = static_cast<unsigned char>(getBVUnsigned(counter));
}
}
}
_exit(res);
+ // - parent
} else {
int status;
pid_t res;
@@ -290,53 +278,51 @@ runAndGetCexForked(::VC vc, STPBuilder *builder, ::VCExpr q,
}
int exitcode = WEXITSTATUS(status);
+
+ // solvable
if (exitcode == 0) {
hasSolution = true;
- } else if (exitcode == 1) {
- hasSolution = false;
- } else if (exitcode == 52) {
- klee_warning("STP timed out");
- // mark that a timeout occurred
- return SolverImpl::SOLVER_RUN_STATUS_TIMEOUT;
- } else {
- klee_warning("STP did not return a recognized code");
- if (!IgnoreSolverFailures)
- exit(1);
- return SolverImpl::SOLVER_RUN_STATUS_UNEXPECTED_EXIT_CODE;
- }
- if (hasSolution) {
- values = std::vector<std::vector<unsigned char> >(objects.size());
- unsigned i = 0;
- for (std::vector<const Array *>::const_iterator it = objects.begin(),
- ie = objects.end();
- it != ie; ++it) {
- const Array *array = *it;
- std::vector<unsigned char> &data = values[i++];
- data.insert(data.begin(), pos, pos + array->size);
- pos += array->size;
+ values.reserve(objects.size());
+ for (const auto object : objects) {
+ values.emplace_back(pos, pos + object->size);
+ pos += object->size;
}
- }
- if (true == hasSolution) {
return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE;
- } else {
+ }
+
+ // unsolvable
+ if (exitcode == 1) {
+ hasSolution = false;
return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE;
}
+
+ // timeout
+ if (exitcode == 52) {
+ klee_warning("STP timed out");
+ // mark that a timeout occurred
+ return SolverImpl::SOLVER_RUN_STATUS_TIMEOUT;
+ }
+
+ // unknown return code
+ klee_warning("STP did not return a recognized code");
+ if (!IgnoreSolverFailures)
+ exit(1);
+ return SolverImpl::SOLVER_RUN_STATUS_UNEXPECTED_EXIT_CODE;
}
}
+
bool STPSolverImpl::computeInitialValues(
const Query &query, const std::vector<const Array *> &objects,
- std::vector<std::vector<unsigned char> > &values, bool &hasSolution) {
+ std::vector<std::vector<unsigned char>> &values, bool &hasSolution) {
runStatusCode = SOLVER_RUN_STATUS_FAILURE;
TimerStatIncrementer t(stats::queryTime);
vc_push(vc);
- for (ConstraintManager::const_iterator it = query.constraints.begin(),
- ie = query.constraints.end();
- it != ie; ++it)
- vc_assertFormula(vc, builder->construct(*it));
+ for (const auto &constraint : query.constraints)
+ vc_assertFormula(vc, builder->construct(constraint));
++stats::queries;
++stats::queryCounterexamples;
@@ -348,6 +334,7 @@ bool STPSolverImpl::computeInitialValues(
unsigned long len;
vc_printQueryStateToBuffer(vc, stp_e, &buf, &len, false);
klee_warning("STP query:\n%.*s\n", (unsigned)len, buf);
+ free(buf);
}
bool success;
@@ -388,5 +375,6 @@ char *STPSolver::getConstraintLog(const Query &query) {
void STPSolver::setCoreSolverTimeout(time::Span timeout) {
impl->setCoreSolverTimeout(timeout);
}
-}
+
+} // klee
#endif // ENABLE_STP