[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
GitOrigin-RevId: 84a48271d4bc4120df4cf01715bc722449686766
diff --git a/FuzzerTracePC.cpp b/FuzzerTracePC.cpp
index 37b32b7..7874f13 100644
--- a/FuzzerTracePC.cpp
+++ b/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<float>(count * 100) / NumInline8bitCounters);
 }