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