1*f6217f89SApple OSS Distributions /*
2*f6217f89SApple OSS Distributions * Copyright (c) 2019 Apple Inc. All rights reserved.
3*f6217f89SApple OSS Distributions *
4*f6217f89SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*f6217f89SApple OSS Distributions *
6*f6217f89SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*f6217f89SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*f6217f89SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*f6217f89SApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*f6217f89SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*f6217f89SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*f6217f89SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*f6217f89SApple OSS Distributions * terms of an Apple operating system software license agreement.
14*f6217f89SApple OSS Distributions *
15*f6217f89SApple OSS Distributions * Please obtain a copy of the License at
16*f6217f89SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*f6217f89SApple OSS Distributions *
18*f6217f89SApple OSS Distributions * The Original Code and all software distributed under the License are
19*f6217f89SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*f6217f89SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*f6217f89SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*f6217f89SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*f6217f89SApple OSS Distributions * Please see the License for the specific language governing rights and
24*f6217f89SApple OSS Distributions * limitations under the License.
25*f6217f89SApple OSS Distributions *
26*f6217f89SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*f6217f89SApple OSS Distributions */
28*f6217f89SApple OSS Distributions
29*f6217f89SApple OSS Distributions #include <stdlib.h>
30*f6217f89SApple OSS Distributions #include <stdio.h>
31*f6217f89SApple OSS Distributions #include <stdint.h>
32*f6217f89SApple OSS Distributions #include <stdbool.h>
33*f6217f89SApple OSS Distributions #include <stdatomic.h>
34*f6217f89SApple OSS Distributions #include <errno.h>
35*f6217f89SApple OSS Distributions
36*f6217f89SApple OSS Distributions #include <fcntl.h>
37*f6217f89SApple OSS Distributions #include <sys/ioctl.h>
38*f6217f89SApple OSS Distributions
39*f6217f89SApple OSS Distributions #include <getopt.h>
40*f6217f89SApple OSS Distributions #include <unistd.h>
41*f6217f89SApple OSS Distributions
42*f6217f89SApple OSS Distributions #include "ksancov.h"
43*f6217f89SApple OSS Distributions
44*f6217f89SApple OSS Distributions static void
usage(void)45*f6217f89SApple OSS Distributions usage(void)
46*f6217f89SApple OSS Distributions {
47*f6217f89SApple OSS Distributions fprintf(stderr,
48*f6217f89SApple OSS Distributions "usage: ./ksancov [OPTIONS]\n\n"
49*f6217f89SApple OSS Distributions " -t | --trace use trace (PC log) mode [default]\n"
50*f6217f89SApple OSS Distributions " -s | --stksize use trace (PC log) with stack size mode\n"
51*f6217f89SApple OSS Distributions " -c | --counters use edge counter mode\n"
52*f6217f89SApple OSS Distributions " -p | --cmptrace use trace (CMP log) mode\n"
53*f6217f89SApple OSS Distributions " -n | --entries <n> override max entries in trace log\n"
54*f6217f89SApple OSS Distributions " -x | --exec <path> instrument execution of binary at <path>\n"
55*f6217f89SApple OSS Distributions " -b | --bundle <b> bundle for on-demand tracing\n");
56*f6217f89SApple OSS Distributions exit(1);
57*f6217f89SApple OSS Distributions }
58*f6217f89SApple OSS Distributions
59*f6217f89SApple OSS Distributions /*
60*f6217f89SApple OSS Distributions * Structure holds all data required for coverage collection.
61*f6217f89SApple OSS Distributions */
62*f6217f89SApple OSS Distributions typedef struct ksancov_state {
63*f6217f89SApple OSS Distributions ksancov_mode_t ks_mode;
64*f6217f89SApple OSS Distributions ksancov_edgemap_t *ks_edgemap;
65*f6217f89SApple OSS Distributions union {
66*f6217f89SApple OSS Distributions ksancov_header_t *ks_header;
67*f6217f89SApple OSS Distributions ksancov_trace_t *ks_trace;
68*f6217f89SApple OSS Distributions ksancov_counters_t *ks_counters;
69*f6217f89SApple OSS Distributions };
70*f6217f89SApple OSS Distributions ksancov_cmps_mode_t ks_cmps_mode;
71*f6217f89SApple OSS Distributions union {
72*f6217f89SApple OSS Distributions ksancov_header_t *ks_cmps_header;
73*f6217f89SApple OSS Distributions ksancov_trace_t *ks_cmps_trace;
74*f6217f89SApple OSS Distributions };
75*f6217f89SApple OSS Distributions } ksancov_state_t;
76*f6217f89SApple OSS Distributions
77*f6217f89SApple OSS Distributions /*
78*f6217f89SApple OSS Distributions * Configures ksancov device for selected coverage mode.
79*f6217f89SApple OSS Distributions */
80*f6217f89SApple OSS Distributions static int
ksancov_set_mode(int fd,ksancov_mode_t mode,int max_entries)81*f6217f89SApple OSS Distributions ksancov_set_mode(int fd, ksancov_mode_t mode, int max_entries)
82*f6217f89SApple OSS Distributions {
83*f6217f89SApple OSS Distributions int ret = 0;
84*f6217f89SApple OSS Distributions
85*f6217f89SApple OSS Distributions switch (mode) {
86*f6217f89SApple OSS Distributions case KS_MODE_TRACE:
87*f6217f89SApple OSS Distributions ret = ksancov_mode_trace(fd, max_entries);
88*f6217f89SApple OSS Distributions break;
89*f6217f89SApple OSS Distributions case KS_MODE_STKSIZE:
90*f6217f89SApple OSS Distributions ret = ksancov_mode_stksize(fd, max_entries);
91*f6217f89SApple OSS Distributions break;
92*f6217f89SApple OSS Distributions case KS_MODE_COUNTERS:
93*f6217f89SApple OSS Distributions ret = ksancov_mode_counters(fd);
94*f6217f89SApple OSS Distributions break;
95*f6217f89SApple OSS Distributions default:
96*f6217f89SApple OSS Distributions perror("ksancov unsupported mode\n");
97*f6217f89SApple OSS Distributions return ENOTSUP;
98*f6217f89SApple OSS Distributions }
99*f6217f89SApple OSS Distributions
100*f6217f89SApple OSS Distributions return ret;
101*f6217f89SApple OSS Distributions }
102*f6217f89SApple OSS Distributions
103*f6217f89SApple OSS Distributions /*
104*f6217f89SApple OSS Distributions * Configures ksancov device for selected comparison mode.
105*f6217f89SApple OSS Distributions */
106*f6217f89SApple OSS Distributions static int
ksancov_cmps_set_mode(int fd,ksancov_cmps_mode_t mode,int max_entries)107*f6217f89SApple OSS Distributions ksancov_cmps_set_mode(int fd, ksancov_cmps_mode_t mode, int max_entries)
108*f6217f89SApple OSS Distributions {
109*f6217f89SApple OSS Distributions int ret = 0;
110*f6217f89SApple OSS Distributions
111*f6217f89SApple OSS Distributions switch (mode) {
112*f6217f89SApple OSS Distributions case KS_CMPS_MODE_TRACE:
113*f6217f89SApple OSS Distributions ret = ksancov_cmps_mode_trace(fd, max_entries, false);
114*f6217f89SApple OSS Distributions break;
115*f6217f89SApple OSS Distributions case KS_CMPS_MODE_TRACE_FUNC:
116*f6217f89SApple OSS Distributions ret = ksancov_cmps_mode_trace(fd, max_entries, true);
117*f6217f89SApple OSS Distributions break;
118*f6217f89SApple OSS Distributions default:
119*f6217f89SApple OSS Distributions perror("ksancov unsupported cmps mode\n");
120*f6217f89SApple OSS Distributions return ENOTSUP;
121*f6217f89SApple OSS Distributions }
122*f6217f89SApple OSS Distributions
123*f6217f89SApple OSS Distributions return ret;
124*f6217f89SApple OSS Distributions }
125*f6217f89SApple OSS Distributions
126*f6217f89SApple OSS Distributions /*
127*f6217f89SApple OSS Distributions * Initialize coverage state from provided options. Shared mappings with kernel are established
128*f6217f89SApple OSS Distributions * here.
129*f6217f89SApple OSS Distributions */
130*f6217f89SApple OSS Distributions static int
ksancov_init_state(int fd,ksancov_mode_t mode,ksancov_cmps_mode_t cmps_mode,int max_entries,ksancov_state_t * state)131*f6217f89SApple OSS Distributions ksancov_init_state(int fd, ksancov_mode_t mode, ksancov_cmps_mode_t cmps_mode, int max_entries, ksancov_state_t *state)
132*f6217f89SApple OSS Distributions {
133*f6217f89SApple OSS Distributions uintptr_t addr;
134*f6217f89SApple OSS Distributions size_t sz;
135*f6217f89SApple OSS Distributions int ret = 0;
136*f6217f89SApple OSS Distributions
137*f6217f89SApple OSS Distributions /* Map edge map into process address space. */
138*f6217f89SApple OSS Distributions ret = ksancov_map_edgemap(fd, &addr, NULL);
139*f6217f89SApple OSS Distributions if (ret) {
140*f6217f89SApple OSS Distributions perror("ksancov map counters\n");
141*f6217f89SApple OSS Distributions return ret;
142*f6217f89SApple OSS Distributions }
143*f6217f89SApple OSS Distributions state->ks_edgemap = (void *)addr;
144*f6217f89SApple OSS Distributions fprintf(stderr, "nedges (edgemap) = %u\n", state->ks_edgemap->ke_nedges);
145*f6217f89SApple OSS Distributions
146*f6217f89SApple OSS Distributions /* Setup selected tracing mode. */
147*f6217f89SApple OSS Distributions ret = ksancov_set_mode(fd, mode, max_entries);
148*f6217f89SApple OSS Distributions if (ret) {
149*f6217f89SApple OSS Distributions perror("ksancov set mode\n");
150*f6217f89SApple OSS Distributions return ret;
151*f6217f89SApple OSS Distributions }
152*f6217f89SApple OSS Distributions
153*f6217f89SApple OSS Distributions /* Map buffer for selected mode into process address space. */
154*f6217f89SApple OSS Distributions ret = ksancov_map(fd, &addr, &sz);
155*f6217f89SApple OSS Distributions if (ret) {
156*f6217f89SApple OSS Distributions perror("ksancov map");
157*f6217f89SApple OSS Distributions return ret;
158*f6217f89SApple OSS Distributions }
159*f6217f89SApple OSS Distributions fprintf(stderr, "mapped to 0x%lx + %lu\n", addr, sz);
160*f6217f89SApple OSS Distributions
161*f6217f89SApple OSS Distributions /* Finalize state members. */
162*f6217f89SApple OSS Distributions state->ks_mode = mode;
163*f6217f89SApple OSS Distributions state->ks_header = (void *)addr;
164*f6217f89SApple OSS Distributions
165*f6217f89SApple OSS Distributions if (mode == KS_MODE_COUNTERS) {
166*f6217f89SApple OSS Distributions fprintf(stderr, "nedges (counters) = %u\n", state->ks_counters->kc_nedges);
167*f6217f89SApple OSS Distributions } else {
168*f6217f89SApple OSS Distributions fprintf(stderr, "maxpcs = %lu\n", ksancov_trace_max_ent(state->ks_trace));
169*f6217f89SApple OSS Distributions }
170*f6217f89SApple OSS Distributions
171*f6217f89SApple OSS Distributions if (cmps_mode == KS_CMPS_MODE_NONE) {
172*f6217f89SApple OSS Distributions state->ks_cmps_mode = cmps_mode;
173*f6217f89SApple OSS Distributions state->ks_cmps_header = NULL;
174*f6217f89SApple OSS Distributions return ret;
175*f6217f89SApple OSS Distributions }
176*f6217f89SApple OSS Distributions
177*f6217f89SApple OSS Distributions /* Setup selected comparison tracing mode. */
178*f6217f89SApple OSS Distributions ret = ksancov_cmps_set_mode(fd, cmps_mode, max_entries);
179*f6217f89SApple OSS Distributions if (ret) {
180*f6217f89SApple OSS Distributions perror("ksancov cmps set mode\n");
181*f6217f89SApple OSS Distributions return ret;
182*f6217f89SApple OSS Distributions }
183*f6217f89SApple OSS Distributions
184*f6217f89SApple OSS Distributions /* Map buffer for selected mode into process address space. */
185*f6217f89SApple OSS Distributions ret = ksancov_cmps_map(fd, &addr, &sz);
186*f6217f89SApple OSS Distributions if (ret) {
187*f6217f89SApple OSS Distributions perror("ksancov cmps map");
188*f6217f89SApple OSS Distributions return ret;
189*f6217f89SApple OSS Distributions }
190*f6217f89SApple OSS Distributions fprintf(stderr, "cmps mapped to 0x%lx + %lu\n", addr, sz);
191*f6217f89SApple OSS Distributions
192*f6217f89SApple OSS Distributions /* Finalize state members. */
193*f6217f89SApple OSS Distributions state->ks_cmps_mode = cmps_mode;
194*f6217f89SApple OSS Distributions state->ks_cmps_header = (void *)addr;
195*f6217f89SApple OSS Distributions
196*f6217f89SApple OSS Distributions fprintf(stderr, "maxcmps = %lu\n", ksancov_trace_max_ent(state->ks_cmps_trace));
197*f6217f89SApple OSS Distributions
198*f6217f89SApple OSS Distributions return ret;
199*f6217f89SApple OSS Distributions }
200*f6217f89SApple OSS Distributions
201*f6217f89SApple OSS Distributions static int
ksancov_print_state(ksancov_state_t * state)202*f6217f89SApple OSS Distributions ksancov_print_state(ksancov_state_t *state)
203*f6217f89SApple OSS Distributions {
204*f6217f89SApple OSS Distributions if (state->ks_mode == KS_MODE_COUNTERS) {
205*f6217f89SApple OSS Distributions for (size_t i = 0; i < state->ks_counters->kc_nedges; i++) {
206*f6217f89SApple OSS Distributions size_t hits = state->ks_counters->kc_hits[i];
207*f6217f89SApple OSS Distributions if (hits) {
208*f6217f89SApple OSS Distributions fprintf(stderr, "0x%lx: %lu hits [idx %lu]\n",
209*f6217f89SApple OSS Distributions ksancov_edge_addr(state->ks_edgemap, i), hits, i);
210*f6217f89SApple OSS Distributions }
211*f6217f89SApple OSS Distributions }
212*f6217f89SApple OSS Distributions } else {
213*f6217f89SApple OSS Distributions size_t head = ksancov_trace_head(state->ks_trace);
214*f6217f89SApple OSS Distributions fprintf(stderr, "head = %lu\n", head);
215*f6217f89SApple OSS Distributions
216*f6217f89SApple OSS Distributions for (uint32_t i = 0; i < head; i++) {
217*f6217f89SApple OSS Distributions if (state->ks_mode == KS_MODE_TRACE) {
218*f6217f89SApple OSS Distributions fprintf(stderr, "0x%lx\n", ksancov_trace_entry(state->ks_trace, i));
219*f6217f89SApple OSS Distributions } else {
220*f6217f89SApple OSS Distributions fprintf(stderr, "0x%lx [size %u]\n", ksancov_stksize_pc(state->ks_trace, i),
221*f6217f89SApple OSS Distributions ksancov_stksize_size(state->ks_trace, i));
222*f6217f89SApple OSS Distributions }
223*f6217f89SApple OSS Distributions }
224*f6217f89SApple OSS Distributions }
225*f6217f89SApple OSS Distributions
226*f6217f89SApple OSS Distributions if (state->ks_cmps_mode == KS_CMPS_MODE_TRACE || state->ks_cmps_mode == KS_CMPS_MODE_TRACE_FUNC) {
227*f6217f89SApple OSS Distributions static const char *type_map[KCOV_CMP_SIZE8 + 1] = {
228*f6217f89SApple OSS Distributions "8 bits", NULL, "16 bits", NULL, "32 bits",
229*f6217f89SApple OSS Distributions NULL, "64 bits"
230*f6217f89SApple OSS Distributions };
231*f6217f89SApple OSS Distributions
232*f6217f89SApple OSS Distributions size_t head = ksancov_trace_head(state->ks_cmps_trace);
233*f6217f89SApple OSS Distributions fprintf(stderr, "cmps head = %lu\n", head);
234*f6217f89SApple OSS Distributions
235*f6217f89SApple OSS Distributions for (uint32_t i = 0; i < head;) {
236*f6217f89SApple OSS Distributions ksancov_cmps_trace_ent_t *entry = ksancov_cmps_trace_entry(state->ks_cmps_trace, i);
237*f6217f89SApple OSS Distributions if (KCOV_CMP_IS_FUNC(entry->type)) {
238*f6217f89SApple OSS Distributions size_t space = ksancov_cmps_trace_func_space(entry->len1_func, entry->len2_func);
239*f6217f89SApple OSS Distributions i += space / sizeof(ksancov_cmps_trace_ent_t);
240*f6217f89SApple OSS Distributions fprintf(stderr, "0x%llx [func %u %u] '%s' '%s'\n", entry->pc, entry->len1_func, entry->len2_func,
241*f6217f89SApple OSS Distributions ksancov_cmps_trace_func_arg1(entry),
242*f6217f89SApple OSS Distributions ksancov_cmps_trace_func_arg2(entry));
243*f6217f89SApple OSS Distributions } else {
244*f6217f89SApple OSS Distributions uint64_t type = entry->type & KCOV_CMP_SIZE_MASK;
245*f6217f89SApple OSS Distributions fprintf(stderr, "0x%llx [%s] 0x%llx 0x%llx\n", entry->pc, type_map[type], entry->args[0], entry->args[1]);
246*f6217f89SApple OSS Distributions ++i;
247*f6217f89SApple OSS Distributions }
248*f6217f89SApple OSS Distributions }
249*f6217f89SApple OSS Distributions }
250*f6217f89SApple OSS Distributions
251*f6217f89SApple OSS Distributions return 0;
252*f6217f89SApple OSS Distributions }
253*f6217f89SApple OSS Distributions
254*f6217f89SApple OSS Distributions static int
ksancov_on_demand_set_enabled(int fd,const char * bundle,bool enabled)255*f6217f89SApple OSS Distributions ksancov_on_demand_set_enabled(int fd, const char *bundle, bool enabled)
256*f6217f89SApple OSS Distributions {
257*f6217f89SApple OSS Distributions int ret = 0;
258*f6217f89SApple OSS Distributions const uint64_t gate = enabled ? 1 : 0;
259*f6217f89SApple OSS Distributions if (bundle) {
260*f6217f89SApple OSS Distributions fprintf(stderr, "setting on-demand gate for '%s': %llu\n", bundle, gate);
261*f6217f89SApple OSS Distributions ret = ksancov_on_demand_set_gate(fd, bundle, gate);
262*f6217f89SApple OSS Distributions if (ret) {
263*f6217f89SApple OSS Distributions perror("ksancov on demand");
264*f6217f89SApple OSS Distributions }
265*f6217f89SApple OSS Distributions }
266*f6217f89SApple OSS Distributions return ret;
267*f6217f89SApple OSS Distributions }
268*f6217f89SApple OSS Distributions
269*f6217f89SApple OSS Distributions int
main(int argc,char * argv[])270*f6217f89SApple OSS Distributions main(int argc, char *argv[])
271*f6217f89SApple OSS Distributions {
272*f6217f89SApple OSS Distributions ksancov_mode_t ksan_mode = KS_MODE_NONE;
273*f6217f89SApple OSS Distributions ksancov_cmps_mode_t ksan_cmps_mode = KS_CMPS_MODE_NONE;
274*f6217f89SApple OSS Distributions ksancov_state_t ksan_state = {0};
275*f6217f89SApple OSS Distributions
276*f6217f89SApple OSS Distributions int ret;
277*f6217f89SApple OSS Distributions size_t max_entries = 64UL * 1024;
278*f6217f89SApple OSS Distributions char *path = NULL;
279*f6217f89SApple OSS Distributions char *od_bundle = NULL;
280*f6217f89SApple OSS Distributions
281*f6217f89SApple OSS Distributions static struct option opts[] = {
282*f6217f89SApple OSS Distributions { "entries", required_argument, NULL, 'n' },
283*f6217f89SApple OSS Distributions { "exec", required_argument, NULL, 'x' },
284*f6217f89SApple OSS Distributions
285*f6217f89SApple OSS Distributions { "trace", no_argument, NULL, 't' },
286*f6217f89SApple OSS Distributions { "counters", no_argument, NULL, 'c' },
287*f6217f89SApple OSS Distributions { "stksize", no_argument, NULL, 's' },
288*f6217f89SApple OSS Distributions { "cmptrace", no_argument, NULL, 'p' },
289*f6217f89SApple OSS Distributions
290*f6217f89SApple OSS Distributions { "bundle", required_argument, NULL, 'b' },
291*f6217f89SApple OSS Distributions
292*f6217f89SApple OSS Distributions { NULL, 0, NULL, 0 }
293*f6217f89SApple OSS Distributions };
294*f6217f89SApple OSS Distributions
295*f6217f89SApple OSS Distributions int ch;
296*f6217f89SApple OSS Distributions while ((ch = getopt_long(argc, argv, "tsn:x:cpb:", opts, NULL)) != -1) {
297*f6217f89SApple OSS Distributions switch (ch) {
298*f6217f89SApple OSS Distributions case 'n':
299*f6217f89SApple OSS Distributions max_entries = strtoul(optarg, NULL, 0);
300*f6217f89SApple OSS Distributions break;
301*f6217f89SApple OSS Distributions case 'x':
302*f6217f89SApple OSS Distributions path = optarg;
303*f6217f89SApple OSS Distributions break;
304*f6217f89SApple OSS Distributions case 't':
305*f6217f89SApple OSS Distributions ksan_mode = KS_MODE_TRACE;
306*f6217f89SApple OSS Distributions break;
307*f6217f89SApple OSS Distributions case 'c':
308*f6217f89SApple OSS Distributions ksan_mode = KS_MODE_COUNTERS;
309*f6217f89SApple OSS Distributions break;
310*f6217f89SApple OSS Distributions case 's':
311*f6217f89SApple OSS Distributions ksan_mode = KS_MODE_STKSIZE;
312*f6217f89SApple OSS Distributions break;
313*f6217f89SApple OSS Distributions case 'p':
314*f6217f89SApple OSS Distributions ksan_cmps_mode = KS_CMPS_MODE_TRACE_FUNC;
315*f6217f89SApple OSS Distributions break;
316*f6217f89SApple OSS Distributions case 'b':
317*f6217f89SApple OSS Distributions od_bundle = optarg;
318*f6217f89SApple OSS Distributions break;
319*f6217f89SApple OSS Distributions default:
320*f6217f89SApple OSS Distributions usage();
321*f6217f89SApple OSS Distributions }
322*f6217f89SApple OSS Distributions }
323*f6217f89SApple OSS Distributions
324*f6217f89SApple OSS Distributions int fd = ksancov_open();
325*f6217f89SApple OSS Distributions if (fd < 0) {
326*f6217f89SApple OSS Distributions perror("ksancov_open");
327*f6217f89SApple OSS Distributions return errno;
328*f6217f89SApple OSS Distributions }
329*f6217f89SApple OSS Distributions fprintf(stderr, "opened ksancov on fd %i\n", fd);
330*f6217f89SApple OSS Distributions
331*f6217f89SApple OSS Distributions /* Initialize ksancov state. */
332*f6217f89SApple OSS Distributions ret = ksancov_init_state(fd, ksan_mode, ksan_cmps_mode, max_entries, &ksan_state);
333*f6217f89SApple OSS Distributions if (ret) {
334*f6217f89SApple OSS Distributions perror("ksancov init\n");
335*f6217f89SApple OSS Distributions return ret;
336*f6217f89SApple OSS Distributions }
337*f6217f89SApple OSS Distributions
338*f6217f89SApple OSS Distributions /* Execute binary (when provided) with enabled coverage collection. Run getppid() otherwise. */
339*f6217f89SApple OSS Distributions if (path) {
340*f6217f89SApple OSS Distributions int pid = fork();
341*f6217f89SApple OSS Distributions if (pid == 0) {
342*f6217f89SApple OSS Distributions /* child */
343*f6217f89SApple OSS Distributions
344*f6217f89SApple OSS Distributions ret = ksancov_thread_self(fd);
345*f6217f89SApple OSS Distributions if (ret) {
346*f6217f89SApple OSS Distributions perror("ksancov thread");
347*f6217f89SApple OSS Distributions return ret;
348*f6217f89SApple OSS Distributions }
349*f6217f89SApple OSS Distributions
350*f6217f89SApple OSS Distributions ksancov_on_demand_set_enabled(fd, od_bundle, true);
351*f6217f89SApple OSS Distributions ksancov_reset(ksan_state.ks_header);
352*f6217f89SApple OSS Distributions ksancov_start(ksan_state.ks_header);
353*f6217f89SApple OSS Distributions if (ksan_state.ks_cmps_header) {
354*f6217f89SApple OSS Distributions ksancov_reset(ksan_state.ks_cmps_header);
355*f6217f89SApple OSS Distributions ksancov_start(ksan_state.ks_cmps_header);
356*f6217f89SApple OSS Distributions }
357*f6217f89SApple OSS Distributions ret = execl(path, path, 0);
358*f6217f89SApple OSS Distributions perror("execl");
359*f6217f89SApple OSS Distributions ksancov_on_demand_set_enabled(fd, od_bundle, false);
360*f6217f89SApple OSS Distributions
361*f6217f89SApple OSS Distributions exit(1);
362*f6217f89SApple OSS Distributions } else {
363*f6217f89SApple OSS Distributions /* parent */
364*f6217f89SApple OSS Distributions waitpid(pid, NULL, 0);
365*f6217f89SApple OSS Distributions ksancov_stop(ksan_state.ks_header);
366*f6217f89SApple OSS Distributions if (ksan_state.ks_cmps_header) {
367*f6217f89SApple OSS Distributions ksancov_stop(ksan_state.ks_cmps_header);
368*f6217f89SApple OSS Distributions }
369*f6217f89SApple OSS Distributions ksancov_on_demand_set_enabled(fd, od_bundle, false);
370*f6217f89SApple OSS Distributions }
371*f6217f89SApple OSS Distributions } else {
372*f6217f89SApple OSS Distributions ret = ksancov_thread_self(fd);
373*f6217f89SApple OSS Distributions if (ret) {
374*f6217f89SApple OSS Distributions perror("ksancov thread");
375*f6217f89SApple OSS Distributions return ret;
376*f6217f89SApple OSS Distributions }
377*f6217f89SApple OSS Distributions
378*f6217f89SApple OSS Distributions ksancov_on_demand_set_enabled(fd, od_bundle, true);
379*f6217f89SApple OSS Distributions ksancov_reset(ksan_state.ks_header);
380*f6217f89SApple OSS Distributions ksancov_start(ksan_state.ks_header);
381*f6217f89SApple OSS Distributions if (ksan_state.ks_cmps_header) {
382*f6217f89SApple OSS Distributions ksancov_reset(ksan_state.ks_cmps_header);
383*f6217f89SApple OSS Distributions ksancov_start(ksan_state.ks_cmps_header);
384*f6217f89SApple OSS Distributions }
385*f6217f89SApple OSS Distributions int ppid = getppid();
386*f6217f89SApple OSS Distributions ksancov_stop(ksan_state.ks_header);
387*f6217f89SApple OSS Distributions if (ksan_state.ks_cmps_header) {
388*f6217f89SApple OSS Distributions ksancov_stop(ksan_state.ks_cmps_header);
389*f6217f89SApple OSS Distributions }
390*f6217f89SApple OSS Distributions ksancov_on_demand_set_enabled(fd, od_bundle, false);
391*f6217f89SApple OSS Distributions fprintf(stderr, "ppid = %i\n", ppid);
392*f6217f89SApple OSS Distributions }
393*f6217f89SApple OSS Distributions
394*f6217f89SApple OSS Distributions /* Print report and cleanup. */
395*f6217f89SApple OSS Distributions ksancov_print_state(&ksan_state);
396*f6217f89SApple OSS Distributions ret = close(fd);
397*f6217f89SApple OSS Distributions fprintf(stderr, "close = %i\n", ret);
398*f6217f89SApple OSS Distributions
399*f6217f89SApple OSS Distributions return 0;
400*f6217f89SApple OSS Distributions }
401