Home | History | Annotate | Download | only in FuzzMutate
      1 //===-- FuzzerCLI.cpp -----------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/FuzzMutate/FuzzerCLI.h"
     11 #include "llvm/ADT/Triple.h"
     12 #include "llvm/Bitcode/BitcodeReader.h"
     13 #include "llvm/Bitcode/BitcodeWriter.h"
     14 #include "llvm/IR/LLVMContext.h"
     15 #include "llvm/Support/CommandLine.h"
     16 #include "llvm/Support/Compiler.h"
     17 #include "llvm/Support/Error.h"
     18 #include "llvm/Support/MemoryBuffer.h"
     19 #include "llvm/Support/SourceMgr.h"
     20 #include "llvm/Support/raw_ostream.h"
     21 #include "llvm/IR/Verifier.h"
     22 
     23 using namespace llvm;
     24 
     25 void llvm::parseFuzzerCLOpts(int ArgC, char *ArgV[]) {
     26   std::vector<const char *> CLArgs;
     27   CLArgs.push_back(ArgV[0]);
     28 
     29   int I = 1;
     30   while (I < ArgC)
     31     if (StringRef(ArgV[I++]).equals("-ignore_remaining_args=1"))
     32       break;
     33   while (I < ArgC)
     34     CLArgs.push_back(ArgV[I++]);
     35 
     36   cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
     37 }
     38 
     39 void llvm::handleExecNameEncodedBEOpts(StringRef ExecName) {
     40   std::vector<std::string> Args{ExecName};
     41 
     42   auto NameAndArgs = ExecName.split("--");
     43   if (NameAndArgs.second.empty())
     44     return;
     45 
     46   SmallVector<StringRef, 4> Opts;
     47   NameAndArgs.second.split(Opts, '-');
     48   for (StringRef Opt : Opts) {
     49     if (Opt.equals("gisel")) {
     50       Args.push_back("-global-isel");
     51       // For now we default GlobalISel to -O0
     52       Args.push_back("-O0");
     53     } else if (Opt.startswith("O")) {
     54       Args.push_back("-" + Opt.str());
     55     } else if (Triple(Opt).getArch()) {
     56       Args.push_back("-mtriple=" + Opt.str());
     57     } else {
     58       errs() << ExecName << ": Unknown option: " << Opt << ".\n";
     59       exit(1);
     60     }
     61   }
     62   errs() << NameAndArgs.first << ": Injected args:";
     63   for (int I = 1, E = Args.size(); I < E; ++I)
     64     errs() << " " << Args[I];
     65   errs() << "\n";
     66 
     67   std::vector<const char *> CLArgs;
     68   CLArgs.reserve(Args.size());
     69   for (std::string &S : Args)
     70     CLArgs.push_back(S.c_str());
     71 
     72   cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
     73 }
     74 
     75 void llvm::handleExecNameEncodedOptimizerOpts(StringRef ExecName) {
     76   // TODO: Refactor parts common with the 'handleExecNameEncodedBEOpts'
     77   std::vector<std::string> Args{ExecName};
     78 
     79   auto NameAndArgs = ExecName.split("--");
     80   if (NameAndArgs.second.empty())
     81     return;
     82 
     83   SmallVector<StringRef, 4> Opts;
     84   NameAndArgs.second.split(Opts, '-');
     85   for (StringRef Opt : Opts) {
     86     if (Opt == "instcombine") {
     87       Args.push_back("-passes=instcombine");
     88     } else if (Opt == "earlycse") {
     89       Args.push_back("-passes=early-cse");
     90     } else if (Opt == "simplifycfg") {
     91       Args.push_back("-passes=simplify-cfg");
     92     } else if (Opt == "gvn") {
     93       Args.push_back("-passes=gvn");
     94     } else if (Opt == "sccp") {
     95       Args.push_back("-passes=sccp");
     96 
     97     } else if (Opt == "loop_predication") {
     98       Args.push_back("-passes=loop-predication");
     99     } else if (Opt == "guard_widening") {
    100       Args.push_back("-passes=guard-widening");
    101     } else if (Opt == "loop_rotate") {
    102       Args.push_back("-passes=loop(rotate)");
    103     } else if (Opt == "loop_unswitch") {
    104       Args.push_back("-passes=loop(unswitch)");
    105     } else if (Opt == "loop_unroll") {
    106       Args.push_back("-passes=unroll");
    107     } else if (Opt == "loop_vectorize") {
    108       Args.push_back("-passes=loop-vectorize");
    109     } else if (Opt == "licm") {
    110       Args.push_back("-passes=licm");
    111     } else if (Opt == "indvars") {
    112       Args.push_back("-passes=indvars");
    113     } else if (Opt == "strength_reduce") {
    114       Args.push_back("-passes=strength-reduce");
    115     } else if (Opt == "irce") {
    116       Args.push_back("-passes=irce");
    117 
    118     } else if (Triple(Opt).getArch()) {
    119       Args.push_back("-mtriple=" + Opt.str());
    120     } else {
    121       errs() << ExecName << ": Unknown option: " << Opt << ".\n";
    122       exit(1);
    123     }
    124   }
    125 
    126   errs() << NameAndArgs.first << ": Injected args:";
    127   for (int I = 1, E = Args.size(); I < E; ++I)
    128     errs() << " " << Args[I];
    129   errs() << "\n";
    130 
    131   std::vector<const char *> CLArgs;
    132   CLArgs.reserve(Args.size());
    133   for (std::string &S : Args)
    134     CLArgs.push_back(S.c_str());
    135 
    136   cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
    137 }
    138 
    139 int llvm::runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne,
    140                             FuzzerInitFun Init) {
    141   errs() << "*** This tool was not linked to libFuzzer.\n"
    142          << "*** No fuzzing will be performed.\n";
    143   if (int RC = Init(&ArgC, &ArgV)) {
    144     errs() << "Initialization failed\n";
    145     return RC;
    146   }
    147 
    148   for (int I = 1; I < ArgC; ++I) {
    149     StringRef Arg(ArgV[I]);
    150     if (Arg.startswith("-")) {
    151       if (Arg.equals("-ignore_remaining_args=1"))
    152         break;
    153       continue;
    154     }
    155 
    156     auto BufOrErr = MemoryBuffer::getFile(Arg, /*FileSize-*/ -1,
    157                                           /*RequiresNullTerminator=*/false);
    158     if (std::error_code EC = BufOrErr.getError()) {
    159       errs() << "Error reading file: " << Arg << ": " << EC.message() << "\n";
    160       return 1;
    161     }
    162     std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
    163     errs() << "Running: " << Arg << " (" << Buf->getBufferSize() << " bytes)\n";
    164     TestOne(reinterpret_cast<const uint8_t *>(Buf->getBufferStart()),
    165             Buf->getBufferSize());
    166   }
    167   return 0;
    168 }
    169 
    170 std::unique_ptr<Module> llvm::parseModule(
    171     const uint8_t *Data, size_t Size, LLVMContext &Context) {
    172 
    173   if (Size <= 1)
    174     // We get bogus data given an empty corpus - just create a new module.
    175     return llvm::make_unique<Module>("M", Context);
    176 
    177   auto Buffer = MemoryBuffer::getMemBuffer(
    178       StringRef(reinterpret_cast<const char *>(Data), Size), "Fuzzer input",
    179       /*RequiresNullTerminator=*/false);
    180 
    181   SMDiagnostic Err;
    182   auto M = parseBitcodeFile(Buffer->getMemBufferRef(), Context);
    183   if (Error E = M.takeError()) {
    184     errs() << toString(std::move(E)) << "\n";
    185     return nullptr;
    186   }
    187   return std::move(M.get());
    188 }
    189 
    190 size_t llvm::writeModule(const Module &M, uint8_t *Dest, size_t MaxSize) {
    191   std::string Buf;
    192   {
    193     raw_string_ostream OS(Buf);
    194     WriteBitcodeToFile(M, OS);
    195   }
    196   if (Buf.size() > MaxSize)
    197       return 0;
    198   memcpy(Dest, Buf.data(), Buf.size());
    199   return Buf.size();
    200 }
    201 
    202 std::unique_ptr<Module> llvm::parseAndVerify(const uint8_t *Data, size_t Size,
    203                                              LLVMContext &Context) {
    204   auto M = parseModule(Data, Size, Context);
    205   if (!M || verifyModule(*M, &errs()))
    206     return nullptr;
    207 
    208   return M;
    209 }
    210