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.starts_with("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 } else if (Opt == "loop_predication") { 90 Args.push_back("-passes=loop-predication"); 91 } else if (Opt == "guard_widening") { 92 Args.push_back("-passes=guard-widening"); 93 } else if (Opt == "loop_rotate") { 94 Args.push_back("-passes=loop-rotate"); 95 } else if (Opt == "loop_unswitch") { 96 Args.push_back("-passes=loop(simple-loop-unswitch)"); 97 } else if (Opt == "loop_unroll") { 98 Args.push_back("-passes=unroll"); 99 } else if (Opt == "loop_vectorize") { 100 Args.push_back("-passes=loop-vectorize"); 101 } else if (Opt == "licm") { 102 Args.push_back("-passes=licm"); 103 } else if (Opt == "indvars") { 104 Args.push_back("-passes=indvars"); 105 } else if (Opt == "strength_reduce") { 106 Args.push_back("-passes=loop-reduce"); 107 } else if (Opt == "irce") { 108 Args.push_back("-passes=irce"); 109 } else if (Opt == "dse") { 110 Args.push_back("-passes=dse"); 111 } else if (Opt == "loop_idiom") { 112 Args.push_back("-passes=loop-idiom"); 113 } else if (Opt == "reassociate") { 114 Args.push_back("-passes=reassociate"); 115 } else if (Opt == "lower_matrix_intrinsics") { 116 Args.push_back("-passes=lower-matrix-intrinsics"); 117 } else if (Opt == "memcpyopt") { 118 Args.push_back("-passes=memcpyopt"); 119 } else if (Opt == "sroa") { 120 Args.push_back("-passes=sroa"); 121 } else if (Triple(Opt).getArch()) { 122 Args.push_back("-mtriple=" + Opt.str()); 123 } else { 124 errs() << ExecName << ": Unknown option: " << Opt << ".\n"; 125 exit(1); 126 } 127 } 128 129 errs() << NameAndArgs.first << ": Injected args:"; 130 for (int I = 1, E = Args.size(); I < E; ++I) 131 errs() << " " << Args[I]; 132 errs() << "\n"; 133 134 std::vector<const char *> CLArgs; 135 CLArgs.reserve(Args.size()); 136 for (std::string &S : Args) 137 CLArgs.push_back(S.c_str()); 138 139 cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data()); 140 } 141 142 int llvm::runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne, 143 FuzzerInitFun Init) { 144 errs() << "*** This tool was not linked to libFuzzer.\n" 145 << "*** No fuzzing will be performed.\n"; 146 if (int RC = Init(&ArgC, &ArgV)) { 147 errs() << "Initialization failed\n"; 148 return RC; 149 } 150 151 for (int I = 1; I < ArgC; ++I) { 152 StringRef Arg(ArgV[I]); 153 if (Arg.starts_with("-")) { 154 if (Arg.equals("-ignore_remaining_args=1")) 155 break; 156 continue; 157 } 158 159 auto BufOrErr = MemoryBuffer::getFile(Arg, /*IsText=*/false, 160 /*RequiresNullTerminator=*/false); 161 if (std::error_code EC = BufOrErr.getError()) { 162 errs() << "Error reading file: " << Arg << ": " << EC.message() << "\n"; 163 return 1; 164 } 165 std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get()); 166 errs() << "Running: " << Arg << " (" << Buf->getBufferSize() << " bytes)\n"; 167 TestOne(reinterpret_cast<const uint8_t *>(Buf->getBufferStart()), 168 Buf->getBufferSize()); 169 } 170 return 0; 171 } 172