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