| //===-- FuzzerCLI.cpp -----------------------------------------------------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "llvm/FuzzMutate/FuzzerCLI.h" | 
 | #include "llvm/ADT/Triple.h" | 
 | #include "llvm/Bitcode/BitcodeReader.h" | 
 | #include "llvm/Bitcode/BitcodeWriter.h" | 
 | #include "llvm/IR/LLVMContext.h" | 
 | #include "llvm/Support/CommandLine.h" | 
 | #include "llvm/Support/Compiler.h" | 
 | #include "llvm/Support/Error.h" | 
 | #include "llvm/Support/MemoryBuffer.h" | 
 | #include "llvm/Support/SourceMgr.h" | 
 | #include "llvm/Support/raw_ostream.h" | 
 | #include "llvm/IR/Verifier.h" | 
 |  | 
 | using namespace llvm; | 
 |  | 
 | void llvm::parseFuzzerCLOpts(int ArgC, char *ArgV[]) { | 
 |   std::vector<const char *> CLArgs; | 
 |   CLArgs.push_back(ArgV[0]); | 
 |  | 
 |   int I = 1; | 
 |   while (I < ArgC) | 
 |     if (StringRef(ArgV[I++]).equals("-ignore_remaining_args=1")) | 
 |       break; | 
 |   while (I < ArgC) | 
 |     CLArgs.push_back(ArgV[I++]); | 
 |  | 
 |   cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data()); | 
 | } | 
 |  | 
 | void llvm::handleExecNameEncodedBEOpts(StringRef ExecName) { | 
 |   std::vector<std::string> Args{ExecName}; | 
 |  | 
 |   auto NameAndArgs = ExecName.split("--"); | 
 |   if (NameAndArgs.second.empty()) | 
 |     return; | 
 |  | 
 |   SmallVector<StringRef, 4> Opts; | 
 |   NameAndArgs.second.split(Opts, '-'); | 
 |   for (StringRef Opt : Opts) { | 
 |     if (Opt.equals("gisel")) { | 
 |       Args.push_back("-global-isel"); | 
 |       // For now we default GlobalISel to -O0 | 
 |       Args.push_back("-O0"); | 
 |     } else if (Opt.startswith("O")) { | 
 |       Args.push_back("-" + Opt.str()); | 
 |     } else if (Triple(Opt).getArch()) { | 
 |       Args.push_back("-mtriple=" + Opt.str()); | 
 |     } else { | 
 |       errs() << ExecName << ": Unknown option: " << Opt << ".\n"; | 
 |       exit(1); | 
 |     } | 
 |   } | 
 |   errs() << NameAndArgs.first << ": Injected args:"; | 
 |   for (int I = 1, E = Args.size(); I < E; ++I) | 
 |     errs() << " " << Args[I]; | 
 |   errs() << "\n"; | 
 |  | 
 |   std::vector<const char *> CLArgs; | 
 |   CLArgs.reserve(Args.size()); | 
 |   for (std::string &S : Args) | 
 |     CLArgs.push_back(S.c_str()); | 
 |  | 
 |   cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data()); | 
 | } | 
 |  | 
 | void llvm::handleExecNameEncodedOptimizerOpts(StringRef ExecName) { | 
 |   // TODO: Refactor parts common with the 'handleExecNameEncodedBEOpts' | 
 |   std::vector<std::string> Args{ExecName}; | 
 |  | 
 |   auto NameAndArgs = ExecName.split("--"); | 
 |   if (NameAndArgs.second.empty()) | 
 |     return; | 
 |  | 
 |   SmallVector<StringRef, 4> Opts; | 
 |   NameAndArgs.second.split(Opts, '-'); | 
 |   for (StringRef Opt : Opts) { | 
 |     if (Opt == "instcombine") { | 
 |       Args.push_back("-passes=instcombine"); | 
 |     } else if (Opt == "earlycse") { | 
 |       Args.push_back("-passes=early-cse"); | 
 |     } else if (Opt == "simplifycfg") { | 
 |       Args.push_back("-passes=simplify-cfg"); | 
 |     } else if (Opt == "gvn") { | 
 |       Args.push_back("-passes=gvn"); | 
 |     } else if (Opt == "sccp") { | 
 |       Args.push_back("-passes=sccp"); | 
 |  | 
 |     } else if (Opt == "loop_predication") { | 
 |       Args.push_back("-passes=loop-predication"); | 
 |     } else if (Opt == "guard_widening") { | 
 |       Args.push_back("-passes=guard-widening"); | 
 |     } else if (Opt == "loop_rotate") { | 
 |       Args.push_back("-passes=loop(rotate)"); | 
 |     } else if (Opt == "loop_unswitch") { | 
 |       Args.push_back("-passes=loop(unswitch)"); | 
 |     } else if (Opt == "loop_unroll") { | 
 |       Args.push_back("-passes=unroll"); | 
 |     } else if (Opt == "loop_vectorize") { | 
 |       Args.push_back("-passes=loop-vectorize"); | 
 |     } else if (Opt == "licm") { | 
 |       Args.push_back("-passes=licm"); | 
 |     } else if (Opt == "indvars") { | 
 |       Args.push_back("-passes=indvars"); | 
 |     } else if (Opt == "strength_reduce") { | 
 |       Args.push_back("-passes=strength-reduce"); | 
 |     } else if (Opt == "irce") { | 
 |       Args.push_back("-passes=irce"); | 
 |  | 
 |     } else if (Triple(Opt).getArch()) { | 
 |       Args.push_back("-mtriple=" + Opt.str()); | 
 |     } else { | 
 |       errs() << ExecName << ": Unknown option: " << Opt << ".\n"; | 
 |       exit(1); | 
 |     } | 
 |   } | 
 |  | 
 |   errs() << NameAndArgs.first << ": Injected args:"; | 
 |   for (int I = 1, E = Args.size(); I < E; ++I) | 
 |     errs() << " " << Args[I]; | 
 |   errs() << "\n"; | 
 |  | 
 |   std::vector<const char *> CLArgs; | 
 |   CLArgs.reserve(Args.size()); | 
 |   for (std::string &S : Args) | 
 |     CLArgs.push_back(S.c_str()); | 
 |  | 
 |   cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data()); | 
 | } | 
 |  | 
 | int llvm::runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne, | 
 |                             FuzzerInitFun Init) { | 
 |   errs() << "*** This tool was not linked to libFuzzer.\n" | 
 |          << "*** No fuzzing will be performed.\n"; | 
 |   if (int RC = Init(&ArgC, &ArgV)) { | 
 |     errs() << "Initialization failed\n"; | 
 |     return RC; | 
 |   } | 
 |  | 
 |   for (int I = 1; I < ArgC; ++I) { | 
 |     StringRef Arg(ArgV[I]); | 
 |     if (Arg.startswith("-")) { | 
 |       if (Arg.equals("-ignore_remaining_args=1")) | 
 |         break; | 
 |       continue; | 
 |     } | 
 |  | 
 |     auto BufOrErr = MemoryBuffer::getFile(Arg, /*FileSize-*/ -1, | 
 |                                           /*RequiresNullTerminator=*/false); | 
 |     if (std::error_code EC = BufOrErr.getError()) { | 
 |       errs() << "Error reading file: " << Arg << ": " << EC.message() << "\n"; | 
 |       return 1; | 
 |     } | 
 |     std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get()); | 
 |     errs() << "Running: " << Arg << " (" << Buf->getBufferSize() << " bytes)\n"; | 
 |     TestOne(reinterpret_cast<const uint8_t *>(Buf->getBufferStart()), | 
 |             Buf->getBufferSize()); | 
 |   } | 
 |   return 0; | 
 | } | 
 |  | 
 | std::unique_ptr<Module> llvm::parseModule( | 
 |     const uint8_t *Data, size_t Size, LLVMContext &Context) { | 
 |  | 
 |   if (Size <= 1) | 
 |     // We get bogus data given an empty corpus - just create a new module. | 
 |     return llvm::make_unique<Module>("M", Context); | 
 |  | 
 |   auto Buffer = MemoryBuffer::getMemBuffer( | 
 |       StringRef(reinterpret_cast<const char *>(Data), Size), "Fuzzer input", | 
 |       /*RequiresNullTerminator=*/false); | 
 |  | 
 |   SMDiagnostic Err; | 
 |   auto M = parseBitcodeFile(Buffer->getMemBufferRef(), Context); | 
 |   if (Error E = M.takeError()) { | 
 |     errs() << toString(std::move(E)) << "\n"; | 
 |     return nullptr; | 
 |   } | 
 |   return std::move(M.get()); | 
 | } | 
 |  | 
 | size_t llvm::writeModule(const Module &M, uint8_t *Dest, size_t MaxSize) { | 
 |   std::string Buf; | 
 |   { | 
 |     raw_string_ostream OS(Buf); | 
 |     WriteBitcodeToFile(M, OS); | 
 |   } | 
 |   if (Buf.size() > MaxSize) | 
 |       return 0; | 
 |   memcpy(Dest, Buf.data(), Buf.size()); | 
 |   return Buf.size(); | 
 | } | 
 |  | 
 | std::unique_ptr<Module> llvm::parseAndVerify(const uint8_t *Data, size_t Size, | 
 |                                              LLVMContext &Context) { | 
 |   auto M = parseModule(Data, Size, Context); | 
 |   if (!M || verifyModule(*M, &errs())) | 
 |     return nullptr; | 
 |  | 
 |   return M; | 
 | } |