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 17namespace fuzzer { 18 19void PcCoverageMap::Reset() { memset(Map, 0, sizeof(Map)); } 20 21void 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 28size_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 35static PcCoverageMap CurrentMap; 36static thread_local uintptr_t Prev; 37 38void PcMapResetCurrent() { 39 if (Prev) { 40 Prev = 0; 41 CurrentMap.Reset(); 42 } 43} 44 45size_t PcMapMergeInto(PcCoverageMap *Map) { 46 if (!Prev) 47 return 0; 48 return Map->MergeFrom(CurrentMap); 49} 50 51static 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 60extern "C" { 61void __sanitizer_cov_trace_pc() { 62 fuzzer::HandlePC(static_cast<uint32_t>( 63 reinterpret_cast<uintptr_t>(__builtin_return_address(0)))); 64} 65 66void __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