17
17
// and also provides basic-block coverage for every input.
18
18
//
19
19
// Build:
20
- // 1. Compile this file with -fsanitize=dataflow
21
- // 2. Build the fuzz target with -g -fsanitize=dataflow
20
+ // 1. Compile this file (DataFlow.cpp) with -fsanitize=dataflow and -O2.
21
+ // 2. Compile DataFlowCallbacks.cpp with -O2 -fPIC.
22
+ // 3. Build the fuzz target with -g -fsanitize=dataflow
22
23
// -fsanitize-coverage=trace-pc-guard,pc-table,bb,trace-cmp
23
- // 3 . Link those together with -fsanitize=dataflow
24
+ // 4 . Link those together with -fsanitize=dataflow
24
25
//
25
26
// -fsanitize-coverage=trace-cmp inserts callbacks around every comparison
26
27
// instruction, DFSan modifies the calls to pass the data flow labels.
63
64
64
65
#include < execinfo.h> // backtrace_symbols_fd
65
66
66
- #include < sanitizer/dfsan_interface.h >
67
+ #include " DataFlow.h "
67
68
68
69
extern " C" {
69
70
extern int LLVMFuzzerTestOneInput (const unsigned char *Data, size_t Size );
70
71
__attribute__ ((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv);
71
72
} // extern "C"
72
73
74
+ CallbackData __dft;
73
75
static size_t InputLen;
74
76
static size_t NumIterations;
75
- static size_t NumFuncs, NumGuards;
76
- static uint32_t *GuardsBeg, *GuardsEnd;
77
- static const uintptr_t *PCsBeg, *PCsEnd;
78
- static __thread size_t CurrentFunc, CurrentIteration;
79
- static dfsan_label **FuncLabels; // NumFuncs x NumIterations.
80
- static bool *BBExecuted; // Array of NumGuards elements.
81
-
82
- enum {
83
- PCFLAG_FUNC_ENTRY = 1 ,
84
- };
85
-
86
- const int kNumLabels = 16 ;
77
+ static dfsan_label **FuncLabelsPerIter; // NumIterations x NumFuncs;
87
78
88
79
static inline bool BlockIsEntry (size_t BlockIdx) {
89
- return PCsBeg[BlockIdx * 2 + 1 ] & PCFLAG_FUNC_ENTRY;
80
+ return __dft. PCsBeg [BlockIdx * 2 + 1 ] & PCFLAG_FUNC_ENTRY;
90
81
}
91
82
83
+ const int kNumLabels = 16 ;
84
+
92
85
// Prints all instrumented functions.
93
86
static int PrintFunctions () {
94
87
// We don't have the symbolizer integrated with dfsan yet.
@@ -101,8 +94,8 @@ static int PrintFunctions() {
101
94
" | sed 's/dfs\\ $//g' "
102
95
" | c++filt" ,
103
96
" w" );
104
- for (size_t I = 0 ; I < NumGuards; I++) {
105
- uintptr_t PC = PCsBeg[I * 2 ];
97
+ for (size_t I = 0 ; I < __dft. NumGuards ; I++) {
98
+ uintptr_t PC = __dft. PCsBeg [I * 2 ];
106
99
if (!BlockIsEntry (I)) continue ;
107
100
void *const Buf[1 ] = {(void *)PC};
108
101
backtrace_symbols_fd (Buf, 1 , fileno (Pipe));
@@ -121,10 +114,10 @@ static void PrintBinary(FILE *Out, dfsan_label L, size_t Len) {
121
114
}
122
115
123
116
static void PrintDataFlow (FILE *Out) {
124
- for (size_t Func = 0 ; Func < NumFuncs; Func++) {
117
+ for (size_t Func = 0 ; Func < __dft. NumFuncs ; Func++) {
125
118
bool HasAny = false ;
126
119
for (size_t Iter = 0 ; Iter < NumIterations; Iter++)
127
- if (FuncLabels[Func][Iter ])
120
+ if (FuncLabelsPerIter[Iter][Func ])
128
121
HasAny = true ;
129
122
if (!HasAny)
130
123
continue ;
@@ -133,7 +126,7 @@ static void PrintDataFlow(FILE *Out) {
133
126
if (auto Tail = InputLen % kNumLabels )
134
127
LenOfLastIteration = Tail;
135
128
for (size_t Iter = 0 ; Iter < NumIterations; Iter++)
136
- PrintBinary (Out, FuncLabels[Func][Iter ],
129
+ PrintBinary (Out, FuncLabelsPerIter[Iter][Func ],
137
130
Iter == NumIterations - 1 ? LenOfLastIteration : kNumLabels );
138
131
fprintf (Out, " \n " );
139
132
}
@@ -143,16 +136,16 @@ static void PrintCoverage(FILE *Out) {
143
136
ssize_t CurrentFuncGuard = -1 ;
144
137
ssize_t CurrentFuncNum = -1 ;
145
138
ssize_t NumBlocksInCurrentFunc = -1 ;
146
- for (size_t FuncBeg = 0 ; FuncBeg < NumGuards;) {
139
+ for (size_t FuncBeg = 0 ; FuncBeg < __dft. NumGuards ;) {
147
140
CurrentFuncNum++;
148
141
assert (BlockIsEntry (FuncBeg));
149
142
size_t FuncEnd = FuncBeg + 1 ;
150
- for (; FuncEnd < NumGuards && !BlockIsEntry (FuncEnd); FuncEnd++)
143
+ for (; FuncEnd < __dft. NumGuards && !BlockIsEntry (FuncEnd); FuncEnd++)
151
144
;
152
- if (BBExecuted[FuncBeg]) {
145
+ if (__dft. BBExecuted [FuncBeg]) {
153
146
fprintf (Out, " C%zd" , CurrentFuncNum);
154
147
for (size_t I = FuncBeg + 1 ; I < FuncEnd; I++)
155
- if (BBExecuted[I])
148
+ if (__dft. BBExecuted [I])
156
149
fprintf (Out, " %zd" , I - FuncBeg);
157
150
fprintf (Out, " %zd\n " , FuncEnd - FuncBeg);
158
151
}
@@ -180,19 +173,19 @@ int main(int argc, char **argv) {
180
173
fclose (In);
181
174
182
175
NumIterations = (NumBytesRead + kNumLabels - 1 ) / kNumLabels ;
183
- FuncLabels = (dfsan_label**)calloc (NumFuncs, sizeof (dfsan_label*));
184
- for (size_t Func = 0 ; Func < NumFuncs; Func++)
185
- FuncLabels[Func] =
186
- (dfsan_label *)calloc (NumIterations, sizeof (dfsan_label));
187
-
188
- for (CurrentIteration = 0 ; CurrentIteration < NumIterations;
189
- CurrentIteration++) {
190
- fprintf (stderr, " INFO: running '%s' %zd/%zd\n " , Input, CurrentIteration,
191
- NumIterations);
176
+ FuncLabelsPerIter =
177
+ (dfsan_label **)calloc (NumIterations, sizeof (dfsan_label *));
178
+ for (size_t Iter = 0 ; Iter < NumIterations; Iter++)
179
+ FuncLabelsPerIter[Iter] =
180
+ (dfsan_label *)calloc (__dft.NumFuncs , sizeof (dfsan_label));
181
+
182
+ for (size_t Iter = 0 ; Iter < NumIterations; Iter++) {
183
+ fprintf (stderr, " INFO: running '%s' %zd/%zd\n " , Input, Iter, NumIterations);
192
184
dfsan_flush ();
193
185
dfsan_set_label (0 , Buf, InputLen);
186
+ __dft.FuncLabels = FuncLabelsPerIter[Iter];
194
187
195
- size_t BaseIdx = CurrentIteration * kNumLabels ;
188
+ size_t BaseIdx = Iter * kNumLabels ;
196
189
size_t LastIdx = BaseIdx + kNumLabels < NumBytesRead ? BaseIdx + kNumLabels
197
190
: NumBytesRead;
198
191
assert (BaseIdx < LastIdx);
@@ -210,67 +203,3 @@ int main(int argc, char **argv) {
210
203
PrintCoverage (Out);
211
204
if (!OutIsStdout) fclose (Out);
212
205
}
213
-
214
- extern " C" {
215
-
216
- void __sanitizer_cov_trace_pc_guard_init (uint32_t *start,
217
- uint32_t *stop) {
218
- assert (NumFuncs == 0 && " This tool does not support DSOs" );
219
- assert (start < stop && " The code is not instrumented for coverage" );
220
- if (start == stop || *start) return ; // Initialize only once.
221
- GuardsBeg = start;
222
- GuardsEnd = stop;
223
- }
224
-
225
- void __sanitizer_cov_pcs_init (const uintptr_t *pcs_beg,
226
- const uintptr_t *pcs_end) {
227
- if (NumGuards) return ; // Initialize only once.
228
- NumGuards = GuardsEnd - GuardsBeg;
229
- PCsBeg = pcs_beg;
230
- PCsEnd = pcs_end;
231
- assert (NumGuards == (PCsEnd - PCsBeg) / 2 );
232
- for (size_t i = 0 ; i < NumGuards; i++) {
233
- if (BlockIsEntry (i)) {
234
- NumFuncs++;
235
- GuardsBeg[i] = NumFuncs;
236
- }
237
- }
238
- BBExecuted = (bool *)calloc (NumGuards, sizeof (bool ));
239
- fprintf (stderr, " INFO: %zd instrumented function(s) observed "
240
- " and %zd basic blocks\n " , NumFuncs, NumGuards);
241
- }
242
-
243
- void __sanitizer_cov_trace_pc_indir (uint64_t x){} // unused.
244
-
245
- void __sanitizer_cov_trace_pc_guard (uint32_t *guard) {
246
- size_t GuardIdx = guard - GuardsBeg;
247
- assert (GuardIdx < NumGuards);
248
- BBExecuted[GuardIdx] = true ;
249
- if (!*guard) return ; // not a function entry.
250
- uint32_t FuncNum = *guard - 1 ; // Guards start from 1.
251
- assert (FuncNum < NumFuncs);
252
- CurrentFunc = FuncNum;
253
- }
254
-
255
- void __dfsw___sanitizer_cov_trace_switch (uint64_t Val, uint64_t *Cases,
256
- dfsan_label L1, dfsan_label UnusedL) {
257
- assert (CurrentFunc < NumFuncs);
258
- FuncLabels[CurrentFunc][CurrentIteration] |= L1;
259
- }
260
-
261
- #define HOOK (Name, Type ) \
262
- void Name (Type Arg1, Type Arg2, dfsan_label L1, dfsan_label L2) { \
263
- assert (CurrentFunc < NumFuncs); \
264
- FuncLabels[CurrentFunc][CurrentIteration] |= L1 | L2; \
265
- }
266
-
267
- HOOK (__dfsw___sanitizer_cov_trace_const_cmp1, uint8_t )
268
- HOOK(__dfsw___sanitizer_cov_trace_const_cmp2, uint16_t )
269
- HOOK(__dfsw___sanitizer_cov_trace_const_cmp4, uint32_t )
270
- HOOK(__dfsw___sanitizer_cov_trace_const_cmp8, uint64_t )
271
- HOOK(__dfsw___sanitizer_cov_trace_cmp1, uint8_t )
272
- HOOK(__dfsw___sanitizer_cov_trace_cmp2, uint16_t )
273
- HOOK(__dfsw___sanitizer_cov_trace_cmp4, uint32_t )
274
- HOOK(__dfsw___sanitizer_cov_trace_cmp8, uint64_t )
275
-
276
- } // extern "C"
0 commit comments