From 9b5e99905e6732d64522d0efc212f3f1ce290ccc Mon Sep 17 00:00:00 2001 From: Cristian Cadar Date: Wed, 12 Sep 2012 14:37:39 +0000 Subject: Restructured the command-line options for setting the search heuristics in KLEE. The new options are documented at http://klee.llvm.org/klee-options.html. Cleaned a bit the code in UserSearcher.cpp, and fixed some test cases to use the new options. git-svn-id: https://llvm.org/svn/llvm-project/klee/trunk@163711 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Core/Searcher.h | 12 +++ lib/Core/UserSearcher.cpp | 158 ++++++++++++++---------------------- lib/Core/UserSearcher.h | 2 - test/Dogfood/ImmutableSet.cpp | 2 +- test/Feature/CopyOnWrite.c | 2 +- test/Feature/MakeSymbolicName.c | 2 +- test/Feature/Searchers.c | 31 +++---- test/Runtime/POSIX/DirConsistency.c | 4 +- test/Runtime/POSIX/FD_Fail2.c | 15 ++-- www/Documentation.html | 5 ++ www/klee-options.html | 73 +++++++++++++++++ 11 files changed, 181 insertions(+), 125 deletions(-) create mode 100644 www/klee-options.html diff --git a/lib/Core/Searcher.h b/lib/Core/Searcher.h index 9703e973..58772bbb 100644 --- a/lib/Core/Searcher.h +++ b/lib/Core/Searcher.h @@ -66,6 +66,18 @@ namespace klee { tmp.insert(es); update(current, std::set(), tmp); } + + enum CoreSearchType { + DFS, + RandomState, + RandomPath, + NURS_CovNew, + NURS_MD2U, + NURS_Depth, + NURS_ICnt, + NURS_CPICnt, + NURS_QC + }; }; class DFSSearcher : public Searcher { diff --git a/lib/Core/UserSearcher.cpp b/lib/Core/UserSearcher.cpp index 1aff9e5e..361092d2 100644 --- a/lib/Core/UserSearcher.cpp +++ b/lib/Core/UserSearcher.cpp @@ -20,61 +20,27 @@ using namespace llvm; using namespace klee; namespace { - cl::opt - UseRandomSearch("use-random-search"); - - cl::opt - UseInterleavedRS("use-interleaved-RS"); - - cl::opt - UseInterleavedNURS("use-interleaved-NURS"); - - cl::opt - UseInterleavedMD2UNURS("use-interleaved-MD2U-NURS"); - - cl::opt - UseInterleavedInstCountNURS("use-interleaved-icnt-NURS"); - - cl::opt - UseInterleavedCPInstCountNURS("use-interleaved-cpicnt-NURS"); - - cl::opt - UseInterleavedQueryCostNURS("use-interleaved-query-cost-NURS"); + cl::list + CoreSearch("search", cl::desc("Specify the search heuristic (default=random-path interleaved with nurs:covnew)"), + cl::values(clEnumValN(Searcher::DFS, "dfs", "use Depth First Search (DFS)"), + clEnumValN(Searcher::RandomState, "random-state", "randomly select a state to explore"), + clEnumValN(Searcher::RandomPath, "random-path", "use Random Path Selection (see OSDI'08 paper)"), + clEnumValN(Searcher::NURS_CovNew, "nurs:covnew", "use Non Uniform Random Search (NURS) with Coverage-New"), + clEnumValN(Searcher::NURS_MD2U, "nurs:md2u", "use NURS with Min-Dist-to-Uncovered"), + clEnumValN(Searcher::NURS_Depth, "nurs:depth", "use NURS with 2^depth"), + clEnumValN(Searcher::NURS_ICnt, "nurs:icnt", "use NURS with Instr-Count"), + clEnumValN(Searcher::NURS_CPICnt, "nurs:cpicnt", "use NURS with CallPath-Instr-Count"), + clEnumValN(Searcher::NURS_QC, "nurs:qc", "use NURS with Query-Cost"), + clEnumValEnd)); - cl::opt - UseInterleavedCovNewNURS("use-interleaved-covnew-NURS"); - - cl::opt - UseNonUniformRandomSearch("use-non-uniform-random-search"); - - cl::opt - UseRandomPathSearch("use-random-path"); - - cl::opt - WeightType("weight-type", cl::desc("Set the weight type for --use-non-uniform-random-search"), - cl::values(clEnumValN(WeightedRandomSearcher::Depth, "none", "use (2^depth)"), - clEnumValN(WeightedRandomSearcher::InstCount, "icnt", "use current pc exec count"), - clEnumValN(WeightedRandomSearcher::CPInstCount, "cpicnt", "use current pc exec count"), - clEnumValN(WeightedRandomSearcher::QueryCost, "query-cost", "use query cost"), - clEnumValN(WeightedRandomSearcher::MinDistToUncovered, "md2u", "use min dist to uncovered"), - clEnumValN(WeightedRandomSearcher::CoveringNew, "covnew", "use min dist to uncovered + coveringNew flag"), - clEnumValEnd)); - - cl::opt - UseMerge("use-merge", - cl::desc("Enable support for klee_merge() (experimental)")); - - cl::opt - UseBumpMerge("use-bump-merge", - cl::desc("Enable support for klee_merge() (extra experimental)")); - cl::opt UseIterativeDeepeningTimeSearch("use-iterative-deepening-time-search", cl::desc("(experimental)")); cl::opt UseBatchingSearch("use-batching-search", - cl::desc("Use batching searcher (keep running selected state for N instructions/time, see --batch-instructions and --batch-time")); + cl::desc("Use batching searcher (keep running selected state for N instructions/time, see --batch-instructions and --batch-time)"), + cl::init(false)); cl::opt BatchInstructions("batch-instructions", @@ -85,68 +51,62 @@ namespace { BatchTime("batch-time", cl::desc("Amount of time to batch when using --use-batching-search"), cl::init(5.0)); + + + cl::opt + UseMerge("use-merge", + cl::desc("Enable support for klee_merge() (experimental)")); + + cl::opt + UseBumpMerge("use-bump-merge", + cl::desc("Enable support for klee_merge() (extra experimental)")); + } + bool klee::userSearcherRequiresMD2U() { - return (WeightType==WeightedRandomSearcher::MinDistToUncovered || - WeightType==WeightedRandomSearcher::CoveringNew || - UseInterleavedMD2UNURS || - UseInterleavedCovNewNURS || - UseInterleavedInstCountNURS || - UseInterleavedCPInstCountNURS || - UseInterleavedQueryCostNURS); + return (std::find(CoreSearch.begin(), CoreSearch.end(), Searcher::NURS_MD2U) != CoreSearch.end() || + std::find(CoreSearch.begin(), CoreSearch.end(), Searcher::NURS_CovNew) != CoreSearch.end() || + std::find(CoreSearch.begin(), CoreSearch.end(), Searcher::NURS_ICnt) != CoreSearch.end() || + std::find(CoreSearch.begin(), CoreSearch.end(), Searcher::NURS_CPICnt) != CoreSearch.end() || + std::find(CoreSearch.begin(), CoreSearch.end(), Searcher::NURS_QC) != CoreSearch.end()); } -// FIXME: Remove. -bool klee::userSearcherRequiresBranchSequences() { - return false; + +Searcher *getNewSearcher(Searcher::CoreSearchType type, Executor &executor) { + Searcher *searcher = NULL; + switch (type) { + case Searcher::DFS: searcher = new DFSSearcher(); break; + case Searcher::RandomState: searcher = new RandomSearcher(); break; + case Searcher::RandomPath: searcher = new RandomPathSearcher(executor); break; + case Searcher::NURS_CovNew: searcher = new WeightedRandomSearcher(executor, WeightedRandomSearcher::CoveringNew); break; + case Searcher::NURS_MD2U: searcher = new WeightedRandomSearcher(executor, WeightedRandomSearcher::MinDistToUncovered); break; + case Searcher::NURS_Depth: searcher = new WeightedRandomSearcher(executor, WeightedRandomSearcher::Depth); break; + case Searcher::NURS_ICnt: searcher = new WeightedRandomSearcher(executor, WeightedRandomSearcher::InstCount); break; + case Searcher::NURS_CPICnt: searcher = new WeightedRandomSearcher(executor, WeightedRandomSearcher::CPInstCount); break; + case Searcher::NURS_QC: searcher = new WeightedRandomSearcher(executor, WeightedRandomSearcher::QueryCost); break; + } + + return searcher; } Searcher *klee::constructUserSearcher(Executor &executor) { - Searcher *searcher = 0; - - if (UseRandomPathSearch) { - searcher = new RandomPathSearcher(executor); - } else if (UseNonUniformRandomSearch) { - searcher = new WeightedRandomSearcher(executor, WeightType); - } else if (UseRandomSearch) { - searcher = new RandomSearcher(); - } else { - searcher = new DFSSearcher(); + + // default values + if (CoreSearch.size() == 0) { + CoreSearch.push_back(Searcher::RandomPath); + CoreSearch.push_back(Searcher::NURS_CovNew); } - if (UseInterleavedNURS || UseInterleavedMD2UNURS || UseInterleavedRS || - UseInterleavedCovNewNURS || UseInterleavedInstCountNURS || - UseInterleavedCPInstCountNURS || UseInterleavedQueryCostNURS) { + Searcher *searcher = getNewSearcher(CoreSearch[0], executor); + + if (CoreSearch.size() > 1) { std::vector s; s.push_back(searcher); - - if (UseInterleavedNURS) - s.push_back(new WeightedRandomSearcher(executor, - WeightedRandomSearcher::Depth)); - if (UseInterleavedMD2UNURS) - s.push_back(new WeightedRandomSearcher(executor, - WeightedRandomSearcher::MinDistToUncovered)); - - if (UseInterleavedCovNewNURS) - s.push_back(new WeightedRandomSearcher(executor, - WeightedRandomSearcher::CoveringNew)); - - if (UseInterleavedInstCountNURS) - s.push_back(new WeightedRandomSearcher(executor, - WeightedRandomSearcher::InstCount)); - - if (UseInterleavedCPInstCountNURS) - s.push_back(new WeightedRandomSearcher(executor, - WeightedRandomSearcher::CPInstCount)); - - if (UseInterleavedQueryCostNURS) - s.push_back(new WeightedRandomSearcher(executor, - WeightedRandomSearcher::QueryCost)); - - if (UseInterleavedRS) - s.push_back(new RandomSearcher()); + for (unsigned i=1; i diff --git a/test/Feature/MakeSymbolicName.c b/test/Feature/MakeSymbolicName.c index a4d4e2a6..a31b4a9b 100644 --- a/test/Feature/MakeSymbolicName.c +++ b/test/Feature/MakeSymbolicName.c @@ -1,5 +1,5 @@ // RUN: %llvmgcc %s -emit-llvm -g -c -o %t1.bc -// RUN: %klee --use-random-search --exit-on-error %t1.bc +// RUN: %klee --search=random-state --exit-on-error %t1.bc #include diff --git a/test/Feature/Searchers.c b/test/Feature/Searchers.c index d61037b9..b120d354 100644 --- a/test/Feature/Searchers.c +++ b/test/Feature/Searchers.c @@ -1,27 +1,30 @@ // RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t2.bc // RUN: %klee %t2.bc -// RUN: %klee --use-random-search %t2.bc -// RUN: %klee --use-non-uniform-random-search %t2.bc -// RUN: %klee --use-non-uniform-random-search --weight-type=query-cost %t2.bc +// RUN: %klee --search=random-state %t2.bc +// RUN: %klee --search=nurs:depth %t2.bc +// RUN: %klee --search=nurs:qc %t2.bc // RUN: %klee --use-batching-search %t2.bc -// RUN: %klee --use-batching-search --use-random-search %t2.bc -// RUN: %klee --use-batching-search --use-non-uniform-random-search %t2.bc -// RUN: %klee --use-batching-search --use-non-uniform-random-search --weight-type=query-cost %t2.bc -// RUN: %klee --use-merge --debug-log-merge --debug-log-state-merge %t2.bc -// RUN: %klee --use-merge --use-batching-search %t2.bc -// RUN: %klee --use-merge --use-batching-search --use-random-search %t2.bc -// RUN: %klee --use-merge --use-batching-search --use-non-uniform-random-search %t2.bc -// RUN: %klee --use-merge --use-batching-search --use-non-uniform-random-search --weight-type=query-cost %t2.bc +// RUN: %klee --use-batching-search --search=random-state %t2.bc +// RUN: %klee --use-batching-search --search=nurs:depth %t2.bc +// RUN: %klee --use-batching-search --search=nurs:qc %t2.bc +// RUN: %klee --search=random-path --search=nurs:qc %t2.bc +// RUN: %klee --use-merge --search=dfs --debug-log-merge --debug-log-state-merge %t2.bc +// RUN: %klee --use-merge --use-batching-search --search=dfs %t2.bc +// RUN: %klee --use-merge --use-batching-search --search=random-state %t2.bc +// RUN: %klee --use-merge --use-batching-search --search=nurs:depth %t2.bc +// RUN: %klee --use-merge --use-batching-search --search=nurs:qc %t2.bc // RUN: %klee --use-iterative-deepening-time-search --use-batching-search %t2.bc -// RUN: %klee --use-iterative-deepening-time-search --use-batching-search --use-random-search %t2.bc -// RUN: %klee --use-iterative-deepening-time-search --use-batching-search --use-non-uniform-random-search %t2.bc -// RUN: %klee --use-iterative-deepening-time-search --use-batching-search --use-non-uniform-random-search --weight-type=query-cost %t2.bc +// RUN: %klee --use-iterative-deepening-time-search --use-batching-search --search=random-state %t2.bc +// RUN: %klee --use-iterative-deepening-time-search --use-batching-search --search=nurs:depth %t2.bc +// RUN: %klee --use-iterative-deepening-time-search --use-batching-search --search=nurs:qc %t2.bc /* this test is basically just for coverage and doesn't really do any correctness check (aside from testing that the various combinations don't crash) */ +#include + int validate(char *buf, int N) { int i; diff --git a/test/Runtime/POSIX/DirConsistency.c b/test/Runtime/POSIX/DirConsistency.c index 30696650..24bb8a6e 100644 --- a/test/Runtime/POSIX/DirConsistency.c +++ b/test/Runtime/POSIX/DirConsistency.c @@ -1,7 +1,7 @@ // RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t.bc -// RUN: %klee --run-in=/tmp --use-random-search --libc=uclibc --posix-runtime --exit-on-error %t.bc --sym-files 1 1 > %t1.log +// RUN: %klee --run-in=/tmp --search=random-state --libc=uclibc --posix-runtime --exit-on-error %t.bc --sym-files 1 1 > %t1.log // RUN: %llvmgcc -D_FILE_OFFSET_BITS=64 %s -emit-llvm -O0 -c -o %t.bc -// RUN: %klee --run-in=/tmp --use-random-search --libc=uclibc --posix-runtime --exit-on-error %t.bc --sym-files 1 1 > %t2.log +// RUN: %klee --run-in=/tmp --search=random-state --libc=uclibc --posix-runtime --exit-on-error %t.bc --sym-files 1 1 > %t2.log // RUN: sort %t1.log %t2.log | uniq -c > %t3.log // RUN: grep -q "4 COUNT" %t3.log diff --git a/test/Runtime/POSIX/FD_Fail2.c b/test/Runtime/POSIX/FD_Fail2.c index 062f7027..b42e03bf 100644 --- a/test/Runtime/POSIX/FD_Fail2.c +++ b/test/Runtime/POSIX/FD_Fail2.c @@ -1,5 +1,5 @@ // RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc -// RUN: %klee --libc=uclibc --posix-runtime %t1.bc --sym-files 0 0 --max-fail 1 +// RUN: %klee --libc=uclibc --posix-runtime --search=dfs %t1.bc --sym-files 1 10 --max-fail 1 // RUN: test -f klee-last/test000001.ktest // RUN: test -f klee-last/test000002.ktest // RUN: test -f klee-last/test000003.ktest @@ -14,21 +14,24 @@ #include #include #include +#include int main(int argc, char** argv) { char buf[1024]; - int fd = open("/etc/fstab", O_RDONLY); + int fd = open("A", O_RDONLY); assert(fd != -1); - - int r = read(fd, buf, 1, 100); + + int r; + + r = read(fd, buf, 1, 5); if (r != -1) printf("read() succeeded\n"); - else printf("read() failed with errno %s\n", strerror(errno)); + else printf("read() failed with error '%s'\n", strerror(errno)); r = close(fd); if (r != -1) printf("close() succeeded\n"); - else printf("close() failed with errno %s\n", strerror(errno)); + else printf("close() failed with error '%s'\n", strerror(errno)); return 0; } diff --git a/www/Documentation.html b/www/Documentation.html index cf20cc5d..b266e439 100644 --- a/www/Documentation.html +++ b/www/Documentation.html @@ -22,6 +22,11 @@ Simple examples of how to use KLEE to test programs. +
  • + KLEE Options: + Overview of the KLEE's main command-line options. +
  • +
  • KLEE Generated Files: diff --git a/www/klee-options.html b/www/klee-options.html new file mode 100644 index 00000000..22871e0e --- /dev/null +++ b/www/klee-options.html @@ -0,0 +1,73 @@ + + + + + + The KLEE Symbolic Virtual Machine + + + + + +
    + +

    KLEE Options

    + + +

    Search Heuristics

    + +

    Main search heuristics

    + +

    + KLEE provides four main search heuristics: +

      +
    1. Depth-First Search (DFS): Traverses states in depth-first order.
    2. +
    3. Random State Search:Randomly selects a state to explore.
    4. +
    5. Random Path Selection: Described in our KLEE OSDI'08 paper.
    6. +
    7. Non Uniform Random Search (NURS): Selects a state randomly according to a given distribution. The distribution can be based on the minimum distance to an uncovered instruction (MD2U), the query cost, etc. +
    + + To select a search heuristic, use the --search option provided by KLEE. For example: +
    +    $ klee --search=dfs demo.o
    + + runs demo.o using DFS, while +
    +    $ klee --search=random-path demo.o 
    + runs it using the random path selection strategy. + + The full list of options is shown in KLEE's help message: +
    +    $ klee --help
    +    -search                                 - Specify the search heuristic (default=random-path interleaved with nurs:covnew)
    +      =dfs                                  -   use Depth First Search (DFS)
    +      =random-state                         -   randomly select a state to explore
    +      =random-path                          -   use Random Path Selection (see OSDI'08 paper)
    +      =nurs:covnew                          -   use Non Uniform Random Search (NURS) with Coverage-New heuristic
    +      =nurs:md2u                            -   use NURS with Min-Dist-to-Uncovered heuristic
    +      =nurs:depth                           -   use NURS with 2^depth heuristic
    +      =nurs:icnt                            -   use NURS with Instr-Count heuristic
    +      =nurs:cpicnt                          -   use NURS with CallPath-Instr-Count heuristic
    +      =nurs:qc                              -   use NURS with Query-Cost heuristic   
    + + +

    Interleaving search heuristics

    +

    + Search heuristics in KLEE can be interleaved in a round-robin + fashion. To interleave several search heuristics to be interleaved, use the --search multiple times. For example: +

    +    $ klee --search=random-state --search=nurs:md2u demo.o 
    + interleaves the Random State and the NURS:MD2U heuristics in a round robin fashion. +
    +

    + + +

    Default search heuristics

    +

    + The default heuristics used by KLEE are random-path interleaved with nurs:covnew. +

    + +
    + + -- cgit 1.4.1