blob: 46c43d0c17f089494f3ebb5fcec73de0f6a10057 [file] [log] [blame]
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +00001//===- 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//
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000013//===----------------------------------------------------------------------===//
14
15#include "FuzzerInternal.h"
16
17namespace fuzzer {
Mike Aizatsky1aa501e2016-05-10 23:43:15 +000018
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;
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000036static thread_local uintptr_t Prev;
37
38void PcMapResetCurrent() {
39 if (Prev) {
40 Prev = 0;
Mike Aizatsky1aa501e2016-05-10 23:43:15 +000041 CurrentMap.Reset();
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000042 }
43}
44
Mike Aizatsky1aa501e2016-05-10 23:43:15 +000045size_t PcMapMergeInto(PcCoverageMap *Map) {
46 if (!Prev)
47 return 0;
48 return Map->MergeFrom(CurrentMap);
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000049}
50
Kostya Serebryany2d4f8f12016-02-27 01:50:16 +000051static void HandlePC(uint32_t PC) {
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000052 // We take 12 bits of PC and mix it with the previous PCs.
Kostya Serebryany2d4f8f12016-02-27 01:50:16 +000053 uintptr_t Next = (Prev << 5) ^ (PC & 4095);
Mike Aizatsky1aa501e2016-05-10 23:43:15 +000054 CurrentMap.Update(Next);
Kostya Serebryany2d4f8f12016-02-27 01:50:16 +000055 Prev = Next;
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000056}
57
58} // namespace fuzzer
59
Dan Liew59144072016-06-06 20:27:09 +000060extern "C" {
61void __sanitizer_cov_trace_pc() {
Kostya Serebryany2d4f8f12016-02-27 01:50:16 +000062 fuzzer::HandlePC(static_cast<uint32_t>(
63 reinterpret_cast<uintptr_t>(__builtin_return_address(0))));
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000064}
Dan Liew59144072016-06-06 20:27:09 +000065
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}