23#include "llvm/IR/Function.h"
24#include "llvm/IR/Instruction.h"
25#include "llvm/IR/Value.h"
26#include "llvm/Support/CommandLine.h"
27#include "llvm/Support/raw_ostream.h"
37 UseConstantArrays(
"use-constant-arrays",
38 cl::desc(
"Use constant arrays instead of updates when possible (default=true)\n"),
45int MemoryObject::counter = 0;
47MemoryObject::~MemoryObject() {
53 llvm::raw_string_ostream info(result);
55 info <<
"MO" <<
id <<
"[" <<
size <<
"]";
58 info <<
" allocated at ";
59 if (
const Instruction *i = dyn_cast<Instruction>(
allocSite)) {
60 info << i->getParent()->getParent()->getName() <<
"():";
62 }
else if (
const GlobalValue *gv = dyn_cast<GlobalValue>(
allocSite)) {
63 info <<
"global:" << gv->getName();
68 info <<
" (no allocation info)";
77 : copyOnWriteOwner(0),
79 concreteStore(new uint8_t[mo->size]),
80 concreteMask(nullptr),
81 knownSymbolics(nullptr),
82 unflushedMask(nullptr),
83 updates(nullptr, nullptr),
86 if (!UseConstantArrays) {
87 static unsigned id = 0;
97 : copyOnWriteOwner(0),
99 concreteStore(new uint8_t[mo->size]),
100 concreteMask(nullptr),
101 knownSymbolics(nullptr),
102 unflushedMask(nullptr),
103 updates(array, nullptr),
111 : copyOnWriteOwner(0),
113 concreteStore(new uint8_t[os.size]),
114 concreteMask(os.concreteMask ? new
BitArray(*os.concreteMask, os.size) : nullptr),
115 knownSymbolics(nullptr),
116 unflushedMask(os.unflushedMask ? new
BitArray(*os.unflushedMask, os.size) : nullptr),
120 assert(!os.
readOnly &&
"no need to copy read only object?");
123 for (
unsigned i=0; i<
size; i++)
138 assert(
object &&
"object was NULL");
139 return object->parent->getArrayCache();
153 std::vector< std::pair< ref<Expr>,
ref<Expr> > > Writes(NumWrites);
155 for (
unsigned i = NumWrites; i != 0; un = un->next.get()) {
157 Writes[i] = std::make_pair(un->index, un->value);
160 std::vector< ref<ConstantExpr> > Contents(
size);
163 for (
unsigned i = 0, e =
size; i != e; ++i)
167 unsigned Begin = 0, End = Writes.size();
168 for (; Begin != End; ++Begin) {
170 ConstantExpr *Index = dyn_cast<ConstantExpr>(Writes[Begin].first);
174 ConstantExpr *Value = dyn_cast<ConstantExpr>(Writes[Begin].second);
181 static unsigned id = 0;
183 "const_arr" + llvm::utostr(++
id),
size, &Contents[0],
184 &Contents[0] + Contents.size());
188 for (; Begin != End; ++Begin)
197 for (
unsigned i = 0; i <
size; i++) {
203 klee_warning(
"Solver timed out when getting a value for external call, "
204 "byte %p+%u will have random value",
205 (
void *)
object->address, i);
223 "XXX makeSymbolic of objects with symbolic values is unsupported");
226 for (
unsigned i=0; i<
size; i++) {
240 for (
unsigned i=0; i<
size; i++) {
256 unsigned *size_r)
const {
262 unsigned rangeSize)
const {
266 for (
unsigned offset = rangeBase; offset < rangeBase + rangeSize; offset++) {
273 "invalid bit set in unflushedMask");
287 for (
unsigned offset = rangeBase; offset < rangeBase + rangeSize; offset++) {
295 "invalid bit set in unflushedMask");
370 assert(!
isByteUnflushed(offset) &&
"unflushed byte without cache value");
378 assert(!isa<ConstantExpr>(offset) &&
"constant offset passed to symbolic read8");
384 std::string allocInfo;
385 object->getAllocInfo(allocInfo);
406 write8(offset, (uint8_t) CE->getZExtValue(8));
416 assert(!isa<ConstantExpr>(offset) &&
"constant offset passed to symbolic write8");
422 std::string allocInfo;
423 object->getAllocInfo(allocInfo);
440 return read(CE->getZExtValue(32), width);
447 unsigned NumBytes = width / 8;
448 assert(width == NumBytes * 8 &&
"Invalid read size!");
450 for (
unsigned i = 0; i != NumBytes; ++i) {
467 unsigned NumBytes = width / 8;
468 assert(width == NumBytes * 8 &&
"Invalid width for read size!");
470 for (
unsigned i = 0; i != NumBytes; ++i) {
484 if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(offset)) {
485 write(CE->getZExtValue(32), value);
497 unsigned NumBytes = w / 8;
498 assert(w == NumBytes * 8 &&
"Invalid write size!");
499 for (
unsigned i = 0; i != NumBytes; ++i) {
511 uint64_t val = CE->getZExtValue();
513 default: assert(0 &&
"Invalid write size!");
531 unsigned NumBytes = w / 8;
532 assert(w == NumBytes * 8 &&
"Invalid write size!");
533 for (
unsigned i = 0; i != NumBytes; ++i) {
540 unsigned NumBytes = 2;
541 for (
unsigned i = 0; i != NumBytes; ++i) {
543 write8(offset + idx, (uint8_t) (value >> (8 * i)));
548 unsigned NumBytes = 4;
549 for (
unsigned i = 0; i != NumBytes; ++i) {
551 write8(offset + idx, (uint8_t) (value >> (8 * i)));
556 unsigned NumBytes = 8;
557 for (
unsigned i = 0; i != NumBytes; ++i) {
559 write8(offset + idx, (uint8_t) (value >> (8 * i)));
564 llvm::errs() <<
"-- ObjectState --\n";
565 llvm::errs() <<
"\tMemoryObject ID: " <<
object->id <<
"\n";
566 llvm::errs() <<
"\tRoot Object: " <<
updates.
root <<
"\n";
567 llvm::errs() <<
"\tSize: " <<
size <<
"\n";
569 llvm::errs() <<
"\tBytes:\n";
570 for (
unsigned i=0; i<
size; i++) {
571 llvm::errs() <<
"\t\t["<<i<<
"]"
576 llvm::errs() << e <<
"\n";
579 llvm::errs() <<
"\tUpdates:\n";
580 for (
const auto *un =
updates.
head.get(); un; un = un->next.get()) {
581 llvm::errs() <<
"\t\t[" << un->index <<
"] = " << un->value <<
"\n";
Provides an interface for creating and destroying Array objects.
const Array * CreateArray(const std::string &_name, uint64_t _size, const ref< ConstantExpr > *constantValuesBegin=0, const ref< ConstantExpr > *constantValuesEnd=0, Expr::Width _domain=Expr::Int32, Expr::Width _range=Expr::Int8)
Create an Array object.
static ref< Expr > create(const ref< Expr > &l, const ref< Expr > &r)
static ref< ConstantExpr > create(uint64_t v, Width w)
uint64_t getZExtValue(unsigned bits=64) const
bool isLittleEndian() const
static const Context & get()
get - Return the global singleton instance of the Context.
ExecutionState representing a path under exploration.
SolverQueryMetaData queryMetaData
Statistics and information.
ConstraintSet constraints
Constraints collected so far.
Class representing symbolic expressions.
virtual Width getWidth() const =0
unsigned Width
The type of an expression is simply its width, in bits.
void markFreed(MemoryObject *mo)
unsigned size
size in bytes
void getAllocInfo(std::string &result) const
Get an identifying string for this allocation.
const llvm::Value * allocSite
ref< Expr > read8(unsigned offset) const
void initializeToZero()
Make contents all concrete and zero.
ref< Expr > read(ref< Expr > offset, Expr::Width width) const
void flushRangeForRead(unsigned rangeBase, unsigned rangeSize) const
void markByteConcrete(unsigned offset)
void write64(unsigned offset, uint64_t value)
ref< const MemoryObject > object
void write8(unsigned offset, uint8_t value)
ArrayCache * getArrayCache() const
void initializeToRandom()
Make contents all concrete and random.
void setKnownSymbolic(unsigned offset, Expr *value)
const UpdateList & getUpdates() const
void write16(unsigned offset, uint16_t value)
void flushRangeForWrite(unsigned rangeBase, unsigned rangeSize)
void markByteFlushed(unsigned offset)
void write(unsigned offset, ref< Expr > value)
void markByteSymbolic(unsigned offset)
void markByteUnflushed(unsigned offset)
bool isByteConcrete(unsigned offset) const
isByteConcrete ==> !isByteKnownSymbolic
void fastRangeCheckOffset(ref< Expr > offset, unsigned *base_r, unsigned *size_r) const
void write32(unsigned offset, uint32_t value)
uint8_t * concreteStore
Holds all known concrete bytes.
bool isByteUnflushed(unsigned offset) const
isByteUnflushed(i) => (isByteConcrete(i) || isByteKnownSymbolic(i))
ObjectState(const MemoryObject *mo)
void flushToConcreteStore(TimingSolver *solver, const ExecutionState &state) const
BitArray * concreteMask
concreteMask[byte] is set if byte is known to be concrete
bool isByteKnownSymbolic(unsigned offset) const
isByteKnownSymbolic ==> !isByteConcrete
ref< Expr > * knownSymbolics
static ref< Expr > create(const UpdateList &updates, ref< Expr > i)
bool getValue(const ConstraintSet &, ref< Expr > expr, ref< ConstantExpr > &result, SolverQueryMetaData &metaData)
Class representing a complete list of updates into an array.
void extend(const ref< Expr > &index, const ref< Expr > &value)
ref< UpdateNode > head
pointer to the most recent update node
uint64_t isPowerOfTwo(uint64_t x)
llvm::cl::OptionCategory SolvingCat
void void void void klee_warning_once(const void *id, const char *msg,...) __attribute__((format(printf
void void void klee_warning(const char *msg,...) __attribute__((format(printf