| 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 |