xref: /llvm-project/compiler-rt/lib/fuzzer/dataflow/DataFlowCallbacks.cpp (revision 679669a77e5bbd7451f4c482ec1996b0649f65d0)
1*679669a7SKostya Serebryany /*===- DataFlowCallbacks.cpp - a standalone DataFlow trace          -------===//
2*679669a7SKostya Serebryany //
3*679669a7SKostya Serebryany // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*679669a7SKostya Serebryany // See https://llvm.org/LICENSE.txt for license information.
5*679669a7SKostya Serebryany // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*679669a7SKostya Serebryany //
7*679669a7SKostya Serebryany //===----------------------------------------------------------------------===//
8*679669a7SKostya Serebryany // Instrumentation callbacks for DataFlow.cpp.
9*679669a7SKostya Serebryany // These functions should not be instrumented by DFSan, so we
10*679669a7SKostya Serebryany // keep them in a separate file and compile it w/o DFSan.
11*679669a7SKostya Serebryany //===----------------------------------------------------------------------===*/
12*679669a7SKostya Serebryany #include "DataFlow.h"
13*679669a7SKostya Serebryany 
14*679669a7SKostya Serebryany #include <cassert>
15*679669a7SKostya Serebryany #include <cstdio>
16*679669a7SKostya Serebryany #include <cstdlib>
17*679669a7SKostya Serebryany 
18*679669a7SKostya Serebryany static __thread size_t CurrentFunc;
19*679669a7SKostya Serebryany static uint32_t *GuardsBeg, *GuardsEnd;
BlockIsEntry(size_t BlockIdx)20*679669a7SKostya Serebryany static inline bool BlockIsEntry(size_t BlockIdx) {
21*679669a7SKostya Serebryany   return __dft.PCsBeg[BlockIdx * 2 + 1] & PCFLAG_FUNC_ENTRY;
22*679669a7SKostya Serebryany }
23*679669a7SKostya Serebryany 
24*679669a7SKostya Serebryany extern "C" {
25*679669a7SKostya Serebryany 
__sanitizer_cov_trace_pc_guard_init(uint32_t * start,uint32_t * stop)26*679669a7SKostya Serebryany void __sanitizer_cov_trace_pc_guard_init(uint32_t *start,
27*679669a7SKostya Serebryany                                          uint32_t *stop) {
28*679669a7SKostya Serebryany   assert(__dft.NumFuncs == 0 && "This tool does not support DSOs");
29*679669a7SKostya Serebryany   assert(start < stop && "The code is not instrumented for coverage");
30*679669a7SKostya Serebryany   if (start == stop || *start) return;  // Initialize only once.
31*679669a7SKostya Serebryany   GuardsBeg = start;
32*679669a7SKostya Serebryany   GuardsEnd = stop;
33*679669a7SKostya Serebryany }
34*679669a7SKostya Serebryany 
__sanitizer_cov_pcs_init(const uintptr_t * pcs_beg,const uintptr_t * pcs_end)35*679669a7SKostya Serebryany void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
36*679669a7SKostya Serebryany                               const uintptr_t *pcs_end) {
37*679669a7SKostya Serebryany   if (__dft.NumGuards) return;  // Initialize only once.
38*679669a7SKostya Serebryany   __dft.NumGuards = GuardsEnd - GuardsBeg;
39*679669a7SKostya Serebryany   __dft.PCsBeg = pcs_beg;
40*679669a7SKostya Serebryany   __dft.PCsEnd = pcs_end;
41*679669a7SKostya Serebryany   assert(__dft.NumGuards == (__dft.PCsEnd - __dft.PCsBeg) / 2);
42*679669a7SKostya Serebryany   for (size_t i = 0; i < __dft.NumGuards; i++) {
43*679669a7SKostya Serebryany     if (BlockIsEntry(i)) {
44*679669a7SKostya Serebryany       __dft.NumFuncs++;
45*679669a7SKostya Serebryany       GuardsBeg[i] = __dft.NumFuncs;
46*679669a7SKostya Serebryany     }
47*679669a7SKostya Serebryany   }
48*679669a7SKostya Serebryany   __dft.BBExecuted = (bool*)calloc(__dft.NumGuards, sizeof(bool));
49*679669a7SKostya Serebryany   fprintf(stderr, "INFO: %zd instrumented function(s) observed "
50*679669a7SKostya Serebryany           "and %zd basic blocks\n", __dft.NumFuncs, __dft.NumGuards);
51*679669a7SKostya Serebryany }
52*679669a7SKostya Serebryany 
__sanitizer_cov_trace_pc_indir(uint64_t x)53*679669a7SKostya Serebryany void __sanitizer_cov_trace_pc_indir(uint64_t x){}  // unused.
54*679669a7SKostya Serebryany 
__sanitizer_cov_trace_pc_guard(uint32_t * guard)55*679669a7SKostya Serebryany void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
56*679669a7SKostya Serebryany   size_t GuardIdx = guard - GuardsBeg;
57*679669a7SKostya Serebryany   // assert(GuardIdx < __dft.NumGuards);
58*679669a7SKostya Serebryany   __dft.BBExecuted[GuardIdx] = true;
59*679669a7SKostya Serebryany   if (!*guard) return;  // not a function entry.
60*679669a7SKostya Serebryany   uint32_t FuncNum = *guard - 1;  // Guards start from 1.
61*679669a7SKostya Serebryany   // assert(FuncNum < __dft.NumFuncs);
62*679669a7SKostya Serebryany   CurrentFunc = FuncNum;
63*679669a7SKostya Serebryany }
64*679669a7SKostya Serebryany 
__dfsw___sanitizer_cov_trace_switch(uint64_t Val,uint64_t * Cases,dfsan_label L1,dfsan_label UnusedL)65*679669a7SKostya Serebryany void __dfsw___sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases,
66*679669a7SKostya Serebryany                                          dfsan_label L1, dfsan_label UnusedL) {
67*679669a7SKostya Serebryany   assert(CurrentFunc < __dft.NumFuncs);
68*679669a7SKostya Serebryany   __dft.FuncLabels[CurrentFunc] |= L1;
69*679669a7SKostya Serebryany }
70*679669a7SKostya Serebryany 
71*679669a7SKostya Serebryany #define HOOK(Name, Type)                                                       \
72*679669a7SKostya Serebryany   void Name(Type Arg1, Type Arg2, dfsan_label L1, dfsan_label L2) {            \
73*679669a7SKostya Serebryany     __dft.FuncLabels[CurrentFunc] |= L1 | L2;                                  \
74*679669a7SKostya Serebryany   }
75*679669a7SKostya Serebryany     //assert(CurrentFunc < __dft.NumFuncs);
76*679669a7SKostya Serebryany 
77*679669a7SKostya Serebryany HOOK(__dfsw___sanitizer_cov_trace_const_cmp1, uint8_t)
78*679669a7SKostya Serebryany HOOK(__dfsw___sanitizer_cov_trace_const_cmp2, uint16_t)
79*679669a7SKostya Serebryany HOOK(__dfsw___sanitizer_cov_trace_const_cmp4, uint32_t)
80*679669a7SKostya Serebryany HOOK(__dfsw___sanitizer_cov_trace_const_cmp8, uint64_t)
81*679669a7SKostya Serebryany HOOK(__dfsw___sanitizer_cov_trace_cmp1, uint8_t)
82*679669a7SKostya Serebryany HOOK(__dfsw___sanitizer_cov_trace_cmp2, uint16_t)
83*679669a7SKostya Serebryany HOOK(__dfsw___sanitizer_cov_trace_cmp4, uint32_t)
84*679669a7SKostya Serebryany HOOK(__dfsw___sanitizer_cov_trace_cmp8, uint64_t)
85*679669a7SKostya Serebryany 
86*679669a7SKostya Serebryany } // extern "C"
87