]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/FuzzMutate/FuzzerCLI.cpp
MFV r328225: 8603 rename zilog's "zl_writer_lock" to "zl_issuer_lock"
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / FuzzMutate / FuzzerCLI.cpp
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
22 using namespace llvm;
23
24 void llvm::parseFuzzerCLOpts(int ArgC, char *ArgV[]) {
25   std::vector<const char *> CLArgs;
26   CLArgs.push_back(ArgV[0]);
27
28   int I = 1;
29   while (I < ArgC)
30     if (StringRef(ArgV[I++]).equals("-ignore_remaining_args=1"))
31       break;
32   while (I < ArgC)
33     CLArgs.push_back(ArgV[I++]);
34
35   cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
36 }
37
38 void llvm::handleExecNameEncodedBEOpts(StringRef ExecName) {
39   std::vector<std::string> Args{ExecName};
40
41   auto NameAndArgs = ExecName.split("--");
42   if (NameAndArgs.second.empty())
43     return;
44
45   SmallVector<StringRef, 4> Opts;
46   NameAndArgs.second.split(Opts, '-');
47   for (StringRef Opt : Opts) {
48     if (Opt.equals("gisel")) {
49       Args.push_back("-global-isel");
50       // For now we default GlobalISel to -O0
51       Args.push_back("-O0");
52     } else if (Opt.startswith("O")) {
53       Args.push_back("-" + Opt.str());
54     } else if (Triple(Opt).getArch()) {
55       Args.push_back("-mtriple=" + Opt.str());
56     } else {
57       errs() << ExecName << ": Unknown option: " << Opt << ".\n";
58       exit(1);
59     }
60   }
61   errs() << NameAndArgs.first << ": Injected args:";
62   for (int I = 1, E = Args.size(); I < E; ++I)
63     errs() << " " << Args[I];
64   errs() << "\n";
65
66   std::vector<const char *> CLArgs;
67   CLArgs.reserve(Args.size());
68   for (std::string &S : Args)
69     CLArgs.push_back(S.c_str());
70
71   cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
72 }
73
74 void llvm::handleExecNameEncodedOptimizerOpts(StringRef ExecName) {
75   // TODO: Refactor parts common with the 'handleExecNameEncodedBEOpts'
76   std::vector<std::string> Args{ExecName};
77
78   auto NameAndArgs = ExecName.split("--");
79   if (NameAndArgs.second.empty())
80     return;
81
82   SmallVector<StringRef, 4> Opts;
83   NameAndArgs.second.split(Opts, '-');
84   for (StringRef Opt : Opts) {
85     if (Opt.startswith("instcombine")) {
86       Args.push_back("-passes=instcombine");
87     } else if (Triple(Opt).getArch()) {
88       Args.push_back("-mtriple=" + Opt.str());
89     } else {
90       errs() << ExecName << ": Unknown option: " << Opt << ".\n";
91       exit(1);
92     }
93   }
94
95   errs() << NameAndArgs.first << ": Injected args:";
96   for (int I = 1, E = Args.size(); I < E; ++I)
97     errs() << " " << Args[I];
98   errs() << "\n";
99
100   std::vector<const char *> CLArgs;
101   CLArgs.reserve(Args.size());
102   for (std::string &S : Args)
103     CLArgs.push_back(S.c_str());
104
105   cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
106 }
107
108 int llvm::runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne,
109                             FuzzerInitFun Init) {
110   errs() << "*** This tool was not linked to libFuzzer.\n"
111          << "*** No fuzzing will be performed.\n";
112   if (int RC = Init(&ArgC, &ArgV)) {
113     errs() << "Initialization failed\n";
114     return RC;
115   }
116
117   for (int I = 1; I < ArgC; ++I) {
118     StringRef Arg(ArgV[I]);
119     if (Arg.startswith("-")) {
120       if (Arg.equals("-ignore_remaining_args=1"))
121         break;
122       continue;
123     }
124
125     auto BufOrErr = MemoryBuffer::getFile(Arg, /*FileSize-*/ -1,
126                                           /*RequiresNullTerminator=*/false);
127     if (std::error_code EC = BufOrErr.getError()) {
128       errs() << "Error reading file: " << Arg << ": " << EC.message() << "\n";
129       return 1;
130     }
131     std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
132     errs() << "Running: " << Arg << " (" << Buf->getBufferSize() << " bytes)\n";
133     TestOne(reinterpret_cast<const uint8_t *>(Buf->getBufferStart()),
134             Buf->getBufferSize());
135   }
136   return 0;
137 }
138
139 std::unique_ptr<Module> llvm::parseModule(
140     const uint8_t *Data, size_t Size, LLVMContext &Context) {
141
142   if (Size <= 1)
143     // We get bogus data given an empty corpus - just create a new module.
144     return llvm::make_unique<Module>("M", Context);
145
146   auto Buffer = MemoryBuffer::getMemBuffer(
147       StringRef(reinterpret_cast<const char *>(Data), Size), "Fuzzer input",
148       /*RequiresNullTerminator=*/false);
149
150   SMDiagnostic Err;
151   auto M = parseBitcodeFile(Buffer->getMemBufferRef(), Context);
152   if (Error E = M.takeError()) {
153     errs() << toString(std::move(E)) << "\n";
154     return nullptr;
155   }
156   return std::move(M.get());
157 }
158
159 size_t llvm::writeModule(const Module &M, uint8_t *Dest, size_t MaxSize) {
160   std::string Buf;
161   {
162     raw_string_ostream OS(Buf);
163     WriteBitcodeToFile(&M, OS);
164   }
165   if (Buf.size() > MaxSize)
166       return 0;
167   memcpy(Dest, Buf.data(), Buf.size());
168   return Buf.size();
169 }