0a852ed4257595ff09ae84127d5ec47915978594
[oota-llvm.git] / lib / Fuzzer / FuzzerMain.cpp
1 //===- FuzzerMain.cpp - main() 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 // main() and flags.
10 //===----------------------------------------------------------------------===//
11
12 #include "FuzzerInternal.h"
13
14 #include <climits>
15 #include <cstring>
16 #include <unistd.h>
17 #include <iostream>
18 #include <thread>
19 #include <atomic>
20 #include <mutex>
21
22 // ASAN options:
23 //   * don't dump the coverage to disk.
24 //   * enable coverage by default.
25 extern "C" const char *__asan_default_options() {
26   return "coverage_pcs=0:coverage=1";
27 }
28
29 // Program arguments.
30 struct FlagDescription {
31   const char *Name;
32   const char *Description;
33   int   Default;
34   int   *Flag;
35 };
36
37 struct {
38 #define FUZZER_FLAG(Type, Name, Default, Description) Type Name;
39 #include "FuzzerFlags.def"
40 #undef FUZZER_FLAG
41 } Flags;
42
43 static FlagDescription FlagDescriptions [] {
44 #define FUZZER_FLAG(Type, Name, Default, Description) {#Name, Description, Default, &Flags.Name},
45 #include "FuzzerFlags.def"
46 #undef FUZZER_FLAG
47 };
48
49 static const size_t kNumFlags =
50     sizeof(FlagDescriptions) / sizeof(FlagDescriptions[0]);
51
52 static std::vector<std::string> inputs;
53 static const char *ProgName;
54
55 static void PrintHelp() {
56   std::cerr << "Usage: " << ProgName
57             << " [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n";
58   std::cerr << "\nFlags: (strictly in form -flag=value)\n";
59   size_t MaxFlagLen = 0;
60   for (size_t F = 0; F < kNumFlags; F++)
61     MaxFlagLen = std::max(strlen(FlagDescriptions[F].Name), MaxFlagLen);
62
63   for (size_t F = 0; F < kNumFlags; F++) {
64     const auto &D = FlagDescriptions[F];
65     std::cerr << "  " << D.Name;
66     for (size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++)
67       std::cerr << " ";
68     std::cerr << "\t";
69     std::cerr << D.Default << "\t" << D.Description << "\n";
70   }
71 }
72
73 static const char *FlagValue(const char *Param, const char *Name) {
74   size_t Len = strlen(Name);
75   if (Param[0] == '-' && strstr(Param + 1, Name) == Param + 1 &&
76       Param[Len + 1] == '=')
77       return &Param[Len + 2];
78   return nullptr;
79 }
80
81 static bool ParseOneFlag(const char *Param) {
82   if (Param[0] != '-') return false;
83   for (size_t F = 0; F < kNumFlags; F++) {
84     const char *Name = FlagDescriptions[F].Name;
85     const char *Str = FlagValue(Param, Name);
86     if (Str)  {
87       int Val = std::stol(Str);
88       *FlagDescriptions[F].Flag = Val;
89       if (Flags.verbosity >= 2)
90         std::cerr << "Flag: " << Name << " " << Val << "\n";
91       return true;
92     }
93   }
94   PrintHelp();
95   exit(1);
96 }
97
98 // We don't use any library to minimize dependencies.
99 static void ParseFlags(int argc, char **argv) {
100   for (size_t F = 0; F < kNumFlags; F++)
101     *FlagDescriptions[F].Flag = FlagDescriptions[F].Default;
102   for (int A = 1; A < argc; A++) {
103     if (ParseOneFlag(argv[A])) continue;
104     inputs.push_back(argv[A]);
105   }
106 }
107
108 static void WorkerThread(const std::string &Cmd, std::atomic<int> *Counter,
109                         int NumJobs, std::atomic<bool> *HasErrors) {
110   static std::mutex CerrMutex;
111   while (true) {
112     int C = (*Counter)++;
113     if (C >= NumJobs) break;
114     std::string Log = "fuzz-" + std::to_string(C) + ".log";
115     std::string ToRun = Cmd + " > " + Log + " 2>&1\n";
116     if (Flags.verbosity)
117       std::cerr << ToRun;
118     int ExitCode = system(ToRun.c_str());
119     if (ExitCode != 0)
120       *HasErrors = true;
121     std::lock_guard<std::mutex> Lock(CerrMutex);
122     std::cerr << "================== Job " << C
123               << " exited with exit code " << ExitCode
124               << " =================\n";
125     fuzzer::CopyFileToErr(Log);
126   }
127 }
128
129 static int RunInMultipleProcesses(int argc, char **argv, int NumWorkers,
130                                   int NumJobs) {
131   std::atomic<int> Counter(0);
132   std::atomic<bool> HasErrors(false);
133   std::string Cmd;
134   for (int i = 0; i < argc; i++) {
135     if (FlagValue(argv[i], "jobs") || FlagValue(argv[i], "workers")) continue;
136     Cmd += argv[i];
137     Cmd += " ";
138   }
139   std::vector<std::thread> V;
140   for (int i = 0; i < NumWorkers; i++)
141     V.push_back(std::thread(WorkerThread, Cmd, &Counter, NumJobs, &HasErrors));
142   for (auto &T : V)
143     T.join();
144   return HasErrors ? 1 : 0;
145 }
146
147 int main(int argc, char **argv) {
148   using namespace fuzzer;
149
150   ProgName = argv[0];
151   ParseFlags(argc, argv);
152   if (Flags.help) {
153     PrintHelp();
154     return 0;
155   }
156
157   if (Flags.workers > 0 && Flags.jobs > 0)
158     return RunInMultipleProcesses(argc, argv, Flags.workers, Flags.jobs);
159
160   Fuzzer::FuzzingOptions Options;
161   Options.Verbosity = Flags.verbosity;
162   Options.MaxLen = Flags.max_len;
163   Options.DoCrossOver = Flags.cross_over;
164   Options.MutateDepth = Flags.mutate_depth;
165   Options.ExitOnFirst = Flags.exit_on_first;
166   Options.UseFullCoverageSet = Flags.use_full_coverage_set;
167   if (!inputs.empty())
168     Options.OutputCorpus = inputs[0];
169   Fuzzer F(Options);
170
171   unsigned seed = Flags.seed;
172   // Initialize seed.
173   if (seed == 0)
174     seed = time(0) * 10000 + getpid();
175   if (Flags.verbosity)
176     std::cerr << "Seed: " << seed << "\n";
177   srand(seed);
178
179   // Timer
180   if (Flags.timeout > 0)
181     SetTimer(Flags.timeout);
182
183   for (auto &inp : inputs)
184     F.ReadDir(inp);
185
186   if (F.CorpusSize() == 0)
187     F.AddToCorpus(Unit());  // Can't fuzz empty corpus, so add an empty input.
188   F.ShuffleAndMinimize();
189   if (Flags.save_minimized_corpus)
190     F.SaveCorpus();
191   F.Loop(Flags.iterations < 0 ? INT_MAX : Flags.iterations);
192   if (Flags.verbosity)
193     std::cerr << "Done\n";
194   return 0;
195 }