X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FFuzzer%2FFuzzerLoop.cpp;h=5237682ff24d58001e1d9159133dc792050874c5;hb=43a24b5d9351abd97a0e2378cd167bb9ee6d9a8d;hp=7aea169b7ae992905a1828614ad5894dde421431;hpb=e8d7ae6209f89e7ad2f5b22f48960a1def2c69c1;p=oota-llvm.git diff --git a/lib/Fuzzer/FuzzerLoop.cpp b/lib/Fuzzer/FuzzerLoop.cpp index 7aea169b7ae..5237682ff24 100644 --- a/lib/Fuzzer/FuzzerLoop.cpp +++ b/lib/Fuzzer/FuzzerLoop.cpp @@ -31,6 +31,8 @@ void __sanitizer_set_death_callback(void (*callback)(void)); __attribute__((weak)) size_t __sanitizer_get_number_of_counters(); __attribute__((weak)) uintptr_t __sanitizer_update_counter_bitset_and_clear_counters(uint8_t *bitset); +__attribute__((weak)) uintptr_t +__sanitizer_get_coverage_pc_buffer(uintptr_t **data); } namespace fuzzer { @@ -238,14 +240,32 @@ void Fuzzer::RunOneAndUpdateCorpus(Unit &U) { } void Fuzzer::ExecuteCallback(const Unit &U) { - int Res = USF.TargetFunction(U.data(), U.size()); + const uint8_t *Data = U.data(); + uint8_t EmptyData; + if (!Data) + Data = &EmptyData; + int Res = USF.TargetFunction(Data, U.size()); (void)Res; assert(Res == 0); } size_t Fuzzer::RecordBlockCoverage() { CHECK_WEAK_API_FUNCTION(__sanitizer_get_total_unique_coverage); - return LastRecordedBlockCoverage = __sanitizer_get_total_unique_coverage(); + uintptr_t PrevCoverage = LastRecordedBlockCoverage; + LastRecordedBlockCoverage = __sanitizer_get_total_unique_coverage(); + + if (PrevCoverage == LastRecordedBlockCoverage || !Options.PrintNewCovPcs) + return LastRecordedBlockCoverage; + + uintptr_t PrevBufferLen = LastCoveragePcBufferLen; + uintptr_t *CoverageBuf; + LastCoveragePcBufferLen = __sanitizer_get_coverage_pc_buffer(&CoverageBuf); + assert(CoverageBuf); + for (size_t i = PrevBufferLen; i < LastCoveragePcBufferLen; ++i) { + Printf("0x%x\n", CoverageBuf[i]); + } + + return LastRecordedBlockCoverage; } size_t Fuzzer::RecordCallerCalleeCoverage() { @@ -298,10 +318,8 @@ void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) { WriteToFile(U, Path); Printf("artifact_prefix='%s'; Test unit written to %s\n", Options.ArtifactPrefix.c_str(), Path.c_str()); - if (U.size() <= kMaxUnitSizeToPrint) { - Printf("Base64: "); - PrintFileAsBase64(Path); - } + if (U.size() <= kMaxUnitSizeToPrint) + Printf("Base64: %s\n", Base64(U).c_str()); } void Fuzzer::SaveCorpus() { @@ -318,12 +336,8 @@ void Fuzzer::PrintStatusForNewUnit(const Unit &U) { return; PrintStats("NEW ", ""); if (Options.Verbosity) { - Printf(" L: %zd", U.size()); - if (U.size() < 30) { - Printf(" "); - PrintUnitInASCII(U, "\t"); - Print(U); - } + Printf(" L: %zd ", U.size()); + USF.PrintMutationSequence(); Printf("\n"); } } @@ -369,31 +383,24 @@ void Fuzzer::Merge(const std::vector &Corpora) { Printf("Merge: written %zd out of %zd units\n", NumMerged, NumTried); } -void Fuzzer::MutateAndTestOne(Unit *U) { +void Fuzzer::MutateAndTestOne() { + auto &U = CurrentUnit; + USF.StartMutationSequence(); + + U = ChooseUnitToMutate(); + for (int i = 0; i < Options.MutateDepth; i++) { - StartTraceRecording(); - size_t Size = U->size(); - U->resize(Options.MaxLen); - size_t NewSize = USF.Mutate(U->data(), Size, U->size()); + size_t Size = U.size(); + U.resize(Options.MaxLen); + size_t NewSize = USF.Mutate(U.data(), Size, U.size()); assert(NewSize > 0 && "Mutator returned empty unit"); assert(NewSize <= (size_t)Options.MaxLen && "Mutator return overisized unit"); - U->resize(NewSize); - RunOneAndUpdateCorpus(*U); - size_t NumTraceBasedMutations = StopTraceRecording(); - size_t TBMWidth = - std::min((size_t)Options.TBMWidth, NumTraceBasedMutations); - size_t TBMDepth = - std::min((size_t)Options.TBMDepth, NumTraceBasedMutations); - Unit BackUp = *U; - for (size_t w = 0; w < TBMWidth; w++) { - *U = BackUp; - for (size_t d = 0; d < TBMDepth; d++) { - TotalNumberOfExecutedTraceBasedMutations++; - ApplyTraceBasedMutation(USF.GetRand()(NumTraceBasedMutations), U); - RunOneAndUpdateCorpus(*U); - } - } + U.resize(NewSize); + if (i == 0) + StartTraceRecording(); + RunOneAndUpdateCorpus(U); + StopTraceRecording(); } } @@ -448,12 +455,15 @@ void Fuzzer::Drill() { PrintStats("REINIT"); SavedOutputCorpusPath.swap(Options.OutputCorpus); - for (auto &U : SavedCorpus) + for (auto &U : SavedCorpus) { + CurrentUnit = U; RunOne(U); + } PrintStats("MERGE "); Options.PrintNEW = true; size_t NumMerged = 0; for (auto &U : Corpus) { + CurrentUnit = U; if (RunOne(U)) { PrintStatusForNewUnit(U); NumMerged++; @@ -466,34 +476,24 @@ void Fuzzer::Drill() { } void Fuzzer::Loop() { + system_clock::time_point LastCorpusReload = system_clock::now(); + if (Options.DoCrossOver) + USF.SetCorpus(&Corpus); while (true) { - size_t J1 = ChooseUnitIdxToMutate();; SyncCorpus(); - RereadOutputCorpus(); + auto Now = system_clock::now(); + if (duration_cast(Now - LastCorpusReload).count()) { + RereadOutputCorpus(); + LastCorpusReload = Now; + } if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) break; if (Options.MaxTotalTimeSec > 0 && secondsSinceProcessStartUp() > static_cast(Options.MaxTotalTimeSec)) break; - CurrentUnit = Corpus[J1]; - // Optionally, cross with another unit. - if (Options.DoCrossOver && USF.GetRand().RandBool()) { - size_t J2 = ChooseUnitIdxToMutate(); - if (!Corpus[J1].empty() && !Corpus[J2].empty()) { - assert(!Corpus[J2].empty()); - CurrentUnit.resize(Options.MaxLen); - size_t NewSize = USF.CrossOver( - Corpus[J1].data(), Corpus[J1].size(), Corpus[J2].data(), - Corpus[J2].size(), CurrentUnit.data(), CurrentUnit.size()); - assert(NewSize > 0 && "CrossOver returned empty unit"); - assert(NewSize <= (size_t)Options.MaxLen && - "CrossOver returned overisized unit"); - CurrentUnit.resize(NewSize); - } - } // Perform several mutations and runs. - MutateAndTestOne(&CurrentUnit); + MutateAndTestOne(); } PrintStats("DONE ", "\n");