]> git.saurik.com Git - apple/xnu.git/blame - san/tools/ksancov.c
xnu-6153.11.26.tar.gz
[apple/xnu.git] / san / tools / ksancov.c
CommitLineData
cb323159
A
1#if 0
2CC = clang
3 CFLAGS = -O3
4 $(MAKEFILE_LIST:.c = ):
5
6 ifeq (0, 1)
7 * /
8#endif
9
10/*
11 * Copyright (c) 2019 Apple Inc. All rights reserved.
12 *
13 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
14 *
15 * This file contains Original Code and/or Modifications of Original Code
16 * as defined in and that are subject to the Apple Public Source License
17 * Version 2.0 (the 'License'). You may not use this file except in
18 * compliance with the License. The rights granted to you under the License
19 * may not be used to create, or enable the creation or redistribution of,
20 * unlawful or unlicensed copies of an Apple operating system, or to
21 * circumvent, violate, or enable the circumvention or violation of, any
22 * terms of an Apple operating system software license agreement.
23 *
24 * Please obtain a copy of the License at
25 * http://www.opensource.apple.com/apsl/ and read it before using this file.
26 *
27 * The Original Code and all software distributed under the License are
28 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
29 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
30 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
31 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
32 * Please see the License for the specific language governing rights and
33 * limitations under the License.
34 *
35 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
36 */
37
38#include <stdlib.h>
39#include <stdio.h>
40#include <stdint.h>
41#include <stdbool.h>
42#include <stdatomic.h>
43#include <errno.h>
44
45#include <fcntl.h>
46#include <sys/ioctl.h>
47
48#include <getopt.h>
49
50#include "../ksancov.h"
51
52 static void
53 usage(void)
54 {
55 fprintf(stderr,
56 "usage: ./ksancov [OPTIONS]\n\n"
57 " -t | --trace use trace (PC log) mode [default]\n"
58 " -c | --counters use edge counter mode\n"
59 " -n | --entries <n> override max entries in trace log\n"
60 " -x | --exec <path> instrument execution of binary at <path>\n");
61 exit(1);
62 }
63
64 int
65 main(int argc, char *argv[])
66 {
67 struct ksancov_trace *trace = NULL;
68 struct ksancov_counters *counters = NULL;
69 struct ksancov_header *header = NULL;
70
71 int ret;
72 size_t max_entries = 64UL * 1024;
73 char *path = NULL;
74 bool docounters = false;
75
76 struct option opts[] = {
77 { "entries", required_argument, NULL, 'n' },
78 { "exec", required_argument, NULL, 'x' },
79
80 { "trace", no_argument, NULL, 't' },
81 { "counters", no_argument, NULL, 'c' },
82
83 { NULL, 0, NULL, 0 }
84 };
85
86 int ch;
87 while ((ch = getopt_long(argc, argv, "tn:x:c", opts, NULL)) != -1) {
88 switch (ch) {
89 case 'n':
90 max_entries = strtoul(optarg, NULL, 0);
91 break;
92 case 'x':
93 path = optarg;
94 break;
95 case 't':
96 docounters = false;
97 break;
98 case 'c':
99 docounters = true;
100 break;
101 default:
102 usage();
103 }
104 ;
105 }
106
107 int fd;
108 uintptr_t addr;
109 size_t sz;
110
111 fd = ksancov_open();
112 if (fd < 0) {
113 perror("ksancov_open");
114 return errno;
115 }
116 fprintf(stderr, "opened ksancov on fd %i\n", fd);
117
118 uintptr_t e;
119 ret = ksancov_map_edgemap(fd, &e, NULL);
120 if (ret) {
121 perror("ksancov map counters\n");
122 return ret;
123 }
124 struct ksancov_edgemap *map = (void *)e;
125 fprintf(stderr, "nedges (edgemap) = %u\n", map->nedges);
126
127 if (docounters) {
128 ret = ksancov_mode_counters(fd);
129 if (ret) {
130 perror("ksancov set mode\n");
131 return ret;
132 }
133 } else {
134 ret = ksancov_mode_trace(fd, max_entries);
135 if (ret) {
136 perror("ksancov set mode\n");
137 return ret;
138 }
139 }
140
141 ret = ksancov_map(fd, &addr, &sz);
142 if (ret) {
143 perror("ksancov map");
144 return ret;
145 }
146 fprintf(stderr, "mapped to 0x%lx + %lu\n", addr, sz);
147
148 if (docounters) {
149 counters = (void *)addr;
150 fprintf(stderr, "nedges (counters) = %u\n", counters->nedges);
151 } else {
152 trace = (void *)addr;
153 fprintf(stderr, "maxpcs = %lu\n", ksancov_trace_max_pcs(trace));
154 }
155 header = (void *)addr;
156
157 if (path) {
158 int pid = fork();
159 if (pid == 0) {
160 /* child */
161
162 ret = ksancov_thread_self(fd);
163 if (ret) {
164 perror("ksancov thread");
165 return ret;
166 }
167
168 ksancov_reset(header);
169 ksancov_start(header);
170 ret = execl(path, path, 0);
171 perror("execl");
172
173 exit(1);
174 } else {
175 /* parent */
176 waitpid(pid, NULL, 0);
177 ksancov_stop(header);
178 }
179 } else {
180 ret = ksancov_thread_self(fd);
181 if (ret) {
182 perror("ksancov thread");
183 return ret;
184 }
185
186 ksancov_reset(header);
187 ksancov_start(header);
188 int ppid = getppid();
189 ksancov_stop(header);
190 fprintf(stderr, "ppid = %i\n", ppid);
191 }
192
193 if (docounters) {
194 for (size_t i = 0; i < counters->nedges; i++) {
195 size_t hits = counters->hits[i];
196 if (hits) {
197 fprintf(stderr, "0x%lx: %lu hits [idx %lu]\n", ksancov_edge_addr(map, i), hits, i);
198 }
199 }
200 } else {
201 size_t head = ksancov_trace_head(trace);
202 fprintf(stderr, "head = %lu\n", head);
203 for (uint32_t i = 0; i < head; i++) {
204 uintptr_t pc = ksancov_trace_entry(trace, i);
205 fprintf(stderr, "0x%lx\n", pc);
206 }
207 }
208
209 ret = close(fd);
210 fprintf(stderr, "close = %i\n", ret);
211
212 return 0;
213 }
214
215/*
216 * endif
217 # */