1*8d741a5dSApple OSS Distributions /*
2*8d741a5dSApple OSS Distributions * Copyright (c) 2019 Apple Inc. All rights reserved.
3*8d741a5dSApple OSS Distributions *
4*8d741a5dSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*8d741a5dSApple OSS Distributions *
6*8d741a5dSApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*8d741a5dSApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*8d741a5dSApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*8d741a5dSApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*8d741a5dSApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*8d741a5dSApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*8d741a5dSApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*8d741a5dSApple OSS Distributions * terms of an Apple operating system software license agreement.
14*8d741a5dSApple OSS Distributions *
15*8d741a5dSApple OSS Distributions * Please obtain a copy of the License at
16*8d741a5dSApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*8d741a5dSApple OSS Distributions *
18*8d741a5dSApple OSS Distributions * The Original Code and all software distributed under the License are
19*8d741a5dSApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*8d741a5dSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*8d741a5dSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*8d741a5dSApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*8d741a5dSApple OSS Distributions * Please see the License for the specific language governing rights and
24*8d741a5dSApple OSS Distributions * limitations under the License.
25*8d741a5dSApple OSS Distributions *
26*8d741a5dSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*8d741a5dSApple OSS Distributions */
28*8d741a5dSApple OSS Distributions
29*8d741a5dSApple OSS Distributions #ifndef _KSANCOV_H_
30*8d741a5dSApple OSS Distributions #define _KSANCOV_H_
31*8d741a5dSApple OSS Distributions
32*8d741a5dSApple OSS Distributions #include <stdint.h>
33*8d741a5dSApple OSS Distributions #include <stdatomic.h>
34*8d741a5dSApple OSS Distributions #include <sys/ioccom.h>
35*8d741a5dSApple OSS Distributions #include <sys/ioctl.h>
36*8d741a5dSApple OSS Distributions #include <strings.h>
37*8d741a5dSApple OSS Distributions #include <assert.h>
38*8d741a5dSApple OSS Distributions #include <unistd.h>
39*8d741a5dSApple OSS Distributions
40*8d741a5dSApple OSS Distributions #define KSANCOV_DEVNODE "ksancov"
41*8d741a5dSApple OSS Distributions #define KSANCOV_PATH "/dev/" KSANCOV_DEVNODE
42*8d741a5dSApple OSS Distributions
43*8d741a5dSApple OSS Distributions /* Set mode */
44*8d741a5dSApple OSS Distributions #define KSANCOV_IOC_TRACE _IOW('K', 1, size_t) /* number of pcs */
45*8d741a5dSApple OSS Distributions #define KSANCOV_IOC_COUNTERS _IO('K', 2)
46*8d741a5dSApple OSS Distributions #define KSANCOV_IOC_STKSIZE _IOW('K', 3, size_t) /* number of pcs */
47*8d741a5dSApple OSS Distributions
48*8d741a5dSApple OSS Distributions /* Establish a shared mapping of the coverage buffer. */
49*8d741a5dSApple OSS Distributions #define KSANCOV_IOC_MAP _IOWR('K', 8, struct ksancov_buf_desc)
50*8d741a5dSApple OSS Distributions
51*8d741a5dSApple OSS Distributions /* Establish a shared mapping of the edge address buffer. */
52*8d741a5dSApple OSS Distributions #define KSANCOV_IOC_MAP_EDGEMAP _IOWR('K', 9, struct ksancov_buf_desc)
53*8d741a5dSApple OSS Distributions
54*8d741a5dSApple OSS Distributions /* Log the current thread */
55*8d741a5dSApple OSS Distributions #define KSANCOV_IOC_START _IOW('K', 10, uintptr_t)
56*8d741a5dSApple OSS Distributions #define KSANCOV_IOC_NEDGES _IOR('K', 50, size_t)
57*8d741a5dSApple OSS Distributions
58*8d741a5dSApple OSS Distributions /* kext-related operations */
59*8d741a5dSApple OSS Distributions #define KSANCOV_IOC_ON_DEMAND _IOWR('K', 60, struct ksancov_on_demand_msg)
60*8d741a5dSApple OSS Distributions
61*8d741a5dSApple OSS Distributions /*
62*8d741a5dSApple OSS Distributions * shared kernel-user mapping
63*8d741a5dSApple OSS Distributions */
64*8d741a5dSApple OSS Distributions
65*8d741a5dSApple OSS Distributions #define KSANCOV_MAX_EDGES (1 << 24)
66*8d741a5dSApple OSS Distributions #define KSANCOV_MAX_HITS UINT8_MAX
67*8d741a5dSApple OSS Distributions #define KSANCOV_TRACE_MAGIC (uint32_t)0x5AD17F5BU
68*8d741a5dSApple OSS Distributions #define KSANCOV_COUNTERS_MAGIC (uint32_t)0x5AD27F6BU
69*8d741a5dSApple OSS Distributions #define KSANCOV_EDGEMAP_MAGIC (uint32_t)0x5AD37F7BU
70*8d741a5dSApple OSS Distributions #define KSANCOV_STKSIZE_MAGIC (uint32_t)0x5AD47F8BU
71*8d741a5dSApple OSS Distributions
72*8d741a5dSApple OSS Distributions /*
73*8d741a5dSApple OSS Distributions * ioctl
74*8d741a5dSApple OSS Distributions */
75*8d741a5dSApple OSS Distributions
76*8d741a5dSApple OSS Distributions struct ksancov_buf_desc {
77*8d741a5dSApple OSS Distributions uintptr_t ptr; /* ptr to shared buffer [out] */
78*8d741a5dSApple OSS Distributions size_t sz; /* size of shared buffer [out] */
79*8d741a5dSApple OSS Distributions };
80*8d741a5dSApple OSS Distributions
81*8d741a5dSApple OSS Distributions /*
82*8d741a5dSApple OSS Distributions * Supported coverage modes.
83*8d741a5dSApple OSS Distributions */
84*8d741a5dSApple OSS Distributions typedef enum {
85*8d741a5dSApple OSS Distributions KS_MODE_NONE,
86*8d741a5dSApple OSS Distributions KS_MODE_TRACE,
87*8d741a5dSApple OSS Distributions KS_MODE_COUNTERS,
88*8d741a5dSApple OSS Distributions KS_MODE_STKSIZE,
89*8d741a5dSApple OSS Distributions KS_MODE_MAX
90*8d741a5dSApple OSS Distributions } ksancov_mode_t;
91*8d741a5dSApple OSS Distributions
92*8d741a5dSApple OSS Distributions /*
93*8d741a5dSApple OSS Distributions * A header that is always present in every ksancov mode shared memory structure.
94*8d741a5dSApple OSS Distributions */
95*8d741a5dSApple OSS Distributions typedef struct ksancov_header {
96*8d741a5dSApple OSS Distributions uint32_t kh_magic;
97*8d741a5dSApple OSS Distributions _Atomic uint32_t kh_enabled;
98*8d741a5dSApple OSS Distributions } ksancov_header_t;
99*8d741a5dSApple OSS Distributions
100*8d741a5dSApple OSS Distributions /*
101*8d741a5dSApple OSS Distributions * TRACE mode data structure.
102*8d741a5dSApple OSS Distributions */
103*8d741a5dSApple OSS Distributions
104*8d741a5dSApple OSS Distributions /*
105*8d741a5dSApple OSS Distributions * All trace based tools share this structure.
106*8d741a5dSApple OSS Distributions */
107*8d741a5dSApple OSS Distributions typedef struct ksancov_trace {
108*8d741a5dSApple OSS Distributions ksancov_header_t kt_hdr; /* header (must be always first) */
109*8d741a5dSApple OSS Distributions uint32_t kt_maxent; /* Maximum entries in this shared buffer. */
110*8d741a5dSApple OSS Distributions _Atomic uint32_t kt_head; /* Pointer to the first unused element. */
111*8d741a5dSApple OSS Distributions uint64_t kt_entries[]; /* Trace entries in this buffer. */
112*8d741a5dSApple OSS Distributions } ksancov_trace_t;
113*8d741a5dSApple OSS Distributions
114*8d741a5dSApple OSS Distributions /* PC tracing only records PCs. */
115*8d741a5dSApple OSS Distributions typedef uintptr_t ksancov_trace_pc_ent_t;
116*8d741a5dSApple OSS Distributions
117*8d741a5dSApple OSS Distributions /* STKSIZE tracing records PCs and stack size. */
118*8d741a5dSApple OSS Distributions typedef struct ksancov_trace_stksize_entry {
119*8d741a5dSApple OSS Distributions uintptr_t pc; /* PC */
120*8d741a5dSApple OSS Distributions uint32_t stksize; /* associated stack size */
121*8d741a5dSApple OSS Distributions } ksancov_trace_stksize_ent_t;
122*8d741a5dSApple OSS Distributions
123*8d741a5dSApple OSS Distributions /*
124*8d741a5dSApple OSS Distributions * COUNTERS mode data structure.
125*8d741a5dSApple OSS Distributions */
126*8d741a5dSApple OSS Distributions typedef struct ksancov_counters {
127*8d741a5dSApple OSS Distributions ksancov_header_t kc_hdr;
128*8d741a5dSApple OSS Distributions uint32_t kc_nedges; /* total number of edges */
129*8d741a5dSApple OSS Distributions uint8_t kc_hits[]; /* hits on each edge (8bit saturating) */
130*8d741a5dSApple OSS Distributions } ksancov_counters_t;
131*8d741a5dSApple OSS Distributions
132*8d741a5dSApple OSS Distributions /*
133*8d741a5dSApple OSS Distributions * Edge to PC mapping.
134*8d741a5dSApple OSS Distributions */
135*8d741a5dSApple OSS Distributions typedef struct ksancov_edgemap {
136*8d741a5dSApple OSS Distributions uint32_t ke_magic;
137*8d741a5dSApple OSS Distributions uint32_t ke_nedges;
138*8d741a5dSApple OSS Distributions uintptr_t ke_addrs[]; /* address of each edge relative to 'offset' */
139*8d741a5dSApple OSS Distributions } ksancov_edgemap_t;
140*8d741a5dSApple OSS Distributions
141*8d741a5dSApple OSS Distributions /*
142*8d741a5dSApple OSS Distributions * On-demand related functionalities
143*8d741a5dSApple OSS Distributions */
144*8d741a5dSApple OSS Distributions typedef enum {
145*8d741a5dSApple OSS Distributions KS_OD_GET_GATE = 1,
146*8d741a5dSApple OSS Distributions KS_OD_SET_GATE = 2,
147*8d741a5dSApple OSS Distributions KS_OD_GET_RANGE = 3,
148*8d741a5dSApple OSS Distributions } ksancov_on_demand_operation_t;
149*8d741a5dSApple OSS Distributions
150*8d741a5dSApple OSS Distributions struct ksancov_on_demand_msg {
151*8d741a5dSApple OSS Distributions char bundle[/*KMOD_MAX_NAME*/ 64];
152*8d741a5dSApple OSS Distributions ksancov_on_demand_operation_t operation;
153*8d741a5dSApple OSS Distributions union {
154*8d741a5dSApple OSS Distributions uint64_t gate;
155*8d741a5dSApple OSS Distributions struct {
156*8d741a5dSApple OSS Distributions uint32_t start;
157*8d741a5dSApple OSS Distributions uint32_t stop;
158*8d741a5dSApple OSS Distributions } range;
159*8d741a5dSApple OSS Distributions };
160*8d741a5dSApple OSS Distributions };
161*8d741a5dSApple OSS Distributions
162*8d741a5dSApple OSS Distributions /*
163*8d741a5dSApple OSS Distributions * ksancov userspace API
164*8d741a5dSApple OSS Distributions *
165*8d741a5dSApple OSS Distributions * Usage:
166*8d741a5dSApple OSS Distributions * 1) open the ksancov device
167*8d741a5dSApple OSS Distributions * 2) set the coverage mode
168*8d741a5dSApple OSS Distributions * 3) map the coverage buffer
169*8d741a5dSApple OSS Distributions * 4) start the trace on a thread
170*8d741a5dSApple OSS Distributions * 5) flip the enable bit
171*8d741a5dSApple OSS Distributions */
172*8d741a5dSApple OSS Distributions
173*8d741a5dSApple OSS Distributions static inline int
ksancov_open(void)174*8d741a5dSApple OSS Distributions ksancov_open(void)
175*8d741a5dSApple OSS Distributions {
176*8d741a5dSApple OSS Distributions return open(KSANCOV_PATH, 0);
177*8d741a5dSApple OSS Distributions }
178*8d741a5dSApple OSS Distributions
179*8d741a5dSApple OSS Distributions static inline int
ksancov_map(int fd,uintptr_t * buf,size_t * sz)180*8d741a5dSApple OSS Distributions ksancov_map(int fd, uintptr_t *buf, size_t *sz)
181*8d741a5dSApple OSS Distributions {
182*8d741a5dSApple OSS Distributions int ret;
183*8d741a5dSApple OSS Distributions struct ksancov_buf_desc mc = {0};
184*8d741a5dSApple OSS Distributions
185*8d741a5dSApple OSS Distributions ret = ioctl(fd, KSANCOV_IOC_MAP, &mc);
186*8d741a5dSApple OSS Distributions if (ret == -1) {
187*8d741a5dSApple OSS Distributions return errno;
188*8d741a5dSApple OSS Distributions }
189*8d741a5dSApple OSS Distributions
190*8d741a5dSApple OSS Distributions *buf = mc.ptr;
191*8d741a5dSApple OSS Distributions if (sz) {
192*8d741a5dSApple OSS Distributions *sz = mc.sz;
193*8d741a5dSApple OSS Distributions }
194*8d741a5dSApple OSS Distributions
195*8d741a5dSApple OSS Distributions ksancov_header_t *hdr = (ksancov_header_t *)mc.ptr;
196*8d741a5dSApple OSS Distributions assert(hdr->kh_magic == KSANCOV_TRACE_MAGIC ||
197*8d741a5dSApple OSS Distributions hdr->kh_magic == KSANCOV_COUNTERS_MAGIC ||
198*8d741a5dSApple OSS Distributions hdr->kh_magic == KSANCOV_STKSIZE_MAGIC);
199*8d741a5dSApple OSS Distributions
200*8d741a5dSApple OSS Distributions return 0;
201*8d741a5dSApple OSS Distributions }
202*8d741a5dSApple OSS Distributions
203*8d741a5dSApple OSS Distributions static inline int
ksancov_map_edgemap(int fd,uintptr_t * buf,size_t * sz)204*8d741a5dSApple OSS Distributions ksancov_map_edgemap(int fd, uintptr_t *buf, size_t *sz)
205*8d741a5dSApple OSS Distributions {
206*8d741a5dSApple OSS Distributions int ret;
207*8d741a5dSApple OSS Distributions struct ksancov_buf_desc mc = {0};
208*8d741a5dSApple OSS Distributions
209*8d741a5dSApple OSS Distributions ret = ioctl(fd, KSANCOV_IOC_MAP_EDGEMAP, &mc);
210*8d741a5dSApple OSS Distributions if (ret == -1) {
211*8d741a5dSApple OSS Distributions return errno;
212*8d741a5dSApple OSS Distributions }
213*8d741a5dSApple OSS Distributions
214*8d741a5dSApple OSS Distributions *buf = mc.ptr;
215*8d741a5dSApple OSS Distributions if (sz) {
216*8d741a5dSApple OSS Distributions *sz = mc.sz;
217*8d741a5dSApple OSS Distributions }
218*8d741a5dSApple OSS Distributions
219*8d741a5dSApple OSS Distributions ksancov_edgemap_t *emap = (ksancov_edgemap_t *)mc.ptr;
220*8d741a5dSApple OSS Distributions assert(emap->ke_magic == KSANCOV_EDGEMAP_MAGIC);
221*8d741a5dSApple OSS Distributions
222*8d741a5dSApple OSS Distributions return 0;
223*8d741a5dSApple OSS Distributions }
224*8d741a5dSApple OSS Distributions
225*8d741a5dSApple OSS Distributions static inline size_t
ksancov_nedges(int fd)226*8d741a5dSApple OSS Distributions ksancov_nedges(int fd)
227*8d741a5dSApple OSS Distributions {
228*8d741a5dSApple OSS Distributions size_t nedges;
229*8d741a5dSApple OSS Distributions int ret = ioctl(fd, KSANCOV_IOC_NEDGES, &nedges);
230*8d741a5dSApple OSS Distributions if (ret == -1) {
231*8d741a5dSApple OSS Distributions return SIZE_MAX;
232*8d741a5dSApple OSS Distributions }
233*8d741a5dSApple OSS Distributions return nedges;
234*8d741a5dSApple OSS Distributions }
235*8d741a5dSApple OSS Distributions
236*8d741a5dSApple OSS Distributions static inline int
ksancov_mode_trace(int fd,size_t entries)237*8d741a5dSApple OSS Distributions ksancov_mode_trace(int fd, size_t entries)
238*8d741a5dSApple OSS Distributions {
239*8d741a5dSApple OSS Distributions int ret;
240*8d741a5dSApple OSS Distributions ret = ioctl(fd, KSANCOV_IOC_TRACE, &entries);
241*8d741a5dSApple OSS Distributions if (ret == -1) {
242*8d741a5dSApple OSS Distributions return errno;
243*8d741a5dSApple OSS Distributions }
244*8d741a5dSApple OSS Distributions return 0;
245*8d741a5dSApple OSS Distributions }
246*8d741a5dSApple OSS Distributions
247*8d741a5dSApple OSS Distributions static inline int
ksancov_mode_stksize(int fd,size_t entries)248*8d741a5dSApple OSS Distributions ksancov_mode_stksize(int fd, size_t entries)
249*8d741a5dSApple OSS Distributions {
250*8d741a5dSApple OSS Distributions int ret;
251*8d741a5dSApple OSS Distributions ret = ioctl(fd, KSANCOV_IOC_STKSIZE, &entries);
252*8d741a5dSApple OSS Distributions if (ret == -1) {
253*8d741a5dSApple OSS Distributions return errno;
254*8d741a5dSApple OSS Distributions }
255*8d741a5dSApple OSS Distributions return 0;
256*8d741a5dSApple OSS Distributions }
257*8d741a5dSApple OSS Distributions
258*8d741a5dSApple OSS Distributions static inline int
ksancov_mode_counters(int fd)259*8d741a5dSApple OSS Distributions ksancov_mode_counters(int fd)
260*8d741a5dSApple OSS Distributions {
261*8d741a5dSApple OSS Distributions int ret;
262*8d741a5dSApple OSS Distributions ret = ioctl(fd, KSANCOV_IOC_COUNTERS);
263*8d741a5dSApple OSS Distributions if (ret == -1) {
264*8d741a5dSApple OSS Distributions return errno;
265*8d741a5dSApple OSS Distributions }
266*8d741a5dSApple OSS Distributions return 0;
267*8d741a5dSApple OSS Distributions }
268*8d741a5dSApple OSS Distributions
269*8d741a5dSApple OSS Distributions static inline int
ksancov_thread_self(int fd)270*8d741a5dSApple OSS Distributions ksancov_thread_self(int fd)
271*8d741a5dSApple OSS Distributions {
272*8d741a5dSApple OSS Distributions int ret;
273*8d741a5dSApple OSS Distributions uintptr_t th = 0;
274*8d741a5dSApple OSS Distributions ret = ioctl(fd, KSANCOV_IOC_START, &th);
275*8d741a5dSApple OSS Distributions if (ret == -1) {
276*8d741a5dSApple OSS Distributions return errno;
277*8d741a5dSApple OSS Distributions }
278*8d741a5dSApple OSS Distributions return 0;
279*8d741a5dSApple OSS Distributions }
280*8d741a5dSApple OSS Distributions
281*8d741a5dSApple OSS Distributions static inline int
ksancov_start(void * buf)282*8d741a5dSApple OSS Distributions ksancov_start(void *buf)
283*8d741a5dSApple OSS Distributions {
284*8d741a5dSApple OSS Distributions ksancov_header_t *hdr = (ksancov_header_t *)buf;
285*8d741a5dSApple OSS Distributions atomic_store_explicit(&hdr->kh_enabled, 1, memory_order_relaxed);
286*8d741a5dSApple OSS Distributions return 0;
287*8d741a5dSApple OSS Distributions }
288*8d741a5dSApple OSS Distributions
289*8d741a5dSApple OSS Distributions static inline int
ksancov_stop(void * buf)290*8d741a5dSApple OSS Distributions ksancov_stop(void *buf)
291*8d741a5dSApple OSS Distributions {
292*8d741a5dSApple OSS Distributions ksancov_header_t *hdr = (ksancov_header_t *)buf;
293*8d741a5dSApple OSS Distributions atomic_store_explicit(&hdr->kh_enabled, 0, memory_order_relaxed);
294*8d741a5dSApple OSS Distributions return 0;
295*8d741a5dSApple OSS Distributions }
296*8d741a5dSApple OSS Distributions
297*8d741a5dSApple OSS Distributions static inline int
ksancov_reset(void * buf)298*8d741a5dSApple OSS Distributions ksancov_reset(void *buf)
299*8d741a5dSApple OSS Distributions {
300*8d741a5dSApple OSS Distributions ksancov_header_t *hdr = (ksancov_header_t *)buf;
301*8d741a5dSApple OSS Distributions if (hdr->kh_magic == KSANCOV_TRACE_MAGIC || hdr->kh_magic == KSANCOV_STKSIZE_MAGIC) {
302*8d741a5dSApple OSS Distributions ksancov_trace_t *trace = (ksancov_trace_t *)buf;
303*8d741a5dSApple OSS Distributions atomic_store_explicit(&trace->kt_head, 0, memory_order_relaxed);
304*8d741a5dSApple OSS Distributions } else if (hdr->kh_magic == KSANCOV_COUNTERS_MAGIC) {
305*8d741a5dSApple OSS Distributions ksancov_counters_t *counters = (ksancov_counters_t *)buf;
306*8d741a5dSApple OSS Distributions bzero(counters->kc_hits, counters->kc_nedges);
307*8d741a5dSApple OSS Distributions } else {
308*8d741a5dSApple OSS Distributions return EINVAL;
309*8d741a5dSApple OSS Distributions }
310*8d741a5dSApple OSS Distributions return 0;
311*8d741a5dSApple OSS Distributions }
312*8d741a5dSApple OSS Distributions
313*8d741a5dSApple OSS Distributions static inline uintptr_t
ksancov_edge_addr(ksancov_edgemap_t * kemap,size_t idx)314*8d741a5dSApple OSS Distributions ksancov_edge_addr(ksancov_edgemap_t *kemap, size_t idx)
315*8d741a5dSApple OSS Distributions {
316*8d741a5dSApple OSS Distributions assert(kemap);
317*8d741a5dSApple OSS Distributions if (idx >= kemap->ke_nedges) {
318*8d741a5dSApple OSS Distributions return 0;
319*8d741a5dSApple OSS Distributions }
320*8d741a5dSApple OSS Distributions return kemap->ke_addrs[idx];
321*8d741a5dSApple OSS Distributions }
322*8d741a5dSApple OSS Distributions
323*8d741a5dSApple OSS Distributions static inline size_t
ksancov_trace_max_ent(ksancov_trace_t * trace)324*8d741a5dSApple OSS Distributions ksancov_trace_max_ent(ksancov_trace_t *trace)
325*8d741a5dSApple OSS Distributions {
326*8d741a5dSApple OSS Distributions assert(trace);
327*8d741a5dSApple OSS Distributions return trace->kt_maxent;
328*8d741a5dSApple OSS Distributions }
329*8d741a5dSApple OSS Distributions
330*8d741a5dSApple OSS Distributions static inline size_t
ksancov_trace_head(ksancov_trace_t * trace)331*8d741a5dSApple OSS Distributions ksancov_trace_head(ksancov_trace_t *trace)
332*8d741a5dSApple OSS Distributions {
333*8d741a5dSApple OSS Distributions assert(trace);
334*8d741a5dSApple OSS Distributions size_t maxent = trace->kt_maxent;
335*8d741a5dSApple OSS Distributions size_t head = atomic_load_explicit(&trace->kt_head, memory_order_acquire);
336*8d741a5dSApple OSS Distributions return head < maxent ? head : maxent;
337*8d741a5dSApple OSS Distributions }
338*8d741a5dSApple OSS Distributions
339*8d741a5dSApple OSS Distributions static inline uintptr_t
ksancov_trace_entry(ksancov_trace_t * trace,size_t i)340*8d741a5dSApple OSS Distributions ksancov_trace_entry(ksancov_trace_t *trace, size_t i)
341*8d741a5dSApple OSS Distributions {
342*8d741a5dSApple OSS Distributions assert(trace);
343*8d741a5dSApple OSS Distributions assert(trace->kt_hdr.kh_magic == KSANCOV_TRACE_MAGIC);
344*8d741a5dSApple OSS Distributions if (i >= trace->kt_head) {
345*8d741a5dSApple OSS Distributions return 0;
346*8d741a5dSApple OSS Distributions }
347*8d741a5dSApple OSS Distributions
348*8d741a5dSApple OSS Distributions ksancov_trace_pc_ent_t *entries = (ksancov_trace_pc_ent_t *)trace->kt_entries;
349*8d741a5dSApple OSS Distributions return entries[i];
350*8d741a5dSApple OSS Distributions }
351*8d741a5dSApple OSS Distributions
352*8d741a5dSApple OSS Distributions static inline uintptr_t
ksancov_stksize_pc(ksancov_trace_t * trace,size_t i)353*8d741a5dSApple OSS Distributions ksancov_stksize_pc(ksancov_trace_t *trace, size_t i)
354*8d741a5dSApple OSS Distributions {
355*8d741a5dSApple OSS Distributions assert(trace);
356*8d741a5dSApple OSS Distributions assert(trace->kt_hdr.kh_magic == KSANCOV_STKSIZE_MAGIC);
357*8d741a5dSApple OSS Distributions if (i >= trace->kt_head) {
358*8d741a5dSApple OSS Distributions return 0;
359*8d741a5dSApple OSS Distributions }
360*8d741a5dSApple OSS Distributions
361*8d741a5dSApple OSS Distributions ksancov_trace_stksize_ent_t *entries = (ksancov_trace_stksize_ent_t *)trace->kt_entries;
362*8d741a5dSApple OSS Distributions return entries[i].pc;
363*8d741a5dSApple OSS Distributions }
364*8d741a5dSApple OSS Distributions
365*8d741a5dSApple OSS Distributions static inline uint32_t
ksancov_stksize_size(ksancov_trace_t * trace,size_t i)366*8d741a5dSApple OSS Distributions ksancov_stksize_size(ksancov_trace_t *trace, size_t i)
367*8d741a5dSApple OSS Distributions {
368*8d741a5dSApple OSS Distributions assert(trace);
369*8d741a5dSApple OSS Distributions assert(trace->kt_hdr.kh_magic == KSANCOV_STKSIZE_MAGIC);
370*8d741a5dSApple OSS Distributions if (i >= trace->kt_head) {
371*8d741a5dSApple OSS Distributions return 0;
372*8d741a5dSApple OSS Distributions }
373*8d741a5dSApple OSS Distributions
374*8d741a5dSApple OSS Distributions ksancov_trace_stksize_ent_t *entries = (ksancov_trace_stksize_ent_t *)trace->kt_entries;
375*8d741a5dSApple OSS Distributions return entries[i].stksize;
376*8d741a5dSApple OSS Distributions }
377*8d741a5dSApple OSS Distributions
378*8d741a5dSApple OSS Distributions /*
379*8d741a5dSApple OSS Distributions * On-demand control API
380*8d741a5dSApple OSS Distributions */
381*8d741a5dSApple OSS Distributions
382*8d741a5dSApple OSS Distributions static inline int
_ksancov_on_demand_operation(int fd,const char * bundle,ksancov_on_demand_operation_t op,struct ksancov_on_demand_msg * msg)383*8d741a5dSApple OSS Distributions _ksancov_on_demand_operation(int fd, const char *bundle, ksancov_on_demand_operation_t op, struct ksancov_on_demand_msg *msg)
384*8d741a5dSApple OSS Distributions {
385*8d741a5dSApple OSS Distributions int ret;
386*8d741a5dSApple OSS Distributions
387*8d741a5dSApple OSS Distributions msg->operation = op;
388*8d741a5dSApple OSS Distributions strlcpy(msg->bundle, bundle, sizeof(msg->bundle));
389*8d741a5dSApple OSS Distributions
390*8d741a5dSApple OSS Distributions ret = ioctl(fd, KSANCOV_IOC_ON_DEMAND, msg);
391*8d741a5dSApple OSS Distributions if (ret == -1) {
392*8d741a5dSApple OSS Distributions return errno;
393*8d741a5dSApple OSS Distributions }
394*8d741a5dSApple OSS Distributions
395*8d741a5dSApple OSS Distributions return ret;
396*8d741a5dSApple OSS Distributions }
397*8d741a5dSApple OSS Distributions
398*8d741a5dSApple OSS Distributions /*
399*8d741a5dSApple OSS Distributions * Retrieve the value of the gate for a given module bundle ID.
400*8d741a5dSApple OSS Distributions */
401*8d741a5dSApple OSS Distributions static inline int
ksancov_on_demand_get_gate(int fd,const char * bundle,uint64_t * gate)402*8d741a5dSApple OSS Distributions ksancov_on_demand_get_gate(int fd, const char *bundle, uint64_t *gate)
403*8d741a5dSApple OSS Distributions {
404*8d741a5dSApple OSS Distributions assert(gate);
405*8d741a5dSApple OSS Distributions
406*8d741a5dSApple OSS Distributions struct ksancov_on_demand_msg msg;
407*8d741a5dSApple OSS Distributions int ret = _ksancov_on_demand_operation(fd, bundle, KS_OD_GET_GATE, &msg);
408*8d741a5dSApple OSS Distributions if (ret == 0) {
409*8d741a5dSApple OSS Distributions *gate = msg.gate;
410*8d741a5dSApple OSS Distributions }
411*8d741a5dSApple OSS Distributions return ret;
412*8d741a5dSApple OSS Distributions }
413*8d741a5dSApple OSS Distributions
414*8d741a5dSApple OSS Distributions /*
415*8d741a5dSApple OSS Distributions * Set the value of the gate for a given module bundle ID.
416*8d741a5dSApple OSS Distributions *
417*8d741a5dSApple OSS Distributions * Any non-zero value enables the invocation of the sanitizer coverage callbacks
418*8d741a5dSApple OSS Distributions * inserted in the specified module.
419*8d741a5dSApple OSS Distributions */
420*8d741a5dSApple OSS Distributions static inline int
ksancov_on_demand_set_gate(int fd,const char * bundle,uint64_t value)421*8d741a5dSApple OSS Distributions ksancov_on_demand_set_gate(int fd, const char *bundle, uint64_t value)
422*8d741a5dSApple OSS Distributions {
423*8d741a5dSApple OSS Distributions struct ksancov_on_demand_msg msg = {};
424*8d741a5dSApple OSS Distributions msg.gate = value;
425*8d741a5dSApple OSS Distributions return _ksancov_on_demand_operation(fd, bundle, KS_OD_SET_GATE, &msg);
426*8d741a5dSApple OSS Distributions }
427*8d741a5dSApple OSS Distributions
428*8d741a5dSApple OSS Distributions /*
429*8d741a5dSApple OSS Distributions * Get the guards range for a specified module.
430*8d741a5dSApple OSS Distributions */
431*8d741a5dSApple OSS Distributions static inline int
ksancov_on_demand_get_range(int fd,const char * bundle,uint32_t * start,uint32_t * stop)432*8d741a5dSApple OSS Distributions ksancov_on_demand_get_range(int fd, const char *bundle, uint32_t *start, uint32_t *stop)
433*8d741a5dSApple OSS Distributions {
434*8d741a5dSApple OSS Distributions assert(start && stop);
435*8d741a5dSApple OSS Distributions
436*8d741a5dSApple OSS Distributions struct ksancov_on_demand_msg msg = {};
437*8d741a5dSApple OSS Distributions int ret = _ksancov_on_demand_operation(fd, bundle, KS_OD_GET_RANGE, &msg);
438*8d741a5dSApple OSS Distributions if (ret == 0) {
439*8d741a5dSApple OSS Distributions *start = msg.range.start;
440*8d741a5dSApple OSS Distributions *stop = msg.range.stop;
441*8d741a5dSApple OSS Distributions }
442*8d741a5dSApple OSS Distributions return ret;
443*8d741a5dSApple OSS Distributions }
444*8d741a5dSApple OSS Distributions
445*8d741a5dSApple OSS Distributions #endif /* _KSANCOV_H_ */
446