about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
authorAlastair Reid <adreid@google.com>2020-07-30 17:02:20 +0000
committerCristian Cadar <c.cadar@imperial.ac.uk>2020-08-07 19:27:34 +0100
commit07148eeb5ea4d1c6c51e6aa5a666811ef9f50b90 (patch)
treebf296395b4bac7f3958aa146ce11a51eef84fbc6
parent088fc21e12c9675161172899be5ef5051f1ae96b (diff)
downloadklee-07148eeb5ea4d1c6c51e6aa5a666811ef9f50b90.tar.gz
New intrinsic: klee_is_replay
This instrinsic detects whether the program is being executed
symbolically or concretely (i.e., using the libkleeRuntest library).

The intended usage (illustrated in the test program) is to
allow the test program to display the input values by invoking
any libraries it wants to.

This is especially valuable if you are constructing complex,
structured values and for languages like Rust (or C++) that have
rich libraries and print libraries.
For example, you might pick a symbolic value N with the
assumption "0 <= N < 10" and then pick N symbolic
values and write them to an array.
The resulting ktest file is a bit hard to understand compared with the
output of the standard print function in Rust/C++.
-rw-r--r--include/klee/klee.h6
-rw-r--r--runtime/Intrinsic/klee_is_replay.c15
-rw-r--r--runtime/Runtest/intrinsics.c4
-rw-r--r--test/Replay/libkleeruntest/replay_detection.c33
4 files changed, 58 insertions, 0 deletions
diff --git a/include/klee/klee.h b/include/klee/klee.h
index 99fe15c7..fafdd55f 100644
--- a/include/klee/klee.h
+++ b/include/klee/klee.h
@@ -103,6 +103,12 @@ extern "C" {
   unsigned klee_is_symbolic(uintptr_t n);
 
 
+  /* Return true if replaying a concrete test case using the libkleeRuntime library
+   * Return false if executing symbolically in KLEE.
+   */
+  unsigned klee_is_replay();
+
+
   /* The following intrinsics are primarily intended for internal use
      and may have peculiar semantics. */
 
diff --git a/runtime/Intrinsic/klee_is_replay.c b/runtime/Intrinsic/klee_is_replay.c
new file mode 100644
index 00000000..ac9e541d
--- /dev/null
+++ b/runtime/Intrinsic/klee_is_replay.c
@@ -0,0 +1,15 @@
+
+/*===-- klee_is_replay.c --------------------------------------------------===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===*/
+
+#include "klee/klee.h"
+
+unsigned klee_is_replay() {
+  return 0;
+}
diff --git a/runtime/Runtest/intrinsics.c b/runtime/Runtest/intrinsics.c
index cdc8c9d6..f82bd554 100644
--- a/runtime/Runtest/intrinsics.c
+++ b/runtime/Runtest/intrinsics.c
@@ -146,6 +146,10 @@ uintptr_t klee_choose(uintptr_t n) {
   return x;
 }
 
+unsigned klee_is_replay() {
+  return 1;
+}
+
 void klee_assume(uintptr_t x) {
   if (!x) {
     report_internal_error("invalid klee_assume");
diff --git a/test/Replay/libkleeruntest/replay_detection.c b/test/Replay/libkleeruntest/replay_detection.c
new file mode 100644
index 00000000..7516ecd1
--- /dev/null
+++ b/test/Replay/libkleeruntest/replay_detection.c
@@ -0,0 +1,33 @@
+// RUN: %clang %s -emit-llvm -g %O0opt -c -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out %t.bc
+//
+// There should be a unique solution
+// RUN: test -f %t.klee-out/test000001.ktest
+// RUN: test ! -f %t.klee-out/test000002.ktest
+
+// Now try to replay with libkleeRuntest
+// RUN: %cc %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner
+// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest %t_runner | FileCheck %s
+
+#include "klee/klee.h"
+#include <stdio.h>
+
+int main(int argc, char** argv) {
+  int x = 0;
+  klee_make_symbolic(&x, sizeof(x), "x");
+
+  if (klee_is_replay()) { // only print x on replay runs
+    printf("x = %d\n", x);
+  }
+
+  // For the sake of testing, these constraints have a single solution
+  klee_assume(40 < x);
+  klee_assume(x < 43);
+  klee_assume((x & 1) == 0);
+
+  return 0;
+}
+
+// When replaying, it should print the concrete value it is running with
+// CHECK: x = 42