1 /*
2 *
3 * honggfuzz - Intel PT decoder
4 * -----------------------------------------
5 *
6 * Author: Robert Swiecki <swiecki@google.com>
7 *
8 * Copyright 2010-2016 by Google Inc. All Rights Reserved.
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License"); you may
11 * not use this file except in compliance with the License. You may obtain
12 * a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
19 * implied. See the License for the specific language governing
20 * permissions and limitations under the License.
21 *
22 */
23
24 #include "libcommon/common.h"
25
26 #include <inttypes.h>
27 #include <linux/perf_event.h>
28
29 #include "libcommon/log.h"
30 #include "libcommon/util.h"
31 #include "pt.h"
32
33 #ifdef _HF_LINUX_INTEL_PT_LIB
34
35 #include <intel-pt.h>
36
37 /* Sign-extend a uint64_t value. */
sext(uint64_t val,uint8_t sign)38 inline static uint64_t sext(uint64_t val, uint8_t sign) {
39 uint64_t signbit, mask;
40
41 signbit = 1ull << (sign - 1);
42 mask = ~0ull << sign;
43
44 return val & signbit ? val | mask : val & ~mask;
45 }
46
perf_ptAnalyzePkt(run_t * run,struct pt_packet * packet)47 __attribute__((hot)) inline static void perf_ptAnalyzePkt(run_t* run, struct pt_packet* packet) {
48 if (packet->type != ppt_tip) {
49 return;
50 }
51
52 uint64_t ip;
53 switch (packet->payload.ip.ipc) {
54 case pt_ipc_update_16:
55 ip = packet->payload.ip.ip & 0xFFFF;
56 break;
57 case pt_ipc_update_32:
58 ip = packet->payload.ip.ip & 0xFFFFFFFF;
59 break;
60 case pt_ipc_update_48:
61 ip = packet->payload.ip.ip & 0xFFFFFFFFFFFF;
62 break;
63 case pt_ipc_sext_48:
64 ip = sext(packet->payload.ip.ip, 48);
65 break;
66 case pt_ipc_full:
67 ip = packet->payload.ip.ip;
68 break;
69 default:
70 return;
71 }
72
73 ip &= _HF_PERF_BITMAP_BITSZ_MASK;
74 register uint8_t prev = ATOMIC_BTS(run->global->feedback->bbMapPc, ip);
75 if (!prev) {
76 run->linux.hwCnts.newBBCnt++;
77 }
78 return;
79 }
80
arch_ptAnalyze(run_t * run)81 void arch_ptAnalyze(run_t* run) {
82 struct perf_event_mmap_page* pem = (struct perf_event_mmap_page*)run->linux.perfMmapBuf;
83
84 uint64_t aux_tail = ATOMIC_GET(pem->aux_tail);
85 uint64_t aux_head = ATOMIC_GET(pem->aux_head);
86
87 struct pt_config ptc;
88 pt_config_init(&ptc);
89 ptc.begin = &run->linux.perfMmapAux[aux_tail];
90 ptc.end = &run->linux.perfMmapAux[aux_head - 1];
91
92 int errcode = pt_cpu_errata(&ptc.errata, &ptc.cpu);
93 if (errcode < 0) {
94 LOG_F("pt_errata() failed: %s", pt_errstr(errcode));
95 }
96
97 struct pt_packet_decoder* ptd = pt_pkt_alloc_decoder(&ptc);
98 if (ptd == NULL) {
99 LOG_F("pt_pkt_alloc_decoder() failed");
100 }
101 defer { pt_pkt_free_decoder(ptd); };
102
103 errcode = pt_pkt_sync_forward(ptd);
104 if (errcode < 0) {
105 LOG_W("pt_pkt_sync_forward() failed: %s", pt_errstr(errcode));
106 return;
107 }
108
109 for (;;) {
110 struct pt_packet packet;
111 errcode = pt_pkt_next(ptd, &packet, sizeof(packet));
112 if (errcode == -pte_eos) {
113 break;
114 }
115 if (errcode < 0) {
116 LOG_W("pt_pkt_next() failed: %s", pt_errstr(errcode));
117 break;
118 }
119 perf_ptAnalyzePkt(run, &packet);
120 }
121 }
122
123 #else /* _HF_LINUX_INTEL_PT_LIB */
124
arch_ptAnalyze(run_t * fuzzer UNUSED)125 void arch_ptAnalyze(run_t* fuzzer UNUSED) {
126 LOG_F(
127 "The program has not been linked against the Intel's Processor Trace Library (libipt.so)");
128 }
129
130 #endif /* _HF_LINUX_INTEL_PT_LIB */
131