klee
main.cpp
Go to the documentation of this file.
1/* -*- mode: c++; c-basic-offset: 2; -*- */
2
3//===-- main.cpp ------------------------------------------------*- C++ -*-===//
4//
5// The KLEE Symbolic Virtual Machine
6//
7// This file is distributed under the University of Illinois Open Source
8// License. See LICENSE.TXT for details.
9//
10//===----------------------------------------------------------------------===//
11
12#include "klee/ADT/TreeStream.h"
13#include "klee/Config/Version.h"
15#include "klee/Expr/Expr.h"
16#include "klee/ADT/KTest.h"
20#include "klee/Support/Debug.h"
25#include "klee/System/Time.h"
26
27#include "llvm/Bitcode/BitcodeReader.h"
28#include "llvm/IR/Constants.h"
29#include "llvm/IR/IRBuilder.h"
30#include "llvm/IR/InstrTypes.h"
31#include "llvm/IR/Instruction.h"
32#include "llvm/IR/Instructions.h"
33#include "llvm/IR/LLVMContext.h"
34#include "llvm/IR/Type.h"
35#include "llvm/Support/CommandLine.h"
36#include "llvm/Support/Errno.h"
37#include "llvm/Support/FileSystem.h"
38#include "llvm/Support/Host.h"
39#include "llvm/Support/ManagedStatic.h"
40#include "llvm/Support/MemoryBuffer.h"
41#include "llvm/Support/Path.h"
42#include "llvm/Support/raw_ostream.h"
43
44#include "llvm/Support/TargetSelect.h"
45#include "llvm/Support/Signals.h"
46
47
48#include <dirent.h>
49#include <signal.h>
50#include <unistd.h>
51#include <sys/stat.h>
52#include <sys/wait.h>
53
54#include <cerrno>
55#include <ctime>
56#include <fstream>
57#include <iomanip>
58#include <iterator>
59#include <sstream>
60
61
62using namespace llvm;
63using namespace klee;
64
65namespace {
66 cl::opt<std::string>
67 InputFile(cl::desc("<input bytecode>"), cl::Positional, cl::init("-"));
68
69 cl::list<std::string>
70 InputArgv(cl::ConsumeAfter,
71 cl::desc("<program arguments>..."));
72
73
74 /*** Test case options ***/
75
76 cl::OptionCategory TestCaseCat("Test case options",
77 "These options select the files to generate for each test case.");
78
79 cl::opt<bool>
80 WriteNone("write-no-tests",
81 cl::init(false),
82 cl::desc("Do not generate any test files (default=false)"),
83 cl::cat(TestCaseCat));
84
85 cl::opt<bool>
86 WriteCVCs("write-cvcs",
87 cl::desc("Write .cvc files for each test case (default=false)"),
88 cl::cat(TestCaseCat));
89
90 cl::opt<bool>
91 WriteKQueries("write-kqueries",
92 cl::desc("Write .kquery files for each test case (default=false)"),
93 cl::cat(TestCaseCat));
94
95 cl::opt<bool>
96 WriteSMT2s("write-smt2s",
97 cl::desc("Write .smt2 (SMT-LIBv2) files for each test case (default=false)"),
98 cl::cat(TestCaseCat));
99
100 cl::opt<bool>
101 WriteCov("write-cov",
102 cl::desc("Write coverage information for each test case (default=false)"),
103 cl::cat(TestCaseCat));
104
105 cl::opt<bool>
106 WriteTestInfo("write-test-info",
107 cl::desc("Write additional test case information (default=false)"),
108 cl::cat(TestCaseCat));
109
110 cl::opt<bool>
111 WritePaths("write-paths",
112 cl::desc("Write .path files for each test case (default=false)"),
113 cl::cat(TestCaseCat));
114
115 cl::opt<bool>
116 WriteSymPaths("write-sym-paths",
117 cl::desc("Write .sym.path files for each test case (default=false)"),
118 cl::cat(TestCaseCat));
119
120
121 /*** Startup options ***/
122
123 cl::OptionCategory StartCat("Startup options",
124 "These options affect how execution is started.");
125
126 cl::opt<std::string>
127 EntryPoint("entry-point",
128 cl::desc("Function in which to start execution (default=main)"),
129 cl::init("main"),
130 cl::cat(StartCat));
131
132 cl::opt<std::string>
133 RunInDir("run-in-dir",
134 cl::desc("Change to the given directory before starting execution (default=location of tested file)."),
135 cl::cat(StartCat));
136
137 cl::opt<std::string>
138 OutputDir("output-dir",
139 cl::desc("Directory in which to write results (default=klee-out-<N>)"),
140 cl::init(""),
141 cl::cat(StartCat));
142
143 cl::opt<std::string>
144 Environ("env-file",
145 cl::desc("Parse environment from the given file (in \"env\" format)"),
146 cl::cat(StartCat));
147
148 cl::opt<bool>
149 OptimizeModule("optimize",
150 cl::desc("Optimize the code before execution (default=false)."),
151 cl::init(false),
152 cl::cat(StartCat));
153
154 cl::opt<bool>
155 WarnAllExternals("warn-all-external-symbols",
156 cl::desc("Issue a warning on startup for all external symbols (default=false)."),
157 cl::cat(StartCat));
158
159
160 /*** Linking options ***/
161
162 cl::OptionCategory LinkCat("Linking options",
163 "These options control the libraries being linked.");
164
165 enum class LibcType { FreestandingLibc, KleeLibc, UcLibc };
166
167 cl::opt<LibcType> Libc(
168 "libc", cl::desc("Choose libc version (none by default)."),
169 cl::values(
170 clEnumValN(
171 LibcType::FreestandingLibc, "none",
172 "Don't link in a libc (only provide freestanding environment)"),
173 clEnumValN(LibcType::KleeLibc, "klee", "Link in KLEE's libc"),
174 clEnumValN(LibcType::UcLibc, "uclibc",
175 "Link in uclibc (adapted for KLEE)")),
176 cl::init(LibcType::FreestandingLibc), cl::cat(LinkCat));
177
178 cl::list<std::string>
179 LinkLibraries("link-llvm-lib",
180 cl::desc("Link the given bitcode library before execution, "
181 "e.g. .bca, .bc, .a. Can be used multiple times."),
182 cl::value_desc("bitcode library file"), cl::cat(LinkCat));
183
184 cl::opt<bool>
185 WithPOSIXRuntime("posix-runtime",
186 cl::desc("Link with POSIX runtime. Options that can be passed as arguments to the programs are: --sym-arg <max-len> --sym-args <min-argvs> <max-argvs> <max-len> + file model options (default=false)."),
187 cl::init(false),
188 cl::cat(LinkCat));
189
190 cl::opt<std::string> RuntimeBuild(
191 "runtime-build",
192 cl::desc("Link with versions of the runtime library that were built with "
193 "the provided configuration (default=" RUNTIME_CONFIGURATION
194 ")."),
195 cl::init(RUNTIME_CONFIGURATION), cl::cat(LinkCat));
196
197 /*** Checks options ***/
198
199 cl::OptionCategory ChecksCat("Checks options",
200 "These options control some of the checks being done by KLEE.");
201
202 cl::opt<bool>
203 CheckDivZero("check-div-zero",
204 cl::desc("Inject checks for division-by-zero (default=true)"),
205 cl::init(true),
206 cl::cat(ChecksCat));
207
208 cl::opt<bool>
209 CheckOvershift("check-overshift",
210 cl::desc("Inject checks for overshift (default=true)"),
211 cl::init(true),
212 cl::cat(ChecksCat));
213
214
215
216 cl::opt<bool>
217 OptExitOnError("exit-on-error",
218 cl::desc("Exit KLEE if an error in the tested application has been found (default=false)"),
219 cl::init(false),
220 cl::cat(TerminationCat));
221
222
223 /*** Replaying options ***/
224
225 cl::OptionCategory ReplayCat("Replaying options",
226 "These options impact replaying of test cases.");
227
228 cl::opt<bool>
229 ReplayKeepSymbolic("replay-keep-symbolic",
230 cl::desc("Replay the test cases only by asserting "
231 "the bytes, not necessarily making them concrete."),
232 cl::cat(ReplayCat));
233
234 cl::list<std::string>
235 ReplayKTestFile("replay-ktest-file",
236 cl::desc("Specify a ktest file to use for replay"),
237 cl::value_desc("ktest file"),
238 cl::cat(ReplayCat));
239
240 cl::list<std::string>
241 ReplayKTestDir("replay-ktest-dir",
242 cl::desc("Specify a directory to replay ktest files from"),
243 cl::value_desc("output directory"),
244 cl::cat(ReplayCat));
245
246 cl::opt<std::string>
247 ReplayPathFile("replay-path",
248 cl::desc("Specify a path file to replay"),
249 cl::value_desc("path file"),
250 cl::cat(ReplayCat));
251
252
253
254 cl::list<std::string>
255 SeedOutFile("seed-file",
256 cl::desc(".ktest file to be used as seed"),
257 cl::cat(SeedingCat));
258
259 cl::list<std::string>
260 SeedOutDir("seed-dir",
261 cl::desc("Directory with .ktest files to be used as seeds"),
262 cl::cat(SeedingCat));
263
264 cl::opt<unsigned>
265 MakeConcreteSymbolic("make-concrete-symbolic",
266 cl::desc("Probabilistic rate at which to make concrete reads symbolic, "
267 "i.e. approximately 1 in n concrete reads will be made symbolic (0=off, 1=all). "
268 "Used for testing (default=0)"),
269 cl::init(0),
270 cl::cat(DebugCat));
271
272 cl::opt<unsigned>
273 MaxTests("max-tests",
274 cl::desc("Stop execution after generating the given number of tests. Extra tests corresponding to partially explored paths will also be dumped. Set to 0 to disable (default=0)"),
275 cl::init(0),
276 cl::cat(TerminationCat));
277
278 cl::opt<bool>
279 Watchdog("watchdog",
280 cl::desc("Use a watchdog process to enforce --max-time."),
281 cl::init(0),
282 cl::cat(TerminationCat));
283
284 cl::opt<bool>
285 Libcxx("libcxx",
286 cl::desc("Link the llvm libc++ library into the bitcode (default=false)"),
287 cl::init(false),
288 cl::cat(LinkCat));
289}
290
291namespace klee {
292extern cl::opt<std::string> MaxTime;
293class ExecutionState;
294}
295
296/***/
297
299private:
302 std::unique_ptr<llvm::raw_ostream> m_infoFile;
303
304 SmallString<128> m_outputDirectory;
305
306 unsigned m_numTotalTests; // Number of tests received from the interpreter
307 unsigned m_numGeneratedTests; // Number of tests successfully generated
308 unsigned m_pathsCompleted; // number of completed paths
309 unsigned m_pathsExplored; // number of partially explored and completed paths
310
311 // used for writing .ktest files
313 char **m_argv;
314
315public:
316 KleeHandler(int argc, char **argv);
317 ~KleeHandler();
318
319 llvm::raw_ostream &getInfoStream() const { return *m_infoFile; }
325 void incPathsExplored(std::uint32_t num = 1) {
326 m_pathsExplored += num; }
327
329
330 void processTestCase(const ExecutionState &state,
331 const char *errorMessage,
332 const char *errorSuffix);
333
334 std::string getOutputFilename(const std::string &filename);
335 std::unique_ptr<llvm::raw_fd_ostream> openOutputFile(const std::string &filename);
336 std::string getTestFilename(const std::string &suffix, unsigned id);
337 std::unique_ptr<llvm::raw_fd_ostream> openTestFile(const std::string &suffix, unsigned id);
338
339 // load a .path file
340 static void loadPathFile(std::string name,
341 std::vector<bool> &buffer);
342
343 static void getKTestFilesInDir(std::string directoryPath,
344 std::vector<std::string> &results);
345
346 static std::string getRunTimeLibraryPath(const char *argv0);
347};
348
349KleeHandler::KleeHandler(int argc, char **argv)
350 : m_interpreter(0), m_pathWriter(0), m_symPathWriter(0),
351 m_outputDirectory(), m_numTotalTests(0), m_numGeneratedTests(0),
352 m_pathsCompleted(0), m_pathsExplored(0), m_argc(argc), m_argv(argv) {
353
354 // create output directory (OutputDir or "klee-out-<i>")
355 bool dir_given = OutputDir != "";
356 SmallString<128> directory(dir_given ? OutputDir : InputFile);
357
358 if (!dir_given) sys::path::remove_filename(directory);
359 if (auto ec = sys::fs::make_absolute(directory)) {
360 klee_error("unable to determine absolute path: %s", ec.message().c_str());
361 }
362
363 if (dir_given) {
364 // OutputDir
365 if (mkdir(directory.c_str(), 0775) < 0)
366 klee_error("cannot create \"%s\": %s", directory.c_str(), strerror(errno));
367
368 m_outputDirectory = directory;
369 } else {
370 // "klee-out-<i>"
371 int i = 0;
372 for (; i <= INT_MAX; ++i) {
373 SmallString<128> d(directory);
374 llvm::sys::path::append(d, "klee-out-");
375 raw_svector_ostream ds(d);
376 ds << i;
377 // SmallString is always up-to-date, no need to flush. See Support/raw_ostream.h
378
379 // create directory and try to link klee-last
380 if (mkdir(d.c_str(), 0775) == 0) {
382
383 SmallString<128> klee_last(directory);
384 llvm::sys::path::append(klee_last, "klee-last");
385
386 if (((unlink(klee_last.c_str()) < 0) && (errno != ENOENT)) ||
387 symlink(m_outputDirectory.c_str(), klee_last.c_str()) < 0) {
388
389 klee_warning("cannot create klee-last symlink: %s", strerror(errno));
390 }
391
392 break;
393 }
394
395 // otherwise try again or exit on error
396 if (errno != EEXIST)
397 klee_error("cannot create \"%s\": %s", m_outputDirectory.c_str(), strerror(errno));
398 }
399 if (i == INT_MAX && m_outputDirectory.str().equals(""))
400 klee_error("cannot create output directory: index out of range");
401 }
402
403 klee_message("output directory is \"%s\"", m_outputDirectory.c_str());
404
405 // open warnings.txt
406 std::string file_path = getOutputFilename("warnings.txt");
407 if ((klee_warning_file = fopen(file_path.c_str(), "w")) == NULL)
408 klee_error("cannot open file \"%s\": %s", file_path.c_str(), strerror(errno));
409
410 // open messages.txt
411 file_path = getOutputFilename("messages.txt");
412 if ((klee_message_file = fopen(file_path.c_str(), "w")) == NULL)
413 klee_error("cannot open file \"%s\": %s", file_path.c_str(), strerror(errno));
414
415 // open info
416 m_infoFile = openOutputFile("info");
417}
418
420 delete m_pathWriter;
421 delete m_symPathWriter;
422 fclose(klee_warning_file);
423 fclose(klee_message_file);
424}
425
427 m_interpreter = i;
428
429 if (WritePaths) {
431 assert(m_pathWriter->good());
433 }
434
435 if (WriteSymPaths) {
437 assert(m_symPathWriter->good());
439 }
440}
441
442std::string KleeHandler::getOutputFilename(const std::string &filename) {
443 SmallString<128> path = m_outputDirectory;
444 sys::path::append(path,filename);
445 return path.c_str();
446}
447
448std::unique_ptr<llvm::raw_fd_ostream>
449KleeHandler::openOutputFile(const std::string &filename) {
450 std::string Error;
451 std::string path = getOutputFilename(filename);
452 auto f = klee_open_output_file(path, Error);
453 if (!f) {
454 klee_warning("error opening file \"%s\". KLEE may have run out of file "
455 "descriptors: try to increase the maximum number of open file "
456 "descriptors by using ulimit (%s).",
457 path.c_str(), Error.c_str());
458 return nullptr;
459 }
460 return f;
461}
462
463std::string KleeHandler::getTestFilename(const std::string &suffix, unsigned id) {
464 std::stringstream filename;
465 filename << "test" << std::setfill('0') << std::setw(6) << id << '.' << suffix;
466 return filename.str();
467}
468
469std::unique_ptr<llvm::raw_fd_ostream>
470KleeHandler::openTestFile(const std::string &suffix, unsigned id) {
472}
473
474
475/* Outputs all files (.ktest, .kquery, .cov etc.) describing a test case */
477 const char *errorMessage,
478 const char *errorSuffix) {
479 if (!WriteNone) {
480 std::vector< std::pair<std::string, std::vector<unsigned char> > > out;
481 bool success = m_interpreter->getSymbolicSolution(state, out);
482
483 if (!success)
484 klee_warning("unable to get symbolic solution, losing test case");
485
486 const auto start_time = time::getWallTime();
487
488 unsigned id = ++m_numTotalTests;
489
490 if (success) {
491 KTest b;
492 b.numArgs = m_argc;
493 b.args = m_argv;
494 b.symArgvs = 0;
495 b.symArgvLen = 0;
496 b.numObjects = out.size();
497 b.objects = new KTestObject[b.numObjects];
498 assert(b.objects);
499 for (unsigned i=0; i<b.numObjects; i++) {
500 KTestObject *o = &b.objects[i];
501 o->name = const_cast<char*>(out[i].first.c_str());
502 o->numBytes = out[i].second.size();
503 o->bytes = new unsigned char[o->numBytes];
504 assert(o->bytes);
505 std::copy(out[i].second.begin(), out[i].second.end(), o->bytes);
506 }
507
508 if (!kTest_toFile(&b, getOutputFilename(getTestFilename("ktest", id)).c_str())) {
509 klee_warning("unable to write output test case, losing it");
510 } else {
512 }
513
514 for (unsigned i=0; i<b.numObjects; i++)
515 delete[] b.objects[i].bytes;
516 delete[] b.objects;
517 }
518
519 if (errorMessage) {
520 auto f = openTestFile(errorSuffix, id);
521 if (f)
522 *f << errorMessage;
523 }
524
525 if (m_pathWriter) {
526 std::vector<unsigned char> concreteBranches;
528 concreteBranches);
529 auto f = openTestFile("path", id);
530 if (f) {
531 for (const auto &branch : concreteBranches) {
532 *f << branch << '\n';
533 }
534 }
535 }
536
537 if (errorMessage || WriteKQueries) {
538 std::string constraints;
539 m_interpreter->getConstraintLog(state, constraints,Interpreter::KQUERY);
540 auto f = openTestFile("kquery", id);
541 if (f)
542 *f << constraints;
543 }
544
545 if (WriteCVCs) {
546 // FIXME: If using Z3 as the core solver the emitted file is actually
547 // SMT-LIBv2 not CVC which is a bit confusing
548 std::string constraints;
549 m_interpreter->getConstraintLog(state, constraints, Interpreter::STP);
550 auto f = openTestFile("cvc", id);
551 if (f)
552 *f << constraints;
553 }
554
555 if (WriteSMT2s) {
556 std::string constraints;
557 m_interpreter->getConstraintLog(state, constraints, Interpreter::SMTLIB2);
558 auto f = openTestFile("smt2", id);
559 if (f)
560 *f << constraints;
561 }
562
563 if (m_symPathWriter) {
564 std::vector<unsigned char> symbolicBranches;
566 symbolicBranches);
567 auto f = openTestFile("sym.path", id);
568 if (f) {
569 for (const auto &branch : symbolicBranches) {
570 *f << branch << '\n';
571 }
572 }
573 }
574
575 if (WriteCov) {
576 std::map<const std::string*, std::set<unsigned> > cov;
577 m_interpreter->getCoveredLines(state, cov);
578 auto f = openTestFile("cov", id);
579 if (f) {
580 for (const auto &entry : cov) {
581 for (const auto &line : entry.second) {
582 *f << *entry.first << ':' << line << '\n';
583 }
584 }
585 }
586 }
587
588 if (m_numGeneratedTests == MaxTests)
590
591 if (WriteTestInfo) {
592 time::Span elapsed_time(time::getWallTime() - start_time);
593 auto f = openTestFile("info", id);
594 if (f)
595 *f << "Time to generate test case: " << elapsed_time << '\n';
596 }
597 } // if (!WriteNone)
598
599 if (errorMessage && OptExitOnError) {
601 klee_error("EXITING ON ERROR:\n%s\n", errorMessage);
602 }
603}
604
605 // load a .path file
606void KleeHandler::loadPathFile(std::string name,
607 std::vector<bool> &buffer) {
608 std::ifstream f(name.c_str(), std::ios::in | std::ios::binary);
609
610 if (!f.good())
611 assert(0 && "unable to open path file");
612
613 while (f.good()) {
614 unsigned value;
615 f >> value;
616 buffer.push_back(!!value);
617 f.get();
618 }
619}
620
621void KleeHandler::getKTestFilesInDir(std::string directoryPath,
622 std::vector<std::string> &results) {
623 std::error_code ec;
624 llvm::sys::fs::directory_iterator i(directoryPath, ec), e;
625 for (; i != e && !ec; i.increment(ec)) {
626 auto f = i->path();
627 if (f.size() >= 6 && f.substr(f.size()-6,f.size()) == ".ktest") {
628 results.push_back(f);
629 }
630 }
631
632 if (ec) {
633 llvm::errs() << "ERROR: unable to read output directory: " << directoryPath
634 << ": " << ec.message() << "\n";
635 exit(1);
636 }
637}
638
639std::string KleeHandler::getRunTimeLibraryPath(const char *argv0) {
640 // allow specifying the path to the runtime library
641 const char *env = getenv("KLEE_RUNTIME_LIBRARY_PATH");
642 if (env)
643 return std::string(env);
644
645 // Take any function from the execution binary but not main (as not allowed by
646 // C++ standard)
647 void *MainExecAddr = (void *)(intptr_t)getRunTimeLibraryPath;
648 SmallString<128> toolRoot(
649 llvm::sys::fs::getMainExecutable(argv0, MainExecAddr)
650 );
651
652 // Strip off executable so we have a directory path
653 llvm::sys::path::remove_filename(toolRoot);
654
655 SmallString<128> libDir;
656
657 if (strlen( KLEE_INSTALL_BIN_DIR ) != 0 &&
658 strlen( KLEE_INSTALL_RUNTIME_DIR ) != 0 &&
659 toolRoot.str().endswith( KLEE_INSTALL_BIN_DIR ))
660 {
661 KLEE_DEBUG_WITH_TYPE("klee_runtime", llvm::dbgs() <<
662 "Using installed KLEE library runtime: ");
663 libDir = toolRoot.str().substr(0,
664 toolRoot.str().size() - strlen( KLEE_INSTALL_BIN_DIR ));
665 llvm::sys::path::append(libDir, KLEE_INSTALL_RUNTIME_DIR);
666 }
667 else
668 {
669 KLEE_DEBUG_WITH_TYPE("klee_runtime", llvm::dbgs() <<
670 "Using build directory KLEE library runtime :");
671 libDir = KLEE_DIR;
672 llvm::sys::path::append(libDir, "runtime/lib");
673 }
674
675 KLEE_DEBUG_WITH_TYPE("klee_runtime", llvm::dbgs() <<
676 libDir.c_str() << "\n");
677 return libDir.c_str();
678}
679
680//===----------------------------------------------------------------------===//
681// main Driver function
682//
683static std::string strip(std::string &in) {
684 unsigned len = in.size();
685 unsigned lead = 0, trail = len;
686 while (lead<len && isspace(in[lead]))
687 ++lead;
688 while (trail>lead && isspace(in[trail-1]))
689 --trail;
690 return in.substr(lead, trail-lead);
691}
692
693static void parseArguments(int argc, char **argv) {
694 cl::SetVersionPrinter(klee::printVersion);
695 // This version always reads response files
696 cl::ParseCommandLineOptions(argc, argv, " klee\n");
697}
698
699static void
700preparePOSIX(std::vector<std::unique_ptr<llvm::Module>> &loadedModules,
701 llvm::StringRef libCPrefix) {
702 // Get the main function from the main module and rename it such that it can
703 // be called after the POSIX setup
704 Function *mainFn = nullptr;
705 for (auto &module : loadedModules) {
706 mainFn = module->getFunction(EntryPoint);
707 if (mainFn)
708 break;
709 }
710
711 if (!mainFn)
712 klee_error("Entry function '%s' not found in module.", EntryPoint.c_str());
713 mainFn->setName("__klee_posix_wrapped_main");
714
715 // Add a definition of the entry function if needed. This is the case if we
716 // link against a libc implementation. Preparing for libc linking (i.e.
717 // linking with uClibc will expect a main function and rename it to
718 // _user_main. We just provide the definition here.
719 if (!libCPrefix.empty() && !mainFn->getParent()->getFunction(EntryPoint))
720 llvm::Function::Create(mainFn->getFunctionType(),
721 llvm::Function::ExternalLinkage, EntryPoint,
722 mainFn->getParent());
723
724 llvm::Function *wrapper = nullptr;
725 for (auto &module : loadedModules) {
726 wrapper = module->getFunction("__klee_posix_wrapper");
727 if (wrapper)
728 break;
729 }
730 assert(wrapper && "klee_posix_wrapper not found");
731
732 // Rename the POSIX wrapper to prefixed entrypoint, e.g. _user_main as uClibc
733 // would expect it or main otherwise
734 wrapper->setName(libCPrefix + EntryPoint);
735}
736
737
738// This is a terrible hack until we get some real modeling of the
739// system. All we do is check the undefined symbols and warn about
740// any "unrecognized" externals and about any obviously unsafe ones.
741
742// Symbols we explicitly support
743static const char *modelledExternals[] = {
744 "_ZTVN10__cxxabiv117__class_type_infoE",
745 "_ZTVN10__cxxabiv120__si_class_type_infoE",
746 "_ZTVN10__cxxabiv121__vmi_class_type_infoE",
747
748 // special functions
749 "_assert",
750 "__assert_fail",
751 "__assert_rtn",
752 "__errno_location",
753 "__error",
754 "calloc",
755 "_exit",
756 "exit",
757 "free",
758 "abort",
759 "klee_abort",
760 "klee_assume",
761 "klee_check_memory_access",
762 "klee_define_fixed_object",
763 "klee_get_errno",
764 "klee_get_valuef",
765 "klee_get_valued",
766 "klee_get_valuel",
767 "klee_get_valuell",
768 "klee_get_value_i32",
769 "klee_get_value_i64",
770 "klee_get_obj_size",
771 "klee_is_symbolic",
772 "klee_make_symbolic",
773 "klee_mark_global",
774 "klee_open_merge",
775 "klee_close_merge",
776 "klee_prefer_cex",
777 "klee_posix_prefer_cex",
778 "klee_print_expr",
779 "klee_print_range",
780 "klee_report_error",
781 "klee_set_forking",
782 "klee_silent_exit",
783 "klee_warning",
784 "klee_warning_once",
785 "klee_stack_trace",
786#ifdef SUPPORT_KLEE_EH_CXX
787 "_klee_eh_Unwind_RaiseException_impl",
788 "klee_eh_typeid_for",
789#endif
790 "llvm.dbg.declare",
791 "llvm.dbg.value",
792 "llvm.va_start",
793 "llvm.va_end",
794 "malloc",
795 "realloc",
796 "memalign",
797 "_ZdaPv",
798 "_ZdlPv",
799 "_Znaj",
800 "_Znwj",
801 "_Znam",
802 "_Znwm",
803 "__ubsan_handle_add_overflow",
804 "__ubsan_handle_sub_overflow",
805 "__ubsan_handle_mul_overflow",
806 "__ubsan_handle_divrem_overflow",
807};
808
809// Symbols we aren't going to warn about
810static const char *dontCareExternals[] = {
811#if 0
812 // stdio
813 "fprintf",
814 "fflush",
815 "fopen",
816 "fclose",
817 "fputs_unlocked",
818 "putchar_unlocked",
819 "vfprintf",
820 "fwrite",
821 "puts",
822 "printf",
823 "stdin",
824 "stdout",
825 "stderr",
826 "_stdio_term",
827 "__errno_location",
828 "fstat",
829#endif
830
831 // static information, pretty ok to return
832 "getegid",
833 "geteuid",
834 "getgid",
835 "getuid",
836 "getpid",
837 "gethostname",
838 "getpgrp",
839 "getppid",
840 "getpagesize",
841 "getpriority",
842 "getgroups",
843 "getdtablesize",
844 "getrlimit",
845 "getrlimit64",
846 "getcwd",
847 "getwd",
848 "gettimeofday",
849 "uname",
850
851 // fp stuff we just don't worry about yet
852 "frexp",
853 "ldexp",
854 "__isnan",
855 "__signbit",
856};
857
858// Extra symbols we aren't going to warn about with klee-libc
859static const char *dontCareKlee[] = {
860 "__ctype_b_loc",
861 "__ctype_get_mb_cur_max",
862
863 // I/O system calls
864 "open",
865 "write",
866 "read",
867 "close",
868};
869
870// Extra symbols we aren't going to warn about with uclibc
871static const char *dontCareUclibc[] = {
872 "__dso_handle",
873
874 // Don't warn about these since we explicitly commented them out of
875 // uclibc.
876 "printf",
877 "vprintf"
878};
879
880// Symbols we consider unsafe
881static const char *unsafeExternals[] = {
882 "fork", // oh lord
883 "exec", // heaven help us
884 "error", // calls _exit
885 "raise", // yeah
886 "kill", // mmmhmmm
887};
888
889#define NELEMS(array) (sizeof(array)/sizeof(array[0]))
890void externalsAndGlobalsCheck(const llvm::Module *m) {
891 std::map<std::string, bool> externals;
892 std::set<std::string> modelled(modelledExternals,
894 std::set<std::string> dontCare(dontCareExternals,
896 std::set<std::string> unsafe(unsafeExternals,
898
899 switch (Libc) {
900 case LibcType::KleeLibc:
901 dontCare.insert(dontCareKlee, dontCareKlee+NELEMS(dontCareKlee));
902 break;
903 case LibcType::UcLibc:
904 dontCare.insert(dontCareUclibc,
906 break;
907 case LibcType::FreestandingLibc: /* silence compiler warning */
908 break;
909 }
910
911 if (WithPOSIXRuntime)
912 dontCare.insert("syscall");
913
914 for (Module::const_iterator fnIt = m->begin(), fn_ie = m->end();
915 fnIt != fn_ie; ++fnIt) {
916 if (fnIt->isDeclaration() && !fnIt->use_empty())
917 externals.insert(std::make_pair(fnIt->getName(), false));
918 for (Function::const_iterator bbIt = fnIt->begin(), bb_ie = fnIt->end();
919 bbIt != bb_ie; ++bbIt) {
920 for (BasicBlock::const_iterator it = bbIt->begin(), ie = bbIt->end();
921 it != ie; ++it) {
922 if (const CallInst *ci = dyn_cast<CallInst>(it)) {
923#if LLVM_VERSION_CODE >= LLVM_VERSION(8, 0)
924 if (isa<InlineAsm>(ci->getCalledOperand())) {
925#else
926 if (isa<InlineAsm>(ci->getCalledValue())) {
927#endif
928 klee_warning_once(&*fnIt,
929 "function \"%s\" has inline asm",
930 fnIt->getName().data());
931 }
932 }
933 }
934 }
935 }
936
937 for (Module::const_global_iterator
938 it = m->global_begin(), ie = m->global_end();
939 it != ie; ++it)
940 if (it->isDeclaration() && !it->use_empty())
941 externals.insert(std::make_pair(it->getName(), true));
942 // and remove aliases (they define the symbol after global
943 // initialization)
944 for (Module::const_alias_iterator
945 it = m->alias_begin(), ie = m->alias_end();
946 it != ie; ++it) {
947 std::map<std::string, bool>::iterator it2 =
948 externals.find(it->getName().str());
949 if (it2!=externals.end())
950 externals.erase(it2);
951 }
952
953 std::map<std::string, bool> foundUnsafe;
954 for (std::map<std::string, bool>::iterator
955 it = externals.begin(), ie = externals.end();
956 it != ie; ++it) {
957 const std::string &ext = it->first;
958 if (!modelled.count(ext) && (WarnAllExternals ||
959 !dontCare.count(ext))) {
960 if (ext.compare(0, 5, "llvm.") != 0) { // not an LLVM reserved name
961 if (unsafe.count(ext)) {
962 foundUnsafe.insert(*it);
963 } else {
964 klee_warning("undefined reference to %s: %s",
965 it->second ? "variable" : "function",
966 ext.c_str());
967 }
968 }
969 }
970 }
971
972 for (std::map<std::string, bool>::iterator
973 it = foundUnsafe.begin(), ie = foundUnsafe.end();
974 it != ie; ++it) {
975 const std::string &ext = it->first;
976 klee_warning("undefined reference to %s: %s (UNSAFE)!",
977 it->second ? "variable" : "function",
978 ext.c_str());
979 }
980}
981
983
984static bool interrupted = false;
985
986// Pulled out so it can be easily called from a debugger.
987extern "C"
990}
991
992extern "C"
995}
996
997static void interrupt_handle() {
998 if (!interrupted && theInterpreter) {
999 llvm::errs() << "KLEE: ctrl-c detected, requesting interpreter to halt.\n";
1001 sys::SetInterruptFunction(interrupt_handle);
1002 } else {
1003 llvm::errs() << "KLEE: ctrl-c detected, exiting.\n";
1004 exit(1);
1005 }
1006 interrupted = true;
1007}
1008
1010 // just wait for the child to finish
1011}
1012
1013// This is a temporary hack. If the running process has access to
1014// externals then it can disable interrupts, which screws up the
1015// normal "nice" watchdog termination process. We try to request the
1016// interpreter to halt using this mechanism as a last resort to save
1017// the state data before going ahead and killing it.
1018static void halt_via_gdb(int pid) {
1019 char buffer[256];
1020 snprintf(buffer, sizeof(buffer),
1021 "gdb --batch --eval-command=\"p halt_execution()\" "
1022 "--eval-command=detach --pid=%d &> /dev/null",
1023 pid);
1024 // fprintf(stderr, "KLEE: WATCHDOG: running: %s\n", buffer);
1025 if (system(buffer)==-1)
1026 perror("system");
1027}
1028
1029#ifndef SUPPORT_KLEE_UCLIBC
1030static void
1031linkWithUclibc(StringRef libDir, std::string opt_suffix,
1032 std::vector<std::unique_ptr<llvm::Module>> &modules) {
1033 klee_error("invalid libc, no uclibc support!\n");
1034}
1035#else
1036static void replaceOrRenameFunction(llvm::Module *module,
1037 const char *old_name, const char *new_name)
1038{
1039 Function *new_function, *old_function;
1040 new_function = module->getFunction(new_name);
1041 old_function = module->getFunction(old_name);
1042 if (old_function) {
1043 if (new_function) {
1044 old_function->replaceAllUsesWith(new_function);
1045 old_function->eraseFromParent();
1046 } else {
1047 old_function->setName(new_name);
1048 assert(old_function->getName() == new_name);
1049 }
1050 }
1051}
1052
1053static void
1054createLibCWrapper(std::vector<std::unique_ptr<llvm::Module>> &modules,
1055 llvm::StringRef intendedFunction,
1056 llvm::StringRef libcMainFunction) {
1057 // XXX we need to rearchitect so this can also be used with
1058 // programs externally linked with libc implementation.
1059
1060 // We now need to swap things so that libcMainFunction is the entry
1061 // point, in such a way that the arguments are passed to
1062 // libcMainFunction correctly. We do this by renaming the user main
1063 // and generating a stub function to call intendedFunction. There is
1064 // also an implicit cooperation in that runFunctionAsMain sets up
1065 // the environment arguments to what a libc expects (following
1066 // argv), since it does not explicitly take an envp argument.
1067 auto &ctx = modules[0]->getContext();
1068 Function *userMainFn = modules[0]->getFunction(intendedFunction);
1069 assert(userMainFn && "unable to get user main");
1070 // Rename entry point using a prefix
1071 userMainFn->setName("__user_" + intendedFunction);
1072
1073 // force import of libcMainFunction
1074 llvm::Function *libcMainFn = nullptr;
1075 for (auto &module : modules) {
1076 if ((libcMainFn = module->getFunction(libcMainFunction)))
1077 break;
1078 }
1079 if (!libcMainFn)
1080 klee_error("Could not add %s wrapper", libcMainFunction.str().c_str());
1081
1082 auto inModuleReference = libcMainFn->getParent()->getOrInsertFunction(
1083 userMainFn->getName(), userMainFn->getFunctionType());
1084
1085 const auto ft = libcMainFn->getFunctionType();
1086
1087 if (ft->getNumParams() != 7)
1088 klee_error("Imported %s wrapper does not have the correct "
1089 "number of arguments",
1090 libcMainFunction.str().c_str());
1091
1092 std::vector<Type *> fArgs;
1093 fArgs.push_back(ft->getParamType(1)); // argc
1094 fArgs.push_back(ft->getParamType(2)); // argv
1095 Function *stub =
1096 Function::Create(FunctionType::get(Type::getInt32Ty(ctx), fArgs, false),
1097 GlobalVariable::ExternalLinkage, intendedFunction,
1098 libcMainFn->getParent());
1099 BasicBlock *bb = BasicBlock::Create(ctx, "entry", stub);
1100 llvm::IRBuilder<> Builder(bb);
1101
1102 std::vector<llvm::Value*> args;
1103 args.push_back(llvm::ConstantExpr::getBitCast(
1105 cast<llvm::Constant>(inModuleReference.getCallee()),
1106#else
1107 inModuleReference,
1108#endif
1109 ft->getParamType(0)));
1110 args.push_back(&*(stub->arg_begin())); // argc
1111 auto arg_it = stub->arg_begin();
1112 args.push_back(&*(++arg_it)); // argv
1113 args.push_back(Constant::getNullValue(ft->getParamType(3))); // app_init
1114 args.push_back(Constant::getNullValue(ft->getParamType(4))); // app_fini
1115 args.push_back(Constant::getNullValue(ft->getParamType(5))); // rtld_fini
1116 args.push_back(Constant::getNullValue(ft->getParamType(6))); // stack_end
1117 Builder.CreateCall(libcMainFn, args);
1118 Builder.CreateUnreachable();
1119}
1120
1121static void
1122linkWithUclibc(StringRef libDir, std::string opt_suffix,
1123 std::vector<std::unique_ptr<llvm::Module>> &modules) {
1124 LLVMContext &ctx = modules[0]->getContext();
1125
1126 size_t newModules = modules.size();
1127
1128 // Ensure that klee-uclibc exists
1129 SmallString<128> uclibcBCA(libDir);
1130 std::string errorMsg;
1131 llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_NAME);
1132 if (!klee::loadFile(uclibcBCA.c_str(), ctx, modules, errorMsg))
1133 klee_error("Cannot find klee-uclibc '%s': %s", uclibcBCA.c_str(),
1134 errorMsg.c_str());
1135
1136 for (auto i = newModules, j = modules.size(); i < j; ++i) {
1137 replaceOrRenameFunction(modules[i].get(), "__libc_open", "open");
1138 replaceOrRenameFunction(modules[i].get(), "__libc_fcntl", "fcntl");
1139 }
1140
1141 createLibCWrapper(modules, EntryPoint, "__uClibc_main");
1142 klee_message("NOTE: Using klee-uclibc : %s", uclibcBCA.c_str());
1143
1144 // Link the fortified library
1145 SmallString<128> FortifyPath(libDir);
1146 llvm::sys::path::append(FortifyPath,
1147 "libkleeRuntimeFortify" + opt_suffix + ".bca");
1148 if (!klee::loadFile(FortifyPath.c_str(), ctx, modules, errorMsg))
1149 klee_error("error loading the fortify library '%s': %s",
1150 FortifyPath.c_str(), errorMsg.c_str());
1151}
1152#endif
1153
1154int main(int argc, char **argv, char **envp) {
1155 atexit(llvm_shutdown); // Call llvm_shutdown() on exit.
1156
1157#if LLVM_VERSION_CODE >= LLVM_VERSION(13, 0)
1158 KCommandLine::HideOptions(llvm::cl::getGeneralCategory());
1159#else
1160 KCommandLine::HideOptions(llvm::cl::GeneralCategory);
1161#endif
1162
1163 llvm::InitializeNativeTarget();
1164
1165 parseArguments(argc, argv);
1166 sys::PrintStackTraceOnErrorSignal(argv[0]);
1167
1168 if (Watchdog) {
1169 if (MaxTime.empty()) {
1170 klee_error("--watchdog used without --max-time");
1171 }
1172
1173 int pid = fork();
1174 if (pid<0) {
1175 klee_error("unable to fork watchdog");
1176 } else if (pid) {
1177 klee_message("KLEE: WATCHDOG: watching %d\n", pid);
1178 fflush(stderr);
1179 sys::SetInterruptFunction(interrupt_handle_watchdog);
1180
1181 const time::Span maxTime(MaxTime);
1182 auto nextStep = time::getWallTime() + maxTime + (maxTime / 10);
1183 int level = 0;
1184
1185 // Simple stupid code...
1186 while (1) {
1187 sleep(1);
1188
1189 int status, res = waitpid(pid, &status, WNOHANG);
1190
1191 if (res < 0) {
1192 if (errno==ECHILD) { // No child, no need to watch but
1193 // return error since we didn't catch
1194 // the exit.
1195 klee_warning("KLEE: watchdog exiting (no child)\n");
1196 return 1;
1197 } else if (errno!=EINTR) {
1198 perror("watchdog waitpid");
1199 exit(1);
1200 }
1201 } else if (res==pid && WIFEXITED(status)) {
1202 return WEXITSTATUS(status);
1203 } else {
1204 auto time = time::getWallTime();
1205
1206 if (time > nextStep) {
1207 ++level;
1208
1209 if (level==1) {
1211 "KLEE: WATCHDOG: time expired, attempting halt via INT\n");
1212 kill(pid, SIGINT);
1213 } else if (level==2) {
1215 "KLEE: WATCHDOG: time expired, attempting halt via gdb\n");
1216 halt_via_gdb(pid);
1217 } else {
1219 "KLEE: WATCHDOG: kill(9)ing child (I tried to be nice)\n");
1220 kill(pid, SIGKILL);
1221 return 1; // what more can we do
1222 }
1223
1224 // Ideally this triggers a dump, which may take a while,
1225 // so try and give the process extra time to clean up.
1226 auto max = std::max(time::seconds(15), maxTime / 10);
1227 nextStep = time::getWallTime() + max;
1228 }
1229 }
1230 }
1231
1232 return 0;
1233 }
1234 }
1235
1236 sys::SetInterruptFunction(interrupt_handle);
1237
1238 // Load the bytecode...
1239 std::string errorMsg;
1240 LLVMContext ctx;
1241 std::vector<std::unique_ptr<llvm::Module>> loadedModules;
1242 if (!klee::loadFile(InputFile, ctx, loadedModules, errorMsg)) {
1243 klee_error("error loading program '%s': %s", InputFile.c_str(),
1244 errorMsg.c_str());
1245 }
1246 // Load and link the whole files content. The assumption is that this is the
1247 // application under test.
1248 // Nothing gets removed in the first place.
1249 std::unique_ptr<llvm::Module> M(klee::linkModules(
1250 loadedModules, "" /* link all modules together */, errorMsg));
1251 if (!M) {
1252 klee_error("error loading program '%s': %s", InputFile.c_str(),
1253 errorMsg.c_str());
1254 }
1255
1256 llvm::Module *mainModule = M.get();
1257
1258 const std::string &module_triple = mainModule->getTargetTriple();
1259 std::string host_triple = llvm::sys::getDefaultTargetTriple();
1260
1261 if (module_triple != host_triple)
1262 klee_warning("Module and host target triples do not match: '%s' != '%s'\n"
1263 "This may cause unexpected crashes or assertion violations.",
1264 module_triple.c_str(), host_triple.c_str());
1265
1266 // Detect architecture
1267 std::string opt_suffix = "64"; // Fall back to 64bit
1268 if (module_triple.find("i686") != std::string::npos ||
1269 module_triple.find("i586") != std::string::npos ||
1270 module_triple.find("i486") != std::string::npos ||
1271 module_triple.find("i386") != std::string::npos)
1272 opt_suffix = "32";
1273
1274 // Add additional user-selected suffix
1275 opt_suffix += "_" + RuntimeBuild.getValue();
1276
1277 // Push the module as the first entry
1278 loadedModules.emplace_back(std::move(M));
1279
1280 std::string LibraryDir = KleeHandler::getRunTimeLibraryPath(argv[0]);
1281 Interpreter::ModuleOptions Opts(LibraryDir.c_str(), EntryPoint, opt_suffix,
1282 /*Optimize=*/OptimizeModule,
1283 /*CheckDivZero=*/CheckDivZero,
1284 /*CheckOvershift=*/CheckOvershift);
1285
1286 if (WithPOSIXRuntime) {
1287 SmallString<128> Path(Opts.LibraryDir);
1288 llvm::sys::path::append(Path, "libkleeRuntimePOSIX" + opt_suffix + ".bca");
1289 klee_message("NOTE: Using POSIX model: %s", Path.c_str());
1290 if (!klee::loadFile(Path.c_str(), mainModule->getContext(), loadedModules,
1291 errorMsg))
1292 klee_error("error loading POSIX support '%s': %s", Path.c_str(),
1293 errorMsg.c_str());
1294
1295 std::string libcPrefix = (Libc == LibcType::UcLibc ? "__user_" : "");
1296 preparePOSIX(loadedModules, libcPrefix);
1297 }
1298
1299 if (Libcxx) {
1300#ifndef SUPPORT_KLEE_LIBCXX
1301 klee_error("KLEE was not compiled with libc++ support");
1302#else
1303 SmallString<128> LibcxxBC(Opts.LibraryDir);
1304 llvm::sys::path::append(LibcxxBC, KLEE_LIBCXX_BC_NAME);
1305 if (!klee::loadFile(LibcxxBC.c_str(), mainModule->getContext(), loadedModules,
1306 errorMsg))
1307 klee_error("error loading libc++ '%s': %s", LibcxxBC.c_str(),
1308 errorMsg.c_str());
1309 klee_message("NOTE: Using libc++ : %s", LibcxxBC.c_str());
1310#ifdef SUPPORT_KLEE_EH_CXX
1311 SmallString<128> EhCxxPath(Opts.LibraryDir);
1312 llvm::sys::path::append(EhCxxPath, "libkleeeh-cxx" + opt_suffix + ".bca");
1313 if (!klee::loadFile(EhCxxPath.c_str(), mainModule->getContext(),
1314 loadedModules, errorMsg))
1315 klee_error("error loading libklee-eh-cxx '%s': %s", EhCxxPath.c_str(),
1316 errorMsg.c_str());
1317 klee_message("NOTE: Enabled runtime support for C++ exceptions");
1318#else
1319 klee_message("NOTE: KLEE was not compiled with support for C++ exceptions");
1320#endif
1321#endif
1322 }
1323
1324 switch (Libc) {
1325 case LibcType::KleeLibc: {
1326 // FIXME: Find a reasonable solution for this.
1327 SmallString<128> Path(Opts.LibraryDir);
1328 llvm::sys::path::append(Path,
1329 "libkleeRuntimeKLEELibc" + opt_suffix + ".bca");
1330 if (!klee::loadFile(Path.c_str(), mainModule->getContext(), loadedModules,
1331 errorMsg))
1332 klee_error("error loading klee libc '%s': %s", Path.c_str(),
1333 errorMsg.c_str());
1334 }
1335 /* Falls through. */
1336 case LibcType::FreestandingLibc: {
1337 SmallString<128> Path(Opts.LibraryDir);
1338 llvm::sys::path::append(Path,
1339 "libkleeRuntimeFreestanding" + opt_suffix + ".bca");
1340 if (!klee::loadFile(Path.c_str(), mainModule->getContext(), loadedModules,
1341 errorMsg))
1342 klee_error("error loading freestanding support '%s': %s", Path.c_str(),
1343 errorMsg.c_str());
1344 break;
1345 }
1346 case LibcType::UcLibc:
1347 linkWithUclibc(LibraryDir, opt_suffix, loadedModules);
1348 break;
1349 }
1350
1351 for (const auto &library : LinkLibraries) {
1352 if (!klee::loadFile(library, mainModule->getContext(), loadedModules,
1353 errorMsg))
1354 klee_error("error loading bitcode library '%s': %s", library.c_str(),
1355 errorMsg.c_str());
1356 }
1357
1358 // FIXME: Change me to std types.
1359 int pArgc;
1360 char **pArgv;
1361 char **pEnvp;
1362 if (Environ != "") {
1363 std::vector<std::string> items;
1364 std::ifstream f(Environ.c_str());
1365 if (!f.good())
1366 klee_error("unable to open --environ file: %s", Environ.c_str());
1367 while (!f.eof()) {
1368 std::string line;
1369 std::getline(f, line);
1370 line = strip(line);
1371 if (!line.empty())
1372 items.push_back(line);
1373 }
1374 f.close();
1375 pEnvp = new char *[items.size()+1];
1376 unsigned i=0;
1377 for (; i != items.size(); ++i)
1378 pEnvp[i] = strdup(items[i].c_str());
1379 pEnvp[i] = 0;
1380 } else {
1381 pEnvp = envp;
1382 }
1383
1384 pArgc = InputArgv.size() + 1;
1385 pArgv = new char *[pArgc];
1386 for (unsigned i=0; i<InputArgv.size()+1; i++) {
1387 std::string &arg = (i==0 ? InputFile : InputArgv[i-1]);
1388 unsigned size = arg.size() + 1;
1389 char *pArg = new char[size];
1390
1391 std::copy(arg.begin(), arg.end(), pArg);
1392 pArg[size - 1] = 0;
1393
1394 pArgv[i] = pArg;
1395 }
1396
1397 std::vector<bool> replayPath;
1398
1399 if (ReplayPathFile != "") {
1400 KleeHandler::loadPathFile(ReplayPathFile, replayPath);
1401 }
1402
1404 IOpts.MakeConcreteSymbolic = MakeConcreteSymbolic;
1405 KleeHandler *handler = new KleeHandler(pArgc, pArgv);
1406 Interpreter *interpreter =
1407 theInterpreter = Interpreter::create(ctx, IOpts, handler);
1408 assert(interpreter);
1409 handler->setInterpreter(interpreter);
1410
1411 for (int i=0; i<argc; i++) {
1412 handler->getInfoStream() << argv[i] << (i+1<argc ? " ":"\n");
1413 }
1414 handler->getInfoStream() << "PID: " << getpid() << "\n";
1415
1416 // Get the desired main function. klee_main initializes uClibc
1417 // locale and other data and then calls main.
1418
1419 auto finalModule = interpreter->setModule(loadedModules, Opts);
1420 Function *mainFn = finalModule->getFunction(EntryPoint);
1421 if (!mainFn) {
1422 klee_error("Entry function '%s' not found in module.", EntryPoint.c_str());
1423 }
1424
1425 externalsAndGlobalsCheck(finalModule);
1426
1427 if (ReplayPathFile != "") {
1428 interpreter->setReplayPath(&replayPath);
1429 }
1430
1431
1432 auto startTime = std::time(nullptr);
1433 { // output clock info and start time
1434 std::stringstream startInfo;
1435 startInfo << time::getClockInfo()
1436 << "Started: "
1437 << std::put_time(std::localtime(&startTime), "%Y-%m-%d %H:%M:%S") << '\n';
1438 handler->getInfoStream() << startInfo.str();
1439 handler->getInfoStream().flush();
1440 }
1441
1442 if (!ReplayKTestDir.empty() || !ReplayKTestFile.empty()) {
1443 assert(SeedOutFile.empty());
1444 assert(SeedOutDir.empty());
1445
1446 std::vector<std::string> kTestFiles = ReplayKTestFile;
1447 for (std::vector<std::string>::iterator
1448 it = ReplayKTestDir.begin(), ie = ReplayKTestDir.end();
1449 it != ie; ++it)
1450 KleeHandler::getKTestFilesInDir(*it, kTestFiles);
1451 std::vector<KTest*> kTests;
1452 for (std::vector<std::string>::iterator
1453 it = kTestFiles.begin(), ie = kTestFiles.end();
1454 it != ie; ++it) {
1455 KTest *out = kTest_fromFile(it->c_str());
1456 if (out) {
1457 kTests.push_back(out);
1458 } else {
1459 klee_warning("unable to open: %s\n", (*it).c_str());
1460 }
1461 }
1462
1463 if (RunInDir != "") {
1464 int res = chdir(RunInDir.c_str());
1465 if (res < 0) {
1466 klee_error("Unable to change directory to: %s - %s", RunInDir.c_str(),
1467 sys::StrError(errno).c_str());
1468 }
1469 }
1470
1471 unsigned i=0;
1472 for (std::vector<KTest*>::iterator
1473 it = kTests.begin(), ie = kTests.end();
1474 it != ie; ++it) {
1475 KTest *out = *it;
1476 interpreter->setReplayKTest(out);
1477 llvm::errs() << "KLEE: replaying: " << *it << " (" << kTest_numBytes(out)
1478 << " bytes)"
1479 << " (" << ++i << "/" << kTestFiles.size() << ")\n";
1480 // XXX should put envp in .ktest ?
1481 interpreter->runFunctionAsMain(mainFn, out->numArgs, out->args, pEnvp);
1482 if (interrupted) break;
1483 }
1484 interpreter->setReplayKTest(0);
1485 while (!kTests.empty()) {
1486 kTest_free(kTests.back());
1487 kTests.pop_back();
1488 }
1489 } else {
1490 std::vector<KTest *> seeds;
1491 for (std::vector<std::string>::iterator
1492 it = SeedOutFile.begin(), ie = SeedOutFile.end();
1493 it != ie; ++it) {
1494 KTest *out = kTest_fromFile(it->c_str());
1495 if (!out) {
1496 klee_error("unable to open: %s\n", (*it).c_str());
1497 }
1498 seeds.push_back(out);
1499 }
1500 for (std::vector<std::string>::iterator
1501 it = SeedOutDir.begin(), ie = SeedOutDir.end();
1502 it != ie; ++it) {
1503 std::vector<std::string> kTestFiles;
1504 KleeHandler::getKTestFilesInDir(*it, kTestFiles);
1505 for (std::vector<std::string>::iterator
1506 it2 = kTestFiles.begin(), ie = kTestFiles.end();
1507 it2 != ie; ++it2) {
1508 KTest *out = kTest_fromFile(it2->c_str());
1509 if (!out) {
1510 klee_error("unable to open: %s\n", (*it2).c_str());
1511 }
1512 seeds.push_back(out);
1513 }
1514 if (kTestFiles.empty()) {
1515 klee_error("seeds directory is empty: %s\n", (*it).c_str());
1516 }
1517 }
1518
1519 if (!seeds.empty()) {
1520 klee_message("KLEE: using %lu seeds\n", seeds.size());
1521 interpreter->useSeeds(&seeds);
1522 }
1523 if (RunInDir != "") {
1524 int res = chdir(RunInDir.c_str());
1525 if (res < 0) {
1526 klee_error("Unable to change directory to: %s - %s", RunInDir.c_str(),
1527 sys::StrError(errno).c_str());
1528 }
1529 }
1530 interpreter->runFunctionAsMain(mainFn, pArgc, pArgv, pEnvp);
1531
1532 while (!seeds.empty()) {
1533 kTest_free(seeds.back());
1534 seeds.pop_back();
1535 }
1536 }
1537
1538 auto endTime = std::time(nullptr);
1539 { // output end and elapsed time
1540 std::uint32_t h;
1541 std::uint8_t m, s;
1542 std::tie(h,m,s) = time::seconds(endTime - startTime).toHMS();
1543 std::stringstream endInfo;
1544 endInfo << "Finished: "
1545 << std::put_time(std::localtime(&endTime), "%Y-%m-%d %H:%M:%S") << '\n'
1546 << "Elapsed: "
1547 << std::setfill('0') << std::setw(2) << h
1548 << ':'
1549 << std::setfill('0') << std::setw(2) << +m
1550 << ':'
1551 << std::setfill('0') << std::setw(2) << +s
1552 << '\n';
1553 handler->getInfoStream() << endInfo.str();
1554 handler->getInfoStream().flush();
1555 }
1556
1557 // Free all the args.
1558 for (unsigned i=0; i<InputArgv.size()+1; i++)
1559 delete[] pArgv[i];
1560 delete[] pArgv;
1561
1562 delete interpreter;
1563
1564 uint64_t queries =
1566 uint64_t queriesValid =
1567 *theStatisticManager->getStatisticByName("QueriesValid");
1568 uint64_t queriesInvalid =
1569 *theStatisticManager->getStatisticByName("QueriesInvalid");
1570 uint64_t queryCounterexamples =
1572 uint64_t queryConstructs =
1573 *theStatisticManager->getStatisticByName("QueryConstructs");
1574 uint64_t instructions =
1575 *theStatisticManager->getStatisticByName("Instructions");
1576 uint64_t forks =
1578
1579 handler->getInfoStream()
1580 << "KLEE: done: explored paths = " << 1 + forks << "\n";
1581
1582 // Write some extra information in the info file which users won't
1583 // necessarily care about or understand.
1584 if (queries)
1585 handler->getInfoStream()
1586 << "KLEE: done: avg. constructs per query = "
1587 << queryConstructs / queries << "\n";
1588 handler->getInfoStream()
1589 << "KLEE: done: total queries = " << queries << "\n"
1590 << "KLEE: done: valid queries = " << queriesValid << "\n"
1591 << "KLEE: done: invalid queries = " << queriesInvalid << "\n"
1592 << "KLEE: done: query cex = " << queryCounterexamples << "\n";
1593
1594 std::stringstream stats;
1595 stats << '\n'
1596 << "KLEE: done: total instructions = " << instructions << '\n'
1597 << "KLEE: done: completed paths = " << handler->getNumPathsCompleted()
1598 << '\n'
1599 << "KLEE: done: partially completed paths = "
1600 << handler->getNumPathsExplored() - handler->getNumPathsCompleted()
1601 << '\n'
1602 << "KLEE: done: generated tests = " << handler->getNumTestCases()
1603 << '\n';
1604
1605 bool useColors = llvm::errs().is_displayed();
1606 if (useColors)
1607 llvm::errs().changeColor(llvm::raw_ostream::GREEN,
1608 /*bold=*/true,
1609 /*bg=*/false);
1610
1611 llvm::errs() << stats.str();
1612
1613 if (useColors)
1614 llvm::errs().resetColor();
1615
1616 handler->getInfoStream() << stats.str();
1617
1618 delete handler;
1619
1620 return 0;
1621}
void kTest_free(KTest *bo)
Definition: KTest.cpp:229
int kTest_toFile(KTest *bo, const char *path)
Definition: KTest.cpp:178
KTest * kTest_fromFile(const char *path)
Definition: KTest.cpp:94
unsigned kTest_numBytes(KTest *bo)
Definition: KTest.cpp:222
#define LLVM_VERSION_CODE
Definition: Version.h:16
#define LLVM_VERSION(major, minor)
Definition: Version.h:15
std::unique_ptr< llvm::raw_ostream > m_infoFile
Definition: main.cpp:302
unsigned getNumPathsCompleted()
Definition: main.cpp:322
unsigned m_numGeneratedTests
Definition: main.cpp:307
unsigned m_numTotalTests
Definition: main.cpp:306
SmallString< 128 > m_outputDirectory
Definition: main.cpp:304
int m_argc
Definition: main.cpp:312
static void getKTestFilesInDir(std::string directoryPath, std::vector< std::string > &results)
Definition: main.cpp:621
unsigned m_pathsExplored
Definition: main.cpp:309
Interpreter * m_interpreter
Definition: main.cpp:300
void incPathsCompleted()
Definition: main.cpp:324
void incPathsExplored(std::uint32_t num=1)
Definition: main.cpp:325
std::string getTestFilename(const std::string &suffix, unsigned id)
Definition: main.cpp:463
std::unique_ptr< llvm::raw_fd_ostream > openTestFile(const std::string &suffix, unsigned id)
Definition: main.cpp:470
unsigned getNumPathsExplored()
Definition: main.cpp:323
llvm::raw_ostream & getInfoStream() const
Definition: main.cpp:319
unsigned getNumTestCases()
Returns the number of test cases successfully generated so far.
Definition: main.cpp:321
TreeStreamWriter * m_pathWriter
Definition: main.cpp:301
TreeStreamWriter * m_symPathWriter
Definition: main.cpp:301
void processTestCase(const ExecutionState &state, const char *errorMessage, const char *errorSuffix)
Definition: main.cpp:476
std::unique_ptr< llvm::raw_fd_ostream > openOutputFile(const std::string &filename)
Definition: main.cpp:449
void setInterpreter(Interpreter *i)
Definition: main.cpp:426
~KleeHandler()
Definition: main.cpp:419
char ** m_argv
Definition: main.cpp:313
unsigned m_pathsCompleted
Definition: main.cpp:308
static std::string getRunTimeLibraryPath(const char *argv0)
Definition: main.cpp:639
static void loadPathFile(std::string name, std::vector< bool > &buffer)
Definition: main.cpp:606
std::string getOutputFilename(const std::string &filename)
Definition: main.cpp:442
KleeHandler(int argc, char **argv)
Definition: main.cpp:349
ExecutionState representing a path under exploration.
virtual void setReplayKTest(const struct KTest *out)=0
virtual void setSymbolicPathWriter(TreeStreamWriter *tsw)=0
virtual void prepareForEarlyExit()=0
virtual void getCoveredLines(const ExecutionState &state, std::map< const std::string *, std::set< unsigned > > &res)=0
virtual void runFunctionAsMain(llvm::Function *f, int argc, char **argv, char **envp)=0
virtual llvm::Module * setModule(std::vector< std::unique_ptr< llvm::Module > > &modules, const ModuleOptions &opts)=0
virtual void setHaltExecution(bool value)=0
virtual unsigned getPathStreamID(const ExecutionState &state)=0
virtual void setReplayPath(const std::vector< bool > *path)=0
virtual void setInhibitForking(bool value)=0
virtual void setPathWriter(TreeStreamWriter *tsw)=0
virtual void getConstraintLog(const ExecutionState &state, std::string &res, LogType logFormat=STP)=0
virtual unsigned getSymbolicPathStreamID(const ExecutionState &state)=0
virtual bool getSymbolicSolution(const ExecutionState &state, std::vector< std::pair< std::string, std::vector< unsigned char > > > &res)=0
virtual void useSeeds(const std::vector< struct KTest * > *seeds)=0
Statistic * getStatisticByName(const std::string &name) const
Definition: Statistics.cpp:50
void readStream(TreeStreamID id, std::vector< unsigned char > &out)
Definition: TreeStream.cpp:96
int main(int argc, char **argv)
Definition: main.cpp:387
void klee_warning(char *name)
Definition: klee-replay.c:432
void klee_warning_once(char *name)
Definition: klee-replay.c:436
void externalsAndGlobalsCheck(const llvm::Module *m)
Definition: main.cpp:890
static const char * dontCareKlee[]
Definition: main.cpp:859
static const char * modelledExternals[]
Definition: main.cpp:743
static void interrupt_handle()
Definition: main.cpp:997
static void interrupt_handle_watchdog()
Definition: main.cpp:1009
static const char * dontCareExternals[]
Definition: main.cpp:810
static const char * unsafeExternals[]
Definition: main.cpp:881
static const char * dontCareUclibc[]
Definition: main.cpp:871
static void halt_via_gdb(int pid)
Definition: main.cpp:1018
static std::string strip(std::string &in)
Definition: main.cpp:683
void halt_execution()
Definition: main.cpp:988
static void preparePOSIX(std::vector< std::unique_ptr< llvm::Module > > &loadedModules, llvm::StringRef libCPrefix)
Definition: main.cpp:700
static void linkWithUclibc(StringRef libDir, std::string opt_suffix, std::vector< std::unique_ptr< llvm::Module > > &modules)
Definition: main.cpp:1031
void stop_forking()
Definition: main.cpp:993
#define NELEMS(array)
Definition: main.cpp:889
static void parseArguments(int argc, char **argv)
Definition: main.cpp:693
static Interpreter * theInterpreter
Definition: main.cpp:982
static bool interrupted
Definition: main.cpp:984
int line
Definition: klee.h:74
int const char const char * suffix
Definition: klee.h:76
uint64_t ext(uint64_t l, unsigned outWidth, unsigned inWidth)
Statistic queryConstructs
Statistic queriesInvalid
Statistic queriesValid
Statistic instructions
Statistic queryCounterexamples
Statistic queries
Statistic forks
The number of process forks.
Point getWallTime()
Returns point in time using a monotonic steady clock.
Definition: Time.cpp:206
std::string getClockInfo()
Returns information about clock.
Definition: Time.cpp:179
Span seconds(std::uint64_t)
Definition: Time.cpp:139
Definition: main.cpp:291
std::unique_ptr< llvm::raw_fd_ostream > klee_open_output_file(const std::string &path, std::string &error)
FILE * klee_warning_file
void klee_message(const char *msg,...) __attribute__((format(printf
std::unique_ptr< llvm::Module > linkModules(std::vector< std::unique_ptr< llvm::Module > > &modules, llvm::StringRef entryFunction, std::string &errorMsg)
Definition: ModuleUtil.cpp:146
bool loadFile(const std::string &libraryName, llvm::LLVMContext &context, std::vector< std::unique_ptr< llvm::Module > > &modules, std::string &errorMsg)
cl::opt< std::string > MaxTime
void klee_error(const char *msg,...) __attribute__((format(printf
llvm::cl::OptionCategory SeedingCat
llvm::cl::OptionCategory TerminationCat
FILE * klee_message_file
void printVersion(llvm::raw_ostream &OS)
llvm::cl::OptionCategory DebugCat
StatisticManager * theStatisticManager
Definition: Statistics.cpp:57
char * name
Definition: KTest.h:19
unsigned char * bytes
Definition: KTest.h:21
unsigned numBytes
Definition: KTest.h:20
Definition: KTest.h:25
unsigned symArgvLen
Definition: KTest.h:33
unsigned numObjects
Definition: KTest.h:35
KTestObject * objects
Definition: KTest.h:36
unsigned numArgs
Definition: KTest.h:29
unsigned symArgvs
Definition: KTest.h:32
char ** args
Definition: KTest.h:30
std::tuple< std::uint32_t, std::uint8_t, std::uint8_t > toHMS() const
Definition: Time.cpp:167