blob: 2822725f555cb63909032f72a9ec428e45ef961a [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 Serebryanya5277d52016-09-15 01:30:18 +000021void TracePC::HandleTrace(uint8_t *Guard, uintptr_t PC) {
22 if (UseCounters) {
23 uintptr_t GV = *Guard;
24 if (GV == 0)
25 TotalCoverage++;
26 if (GV < 255)
27 GV++;
28 *Guard = GV;
29 } else {
30 *Guard = 0xff;
31 TotalCoverage++;
32 }
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000033}
Kostya Serebryanya5277d52016-09-15 01:30:18 +000034
35void TracePC::HandleInit(uint8_t *Start, uint8_t *Stop) {
36 // TODO: this handles only one DSO/binary.
37 this->Start = Start;
38 this->Stop = Stop;
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000039}
Kostya Serebryanya5277d52016-09-15 01:30:18 +000040
41void TracePC::FinalizeTrace() {
42 if (UseCounters && TotalCoverage) {
43 for (uint8_t *X = Start; X < Stop; X++) {
44 uint8_t Value = *X;
45 size_t Idx = X - Start;
46 if (Value >= 2) {
47 unsigned Bit = 31 - __builtin_clz(Value);
48 assert(Bit < 8);
49 CounterMap.AddValue(Idx * 8 + Bit);
50 }
51 *X = 1;
52 }
53 }
54}
55
56size_t TracePC::UpdateCounterMap(ValueBitMap *Map) {
57 if (!TotalCoverage) return 0;
58 size_t NewTotalCounterBits = Map->MergeFrom(CounterMap);
59 size_t Delta = NewTotalCounterBits - TotalCounterBits;
60 TotalCounterBits = NewTotalCounterBits;
61 return Delta;
62}
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000063
64} // namespace fuzzer
65
Dan Liew59144072016-06-06 20:27:09 +000066extern "C" {
Kostya Serebryany32661f92016-08-18 20:52:52 +000067__attribute__((visibility("default")))
Kostya Serebryanya5277d52016-09-15 01:30:18 +000068void __sanitizer_cov_trace_pc_guard(uint8_t *Guard) {
Kostya Serebryanya00b2432016-09-14 02:13:06 +000069 uintptr_t PC = (uintptr_t)__builtin_return_address(0);
Kostya Serebryanya5277d52016-09-15 01:30:18 +000070 fuzzer::TPC.HandleTrace(Guard, PC);
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000071}
Dan Liew59144072016-06-06 20:27:09 +000072
Kostya Serebryany32661f92016-08-18 20:52:52 +000073__attribute__((visibility("default")))
Kostya Serebryanya5277d52016-09-15 01:30:18 +000074void __sanitizer_cov_trace_pc_guard_init(uint8_t *Start, uint8_t *Stop) {
75 fuzzer::TPC.HandleInit(Start, Stop);
Dan Liew59144072016-06-06 20:27:09 +000076}
77}