Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 1 | //===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===// |
| 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 | // Define the main class fuzzer::Fuzzer and most functions. |
| 10 | //===----------------------------------------------------------------------===// |
Yaron Keren | 347663b | 2015-08-10 16:37:40 +0000 | [diff] [blame] | 11 | |
| 12 | #ifndef LLVM_FUZZER_INTERNAL_H |
| 13 | #define LLVM_FUZZER_INTERNAL_H |
| 14 | |
Kostya Serebryany | 292cf03 | 2016-02-13 03:37:24 +0000 | [diff] [blame] | 15 | #include <algorithm> |
Kostya Serebryany | 0edb563 | 2016-05-27 00:54:15 +0000 | [diff] [blame] | 16 | #include <atomic> |
Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 17 | #include <chrono> |
Ivan Krasin | df91910 | 2016-01-22 22:28:27 +0000 | [diff] [blame] | 18 | #include <climits> |
Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 19 | #include <cstdlib> |
Kostya Serebryany | 476f0ce | 2016-01-16 03:53:32 +0000 | [diff] [blame] | 20 | #include <string.h> |
Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 21 | |
Kostya Serebryany | 6f5a804 | 2016-09-21 01:50:50 +0000 | [diff] [blame] | 22 | #include "FuzzerDefs.h" |
Kostya Serebryany | bceadcf | 2016-08-24 01:38:42 +0000 | [diff] [blame] | 23 | #include "FuzzerExtFunctions.h" |
| 24 | #include "FuzzerInterface.h" |
Kostya Serebryany | 556894f | 2016-09-21 02:05:39 +0000 | [diff] [blame] | 25 | #include "FuzzerOptions.h" |
Zachary Turner | 24a148b | 2016-11-30 19:06:14 +0000 | [diff] [blame] | 26 | #include "FuzzerSHA1.h" |
Kostya Serebryany | bceadcf | 2016-08-24 01:38:42 +0000 | [diff] [blame] | 27 | #include "FuzzerValueBitMap.h" |
| 28 | |
Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 29 | namespace fuzzer { |
Kostya Serebryany | 8b0d90a | 2016-05-13 18:04:35 +0000 | [diff] [blame] | 30 | |
Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 31 | using namespace std::chrono; |
Kostya Serebryany | 9690fcf | 2015-05-12 18:51:57 +0000 | [diff] [blame] | 32 | |
Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 33 | class Fuzzer { |
Ivan Krasin | df91910 | 2016-01-22 22:28:27 +0000 | [diff] [blame] | 34 | public: |
Mike Aizatsky | 1aa501e | 2016-05-10 23:43:15 +0000 | [diff] [blame] | 35 | |
| 36 | // Aggregates all available coverage measurements. |
| 37 | struct Coverage { |
| 38 | Coverage() { Reset(); } |
| 39 | |
| 40 | void Reset() { |
| 41 | BlockCoverage = 0; |
| 42 | CallerCalleeCoverage = 0; |
Mike Aizatsky | 1aa501e | 2016-05-10 23:43:15 +0000 | [diff] [blame] | 43 | CounterBitmapBits = 0; |
Mike Aizatsky | 1aa501e | 2016-05-10 23:43:15 +0000 | [diff] [blame] | 44 | CounterBitmap.clear(); |
Kostya Serebryany | d46a59f | 2016-08-16 19:33:51 +0000 | [diff] [blame] | 45 | VPMap.Reset(); |
Mike Aizatsky | 1aa501e | 2016-05-10 23:43:15 +0000 | [diff] [blame] | 46 | } |
| 47 | |
Mike Aizatsky | 1aa501e | 2016-05-10 23:43:15 +0000 | [diff] [blame] | 48 | size_t BlockCoverage; |
| 49 | size_t CallerCalleeCoverage; |
Mike Aizatsky | 1aa501e | 2016-05-10 23:43:15 +0000 | [diff] [blame] | 50 | // Precalculated number of bits in CounterBitmap. |
| 51 | size_t CounterBitmapBits; |
| 52 | std::vector<uint8_t> CounterBitmap; |
Kostya Serebryany | d46a59f | 2016-08-16 19:33:51 +0000 | [diff] [blame] | 53 | ValueBitMap VPMap; |
Mike Aizatsky | 1aa501e | 2016-05-10 23:43:15 +0000 | [diff] [blame] | 54 | }; |
| 55 | |
Kostya Serebryany | 29bb664 | 2016-09-21 22:42:17 +0000 | [diff] [blame] | 56 | Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, |
| 57 | FuzzingOptions Options); |
Mike Aizatsky | b4bbc3b | 2016-08-05 20:09:53 +0000 | [diff] [blame] | 58 | ~Fuzzer(); |
Kostya Serebryany | 468ed78 | 2015-09-08 17:30:35 +0000 | [diff] [blame] | 59 | void Loop(); |
Kostya Serebryany | f9b8e8b | 2016-10-15 01:00:24 +0000 | [diff] [blame] | 60 | void MinimizeCrashLoop(const Unit &U); |
Kostya Serebryany | 09aa01a | 2016-09-21 01:04:43 +0000 | [diff] [blame] | 61 | void ShuffleAndMinimize(UnitVector *V); |
Kostya Serebryany | 2252625 | 2015-05-11 21:16:27 +0000 | [diff] [blame] | 62 | void InitializeTraceState(); |
Kostya Serebryany | 64d2457 | 2016-03-12 01:57:04 +0000 | [diff] [blame] | 63 | void RereadOutputCorpus(size_t MaxSize); |
Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 64 | |
Kostya Serebryany | 92e0476 | 2015-02-04 23:42:42 +0000 | [diff] [blame] | 65 | size_t secondsSinceProcessStartUp() { |
| 66 | return duration_cast<seconds>(system_clock::now() - ProcessStartTime) |
| 67 | .count(); |
| 68 | } |
Kostya Serebryany | f9b8e8b | 2016-10-15 01:00:24 +0000 | [diff] [blame] | 69 | |
| 70 | bool TimedOut() { |
| 71 | return Options.MaxTotalTimeSec > 0 && |
| 72 | secondsSinceProcessStartUp() > |
| 73 | static_cast<size_t>(Options.MaxTotalTimeSec); |
| 74 | } |
| 75 | |
Kostya Serebryany | 66ff075 | 2016-02-26 22:42:23 +0000 | [diff] [blame] | 76 | size_t execPerSec() { |
| 77 | size_t Seconds = secondsSinceProcessStartUp(); |
| 78 | return Seconds ? TotalNumberOfRuns / Seconds : 0; |
| 79 | } |
Kostya Serebryany | 92e0476 | 2015-02-04 23:42:42 +0000 | [diff] [blame] | 80 | |
| 81 | size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; } |
| 82 | |
Kostya Serebryany | 52a788e | 2015-03-31 20:13:20 +0000 | [diff] [blame] | 83 | static void StaticAlarmCallback(); |
Kostya Serebryany | 228d5b1 | 2016-03-01 22:19:21 +0000 | [diff] [blame] | 84 | static void StaticCrashSignalCallback(); |
| 85 | static void StaticInterruptCallback(); |
Kostya Serebryany | 52a788e | 2015-03-31 20:13:20 +0000 | [diff] [blame] | 86 | |
Kostya Serebryany | 8a5bef0 | 2016-02-13 17:56:51 +0000 | [diff] [blame] | 87 | void ExecuteCallback(const uint8_t *Data, size_t Size); |
Kostya Serebryany | 1c73f1b | 2016-10-05 22:56:21 +0000 | [diff] [blame] | 88 | size_t RunOne(const uint8_t *Data, size_t Size); |
Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 89 | |
Kostya Serebryany | 9cc3b0d | 2015-10-24 01:16:40 +0000 | [diff] [blame] | 90 | // Merge Corpora[1:] into Corpora[0]. |
| 91 | void Merge(const std::vector<std::string> &Corpora); |
Kostya Serebryany | 945761b | 2016-03-18 00:23:29 +0000 | [diff] [blame] | 92 | // Returns a subset of 'Extra' that adds coverage to 'Initial'. |
| 93 | UnitVector FindExtraUnits(const UnitVector &Initial, const UnitVector &Extra); |
Kostya Serebryany | 1deb049 | 2016-02-13 06:24:18 +0000 | [diff] [blame] | 94 | MutationDispatcher &GetMD() { return MD; } |
Kostya Serebryany | 66ff075 | 2016-02-26 22:42:23 +0000 | [diff] [blame] | 95 | void PrintFinalStats(); |
Kostya Serebryany | be0ed59 | 2016-09-22 23:16:36 +0000 | [diff] [blame] | 96 | void SetMaxInputLen(size_t MaxInputLen); |
| 97 | void SetMaxMutationLen(size_t MaxMutationLen); |
Kostya Serebryany | 8b8f7a3 | 2016-05-06 23:38:07 +0000 | [diff] [blame] | 98 | void RssLimitCallback(); |
Kostya Serebryany | 9cc3b0d | 2015-10-24 01:16:40 +0000 | [diff] [blame] | 99 | |
Mike Aizatsky | af432a4 | 2016-05-24 23:14:29 +0000 | [diff] [blame] | 100 | // Public for tests. |
| 101 | void ResetCoverage(); |
| 102 | |
Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 103 | bool InFuzzingThread() const { return IsMyThread; } |
Kostya Serebryany | d838412 | 2016-05-26 22:17:32 +0000 | [diff] [blame] | 104 | size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const; |
Kostya Serebryany | bb59ef7 | 2016-10-18 18:38:08 +0000 | [diff] [blame] | 105 | void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, |
| 106 | bool DuringInitialCorpusExecution); |
Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 107 | |
Kostya Serebryany | 05f7791 | 2016-11-30 22:39:35 +0000 | [diff] [blame^] | 108 | void HandleMalloc(size_t Size); |
| 109 | |
Ivan Krasin | df91910 | 2016-01-22 22:28:27 +0000 | [diff] [blame] | 110 | private: |
Kostya Serebryany | 52a788e | 2015-03-31 20:13:20 +0000 | [diff] [blame] | 111 | void AlarmCallback(); |
Kostya Serebryany | 228d5b1 | 2016-03-01 22:19:21 +0000 | [diff] [blame] | 112 | void CrashCallback(); |
| 113 | void InterruptCallback(); |
Kostya Serebryany | 27ab2d7 | 2015-12-19 02:49:09 +0000 | [diff] [blame] | 114 | void MutateAndTestOne(); |
Kostya Serebryany | 29bb664 | 2016-09-21 22:42:17 +0000 | [diff] [blame] | 115 | void ReportNewCoverage(InputInfo *II, const Unit &U); |
Kostya Serebryany | 1c73f1b | 2016-10-05 22:56:21 +0000 | [diff] [blame] | 116 | size_t RunOne(const Unit &U) { return RunOne(U.data(), U.size()); } |
Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 117 | void WriteToOutputCorpus(const Unit &U); |
Kostya Serebryany | 2b7d2e9 | 2015-07-23 18:37:22 +0000 | [diff] [blame] | 118 | void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix); |
Kostya Serebryany | 16a145f | 2016-09-23 01:58:51 +0000 | [diff] [blame] | 119 | void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0); |
Kostya Serebryany | dc3135d | 2015-11-12 01:02:01 +0000 | [diff] [blame] | 120 | void PrintStatusForNewUnit(const Unit &U); |
Kostya Serebryany | 945761b | 2016-03-18 00:23:29 +0000 | [diff] [blame] | 121 | void ShuffleCorpus(UnitVector *V); |
Kostya Serebryany | 90f8f36 | 2016-09-30 23:29:27 +0000 | [diff] [blame] | 122 | void AddToCorpus(const Unit &U); |
Kostya Serebryany | 8dfed45 | 2016-10-18 18:06:05 +0000 | [diff] [blame] | 123 | void CheckExitOnSrcPosOrItem(); |
Kostya Serebryany | 945761b | 2016-03-18 00:23:29 +0000 | [diff] [blame] | 124 | |
Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 125 | // Trace-based fuzzing: we run a unit with some kind of tracing |
| 126 | // enabled and record potentially useful mutations. Then |
| 127 | // We apply these mutations one by one to the unit and run it again. |
| 128 | |
| 129 | // Start tracing; forget all previously proposed mutations. |
| 130 | void StartTraceRecording(); |
Kostya Serebryany | b65805a | 2016-01-09 03:08:58 +0000 | [diff] [blame] | 131 | // Stop tracing. |
| 132 | void StopTraceRecording(); |
Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 133 | |
Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 134 | void SetDeathCallback(); |
Kostya Serebryany | 52a788e | 2015-03-31 20:13:20 +0000 | [diff] [blame] | 135 | static void StaticDeathCallback(); |
Kostya Serebryany | 228d5b1 | 2016-03-01 22:19:21 +0000 | [diff] [blame] | 136 | void DumpCurrentUnit(const char *Prefix); |
Kostya Serebryany | 52a788e | 2015-03-31 20:13:20 +0000 | [diff] [blame] | 137 | void DeathCallback(); |
Kostya Serebryany | 98abb2c | 2016-01-13 23:46:01 +0000 | [diff] [blame] | 138 | |
Kostya Serebryany | f67357c | 2016-08-25 01:25:03 +0000 | [diff] [blame] | 139 | void ResetEdgeCoverage(); |
Kostya Serebryany | b76a2a5 | 2016-09-09 02:38:28 +0000 | [diff] [blame] | 140 | void ResetCounters(); |
Kostya Serebryany | f67357c | 2016-08-25 01:25:03 +0000 | [diff] [blame] | 141 | void PrepareCounters(Fuzzer::Coverage *C); |
| 142 | bool RecordMaxCoverage(Fuzzer::Coverage *C); |
| 143 | |
Kostya Serebryany | be0ed59 | 2016-09-22 23:16:36 +0000 | [diff] [blame] | 144 | void AllocateCurrentUnitData(); |
Kostya Serebryany | 8fc3a27 | 2016-05-27 00:21:33 +0000 | [diff] [blame] | 145 | uint8_t *CurrentUnitData = nullptr; |
Kostya Serebryany | 0edb563 | 2016-05-27 00:54:15 +0000 | [diff] [blame] | 146 | std::atomic<size_t> CurrentUnitSize; |
Kostya Serebryany | a9a5480 | 2016-08-17 20:45:23 +0000 | [diff] [blame] | 147 | uint8_t BaseSha1[kSHA1NumBytes]; // Checksum of the base unit. |
Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 148 | |
| 149 | size_t TotalNumberOfRuns = 0; |
Kostya Serebryany | 66ff075 | 2016-02-26 22:42:23 +0000 | [diff] [blame] | 150 | size_t NumberOfNewUnitsAdded = 0; |
Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 151 | |
Kostya Serebryany | 1bfd583 | 2016-04-20 00:24:21 +0000 | [diff] [blame] | 152 | bool HasMoreMallocsThanFrees = false; |
Kostya Serebryany | 7018a1a | 2016-04-27 19:52:34 +0000 | [diff] [blame] | 153 | size_t NumberOfLeakDetectionAttempts = 0; |
Kostya Serebryany | 1bfd583 | 2016-04-20 00:24:21 +0000 | [diff] [blame] | 154 | |
Kostya Serebryany | 7ec0c56 | 2016-02-13 03:25:16 +0000 | [diff] [blame] | 155 | UserCallback CB; |
Kostya Serebryany | 29bb664 | 2016-09-21 22:42:17 +0000 | [diff] [blame] | 156 | InputCorpus &Corpus; |
Kostya Serebryany | 7ec0c56 | 2016-02-13 03:25:16 +0000 | [diff] [blame] | 157 | MutationDispatcher &MD; |
Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 158 | FuzzingOptions Options; |
Kostya Serebryany | 29bb664 | 2016-09-21 22:42:17 +0000 | [diff] [blame] | 159 | |
Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 160 | system_clock::time_point ProcessStartTime = system_clock::now(); |
Kostya Serebryany | 624f59f | 2016-09-22 01:34:58 +0000 | [diff] [blame] | 161 | system_clock::time_point UnitStartTime, UnitStopTime; |
Kostya Serebryany | 16901a9 | 2015-03-30 23:04:35 +0000 | [diff] [blame] | 162 | long TimeOfLongestUnitInSeconds = 0; |
Kostya Serebryany | 1ac8055 | 2015-05-08 21:30:55 +0000 | [diff] [blame] | 163 | long EpochOfLastReadOfOutputCorpus = 0; |
Mike Aizatsky | 1aa501e | 2016-05-10 23:43:15 +0000 | [diff] [blame] | 164 | |
| 165 | // Maximum recorded coverage. |
| 166 | Coverage MaxCoverage; |
Kostya Serebryany | f67357c | 2016-08-25 01:25:03 +0000 | [diff] [blame] | 167 | |
Kostya Serebryany | be0ed59 | 2016-09-22 23:16:36 +0000 | [diff] [blame] | 168 | size_t MaxInputLen = 0; |
| 169 | size_t MaxMutationLen = 0; |
| 170 | |
Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 171 | // Need to know our own thread. |
| 172 | static thread_local bool IsMyThread; |
Kostya Serebryany | b991cc1 | 2016-09-10 00:15:41 +0000 | [diff] [blame] | 173 | |
| 174 | bool InMergeMode = false; |
Aaron Ballman | ef11698 | 2015-01-29 16:58:29 +0000 | [diff] [blame] | 175 | }; |
| 176 | |
Ivan Krasin | df91910 | 2016-01-22 22:28:27 +0000 | [diff] [blame] | 177 | }; // namespace fuzzer |
Yaron Keren | 347663b | 2015-08-10 16:37:40 +0000 | [diff] [blame] | 178 | |
| 179 | #endif // LLVM_FUZZER_INTERNAL_H |