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 //===----------------------------------------------------------------------===// 14 15 #include "FuzzerInternal.h" 16 17 namespace fuzzer { 18 19 void PcCoverageMap::Reset() { memset(Map, 0, sizeof(Map)); } 20 21 void PcCoverageMap::Update(uintptr_t Addr) { 22 uintptr_t Idx = Addr % kMapSizeInBits; 23 uintptr_t WordIdx = Idx / kBitsInWord; 24 uintptr_t BitIdx = Idx % kBitsInWord; 25 Map[WordIdx] |= 1UL << BitIdx; 26 } 27 28 size_t PcCoverageMap::MergeFrom(const PcCoverageMap &Other) { 29 uintptr_t Res = 0; 30 for (size_t i = 0; i < kMapSizeInWords; i++) 31 Res += __builtin_popcountl(Map[i] |= Other.Map[i]); 32 return Res; 33 } 34 35 static PcCoverageMap CurrentMap; 36 static thread_local uintptr_t Prev; 37 38 void PcMapResetCurrent() { 39 if (Prev) { 40 Prev = 0; 41 CurrentMap.Reset(); 42 } 43 } 44 45 size_t PcMapMergeInto(PcCoverageMap *Map) { 46 if (!Prev) 47 return 0; 48 return Map->MergeFrom(CurrentMap); 49 } 50 51 static void HandlePC(uint32_t PC) { 52 // We take 12 bits of PC and mix it with the previous PCs. 53 uintptr_t Next = (Prev << 5) ^ (PC & 4095); 54 CurrentMap.Update(Next); 55 Prev = Next; 56 } 57 58 } // namespace fuzzer 59 60 extern "C" { 61 void __sanitizer_cov_trace_pc() { 62 fuzzer::HandlePC(static_cast<uint32_t>( 63 reinterpret_cast<uintptr_t>(__builtin_return_address(0)))); 64 } 65 66 void __sanitizer_cov_trace_pc_indir(int *) { 67 // Stub to allow linking with code built with 68 // -fsanitize=indirect-calls,trace-pc. 69 // This isn't used currently. 70 } 71 } 72