Home | History | Annotate | Line # | Download | only in fuzzer
      1  1.1  kamil //===- FuzzerTracePC.cpp - PC tracing--------------------------------------===//
      2  1.1  kamil //
      3  1.1  kamil //                     The LLVM Compiler Infrastructure
      4  1.1  kamil //
      5  1.1  kamil // This file is distributed under the University of Illinois Open Source
      6  1.1  kamil // License. See LICENSE.TXT for details.
      7  1.1  kamil //
      8  1.1  kamil //===----------------------------------------------------------------------===//
      9  1.1  kamil // Trace PCs.
     10  1.1  kamil // This module implements __sanitizer_cov_trace_pc_guard[_init],
     11  1.1  kamil // the callback required for -fsanitize-coverage=trace-pc-guard instrumentation.
     12  1.1  kamil //
     13  1.1  kamil //===----------------------------------------------------------------------===//
     14  1.1  kamil 
     15  1.1  kamil #include "FuzzerTracePC.h"
     16  1.1  kamil #include "FuzzerCorpus.h"
     17  1.1  kamil #include "FuzzerDefs.h"
     18  1.1  kamil #include "FuzzerDictionary.h"
     19  1.1  kamil #include "FuzzerExtFunctions.h"
     20  1.1  kamil #include "FuzzerIO.h"
     21  1.1  kamil #include "FuzzerUtil.h"
     22  1.1  kamil #include "FuzzerValueBitMap.h"
     23  1.1  kamil #include <set>
     24  1.1  kamil 
     25  1.1  kamil // The coverage counters and PCs.
     26  1.1  kamil // These are declared as global variables named "__sancov_*" to simplify
     27  1.1  kamil // experiments with inlined instrumentation.
     28  1.1  kamil alignas(64) ATTRIBUTE_INTERFACE
     29  1.1  kamil uint8_t __sancov_trace_pc_guard_8bit_counters[fuzzer::TracePC::kNumPCs];
     30  1.1  kamil 
     31  1.1  kamil ATTRIBUTE_INTERFACE
     32  1.1  kamil uintptr_t __sancov_trace_pc_pcs[fuzzer::TracePC::kNumPCs];
     33  1.1  kamil 
     34  1.1  kamil // Used by -fsanitize-coverage=stack-depth to track stack depth
     35  1.1  kamil ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC uintptr_t __sancov_lowest_stack;
     36  1.1  kamil 
     37  1.1  kamil namespace fuzzer {
     38  1.1  kamil 
     39  1.1  kamil TracePC TPC;
     40  1.1  kamil 
     41  1.1  kamil uint8_t *TracePC::Counters() const {
     42  1.1  kamil   return __sancov_trace_pc_guard_8bit_counters;
     43  1.1  kamil }
     44  1.1  kamil 
     45  1.1  kamil uintptr_t *TracePC::PCs() const {
     46  1.1  kamil   return __sancov_trace_pc_pcs;
     47  1.1  kamil }
     48  1.1  kamil 
     49  1.1  kamil size_t TracePC::GetTotalPCCoverage() {
     50  1.1  kamil   if (ObservedPCs.size())
     51  1.1  kamil     return ObservedPCs.size();
     52  1.1  kamil   size_t Res = 0;
     53  1.1  kamil   for (size_t i = 1, N = GetNumPCs(); i < N; i++)
     54  1.1  kamil     if (PCs()[i])
     55  1.1  kamil       Res++;
     56  1.1  kamil   return Res;
     57  1.1  kamil }
     58  1.1  kamil 
     59  1.1  kamil template<class CallBack>
     60  1.1  kamil void TracePC::IterateInline8bitCounters(CallBack CB) const {
     61  1.1  kamil   if (NumInline8bitCounters && NumInline8bitCounters == NumPCsInPCTables) {
     62  1.1  kamil     size_t CounterIdx = 0;
     63  1.1  kamil     for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
     64  1.1  kamil       uint8_t *Beg = ModuleCounters[i].Start;
     65  1.1  kamil       size_t Size = ModuleCounters[i].Stop - Beg;
     66  1.1  kamil       assert(Size == (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start));
     67  1.1  kamil       for (size_t j = 0; j < Size; j++, CounterIdx++)
     68  1.1  kamil         CB(i, j, CounterIdx);
     69  1.1  kamil     }
     70  1.1  kamil   }
     71  1.1  kamil }
     72  1.1  kamil 
     73  1.1  kamil // Initializes unstable counters by copying Inline8bitCounters to unstable
     74  1.1  kamil // counters.
     75  1.1  kamil void TracePC::InitializeUnstableCounters() {
     76  1.1  kamil   IterateInline8bitCounters([&](int i, int j, int UnstableIdx) {
     77  1.1  kamil     UnstableCounters[UnstableIdx].Counter = ModuleCounters[i].Start[j];
     78  1.1  kamil   });
     79  1.1  kamil }
     80  1.1  kamil 
     81  1.1  kamil // Compares the current counters with counters from previous runs
     82  1.1  kamil // and records differences as unstable edges.
     83  1.1  kamil bool TracePC::UpdateUnstableCounters(int UnstableMode) {
     84  1.1  kamil   bool Updated = false;
     85  1.1  kamil   IterateInline8bitCounters([&](int i, int j, int UnstableIdx) {
     86  1.1  kamil     if (ModuleCounters[i].Start[j] != UnstableCounters[UnstableIdx].Counter) {
     87  1.1  kamil       Updated = true;
     88  1.1  kamil       UnstableCounters[UnstableIdx].IsUnstable = true;
     89  1.1  kamil       if (UnstableMode == ZeroUnstable)
     90  1.1  kamil         UnstableCounters[UnstableIdx].Counter = 0;
     91  1.1  kamil       else if (UnstableMode == MinUnstable)
     92  1.1  kamil         UnstableCounters[UnstableIdx].Counter = std::min(
     93  1.1  kamil             ModuleCounters[i].Start[j], UnstableCounters[UnstableIdx].Counter);
     94  1.1  kamil     }
     95  1.1  kamil   });
     96  1.1  kamil   return Updated;
     97  1.1  kamil }
     98  1.1  kamil 
     99  1.1  kamil // Updates and applies unstable counters to ModuleCounters in single iteration
    100  1.1  kamil void TracePC::UpdateAndApplyUnstableCounters(int UnstableMode) {
    101  1.1  kamil   IterateInline8bitCounters([&](int i, int j, int UnstableIdx) {
    102  1.1  kamil     if (ModuleCounters[i].Start[j] != UnstableCounters[UnstableIdx].Counter) {
    103  1.1  kamil       UnstableCounters[UnstableIdx].IsUnstable = true;
    104  1.1  kamil       if (UnstableMode == ZeroUnstable)
    105  1.1  kamil         ModuleCounters[i].Start[j] = 0;
    106  1.1  kamil       else if (UnstableMode == MinUnstable)
    107  1.1  kamil         ModuleCounters[i].Start[j] = std::min(
    108  1.1  kamil             ModuleCounters[i].Start[j], UnstableCounters[UnstableIdx].Counter);
    109  1.1  kamil     }
    110  1.1  kamil   });
    111  1.1  kamil }
    112  1.1  kamil 
    113  1.1  kamil void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop) {
    114  1.1  kamil   if (Start == Stop) return;
    115  1.1  kamil   if (NumModulesWithInline8bitCounters &&
    116  1.1  kamil       ModuleCounters[NumModulesWithInline8bitCounters-1].Start == Start) return;
    117  1.1  kamil   assert(NumModulesWithInline8bitCounters <
    118  1.1  kamil          sizeof(ModuleCounters) / sizeof(ModuleCounters[0]));
    119  1.1  kamil   ModuleCounters[NumModulesWithInline8bitCounters++] = {Start, Stop};
    120  1.1  kamil   NumInline8bitCounters += Stop - Start;
    121  1.1  kamil }
    122  1.1  kamil 
    123  1.1  kamil void TracePC::HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop) {
    124  1.1  kamil   const PCTableEntry *B = reinterpret_cast<const PCTableEntry *>(Start);
    125  1.1  kamil   const PCTableEntry *E = reinterpret_cast<const PCTableEntry *>(Stop);
    126  1.1  kamil   if (NumPCTables && ModulePCTable[NumPCTables - 1].Start == B) return;
    127  1.1  kamil   assert(NumPCTables < sizeof(ModulePCTable) / sizeof(ModulePCTable[0]));
    128  1.1  kamil   ModulePCTable[NumPCTables++] = {B, E};
    129  1.1  kamil   NumPCsInPCTables += E - B;
    130  1.1  kamil }
    131  1.1  kamil 
    132  1.1  kamil void TracePC::HandleInit(uint32_t *Start, uint32_t *Stop) {
    133  1.1  kamil   if (Start == Stop || *Start) return;
    134  1.1  kamil   assert(NumModules < sizeof(Modules) / sizeof(Modules[0]));
    135  1.1  kamil   for (uint32_t *P = Start; P < Stop; P++) {
    136  1.1  kamil     NumGuards++;
    137  1.1  kamil     if (NumGuards == kNumPCs) {
    138  1.1  kamil       RawPrint(
    139  1.1  kamil           "WARNING: The binary has too many instrumented PCs.\n"
    140  1.1  kamil           "         You may want to reduce the size of the binary\n"
    141  1.1  kamil           "         for more efficient fuzzing and precise coverage data\n");
    142  1.1  kamil     }
    143  1.1  kamil     *P = NumGuards % kNumPCs;
    144  1.1  kamil   }
    145  1.1  kamil   Modules[NumModules].Start = Start;
    146  1.1  kamil   Modules[NumModules].Stop = Stop;
    147  1.1  kamil   NumModules++;
    148  1.1  kamil }
    149  1.1  kamil 
    150  1.1  kamil void TracePC::PrintModuleInfo() {
    151  1.1  kamil   if (NumGuards) {
    152  1.1  kamil     Printf("INFO: Loaded %zd modules   (%zd guards): ", NumModules, NumGuards);
    153  1.1  kamil     for (size_t i = 0; i < NumModules; i++)
    154  1.1  kamil       Printf("%zd [%p, %p), ", Modules[i].Stop - Modules[i].Start,
    155  1.1  kamil              Modules[i].Start, Modules[i].Stop);
    156  1.1  kamil     Printf("\n");
    157  1.1  kamil   }
    158  1.1  kamil   if (NumModulesWithInline8bitCounters) {
    159  1.1  kamil     Printf("INFO: Loaded %zd modules   (%zd inline 8-bit counters): ",
    160  1.1  kamil            NumModulesWithInline8bitCounters, NumInline8bitCounters);
    161  1.1  kamil     for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++)
    162  1.1  kamil       Printf("%zd [%p, %p), ", ModuleCounters[i].Stop - ModuleCounters[i].Start,
    163  1.1  kamil              ModuleCounters[i].Start, ModuleCounters[i].Stop);
    164  1.1  kamil     Printf("\n");
    165  1.1  kamil   }
    166  1.1  kamil   if (NumPCTables) {
    167  1.1  kamil     Printf("INFO: Loaded %zd PC tables (%zd PCs): ", NumPCTables,
    168  1.1  kamil            NumPCsInPCTables);
    169  1.1  kamil     for (size_t i = 0; i < NumPCTables; i++) {
    170  1.1  kamil       Printf("%zd [%p,%p), ", ModulePCTable[i].Stop - ModulePCTable[i].Start,
    171  1.1  kamil              ModulePCTable[i].Start, ModulePCTable[i].Stop);
    172  1.1  kamil     }
    173  1.1  kamil     Printf("\n");
    174  1.1  kamil 
    175  1.1  kamil     if ((NumGuards && NumGuards != NumPCsInPCTables) ||
    176  1.1  kamil         (NumInline8bitCounters && NumInline8bitCounters != NumPCsInPCTables)) {
    177  1.1  kamil       Printf("ERROR: The size of coverage PC tables does not match the\n"
    178  1.1  kamil              "number of instrumented PCs. This might be a compiler bug,\n"
    179  1.1  kamil              "please contact the libFuzzer developers.\n"
    180  1.1  kamil              "Also check https://bugs.llvm.org/show_bug.cgi?id=34636\n"
    181  1.1  kamil              "for possible workarounds (tl;dr: don't use the old GNU ld)\n");
    182  1.1  kamil       _Exit(1);
    183  1.1  kamil     }
    184  1.1  kamil   }
    185  1.1  kamil   if (size_t NumExtraCounters = ExtraCountersEnd() - ExtraCountersBegin())
    186  1.1  kamil     Printf("INFO: %zd Extra Counters\n", NumExtraCounters);
    187  1.1  kamil }
    188  1.1  kamil 
    189  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    190  1.1  kamil void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) {
    191  1.1  kamil   const uintptr_t kBits = 12;
    192  1.1  kamil   const uintptr_t kMask = (1 << kBits) - 1;
    193  1.1  kamil   uintptr_t Idx = (Caller & kMask) | ((Callee & kMask) << kBits);
    194  1.1  kamil   ValueProfileMap.AddValueModPrime(Idx);
    195  1.1  kamil }
    196  1.1  kamil 
    197  1.1  kamil /// \return the address of the previous instruction.
    198  1.1  kamil /// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.h`
    199  1.1  kamil inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) {
    200  1.1  kamil #if defined(__arm__)
    201  1.1  kamil   // T32 (Thumb) branch instructions might be 16 or 32 bit long,
    202  1.1  kamil   // so we return (pc-2) in that case in order to be safe.
    203  1.1  kamil   // For A32 mode we return (pc-4) because all instructions are 32 bit long.
    204  1.1  kamil   return (PC - 3) & (~1);
    205  1.1  kamil #elif defined(__powerpc__) || defined(__powerpc64__) || defined(__aarch64__)
    206  1.1  kamil   // PCs are always 4 byte aligned.
    207  1.1  kamil   return PC - 4;
    208  1.1  kamil #elif defined(__sparc__) || defined(__mips__)
    209  1.1  kamil   return PC - 8;
    210  1.1  kamil #else
    211  1.1  kamil   return PC - 1;
    212  1.1  kamil #endif
    213  1.1  kamil }
    214  1.1  kamil 
    215  1.1  kamil /// \return the address of the next instruction.
    216  1.1  kamil /// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.cc`
    217  1.1  kamil inline ALWAYS_INLINE uintptr_t GetNextInstructionPc(uintptr_t PC) {
    218  1.1  kamil #if defined(__mips__)
    219  1.1  kamil   return PC + 8;
    220  1.1  kamil #elif defined(__powerpc__) || defined(__sparc__) || defined(__arm__) || \
    221  1.1  kamil     defined(__aarch64__)
    222  1.1  kamil   return PC + 4;
    223  1.1  kamil #else
    224  1.1  kamil   return PC + 1;
    225  1.1  kamil #endif
    226  1.1  kamil }
    227  1.1  kamil 
    228  1.1  kamil void TracePC::UpdateObservedPCs() {
    229  1.1  kamil   Vector<uintptr_t> CoveredFuncs;
    230  1.1  kamil   auto ObservePC = [&](uintptr_t PC) {
    231  1.1  kamil     if (ObservedPCs.insert(PC).second && DoPrintNewPCs) {
    232  1.1  kamil       PrintPC("\tNEW_PC: %p %F %L", "\tNEW_PC: %p", GetNextInstructionPc(PC));
    233  1.1  kamil       Printf("\n");
    234  1.1  kamil     }
    235  1.1  kamil   };
    236  1.1  kamil 
    237  1.1  kamil   auto Observe = [&](const PCTableEntry &TE) {
    238  1.1  kamil     if (TE.PCFlags & 1)
    239  1.1  kamil       if (++ObservedFuncs[TE.PC] == 1 && NumPrintNewFuncs)
    240  1.1  kamil         CoveredFuncs.push_back(TE.PC);
    241  1.1  kamil     ObservePC(TE.PC);
    242  1.1  kamil   };
    243  1.1  kamil 
    244  1.1  kamil   if (NumPCsInPCTables) {
    245  1.1  kamil     if (NumInline8bitCounters == NumPCsInPCTables) {
    246  1.1  kamil       IterateInline8bitCounters([&](int i, int j, int CounterIdx) {
    247  1.1  kamil         if (ModuleCounters[i].Start[j])
    248  1.1  kamil           Observe(ModulePCTable[i].Start[j]);
    249  1.1  kamil       });
    250  1.1  kamil     } else if (NumGuards == NumPCsInPCTables) {
    251  1.1  kamil       size_t GuardIdx = 1;
    252  1.1  kamil       for (size_t i = 0; i < NumModules; i++) {
    253  1.1  kamil         uint32_t *Beg = Modules[i].Start;
    254  1.1  kamil         size_t Size = Modules[i].Stop - Beg;
    255  1.1  kamil         assert(Size ==
    256  1.1  kamil                (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start));
    257  1.1  kamil         for (size_t j = 0; j < Size; j++, GuardIdx++)
    258  1.1  kamil           if (Counters()[GuardIdx])
    259  1.1  kamil             Observe(ModulePCTable[i].Start[j]);
    260  1.1  kamil       }
    261  1.1  kamil     }
    262  1.1  kamil   }
    263  1.1  kamil 
    264  1.1  kamil   for (size_t i = 0, N = Min(CoveredFuncs.size(), NumPrintNewFuncs); i < N;
    265  1.1  kamil        i++) {
    266  1.1  kamil     Printf("\tNEW_FUNC[%zd/%zd]: ", i + 1, CoveredFuncs.size());
    267  1.1  kamil     PrintPC("%p %F %L", "%p", GetNextInstructionPc(CoveredFuncs[i]));
    268  1.1  kamil     Printf("\n");
    269  1.1  kamil   }
    270  1.1  kamil }
    271  1.1  kamil 
    272  1.1  kamil 
    273  1.1  kamil static std::string GetModuleName(uintptr_t PC) {
    274  1.1  kamil   char ModulePathRaw[4096] = "";  // What's PATH_MAX in portable C++?
    275  1.1  kamil   void *OffsetRaw = nullptr;
    276  1.1  kamil   if (!EF->__sanitizer_get_module_and_offset_for_pc(
    277  1.1  kamil       reinterpret_cast<void *>(PC), ModulePathRaw,
    278  1.1  kamil       sizeof(ModulePathRaw), &OffsetRaw))
    279  1.1  kamil     return "";
    280  1.1  kamil   return ModulePathRaw;
    281  1.1  kamil }
    282  1.1  kamil 
    283  1.1  kamil template<class CallBack>
    284  1.1  kamil void TracePC::IterateCoveredFunctions(CallBack CB) {
    285  1.1  kamil   for (size_t i = 0; i < NumPCTables; i++) {
    286  1.1  kamil     auto &M = ModulePCTable[i];
    287  1.1  kamil     assert(M.Start < M.Stop);
    288  1.1  kamil     auto ModuleName = GetModuleName(M.Start->PC);
    289  1.1  kamil     for (auto NextFE = M.Start; NextFE < M.Stop; ) {
    290  1.1  kamil       auto FE = NextFE;
    291  1.1  kamil       assert((FE->PCFlags & 1) && "Not a function entry point");
    292  1.1  kamil       do {
    293  1.1  kamil         NextFE++;
    294  1.1  kamil       } while (NextFE < M.Stop && !(NextFE->PCFlags & 1));
    295  1.1  kamil       if (ObservedFuncs.count(FE->PC))
    296  1.1  kamil         CB(FE, NextFE, ObservedFuncs[FE->PC]);
    297  1.1  kamil     }
    298  1.1  kamil   }
    299  1.1  kamil }
    300  1.1  kamil 
    301  1.1  kamil void TracePC::SetFocusFunction(const std::string &FuncName) {
    302  1.1  kamil   // This function should be called once.
    303  1.1  kamil   assert(FocusFunction.first > NumModulesWithInline8bitCounters);
    304  1.1  kamil   if (FuncName.empty())
    305  1.1  kamil     return;
    306  1.1  kamil   for (size_t M = 0; M < NumModulesWithInline8bitCounters; M++) {
    307  1.1  kamil     auto &PCTE = ModulePCTable[M];
    308  1.1  kamil     size_t N = PCTE.Stop - PCTE.Start;
    309  1.1  kamil     for (size_t I = 0; I < N; I++) {
    310  1.1  kamil       if (!(PCTE.Start[I].PCFlags & 1)) continue;  // not a function entry.
    311  1.1  kamil       auto Name = DescribePC("%F", GetNextInstructionPc(PCTE.Start[I].PC));
    312  1.1  kamil       if (Name[0] == 'i' && Name[1] == 'n' && Name[2] == ' ')
    313  1.1  kamil         Name = Name.substr(3, std::string::npos);
    314  1.1  kamil       if (FuncName != Name) continue;
    315  1.1  kamil       Printf("INFO: Focus function is set to '%s'\n", Name.c_str());
    316  1.1  kamil       FocusFunction = {M, I};
    317  1.1  kamil       return;
    318  1.1  kamil     }
    319  1.1  kamil   }
    320  1.1  kamil }
    321  1.1  kamil 
    322  1.1  kamil bool TracePC::ObservedFocusFunction() {
    323  1.1  kamil   size_t I = FocusFunction.first;
    324  1.1  kamil   size_t J = FocusFunction.second;
    325  1.1  kamil   if (I >= NumModulesWithInline8bitCounters)
    326  1.1  kamil     return false;
    327  1.1  kamil   auto &MC = ModuleCounters[I];
    328  1.1  kamil   size_t Size = MC.Stop - MC.Start;
    329  1.1  kamil   if (J >= Size)
    330  1.1  kamil     return false;
    331  1.1  kamil   return MC.Start[J] != 0;
    332  1.1  kamil }
    333  1.1  kamil 
    334  1.1  kamil void TracePC::PrintCoverage() {
    335  1.1  kamil   if (!EF->__sanitizer_symbolize_pc ||
    336  1.1  kamil       !EF->__sanitizer_get_module_and_offset_for_pc) {
    337  1.1  kamil     Printf("INFO: __sanitizer_symbolize_pc or "
    338  1.1  kamil            "__sanitizer_get_module_and_offset_for_pc is not available,"
    339  1.1  kamil            " not printing coverage\n");
    340  1.1  kamil     return;
    341  1.1  kamil   }
    342  1.1  kamil   Printf("COVERAGE:\n");
    343  1.1  kamil   auto CoveredFunctionCallback = [&](const PCTableEntry *First,
    344  1.1  kamil                                      const PCTableEntry *Last,
    345  1.1  kamil                                      uintptr_t Counter) {
    346  1.1  kamil     assert(First < Last);
    347  1.1  kamil     auto VisualizePC = GetNextInstructionPc(First->PC);
    348  1.1  kamil     std::string FileStr = DescribePC("%s", VisualizePC);
    349  1.1  kamil     if (!IsInterestingCoverageFile(FileStr))
    350  1.1  kamil       return;
    351  1.1  kamil     std::string FunctionStr = DescribePC("%F", VisualizePC);
    352  1.1  kamil     if (FunctionStr.find("in ") == 0)
    353  1.1  kamil       FunctionStr = FunctionStr.substr(3);
    354  1.1  kamil     std::string LineStr = DescribePC("%l", VisualizePC);
    355  1.1  kamil     size_t Line = std::stoul(LineStr);
    356  1.1  kamil     size_t NumEdges = Last - First;
    357  1.1  kamil     Vector<uintptr_t> UncoveredPCs;
    358  1.1  kamil     for (auto TE = First; TE < Last; TE++)
    359  1.1  kamil       if (!ObservedPCs.count(TE->PC))
    360  1.1  kamil         UncoveredPCs.push_back(TE->PC);
    361  1.1  kamil     Printf("COVERED_FUNC: hits: %zd", Counter);
    362  1.1  kamil     Printf(" edges: %zd/%zd", NumEdges - UncoveredPCs.size(), NumEdges);
    363  1.1  kamil     Printf(" %s %s:%zd\n", FunctionStr.c_str(), FileStr.c_str(), Line);
    364  1.1  kamil     for (auto PC: UncoveredPCs)
    365  1.1  kamil       Printf("  UNCOVERED_PC: %s\n",
    366  1.1  kamil              DescribePC("%s:%l", GetNextInstructionPc(PC)).c_str());
    367  1.1  kamil   };
    368  1.1  kamil 
    369  1.1  kamil   IterateCoveredFunctions(CoveredFunctionCallback);
    370  1.1  kamil }
    371  1.1  kamil 
    372  1.1  kamil void TracePC::DumpCoverage() {
    373  1.1  kamil   if (EF->__sanitizer_dump_coverage) {
    374  1.1  kamil     Vector<uintptr_t> PCsCopy(GetNumPCs());
    375  1.1  kamil     for (size_t i = 0; i < GetNumPCs(); i++)
    376  1.1  kamil       PCsCopy[i] = PCs()[i] ? GetPreviousInstructionPc(PCs()[i]) : 0;
    377  1.1  kamil     EF->__sanitizer_dump_coverage(PCsCopy.data(), PCsCopy.size());
    378  1.1  kamil   }
    379  1.1  kamil }
    380  1.1  kamil 
    381  1.1  kamil void TracePC::PrintUnstableStats() {
    382  1.1  kamil   size_t count = 0;
    383  1.1  kamil   Printf("UNSTABLE_FUNCTIONS:\n");
    384  1.1  kamil   IterateInline8bitCounters([&](int i, int j, int UnstableIdx) {
    385  1.1  kamil     const PCTableEntry &TE = ModulePCTable[i].Start[j];
    386  1.1  kamil     if (UnstableCounters[UnstableIdx].IsUnstable) {
    387  1.1  kamil       count++;
    388  1.1  kamil       if (ObservedFuncs.count(TE.PC)) {
    389  1.1  kamil         auto VisualizePC = GetNextInstructionPc(TE.PC);
    390  1.1  kamil         std::string FunctionStr = DescribePC("%F", VisualizePC);
    391  1.1  kamil         if (FunctionStr.find("in ") == 0)
    392  1.1  kamil           FunctionStr = FunctionStr.substr(3);
    393  1.1  kamil         Printf("%s\n", FunctionStr.c_str());
    394  1.1  kamil       }
    395  1.1  kamil     }
    396  1.1  kamil   });
    397  1.1  kamil 
    398  1.1  kamil   Printf("stat::stability_rate: %.2f\n",
    399  1.1  kamil          100 - static_cast<float>(count * 100) / NumInline8bitCounters);
    400  1.1  kamil }
    401  1.1  kamil 
    402  1.1  kamil // Value profile.
    403  1.1  kamil // We keep track of various values that affect control flow.
    404  1.1  kamil // These values are inserted into a bit-set-based hash map.
    405  1.1  kamil // Every new bit in the map is treated as a new coverage.
    406  1.1  kamil //
    407  1.1  kamil // For memcmp/strcmp/etc the interesting value is the length of the common
    408  1.1  kamil // prefix of the parameters.
    409  1.1  kamil // For cmp instructions the interesting value is a XOR of the parameters.
    410  1.1  kamil // The interesting value is mixed up with the PC and is then added to the map.
    411  1.1  kamil 
    412  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    413  1.1  kamil void TracePC::AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2,
    414  1.1  kamil                                 size_t n, bool StopAtZero) {
    415  1.1  kamil   if (!n) return;
    416  1.1  kamil   size_t Len = std::min(n, Word::GetMaxSize());
    417  1.1  kamil   const uint8_t *A1 = reinterpret_cast<const uint8_t *>(s1);
    418  1.1  kamil   const uint8_t *A2 = reinterpret_cast<const uint8_t *>(s2);
    419  1.1  kamil   uint8_t B1[Word::kMaxSize];
    420  1.1  kamil   uint8_t B2[Word::kMaxSize];
    421  1.1  kamil   // Copy the data into locals in this non-msan-instrumented function
    422  1.1  kamil   // to avoid msan complaining further.
    423  1.1  kamil   size_t Hash = 0;  // Compute some simple hash of both strings.
    424  1.1  kamil   for (size_t i = 0; i < Len; i++) {
    425  1.1  kamil     B1[i] = A1[i];
    426  1.1  kamil     B2[i] = A2[i];
    427  1.1  kamil     size_t T = B1[i];
    428  1.1  kamil     Hash ^= (T << 8) | B2[i];
    429  1.1  kamil   }
    430  1.1  kamil   size_t I = 0;
    431  1.1  kamil   for (; I < Len; I++)
    432  1.1  kamil     if (B1[I] != B2[I] || (StopAtZero && B1[I] == 0))
    433  1.1  kamil       break;
    434  1.1  kamil   size_t PC = reinterpret_cast<size_t>(caller_pc);
    435  1.1  kamil   size_t Idx = (PC & 4095) | (I << 12);
    436  1.1  kamil   ValueProfileMap.AddValue(Idx);
    437  1.1  kamil   TORCW.Insert(Idx ^ Hash, Word(B1, Len), Word(B2, Len));
    438  1.1  kamil }
    439  1.1  kamil 
    440  1.1  kamil template <class T>
    441  1.1  kamil ATTRIBUTE_TARGET_POPCNT ALWAYS_INLINE
    442  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    443  1.1  kamil void TracePC::HandleCmp(uintptr_t PC, T Arg1, T Arg2) {
    444  1.1  kamil   uint64_t ArgXor = Arg1 ^ Arg2;
    445  1.1  kamil   if (sizeof(T) == 4)
    446  1.1  kamil       TORC4.Insert(ArgXor, Arg1, Arg2);
    447  1.1  kamil   else if (sizeof(T) == 8)
    448  1.1  kamil       TORC8.Insert(ArgXor, Arg1, Arg2);
    449  1.1  kamil   uint64_t HammingDistance = __builtin_popcountll(ArgXor); // [0,64]
    450  1.1  kamil   uint64_t AbsoluteDistance =
    451  1.1  kamil       (Arg1 == Arg2 ? 0 : __builtin_clzll(Arg1 - Arg2) + 1);
    452  1.1  kamil   ValueProfileMap.AddValue(PC * 128 + HammingDistance);
    453  1.1  kamil   ValueProfileMap.AddValue(PC * 128 + 64 + AbsoluteDistance);
    454  1.1  kamil }
    455  1.1  kamil 
    456  1.1  kamil static size_t InternalStrnlen(const char *S, size_t MaxLen) {
    457  1.1  kamil   size_t Len = 0;
    458  1.1  kamil   for (; Len < MaxLen && S[Len]; Len++) {}
    459  1.1  kamil   return Len;
    460  1.1  kamil }
    461  1.1  kamil 
    462  1.1  kamil // Finds min of (strlen(S1), strlen(S2)).
    463  1.1  kamil // Needed bacause one of these strings may actually be non-zero terminated.
    464  1.1  kamil static size_t InternalStrnlen2(const char *S1, const char *S2) {
    465  1.1  kamil   size_t Len = 0;
    466  1.1  kamil   for (; S1[Len] && S2[Len]; Len++)  {}
    467  1.1  kamil   return Len;
    468  1.1  kamil }
    469  1.1  kamil 
    470  1.1  kamil void TracePC::ClearInlineCounters() {
    471  1.1  kamil   for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
    472  1.1  kamil     uint8_t *Beg = ModuleCounters[i].Start;
    473  1.1  kamil     size_t Size = ModuleCounters[i].Stop - Beg;
    474  1.1  kamil     memset(Beg, 0, Size);
    475  1.1  kamil   }
    476  1.1  kamil }
    477  1.1  kamil 
    478  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    479  1.1  kamil void TracePC::RecordInitialStack() {
    480  1.1  kamil   int stack;
    481  1.1  kamil   __sancov_lowest_stack = InitialStack = reinterpret_cast<uintptr_t>(&stack);
    482  1.1  kamil }
    483  1.1  kamil 
    484  1.1  kamil uintptr_t TracePC::GetMaxStackOffset() const {
    485  1.1  kamil   return InitialStack - __sancov_lowest_stack;  // Stack grows down
    486  1.1  kamil }
    487  1.1  kamil 
    488  1.1  kamil } // namespace fuzzer
    489  1.1  kamil 
    490  1.1  kamil extern "C" {
    491  1.1  kamil ATTRIBUTE_INTERFACE
    492  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    493  1.1  kamil void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) {
    494  1.1  kamil   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    495  1.1  kamil   uint32_t Idx = *Guard;
    496  1.1  kamil   __sancov_trace_pc_pcs[Idx] = PC;
    497  1.1  kamil   __sancov_trace_pc_guard_8bit_counters[Idx]++;
    498  1.1  kamil }
    499  1.1  kamil 
    500  1.1  kamil // Best-effort support for -fsanitize-coverage=trace-pc, which is available
    501  1.1  kamil // in both Clang and GCC.
    502  1.1  kamil ATTRIBUTE_INTERFACE
    503  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    504  1.1  kamil void __sanitizer_cov_trace_pc() {
    505  1.1  kamil   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    506  1.1  kamil   uintptr_t Idx = PC & (((uintptr_t)1 << fuzzer::TracePC::kTracePcBits) - 1);
    507  1.1  kamil   __sancov_trace_pc_pcs[Idx] = PC;
    508  1.1  kamil   __sancov_trace_pc_guard_8bit_counters[Idx]++;
    509  1.1  kamil }
    510  1.1  kamil 
    511  1.1  kamil ATTRIBUTE_INTERFACE
    512  1.1  kamil void __sanitizer_cov_trace_pc_guard_init(uint32_t *Start, uint32_t *Stop) {
    513  1.1  kamil   fuzzer::TPC.HandleInit(Start, Stop);
    514  1.1  kamil }
    515  1.1  kamil 
    516  1.1  kamil ATTRIBUTE_INTERFACE
    517  1.1  kamil void __sanitizer_cov_8bit_counters_init(uint8_t *Start, uint8_t *Stop) {
    518  1.1  kamil   fuzzer::TPC.HandleInline8bitCountersInit(Start, Stop);
    519  1.1  kamil }
    520  1.1  kamil 
    521  1.1  kamil ATTRIBUTE_INTERFACE
    522  1.1  kamil void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
    523  1.1  kamil                               const uintptr_t *pcs_end) {
    524  1.1  kamil   fuzzer::TPC.HandlePCsInit(pcs_beg, pcs_end);
    525  1.1  kamil }
    526  1.1  kamil 
    527  1.1  kamil ATTRIBUTE_INTERFACE
    528  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    529  1.1  kamil void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) {
    530  1.1  kamil   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    531  1.1  kamil   fuzzer::TPC.HandleCallerCallee(PC, Callee);
    532  1.1  kamil }
    533  1.1  kamil 
    534  1.1  kamil ATTRIBUTE_INTERFACE
    535  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    536  1.1  kamil ATTRIBUTE_TARGET_POPCNT
    537  1.1  kamil void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2) {
    538  1.1  kamil   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    539  1.1  kamil   fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
    540  1.1  kamil }
    541  1.1  kamil 
    542  1.1  kamil ATTRIBUTE_INTERFACE
    543  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    544  1.1  kamil ATTRIBUTE_TARGET_POPCNT
    545  1.1  kamil // Now the __sanitizer_cov_trace_const_cmp[1248] callbacks just mimic
    546  1.1  kamil // the behaviour of __sanitizer_cov_trace_cmp[1248] ones. This, however,
    547  1.1  kamil // should be changed later to make full use of instrumentation.
    548  1.1  kamil void __sanitizer_cov_trace_const_cmp8(uint64_t Arg1, uint64_t Arg2) {
    549  1.1  kamil   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    550  1.1  kamil   fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
    551  1.1  kamil }
    552  1.1  kamil 
    553  1.1  kamil ATTRIBUTE_INTERFACE
    554  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    555  1.1  kamil ATTRIBUTE_TARGET_POPCNT
    556  1.1  kamil void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2) {
    557  1.1  kamil   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    558  1.1  kamil   fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
    559  1.1  kamil }
    560  1.1  kamil 
    561  1.1  kamil ATTRIBUTE_INTERFACE
    562  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    563  1.1  kamil ATTRIBUTE_TARGET_POPCNT
    564  1.1  kamil void __sanitizer_cov_trace_const_cmp4(uint32_t Arg1, uint32_t Arg2) {
    565  1.1  kamil   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    566  1.1  kamil   fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
    567  1.1  kamil }
    568  1.1  kamil 
    569  1.1  kamil ATTRIBUTE_INTERFACE
    570  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    571  1.1  kamil ATTRIBUTE_TARGET_POPCNT
    572  1.1  kamil void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2) {
    573  1.1  kamil   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    574  1.1  kamil   fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
    575  1.1  kamil }
    576  1.1  kamil 
    577  1.1  kamil ATTRIBUTE_INTERFACE
    578  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    579  1.1  kamil ATTRIBUTE_TARGET_POPCNT
    580  1.1  kamil void __sanitizer_cov_trace_const_cmp2(uint16_t Arg1, uint16_t Arg2) {
    581  1.1  kamil   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    582  1.1  kamil   fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
    583  1.1  kamil }
    584  1.1  kamil 
    585  1.1  kamil ATTRIBUTE_INTERFACE
    586  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    587  1.1  kamil ATTRIBUTE_TARGET_POPCNT
    588  1.1  kamil void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2) {
    589  1.1  kamil   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    590  1.1  kamil   fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
    591  1.1  kamil }
    592  1.1  kamil 
    593  1.1  kamil ATTRIBUTE_INTERFACE
    594  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    595  1.1  kamil ATTRIBUTE_TARGET_POPCNT
    596  1.1  kamil void __sanitizer_cov_trace_const_cmp1(uint8_t Arg1, uint8_t Arg2) {
    597  1.1  kamil   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    598  1.1  kamil   fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
    599  1.1  kamil }
    600  1.1  kamil 
    601  1.1  kamil ATTRIBUTE_INTERFACE
    602  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    603  1.1  kamil ATTRIBUTE_TARGET_POPCNT
    604  1.1  kamil void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) {
    605  1.1  kamil   uint64_t N = Cases[0];
    606  1.1  kamil   uint64_t ValSizeInBits = Cases[1];
    607  1.1  kamil   uint64_t *Vals = Cases + 2;
    608  1.1  kamil   // Skip the most common and the most boring case.
    609  1.1  kamil   if (Vals[N - 1]  < 256 && Val < 256)
    610  1.1  kamil     return;
    611  1.1  kamil   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    612  1.1  kamil   size_t i;
    613  1.1  kamil   uint64_t Token = 0;
    614  1.1  kamil   for (i = 0; i < N; i++) {
    615  1.1  kamil     Token = Val ^ Vals[i];
    616  1.1  kamil     if (Val < Vals[i])
    617  1.1  kamil       break;
    618  1.1  kamil   }
    619  1.1  kamil 
    620  1.1  kamil   if (ValSizeInBits == 16)
    621  1.1  kamil     fuzzer::TPC.HandleCmp(PC + i, static_cast<uint16_t>(Token), (uint16_t)(0));
    622  1.1  kamil   else if (ValSizeInBits == 32)
    623  1.1  kamil     fuzzer::TPC.HandleCmp(PC + i, static_cast<uint32_t>(Token), (uint32_t)(0));
    624  1.1  kamil   else
    625  1.1  kamil     fuzzer::TPC.HandleCmp(PC + i, Token, (uint64_t)(0));
    626  1.1  kamil }
    627  1.1  kamil 
    628  1.1  kamil ATTRIBUTE_INTERFACE
    629  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    630  1.1  kamil ATTRIBUTE_TARGET_POPCNT
    631  1.1  kamil void __sanitizer_cov_trace_div4(uint32_t Val) {
    632  1.1  kamil   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    633  1.1  kamil   fuzzer::TPC.HandleCmp(PC, Val, (uint32_t)0);
    634  1.1  kamil }
    635  1.1  kamil 
    636  1.1  kamil ATTRIBUTE_INTERFACE
    637  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    638  1.1  kamil ATTRIBUTE_TARGET_POPCNT
    639  1.1  kamil void __sanitizer_cov_trace_div8(uint64_t Val) {
    640  1.1  kamil   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    641  1.1  kamil   fuzzer::TPC.HandleCmp(PC, Val, (uint64_t)0);
    642  1.1  kamil }
    643  1.1  kamil 
    644  1.1  kamil ATTRIBUTE_INTERFACE
    645  1.1  kamil ATTRIBUTE_NO_SANITIZE_ALL
    646  1.1  kamil ATTRIBUTE_TARGET_POPCNT
    647  1.1  kamil void __sanitizer_cov_trace_gep(uintptr_t Idx) {
    648  1.1  kamil   uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
    649  1.1  kamil   fuzzer::TPC.HandleCmp(PC, Idx, (uintptr_t)0);
    650  1.1  kamil }
    651  1.1  kamil 
    652  1.1  kamil ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
    653  1.1  kamil void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1,
    654  1.1  kamil                                   const void *s2, size_t n, int result) {
    655  1.1  kamil   if (!fuzzer::RunningUserCallback) return;
    656  1.1  kamil   if (result == 0) return;  // No reason to mutate.
    657  1.1  kamil   if (n <= 1) return;  // Not interesting.
    658  1.1  kamil   fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/false);
    659  1.1  kamil }
    660  1.1  kamil 
    661  1.1  kamil ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
    662  1.1  kamil void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1,
    663  1.1  kamil                                    const char *s2, size_t n, int result) {
    664  1.1  kamil   if (!fuzzer::RunningUserCallback) return;
    665  1.1  kamil   if (result == 0) return;  // No reason to mutate.
    666  1.1  kamil   size_t Len1 = fuzzer::InternalStrnlen(s1, n);
    667  1.1  kamil   size_t Len2 = fuzzer::InternalStrnlen(s2, n);
    668  1.1  kamil   n = std::min(n, Len1);
    669  1.1  kamil   n = std::min(n, Len2);
    670  1.1  kamil   if (n <= 1) return;  // Not interesting.
    671  1.1  kamil   fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/true);
    672  1.1  kamil }
    673  1.1  kamil 
    674  1.1  kamil ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
    675  1.1  kamil void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1,
    676  1.1  kamil                                    const char *s2, int result) {
    677  1.1  kamil   if (!fuzzer::RunningUserCallback) return;
    678  1.1  kamil   if (result == 0) return;  // No reason to mutate.
    679  1.1  kamil   size_t N = fuzzer::InternalStrnlen2(s1, s2);
    680  1.1  kamil   if (N <= 1) return;  // Not interesting.
    681  1.1  kamil   fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, N, /*StopAtZero*/true);
    682  1.1  kamil }
    683  1.1  kamil 
    684  1.1  kamil ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
    685  1.1  kamil void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1,
    686  1.1  kamil                                        const char *s2, size_t n, int result) {
    687  1.1  kamil   if (!fuzzer::RunningUserCallback) return;
    688  1.1  kamil   return __sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result);
    689  1.1  kamil }
    690  1.1  kamil 
    691  1.1  kamil ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
    692  1.1  kamil void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1,
    693  1.1  kamil                                       const char *s2, int result) {
    694  1.1  kamil   if (!fuzzer::RunningUserCallback) return;
    695  1.1  kamil   return __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result);
    696  1.1  kamil }
    697  1.1  kamil 
    698  1.1  kamil ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
    699  1.1  kamil void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1,
    700  1.1  kamil                                   const char *s2, char *result) {
    701  1.1  kamil   if (!fuzzer::RunningUserCallback) return;
    702  1.1  kamil   fuzzer::TPC.MMT.Add(reinterpret_cast<const uint8_t *>(s2), strlen(s2));
    703  1.1  kamil }
    704  1.1  kamil 
    705  1.1  kamil ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
    706  1.1  kamil void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1,
    707  1.1  kamil                                       const char *s2, char *result) {
    708  1.1  kamil   if (!fuzzer::RunningUserCallback) return;
    709  1.1  kamil   fuzzer::TPC.MMT.Add(reinterpret_cast<const uint8_t *>(s2), strlen(s2));
    710  1.1  kamil }
    711  1.1  kamil 
    712  1.1  kamil ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
    713  1.1  kamil void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1,
    714  1.1  kamil                                   const void *s2, size_t len2, void *result) {
    715  1.1  kamil   if (!fuzzer::RunningUserCallback) return;
    716  1.1  kamil   fuzzer::TPC.MMT.Add(reinterpret_cast<const uint8_t *>(s2), len2);
    717  1.1  kamil }
    718  1.1  kamil }  // extern "C"
    719