diff options
-rw-r--r-- | llvm/docs/LibFuzzer.rst | 2 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerDriver.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerExtFunctions.def | 2 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerFlags.def | 2 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerInternal.h | 4 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/FuzzerLoop.cpp | 24 | ||||
-rw-r--r-- | llvm/lib/Fuzzer/test/fuzzer-printcovpcs.test | 6 |
7 files changed, 30 insertions, 12 deletions
diff --git a/llvm/docs/LibFuzzer.rst b/llvm/docs/LibFuzzer.rst index e3cbde01e84..be4eda323ad 100644 --- a/llvm/docs/LibFuzzer.rst +++ b/llvm/docs/LibFuzzer.rst @@ -270,6 +270,8 @@ The most important command line options are: failure (crash, timeout) as ``$(exact_artifact_path)``. This overrides ``-artifact_prefix`` and will not use checksum in the file name. Do not use the same path for several parallel processes. +``-print_pcs`` + If 1, print out newly covered PCs. Defaults to 0. ``-print_final_stats`` If 1, print statistics at exit. Defaults to 0. ``-detect_leaks`` diff --git a/llvm/lib/Fuzzer/FuzzerDriver.cpp b/llvm/lib/Fuzzer/FuzzerDriver.cpp index e9913e470fd..592c88a319e 100644 --- a/llvm/lib/Fuzzer/FuzzerDriver.cpp +++ b/llvm/lib/Fuzzer/FuzzerDriver.cpp @@ -334,7 +334,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { Printf("Dictionary: %zd entries\n", Dictionary.size()); bool DoPlainRun = AllInputsAreFiles(); Options.SaveArtifacts = !DoPlainRun; - Options.PrintNewCovPcs = Flags.print_new_cov_pcs; + Options.PrintNewCovPcs = Flags.print_pcs; Options.PrintFinalStats = Flags.print_final_stats; Options.TruncateUnits = Flags.truncate_units; Options.PruneCorpus = Flags.prune_corpus; diff --git a/llvm/lib/Fuzzer/FuzzerExtFunctions.def b/llvm/lib/Fuzzer/FuzzerExtFunctions.def index 08b661392ec..e5cb3a7d9bb 100644 --- a/llvm/lib/Fuzzer/FuzzerExtFunctions.def +++ b/llvm/lib/Fuzzer/FuzzerExtFunctions.def @@ -40,6 +40,8 @@ EXT_FUNC(__sanitizer_get_total_unique_caller_callee_pairs, size_t, (), false); EXT_FUNC(__sanitizer_get_total_unique_coverage, size_t, (), true); EXT_FUNC(__sanitizer_print_memory_profile, int, (size_t), false); EXT_FUNC(__sanitizer_print_stack_trace, void, (), true); +EXT_FUNC(__sanitizer_symbolize_pc, void, + (void *, const char *fmt, char *out_buf, size_t out_buf_size), false); EXT_FUNC(__sanitizer_reset_coverage, void, (), true); EXT_FUNC(__sanitizer_set_death_callback, void, (void (*)(void)), true); EXT_FUNC(__sanitizer_set_report_fd, void, (void*), false); diff --git a/llvm/lib/Fuzzer/FuzzerFlags.def b/llvm/lib/Fuzzer/FuzzerFlags.def index 0b313eb6570..c89e75c9f71 100644 --- a/llvm/lib/Fuzzer/FuzzerFlags.def +++ b/llvm/lib/Fuzzer/FuzzerFlags.def @@ -71,7 +71,7 @@ FUZZER_FLAG_STRING(exact_artifact_path, FUZZER_FLAG_INT(drill, 0, "Experimental: fuzz using a single unit as the seed " "corpus, then merge with the initial corpus") FUZZER_FLAG_INT(output_csv, 0, "Enable pulse output in CSV format.") -FUZZER_FLAG_INT(print_new_cov_pcs, 0, "If 1, print out new covered pcs.") +FUZZER_FLAG_INT(print_pcs, 0, "If 1, print out newly covered PCs.") FUZZER_FLAG_INT(print_final_stats, 0, "If 1, print statistics at exit.") FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.") diff --git a/llvm/lib/Fuzzer/FuzzerInternal.h b/llvm/lib/Fuzzer/FuzzerInternal.h index 4917f125842..bac83cf801c 100644 --- a/llvm/lib/Fuzzer/FuzzerInternal.h +++ b/llvm/lib/Fuzzer/FuzzerInternal.h @@ -455,6 +455,7 @@ private: void InterruptCallback(); void MutateAndTestOne(); void ReportNewCoverage(const Unit &U); + void PrintNewPCs(); bool RunOne(const Unit &U) { return RunOne(U.data(), U.size()); } void RunOneAndUpdateCorpus(const uint8_t *Data, size_t Size); void WriteToOutputCorpus(const Unit &U); @@ -516,9 +517,10 @@ private: // Maximum recorded coverage. Coverage MaxCoverage; - // For -print_new_cov_pcs + // For -print_pcs uintptr_t* PcBuffer = nullptr; size_t PcBufferLen = 0; + size_t PrevPcBufferPos; // Need to know our own thread. static thread_local bool IsMyThread; diff --git a/llvm/lib/Fuzzer/FuzzerLoop.cpp b/llvm/lib/Fuzzer/FuzzerLoop.cpp index e992612881a..01692ecfa57 100644 --- a/llvm/lib/Fuzzer/FuzzerLoop.cpp +++ b/llvm/lib/Fuzzer/FuzzerLoop.cpp @@ -441,15 +441,9 @@ void Fuzzer::ShuffleAndMinimize() { } bool Fuzzer::UpdateMaxCoverage() { - uintptr_t PrevPcBufferPos = MaxCoverage.PcBufferPos; + PrevPcBufferPos = MaxCoverage.PcBufferPos; bool Res = RecordMaxCoverage(&MaxCoverage); - if (Options.PrintNewCovPcs && PrevPcBufferPos != MaxCoverage.PcBufferPos) { - for (size_t I = PrevPcBufferPos; I < MaxCoverage.PcBufferPos; ++I) { - Printf("%p\n", PcBuffer[I]); - } - } - return Res; } @@ -566,6 +560,21 @@ void Fuzzer::PrintStatusForNewUnit(const Unit &U) { } } +void Fuzzer::PrintNewPCs() { + if (Options.PrintNewCovPcs && PrevPcBufferPos != MaxCoverage.PcBufferPos) { + for (size_t I = PrevPcBufferPos; I < MaxCoverage.PcBufferPos; ++I) { + if (EF->__sanitizer_symbolize_pc) { + char PcDescr[1024]; + EF->__sanitizer_symbolize_pc(reinterpret_cast<void*>(PcBuffer[I]), + "%p %F %L", PcDescr, sizeof(PcDescr)); + Printf("\tNEW_PC: %s\n", PcDescr); + } else { + Printf("\tNEW_PC: %p\n", PcBuffer[I]); + } + } + } +} + void Fuzzer::ReportNewCoverage(const Unit &U) { Corpus.push_back(U); UpdateCorpusDistribution(); @@ -574,6 +583,7 @@ void Fuzzer::ReportNewCoverage(const Unit &U) { PrintStatusForNewUnit(U); WriteToOutputCorpus(U); NumberOfNewUnitsAdded++; + PrintNewPCs(); } // Finds minimal number of units in 'Extra' that add coverage to 'Initial'. diff --git a/llvm/lib/Fuzzer/test/fuzzer-printcovpcs.test b/llvm/lib/Fuzzer/test/fuzzer-printcovpcs.test index 70b22c7a54b..bcc1c4d780b 100644 --- a/llvm/lib/Fuzzer/test/fuzzer-printcovpcs.test +++ b/llvm/lib/Fuzzer/test/fuzzer-printcovpcs.test @@ -1,5 +1,7 @@ -RUN: LLVMFuzzer-SimpleTest -print_new_cov_pcs=1 2>&1 | FileCheck %s --check-prefix=PCS -PCS:{{^0x[a-f0-9]+}} +RUN: LLVMFuzzer-SimpleTest -print_pcs=1 2>&1 | FileCheck %s --check-prefix=PCS +PCS-NOT: NEW_PC +PCS:INITED +PCS:NEW_PC: {{0x[a-f0-9]+}} in LLVMFuzzerTestOneInput {{.*}}SimpleTest.cpp PCS:NEW PCS:BINGO |