00001
00002
00003
00004 #include "../lib/Core/Common.h"
00005
00006 #include "klee/ExecutionState.h"
00007 #include "klee/Expr.h"
00008 #include "klee/Interpreter.h"
00009 #include "klee/Statistics.h"
00010 #include "klee/Config/config.h"
00011 #include "klee/Internal/ADT/KTest.h"
00012 #include "klee/Internal/ADT/TreeStream.h"
00013 #include "klee/Internal/Support/ModuleUtil.h"
00014 #include "klee/Internal/System/Time.h"
00015
00016 #include "llvm/Constants.h"
00017 #include "llvm/Module.h"
00018 #include "llvm/ModuleProvider.h"
00019 #include "llvm/Type.h"
00020 #include "llvm/InstrTypes.h"
00021 #include "llvm/Instruction.h"
00022 #include "llvm/Instructions.h"
00023 #include "llvm/Bitcode/ReaderWriter.h"
00024 #include "llvm/Support/CommandLine.h"
00025 #include "llvm/Support/ManagedStatic.h"
00026 #include "llvm/Support/MemoryBuffer.h"
00027 #include "llvm/System/Signals.h"
00028 #include <iostream>
00029 #include <fstream>
00030 #include <cerrno>
00031 #include <dirent.h>
00032 #include <errno.h>
00033 #include <sys/stat.h>
00034 #include <sys/wait.h>
00035 #include <signal.h>
00036
00037 #include <iostream>
00038 #include <iterator>
00039 #include <fstream>
00040 #include <sstream>
00041
00042 using namespace llvm;
00043 using namespace klee;
00044
00045 namespace {
00046 cl::opt<std::string>
00047 InputFile(cl::desc("<input bytecode>"), cl::Positional, cl::init("-"));
00048
00049 cl::opt<std::string>
00050 RunInDir("run-in", cl::desc("Change to the given directory prior to executing"));
00051
00052 cl::opt<std::string>
00053 Environ("environ", cl::desc("Parse environ from given file (in \"env\" format)"));
00054
00055 cl::list<std::string>
00056 InputArgv(cl::ConsumeAfter,
00057 cl::desc("<program arguments>..."));
00058
00059 cl::opt<bool>
00060 NoOutput("no-output",
00061 cl::desc("Don't generate test files"));
00062
00063 cl::opt<bool>
00064 WarnAllExternals("warn-all-externals",
00065 cl::desc("Give initial warning for all externals."));
00066
00067 cl::opt<bool>
00068 WriteCVCs("write-cvcs",
00069 cl::desc("Write .cvc files for each test case"));
00070
00071 cl::opt<bool>
00072 WritePCs("write-pcs",
00073 cl::desc("Write .pc files for each test case"));
00074
00075 cl::opt<bool>
00076 WriteCov("write-cov",
00077 cl::desc("Write coverage information for each test case"));
00078
00079 cl::opt<bool>
00080 WriteTestInfo("write-test-info",
00081 cl::desc("Write additional test case information"));
00082
00083 cl::opt<bool>
00084 WritePaths("write-paths",
00085 cl::desc("Write .path files for each test case"));
00086
00087 cl::opt<bool>
00088 WriteSymPaths("write-sym-paths",
00089 cl::desc("Write .sym.path files for each test case"));
00090
00091 cl::opt<bool>
00092 ExitOnError("exit-on-error",
00093 cl::desc("Exit if errors occur"));
00094
00095
00096 enum LibcType {
00097 NoLibc, KleeLibc, UcLibc
00098 };
00099
00100 cl::opt<LibcType>
00101 Libc("libc",
00102 cl::desc("Choose libc version (none by default)."),
00103 cl::values(clEnumValN(NoLibc, "none", "Don't link in a libc"),
00104 clEnumValN(KleeLibc, "klee", "Link in klee libc"),
00105 clEnumValN(UcLibc, "uclibc", "Link in uclibc (adapted for klee)"),
00106 clEnumValEnd),
00107 cl::init(NoLibc));
00108
00109
00110 cl::opt<bool>
00111 WithPOSIXRuntime("posix-runtime",
00112 cl::desc("Link with POSIX runtime"),
00113 cl::init(false));
00114
00115 cl::opt<bool>
00116 OptimizeModule("optimize",
00117 cl::desc("Optimize before execution"));
00118
00119 cl::opt<bool>
00120 CheckDivZero("check-div-zero",
00121 cl::desc("Inject checks for division-by-zero"),
00122 cl::init(true));
00123
00124 cl::opt<std::string>
00125 OutputDir("output-dir",
00126 cl::desc("Directory to write results in (defaults to klee-out-N)"),
00127 cl::init(""));
00128
00129
00130 cl::list<std::string>
00131 ReadArgsFilesFake("read-args",
00132 cl::desc("File to read arguments from (one arg per line)"));
00133
00134 cl::opt<bool>
00135 ReplayKeepSymbolic("replay-keep-symbolic",
00136 cl::desc("Replay the test cases only by asserting"
00137 "the bytes, not necessarily making them concrete."));
00138
00139 cl::list<std::string>
00140 ReplayOutFile("replay-out",
00141 cl::desc("Specify an out file to replay"),
00142 cl::value_desc("out file"));
00143
00144 cl::list<std::string>
00145 ReplayOutDir("replay-out-dir",
00146 cl::desc("Specify a directory to replay .out files from"),
00147 cl::value_desc("output directory"));
00148
00149 cl::opt<std::string>
00150 ReplayPathFile("replay-path",
00151 cl::desc("Specify a path file to replay"),
00152 cl::value_desc("path file"));
00153
00154 cl::list<std::string>
00155 SeedOutFile("seed-out");
00156
00157 cl::list<std::string>
00158 SeedOutDir("seed-out-dir");
00159
00160 cl::opt<unsigned>
00161 MakeConcreteSymbolic("make-concrete-symbolic",
00162 cl::desc("Rate at which to make concrete reads symbolic (0=off)"),
00163 cl::init(0));
00164
00165 cl::opt<bool>
00166 InitEnv("init-env",
00167 cl::desc("Create custom environment. Options that can be passed as arguments to the programs are: --sym-argv <max-len> --sym-argvs <min-argvs> <max-argvs> <max-len> + file model options"));
00168
00169 cl::opt<unsigned>
00170 StopAfterNTests("stop-after-n-tests",
00171 cl::desc("Stop execution after generating the given number of tests. Extra tests corresponding to partially explored paths will also be dumped."),
00172 cl::init(0));
00173
00174 cl::opt<bool>
00175 Watchdog("watchdog",
00176 cl::desc("Use a watchdog process to enforce --max-time."),
00177 cl::init(0));
00178 }
00179
00180 extern bool WriteTraces;
00181 extern cl::opt<double> MaxTime;
00182
00183
00184
00185 class KleeHandler : public InterpreterHandler {
00186 private:
00187 Interpreter *m_interpreter;
00188 TreeStreamWriter *m_pathWriter, *m_symPathWriter;
00189 std::ostream *m_infoFile;
00190
00191 char m_outputDirectory[1024];
00192 unsigned m_testIndex;
00193 unsigned m_pathsExplored;
00194
00195
00196 int m_argc;
00197 char **m_argv;
00198
00199 public:
00200 KleeHandler(int argc, char **argv);
00201 ~KleeHandler();
00202
00203 std::ostream &getInfoStream() const { return *m_infoFile; }
00204 unsigned getNumTestCases() { return m_testIndex; }
00205 unsigned getNumPathsExplored() { return m_pathsExplored; }
00206 void incPathsExplored() { m_pathsExplored++; }
00207
00208 void setInterpreter(Interpreter *i);
00209
00210 void processTestCase(const ExecutionState &state,
00211 const char *errorMessage,
00212 const char *errorSuffix);
00213
00214 std::string getOutputFilename(const std::string &filename);
00215 std::ostream *openOutputFile(const std::string &filename);
00216 std::string getTestFilename(const std::string &suffix, unsigned id);
00217 std::ostream *openTestFile(const std::string &suffix, unsigned id);
00218
00219
00220 static void loadOutFile(std::string name,
00221 std::vector<unsigned char> &buffer);
00222
00223
00224 static void loadPathFile(std::string name,
00225 std::vector<bool> &buffer);
00226
00227 static void getOutFiles(std::string path,
00228 std::vector<std::string> &results);
00229 };
00230
00231 KleeHandler::KleeHandler(int argc, char **argv)
00232 : m_interpreter(0),
00233 m_pathWriter(0),
00234 m_symPathWriter(0),
00235 m_infoFile(0),
00236 m_testIndex(0),
00237 m_pathsExplored(0),
00238 m_argc(argc),
00239 m_argv(argv) {
00240 std::string theDir;
00241
00242 if (OutputDir=="") {
00243 llvm::sys::Path directory(InputFile);
00244 std::string dirname = "";
00245 directory.eraseComponent();
00246
00247 if (directory.isEmpty())
00248 directory.set(".");
00249
00250 for (int i = 0; ; i++) {
00251 char buf[256], tmp[64];
00252 sprintf(tmp, "klee-out-%d", i);
00253 dirname = tmp;
00254 sprintf(buf, "%s/%s", directory.c_str(), tmp);
00255 theDir = buf;
00256
00257 if (DIR *dir = opendir(theDir.c_str())) {
00258 closedir(dir);
00259 } else {
00260 break;
00261 }
00262 }
00263
00264 llvm::cerr << "KLEE: output directory = \"" << dirname << "\"\n";
00265
00266 llvm::sys::Path klee_last(directory);
00267 klee_last.appendComponent("klee-last");
00268
00269 if ((unlink(klee_last.c_str()) < 0) && (errno != ENOENT)) {
00270 perror("Cannot unlink klee-last");
00271 assert(0 && "exiting.");
00272 }
00273
00274 if (symlink(dirname.c_str(), klee_last.c_str()) < 0) {
00275 perror("Cannot make symlink");
00276 assert(0 && "exiting.");
00277 }
00278 } else {
00279 theDir = OutputDir;
00280 }
00281
00282 sys::Path p(theDir);
00283 if (!p.isAbsolute()) {
00284 sys::Path cwd = sys::Path::GetCurrentDirectory();
00285 cwd.appendComponent(theDir);
00286 p = cwd;
00287 }
00288 strcpy(m_outputDirectory, p.c_str());
00289
00290 if (mkdir(m_outputDirectory, 0775) < 0) {
00291 llvm::cerr << "KLEE: ERROR: Unable to make output directory: \""
00292 << m_outputDirectory
00293 << "\", refusing to overwrite.\n";
00294 exit(1);
00295 }
00296
00297 char fname[1024];
00298 snprintf(fname, sizeof(fname), "%s/warnings.txt", m_outputDirectory);
00299 klee_warning_file = fopen(fname, "w");
00300 assert(klee_warning_file);
00301
00302 snprintf(fname, sizeof(fname), "%s/messages.txt", m_outputDirectory);
00303 klee_message_file = fopen(fname, "w");
00304 assert(klee_message_file);
00305
00306 m_infoFile = openOutputFile("info");
00307 }
00308
00309 KleeHandler::~KleeHandler() {
00310 if (m_pathWriter) delete m_pathWriter;
00311 if (m_symPathWriter) delete m_symPathWriter;
00312 delete m_infoFile;
00313 }
00314
00315 void KleeHandler::setInterpreter(Interpreter *i) {
00316 m_interpreter = i;
00317
00318 if (WritePaths) {
00319 m_pathWriter = new TreeStreamWriter(getOutputFilename("paths.ts"));
00320 assert(m_pathWriter->good());
00321 m_interpreter->setPathWriter(m_pathWriter);
00322 }
00323
00324 if (WriteSymPaths) {
00325 m_symPathWriter = new TreeStreamWriter(getOutputFilename("symPaths.ts"));
00326 assert(m_symPathWriter->good());
00327 m_interpreter->setSymbolicPathWriter(m_symPathWriter);
00328 }
00329 }
00330
00331 std::string KleeHandler::getOutputFilename(const std::string &filename) {
00332 char outfile[1024];
00333 sprintf(outfile, "%s/%s", m_outputDirectory, filename.c_str());
00334 return outfile;
00335 }
00336
00337 std::ostream *KleeHandler::openOutputFile(const std::string &filename) {
00338 std::ios::openmode io_mode = std::ios::out | std::ios::trunc
00339 | std::ios::binary;
00340 std::ostream *f;
00341 std::string path = getOutputFilename(filename);
00342 f = new std::ofstream(path.c_str(), io_mode);
00343 if (!f) {
00344 klee_warning("out of memory");
00345 } else if (!f->good()) {
00346 klee_warning("error opening: %s", filename.c_str());
00347 delete f;
00348 f = NULL;
00349 }
00350
00351 return f;
00352 }
00353
00354 std::string KleeHandler::getTestFilename(const std::string &suffix, unsigned id) {
00355 char filename[1024];
00356 sprintf(filename, "test%06d.%s", id, suffix.c_str());
00357 return getOutputFilename(filename);
00358 }
00359
00360 std::ostream *KleeHandler::openTestFile(const std::string &suffix, unsigned id) {
00361 char filename[1024];
00362 sprintf(filename, "test%06d.%s", id, suffix.c_str());
00363 return openOutputFile(filename);
00364 }
00365
00366
00367
00368 void KleeHandler::processTestCase(const ExecutionState &state,
00369 const char *errorMessage,
00370 const char *errorSuffix) {
00371 if (errorMessage && ExitOnError) {
00372 llvm::cerr << "EXITING ON ERROR: " << errorMessage << "\n";
00373 abort();
00374 }
00375
00376 if (!NoOutput) {
00377 std::vector< std::pair<std::string, std::vector<unsigned char> > > out;
00378 bool success = m_interpreter->getSymbolicSolution(state, out);
00379
00380 if (!success)
00381 klee_warning("unable to get symbolic solution, losing test case");
00382
00383 double start_time = util::getWallTime();
00384
00385 unsigned id = ++m_testIndex;
00386
00387 if (success) {
00388 KTest b;
00389 b.numArgs = m_argc;
00390 b.args = m_argv;
00391 b.symArgvs = 0;
00392 b.symArgvLen = 0;
00393 b.numObjects = out.size();
00394 b.objects = new KTestObject[b.numObjects];
00395 assert(b.objects);
00396 for (unsigned i=0; i<b.numObjects; i++) {
00397 KTestObject *o = &b.objects[i];
00398 o->name = const_cast<char*>(out[i].first.c_str());
00399 o->numBytes = out[i].second.size();
00400 o->bytes = new unsigned char[o->numBytes];
00401 assert(o->bytes);
00402 std::copy(out[i].second.begin(), out[i].second.end(), o->bytes);
00403 }
00404
00405 if (!kTest_toFile(&b, getTestFilename("ktest", id).c_str())) {
00406 klee_warning("unable to write output test case, losing it");
00407 }
00408
00409 for (unsigned i=0; i<b.numObjects; i++)
00410 delete[] b.objects[i].bytes;
00411 delete[] b.objects;
00412 }
00413
00414 if (errorMessage) {
00415 std::ostream *f = openTestFile(errorSuffix, id);
00416 *f << errorMessage;
00417 delete f;
00418 }
00419
00420 if (m_pathWriter) {
00421 std::vector<unsigned char> concreteBranches;
00422 m_pathWriter->readStream(m_interpreter->getPathStreamID(state),
00423 concreteBranches);
00424 std::ostream *f = openTestFile("path", id);
00425 std::copy(concreteBranches.begin(), concreteBranches.end(),
00426 std::ostream_iterator<unsigned char>(*f, "\n"));
00427 delete f;
00428 }
00429
00430 if (errorMessage || WritePCs) {
00431 std::string constraints;
00432 m_interpreter->getConstraintLog(state, constraints);
00433 std::ostream *f = openTestFile("pc", id);
00434 *f << constraints;
00435 delete f;
00436 }
00437
00438 if (WriteCVCs) {
00439 std::string constraints;
00440 m_interpreter->getConstraintLog(state, constraints, true);
00441 std::ostream *f = openTestFile("cvc", id);
00442 *f << constraints;
00443 delete f;
00444 }
00445
00446 if (m_symPathWriter) {
00447 std::vector<unsigned char> symbolicBranches;
00448 m_symPathWriter->readStream(m_interpreter->getSymbolicPathStreamID(state),
00449 symbolicBranches);
00450 std::ostream *f = openTestFile("sym.path", id);
00451 std::copy(symbolicBranches.begin(), symbolicBranches.end(),
00452 std::ostream_iterator<unsigned char>(*f, "\n"));
00453 delete f;
00454 }
00455
00456 if (WriteCov) {
00457 std::map<const std::string*, std::set<unsigned> > cov;
00458 m_interpreter->getCoveredLines(state, cov);
00459 std::ostream *f = openTestFile("cov", id);
00460 for (std::map<const std::string*, std::set<unsigned> >::iterator
00461 it = cov.begin(), ie = cov.end();
00462 it != ie; ++it) {
00463 for (std::set<unsigned>::iterator
00464 it2 = it->second.begin(), ie = it->second.end();
00465 it2 != ie; ++it2)
00466 *f << *it->first << ":" << *it2 << "\n";
00467 }
00468 delete f;
00469 }
00470
00471 if (WriteTraces) {
00472 std::ostream *f = openTestFile("trace", id);
00473 state.exeTraceMgr.printAllEvents(*f);
00474 delete f;
00475 }
00476
00477 if (m_testIndex == StopAfterNTests)
00478 m_interpreter->setHaltExecution(true);
00479
00480 if (WriteTestInfo) {
00481 double elapsed_time = util::getWallTime() - start_time;
00482 std::ostream *f = openTestFile("info", id);
00483 *f << "Time to generate test case: "
00484 << elapsed_time << "s\n";
00485 delete f;
00486 }
00487 }
00488 }
00489
00490
00491 void KleeHandler::loadPathFile(std::string name,
00492 std::vector<bool> &buffer) {
00493 std::ifstream f(name.c_str(), std::ios::in | std::ios::binary);
00494
00495 if (!f.good())
00496 assert(0 && "unable to open path file");
00497
00498 while (f.good()) {
00499 unsigned value;
00500 f >> value;
00501 buffer.push_back(!!value);
00502 f.get();
00503 }
00504 }
00505
00506 void KleeHandler::getOutFiles(std::string path,
00507 std::vector<std::string> &results) {
00508 llvm::sys::Path p(path);
00509 std::set<llvm::sys::Path> contents;
00510 std::string error;
00511 if (p.getDirectoryContents(contents, &error)) {
00512 llvm::cerr << "ERROR: unable to read output directory: " << path
00513 << ": " << error << "\n";
00514 exit(1);
00515 }
00516 for (std::set<llvm::sys::Path>::iterator it = contents.begin(),
00517 ie = contents.end(); it != ie; ++it) {
00518 std::string f = it->toString();
00519 if (f.substr(f.size()-6,f.size()) == ".ktest") {
00520 results.push_back(f);
00521 }
00522 }
00523 }
00524
00525
00526
00527
00528 #if ENABLE_STPLOG == 1
00529 extern "C" void STPLOG_init(const char *);
00530 #endif
00531
00532 static std::string strip(std::string &in) {
00533 unsigned len = in.size();
00534 unsigned lead = 0, trail = len;
00535 while (lead<len && isspace(in[lead]))
00536 ++lead;
00537 while (trail>lead && isspace(in[trail-1]))
00538 --trail;
00539 return in.substr(lead, trail-lead);
00540 }
00541
00542 static void readArgumentsFromFile(char *file, std::vector<std::string> &results) {
00543 std::ifstream f(file);
00544 assert(f.is_open() && "unable to open input for reading arguments");
00545 while (!f.eof()) {
00546 std::string line;
00547 std::getline(f, line);
00548 line = strip(line);
00549 if (!line.empty())
00550 results.push_back(line);
00551 }
00552 f.close();
00553 }
00554
00555 static void parseArguments(int argc, char **argv) {
00556 std::vector<std::string> arguments;
00557
00558 for (int i=1; i<argc; i++) {
00559 if (!strcmp(argv[i],"--read-args") && i+1<argc) {
00560 readArgumentsFromFile(argv[++i], arguments);
00561 } else {
00562 arguments.push_back(argv[i]);
00563 }
00564 }
00565
00566 int numArgs = arguments.size() + 1;
00567 const char **argArray = new const char*[numArgs+1];
00568 argArray[0] = argv[0];
00569 argArray[numArgs] = 0;
00570 for (int i=1; i<numArgs; i++) {
00571 argArray[i] = arguments[i-1].c_str();
00572 }
00573
00574 cl::ParseCommandLineOptions(numArgs, (char**) argArray, " klee\n");
00575 delete[] argArray;
00576 }
00577
00578
00579
00580 static int initEnv(Module *mainModule) {
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594 Function *mainFn = mainModule->getFunction("main");
00595
00596 if (mainFn->arg_size() < 2) {
00597 llvm::cerr << "Cannot handle ""-init-env"" when main() has less than two arguments.\n";
00598 return -1;
00599 }
00600
00601 Instruction* firstInst = mainFn->begin()->begin();
00602
00603 Value* oldArgc = mainFn->arg_begin();
00604 Value* oldArgv = ++mainFn->arg_begin();
00605
00606 AllocaInst* argcPtr = new AllocaInst(oldArgc->getType(), "argcPtr", firstInst);
00607 AllocaInst* argvPtr = new AllocaInst(oldArgv->getType(), "argvPtr", firstInst);
00608
00609
00610 std::vector<const Type*> params;
00611 params.push_back(Type::Int32Ty);
00612 params.push_back(Type::Int32Ty);
00613 Function* initEnvFn =
00614 cast<Function>(mainModule->getOrInsertFunction("klee_init_env",
00615 Type::VoidTy,
00616 argcPtr->getType(),
00617 argvPtr->getType(),
00618 NULL));
00619 assert(initEnvFn);
00620 std::vector<Value*> args;
00621 args.push_back(argcPtr);
00622 args.push_back(argvPtr);
00623 Instruction* initEnvCall = CallInst::Create(initEnvFn, args.begin(), args.end(),
00624 "", firstInst);
00625 Value *argc = new LoadInst(argcPtr, "newArgc", firstInst);
00626 Value *argv = new LoadInst(argvPtr, "newArgv", firstInst);
00627
00628 oldArgc->replaceAllUsesWith(argc);
00629 oldArgv->replaceAllUsesWith(argv);
00630
00631 new StoreInst(oldArgc, argcPtr, initEnvCall);
00632 new StoreInst(oldArgv, argvPtr, initEnvCall);
00633
00634 return 0;
00635 }
00636
00637
00638
00639
00640
00641
00642
00643 static const char *modelledExternals[] = {
00644 "_ZTVN10__cxxabiv117__class_type_infoE",
00645 "_ZTVN10__cxxabiv120__si_class_type_infoE",
00646 "_ZTVN10__cxxabiv121__vmi_class_type_infoE",
00647
00648
00649 "_assert",
00650 "__assert_fail",
00651 "__assert_rtn",
00652 "calloc",
00653 "_exit",
00654 "exit",
00655 "free",
00656 "abort",
00657 "klee_abort",
00658 "klee_assume",
00659 "klee_check_memory_access",
00660 "klee_define_fixed_object",
00661 "klee_get_errno",
00662 "klee_get_value",
00663 "klee_get_obj_size",
00664 "klee_is_symbolic",
00665 "klee_make_symbolic",
00666 "klee_mark_global",
00667 "klee_merge",
00668 "klee_prefer_cex",
00669 "klee_print_expr",
00670 "klee_print_range",
00671 "klee_report_error",
00672 "klee_revirt_objects",
00673 "klee_set_forking",
00674 "klee_silent_exit",
00675 "klee_under_constrained",
00676 "klee_warning",
00677 "klee_warning_once",
00678 "klee_alias_function",
00679 "llvm.dbg.stoppoint",
00680 "llvm.va_start",
00681 "llvm.va_end",
00682 "malloc",
00683 "realloc",
00684 "_ZdaPv",
00685 "_ZdlPv",
00686 "_Znaj",
00687 "_Znwj",
00688 "_Znam",
00689 "_Znwm",
00690 };
00691
00692 static const char *dontCareExternals[] = {
00693 #if 0
00694
00695 "fprintf",
00696 "fflush",
00697 "fopen",
00698 "fclose",
00699 "fputs_unlocked",
00700 "putchar_unlocked",
00701 "vfprintf",
00702 "fwrite",
00703 "puts",
00704 "printf",
00705 "stdin",
00706 "stdout",
00707 "stderr",
00708 "_stdio_term",
00709 "__errno_location",
00710 "fstat",
00711 #endif
00712
00713
00714 "getegid",
00715 "geteuid",
00716 "getgid",
00717 "getuid",
00718 "getpid",
00719 "gethostname",
00720 "getpgrp",
00721 "getppid",
00722 "getpagesize",
00723 "getpriority",
00724 "getgroups",
00725 "getdtablesize",
00726 "getrlimit",
00727 "getrlimit64",
00728 "getcwd",
00729 "getwd",
00730 "gettimeofday",
00731 "uname",
00732
00733
00734 "frexp",
00735 "ldexp",
00736 "__isnan",
00737 "__signbit",
00738 };
00739
00740 static const char *dontCareKlee[] = {
00741 "__ctype_b_loc",
00742 "__ctype_get_mb_cur_max",
00743
00744
00745 "open",
00746 "write",
00747 "read",
00748 "close",
00749 };
00750
00751 static const char *dontCareUclibc[] = {
00752 "__dso_handle",
00753
00754
00755
00756 "printf",
00757 "vprintf"
00758 };
00759
00760 static const char *unsafeExternals[] = {
00761 "fork",
00762 "exec",
00763 "error",
00764 "raise",
00765 "kill",
00766 };
00767 #define NELEMS(array) (sizeof(array)/sizeof(array[0]))
00768 void externalsAndGlobalsCheck(const Module *m) {
00769 std::map<std::string, bool> externals;
00770 std::set<std::string> modelled(modelledExternals,
00771 modelledExternals+NELEMS(modelledExternals));
00772 std::set<std::string> dontCare(dontCareExternals,
00773 dontCareExternals+NELEMS(dontCareExternals));
00774 std::set<std::string> unsafe(unsafeExternals,
00775 unsafeExternals+NELEMS(unsafeExternals));
00776
00777 switch (Libc) {
00778 case KleeLibc:
00779 dontCare.insert(dontCareKlee, dontCareKlee+NELEMS(dontCareKlee));
00780 break;
00781 case UcLibc:
00782 dontCare.insert(dontCareUclibc,
00783 dontCareUclibc+NELEMS(dontCareUclibc));
00784 break;
00785 case NoLibc:
00786 break;
00787 }
00788
00789
00790 if (WithPOSIXRuntime)
00791 dontCare.insert("syscall");
00792
00793 for (Module::const_iterator fnIt = m->begin(), fn_ie = m->end();
00794 fnIt != fn_ie; ++fnIt) {
00795 if (fnIt->isDeclaration() && !fnIt->use_empty())
00796 externals.insert(std::make_pair(fnIt->getName(), false));
00797 for (Function::const_iterator bbIt = fnIt->begin(), bb_ie = fnIt->end();
00798 bbIt != bb_ie; ++bbIt) {
00799 for (BasicBlock::const_iterator it = bbIt->begin(), ie = bbIt->end();
00800 it != it; ++it) {
00801 if (const CallInst *ci = dyn_cast<CallInst>(it)) {
00802 if (isa<InlineAsm>(ci->getCalledValue())) {
00803 klee_warning_once(&*fnIt,
00804 "function \"%s\" has inline asm",
00805 fnIt->getName().c_str());
00806 }
00807 }
00808 }
00809 }
00810 }
00811 for (Module::const_global_iterator
00812 it = m->global_begin(), ie = m->global_end();
00813 it != ie; ++it)
00814 if (it->isDeclaration() && !it->use_empty())
00815 externals.insert(std::make_pair(it->getName(), true));
00816
00817
00818 for (Module::const_alias_iterator
00819 it = m->alias_begin(), ie = m->alias_end();
00820 it != ie; ++it) {
00821 std::map<std::string, bool>::iterator it2 =
00822 externals.find(it->getName());
00823 if (it2!=externals.end())
00824 externals.erase(it2);
00825 }
00826
00827 std::map<std::string, bool> foundUnsafe;
00828 for (std::map<std::string, bool>::iterator
00829 it = externals.begin(), ie = externals.end();
00830 it != ie; ++it) {
00831 const std::string &ext = it->first;
00832 if (!modelled.count(ext) && (WarnAllExternals ||
00833 !dontCare.count(ext))) {
00834 if (unsafe.count(ext)) {
00835 foundUnsafe.insert(*it);
00836 } else {
00837 klee_warning("undefined reference to %s: %s",
00838 it->second ? "variable" : "function",
00839 ext.c_str());
00840 }
00841 }
00842 }
00843
00844 for (std::map<std::string, bool>::iterator
00845 it = foundUnsafe.begin(), ie = foundUnsafe.end();
00846 it != ie; ++it) {
00847 const std::string &ext = it->first;
00848 klee_warning("undefined reference to %s: %s (UNSAFE)!",
00849 it->second ? "variable" : "function",
00850 ext.c_str());
00851 }
00852 }
00853
00854 static Interpreter *theInterpreter = 0;
00855
00856 static bool interrupted = false;
00857
00858
00859 extern "C"
00860 void halt_execution() {
00861 theInterpreter->setHaltExecution(true);
00862 }
00863
00864 extern "C"
00865 void stop_forking() {
00866 theInterpreter->setInhibitForking(true);
00867 }
00868
00869 static void interrupt_handle() {
00870 if (!interrupted && theInterpreter) {
00871 llvm::cerr << "KLEE: ctrl-c detected, requesting interpreter to halt.\n";
00872 halt_execution();
00873 sys::SetInterruptFunction(interrupt_handle);
00874 } else {
00875 llvm::cerr << "KLEE: ctrl-c detected, exiting.\n";
00876 exit(1);
00877 }
00878 interrupted = true;
00879 }
00880
00881
00882
00883
00884
00885
00886 static void halt_via_gdb(int pid) {
00887 char buffer[256];
00888 sprintf(buffer,
00889 "gdb --batch --eval-command=\"p halt_execution()\" "
00890 "--eval-command=detach --pid=%d &> /dev/null",
00891 pid);
00892
00893 if (system(buffer)==-1)
00894 perror("system");
00895 }
00896
00897
00898 static char *format_tdiff(char *buf, long seconds)
00899 {
00900 assert(seconds >= 0);
00901
00902 long minutes = seconds / 60; seconds %= 60;
00903 long hours = minutes / 60; minutes %= 60;
00904 long days = hours / 24; hours %= 24;
00905
00906 buf = strrchr(buf, '\0');
00907 if (days > 0) buf += sprintf(buf, "%ld days, ", days);
00908 buf += sprintf(buf, "%02ld:%02ld:%02ld", hours, minutes, seconds);
00909 return buf;
00910 }
00911
00912 #ifndef KLEE_UCLIBC
00913 static llvm::Module *linkWithUclibc(llvm::Module *mainModule) {
00914 fprintf(stderr, "error: invalid libc, no uclibc support!\n");
00915 exit(1);
00916 return 0;
00917 }
00918 #else
00919 static llvm::Module *linkWithUclibc(llvm::Module *mainModule) {
00920 Function *f;
00921
00922 mainModule->getOrInsertFunction("__uClibc_main",
00923 FunctionType::get(Type::VoidTy,
00924 std::vector<const Type*>(),
00925 true));
00926
00927
00928 if (WithPOSIXRuntime) {
00929 mainModule->getOrInsertFunction("realpath",
00930 PointerType::getUnqual(Type::Int8Ty),
00931 PointerType::getUnqual(Type::Int8Ty),
00932 PointerType::getUnqual(Type::Int8Ty),
00933 NULL);
00934 mainModule->getOrInsertFunction("getutent",
00935 PointerType::getUnqual(Type::Int8Ty),
00936 NULL);
00937 mainModule->getOrInsertFunction("__fgetc_unlocked",
00938 Type::Int32Ty,
00939 PointerType::getUnqual(Type::Int8Ty),
00940 NULL);
00941 mainModule->getOrInsertFunction("__fputc_unlocked",
00942 Type::Int32Ty,
00943 Type::Int32Ty,
00944 PointerType::getUnqual(Type::Int8Ty),
00945 NULL);
00946 }
00947
00948 f = mainModule->getFunction("__ctype_get_mb_cur_max");
00949 if (f) f->setName("_stdlib_mb_cur_max");
00950
00951
00952
00953
00954
00955
00956 for (Module::iterator fi = mainModule->begin(), fe = mainModule->end();
00957 fi != fe;) {
00958 Function *f = fi;
00959 ++fi;
00960 const std::string &name = f->getName();
00961 if (name[0]=='\01') {
00962 unsigned size = name.size();
00963 if (name[size-2]=='6' && name[size-1]=='4') {
00964 std::string unprefixed = name.substr(1);
00965
00966
00967 if (Function *f2 = mainModule->getFunction(unprefixed)) {
00968 f->replaceAllUsesWith(f2);
00969 f->eraseFromParent();
00970 } else {
00971 f->setName(unprefixed);
00972 }
00973 }
00974 }
00975 }
00976
00977 mainModule = klee::linkWithLibrary(mainModule,
00978 KLEE_UCLIBC "/lib/libc.a");
00979 assert(mainModule && "unable to link with uclibc");
00980
00981
00982
00983
00984
00985
00986
00987 Function *f2;
00988 f = mainModule->getFunction("open");
00989 f2 = mainModule->getFunction("__libc_open");
00990 if (f2) {
00991 if (f) {
00992 f2->replaceAllUsesWith(f);
00993 f2->eraseFromParent();
00994 } else {
00995 f2->setName("open");
00996 assert(f2->getName() == "open");
00997 }
00998 }
00999
01000 f = mainModule->getFunction("fcntl");
01001 f2 = mainModule->getFunction("__libc_fcntl");
01002 if (f2) {
01003 if (f) {
01004 f2->replaceAllUsesWith(f);
01005 f2->eraseFromParent();
01006 } else {
01007 f2->setName("fcntl");
01008 assert(f2->getName() == "fcntl");
01009 }
01010 }
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022 Function *userMainFn = mainModule->getFunction("main");
01023 assert(userMainFn && "unable to get user main");
01024 Function *uclibcMainFn = mainModule->getFunction("__uClibc_main");
01025 assert(uclibcMainFn && "unable to get uclibc main");
01026 userMainFn->setName("__user_main");
01027
01028 const FunctionType *ft = uclibcMainFn->getFunctionType();
01029 assert(ft->getNumParams() == 7);
01030
01031 std::vector<const Type*> fArgs;
01032 fArgs.push_back(ft->getParamType(1));
01033 fArgs.push_back(ft->getParamType(2));
01034 Function *stub = Function::Create(FunctionType::get(Type::Int32Ty, fArgs, false),
01035 GlobalVariable::ExternalLinkage,
01036 "main",
01037 mainModule);
01038 BasicBlock *bb = BasicBlock::Create("entry", stub);
01039
01040 std::vector<llvm::Value*> args;
01041 args.push_back(llvm::ConstantExpr::getBitCast(userMainFn,
01042 ft->getParamType(0)));
01043 args.push_back(stub->arg_begin());
01044 args.push_back(++stub->arg_begin());
01045 args.push_back(Constant::getNullValue(ft->getParamType(3)));
01046 args.push_back(Constant::getNullValue(ft->getParamType(4)));
01047 args.push_back(Constant::getNullValue(ft->getParamType(5)));
01048 args.push_back(Constant::getNullValue(ft->getParamType(6)));
01049 CallInst::Create(uclibcMainFn, args.begin(), args.end(), "", bb);
01050
01051 new UnreachableInst(bb);
01052
01053 return mainModule;
01054 }
01055 #endif
01056
01057 int main(int argc, char **argv, char **envp) {
01058 #if ENABLE_STPLOG == 1
01059 STPLOG_init("stplog.c");
01060 #endif
01061
01062 atexit(llvm_shutdown);
01063 parseArguments(argc, argv);
01064 sys::PrintStackTraceOnErrorSignal();
01065
01066 if (Watchdog) {
01067 if (MaxTime==0) {
01068 klee_error("--watchdog used without --max-time");
01069 }
01070
01071 int pid = fork();
01072 if (pid<0) {
01073 klee_error("unable to fork watchdog");
01074 } else if (pid) {
01075 fprintf(stderr, "KLEE: WATCHDOG: watching %d\n", pid);
01076 fflush(stderr);
01077
01078 double nextStep = util::getWallTime() + MaxTime*1.1;
01079 int level = 0;
01080
01081
01082 while (1) {
01083 sleep(1);
01084
01085 int status, res = waitpid(pid, &status, WNOHANG);
01086
01087 if (res < 0) {
01088 if (errno==ECHILD) {
01089
01090
01091 fprintf(stderr, "KLEE: watchdog exiting (no child)\n");
01092 return 1;
01093 } else if (errno!=EINTR) {
01094 perror("watchdog waitpid");
01095 exit(1);
01096 }
01097 } else if (res==pid && WIFEXITED(status)) {
01098 return WEXITSTATUS(status);
01099 } else {
01100 double time = util::getWallTime();
01101
01102 if (time > nextStep) {
01103 ++level;
01104
01105 if (level==1) {
01106 fprintf(stderr, "KLEE: WATCHDOG: time expired, attempting halt via INT\n");
01107 kill(pid, SIGINT);
01108 } else if (level==2) {
01109 fprintf(stderr, "KLEE: WATCHDOG: time expired, attempting halt via gdb\n");
01110 halt_via_gdb(pid);
01111 } else {
01112 fprintf(stderr, "KLEE: WATCHDOG: kill(9)ing child (I tried to be nice)\n");
01113 kill(pid, SIGKILL);
01114 return 1;
01115 }
01116
01117
01118
01119 nextStep = util::getWallTime() + std::max(15., MaxTime*.1);
01120 }
01121 }
01122 }
01123
01124 return 0;
01125 }
01126 }
01127
01128 sys::SetInterruptFunction(interrupt_handle);
01129
01130
01131 std::string ErrorMsg;
01132 ModuleProvider *MP = 0;
01133 if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFile, &ErrorMsg)) {
01134 MP = getBitcodeModuleProvider(Buffer, &ErrorMsg);
01135 if (!MP) delete Buffer;
01136 }
01137
01138 if (!MP)
01139 klee_error("error loading program '%s': %s", InputFile.c_str(), ErrorMsg.c_str());
01140
01141 Module *mainModule = MP->materializeModule();
01142 MP->releaseModule();
01143 delete MP;
01144
01145 assert(mainModule && "unable to materialize");
01146
01147 if (WithPOSIXRuntime)
01148 InitEnv = true;
01149
01150 if (InitEnv) {
01151 int r = initEnv(mainModule);
01152 if (r != 0)
01153 return r;
01154 }
01155
01156 llvm::sys::Path LibraryDir(KLEE_DIR "/" RUNTIME_CONFIGURATION "/lib");
01157 Interpreter::ModuleOptions Opts(LibraryDir.c_str(),
01158 OptimizeModule,
01159 CheckDivZero);
01160
01161 switch (Libc) {
01162 case NoLibc:
01163 break;
01164
01165 case KleeLibc: {
01166
01167 llvm::sys::Path Path(Opts.LibraryDir);
01168 Path.appendComponent("libklee-libc.bca");
01169 mainModule = klee::linkWithLibrary(mainModule, Path.c_str());
01170 assert(mainModule && "unable to link with klee-libc");
01171 break;
01172 }
01173
01174 case UcLibc:
01175 mainModule = linkWithUclibc(mainModule);
01176 break;
01177 }
01178
01179 if (WithPOSIXRuntime) {
01180 llvm::sys::Path Path(Opts.LibraryDir);
01181 Path.appendComponent("libkleeRuntimePOSIX.bca");
01182 klee_message("NOTE: Using model: %s", Path.c_str());
01183 mainModule = klee::linkWithLibrary(mainModule, Path.c_str());
01184 assert(mainModule && "unable to link with simple model");
01185 }
01186
01187
01188
01189 Function *mainFn = mainModule->getFunction("main");
01190 if (!mainFn) {
01191 llvm::cerr << "'main' function not found in module.\n";
01192 return -1;
01193 }
01194
01195
01196 int pArgc;
01197 char **pArgv;
01198 char **pEnvp;
01199 if (Environ != "") {
01200 std::vector<std::string> items;
01201 std::ifstream f(Environ.c_str());
01202 if (!f.good())
01203 klee_error("unable to open --environ file: %s", Environ.c_str());
01204 while (!f.eof()) {
01205 std::string line;
01206 std::getline(f, line);
01207 line = strip(line);
01208 if (!line.empty())
01209 items.push_back(line);
01210 }
01211 f.close();
01212 pEnvp = new char *[items.size()+1];
01213 unsigned i=0;
01214 for (; i != items.size(); ++i)
01215 pEnvp[i] = strdup(items[i].c_str());
01216 pEnvp[i] = 0;
01217 } else {
01218 pEnvp = envp;
01219 }
01220
01221 pArgc = InputArgv.size() + 1;
01222 pArgv = new char *[pArgc];
01223 for (unsigned i=0; i<InputArgv.size()+1; i++) {
01224 std::string &arg = (i==0 ? InputFile : InputArgv[i-1]);
01225 unsigned size = arg.size() + 1;
01226 char *pArg = new char[size];
01227
01228 std::copy(arg.begin(), arg.end(), pArg);
01229 pArg[size - 1] = 0;
01230
01231 pArgv[i] = pArg;
01232 }
01233
01234 std::vector<bool> replayPath;
01235
01236 if (ReplayPathFile != "") {
01237 KleeHandler::loadPathFile(ReplayPathFile, replayPath);
01238 }
01239
01240 Interpreter::InterpreterOptions IOpts;
01241 IOpts.MakeConcreteSymbolic = MakeConcreteSymbolic;
01242 KleeHandler *handler = new KleeHandler(pArgc, pArgv);
01243 Interpreter *interpreter =
01244 theInterpreter = Interpreter::create(IOpts, handler);
01245 handler->setInterpreter(interpreter);
01246
01247 std::ostream &infoFile = handler->getInfoStream();
01248 for (int i=0; i<argc; i++) {
01249 infoFile << argv[i] << (i+1<argc ? " ":"\n");
01250 }
01251 infoFile << "PID: " << getpid() << "\n";
01252
01253 const Module *finalModule =
01254 interpreter->setModule(mainModule, Opts);
01255 externalsAndGlobalsCheck(finalModule);
01256
01257 if (ReplayPathFile != "") {
01258 interpreter->setReplayPath(&replayPath);
01259 }
01260
01261 char buf[256];
01262 time_t t[2];
01263 t[0] = time(NULL);
01264 strftime(buf, sizeof(buf), "Started: %Y-%m-%d %H:%M:%S\n", localtime(&t[0]));
01265 infoFile << buf;
01266 infoFile.flush();
01267
01268 if (!ReplayOutDir.empty() || !ReplayOutFile.empty()) {
01269 assert(SeedOutFile.empty());
01270 assert(SeedOutDir.empty());
01271
01272 std::vector<std::string> outFiles = ReplayOutFile;
01273 for (std::vector<std::string>::iterator
01274 it = ReplayOutDir.begin(), ie = ReplayOutDir.end();
01275 it != ie; ++it)
01276 KleeHandler::getOutFiles(*it, outFiles);
01277 std::vector<KTest*> kTests;
01278 for (std::vector<std::string>::iterator
01279 it = outFiles.begin(), ie = outFiles.end();
01280 it != ie; ++it) {
01281 KTest *out = kTest_fromFile(it->c_str());
01282 if (out) {
01283 kTests.push_back(out);
01284 } else {
01285 llvm::cerr << "KLEE: unable to open: " << *it << "\n";
01286 }
01287 }
01288
01289 if (RunInDir != "") {
01290 int res = chdir(RunInDir.c_str());
01291 if (res < 0) {
01292 klee_error("Unable to change directory to: %s", RunInDir.c_str());
01293 }
01294 }
01295
01296 unsigned i=0;
01297 for (std::vector<KTest*>::iterator
01298 it = kTests.begin(), ie = kTests.end();
01299 it != ie; ++it) {
01300 KTest *out = *it;
01301 interpreter->setReplayOut(out);
01302 llvm::cerr << "KLEE: replaying: " << *it << " (" << kTest_numBytes(out) << " bytes)"
01303 << " (" << ++i << "/" << outFiles.size() << ")\n";
01304
01305 interpreter->runFunctionAsMain(mainFn, out->numArgs, out->args, pEnvp);
01306 if (interrupted) break;
01307 }
01308 interpreter->setReplayOut(0);
01309 while (!kTests.empty()) {
01310 kTest_free(kTests.back());
01311 kTests.pop_back();
01312 }
01313 } else {
01314 std::vector<KTest *> seeds;
01315 for (std::vector<std::string>::iterator
01316 it = SeedOutFile.begin(), ie = SeedOutFile.end();
01317 it != ie; ++it) {
01318 KTest *out = kTest_fromFile(it->c_str());
01319 if (!out) {
01320 llvm::cerr << "KLEE: unable to open: " << *it << "\n";
01321 exit(1);
01322 }
01323 seeds.push_back(out);
01324 }
01325 for (std::vector<std::string>::iterator
01326 it = SeedOutDir.begin(), ie = SeedOutDir.end();
01327 it != ie; ++it) {
01328 std::vector<std::string> outFiles;
01329 KleeHandler::getOutFiles(*it, outFiles);
01330 for (std::vector<std::string>::iterator
01331 it2 = outFiles.begin(), ie = outFiles.end();
01332 it2 != ie; ++it2) {
01333 KTest *out = kTest_fromFile(it2->c_str());
01334 if (!out) {
01335 llvm::cerr << "KLEE: unable to open: " << *it2 << "\n";
01336 exit(1);
01337 }
01338 seeds.push_back(out);
01339 }
01340 if (outFiles.empty()) {
01341 llvm::cerr << "KLEE: seeds directory is empty: " << *it << "\n";
01342 exit(1);
01343 }
01344 }
01345
01346 if (!seeds.empty()) {
01347 llvm::cerr << "KLEE: using " << seeds.size() << " seeds\n";
01348 interpreter->useSeeds(&seeds);
01349 }
01350 if (RunInDir != "") {
01351 int res = chdir(RunInDir.c_str());
01352 if (res < 0) {
01353 klee_error("Unable to change directory to: %s", RunInDir.c_str());
01354 }
01355 }
01356 interpreter->runFunctionAsMain(mainFn, pArgc, pArgv, pEnvp);
01357
01358 while (!seeds.empty()) {
01359 kTest_free(seeds.back());
01360 seeds.pop_back();
01361 }
01362 }
01363
01364 t[1] = time(NULL);
01365 strftime(buf, sizeof(buf), "Finished: %Y-%m-%d %H:%M:%S\n", localtime(&t[1]));
01366 infoFile << buf;
01367
01368 strcpy(buf, "Elapsed: ");
01369 strcpy(format_tdiff(buf, t[1] - t[0]), "\n");
01370 infoFile << buf;
01371
01372
01373 for (unsigned i=0; i<InputArgv.size()+1; i++)
01374 delete[] pArgv[i];
01375 delete[] pArgv;
01376
01377 delete interpreter;
01378
01379 uint64_t queries =
01380 *theStatisticManager->getStatisticByName("Queries");
01381 uint64_t queriesValid =
01382 *theStatisticManager->getStatisticByName("QueriesValid");
01383 uint64_t queriesInvalid =
01384 *theStatisticManager->getStatisticByName("QueriesInvalid");
01385 uint64_t queryCounterexamples =
01386 *theStatisticManager->getStatisticByName("QueriesCEX");
01387 uint64_t queryConstructs =
01388 *theStatisticManager->getStatisticByName("QueriesConstructs");
01389 uint64_t instructions =
01390 *theStatisticManager->getStatisticByName("Instructions");
01391 uint64_t forks =
01392 *theStatisticManager->getStatisticByName("Forks");
01393
01394 handler->getInfoStream()
01395 << "KLEE: done: explored paths = " << 1 + forks << "\n";
01396
01397
01398
01399 if (queries)
01400 handler->getInfoStream()
01401 << "KLEE: done: avg. constructs per query = "
01402 << queryConstructs / queries << "\n";
01403 handler->getInfoStream()
01404 << "KLEE: done: total queries = " << queries << "\n"
01405 << "KLEE: done: valid queries = " << queriesValid << "\n"
01406 << "KLEE: done: invalid queriers = " << queriesInvalid << "\n"
01407 << "KLEE: done: query cex = " << queryCounterexamples << "\n";
01408
01409 std::stringstream stats;
01410 stats << "KLEE: done: total instructions = "
01411 << instructions << "\n";
01412 stats << "KLEE: done: completed paths = "
01413 << handler->getNumPathsExplored() << "\n";
01414 stats << "KLEE: done: generated tests = "
01415 << handler->getNumTestCases() << "\n";
01416 llvm::cerr << stats.str();
01417 handler->getInfoStream() << stats.str();
01418
01419 delete handler;
01420
01421 return 0;
01422 }