Printf("Dictionary: %zd entries\n", Dictionary.size());
Options.SaveArtifacts = !Flags.test_single_input;
Options.PrintNewCovPcs = Flags.print_new_cov_pcs;
+ Options.PrintFinalStats = Flags.print_final_stats;
unsigned Seed = Flags.seed;
// Initialize Seed.
if (Flags.verbosity)
Printf("Done %d runs in %zd second(s)\n", F.getTotalNumberOfRuns(),
F.secondsSinceProcessStartUp());
+ F.PrintFinalStats();
exit(0); // Don't let F destroy itself.
}
"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_final_stats, 0, "If 1, print statistics at exit.")
void SetTimer(int Seconds);
std::string Base64(const Unit &U);
int ExecuteCommand(const std::string &Command);
+size_t GetPeakRSSMb();
// Private copy of SHA1 implementation.
static const int kSHA1NumBytes = 20;
bool PrintNEW = true; // Print a status line when new units are found;
bool OutputCSV = false;
bool PrintNewCovPcs = false;
+ bool PrintFinalStats = false;
};
Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options);
void AddToCorpus(const Unit &U) {
return duration_cast<seconds>(system_clock::now() - ProcessStartTime)
.count();
}
+ size_t execPerSec() {
+ size_t Seconds = secondsSinceProcessStartUp();
+ return Seconds ? TotalNumberOfRuns / Seconds : 0;
+ }
size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; }
// Merge Corpora[1:] into Corpora[0].
void Merge(const std::vector<std::string> &Corpora);
MutationDispatcher &GetMD() { return MD; }
+ void PrintFinalStats();
private:
void AlarmCallback();
size_t TotalNumberOfRuns = 0;
size_t TotalNumberOfExecutedTraceBasedMutations = 0;
+ size_t NumberOfNewUnitsAdded = 0;
std::vector<Unit> Corpus;
std::unordered_set<std::string> UnitHashesAddedToCorpus;
}
WriteUnitToFileWithPrefix(
{CurrentUnitData, CurrentUnitData + CurrentUnitSize}, "crash-");
+ PrintFinalStats();
}
void Fuzzer::StaticAlarmCallback() {
if (__sanitizer_print_stack_trace)
__sanitizer_print_stack_trace();
Printf("SUMMARY: libFuzzer: timeout\n");
+ PrintFinalStats();
if (Options.AbortOnTimeout)
abort();
exit(Options.TimeoutExitCode);
}
void Fuzzer::PrintStats(const char *Where, const char *End) {
- size_t Seconds = secondsSinceProcessStartUp();
- size_t ExecPerSec = (Seconds ? TotalNumberOfRuns / Seconds : 0);
-
+ size_t ExecPerSec = execPerSec();
if (Options.OutputCSV) {
static bool csvHeaderPrinted = false;
if (!csvHeaderPrinted) {
Printf("%s", End);
}
+void Fuzzer::PrintFinalStats() {
+ if (!Options.PrintFinalStats) return;
+ size_t ExecPerSec = execPerSec();
+ Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns);
+ Printf("stat::average_exec_per_sec: %zd\n", ExecPerSec);
+ Printf("stat::new_units_added: %zd\n", NumberOfNewUnitsAdded);
+ Printf("stat::slowest_unit_time_sec: %zd\n", TimeOfLongestUnitInSeconds);
+ Printf("stat::peak_rss_mb: %zd\n", GetPeakRSSMb());
+}
+
void Fuzzer::RereadOutputCorpus() {
if (Options.OutputCorpus.empty())
return;
MD.RecordSuccessfulMutationSequence();
PrintStatusForNewUnit(U);
WriteToOutputCorpus(U);
+ NumberOfNewUnitsAdded++;
if (Options.ExitOnFirst)
exit(0);
}
#include "FuzzerInternal.h"
#include <sstream>
#include <iomanip>
+#include <sys/resource.h>
#include <sys/time.h>
#include <cassert>
#include <cstring>
return Res;
}
+size_t GetPeakRSSMb() {
+ struct rusage usage;
+ if (getrusage(RUSAGE_SELF, &usage))
+ return 0;
+ return usage.ru_maxrss >> 10;
+}
+
} // namespace fuzzer
RUN: not LLVMFuzzer-CustomMutatorTest 2>&1 | FileCheck %s --check-prefix=LLVMFuzzerCustomMutator
LLVMFuzzerCustomMutator: In LLVMFuzzerCustomMutator
LLVMFuzzerCustomMutator: BINGO
+
+RUN: LLVMFuzzer-SimpleTest -seed=1 -runs=77 -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=FINAL_STATS
+FINAL_STATS: stat::number_of_executed_units: 77
+FINAL_STATS: stat::average_exec_per_sec: 0
+FINAL_STATS: stat::new_units_added:
+FINAL_STATS: stat::slowest_unit_time_sec: 0
+FINAL_STATS: stat::peak_rss_mb:
+