blob: f729a5e687871a65cbb656631e3d5c50d3cd903e [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;
Kostya Serebryany53501782016-09-15 04:36:45 +000024 if (GV == 0) {
25 size_t Idx = Guard - Start;
26 if (TotalCoverageMap.AddValue(Idx)) {
27 TotalCoverage++;
28 AddNewPC(PC);
29 }
30 }
Kostya Serebryanya5277d52016-09-15 01:30:18 +000031 if (GV < 255)
32 GV++;
33 *Guard = GV;
34 } else {
35 *Guard = 0xff;
36 TotalCoverage++;
Kostya Serebryany53501782016-09-15 04:36:45 +000037 AddNewPC(PC);
Kostya Serebryanya5277d52016-09-15 01:30:18 +000038 }
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000039}
Kostya Serebryanya5277d52016-09-15 01:30:18 +000040
41void TracePC::HandleInit(uint8_t *Start, uint8_t *Stop) {
42 // TODO: this handles only one DSO/binary.
43 this->Start = Start;
44 this->Stop = Stop;
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000045}
Kostya Serebryanya5277d52016-09-15 01:30:18 +000046
47void TracePC::FinalizeTrace() {
48 if (UseCounters && TotalCoverage) {
49 for (uint8_t *X = Start; X < Stop; X++) {
50 uint8_t Value = *X;
51 size_t Idx = X - Start;
Kostya Serebryany53501782016-09-15 04:36:45 +000052 if (Value >= 1) {
53 unsigned Bit = 0;
54 /**/ if (Value >= 128) Bit = 7;
55 else if (Value >= 32) Bit = 6;
56 else if (Value >= 16) Bit = 5;
57 else if (Value >= 8) Bit = 4;
58 else if (Value >= 4) Bit = 3;
59 else if (Value >= 3) Bit = 2;
60 else if (Value >= 2) Bit = 1;
Kostya Serebryanya5277d52016-09-15 01:30:18 +000061 CounterMap.AddValue(Idx * 8 + Bit);
62 }
Kostya Serebryany53501782016-09-15 04:36:45 +000063 *X = 0;
Kostya Serebryanya5277d52016-09-15 01:30:18 +000064 }
65 }
66}
67
68size_t TracePC::UpdateCounterMap(ValueBitMap *Map) {
69 if (!TotalCoverage) return 0;
70 size_t NewTotalCounterBits = Map->MergeFrom(CounterMap);
71 size_t Delta = NewTotalCounterBits - TotalCounterBits;
72 TotalCounterBits = NewTotalCounterBits;
73 return Delta;
74}
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000075
Kostya Serebryany09845172016-09-15 22:16:15 +000076void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) {
77 const uintptr_t kBits = 12;
78 const uintptr_t kMask = (1 << kBits) - 1;
79 CounterMap.AddValue((Caller & kMask) | ((Callee & kMask) << kBits));
80}
81
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000082} // namespace fuzzer
83
Dan Liew59144072016-06-06 20:27:09 +000084extern "C" {
Kostya Serebryany32661f92016-08-18 20:52:52 +000085__attribute__((visibility("default")))
Kostya Serebryanya5277d52016-09-15 01:30:18 +000086void __sanitizer_cov_trace_pc_guard(uint8_t *Guard) {
Kostya Serebryanya00b2432016-09-14 02:13:06 +000087 uintptr_t PC = (uintptr_t)__builtin_return_address(0);
Kostya Serebryanya5277d52016-09-15 01:30:18 +000088 fuzzer::TPC.HandleTrace(Guard, PC);
Kostya Serebryanyda63c1d2016-02-26 21:33:56 +000089}
Dan Liew59144072016-06-06 20:27:09 +000090
Kostya Serebryany32661f92016-08-18 20:52:52 +000091__attribute__((visibility("default")))
Kostya Serebryanya5277d52016-09-15 01:30:18 +000092void __sanitizer_cov_trace_pc_guard_init(uint8_t *Start, uint8_t *Stop) {
93 fuzzer::TPC.HandleInit(Start, Stop);
Dan Liew59144072016-06-06 20:27:09 +000094}
Kostya Serebryany09845172016-09-15 22:16:15 +000095
96__attribute__((visibility("default")))
97void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) {
98 uintptr_t PC = (uintptr_t)__builtin_return_address(0);
99 fuzzer::TPC.HandleCallerCallee(PC, Callee);
100}
Dan Liew59144072016-06-06 20:27:09 +0000101}