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