void KModule::instrument(const Interpreter::ModuleOptions &opts) { // Inject checks prior to optimization... we also perform the // invariant transformations that we will end up doing later so that // optimize is seeing what is as close as possible to the final // module. LegacyLLVMPassManagerTy pm; pm.add(new RaiseAsmPass()); // This pass will scalarize as much code as possible so that the Executor // does not need to handle operands of vector type for most instructions // other than InsertElementInst and ExtractElementInst. // // NOTE: Must come before division/overshift checks because those passes // don't know how to handle vector instructions. pm.add(createScalarizerPass()); if (opts.CheckDivZero) pm.add(new DivCheckPass()); if (opts.CheckOvershift) pm.add(new OvershiftCheckPass()); pm.add(new IntrinsicCleanerPass(*targetData)); pm.run(*module); }
static bool valueIsOnlyCalled(const Value *v) { #if LLVM_VERSION_CODE < LLVM_VERSION(3, 5) for (auto it = v->use_begin(), ie = v->use_end(); it != ie; ++it) { auto user = *it; #else for (auto user : v->users()) { #endif if (const auto *instr = dyn_cast<Instruction>(user)) { // Make sure the instruction is a call or invoke. CallSite cs(const_cast<Instruction *>(instr)); if (!cs) return false; // Make sure that the value is only the target of this call and // not an argument. if (cs.hasArgument(v)) return false; } else if (const auto *ce = dyn_cast<ConstantExpr>(user)) { if (ce->getOpcode() == Instruction::BitCast) if (valueIsOnlyCalled(ce)) continue; return false; } else if (const auto *ga = dyn_cast<GlobalAlias>(user)) { if (v == ga->getAliasee() && !valueIsOnlyCalled(ga)) return false; } else if (isa<BlockAddress>(user)) { // only valid as operand to indirectbr or comparison against null continue; } else { return false; } } return true; } bool klee::functionEscapes(const Function *f) { return !valueIsOnlyCalled(f); } bool klee::loadFile(const std::string &fileName, LLVMContext &context, std::vector<std::unique_ptr<llvm::Module>> &modules, std::string &errorMsg) { KLEE_DEBUG_WITH_TYPE("klee_loader", dbgs() << "Load file " << fileName << "\n"); #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) ErrorOr<std::unique_ptr<MemoryBuffer>> bufferErr = MemoryBuffer::getFileOrSTDIN(fileName); std::error_code ec = bufferErr.getError(); #else OwningPtr<MemoryBuffer> Buffer; error_code ec = MemoryBuffer::getFileOrSTDIN(fileName, Buffer); #endif if (ec) { klee_error("Loading file %s failed: %s", fileName.c_str(), ec.message().c_str()); } #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) MemoryBufferRef Buffer = bufferErr.get()->getMemBufferRef(); #elif LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) MemoryBuffer *Buffer = bufferErr->get(); #endif #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) sys::fs::file_magic magic = sys::fs::identify_magic(Buffer.getBuffer()); #else sys::fs::file_magic magic = sys::fs::identify_magic(Buffer->getBuffer()); #endif if (magic == sys::fs::file_magic::bitcode) { SMDiagnostic Err; #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) std::unique_ptr<llvm::Module> module(parseIR(Buffer, Err, context)); #elif LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) std::unique_ptr<llvm::Module> module(ParseIR(Buffer, Err, context)); #else std::unique_ptr<llvm::Module> module(ParseIR(Buffer.take(), Err, context)); #endif if (!module) { klee_error("Loading file %s failed: %s", fileName.c_str(), Err.getMessage().str().c_str()); } modules.push_back(std::move(module)); return true; } if (magic == sys::fs::file_magic::archive) { #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) ErrorOr<std::unique_ptr<object::Binary>> archOwner = object::createBinary(Buffer, &context); ec = archOwner.getError(); llvm::object::Binary *arch = archOwner.get().get(); #elif LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) ErrorOr<object::Binary *> archOwner = object::createBinary(std::move(bufferErr.get()), &context); ec = archOwner.getError(); llvm::object::Binary *arch = archOwner.get(); #else OwningPtr<object::Binary> archOwner; ec = object::createBinary(Buffer.take(), archOwner); llvm::object::Binary *arch = archOwner.get(); #endif if (ec) klee_error("Loading file %s failed: %s", fileName.c_str(), ec.message().c_str()); if (auto archive = dyn_cast<object::Archive>(arch)) { // Load all bitcode files into memory #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) for (object::Archive::child_iterator AI = archive->child_begin(), AE = archive->child_end(); AI != AE; ++AI) #else for (object::Archive::child_iterator AI = archive->begin_children(), AE = archive->end_children(); AI != AE; ++AI) #endif { StringRef memberName; #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) std::error_code ec; #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 8) ErrorOr<object::Archive::Child> childOrErr = *AI; ec = childOrErr.getError(); if (ec) { errorMsg = ec.message(); return false; } #else object::Archive::child_iterator childOrErr = AI; #endif ErrorOr<StringRef> memberNameErr = childOrErr->getName(); ec = memberNameErr.getError(); if (!ec) { memberName = memberNameErr.get(); #else error_code ec = AI->getName(memberName); if (ec == errc::success) { #endif KLEE_DEBUG_WITH_TYPE("klee_linker", dbgs() << "Loading archive member " << memberName << "\n"); } else { errorMsg = "Archive member does not have a name!\n"; return false; } #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) ErrorOr<std::unique_ptr<llvm::object::Binary>> child = childOrErr->getAsBinary(); ec = child.getError(); #else OwningPtr<object::Binary> child; ec = AI->getAsBinary(child); #endif if (ec) { // If we can't open as a binary object file its hopefully a bitcode file #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) ErrorOr<MemoryBufferRef> buff = childOrErr->getMemoryBufferRef(); ec = buff.getError(); #elif LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) ErrorOr<std::unique_ptr<MemoryBuffer>> buffErr = AI->getMemoryBuffer(); std::unique_ptr<MemoryBuffer> buff = nullptr; ec = buffErr.getError(); if (!ec) buff = std::move(buffErr.get()); #else OwningPtr<MemoryBuffer> buff; ec = AI->getMemoryBuffer(buff); #endif if (ec) { errorMsg = "Failed to get MemoryBuffer: " + ec.message(); return false; } if (buff) { // FIXME: Maybe load bitcode file lazily? Then if we need to link, // materialise // the module SMDiagnostic Err; #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) std::unique_ptr<llvm::Module> module = parseIR(buff.get(), Err, context); #elif LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) std::unique_ptr<llvm::Module> module( ParseIR(buff.get(), Err, context)); #else std::unique_ptr<llvm::Module> module( ParseIR(buff.take(), Err, context)); #endif if (!module) { klee_error("Loading file %s failed: %s", fileName.c_str(), Err.getMessage().str().c_str()); } modules.push_back(std::move(module)); } else { errorMsg = "Buffer was NULL!"; return false; } } else if (child.get()->isObject()) { errorMsg = "Object file " + child.get()->getFileName().str() + " in archive is not supported"; return false; } else { errorMsg = "Loading archive child with error " + ec.message(); return false; } } } return true; } if (magic.is_object()) { errorMsg = "Loading file " + fileName + " Object file as input is currently not supported"; return false; } // This might still be an assembly file. Let's try to parse it. SMDiagnostic Err; #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) std::unique_ptr<llvm::Module> module(parseIR(Buffer, Err, context)); #elif LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) std::unique_ptr<llvm::Module> module(ParseIR(Buffer, Err, context)); #else std::unique_ptr<llvm::Module> module(ParseIR(Buffer.take(), Err, context)); #endif if (!module) { klee_error("Loading file %s failed: Unrecognized file type.", fileName.c_str()); } modules.push_back(std::move(module)); return true; } void klee::checkModule(llvm::Module *m) { LegacyLLVMPassManagerTy pm; pm.add(createVerifierPass()); pm.run(*m); }
void KModule::prepare(const Interpreter::ModuleOptions &opts, InterpreterHandler *ih) { // Inject checks prior to optimization... we also perform the // invariant transformations that we will end up doing later so that // optimize is seeing what is as close as possible to the final // module. LegacyLLVMPassManagerTy pm; pm.add(new RaiseAsmPass()); // This pass will scalarize as much code as possible so that the Executor // does not need to handle operands of vector type for most instructions // other than InsertElementInst and ExtractElementInst. // // NOTE: Must come before division/overshift checks because those passes // don't know how to handle vector instructions. pm.add(createScalarizerPass()); if (opts.CheckDivZero) pm.add(new DivCheckPass()); if (opts.CheckOvershift) pm.add(new OvershiftCheckPass()); // FIXME: This false here is to work around a bug in // IntrinsicLowering which caches values which may eventually be // deleted (via RAUW). This can be removed once LLVM fixes this // issue. pm.add(new IntrinsicCleanerPass(*targetData, false)); pm.run(*module); if (opts.Optimize) Optimize(module, opts.EntryPoint); // FIXME: Missing force import for various math functions. // FIXME: Find a way that we can test programs without requiring // this to be linked in, it makes low level debugging much more // annoying. SmallString<128> LibPath(opts.LibraryDir); llvm::sys::path::append(LibPath, "kleeRuntimeIntrinsic.bc" ); module = linkWithLibrary(module, LibPath.str()); // Add internal functions which are not used to check if instructions // have been already visited if (opts.CheckDivZero) addInternalFunction("klee_div_zero_check"); if (opts.CheckOvershift) addInternalFunction("klee_overshift_check"); // Needs to happen after linking (since ctors/dtors can be modified) // and optimization (since global optimization can rewrite lists). injectStaticConstructorsAndDestructors(module); // Finally, run the passes that maintain invariants we expect during // interpretation. We run the intrinsic cleaner just in case we // linked in something with intrinsics but any external calls are // going to be unresolved. We really need to handle the intrinsics // directly I think? LegacyLLVMPassManagerTy pm3; pm3.add(createCFGSimplificationPass()); switch(SwitchType) { case eSwitchTypeInternal: break; case eSwitchTypeSimple: pm3.add(new LowerSwitchPass()); break; case eSwitchTypeLLVM: pm3.add(createLowerSwitchPass()); break; default: klee_error("invalid --switch-type"); } InstructionOperandTypeCheckPass *operandTypeCheckPass = new InstructionOperandTypeCheckPass(); pm3.add(new IntrinsicCleanerPass(*targetData)); pm3.add(new PhiCleanerPass()); pm3.add(operandTypeCheckPass); pm3.run(*module); // Enforce the operand type invariants that the Executor expects. This // implicitly depends on the "Scalarizer" pass to be run in order to succeed // in the presence of vector instructions. if (!operandTypeCheckPass->checkPassed()) { klee_error("Unexpected instruction operand types detected"); } // Write out the .ll assembly file. We truncate long lines to work // around a kcachegrind parsing bug (it puts them on new lines), so // that source browsing works. if (OutputSource) { llvm::raw_fd_ostream *os = ih->openOutputFile("assembly.ll"); assert(os && !os->has_error() && "unable to open source output"); // We have an option for this in case the user wants a .ll they // can compile. if (NoTruncateSourceLines) { *os << *module; } else { std::string string; llvm::raw_string_ostream rss(string); rss << *module; rss.flush(); const char *position = string.c_str(); for (;;) { const char *end = index(position, '\n'); if (!end) { *os << position; break; } else { unsigned count = (end - position) + 1; if (count<255) { os->write(position, count); } else { os->write(position, 254); *os << "\n"; } position = end+1; } } } delete os; } if (OutputModule) { llvm::raw_fd_ostream *f = ih->openOutputFile("final.bc"); WriteBitcodeToFile(module, *f); delete f; } /* Build shadow structures */ infos = new InstructionInfoTable(module); for (Module::iterator it = module->begin(), ie = module->end(); it != ie; ++it) { if (it->isDeclaration()) continue; Function *fn = &*it; KFunction *kf = new KFunction(fn, this); for (unsigned i=0; i<kf->numInstructions; ++i) { KInstruction *ki = kf->instructions[i]; ki->info = &infos->getInfo(ki->inst); } functions.push_back(kf); functionMap.insert(std::make_pair(fn, kf)); } /* Compute various interesting properties */ for (std::vector<KFunction*>::iterator it = functions.begin(), ie = functions.end(); it != ie; ++it) { KFunction *kf = *it; if (functionEscapes(kf->function)) escapingFunctions.insert(kf->function); } if (DebugPrintEscapingFunctions && !escapingFunctions.empty()) { llvm::errs() << "KLEE: escaping functions: ["; for (std::set<Function*>::iterator it = escapingFunctions.begin(), ie = escapingFunctions.end(); it != ie; ++it) { llvm::errs() << (*it)->getName() << ", "; } llvm::errs() << "]\n"; } }