[lib/Fuzzer] remove -use_coverage_pairs=1, an experimental feature that is unlikely...
[oota-llvm.git] / lib / Fuzzer / FuzzerDriver.cpp
1 //===- FuzzerDriver.cpp - FuzzerDriver function and flags -----------------===//
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 // FuzzerDriver and flag parsing.
10 //===----------------------------------------------------------------------===//
11
12 #include "FuzzerInterface.h"
13 #include "FuzzerInternal.h"
14
15 #include <cstring>
16 #include <chrono>
17 #include <unistd.h>
18 #include <iostream>
19 #include <thread>
20 #include <atomic>
21 #include <mutex>
22 #include <string>
23 #include <sstream>
24 #include <algorithm>
25 #include <iterator>
26
27 namespace fuzzer {
28
29 // Program arguments.
30 struct FlagDescription {
31   const char *Name;
32   const char *Description;
33   int   Default;
34   int   *IntFlag;
35   const char **StrFlag;
36 };
37
38 struct {
39 #define FUZZER_FLAG_INT(Name, Default, Description) int Name;
40 #define FUZZER_FLAG_STRING(Name, Description) const char *Name;
41 #include "FuzzerFlags.def"
42 #undef FUZZER_FLAG_INT
43 #undef FUZZER_FLAG_STRING
44 } Flags;
45
46 static FlagDescription FlagDescriptions [] {
47 #define FUZZER_FLAG_INT(Name, Default, Description)                            \
48   { #Name, Description, Default, &Flags.Name, nullptr},
49 #define FUZZER_FLAG_STRING(Name, Description)                                  \
50   { #Name, Description, 0, nullptr, &Flags.Name },
51 #include "FuzzerFlags.def"
52 #undef FUZZER_FLAG_INT
53 #undef FUZZER_FLAG_STRING
54 };
55
56 static const size_t kNumFlags =
57     sizeof(FlagDescriptions) / sizeof(FlagDescriptions[0]);
58
59 static std::vector<std::string> inputs;
60 static const char *ProgName;
61
62 static void PrintHelp() {
63   std::cerr << "Usage: " << ProgName
64             << " [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n";
65   std::cerr << "\nFlags: (strictly in form -flag=value)\n";
66   size_t MaxFlagLen = 0;
67   for (size_t F = 0; F < kNumFlags; F++)
68     MaxFlagLen = std::max(strlen(FlagDescriptions[F].Name), MaxFlagLen);
69
70   for (size_t F = 0; F < kNumFlags; F++) {
71     const auto &D = FlagDescriptions[F];
72     std::cerr << "  " << D.Name;
73     for (size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++)
74       std::cerr << " ";
75     std::cerr << "\t";
76     std::cerr << D.Default << "\t" << D.Description << "\n";
77   }
78   std::cerr << "\nFlags starting with '--' will be ignored and "
79             "will be passed verbatim to subprocesses.\n";
80 }
81
82 static const char *FlagValue(const char *Param, const char *Name) {
83   size_t Len = strlen(Name);
84   if (Param[0] == '-' && strstr(Param + 1, Name) == Param + 1 &&
85       Param[Len + 1] == '=')
86       return &Param[Len + 2];
87   return nullptr;
88 }
89
90 static bool ParseOneFlag(const char *Param) {
91   if (Param[0] != '-') return false;
92   if (Param[1] == '-') {
93     static bool PrintedWarning = false;
94     if (!PrintedWarning) {
95       PrintedWarning = true;
96       std::cerr << "WARNING: libFuzzer ignores flags that start with '--'\n";
97     }
98     return true;
99   }
100   for (size_t F = 0; F < kNumFlags; F++) {
101     const char *Name = FlagDescriptions[F].Name;
102     const char *Str = FlagValue(Param, Name);
103     if (Str)  {
104       if (FlagDescriptions[F].IntFlag) {
105         int Val = std::stol(Str);
106         *FlagDescriptions[F].IntFlag = Val;
107         if (Flags.verbosity >= 2)
108           std::cerr << "Flag: " << Name << " " << Val << "\n";
109         return true;
110       } else if (FlagDescriptions[F].StrFlag) {
111         *FlagDescriptions[F].StrFlag = Str;
112         if (Flags.verbosity >= 2)
113           std::cerr << "Flag: " << Name << " " << Str << "\n";
114         return true;
115       }
116     }
117   }
118   PrintHelp();
119   exit(1);
120 }
121
122 // We don't use any library to minimize dependencies.
123 static void ParseFlags(int argc, char **argv) {
124   for (size_t F = 0; F < kNumFlags; F++) {
125     if (FlagDescriptions[F].IntFlag)
126       *FlagDescriptions[F].IntFlag = FlagDescriptions[F].Default;
127     if (FlagDescriptions[F].StrFlag)
128       *FlagDescriptions[F].StrFlag = nullptr;
129   }
130   for (int A = 1; A < argc; A++) {
131     if (ParseOneFlag(argv[A])) continue;
132     inputs.push_back(argv[A]);
133   }
134 }
135
136 static std::mutex Mu;
137
138 static void PulseThread() {
139   while (true) {
140     std::this_thread::sleep_for(std::chrono::seconds(600));
141     std::lock_guard<std::mutex> Lock(Mu);
142     std::cerr << "pulse...\n";
143   }
144 }
145
146 static void WorkerThread(const std::string &Cmd, std::atomic<int> *Counter,
147                         int NumJobs, std::atomic<bool> *HasErrors) {
148   while (true) {
149     int C = (*Counter)++;
150     if (C >= NumJobs) break;
151     std::string Log = "fuzz-" + std::to_string(C) + ".log";
152     std::string ToRun = Cmd + " > " + Log + " 2>&1\n";
153     if (Flags.verbosity)
154       std::cerr << ToRun;
155     int ExitCode = system(ToRun.c_str());
156     if (ExitCode != 0)
157       *HasErrors = true;
158     std::lock_guard<std::mutex> Lock(Mu);
159     std::cerr << "================== Job " << C
160               << " exited with exit code " << ExitCode
161               << " =================\n";
162     fuzzer::CopyFileToErr(Log);
163   }
164 }
165
166 static int RunInMultipleProcesses(int argc, char **argv, int NumWorkers,
167                                   int NumJobs) {
168   std::atomic<int> Counter(0);
169   std::atomic<bool> HasErrors(false);
170   std::string Cmd;
171   for (int i = 0; i < argc; i++) {
172     if (FlagValue(argv[i], "jobs") || FlagValue(argv[i], "workers")) continue;
173     Cmd += argv[i];
174     Cmd += " ";
175   }
176   std::vector<std::thread> V;
177   std::thread Pulse(PulseThread);
178   Pulse.detach();
179   for (int i = 0; i < NumWorkers; i++)
180     V.push_back(std::thread(WorkerThread, Cmd, &Counter, NumJobs, &HasErrors));
181   for (auto &T : V)
182     T.join();
183   return HasErrors ? 1 : 0;
184 }
185
186 std::vector<std::string> ReadTokensFile(const char *TokensFilePath) {
187   if (!TokensFilePath) return {};
188   std::string TokensFileContents = FileToString(TokensFilePath);
189   std::istringstream ISS(TokensFileContents);
190   std::vector<std::string> Res = {std::istream_iterator<std::string>{ISS},
191                                   std::istream_iterator<std::string>{}};
192   Res.push_back(" ");
193   Res.push_back("\t");
194   Res.push_back("\n");
195   return Res;
196 }
197
198 int ApplyTokens(const Fuzzer &F, const char *InputFilePath) {
199   Unit U = FileToVector(InputFilePath);
200   auto T = F.SubstituteTokens(U);
201   T.push_back(0);
202   std::cout << T.data();
203   return 0;
204 }
205
206 int FuzzerDriver(int argc, char **argv, UserCallback Callback) {
207   SimpleUserSuppliedFuzzer SUSF(Callback);
208   return FuzzerDriver(argc, argv, SUSF);
209 }
210
211 int FuzzerDriver(int argc, char **argv, UserSuppliedFuzzer &USF) {
212   using namespace fuzzer;
213
214   ProgName = argv[0];
215   ParseFlags(argc, argv);
216   if (Flags.help) {
217     PrintHelp();
218     return 0;
219   }
220
221   if (Flags.jobs > 0 && Flags.workers == 0) {
222     Flags.workers = std::min(NumberOfCpuCores() / 2, Flags.jobs);
223     if (Flags.workers > 1)
224       std::cerr << "Running " << Flags.workers << " workers\n";
225   }
226
227   if (Flags.workers > 0 && Flags.jobs > 0)
228     return RunInMultipleProcesses(argc, argv, Flags.workers, Flags.jobs);
229
230   Fuzzer::FuzzingOptions Options;
231   Options.Verbosity = Flags.verbosity;
232   Options.MaxLen = Flags.max_len;
233   Options.UnitTimeoutSec = Flags.timeout;
234   Options.DoCrossOver = Flags.cross_over;
235   Options.MutateDepth = Flags.mutate_depth;
236   Options.ExitOnFirst = Flags.exit_on_first;
237   Options.UseCounters = Flags.use_counters;
238   Options.UseTraces = Flags.use_traces;
239   Options.UseFullCoverageSet = Flags.use_full_coverage_set;
240   Options.PreferSmallDuringInitialShuffle =
241       Flags.prefer_small_during_initial_shuffle;
242   Options.Tokens = ReadTokensFile(Flags.tokens);
243   Options.Reload = Flags.reload;
244   if (Flags.runs >= 0)
245     Options.MaxNumberOfRuns = Flags.runs;
246   if (!inputs.empty())
247     Options.OutputCorpus = inputs[0];
248   if (Flags.sync_command)
249     Options.SyncCommand = Flags.sync_command;
250   Options.SyncTimeout = Flags.sync_timeout;
251   Fuzzer F(USF, Options);
252
253   unsigned seed = Flags.seed;
254   // Initialize seed.
255   if (seed == 0)
256     seed = time(0) * 10000 + getpid();
257   if (Flags.verbosity)
258     std::cerr << "Seed: " << seed << "\n";
259   srand(seed);
260
261   // Timer
262   if (Flags.timeout > 0)
263     SetTimer(Flags.timeout / 2 + 1);
264
265   if (Flags.verbosity >= 2) {
266     std::cerr << "Tokens: {";
267     for (auto &T : Options.Tokens)
268       std::cerr << T << ",";
269     std::cerr << "}\n";
270   }
271
272   if (Flags.apply_tokens)
273     return ApplyTokens(F, Flags.apply_tokens);
274
275   F.RereadOutputCorpus();
276   for (auto &inp : inputs)
277     if (inp != Options.OutputCorpus)
278       F.ReadDir(inp, nullptr);
279
280   if (F.CorpusSize() == 0)
281     F.AddToCorpus(Unit());  // Can't fuzz empty corpus, so add an empty input.
282   F.ShuffleAndMinimize();
283   if (Flags.save_minimized_corpus)
284     F.SaveCorpus();
285   F.Loop(Flags.iterations < 0 ? INT_MAX : Flags.iterations);
286   if (Flags.verbosity)
287     std::cerr << "Done " << F.getTotalNumberOfRuns()
288               << " runs in " << F.secondsSinceProcessStartUp()
289               << " seconds\n";
290   return 0;
291 }
292
293 }  // namespace fuzzer