xref: /freebsd/contrib/llvm-project/llvm/lib/FuzzMutate/FuzzerCLI.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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  
parseFuzzerCLOpts(int ArgC,char * ArgV[])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++]) == "-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  
handleExecNameEncodedBEOpts(StringRef ExecName)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 == "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  
handleExecNameEncodedOptimizerOpts(StringRef ExecName)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  
runFuzzerOnInputs(int ArgC,char * ArgV[],FuzzerTestFun TestOne,FuzzerInitFun Init)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 == "-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