xref: /freebsd/contrib/llvm-project/llvm/lib/FuzzMutate/FuzzerCLI.cpp (revision e1c4c8dd8d2d10b6104f06856a77bd5b4813a801)
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