Skip to content

Commit

Permalink
[feat] Introduces KValue --- base class for all KLEEs wrappers around…
Browse files Browse the repository at this point in the history
… llvm::* structures (KInstruction, KConstant, etc.)

[feat] Model unsized globals as objects of symbolic size.
  • Loading branch information
S1eGa committed Dec 13, 2023
1 parent 54b0620 commit 5ae0e30
Show file tree
Hide file tree
Showing 34 changed files with 579 additions and 323 deletions.
2 changes: 2 additions & 0 deletions include/klee/Core/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class Context {

/// Returns width of the pointer in bits
Expr::Width getPointerWidth() const { return PointerWidth; }

Expr::Width getPointerWidthInBytes() const { return PointerWidth / CHAR_BIT; }
};

} // namespace klee
Expand Down
8 changes: 4 additions & 4 deletions include/klee/Expr/SourceBuilder.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#ifndef KLEE_SOURCEBUILDER_H
#define KLEE_SOURCEBUILDER_H

#include "klee/ADT/Ref.h"
#include "klee/ADT/SparseStorage.h"
#include "klee/Expr/SymbolicSource.h"
#include "klee/Module/KModule.h"

namespace klee {

template <typename T, typename Eq> class SparseStorage;
template <typename T> class ref;

class SourceBuilder {
public:
SourceBuilder() = delete;
Expand All @@ -18,7 +18,7 @@ class SourceBuilder {
static ref<SymbolicSource> uninitialized(unsigned version,
const KInstruction *allocSite);
static ref<SymbolicSource>
symbolicSizeConstantAddress(unsigned version, const KInstruction *allocSite,
symbolicSizeConstantAddress(unsigned version, const KValue *allocSite,
ref<Expr> size);
static ref<SymbolicSource> makeSymbolic(const std::string &name,
unsigned version);
Expand Down
8 changes: 5 additions & 3 deletions include/klee/Expr/SymbolicSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ namespace klee {
class Array;
class Expr;
class ConstantExpr;
struct KGlobalVariable;
class KModule;
struct KValue;
struct KInstruction;

class SymbolicSource {
Expand Down Expand Up @@ -125,10 +127,10 @@ class UninitializedSource : public SymbolicSource {
class SymbolicSizeConstantAddressSource : public SymbolicSource {
public:
const unsigned version;
const KInstruction *allocSite;
const KValue *allocSite;
ref<Expr> size;
SymbolicSizeConstantAddressSource(unsigned _version,
const KInstruction *_allocSite,

SymbolicSizeConstantAddressSource(unsigned _version, const KValue *_allocSite,
ref<Expr> _size)
: version(_version), allocSite(_allocSite), size(_size) {}

Expand Down
44 changes: 20 additions & 24 deletions include/klee/Module/KCallable.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,64 +12,60 @@

#include <string>

#include "klee/Module/KValue.h"
#include "klee/Support/CompilerWarning.h"
DISABLE_WARNING_PUSH
DISABLE_WARNING_DEPRECATED_DECLARATIONS
#include "llvm/ADT/Twine.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/Casting.h"
DISABLE_WARNING_POP

namespace klee {
/// Wrapper for callable objects passed in callExternalFunction
class KCallable {
public:
enum CallableKind { CK_Function, CK_InlineAsm };

private:
const CallableKind Kind;
class KCallable : public KValue {
protected:
KCallable(llvm::Value *value, KValue::Kind kind) : KValue(value, kind) {}

public:
KCallable(CallableKind Kind) : Kind(Kind) {}

CallableKind getKind() const { return Kind; }

virtual llvm::StringRef getName() const = 0;
virtual llvm::FunctionType *getFunctionType() const = 0;
virtual llvm::Value *getValue() = 0;

virtual ~KCallable() = default;
static bool classof(const KValue *rhs) {
return rhs->getKind() == KValue::Kind::FUNCTION ||
rhs->getKind() == KValue::Kind::INLINE_ASM;
}
};

class KInlineAsm : public KCallable {
private:
/* Prepared name of ASM code */
std::string name;

static unsigned getFreshAsmId() {
static unsigned globalId = 0;
return globalId++;
}

llvm::InlineAsm *value;
std::string name;

public:
KInlineAsm(llvm::InlineAsm *value)
: KCallable(CK_InlineAsm), value(value),
KInlineAsm(llvm::InlineAsm *inlineAsm)
: KCallable(inlineAsm, KValue::Kind::INLINE_ASM),
name("__asm__" + llvm::Twine(getFreshAsmId()).str()) {}

llvm::StringRef getName() const override { return name; }

llvm::FunctionType *getFunctionType() const override {
return value->getFunctionType();
return inlineAsm()->getFunctionType();
}

llvm::Value *getValue() override { return value; }

static bool classof(const KCallable *callable) {
return callable->getKind() == CK_InlineAsm;
static bool classof(const KValue *rhs) {
return rhs->getKind() == KValue::Kind::INLINE_ASM;
}

llvm::InlineAsm *getInlineAsm() { return value; }
[[nodiscard]] llvm::InlineAsm *inlineAsm() const {
return llvm::dyn_cast<llvm::InlineAsm>(value);
}
};

} // namespace klee
Expand Down
24 changes: 19 additions & 5 deletions include/klee/Module/KInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#define KLEE_KINSTRUCTION_H

#include "KModule.h"
#include "KValue.h"

#include "klee/Config/Version.h"
#include "klee/Support/CompilerWarning.h"
#include "llvm/IR/Argument.h"
Expand All @@ -37,7 +39,7 @@ static const unsigned MAGIC_HASH_CONSTANT = 39;

/// KInstruction - Intermediate instruction representation used
/// during execution.
struct KInstruction {
struct KInstruction : public KValue {

struct Index {
unsigned long instID;
Expand Down Expand Up @@ -66,7 +68,9 @@ struct KInstruction {
}
};

llvm::Instruction *inst;
llvm::Instruction *inst() const {
return llvm::dyn_cast_or_null<llvm::Instruction>(value);
}

/// Value numbers for each operand. -1 is an invalid value,
/// otherwise negative numbers are indices (negated and offset by
Expand Down Expand Up @@ -113,14 +117,24 @@ struct KInstruction {
[[nodiscard]] inline KFunction *getKFunction() const {
return getKBlock()->parent;
}
bool operator<(const KInstruction &other) const {
return getID() < other.getID();

[[nodiscard]] bool operator<(const KValue &rhs) const override {
if (getKind() == rhs.getKind()) {
return getID() < cast<KInstruction>(rhs).getID();
} else {
return getKind() < rhs.getKind();
}
}

[[nodiscard]] inline KModule *getKModule() const {
return getKFunction()->parent;
}

unsigned hash() const { return getID().hash(); }
[[nodiscard]] unsigned hash() const override { return getID().hash(); }

static bool classof(const KValue *rhs) {
return rhs->getKind() == Kind::INSTRUCTION;
}
};

struct KGEPInstruction : KInstruction {
Expand Down
72 changes: 57 additions & 15 deletions include/klee/Module/KModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
#include "klee/Config/Version.h"
#include "klee/Core/Interpreter.h"
#include "klee/Module/KCallable.h"
#include "klee/Module/KValue.h"

#include "klee/Support/CompilerWarning.h"
DISABLE_WARNING_PUSH
DISABLE_WARNING_DEPRECATED_DECLARATIONS
#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/CFG.h"
#include "llvm/Support/Casting.h"
DISABLE_WARNING_POP

#include <deque>
Expand Down Expand Up @@ -57,11 +59,14 @@ template <class T> class ref;

enum KBlockType { Base, Call, Return };

struct KBlock {
struct KBlock : public KValue {
KFunction *parent;
llvm::BasicBlock *basicBlock;
KInstruction **instructions;

[[nodiscard]] llvm::BasicBlock *basicBlock() const {
return llvm::dyn_cast_or_null<llvm::BasicBlock>(value);
}

public:
KBlock(KFunction *, llvm::BasicBlock *, KModule *,
const std::unordered_map<llvm::Instruction *, unsigned> &,
Expand All @@ -74,7 +79,7 @@ struct KBlock {
virtual KBlockType getKBlockType() const { return KBlockType::Base; }
static bool classof(const KBlock *) { return true; }

unsigned getNumInstructions() const noexcept { return basicBlock->size(); }
unsigned getNumInstructions() const noexcept { return basicBlock()->size(); }
KInstruction *getFirstInstruction() const noexcept { return instructions[0]; }
KInstruction *getLastInstruction() const noexcept {
return instructions[getNumInstructions() - 1];
Expand All @@ -84,6 +89,10 @@ struct KBlock {

/// Block number in function
[[nodiscard]] uintptr_t getId() const;

static bool classof(const KValue *rhs) {
return rhs->getKind() == Kind::BLOCK ? classof(cast<KBlock>(rhs)) : false;
}
};

typedef std::function<bool(KBlock *)> KBlockPredicate;
Expand All @@ -107,6 +116,10 @@ struct KCallBlock : KBlock {
bool internal() const;
bool kleeHandled() const;
KFunction *getKFunction() const;

static bool classof(const KValue *rhs) {
return rhs->getKind() == Kind::BLOCK ? classof(cast<KBlock>(rhs)) : false;
}
};

struct KReturnBlock : KBlock {
Expand All @@ -120,6 +133,10 @@ struct KReturnBlock : KBlock {
return E->getKBlockType() == KBlockType::Return;
}
KBlockType getKBlockType() const override { return KBlockType::Return; };

static bool classof(const KValue *rhs) {
return rhs->getKind() == Kind::BLOCK ? classof(cast<KBlock>(rhs)) : false;
}
};

struct KFunction : public KCallable {
Expand All @@ -129,9 +146,12 @@ struct KFunction : public KCallable {

public:
KModule *parent;
llvm::Function *function;
KInstruction **instructions;

[[nodiscard]] llvm::Function *function() const {
return llvm::dyn_cast_or_null<llvm::Function>(value);
}

[[nodiscard]] KInstruction *getInstructionByRegister(size_t reg) const;

std::unordered_map<const llvm::Instruction *, KInstruction *> instructionMap;
Expand All @@ -158,12 +178,8 @@ struct KFunction : public KCallable {

unsigned getArgRegister(unsigned index) const { return index; }

llvm::StringRef getName() const override {
return function ? function->getName() : "";
}

llvm::FunctionType *getFunctionType() const override {
return function->getFunctionType();
return function()->getFunctionType();
}

const std::unordered_map<std::string, KBlock *> &getLabelMap() {
Expand All @@ -175,10 +191,8 @@ struct KFunction : public KCallable {
return labelMap;
}

llvm::Value *getValue() override { return function; }

static bool classof(const KCallable *callable) {
return callable->getKind() == CK_Function;
static bool classof(const KValue *callable) {
return callable->getKind() == KValue::Kind::FUNCTION;
}

[[nodiscard]] size_t getLine() const;
Expand All @@ -203,10 +217,12 @@ struct KFunctionCompare {
}
};

class KConstant {
struct KConstant : public KValue {
public:
/// Actual LLVM constant this represents.
llvm::Constant *ct;
[[nodiscard]] llvm::Constant *ct() const {
return llvm::dyn_cast_or_null<llvm::Constant>(value);
};

/// The constant ID.
unsigned id;
Expand All @@ -216,6 +232,28 @@ class KConstant {
KInstruction *ki;

KConstant(llvm::Constant *, unsigned, KInstruction *);

[[nodiscard]] static bool classof(const KValue *rhs) {
return rhs->getKind() == KValue::Kind::CONSTANT;
}
};

struct KGlobalVariable : public KValue {
public:
KGlobalVariable(llvm::GlobalVariable *global);

[[nodiscard]] llvm::GlobalVariable *globalVariable() const {
return llvm::dyn_cast_or_null<llvm::GlobalVariable>(value);
}

[[nodiscard]] static bool classof(const KValue *rhs) {
return rhs->getKind() == KValue::Kind::GLOBAL_VARIABLE;
}

// Filename where the global variable is defined
[[nodiscard]] std::string getSourceFilepath() const;
// Line number where the global variable is defined
[[nodiscard]] size_t getLine() const;
};

class KModule {
Expand Down Expand Up @@ -248,6 +286,10 @@ class KModule {
constantMap;
KConstant *getKConstant(const llvm::Constant *c);

std::unordered_map<const llvm::GlobalValue *,
std::unique_ptr<KGlobalVariable>>
globalMap;

std::unique_ptr<Cell[]> constantTable;

// Functions which are part of KLEE runtime
Expand Down
Loading

0 comments on commit 5ae0e30

Please sign in to comment.