blob: 8fa9257c23b2c0f1859384e10beaa6fb77eaa833 [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.
Kostya Serebryanya00b2432016-09-14 02:13:06 +000010// This module implements __sanitizer_cov_trace_pc_guard[_init],
11// the callback required for -fsanitize-coverage=trace-pc-guard instrumentation.
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000012//
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000013//===----------------------------------------------------------------------===//
14
15#include "FuzzerInternal.h"
16
17namespace fuzzer {
Mike Aizatsky1aa501e2016-05-10 23:43:15 +000018
Kostya Serebryanya00b2432016-09-14 02:13:06 +000019TracePC TPC;
Mike Aizatsky1aa501e2016-05-10 23:43:15 +000020
Kostya Serebryany3e36ec12016-09-17 05:04:47 +000021void TracePC::HandleTrace(uint64_t *Guard, uintptr_t PC) {
22 const uint64_t kBit63 = 1ULL << 63;
23 uint64_t Value = *Guard;
24 if (Value & kBit63) return;
25 // Printf(" >> %16zx %p\n", Value, Guard);
Kostya Serebryanya5277d52016-09-15 01:30:18 +000026 if (UseCounters) {
Kostya Serebryany3e36ec12016-09-17 05:04:47 +000027 uint64_t Counter = Value & 0xff;
28 if (Counter == 0) {
29 size_t Idx = Value >> 32;
Kostya Serebryany53501782016-09-15 04:36:45 +000030 if (TotalCoverageMap.AddValue(Idx)) {
31 TotalCoverage++;
32 AddNewPC(PC);
33 }
34 }
Kostya Serebryany3e36ec12016-09-17 05:04:47 +000035 if (Counter < 255)
36 Value++;
Kostya Serebryanya5277d52016-09-15 01:30:18 +000037 } else {
Kostya Serebryany3e36ec12016-09-17 05:04:47 +000038 Value |= kBit63;
Kostya Serebryanya5277d52016-09-15 01:30:18 +000039 TotalCoverage++;
Kostya Serebryany53501782016-09-15 04:36:45 +000040 AddNewPC(PC);
Kostya Serebryanya5277d52016-09-15 01:30:18 +000041 }
Kostya Serebryany3e36ec12016-09-17 05:04:47 +000042 // Printf(" << %16zx\n", Value);
43 *Guard = Value;
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000044}
Kostya Serebryanya5277d52016-09-15 01:30:18 +000045
Kostya Serebryany3e36ec12016-09-17 05:04:47 +000046void TracePC::HandleInit(uint64_t *Start, uint64_t *Stop) {
47 if (Start == Stop || *Start) return;
48 assert(NumModules < sizeof(Modules) / sizeof(Modules[0]));
49 for (uint64_t *P = Start; P < Stop; P++)
50 *P = (++NumGuards) << 32;
51 Modules[NumModules].Start = Start;
52 Modules[NumModules].Stop = Stop;
53 NumModules++;
54}
55
56void TracePC::PrintModuleInfo() {
57 Printf("INFO: Loaded %zd modules (%zd guards): ", NumModules, NumGuards);
58 for (size_t i = 0; i < NumModules; i++)
59 Printf("[%p, %p), ", Modules[i].Start, Modules[i].Stop);
60 Printf("\n");
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000061}
Kostya Serebryanya5277d52016-09-15 01:30:18 +000062
63void TracePC::FinalizeTrace() {
64 if (UseCounters && TotalCoverage) {
Kostya Serebryany3e36ec12016-09-17 05:04:47 +000065 for (size_t M = 0; M < NumModules; M++) {
66 for (uint64_t *X = Modules[M].Start; X < Modules[M].Stop; X++) {
67 uint64_t Value = *X & 0xff;
68 uint64_t Idx = *X >> 32;
69 if (Value >= 1) {
70 unsigned Bit = 0;
71 /**/ if (Value >= 128) Bit = 7;
72 else if (Value >= 32) Bit = 6;
73 else if (Value >= 16) Bit = 5;
74 else if (Value >= 8) Bit = 4;
75 else if (Value >= 4) Bit = 3;
76 else if (Value >= 3) Bit = 2;
77 else if (Value >= 2) Bit = 1;
78 CounterMap.AddValue(Idx * 8 + Bit);
79 }
80 *X = Idx << 32;
Kostya Serebryanya5277d52016-09-15 01:30:18 +000081 }
Kostya Serebryanya5277d52016-09-15 01:30:18 +000082 }
83 }
84}
85
86size_t TracePC::UpdateCounterMap(ValueBitMap *Map) {
87 if (!TotalCoverage) return 0;
88 size_t NewTotalCounterBits = Map->MergeFrom(CounterMap);
89 size_t Delta = NewTotalCounterBits - TotalCounterBits;
90 TotalCounterBits = NewTotalCounterBits;
91 return Delta;
92}
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000093
Kostya Serebryany09845172016-09-15 22:16:15 +000094void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) {
95 const uintptr_t kBits = 12;
96 const uintptr_t kMask = (1 << kBits) - 1;
97 CounterMap.AddValue((Caller & kMask) | ((Callee & kMask) << kBits));
98}
99
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +0000100} // namespace fuzzer
101
Dan Liew59144072016-06-06 20:27:09 +0000102extern "C" {
Kostya Serebryany32661f92016-08-18 20:52:52 +0000103__attribute__((visibility("default")))
Kostya Serebryany3e36ec12016-09-17 05:04:47 +0000104void __sanitizer_cov_trace_pc_guard(uint64_t *Guard) {
Kostya Serebryanya00b2432016-09-14 02:13:06 +0000105 uintptr_t PC = (uintptr_t)__builtin_return_address(0);
Kostya Serebryanya5277d52016-09-15 01:30:18 +0000106 fuzzer::TPC.HandleTrace(Guard, PC);
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +0000107}
Dan Liew59144072016-06-06 20:27:09 +0000108
Kostya Serebryany32661f92016-08-18 20:52:52 +0000109__attribute__((visibility("default")))
Kostya Serebryany3e36ec12016-09-17 05:04:47 +0000110void __sanitizer_cov_trace_pc_guard_init(uint64_t *Start, uint64_t *Stop) {
Kostya Serebryanya5277d52016-09-15 01:30:18 +0000111 fuzzer::TPC.HandleInit(Start, Stop);
Dan Liew59144072016-06-06 20:27:09 +0000112}
Kostya Serebryany09845172016-09-15 22:16:15 +0000113
114__attribute__((visibility("default")))
115void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) {
116 uintptr_t PC = (uintptr_t)__builtin_return_address(0);
117 fuzzer::TPC.HandleCallerCallee(PC, Callee);
118}
Dan Liew59144072016-06-06 20:27:09 +0000119}