Skip to content

Commit ae50d15

Browse files
authored
Merge 9da90e2 into 82b0cfd
2 parents 82b0cfd + 9da90e2 commit ae50d15

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+412
-193
lines changed

include/klee/Module/KModule.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ struct KFunction : public KCallable {
187187
/// Unique index for KFunction and KInstruction inside KModule
188188
/// from 0 to [KFunction + KInstruction]
189189
[[nodiscard]] inline unsigned getGlobalIndex() const { return globalIndex; }
190+
191+
bool operator<(const KFunction &rhs) const { return id < rhs.id; }
192+
bool operator<(const KFunction *rhs) const { return id < rhs->id; }
190193
};
191194

192195
struct KBlockCompare {
@@ -197,6 +200,12 @@ struct KBlockCompare {
197200
}
198201
};
199202

203+
struct KFunctionCompare {
204+
bool operator()(const KFunction *a, const KFunction *b) const {
205+
return a->id < b->id;
206+
}
207+
};
208+
200209
class KConstant {
201210
public:
202211
/// Actual LLVM constant this represents.

include/klee/Support/ModuleUtil.h

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,16 @@ bool linkModules(llvm::Module *composite,
3939
std::vector<std::unique_ptr<llvm::Module>> &modules,
4040
const unsigned Flags, std::string &errorMsg);
4141

42-
#if defined(__x86_64__) || defined(__i386__)
43-
#define addFunctionReplacement(from, to) \
44-
{#from "f", #to "f"}, {#from "", #to ""}, { "" #from "l", #to "l" }
42+
void replaceOrRenameFunction(llvm::Module *module, const char *old_name,
43+
const char *new_name);
4544

45+
#if defined(__x86_64__) || defined(__i386__)
4646
#define addIntrinsicReplacement(from, to) \
4747
{"llvm." #from ".f32", #to "f"}, {"llvm." #from ".f64", #to}, { \
4848
"llvm." #from ".f80", #to "l" \
4949
}
5050

5151
#else
52-
#define addFunctionReplacement(from, to) \
53-
{#from "f", #to "f"}, { "" #from, "" #to }
54-
5552
#define addIntrinsicReplacement(from, to) \
5653
{"llvm." #from ".f32", #to "f"}, { "llvm." #from ".f64", #to }
5754

@@ -62,33 +59,15 @@ bool linkModules(llvm::Module *composite,
6259
/// implementations in runtime/klee-fp, but not explicitly replaced here. Should
6360
/// we rename them and complete the list?
6461
const std::vector<std::pair<std::string, std::string>> floatReplacements = {
65-
addFunctionReplacement(__isnan, klee_internal_isnan),
66-
addFunctionReplacement(isnan, klee_internal_isnan),
67-
addFunctionReplacement(__isinf, klee_internal_isinf),
68-
addFunctionReplacement(isinf, klee_internal_isinf),
69-
addFunctionReplacement(__fpclassify, klee_internal_fpclassify),
70-
addFunctionReplacement(fpclassify, klee_internal_fpclassify),
71-
addFunctionReplacement(__finite, klee_internal_finite),
72-
addFunctionReplacement(finite, klee_internal_finite),
73-
addFunctionReplacement(sqrt, klee_internal_sqrt),
74-
addFunctionReplacement(fabs, klee_internal_fabs),
75-
addFunctionReplacement(rint, klee_internal_rint),
76-
addFunctionReplacement(round, klee_internal_rint),
77-
addFunctionReplacement(__signbit, klee_internal_signbit),
78-
addIntrinsicReplacement(sqrt, klee_internal_sqrt),
79-
addIntrinsicReplacement(rint, klee_internal_rint),
80-
addIntrinsicReplacement(round, klee_internal_rint),
62+
addIntrinsicReplacement(sqrt, sqrt),
63+
addIntrinsicReplacement(rint, rint),
64+
addIntrinsicReplacement(round, rint),
8165
addIntrinsicReplacement(nearbyint, nearbyint),
8266
addIntrinsicReplacement(copysign, copysign),
83-
addIntrinsicReplacement(floor, klee_floor),
67+
addIntrinsicReplacement(floor, floor),
8468
addIntrinsicReplacement(ceil, ceil)};
85-
#undef addFunctionReplacement
8669
#undef addIntrinsicReplacement
8770

88-
const std::vector<std::pair<std::string, std::string>> feRoundReplacements{
89-
{"fegetround", "klee_internal_fegetround"},
90-
{"fesetround", "klee_internal_fesetround"}};
91-
9271
/// Return the Function* target of a Call or Invoke instruction, or
9372
/// null if it cannot be determined (should be only for indirect
9473
/// calls, although complicated constant expressions might be

lib/Core/ExecutionState.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,10 @@ void ExecutionState::increaseLevel() {
446446
if (prevPC->inst->isTerminator() && kmodule->inMainModule(*kf->function)) {
447447
auto srcLevel = stack.infoStack().back().multilevel[srcbb].second;
448448
stack.infoStack().back().multilevel.replace({srcbb, srcLevel + 1});
449+
stack.infoStack().back().maxMultilevel =
450+
std::max(stack.infoStack().back().maxMultilevel, srcLevel + 1);
449451
level.insert(prevPC->parent);
452+
stack.infoStack().back().level.insert(prevPC->parent);
450453
}
451454
}
452455

lib/Core/ExecutionState.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ struct InfoStackFrame {
9696
KFunction *kf;
9797
CallPathNode *callPathNode = nullptr;
9898
PersistentMap<llvm::BasicBlock *, unsigned long long> multilevel;
99+
unsigned long long maxMultilevel = 0;
100+
std::set<KBlock *, KBlockCompare> level;
99101

100102
/// Minimum distance to an uncovered instruction once the function
101103
/// returns. This is not a good place for this but is used to

lib/Core/Executor.cpp

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ llvm::Module *Executor::setModule(
575575
kmodule = std::make_unique<KModule>();
576576

577577
// 1.) Link the modules together && 2.) Apply different instrumentation
578-
kmodule->link(userModules, 0);
578+
kmodule->link(userModules, 1);
579579
kmodule->instrument(opts);
580580

581581
kmodule->link(libsModules, 2);
@@ -603,21 +603,28 @@ llvm::Module *Executor::setModule(
603603
specialFunctionHandler = new SpecialFunctionHandler(*this);
604604
specialFunctionHandler->prepare(preservedFunctions);
605605

606-
preservedFunctions.push_back(opts.EntryPoint.c_str());
607-
608606
// Preserve the free-standing library calls
609607
preservedFunctions.push_back("memset");
610608
preservedFunctions.push_back("memcpy");
611609
preservedFunctions.push_back("memcmp");
612610
preservedFunctions.push_back("memmove");
613611

614612
if (FunctionCallReproduce != "") {
615-
// prevent elimination of the function
616-
auto f = kmodule->module->getFunction(FunctionCallReproduce);
617-
if (f)
613+
preservedFunctions.push_back(FunctionCallReproduce.c_str());
614+
}
615+
616+
// prevent elimination of the preservedFunctions functions
617+
for (auto pf : preservedFunctions) {
618+
auto f = kmodule->module->getFunction(pf);
619+
if (f) {
618620
f->addFnAttr(Attribute::OptimizeNone);
621+
f->addFnAttr(Attribute::NoInline);
622+
}
619623
}
620624

625+
// except the entry point
626+
preservedFunctions.push_back(opts.EntryPoint.c_str());
627+
621628
kmodule->optimiseAndPrepare(opts, preservedFunctions);
622629
kmodule->checkModule();
623630

@@ -2942,18 +2949,19 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
29422949
} else {
29432950
ref<Expr> v = eval(ki, 0, state).value;
29442951

2945-
if (!isa<ConstantExpr>(v) && MockExternalCalls) {
2946-
if (ki->inst->getType()->isSized()) {
2947-
prepareMockValue(state, "mockExternResult", ki);
2948-
}
2949-
} else {
2950-
ExecutionState *free = &state;
2951-
bool hasInvalid = false, first = true;
2952-
2953-
/* XXX This is wasteful, no need to do a full evaluate since we
2954-
have already got a value. But in the end the caches should
2955-
handle it for us, albeit with some overhead. */
2956-
do {
2952+
ExecutionState *free = &state;
2953+
bool hasInvalid = false, first = true;
2954+
2955+
/* XXX This is wasteful, no need to do a full evaluate since we
2956+
have already got a value. But in the end the caches should
2957+
handle it for us, albeit with some overhead. */
2958+
do {
2959+
if (!first && MockExternalCalls) {
2960+
free = nullptr;
2961+
if (ki->inst->getType()->isSized()) {
2962+
prepareMockValue(state, "mockExternResult", ki);
2963+
}
2964+
} else {
29572965
v = optimizer.optimizeExpr(v, true);
29582966
ref<ConstantExpr> value;
29592967
bool success = solver->getValue(free->constraints.cs(), v, value,
@@ -2986,8 +2994,8 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
29862994
first = false;
29872995
free = res.second;
29882996
timers.invoke();
2989-
} while (free && !haltExecution);
2990-
}
2997+
}
2998+
} while (free && !haltExecution);
29912999
}
29923000
break;
29933001
}
@@ -4142,7 +4150,7 @@ bool Executor::checkMemoryUsage() {
41424150
const auto mmapUsage = memory->getUsedDeterministicSize() >> 20U;
41434151
const auto totalUsage = mallocUsage + mmapUsage;
41444152

4145-
if (MemoryTriggerCoverOnTheFly && 3 * totalUsage <= 2 * MaxMemory) {
4153+
if (MemoryTriggerCoverOnTheFly && totalUsage > MaxMemory * 0.75) {
41464154
klee_warning_once(0,
41474155
"enabling cover-on-the-fly (close to memory cap: %luMB)",
41484156
totalUsage);
@@ -6755,7 +6763,7 @@ void Executor::runFunctionAsMain(Function *f, int argc, char **argv,
67556763

67566764
if (guidanceKind == GuidanceKind::ErrorGuidance) {
67576765
std::map<klee::KFunction *, klee::ref<klee::TargetForest>,
6758-
klee::TargetedExecutionManager::KFunctionLess>
6766+
klee::KFunctionCompare>
67596767
prepTargets;
67606768
if (FunctionCallReproduce == "") {
67616769
auto &paths = interpreterOpts.Paths.value();

lib/Core/Searcher.cpp

Lines changed: 126 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,7 @@ weight_type TargetedSearcher::getWeight(ExecutionState *es) {
181181
return weight;
182182
}
183183
auto distRes = distanceCalculator.getDistance(*es, target->getBlock());
184-
weight = klee::util::ulog2(distRes.weight + es->steppedMemoryInstructions +
185-
1); // [0, 32)
184+
weight = klee::util::ulog2(distRes.weight + 1); // [0, 32)
186185
if (!distRes.isInsideFunction) {
187186
weight += 32; // [32, 64)
188187
}
@@ -193,12 +192,12 @@ weight_type TargetedSearcher::getWeight(ExecutionState *es) {
193192

194193
ExecutionState &GuidedSearcher::selectState() {
195194
unsigned size = historiesAndTargets.size();
196-
index = theRNG.getInt32() % (size + 1);
195+
interleave ^= 1;
197196
ExecutionState *state = nullptr;
198-
if (index == size) {
197+
if (interleave || !size) {
199198
state = &baseSearcher->selectState();
200199
} else {
201-
index = index % size;
200+
index = theRNG.getInt32() % size;
202201
auto &historyTargetPair = historiesAndTargets[index];
203202
ref<const TargetsHistory> history = historyTargetPair.first;
204203
ref<Target> target = historyTargetPair.second;
@@ -657,7 +656,7 @@ class MaxCyclesMetric final : public IterativeDeepeningSearcher::Metric {
657656
return state.isCycled(maxCycles);
658657
}
659658
void increaseLimit() final {
660-
maxCycles *= 2ULL;
659+
maxCycles *= 4ULL;
661660
klee_message("increased max-cycles to %llu", maxCycles);
662661
}
663662
};
@@ -763,3 +762,124 @@ void InterleavedSearcher::printName(llvm::raw_ostream &os) {
763762
searcher->printName(os);
764763
os << "</InterleavedSearcher>\n";
765764
}
765+
766+
///
767+
768+
BlockLevelSearcher::BlockLevelSearcher(RNG &rng) : theRNG{rng} {}
769+
770+
ExecutionState &BlockLevelSearcher::selectState() {
771+
unsigned rnd = 0;
772+
unsigned index = 0;
773+
unsigned mod = 10;
774+
unsigned border = 9;
775+
776+
auto kfi = data.begin();
777+
index = theRNG.getInt32() % data.size();
778+
std::advance(kfi, index);
779+
auto &sizesTo = kfi->second;
780+
781+
for (auto &sizesSize : sizesTo) {
782+
rnd = theRNG.getInt32();
783+
if (rnd % mod < border) {
784+
for (auto &size : sizesSize.second) {
785+
rnd = theRNG.getInt32();
786+
if (rnd % mod < border) {
787+
auto lbi = size.second.begin();
788+
index = theRNG.getInt32() % size.second.size();
789+
std::advance(lbi, index);
790+
auto &level = *lbi;
791+
auto si = level.second.begin();
792+
index = theRNG.getInt32() % level.second.size();
793+
std::advance(si, index);
794+
auto &state = *si;
795+
return *state;
796+
}
797+
}
798+
}
799+
}
800+
801+
return **(sizesTo.begin()->second.begin()->second.begin()->second.begin());
802+
}
803+
804+
void BlockLevelSearcher::clear(ExecutionState &state) {
805+
KFunction *kf = state.initPC->parent->parent;
806+
BlockLevel &bl = stateToBlockLevel[&state];
807+
auto &sizeTo = data[kf];
808+
auto &sizesTo = sizeTo[bl.sizeOfLevel];
809+
auto &levelTo = sizesTo[bl.sizesOfFrameLevels];
810+
auto &states = levelTo[bl.maxMultilevel];
811+
812+
states.erase(&state);
813+
if (states.size() == 0) {
814+
levelTo.erase(bl.maxMultilevel);
815+
}
816+
if (levelTo.size() == 0) {
817+
sizesTo.erase(bl.sizesOfFrameLevels);
818+
}
819+
if (sizesTo.size() == 0) {
820+
sizeTo.erase(bl.sizeOfLevel);
821+
}
822+
if (sizeTo.size() == 0) {
823+
data.erase(kf);
824+
}
825+
}
826+
827+
void BlockLevelSearcher::update(ExecutionState *current,
828+
const StateIterable &addedStates,
829+
const StateIterable &removedStates) {
830+
if (current && std::find(removedStates.begin(), removedStates.end(),
831+
current) == removedStates.end()) {
832+
KFunction *kf = current->initPC->parent->parent;
833+
BlockLevel &bl = stateToBlockLevel[current];
834+
sizes.clear();
835+
unsigned long long maxMultilevel = 0u;
836+
for (auto &infoFrame : current->stack.infoStack()) {
837+
sizes.push_back(infoFrame.level.size());
838+
maxMultilevel = std::max(maxMultilevel, infoFrame.maxMultilevel);
839+
}
840+
for (auto &kfLevel : current->stack.multilevel) {
841+
maxMultilevel = std::max(maxMultilevel, kfLevel.second);
842+
}
843+
if (sizes != bl.sizesOfFrameLevels ||
844+
current->level.size() != bl.sizeOfLevel ||
845+
maxMultilevel != bl.maxMultilevel) {
846+
clear(*current);
847+
848+
data[kf][current->level.size()][sizes][maxMultilevel].insert(current);
849+
850+
stateToBlockLevel[current] =
851+
BlockLevel(kf, current->level.size(), sizes, maxMultilevel);
852+
}
853+
}
854+
855+
for (const auto state : addedStates) {
856+
KFunction *kf = state->initPC->parent->parent;
857+
858+
sizes.clear();
859+
unsigned long long maxMultilevel = 0u;
860+
for (auto &infoFrame : state->stack.infoStack()) {
861+
sizes.push_back(infoFrame.level.size());
862+
maxMultilevel = std::max(maxMultilevel, infoFrame.maxMultilevel);
863+
}
864+
for (auto &kfLevel : state->stack.multilevel) {
865+
maxMultilevel = std::max(maxMultilevel, kfLevel.second);
866+
}
867+
868+
data[kf][state->level.size()][sizes][maxMultilevel].insert(state);
869+
870+
stateToBlockLevel[state] =
871+
BlockLevel(kf, state->level.size(), sizes, maxMultilevel);
872+
}
873+
874+
// remove states
875+
for (const auto state : removedStates) {
876+
clear(*state);
877+
stateToBlockLevel.erase(state);
878+
}
879+
}
880+
881+
bool BlockLevelSearcher::empty() { return stateToBlockLevel.empty(); }
882+
883+
void BlockLevelSearcher::printName(llvm::raw_ostream &os) {
884+
os << "BlockLevelSearcher\n";
885+
}

0 commit comments

Comments
 (0)