Beispiel #1
0
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);
}
Beispiel #2
0
Module *klee::linkWithLibrary(Module *module, 
                              const std::string &libraryName) {
  KLEE_DEBUG_WITH_TYPE("klee_linker", dbgs() << "Linking file " << libraryName << "\n");
#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6)
  if (!sys::fs::exists(libraryName)) {
    klee_error("Link with library %s failed. No such file.",
        libraryName.c_str());
  }

  ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
      MemoryBuffer::getFile(libraryName);
  std::error_code ec;
  if ((ec = Buffer.getError())) {
    klee_error("Link with library %s failed: %s", libraryName.c_str(),
               ec.message().c_str());
  }

  sys::fs::file_magic magic =
      sys::fs::identify_magic(Buffer.get()->getBuffer());
  MemoryBufferRef BufferRef = Buffer.get()->getMemBufferRef();
  LLVMContext &Context = getGlobalContext();
  std::string ErrorMessage;

  if (magic == sys::fs::file_magic::bitcode) {

    ErrorOr<Module *> Result = parseBitcodeFile(BufferRef, Context);

    if ((ec = Buffer.getError()) || Linker::LinkModules(module, Result.get()))
      klee_error("Link with library %s failed: %s", libraryName.c_str(),
                 ErrorMessage.c_str());

    delete Result.get();

  } else if (magic == sys::fs::file_magic::archive) {

    ErrorOr<std::unique_ptr<object::Binary>> arch =
        object::createBinary(BufferRef, &Context);
    if ((ec = arch.getError()))
      klee_error("Link with library %s failed: %s", libraryName.c_str(),
                 arch.getError().message().c_str());
    if (object::Archive *a = dyn_cast<object::Archive>(arch.get().get())) {
      // Handle in helper
      if (!linkBCA(a, module, ErrorMessage))
        klee_error("Link with library %s failed: %s", libraryName.c_str(),
                   ErrorMessage.c_str());
    } else {
      klee_error("Link with library %s failed: Cast to archive failed",
                 libraryName.c_str());
    }

  } else if (magic.is_object()) {
    std::unique_ptr<object::Binary> obj;
    if (object::ObjectFile *o = dyn_cast<object::ObjectFile>(obj.get())) {
      klee_warning("Link with library: Object file %s in archive %s found. "
                   "Currently not supported.",
                   o->getFileName().data(), libraryName.c_str());
    }
  } else {
    klee_error("Link with library %s failed: Unrecognized file type.",
               libraryName.c_str());
  }
  return module;

#elif LLVM_VERSION_CODE >= LLVM_VERSION(3, 3)
  if (!sys::fs::exists(libraryName)) {
    klee_error("Link with library %s failed. No such file.",
               libraryName.c_str());
  }

  OwningPtr<MemoryBuffer> Buffer;
  if (error_code ec = MemoryBuffer::getFile(libraryName, Buffer)) {
    klee_error("Link with library %s failed: %s", libraryName.c_str(),
               ec.message().c_str());
  }

  sys::fs::file_magic magic = sys::fs::identify_magic(Buffer->getBuffer());

  LLVMContext &Context = getGlobalContext();
  std::string ErrorMessage;

  if (magic == sys::fs::file_magic::bitcode) {
    Module *Result = 0;
    Result = ParseBitcodeFile(Buffer.get(), Context, &ErrorMessage);

    if (!Result || Linker::LinkModules(module, Result, Linker::DestroySource,
                                       &ErrorMessage))
      klee_error("Link with library %s failed: %s", libraryName.c_str(),
                 ErrorMessage.c_str());

    delete Result;

  } else if (magic == sys::fs::file_magic::archive) {
    OwningPtr<object::Binary> arch;
    if (error_code ec = object::createBinary(Buffer.take(), arch))
      klee_error("Link with library %s failed: %s", libraryName.c_str(),
                 ec.message().c_str());

    if (object::Archive *a = dyn_cast<object::Archive>(arch.get())) {
      // Handle in helper
      if (!linkBCA(a, module, ErrorMessage))
        klee_error("Link with library %s failed: %s", libraryName.c_str(),
                   ErrorMessage.c_str());
    } else {
      klee_error("Link with library %s failed: Cast to archive failed",
                 libraryName.c_str());
    }

  } else if (magic.is_object()) {
    OwningPtr<object::Binary> obj;
    if (object::ObjectFile *o = dyn_cast<object::ObjectFile>(obj.get())) {
      klee_warning("Link with library: Object file %s in archive %s found. "
                   "Currently not supported.",
                   o->getFileName().data(), libraryName.c_str());
    }
  } else {
    klee_error("Link with library %s failed: Unrecognized file type.",
               libraryName.c_str());
  }

  return module;
#else
  Linker linker("klee", module, false);

  llvm::sys::Path libraryPath(libraryName);
  bool native = false;

  if (linker.LinkInFile(libraryPath, native)) {
    klee_error("Linking library %s failed", libraryName.c_str());
  }

  return linker.releaseModule();
#endif
}