Index: lib/fuzzer/FuzzerTracePC.cpp =================================================================== --- lib/fuzzer/FuzzerTracePC.cpp +++ lib/fuzzer/FuzzerTracePC.cpp @@ -351,9 +351,21 @@ void TracePC::PrintUnstableStats() { size_t count = 0; - for (size_t i = 0; i < NumInline8bitCounters; i++) - if (UnstableCounters[i].IsUnstable) + Printf("UNSTABLE_FUNCTIONS:\n"); + IterateInline8bitCounters([&](int i, int j, int UnstableIdx) { + const PCTableEntry &TE = ModulePCTable[i].Start[j]; + if (UnstableCounters[UnstableIdx].IsUnstable) { count++; + if (ObservedFuncs.count(TE.PC)) { + auto VisualizePC = GetNextInstructionPc(TE.PC); + std::string FunctionStr = DescribePC("%F", VisualizePC); + if (FunctionStr.find("in ") == 0) + FunctionStr = FunctionStr.substr(3); + Printf("%s\n", FunctionStr.c_str()); + } + } + }); + Printf("stat::stability_rate: %.2f\n", 100 - static_cast(count * 100) / NumInline8bitCounters); } Index: test/fuzzer/PrintUnstableStatsTest.cpp =================================================================== --- test/fuzzer/PrintUnstableStatsTest.cpp +++ test/fuzzer/PrintUnstableStatsTest.cpp @@ -18,11 +18,11 @@ __attribute__((noinline)) void ini1() { x++; } __attribute__((noinline)) void ini2() { x++; } -__attribute__((noinline)) void t0() { x++; } +__attribute__((noinline)) void t0(int a) { x += a; } __attribute__((noinline)) void t1() { x++; } -__attribute__((noinline)) void t2() { x++; } +__attribute__((noinline)) void t2(int a, int b) { x += a + b; } __attribute__((noinline)) void t3() { x++; } -__attribute__((noinline)) void t4() { x++; } +__attribute__((noinline)) void t4(int a, int b, int c) { x += a + b +c; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (Size == 1 && Data[0] == 'A' && !skip0) { @@ -45,19 +45,19 @@ switch (a % 5) { case 0: - t0(); + t0(a); break; case 1: t1(); break; case 2: - t2(); + t2(a, a); break; case 3: t3(); break; case 4: - t4(); + t4(a, a, a); break; default: assert(false); Index: test/fuzzer/handle-unstable.test =================================================================== --- test/fuzzer/handle-unstable.test +++ test/fuzzer/handle-unstable.test @@ -13,11 +13,11 @@ NORMAL-DAG: ini0() NORMAL-DAG: ini1() NORMAL-DAG: ini2() -NORMAL-DAG: t0() +NORMAL-DAG: t0(int) NORMAL-DAG: t1() -NORMAL-DAG: t2() +NORMAL-DAG: t2(int, int) NORMAL-DAG: t3() -NORMAL-DAG: t4() +NORMAL-DAG: t4(int, int, int) ; MinUnstable RUN: %run %t-HandleUnstableTest -print_coverage=1 -handle_unstable=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=MIN Index: test/fuzzer/print_unstable_stats.test =================================================================== --- test/fuzzer/print_unstable_stats.test +++ test/fuzzer/print_unstable_stats.test @@ -1,3 +1,21 @@ RUN: %cpp_compiler %S/PrintUnstableStatsTest.cpp -o %t-PrintUnstableStatsTest + RUN: %run %t-PrintUnstableStatsTest -print_unstable_stats=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=LONG -LONG: stat::stability_rate: 27.59 +; We do not observe ini functions since we take the minimum hit counts, and minimum hit counts for ini is 0. +LONG: UNSTABLE_FUNCTIONS:{{$}} +LONG-NOT: {{^}}det0(){{$}} +LONG-NOT: {{^}}det1(){{$}} +LONG-NOT: {{^}}det2(){{$}} +LONG-NOT: {{^}}det3(){{$}} +LONG-NOT: {{^}}det4(){{$}} +LONG-NOT: {{^}}ini0(){{$}} +LONG-NOT: {{^}}ini1(){{$}} +LONG-NOT: {{^}}ini2(){{$}} +LONG-DAG: {{^}}t0(int){{$}} +LONG-DAG: {{^}}t1(){{$}} +LONG-DAG: {{^}}t2(int, int){{$}} +LONG-DAG: {{^}}t3(){{$}} +LONG-DAG: {{^}}t4(int, int, int){{$}} + +LONG-DAG: stat::stability_rate: 27.59 +