blob: 9daa721cfbc2c511785efacf9f75389e2db389b0 [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"
Kostya Serebryany6f5a8042016-09-21 01:50:50 +000016#include "FuzzerTracePC.h"
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000017
18namespace fuzzer {
Mike Aizatsky1aa501e2016-05-10 23:43:15 +000019
Kostya Serebryanya00b2432016-09-14 02:13:06 +000020TracePC TPC;
Kostya Serebryany8e781a82016-09-18 04:52:23 +000021const size_t TracePC::kNumCounters;
Kostya Serebryanyb706b482016-09-18 21:47:08 +000022const size_t TracePC::kNumPCs;
Mike Aizatsky1aa501e2016-05-10 23:43:15 +000023
Kostya Serebryany8e781a82016-09-18 04:52:23 +000024void TracePC::HandleTrace(uintptr_t *Guard, uintptr_t PC) {
25 uintptr_t Idx = *Guard;
26 if (!Idx) return;
Kostya Serebryanya5277d52016-09-15 01:30:18 +000027 if (UseCounters) {
Kostya Serebryany8e781a82016-09-18 04:52:23 +000028 uint8_t Counter = Counters[Idx % kNumCounters];
Kostya Serebryany3e36ec12016-09-17 05:04:47 +000029 if (Counter == 0) {
Kostya Serebryanyb706b482016-09-18 21:47:08 +000030 PCs[Idx] = PC;
Kostya Serebryany53501782016-09-15 04:36:45 +000031 if (TotalCoverageMap.AddValue(Idx)) {
32 TotalCoverage++;
33 AddNewPC(PC);
34 }
35 }
Kostya Serebryany8e781a82016-09-18 04:52:23 +000036 if (Counter < 128)
37 Counters[Idx % kNumCounters] = Counter + 1;
Kostya Serebryanybc3789a2016-09-17 06:01:55 +000038 else
Kostya Serebryany8e781a82016-09-18 04:52:23 +000039 *Guard = 0;
Kostya Serebryanya5277d52016-09-15 01:30:18 +000040 } else {
Kostya Serebryany8e781a82016-09-18 04:52:23 +000041 *Guard = 0;
Kostya Serebryanya5277d52016-09-15 01:30:18 +000042 TotalCoverage++;
Kostya Serebryany53501782016-09-15 04:36:45 +000043 AddNewPC(PC);
Kostya Serebryanyb706b482016-09-18 21:47:08 +000044 PCs[Idx] = PC;
Kostya Serebryanya5277d52016-09-15 01:30:18 +000045 }
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000046}
Kostya Serebryanya5277d52016-09-15 01:30:18 +000047
Kostya Serebryany8e781a82016-09-18 04:52:23 +000048void TracePC::HandleInit(uintptr_t *Start, uintptr_t *Stop) {
Kostya Serebryany3e36ec12016-09-17 05:04:47 +000049 if (Start == Stop || *Start) return;
50 assert(NumModules < sizeof(Modules) / sizeof(Modules[0]));
Kostya Serebryany8e781a82016-09-18 04:52:23 +000051 for (uintptr_t *P = Start; P < Stop; P++)
52 *P = ++NumGuards;
Kostya Serebryany3e36ec12016-09-17 05:04:47 +000053 Modules[NumModules].Start = Start;
54 Modules[NumModules].Stop = Stop;
55 NumModules++;
56}
57
58void TracePC::PrintModuleInfo() {
59 Printf("INFO: Loaded %zd modules (%zd guards): ", NumModules, NumGuards);
60 for (size_t i = 0; i < NumModules; i++)
61 Printf("[%p, %p), ", Modules[i].Start, Modules[i].Stop);
62 Printf("\n");
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000063}
Kostya Serebryanya5277d52016-09-15 01:30:18 +000064
Kostya Serebryanybc3789a2016-09-17 06:01:55 +000065void TracePC::ResetGuards() {
Kostya Serebryany8e781a82016-09-18 04:52:23 +000066 uintptr_t N = 0;
Kostya Serebryanybc3789a2016-09-17 06:01:55 +000067 for (size_t M = 0; M < NumModules; M++)
Kostya Serebryany8e781a82016-09-18 04:52:23 +000068 for (uintptr_t *X = Modules[M].Start; X < Modules[M].Stop; X++)
69 *X = ++N;
70 assert(N == NumGuards);
Kostya Serebryanybc3789a2016-09-17 06:01:55 +000071}
72
Kostya Serebryanya5277d52016-09-15 01:30:18 +000073void TracePC::FinalizeTrace() {
74 if (UseCounters && TotalCoverage) {
Kostya Serebryany8e781a82016-09-18 04:52:23 +000075 for (size_t Idx = 1, N = std::min(kNumCounters, NumGuards); Idx < N;
76 Idx++) {
77 uint8_t Counter = Counters[Idx];
78 if (!Counter) continue;
79 Counters[Idx] = 0;
80 unsigned Bit = 0;
81 /**/ if (Counter >= 128) Bit = 7;
82 else if (Counter >= 32) Bit = 6;
83 else if (Counter >= 16) Bit = 5;
84 else if (Counter >= 8) Bit = 4;
85 else if (Counter >= 4) Bit = 3;
86 else if (Counter >= 3) Bit = 2;
87 else if (Counter >= 2) Bit = 1;
88 CounterMap.AddValue(Idx * 8 + Bit);
Kostya Serebryanya5277d52016-09-15 01:30:18 +000089 }
90 }
91}
92
93size_t TracePC::UpdateCounterMap(ValueBitMap *Map) {
94 if (!TotalCoverage) return 0;
95 size_t NewTotalCounterBits = Map->MergeFrom(CounterMap);
96 size_t Delta = NewTotalCounterBits - TotalCounterBits;
97 TotalCounterBits = NewTotalCounterBits;
98 return Delta;
99}
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +0000100
Kostya Serebryany09845172016-09-15 22:16:15 +0000101void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) {
102 const uintptr_t kBits = 12;
103 const uintptr_t kMask = (1 << kBits) - 1;
104 CounterMap.AddValue((Caller & kMask) | ((Callee & kMask) << kBits));
105}
106
Kostya Serebryanyb706b482016-09-18 21:47:08 +0000107void TracePC::PrintCoverage() {
108 Printf("COVERAGE:\n");
109 for (size_t i = 0; i < std::min(NumGuards, kNumPCs); i++) {
110 if (PCs[i])
111 PrintPC("COVERED: %p %F %L\n", "COVERED: %p\n", PCs[i]);
112 }
113}
114
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +0000115} // namespace fuzzer
116
Dan Liew59144072016-06-06 20:27:09 +0000117extern "C" {
Kostya Serebryany32661f92016-08-18 20:52:52 +0000118__attribute__((visibility("default")))
Kostya Serebryany8e781a82016-09-18 04:52:23 +0000119void __sanitizer_cov_trace_pc_guard(uintptr_t *Guard) {
Kostya Serebryanya00b2432016-09-14 02:13:06 +0000120 uintptr_t PC = (uintptr_t)__builtin_return_address(0);
Kostya Serebryanya5277d52016-09-15 01:30:18 +0000121 fuzzer::TPC.HandleTrace(Guard, PC);
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +0000122}
Dan Liew59144072016-06-06 20:27:09 +0000123
Kostya Serebryany32661f92016-08-18 20:52:52 +0000124__attribute__((visibility("default")))
Kostya Serebryany8e781a82016-09-18 04:52:23 +0000125void __sanitizer_cov_trace_pc_guard_init(uintptr_t *Start, uintptr_t *Stop) {
Kostya Serebryanya5277d52016-09-15 01:30:18 +0000126 fuzzer::TPC.HandleInit(Start, Stop);
Dan Liew59144072016-06-06 20:27:09 +0000127}
Kostya Serebryany09845172016-09-15 22:16:15 +0000128
129__attribute__((visibility("default")))
130void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) {
131 uintptr_t PC = (uintptr_t)__builtin_return_address(0);
132 fuzzer::TPC.HandleCallerCallee(PC, Callee);
133}
Dan Liew59144072016-06-06 20:27:09 +0000134}