OLD | NEW |
1 /* | 1 /* |
2 american fuzzy lop - LLVM instrumentation bootstrap | 2 american fuzzy lop - LLVM instrumentation bootstrap |
3 --------------------------------------------------- | 3 --------------------------------------------------- |
4 | 4 |
5 Written by Laszlo Szekeres <lszekeres@google.com> and | 5 Written by Laszlo Szekeres <lszekeres@google.com> and |
6 Michal Zalewski <lcamtuf@google.com> | 6 Michal Zalewski <lcamtuf@google.com> |
7 | 7 |
8 LLVM integration design comes from Laszlo Szekeres. | 8 LLVM integration design comes from Laszlo Szekeres. |
9 | 9 |
10 Copyright 2015, 2016 Google Inc. All rights reserved. | 10 Copyright 2015, 2016 Google Inc. All rights reserved. |
(...skipping 16 matching lines...) Expand all Loading... |
27 #include <signal.h> | 27 #include <signal.h> |
28 #include <unistd.h> | 28 #include <unistd.h> |
29 #include <string.h> | 29 #include <string.h> |
30 #include <assert.h> | 30 #include <assert.h> |
31 | 31 |
32 #include <sys/mman.h> | 32 #include <sys/mman.h> |
33 #include <sys/shm.h> | 33 #include <sys/shm.h> |
34 #include <sys/wait.h> | 34 #include <sys/wait.h> |
35 #include <sys/types.h> | 35 #include <sys/types.h> |
36 | 36 |
| 37 /* This is a somewhat ugly hack for the experimental 'trace-pc-guard' mode. |
| 38 Basically, we need to make sure that the forkserver is initialized after |
| 39 the LLVM-generated runtime initialization pass, not before. */ |
| 40 |
| 41 #ifdef USE_TRACE_PC |
| 42 # define CONST_PRIO 5 |
| 43 #else |
| 44 # define CONST_PRIO 0 |
| 45 #endif /* ^USE_TRACE_PC */ |
| 46 |
37 | 47 |
38 /* Globals needed by the injected instrumentation. The __afl_area_initial region | 48 /* Globals needed by the injected instrumentation. The __afl_area_initial region |
39 is used for instrumentation output before __afl_map_shm() has a chance to run
. | 49 is used for instrumentation output before __afl_map_shm() has a chance to run
. |
40 It will end up as .comm, so it shouldn't be too wasteful. */ | 50 It will end up as .comm, so it shouldn't be too wasteful. */ |
41 | 51 |
42 u8 __afl_area_initial[MAP_SIZE]; | 52 u8 __afl_area_initial[MAP_SIZE]; |
43 u8* __afl_area_ptr = __afl_area_initial; | 53 u8* __afl_area_ptr = __afl_area_initial; |
44 | 54 |
45 __thread u32 __afl_prev_loc; | 55 __thread u32 __afl_prev_loc; |
46 | 56 |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 | 237 |
228 __afl_map_shm(); | 238 __afl_map_shm(); |
229 __afl_start_forkserver(); | 239 __afl_start_forkserver(); |
230 init_done = 1; | 240 init_done = 1; |
231 | 241 |
232 } | 242 } |
233 | 243 |
234 } | 244 } |
235 | 245 |
236 | 246 |
237 static void __afl_trace_pc_init(void); | |
238 | |
239 | |
240 /* Proper initialization routine. */ | 247 /* Proper initialization routine. */ |
241 | 248 |
242 __attribute__((constructor(0))) void __afl_auto_init(void) { | 249 __attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) { |
243 | 250 |
244 is_persistent = !!getenv(PERSIST_ENV_VAR); | 251 is_persistent = !!getenv(PERSIST_ENV_VAR); |
245 | 252 |
246 __afl_trace_pc_init(); | |
247 | |
248 if (getenv(DEFER_ENV_VAR)) return; | 253 if (getenv(DEFER_ENV_VAR)) return; |
249 | 254 |
250 __afl_manual_init(); | 255 __afl_manual_init(); |
251 | 256 |
252 } | 257 } |
253 | 258 |
254 | 259 |
255 /* The following stuff deals with support for -fsanitize-coverage=bb,trace-pc. | 260 /* The following stuff deals with supporting -fsanitize-coverage=trace-pc-guard. |
256 It remains non-operational in the traditional, plugin-backed LLVM mode. | 261 It remains non-operational in the traditional, plugin-backed LLVM mode. |
257 For more info about 'trace-pc', see README.llvm. | 262 For more info about 'trace-pc-guard', see README.llvm. |
258 | 263 |
259 The first function (__sanitizer_cov_trace_pc) is called back on every | 264 The first function (__sanitizer_cov_trace_pc_guard) is called back on every |
260 basic block. Since LLVM is not giving us any stable IDs for the blocks, | 265 edge (as opposed to every basic block). */ |
261 we use 12 least significant bits of the return address (which should be | |
262 stable even with ASLR; more significant bits may vary across runs). | |
263 | 266 |
264 Since MAP_SIZE is usually larger than 12 bits, we "pad" it by combining | 267 void __sanitizer_cov_trace_pc_guard(uint32_t* guard) { |
265 left-shifted __afl_prev_loc. This gives us a theoretical maximum of 24 | 268 __afl_area_ptr[*guard]++; |
266 bits, although instruction alignment likely reduces this somewhat. */ | |
267 | |
268 | |
269 static u32 inst_ratio_scaled = MIN(4096, MAP_SIZE); | |
270 | |
271 void __sanitizer_cov_trace_pc(void) { | |
272 | |
273 u32 cur = ((u32)__builtin_return_address(0)) & MIN(4095, MAP_SIZE - 1); | |
274 | |
275 if (cur > inst_ratio_scaled) return; | |
276 | |
277 __afl_area_ptr[cur ^ __afl_prev_loc]++; | |
278 | |
279 #if MAP_SIZE_POW2 > 12 | |
280 __afl_prev_loc = cur << (MAP_SIZE_POW2 - 12); | |
281 #else | |
282 __afl_prev_loc = cur >> 1; | |
283 #endif /* ^MAP_SIZE_POW2 > 12 */ | |
284 | |
285 } | 269 } |
286 | 270 |
287 | 271 |
288 /* Init callback. Unfortunately, LLVM does not support compile-time | 272 /* Init callback. Populates instrumentation IDs. Note that we're using |
289 instrumentation density scaling, at least not just yet. This means | 273 ID of 0 as a special value to indicate non-instrumented bits. That may |
290 taking some performance hit by checking inst_ratio_scaled at runtime. */ | 274 still touch the bitmap, but in a fairly harmless way. */ |
291 | 275 |
292 static void __afl_trace_pc_init(void) { | 276 void __sanitizer_cov_trace_pc_guard_init(uint32_t* start, uint32_t* stop) { |
293 | 277 |
294 u8* x = getenv("AFL_INST_RATIO"); | 278 u32 inst_ratio = 100; |
| 279 u8* x; |
295 | 280 |
296 if (!x) return; | 281 x = getenv("AFL_INST_RATIO"); |
| 282 if (x) inst_ratio = atoi(x); |
297 | 283 |
298 inst_ratio_scaled = atoi(x); | 284 if (!inst_ratio || inst_ratio > 100) { |
299 | |
300 if (!inst_ratio_scaled || inst_ratio_scaled > 100) { | |
301 fprintf(stderr, "[-] ERROR: Invalid AFL_INST_RATIO (must be 1-100).\n"); | 285 fprintf(stderr, "[-] ERROR: Invalid AFL_INST_RATIO (must be 1-100).\n"); |
302 abort(); | 286 abort(); |
303 } | 287 } |
304 | 288 |
305 inst_ratio_scaled = inst_ratio_scaled * MIN(4096, MAP_SIZE) / 100; | 289 while (start < stop) { |
| 290 |
| 291 if (R(100) < inst_ratio) *start = R(MAP_SIZE - 1) + 1; |
| 292 else *start = 0; |
| 293 |
| 294 start++; |
| 295 |
| 296 } |
306 | 297 |
307 } | 298 } |
308 | |
309 | |
310 /* Work around a short-lived bug in LLVM with -fsanitize-coverage=trace-pc. */ | |
311 | |
312 void __sanitizer_cov_module_init(void) __attribute__((weak)); | |
313 void __sanitizer_cov_module_init(void) { } | |
314 | |
OLD | NEW |