Kostya Serebryany | da63c1d | 2016-02-26 21:33:56 +0000 | [diff] [blame^] | 1 | //===- FuzzerTracePC.cpp - PC tracing--------------------------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // Trace PCs. |
| 10 | // This module implements __sanitizer_cov_trace_pc, a callback required |
| 11 | // for -fsanitize-coverage=trace-pc instrumentation. |
| 12 | // |
| 13 | // Experimental and not yet tuned for performance. |
| 14 | //===----------------------------------------------------------------------===// |
| 15 | |
| 16 | #include "FuzzerInternal.h" |
| 17 | |
| 18 | namespace fuzzer { |
| 19 | static const size_t kMapSize = 65371; // Prime. |
| 20 | static uint8_t CurMap[kMapSize]; |
| 21 | static uint8_t CombinedMap[kMapSize]; |
| 22 | static size_t CombinedMapSize; |
| 23 | static thread_local uintptr_t Prev; |
| 24 | |
| 25 | void PcMapResetCurrent() { |
| 26 | if (Prev) { |
| 27 | Prev = 0; |
| 28 | memset(CurMap, 0, sizeof(CurMap)); |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | // TODO: speed this up. |
| 33 | void PcMapMergeCurrentToCombined() { |
| 34 | if (!Prev) return; |
| 35 | uintptr_t Res = 0; |
| 36 | for (size_t i = 0; i < kMapSize; i++) { |
| 37 | uint8_t p = (CombinedMap[i] |= CurMap[i]); |
| 38 | CurMap[i] = 0; |
| 39 | Res += p != 0; |
| 40 | } |
| 41 | CombinedMapSize = Res; |
| 42 | } |
| 43 | |
| 44 | size_t PcMapCombinedSize() { return CombinedMapSize; } |
| 45 | |
| 46 | static void HandlePC(uintptr_t PC) { |
| 47 | // We take 12 bits of PC and mix it with the previous PCs. |
| 48 | uintptr_t Idx = (Prev << 5) ^ (PC & 4095); |
| 49 | CurMap[Idx % kMapSize] = 1; |
| 50 | Prev = Idx; |
| 51 | } |
| 52 | |
| 53 | } // namespace fuzzer |
| 54 | |
| 55 | extern "C" void __sanitizer_cov_trace_pc() { |
| 56 | fuzzer::HandlePC(reinterpret_cast<uintptr_t>(__builtin_return_address(0))); |
| 57 | } |
| 58 | //uintptr_t __sanitizer_get_total_unique_coverage() { return 0; } |
| 59 | //uintptr_t __sanitizer_get_number_of_counters() { return 0; } |