Skip to content

Commit 64dce32

Browse files
fill snapshot into SnapshotNode
1 parent 1bdb7da commit 64dce32

File tree

2 files changed

+76
-39
lines changed

2 files changed

+76
-39
lines changed

headers/wasm/symbolic_rt.hpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -228,14 +228,17 @@ class SymFrames_t {
228228
// A snapshot of the symbolic state and execution context (control)
229229
class Snapshot_t {
230230
public:
231-
explicit Snapshot_t();
231+
explicit Snapshot_t(Cont_t cont, MCont_t mcont);
232232

233233
SymStack_t get_stack() const { return stack; }
234234
SymFrames_t get_frames() const { return frames; }
235235

236236
private:
237237
SymStack_t stack;
238238
SymFrames_t frames;
239+
// The continuation at the snapshot point
240+
Cont_t cont;
241+
MCont_t mcont;
239242
};
240243

241244
inline void SymStack_t::reuse(Snapshot_t snapshot) {
@@ -273,7 +276,7 @@ struct NodeBox {
273276
std::monostate fillFinishedNode();
274277
std::monostate fillFailedNode();
275278
std::monostate fillUnreachableNode();
276-
std::monostate fillSnapshotNode();
279+
std::monostate fillSnapshotNode(Snapshot_t snapshot);
277280
bool isUnexplored() const;
278281
std::vector<SymVal> collect_path_conds();
279282
};
@@ -386,7 +389,7 @@ struct UnExploredNode : Node {
386389
};
387390

388391
struct SnapshotNode : Node {
389-
SnapshotNode() {}
392+
SnapshotNode(Snapshot_t snapshot) : snapshot(snapshot) {}
390393
std::string to_string() override { return "SnapshotNode"; }
391394

392395
protected:
@@ -399,6 +402,9 @@ struct SnapshotNode : Node {
399402
graphviz_edge(os, parent_dot_id, current_node_dot_id, edge_label);
400403
}
401404
}
405+
406+
private:
407+
Snapshot_t snapshot;
402408
};
403409

404410
struct Finished : Node {
@@ -465,9 +471,9 @@ inline std::monostate NodeBox::fillIfElseNode(SymVal cond) {
465471
return std::monostate();
466472
}
467473

468-
inline std::monostate NodeBox::fillSnapshotNode() {
474+
inline std::monostate NodeBox::fillSnapshotNode(Snapshot_t snapshot) {
469475
if (this->isUnexplored()) {
470-
node = std::make_unique<SnapshotNode>();
476+
node = std::make_unique<SnapshotNode>(snapshot);
471477
}
472478
return std::monostate();
473479
}
@@ -545,12 +551,11 @@ class Reuse_t {
545551

546552
static Reuse_t Reuse;
547553

548-
inline Snapshot_t::Snapshot_t() : stack(SymStack), frames(SymFrames) {
554+
inline Snapshot_t::Snapshot_t(Cont_t cont, MCont_t mcont)
555+
: stack(SymStack), frames(SymFrames), cont(cont), mcont(mcont) {
549556
#ifdef DEBUG
550557
std::cout << "Creating snapshot of size " << stack.size() << std::endl;
551558
#endif
552-
assert(!Reuse.is_reusing() &&
553-
"Creating snapshot while reusing the symbolic stack");
554559
}
555560

556561
class ExploreTree_t {
@@ -576,17 +581,17 @@ class ExploreTree_t {
576581
return cursor->fillIfElseNode(cond);
577582
}
578583

579-
std::monostate moveCursor(bool branch) {
584+
std::monostate moveCursor(bool branch, Snapshot_t snapshot) {
580585
assert(cursor != nullptr);
581586
auto if_else_node = dynamic_cast<IfElseNode *>(cursor->node.get());
582587
assert(
583588
if_else_node != nullptr &&
584589
"Can't move cursor when the branch node is not initialized correctly!");
585590
if (branch) {
586-
if_else_node->false_branch->fillSnapshotNode();
591+
if_else_node->false_branch->fillSnapshotNode(snapshot);
587592
cursor = if_else_node->true_branch.get();
588593
} else {
589-
if_else_node->true_branch->fillSnapshotNode();
594+
if_else_node->true_branch->fillSnapshotNode(snapshot);
590595
cursor = if_else_node->false_branch.get();
591596
}
592597

src/main/scala/wasm/StagedConcolicMiniWasm.scala

Lines changed: 60 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,9 @@ trait StagedWasmEvaluator extends SAIOps {
165165
trait Snapshot
166166

167167
// Create a snapshot of the symbolic execution, we should ensure that current symstack is in use
168-
// We don't need to store the control information, since the control is totally decided by concrete states
169-
def makeSnapshot(): Rep[Snapshot] = {
170-
"snapshot-make".reflectCtrlWith[Snapshot]()
168+
// We need to store the control information, so we can resume the execution later
169+
def makeSnapshot(kont: Rep[Cont[Unit]], mkont: Rep[MCont[Unit]]): Rep[Snapshot] = {
170+
"snapshot-make".reflectCtrlWith[Snapshot](kont, mkont)
171171
}
172172

173173
def eval(insts: List[Instr],
@@ -365,14 +365,23 @@ trait StagedWasmEvaluator extends SAIOps {
365365
val newRestCtx = restCtx.shift(offset, funcTy.out.size)
366366
eval(rest, kont, mk, trail)(newRestCtx)
367367
})
368-
// TODO: put the cond.s to path condition
369368
ExploreTree.fillWithIfElse(symCond.s)
369+
def thnK: Rep[Cont[Unit]] = topFun((mk: Rep[MCont[Unit]]) => {
370+
info("Entering the true branch of the if")
371+
eval(thn, restK _, mk, restK _ :: trail)(newCtx)
372+
})
373+
def elsK: Rep[Cont[Unit]] = topFun((mk: Rep[MCont[Unit]]) => {
374+
info("Entering the false branch of the if")
375+
eval(els, restK _, mk, restK _ :: trail)(newCtx)
376+
})
370377
if (cond.toInt != 0) {
371-
ExploreTree.moveCursor(true)
372-
eval(thn, restK _, mkont, restK _ :: trail)(newCtx)
378+
val snapshot = makeSnapshot(elsK, mkont)
379+
ExploreTree.moveCursor(true, snapshot)
380+
thnK(mkont)
373381
} else {
374-
ExploreTree.moveCursor(false)
375-
eval(els, restK _, mkont, restK _ :: trail)(newCtx)
382+
val snapshot = makeSnapshot(thnK, mkont)
383+
ExploreTree.moveCursor(false, snapshot)
384+
elsK(mkont)
376385
}
377386
()
378387
case Br(label) =>
@@ -384,40 +393,63 @@ trait StagedWasmEvaluator extends SAIOps {
384393
val symCond = Stack.popS(ty)
385394
info(s"The br_if(${label})'s condition is ", cond.toInt)
386395
ExploreTree.fillWithIfElse(symCond.s)
396+
def thnK: Rep[Cont[Unit]] = topFun((mk: Rep[MCont[Unit]]) => {
397+
trail(label)(newCtx)(mk)
398+
})
399+
def elsK: Rep[Cont[Unit]] = topFun((mk: Rep[MCont[Unit]]) => {
400+
eval(rest, kont, mk, trail)(newCtx)
401+
})
387402
if (cond.toInt != 0) {
388403
info(s"Jump to $label")
389-
ExploreTree.moveCursor(true)
390-
trail(label)(newCtx)(mkont)
404+
val snapshot = makeSnapshot(elsK, mkont)
405+
ExploreTree.moveCursor(true, snapshot)
406+
thnK(mkont)
391407
} else {
392408
info(s"Continue")
393-
ExploreTree.moveCursor(false)
394-
eval(rest, kont, mkont, trail)(newCtx)
409+
val snapshot = makeSnapshot(thnK, mkont)
410+
ExploreTree.moveCursor(false, snapshot)
411+
elsK(mkont)
395412
}
396413
()
397414
case BrTable(labels, default) =>
398415
val (ty, newCtx) = ctx.pop()
399-
val label = Stack.popC(ty)
400-
val labelSym = Stack.popS(ty)
401-
def aux(choices: List[Int], idx: Int): Rep[Unit] = {
402-
if (choices.isEmpty) trail(default)(newCtx)(mkont)
403-
else {
416+
def aux(choices: List[Int], idx: Int, mkont: Rep[MCont[Unit]]): Rep[Unit] = {
417+
if (choices.isEmpty) {
418+
Stack.popC(ty)
419+
Stack.popS(ty)
420+
trail(default)(newCtx)(mkont)
421+
} else {
422+
val label = Stack.peekC(ty)
423+
val labelSym = Stack.peekS(ty)
404424
val cond = (label - toStagedNum(I32V(idx))).isZero()
405425
val condSym = (labelSym - toStagedSymbolicNum(I32V(idx))).isZero()
406426
ExploreTree.fillWithIfElse(condSym.s)
407427
// When moving the cursor to a branch, we mark another branch as
408428
// snapshotNode (this is done by moveCursor's runtime implementation)
409429
// TODO: store snapshot into this snapshot node
430+
def thnK: Rep[Cont[Unit]] = topFun((mk: Rep[MCont[Unit]]) => {
431+
info("Entering the true branch of the br_table")
432+
Stack.popC(ty)
433+
Stack.popS(ty)
434+
trail(choices.head)(newCtx)(mk)
435+
})
436+
def elsK: Rep[Cont[Unit]] = topFun((mk: Rep[MCont[Unit]]) => {
437+
info("Entering the false branch of the br_table")
438+
aux(choices.tail, idx + 1, mk)
439+
})
410440
if (cond.toInt != 0) {
411-
ExploreTree.moveCursor(true)
412-
trail(choices.head)(newCtx)(mkont)
441+
val snapshot = makeSnapshot(elsK, mkont)
442+
ExploreTree.moveCursor(true, snapshot)
443+
thnK(mkont)
413444
}
414445
else {
415-
ExploreTree.moveCursor(false)
416-
aux(choices.tail, idx + 1)
446+
val snapshot = makeSnapshot(thnK, mkont)
447+
ExploreTree.moveCursor(false, snapshot)
448+
elsK(mkont)
417449
}
418450
}
419451
}
420-
aux(labels, 0)
452+
aux(labels, 0, mkont)
421453
case Return => trail.last(ctx)(mkont)
422454
case Call(f) => evalCall(rest, kont, mkont, trail, f, false)
423455
case ReturnCall(f) => evalCall(rest, kont, mkont, trail, f, true)
@@ -888,9 +920,9 @@ trait StagedWasmEvaluator extends SAIOps {
888920
"tree-fill-finished".reflectCtrlWith[Unit]()
889921
}
890922

891-
def moveCursor(branch: Boolean): Rep[Unit] = {
923+
def moveCursor(branch: Boolean, snapshot: Rep[Snapshot]): Rep[Unit] = {
892924
// when moving cursor from to an unexplored node, we need to change the reuse state
893-
"tree-move-cursor".reflectCtrlWith[Unit](branch)
925+
"tree-move-cursor".reflectCtrlWith[Unit](branch, snapshot)
894926
}
895927

896928
def print(): Rep[Unit] = {
@@ -1323,8 +1355,8 @@ trait StagedWasmCppGen extends CGenBase with CppSAICodeGenBase {
13231355
emit("Stack.pop()")
13241356
case Node(_, "sym-stack-pop", _, _) =>
13251357
emit("SymStack.pop()")
1326-
case Node(_, "snapshot-make", _, _) =>
1327-
emit("Snapshot_t()")
1358+
case Node(_, "snapshot-make", List(k, mk), _) =>
1359+
emit("Snapshot_t("); shallow(k); emit(", "); shallow(mk); emit(")")
13281360
case Node(_, "frame-pop", List(i), _) =>
13291361
emit("Frames.popFrame("); shallow(i); emit(")")
13301362
case Node(_, "sym-frame-pop", List(i), _) =>
@@ -1420,8 +1452,8 @@ trait StagedWasmCppGen extends CGenBase with CppSAICodeGenBase {
14201452
emit("ExploreTree.fillIfElseNode("); shallow(sym); emit(")")
14211453
case Node(_, "tree-fill-finished", List(), _) =>
14221454
emit("ExploreTree.fillFinishedNode()")
1423-
case Node(_, "tree-move-cursor", List(b), _) =>
1424-
emit("ExploreTree.moveCursor("); shallow(b); emit(")")
1455+
case Node(_, "tree-move-cursor", List(b, snapshot), _) =>
1456+
emit("ExploreTree.moveCursor("); shallow(b); emit(", "); shallow(snapshot); emit(")")
14251457
case Node(_, "tree-print", List(), _) =>
14261458
emit("ExploreTree.print()")
14271459
case Node(_, "tree-dump-graphviz", List(f), _) =>

0 commit comments

Comments
 (0)