[libFuzzer] Add unstable function printing to print_unstable_stats flag

Summary:
There may be cases in which a user wants to know which part of their code is unstable.
We use ObservedFuncs and UnstableCounters to print at exit which of the ObservedFunctions
are unstable under the -print_unstable_stats flag.

Patch by Kyungtak Woo (@kevinwkt).

Reviewers: Dor1s, metzman, morehouse

Reviewed By: Dor1s, metzman, morehouse

Subscribers: delcypher, #sanitizers, llvm-commits, kcc

Differential Revision: https://reviews.llvm.org/D50264

llvm-svn: 339081
This commit is contained in:
Max Moroz 2018-08-06 23:14:13 +00:00
parent 673269edd7
commit 84a48271d4
4 changed files with 42 additions and 12 deletions

View File

@ -351,9 +351,21 @@ void TracePC::DumpCoverage() {
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<float>(count * 100) / NumInline8bitCounters);
}

View File

@ -18,11 +18,11 @@ __attribute__((noinline)) void ini0() { x++; }
__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 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
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);

View File

@ -13,11 +13,11 @@ NORMAL-DAG: det4()
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

View File

@ -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