1 //===-- FuzzerCLI.cpp -----------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/FuzzMutate/FuzzerCLI.h" 10 #include "llvm/ADT/StringRef.h" 11 #include "llvm/Support/CommandLine.h" 12 #include "llvm/Support/MemoryBuffer.h" 13 #include "llvm/Support/raw_ostream.h" 14 #include "llvm/TargetParser/Triple.h" 15 16 using namespace llvm; 17 18 void llvm::parseFuzzerCLOpts(int ArgC, char *ArgV[]) { 19 std::vector<const char *> CLArgs; 20 CLArgs.push_back(ArgV[0]); 21 22 int I = 1; 23 while (I < ArgC) 24 if (StringRef(ArgV[I++]).equals("-ignore_remaining_args=1")) 25 break; 26 while (I < ArgC) 27 CLArgs.push_back(ArgV[I++]); 28 29 cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data()); 30 } 31 32 void llvm::handleExecNameEncodedBEOpts(StringRef ExecName) { 33 std::vector<std::string> Args{std::string(ExecName)}; 34 35 auto NameAndArgs = ExecName.split("--"); 36 if (NameAndArgs.second.empty()) 37 return; 38 39 SmallVector<StringRef, 4> Opts; 40 NameAndArgs.second.split(Opts, '-'); 41 for (StringRef Opt : Opts) { 42 if (Opt.equals("gisel")) { 43 Args.push_back("-global-isel"); 44 // For now we default GlobalISel to -O0 45 Args.push_back("-O0"); 46 } else if (Opt.startswith("O")) { 47 Args.push_back("-" + Opt.str()); 48 } else if (Triple(Opt).getArch()) { 49 Args.push_back("-mtriple=" + Opt.str()); 50 } else { 51 errs() << ExecName << ": Unknown option: " << Opt << ".\n"; 52 exit(1); 53 } 54 } 55 errs() << NameAndArgs.first << ": Injected args:"; 56 for (int I = 1, E = Args.size(); I < E; ++I) 57 errs() << " " << Args[I]; 58 errs() << "\n"; 59 60 std::vector<const char *> CLArgs; 61 CLArgs.reserve(Args.size()); 62 for (std::string &S : Args) 63 CLArgs.push_back(S.c_str()); 64 65 cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data()); 66 } 67 68 void llvm::handleExecNameEncodedOptimizerOpts(StringRef ExecName) { 69 // TODO: Refactor parts common with the 'handleExecNameEncodedBEOpts' 70 std::vector<std::string> Args{std::string(ExecName)}; 71 72 auto NameAndArgs = ExecName.split("--"); 73 if (NameAndArgs.second.empty()) 74 return; 75 76 SmallVector<StringRef, 4> Opts; 77 NameAndArgs.second.split(Opts, '-'); 78 for (StringRef Opt : Opts) { 79 if (Opt == "instcombine") { 80 Args.push_back("-passes=instcombine"); 81 } else if (Opt == "earlycse") { 82 Args.push_back("-passes=early-cse"); 83 } else if (Opt == "simplifycfg") { 84 Args.push_back("-passes=simplifycfg"); 85 } else if (Opt == "gvn") { 86 Args.push_back("-passes=gvn"); 87 } else if (Opt == "sccp") { 88 Args.push_back("-passes=sccp"); 89 90 } else if (Opt == "loop_predication") { 91 Args.push_back("-passes=loop-predication"); 92 } else if (Opt == "guard_widening") { 93 Args.push_back("-passes=guard-widening"); 94 } else if (Opt == "loop_rotate") { 95 Args.push_back("-passes=loop(rotate)"); 96 } else if (Opt == "loop_unswitch") { 97 Args.push_back("-passes=loop(simple-loop-unswitch)"); 98 } else if (Opt == "loop_unroll") { 99 Args.push_back("-passes=unroll"); 100 } else if (Opt == "loop_vectorize") { 101 Args.push_back("-passes=loop-vectorize"); 102 } else if (Opt == "licm") { 103 Args.push_back("-passes=licm"); 104 } else if (Opt == "indvars") { 105 Args.push_back("-passes=indvars"); 106 } else if (Opt == "strength_reduce") { 107 Args.push_back("-passes=loop-reduce"); 108 } else if (Opt == "irce") { 109 Args.push_back("-passes=irce"); 110 111 } else if (Triple(Opt).getArch()) { 112 Args.push_back("-mtriple=" + Opt.str()); 113 } else { 114 errs() << ExecName << ": Unknown option: " << Opt << ".\n"; 115 exit(1); 116 } 117 } 118 119 errs() << NameAndArgs.first << ": Injected args:"; 120 for (int I = 1, E = Args.size(); I < E; ++I) 121 errs() << " " << Args[I]; 122 errs() << "\n"; 123 124 std::vector<const char *> CLArgs; 125 CLArgs.reserve(Args.size()); 126 for (std::string &S : Args) 127 CLArgs.push_back(S.c_str()); 128 129 cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data()); 130 } 131 132 int llvm::runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne, 133 FuzzerInitFun Init) { 134 errs() << "*** This tool was not linked to libFuzzer.\n" 135 << "*** No fuzzing will be performed.\n"; 136 if (int RC = Init(&ArgC, &ArgV)) { 137 errs() << "Initialization failed\n"; 138 return RC; 139 } 140 141 for (int I = 1; I < ArgC; ++I) { 142 StringRef Arg(ArgV[I]); 143 if (Arg.startswith("-")) { 144 if (Arg.equals("-ignore_remaining_args=1")) 145 break; 146 continue; 147 } 148 149 auto BufOrErr = MemoryBuffer::getFile(Arg, /*IsText=*/false, 150 /*RequiresNullTerminator=*/false); 151 if (std::error_code EC = BufOrErr.getError()) { 152 errs() << "Error reading file: " << Arg << ": " << EC.message() << "\n"; 153 return 1; 154 } 155 std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get()); 156 errs() << "Running: " << Arg << " (" << Buf->getBufferSize() << " bytes)\n"; 157 TestOne(reinterpret_cast<const uint8_t *>(Buf->getBufferStart()), 158 Buf->getBufferSize()); 159 } 160 return 0; 161 } 162