Skip to content

Commit 75bf174

Browse files
authored
feat: Reintroduce concrete store (#197)
1 parent 6e2c242 commit 75bf174

File tree

5 files changed

+283
-71
lines changed

5 files changed

+283
-71
lines changed

lib/Core/AddressSpace.cpp

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "klee/Statistics/TimerStatIncrementer.h"
1919

2020
#include "CoreStats.h"
21+
#include <cstring>
2122

2223
namespace klee {
2324
llvm::cl::OptionCategory
@@ -384,15 +385,15 @@ bool AddressSpace::resolve(ExecutionState &state, TimingSolver *solver,
384385
// transparently avoid screwing up symbolics (if the byte is symbolic
385386
// then its concrete cache byte isn't being used) but is just a hack.
386387

387-
void AddressSpace::copyOutConcretes(const Assignment &assignment) {
388+
void AddressSpace::copyOutConcretes() {
388389
for (const auto &object : objects) {
389390
auto &mo = object.first;
390391
auto &os = object.second;
391392
if (ref<ConstantExpr> sizeExpr =
392393
dyn_cast<ConstantExpr>(mo->getSizeExpr())) {
393394
if (!mo->isUserSpecified && !os->readOnly &&
394395
sizeExpr->getZExtValue() != 0) {
395-
copyOutConcrete(mo, os.get(), assignment);
396+
copyOutConcrete(mo, os.get());
396397
}
397398
}
398399
}
@@ -407,27 +408,19 @@ ref<ConstantExpr> toConstantExpr(ref<Expr> expr) {
407408
}
408409

409410
void AddressSpace::copyOutConcrete(const MemoryObject *mo,
410-
const ObjectState *os,
411-
const Assignment &assignment) const {
412-
if (ref<ConstantExpr> addressExpr =
413-
dyn_cast<ConstantExpr>(mo->getBaseExpr())) {
414-
auto address =
415-
reinterpret_cast<std::uint8_t *>(addressExpr->getZExtValue());
416-
AssignmentEvaluator evaluator(assignment, false);
417-
if (ref<ConstantExpr> sizeExpr =
418-
dyn_cast<ConstantExpr>(mo->getSizeExpr())) {
419-
size_t moSize = sizeExpr->getZExtValue();
420-
std::vector<uint8_t> concreteStore(moSize);
421-
for (size_t i = 0; i < moSize; i++) {
422-
auto byte = evaluator.visit(os->readValue8(i));
423-
concreteStore[i] = cast<ConstantExpr>(byte)->getZExtValue(Expr::Int8);
424-
}
425-
std::memcpy(address, concreteStore.data(), moSize);
411+
const ObjectState *os) const {
412+
413+
if (auto addressExpr = dyn_cast<ConstantExpr>(mo->getBaseExpr())) {
414+
if (auto sizeExpr = dyn_cast<ConstantExpr>(mo->getSizeExpr())) {
415+
auto address =
416+
reinterpret_cast<std::uint8_t *>(addressExpr->getZExtValue());
417+
auto size = sizeExpr->getZExtValue();
418+
std::memcpy(address, os->valueOS.concreteStore->data(), size);
426419
}
427420
}
428421
}
429422

430-
bool AddressSpace::copyInConcretes(const Assignment &assignment) {
423+
bool AddressSpace::copyInConcretes() {
431424
for (auto &obj : objects) {
432425
const MemoryObject *mo = obj.first;
433426

@@ -436,8 +429,7 @@ bool AddressSpace::copyInConcretes(const Assignment &assignment) {
436429

437430
if (ref<ConstantExpr> arrayConstantAddress =
438431
dyn_cast<ConstantExpr>(mo->getBaseExpr())) {
439-
if (!copyInConcrete(mo, os.get(), arrayConstantAddress->getZExtValue(),
440-
assignment))
432+
if (!copyInConcrete(mo, os.get(), arrayConstantAddress->getZExtValue()))
441433
return false;
442434
}
443435
}
@@ -447,24 +439,17 @@ bool AddressSpace::copyInConcretes(const Assignment &assignment) {
447439
}
448440

449441
bool AddressSpace::copyInConcrete(const MemoryObject *mo, const ObjectState *os,
450-
uint64_t src_address,
451-
const Assignment &assignment) {
452-
AssignmentEvaluator evaluator(assignment, false);
442+
uint64_t src_address) {
453443
auto address = reinterpret_cast<std::uint8_t *>(src_address);
454-
size_t moSize =
455-
cast<ConstantExpr>(evaluator.visit(mo->getSizeExpr()))->getZExtValue();
456-
std::vector<uint8_t> concreteStore(moSize);
457-
for (size_t i = 0; i < moSize; i++) {
458-
auto byte = evaluator.visit(os->readValue8(i));
459-
concreteStore[i] = cast<ConstantExpr>(byte)->getZExtValue(8);
460-
}
461-
if (memcmp(address, concreteStore.data(), moSize) != 0) {
444+
size_t moSize = cast<ConstantExpr>(mo->getSizeExpr())->getZExtValue();
445+
446+
if (memcmp(address, os->valueOS.concreteStore->data(), moSize) != 0) {
462447
if (os->readOnly) {
463448
return false;
464449
} else {
465450
ObjectState *wos = getWriteable(mo, os);
466451
for (size_t i = 0; i < moSize; i++) {
467-
wos->write(i, ConstantExpr::create(address[i], Expr::Int8));
452+
wos->write8(i, address[i]);
468453
}
469454
}
470455
}

lib/Core/AddressSpace.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include "Memory.h"
1414

1515
#include "klee/ADT/ImmutableMap.h"
16-
#include "klee/Expr/Assignment.h"
1716
#include "klee/Expr/Expr.h"
1817
#include "klee/System/Time.h"
1918

@@ -139,10 +138,9 @@ class AddressSpace {
139138
/// actual system memory location they were allocated at.
140139
/// Returns the (hypothetical) number of pages needed provided each written
141140
/// object occupies (at least) a single page.
142-
void copyOutConcretes(const Assignment &assignment);
141+
void copyOutConcretes();
143142

144-
void copyOutConcrete(const MemoryObject *mo, const ObjectState *os,
145-
const Assignment &assignment) const;
143+
void copyOutConcrete(const MemoryObject *mo, const ObjectState *os) const;
146144

147145
/// \brief Obtain an ObjectState suitable for writing.
148146
///
@@ -164,7 +162,7 @@ class AddressSpace {
164162
///
165163
/// \retval true The copy succeeded.
166164
/// \retval false The copy failed because a read-only object was modified.
167-
bool copyInConcretes(const Assignment &assignment);
165+
bool copyInConcretes();
168166

169167
/// Updates the memory object with the raw memory from the address
170168
///
@@ -175,7 +173,7 @@ class AddressSpace {
175173
/// externally
176174
/// @return
177175
bool copyInConcrete(const MemoryObject *mo, const ObjectState *os,
178-
uint64_t src_address, const Assignment &assignment);
176+
uint64_t src_address);
179177
};
180178
} // namespace klee
181179

lib/Core/Executor.cpp

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,7 +1140,7 @@ void Executor::initializeGlobalObjects(ExecutionState &state) {
11401140
if (v.isConstant()) {
11411141
os->setReadOnly(true);
11421142
// initialise constant memory that may be used with external calls
1143-
state.addressSpace.copyOutConcrete(mo, os, {});
1143+
state.addressSpace.copyOutConcrete(mo, os);
11441144
}
11451145
}
11461146
}
@@ -5252,15 +5252,31 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target,
52525252
// uniqueness
52535253
ref<Expr> arg = *ai;
52545254
if (auto pointer = dyn_cast<PointerExpr>(arg)) {
5255-
arg = pointer->getValue();
5256-
}
5257-
arg = optimizer.optimizeExpr(arg, true);
5258-
ref<ConstantExpr> ce = evaluator.visit(arg);
5259-
ce->toMemory(&args[wordIndex]);
5260-
if (ExternalCalls == ExternalCallPolicy::All) {
5261-
addConstraint(state, EqExpr::create(ce, arg));
5255+
ref<ConstantExpr> base = evaluator.visit(pointer->getBase());
5256+
ref<ConstantExpr> value = evaluator.visit(pointer->getValue());
5257+
value->toMemory(&args[wordIndex]);
5258+
ref<ConstantPointerExpr> const_pointer =
5259+
ConstantPointerExpr::create(base, value);
5260+
ObjectPair op;
5261+
if (state.addressSpace.resolveOne(const_pointer, op) &&
5262+
!op.second->readOnly) {
5263+
auto *os = state.addressSpace.getWriteable(op.first, op.second);
5264+
os->flushToConcreteStore(model);
5265+
}
5266+
if (ExternalCalls == ExternalCallPolicy::All) {
5267+
addConstraint(state,
5268+
EqExpr::create(const_pointer->getValue(), arg));
5269+
}
5270+
wordIndex += (value->getWidth() + 63) / 64;
5271+
} else {
5272+
arg = optimizer.optimizeExpr(arg, true);
5273+
ref<ConstantExpr> ce = evaluator.visit(arg);
5274+
ce->toMemory(&args[wordIndex]);
5275+
if (ExternalCalls == ExternalCallPolicy::All) {
5276+
addConstraint(state, EqExpr::create(ce, arg));
5277+
}
5278+
wordIndex += (ce->getWidth() + 63) / 64;
52625279
}
5263-
wordIndex += (ce->getWidth() + 63) / 64;
52645280
} else {
52655281
ref<Expr> arg = toUnique(state, *ai);
52665282
if (ConstantExpr *ce = dyn_cast<ConstantExpr>(arg)) {
@@ -5296,7 +5312,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target,
52965312
solver->getInitialValues(state.constraints.cs(), arrays, values,
52975313
state.queryMetaData);
52985314
Assignment assignment(arrays, values);
5299-
state.addressSpace.copyOutConcretes(assignment);
5315+
state.addressSpace.copyOutConcretes();
53005316
#ifndef WINDOWS
53015317
// Update external errno state with local state value
53025318
ObjectPair result;
@@ -5364,7 +5380,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target,
53645380
return;
53655381
}
53665382

5367-
if (!state.addressSpace.copyInConcretes(assignment)) {
5383+
if (!state.addressSpace.copyInConcretes()) {
53685384
terminateStateOnExecError(state, "external modified read-only object",
53695385
StateTerminationType::External);
53705386
return;
@@ -5374,7 +5390,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target,
53745390
// Update errno memory object with the errno value from the call
53755391
int error = externalDispatcher->getLastErrno();
53765392
state.addressSpace.copyInConcrete(result.first, result.second,
5377-
(uint64_t)&error, assignment);
5393+
(uint64_t)&error);
53785394
#endif
53795395

53805396
Type *resultType = target->inst()->getType();

0 commit comments

Comments
 (0)