• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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