Home | History | Annotate | Download | only in Fuzzer
      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