1*fdd8201dSApple OSS Distributions // Copyright (c) 2020-2021 Apple Inc. All rights reserved.
2*fdd8201dSApple OSS Distributions
3*fdd8201dSApple OSS Distributions #include <darwintest.h>
4*fdd8201dSApple OSS Distributions #include <darwintest_utils.h>
5*fdd8201dSApple OSS Distributions #include <dispatch/dispatch.h>
6*fdd8201dSApple OSS Distributions #include <inttypes.h>
7*fdd8201dSApple OSS Distributions #include <ktrace/session.h>
8*fdd8201dSApple OSS Distributions #include <ktrace/private.h>
9*fdd8201dSApple OSS Distributions #include <kperf/kperf.h>
10*fdd8201dSApple OSS Distributions #include <mach/clock_types.h>
11*fdd8201dSApple OSS Distributions #include <mach/dyld_kernel.h>
12*fdd8201dSApple OSS Distributions #include <mach/host_info.h>
13*fdd8201dSApple OSS Distributions #include <mach/mach.h>
14*fdd8201dSApple OSS Distributions #include <mach/mach_init.h>
15*fdd8201dSApple OSS Distributions #include <mach/task.h>
16*fdd8201dSApple OSS Distributions #include <os/assumes.h>
17*fdd8201dSApple OSS Distributions #include <stdlib.h>
18*fdd8201dSApple OSS Distributions #include <sys/kdebug.h>
19*fdd8201dSApple OSS Distributions #include <sys/kdebug_signpost.h>
20*fdd8201dSApple OSS Distributions #include <sys/resource_private.h>
21*fdd8201dSApple OSS Distributions #include <sys/sysctl.h>
22*fdd8201dSApple OSS Distributions #include <stdint.h>
23*fdd8201dSApple OSS Distributions #include <TargetConditionals.h>
24*fdd8201dSApple OSS Distributions
25*fdd8201dSApple OSS Distributions #include "ktrace_helpers.h"
26*fdd8201dSApple OSS Distributions #include "test_utils.h"
27*fdd8201dSApple OSS Distributions #include "ktrace_meta.h"
28*fdd8201dSApple OSS Distributions
29*fdd8201dSApple OSS Distributions #define KDBG_TEST_MACROS 1
30*fdd8201dSApple OSS Distributions #define KDBG_TEST_OLD_TIMES 2
31*fdd8201dSApple OSS Distributions #define KDBG_TEST_FUTURE_TIMES 3
32*fdd8201dSApple OSS Distributions #define KDBG_TEST_IOP_SYNC_FLUSH 4
33*fdd8201dSApple OSS Distributions
34*fdd8201dSApple OSS Distributions #pragma mark kdebug syscalls
35*fdd8201dSApple OSS Distributions
36*fdd8201dSApple OSS Distributions #define TRACE_DEBUGID (0xfedfed00U)
37*fdd8201dSApple OSS Distributions
38*fdd8201dSApple OSS Distributions T_DECL(kdebug_trace_syscall, "test that kdebug_trace(2) emits correct events")
39*fdd8201dSApple OSS Distributions {
40*fdd8201dSApple OSS Distributions start_controlling_ktrace();
41*fdd8201dSApple OSS Distributions
42*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
43*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "created session");
44*fdd8201dSApple OSS Distributions ktrace_set_collection_interval(s, 200);
45*fdd8201dSApple OSS Distributions
46*fdd8201dSApple OSS Distributions __block int events_seen = 0;
47*fdd8201dSApple OSS Distributions ktrace_events_single(s, TRACE_DEBUGID, ^void (struct trace_point *tp) {
48*fdd8201dSApple OSS Distributions events_seen++;
49*fdd8201dSApple OSS Distributions T_PASS("saw traced event");
50*fdd8201dSApple OSS Distributions
51*fdd8201dSApple OSS Distributions if (ktrace_is_kernel_64_bit(s)) {
52*fdd8201dSApple OSS Distributions T_EXPECT_EQ(tp->arg1, UINT64_C(0xfeedfacefeedface),
53*fdd8201dSApple OSS Distributions "argument 1 of traced event is correct");
54*fdd8201dSApple OSS Distributions } else {
55*fdd8201dSApple OSS Distributions T_EXPECT_EQ(tp->arg1, UINT64_C(0xfeedface),
56*fdd8201dSApple OSS Distributions "argument 1 of traced event is correct");
57*fdd8201dSApple OSS Distributions }
58*fdd8201dSApple OSS Distributions T_EXPECT_EQ(tp->arg2, 2ULL, "argument 2 of traced event is correct");
59*fdd8201dSApple OSS Distributions T_EXPECT_EQ(tp->arg3, 3ULL, "argument 3 of traced event is correct");
60*fdd8201dSApple OSS Distributions T_EXPECT_EQ(tp->arg4, 4ULL, "argument 4 of traced event is correct");
61*fdd8201dSApple OSS Distributions
62*fdd8201dSApple OSS Distributions ktrace_end(s, 1);
63*fdd8201dSApple OSS Distributions });
64*fdd8201dSApple OSS Distributions
65*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^{
66*fdd8201dSApple OSS Distributions T_EXPECT_GE(events_seen, 1, NULL);
67*fdd8201dSApple OSS Distributions ktrace_session_destroy(s);
68*fdd8201dSApple OSS Distributions T_END;
69*fdd8201dSApple OSS Distributions });
70*fdd8201dSApple OSS Distributions
71*fdd8201dSApple OSS Distributions ktrace_filter_pid(s, getpid());
72*fdd8201dSApple OSS Distributions
73*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_start(s, dispatch_get_main_queue()), NULL);
74*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(kdebug_trace(TRACE_DEBUGID, 0xfeedfacefeedface, 2,
75*fdd8201dSApple OSS Distributions 3, 4), NULL);
76*fdd8201dSApple OSS Distributions ktrace_end(s, 0);
77*fdd8201dSApple OSS Distributions
78*fdd8201dSApple OSS Distributions dispatch_main();
79*fdd8201dSApple OSS Distributions }
80*fdd8201dSApple OSS Distributions
81*fdd8201dSApple OSS Distributions #if __LP64__
82*fdd8201dSApple OSS Distributions #define IS_64BIT true
83*fdd8201dSApple OSS Distributions #else // __LP64__
84*fdd8201dSApple OSS Distributions #define IS_64BIT false
85*fdd8201dSApple OSS Distributions #endif // !__LP64__
86*fdd8201dSApple OSS Distributions
87*fdd8201dSApple OSS Distributions #define STRING_SIZE (1024)
88*fdd8201dSApple OSS Distributions
89*fdd8201dSApple OSS Distributions T_DECL(kdebug_trace_string_syscall,
90*fdd8201dSApple OSS Distributions "test that kdebug_trace_string(2) emits correct events",
91*fdd8201dSApple OSS Distributions T_META_ENABLED(IS_64BIT))
92*fdd8201dSApple OSS Distributions {
93*fdd8201dSApple OSS Distributions start_controlling_ktrace();
94*fdd8201dSApple OSS Distributions
95*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
96*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "created session");
97*fdd8201dSApple OSS Distributions ktrace_set_collection_interval(s, 200);
98*fdd8201dSApple OSS Distributions ktrace_filter_pid(s, getpid());
99*fdd8201dSApple OSS Distributions
100*fdd8201dSApple OSS Distributions char *traced_string = calloc(1, STRING_SIZE);
101*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO;
102*fdd8201dSApple OSS Distributions T_ASSERT_NOTNULL(traced_string, "allocated memory for string");
103*fdd8201dSApple OSS Distributions for (size_t i = 0; i < sizeof(traced_string); i++) {
104*fdd8201dSApple OSS Distributions traced_string[i] = 'a' + (i % 26);
105*fdd8201dSApple OSS Distributions }
106*fdd8201dSApple OSS Distributions traced_string[sizeof(traced_string) - 1] = '\0';
107*fdd8201dSApple OSS Distributions size_t traced_len = strlen(traced_string);
108*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_EQ(traced_len, sizeof(traced_string) - 1,
109*fdd8201dSApple OSS Distributions "traced string should be filled");
110*fdd8201dSApple OSS Distributions
111*fdd8201dSApple OSS Distributions ktrace_events_single(s, TRACE_DEBUGID,
112*fdd8201dSApple OSS Distributions ^void (struct trace_point * __unused tp) {
113*fdd8201dSApple OSS Distributions // Do nothing -- just ensure the event is filtered in.
114*fdd8201dSApple OSS Distributions });
115*fdd8201dSApple OSS Distributions
116*fdd8201dSApple OSS Distributions __block unsigned int string_cpu = 0;
117*fdd8201dSApple OSS Distributions __block bool tracing_string = false;
118*fdd8201dSApple OSS Distributions char *observed_string = calloc(1, PATH_MAX);
119*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO;
120*fdd8201dSApple OSS Distributions T_ASSERT_NOTNULL(observed_string, "allocated memory for observed string");
121*fdd8201dSApple OSS Distributions __block size_t string_offset = 0;
122*fdd8201dSApple OSS Distributions ktrace_events_single(s, TRACE_STRING_GLOBAL, ^(struct trace_point *tp){
123*fdd8201dSApple OSS Distributions if (tp->debugid & DBG_FUNC_START && tp->arg1 == TRACE_DEBUGID) {
124*fdd8201dSApple OSS Distributions tracing_string = true;
125*fdd8201dSApple OSS Distributions string_cpu = tp->cpuid;
126*fdd8201dSApple OSS Distributions memcpy(observed_string + string_offset, &tp->arg3,
127*fdd8201dSApple OSS Distributions sizeof(uint64_t) * 2);
128*fdd8201dSApple OSS Distributions string_offset += sizeof(uint64_t) * 2;
129*fdd8201dSApple OSS Distributions } else if (tracing_string && string_cpu == tp->cpuid) {
130*fdd8201dSApple OSS Distributions memcpy(observed_string + string_offset, &tp->arg1,
131*fdd8201dSApple OSS Distributions sizeof(uint64_t) * 4);
132*fdd8201dSApple OSS Distributions string_offset += sizeof(uint64_t) * 4;
133*fdd8201dSApple OSS Distributions if (tp->debugid & DBG_FUNC_END) {
134*fdd8201dSApple OSS Distributions ktrace_end(s, 1);
135*fdd8201dSApple OSS Distributions }
136*fdd8201dSApple OSS Distributions }
137*fdd8201dSApple OSS Distributions });
138*fdd8201dSApple OSS Distributions
139*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^{
140*fdd8201dSApple OSS Distributions T_EXPECT_TRUE(tracing_string, "found string in trace");
141*fdd8201dSApple OSS Distributions size_t observed_len = strlen(observed_string);
142*fdd8201dSApple OSS Distributions T_EXPECT_EQ(traced_len, observed_len, "string lengths should be equal");
143*fdd8201dSApple OSS Distributions if (traced_len == observed_len) {
144*fdd8201dSApple OSS Distributions T_EXPECT_EQ_STR(traced_string, observed_string,
145*fdd8201dSApple OSS Distributions "observed correct string");
146*fdd8201dSApple OSS Distributions }
147*fdd8201dSApple OSS Distributions ktrace_session_destroy(s);
148*fdd8201dSApple OSS Distributions T_END;
149*fdd8201dSApple OSS Distributions });
150*fdd8201dSApple OSS Distributions
151*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_start(s, dispatch_get_main_queue()), NULL);
152*fdd8201dSApple OSS Distributions uint64_t str_id = kdebug_trace_string(TRACE_DEBUGID, 0, traced_string);
153*fdd8201dSApple OSS Distributions T_WITH_ERRNO; T_ASSERT_NE(str_id, (uint64_t)0, "kdebug_trace_string(2)");
154*fdd8201dSApple OSS Distributions ktrace_end(s, 0);
155*fdd8201dSApple OSS Distributions
156*fdd8201dSApple OSS Distributions dispatch_main();
157*fdd8201dSApple OSS Distributions }
158*fdd8201dSApple OSS Distributions
159*fdd8201dSApple OSS Distributions #define SIGNPOST_SINGLE_CODE (0x10U)
160*fdd8201dSApple OSS Distributions #define SIGNPOST_PAIRED_CODE (0x20U)
161*fdd8201dSApple OSS Distributions
162*fdd8201dSApple OSS Distributions T_DECL(kdebug_signpost_syscall,
163*fdd8201dSApple OSS Distributions "test that kdebug_signpost(2) emits correct events")
164*fdd8201dSApple OSS Distributions {
165*fdd8201dSApple OSS Distributions start_controlling_ktrace();
166*fdd8201dSApple OSS Distributions
167*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
168*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "created session");
169*fdd8201dSApple OSS Distributions
170*fdd8201dSApple OSS Distributions __block int single_seen = 0;
171*fdd8201dSApple OSS Distributions __block int paired_seen = 0;
172*fdd8201dSApple OSS Distributions
173*fdd8201dSApple OSS Distributions /* make sure to get enough events for the KDBUFWAIT to trigger */
174*fdd8201dSApple OSS Distributions // ktrace_events_class(s, DBG_MACH, ^(__unused struct trace_point *tp){});
175*fdd8201dSApple OSS Distributions ktrace_events_single(s,
176*fdd8201dSApple OSS Distributions APPSDBG_CODE(DBG_APP_SIGNPOST, SIGNPOST_SINGLE_CODE),
177*fdd8201dSApple OSS Distributions ^(struct trace_point *tp) {
178*fdd8201dSApple OSS Distributions single_seen++;
179*fdd8201dSApple OSS Distributions T_PASS("single signpost is traced");
180*fdd8201dSApple OSS Distributions
181*fdd8201dSApple OSS Distributions T_EXPECT_EQ(tp->arg1, 1ULL, "argument 1 of single signpost is correct");
182*fdd8201dSApple OSS Distributions T_EXPECT_EQ(tp->arg2, 2ULL, "argument 2 of single signpost is correct");
183*fdd8201dSApple OSS Distributions T_EXPECT_EQ(tp->arg3, 3ULL, "argument 3 of single signpost is correct");
184*fdd8201dSApple OSS Distributions T_EXPECT_EQ(tp->arg4, 4ULL, "argument 4 of single signpost is correct");
185*fdd8201dSApple OSS Distributions });
186*fdd8201dSApple OSS Distributions
187*fdd8201dSApple OSS Distributions ktrace_events_single_paired(s,
188*fdd8201dSApple OSS Distributions APPSDBG_CODE(DBG_APP_SIGNPOST, SIGNPOST_PAIRED_CODE),
189*fdd8201dSApple OSS Distributions ^(struct trace_point *start, struct trace_point *end) {
190*fdd8201dSApple OSS Distributions paired_seen++;
191*fdd8201dSApple OSS Distributions T_PASS("paired signposts are traced");
192*fdd8201dSApple OSS Distributions
193*fdd8201dSApple OSS Distributions T_EXPECT_EQ(start->arg1, 5ULL, "argument 1 of start signpost is correct");
194*fdd8201dSApple OSS Distributions T_EXPECT_EQ(start->arg2, 6ULL, "argument 2 of start signpost is correct");
195*fdd8201dSApple OSS Distributions T_EXPECT_EQ(start->arg3, 7ULL, "argument 3 of start signpost is correct");
196*fdd8201dSApple OSS Distributions T_EXPECT_EQ(start->arg4, 8ULL, "argument 4 of start signpost is correct");
197*fdd8201dSApple OSS Distributions
198*fdd8201dSApple OSS Distributions T_EXPECT_EQ(end->arg1, 9ULL, "argument 1 of end signpost is correct");
199*fdd8201dSApple OSS Distributions T_EXPECT_EQ(end->arg2, 10ULL, "argument 2 of end signpost is correct");
200*fdd8201dSApple OSS Distributions T_EXPECT_EQ(end->arg3, 11ULL, "argument 3 of end signpost is correct");
201*fdd8201dSApple OSS Distributions T_EXPECT_EQ(end->arg4, 12ULL, "argument 4 of end signpost is correct");
202*fdd8201dSApple OSS Distributions
203*fdd8201dSApple OSS Distributions T_EXPECT_EQ(single_seen, 1, "signposts are traced in the correct order");
204*fdd8201dSApple OSS Distributions
205*fdd8201dSApple OSS Distributions ktrace_end(s, 1);
206*fdd8201dSApple OSS Distributions });
207*fdd8201dSApple OSS Distributions
208*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^(void) {
209*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_NE(single_seen, 0,
210*fdd8201dSApple OSS Distributions "did not see single tracepoint before timeout");
211*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_NE(paired_seen, 0,
212*fdd8201dSApple OSS Distributions "did not see single tracepoint before timeout");
213*fdd8201dSApple OSS Distributions ktrace_session_destroy(s);
214*fdd8201dSApple OSS Distributions T_END;
215*fdd8201dSApple OSS Distributions });
216*fdd8201dSApple OSS Distributions
217*fdd8201dSApple OSS Distributions ktrace_filter_pid(s, getpid());
218*fdd8201dSApple OSS Distributions
219*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_start(s, dispatch_get_main_queue()),
220*fdd8201dSApple OSS Distributions "started tracing");
221*fdd8201dSApple OSS Distributions
222*fdd8201dSApple OSS Distributions #pragma clang diagnostic push
223*fdd8201dSApple OSS Distributions #pragma clang diagnostic ignored "-Wdeprecated-declarations"
224*fdd8201dSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(kdebug_signpost(SIGNPOST_SINGLE_CODE, 1, 2, 3, 4),
225*fdd8201dSApple OSS Distributions "emitted single signpost");
226*fdd8201dSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(
227*fdd8201dSApple OSS Distributions kdebug_signpost_start(SIGNPOST_PAIRED_CODE, 5, 6, 7, 8),
228*fdd8201dSApple OSS Distributions "emitted start signpost");
229*fdd8201dSApple OSS Distributions T_EXPECT_POSIX_SUCCESS(
230*fdd8201dSApple OSS Distributions kdebug_signpost_end(SIGNPOST_PAIRED_CODE, 9, 10, 11, 12),
231*fdd8201dSApple OSS Distributions "emitted end signpost");
232*fdd8201dSApple OSS Distributions #pragma clang diagnostic pop
233*fdd8201dSApple OSS Distributions ktrace_end(s, 0);
234*fdd8201dSApple OSS Distributions
235*fdd8201dSApple OSS Distributions dispatch_main();
236*fdd8201dSApple OSS Distributions }
237*fdd8201dSApple OSS Distributions
238*fdd8201dSApple OSS Distributions T_DECL(syscall_tracing,
239*fdd8201dSApple OSS Distributions "ensure that syscall arguments are traced propertly")
240*fdd8201dSApple OSS Distributions {
241*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
242*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "created session");
243*fdd8201dSApple OSS Distributions
244*fdd8201dSApple OSS Distributions __block bool seen = 0;
245*fdd8201dSApple OSS Distributions
246*fdd8201dSApple OSS Distributions ktrace_filter_pid(s, getpid());
247*fdd8201dSApple OSS Distributions
248*fdd8201dSApple OSS Distributions static const int telemetry_syscall_no = 451;
249*fdd8201dSApple OSS Distributions static const uint64_t arg1 = 0xfeedfacefeedface;
250*fdd8201dSApple OSS Distributions
251*fdd8201dSApple OSS Distributions ktrace_events_single(s, BSDDBG_CODE(DBG_BSD_EXCP_SC, telemetry_syscall_no),
252*fdd8201dSApple OSS Distributions ^(struct trace_point *evt){
253*fdd8201dSApple OSS Distributions if (KDBG_EXTRACT_CODE(evt->debugid) != telemetry_syscall_no || seen) {
254*fdd8201dSApple OSS Distributions return;
255*fdd8201dSApple OSS Distributions }
256*fdd8201dSApple OSS Distributions
257*fdd8201dSApple OSS Distributions seen = true;
258*fdd8201dSApple OSS Distributions if (ktrace_is_kernel_64_bit(s)) {
259*fdd8201dSApple OSS Distributions T_EXPECT_EQ(evt->arg1, arg1,
260*fdd8201dSApple OSS Distributions "argument 1 of syscall event is correct");
261*fdd8201dSApple OSS Distributions } else {
262*fdd8201dSApple OSS Distributions T_EXPECT_EQ(evt->arg1, (uint64_t)(uint32_t)(arg1),
263*fdd8201dSApple OSS Distributions "argument 1 of syscall event is correct");
264*fdd8201dSApple OSS Distributions }
265*fdd8201dSApple OSS Distributions
266*fdd8201dSApple OSS Distributions ktrace_end(s, 1);
267*fdd8201dSApple OSS Distributions });
268*fdd8201dSApple OSS Distributions
269*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^{
270*fdd8201dSApple OSS Distributions T_ASSERT_TRUE(seen,
271*fdd8201dSApple OSS Distributions "should have seen a syscall event for kevent_id(2)");
272*fdd8201dSApple OSS Distributions ktrace_session_destroy(s);
273*fdd8201dSApple OSS Distributions T_END;
274*fdd8201dSApple OSS Distributions });
275*fdd8201dSApple OSS Distributions
276*fdd8201dSApple OSS Distributions int error = ktrace_start(s, dispatch_get_main_queue());
277*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(error, "started tracing");
278*fdd8201dSApple OSS Distributions
279*fdd8201dSApple OSS Distributions /*
280*fdd8201dSApple OSS Distributions * telemetry(2) has a 64-bit argument that will definitely be traced, and
281*fdd8201dSApple OSS Distributions * is unlikely to be used elsewhere by this process.
282*fdd8201dSApple OSS Distributions */
283*fdd8201dSApple OSS Distributions extern int __telemetry(uint64_t cmd, uint64_t deadline, uint64_t interval,
284*fdd8201dSApple OSS Distributions uint64_t leeway, uint64_t arg4, uint64_t arg5);
285*fdd8201dSApple OSS Distributions (void)__telemetry(arg1, 0, 0, 0, 0, 0);
286*fdd8201dSApple OSS Distributions
287*fdd8201dSApple OSS Distributions dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC),
288*fdd8201dSApple OSS Distributions dispatch_get_main_queue(), ^{
289*fdd8201dSApple OSS Distributions T_LOG("ending test due to timeout");
290*fdd8201dSApple OSS Distributions ktrace_end(s, 0);
291*fdd8201dSApple OSS Distributions });
292*fdd8201dSApple OSS Distributions
293*fdd8201dSApple OSS Distributions dispatch_main();
294*fdd8201dSApple OSS Distributions }
295*fdd8201dSApple OSS Distributions
296*fdd8201dSApple OSS Distributions #pragma mark kdebug behaviors
297*fdd8201dSApple OSS Distributions
298*fdd8201dSApple OSS Distributions #define WRAPPING_EVENTS_COUNT (150000)
299*fdd8201dSApple OSS Distributions #define TRACE_ITERATIONS (5000)
300*fdd8201dSApple OSS Distributions #define WRAPPING_EVENTS_THRESHOLD (100)
301*fdd8201dSApple OSS Distributions
302*fdd8201dSApple OSS Distributions T_DECL(wrapping,
303*fdd8201dSApple OSS Distributions "ensure that wrapping traces lost events and no events prior to the wrap",
304*fdd8201dSApple OSS Distributions T_META_CHECK_LEAKS(false))
305*fdd8201dSApple OSS Distributions {
306*fdd8201dSApple OSS Distributions kbufinfo_t buf_info;
307*fdd8201dSApple OSS Distributions int wait_wrapping_secs = (WRAPPING_EVENTS_COUNT / TRACE_ITERATIONS) + 5;
308*fdd8201dSApple OSS Distributions int current_secs = wait_wrapping_secs;
309*fdd8201dSApple OSS Distributions
310*fdd8201dSApple OSS Distributions start_controlling_ktrace();
311*fdd8201dSApple OSS Distributions
312*fdd8201dSApple OSS Distributions /* use sysctls manually to bypass libktrace assumptions */
313*fdd8201dSApple OSS Distributions
314*fdd8201dSApple OSS Distributions int mib[4] = { CTL_KERN, KERN_KDEBUG };
315*fdd8201dSApple OSS Distributions mib[2] = KERN_KDSETBUF; mib[3] = WRAPPING_EVENTS_COUNT;
316*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(sysctl(mib, 4, NULL, 0, NULL, 0), "KERN_KDSETBUF");
317*fdd8201dSApple OSS Distributions
318*fdd8201dSApple OSS Distributions mib[2] = KERN_KDSETUP; mib[3] = 0;
319*fdd8201dSApple OSS Distributions size_t needed = 0;
320*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(sysctl(mib, 3, NULL, &needed, NULL, 0),
321*fdd8201dSApple OSS Distributions "KERN_KDSETUP");
322*fdd8201dSApple OSS Distributions
323*fdd8201dSApple OSS Distributions mib[2] = KERN_KDENABLE; mib[3] = 1;
324*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(sysctl(mib, 4, NULL, 0, NULL, 0), "KERN_KDENABLE");
325*fdd8201dSApple OSS Distributions
326*fdd8201dSApple OSS Distributions /* wrapping is on by default */
327*fdd8201dSApple OSS Distributions
328*fdd8201dSApple OSS Distributions /* wait until wrapped */
329*fdd8201dSApple OSS Distributions T_LOG("waiting for trace to wrap");
330*fdd8201dSApple OSS Distributions mib[2] = KERN_KDGETBUF;
331*fdd8201dSApple OSS Distributions needed = sizeof(buf_info);
332*fdd8201dSApple OSS Distributions do {
333*fdd8201dSApple OSS Distributions sleep(1);
334*fdd8201dSApple OSS Distributions for (int i = 0; i < TRACE_ITERATIONS; i++) {
335*fdd8201dSApple OSS Distributions T_QUIET;
336*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(kdebug_trace(0xfefe0000, 0, 0, 0, 0), NULL);
337*fdd8201dSApple OSS Distributions }
338*fdd8201dSApple OSS Distributions T_QUIET;
339*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(sysctl(mib, 3, &buf_info, &needed, NULL, 0),
340*fdd8201dSApple OSS Distributions NULL);
341*fdd8201dSApple OSS Distributions } while (!(buf_info.flags & KDBG_WRAPPED) && --current_secs > 0);
342*fdd8201dSApple OSS Distributions
343*fdd8201dSApple OSS Distributions T_ASSERT_TRUE(buf_info.flags & KDBG_WRAPPED,
344*fdd8201dSApple OSS Distributions "trace wrapped (after %d seconds within %d second timeout)",
345*fdd8201dSApple OSS Distributions wait_wrapping_secs - current_secs, wait_wrapping_secs);
346*fdd8201dSApple OSS Distributions
347*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
348*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_NOTNULL(s, NULL);
349*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(ktrace_set_use_existing(s), NULL);
350*fdd8201dSApple OSS Distributions
351*fdd8201dSApple OSS Distributions __block int events = 0;
352*fdd8201dSApple OSS Distributions
353*fdd8201dSApple OSS Distributions ktrace_events_all(s, ^(struct trace_point *tp) {
354*fdd8201dSApple OSS Distributions if (events == 0) {
355*fdd8201dSApple OSS Distributions T_EXPECT_EQ(tp->debugid, (unsigned int)TRACE_LOST_EVENTS,
356*fdd8201dSApple OSS Distributions "first event's debugid 0x%08x (%s) should be TRACE_LOST_EVENTS",
357*fdd8201dSApple OSS Distributions tp->debugid,
358*fdd8201dSApple OSS Distributions ktrace_name_for_eventid(s, tp->debugid & KDBG_EVENTID_MASK));
359*fdd8201dSApple OSS Distributions } else {
360*fdd8201dSApple OSS Distributions T_QUIET;
361*fdd8201dSApple OSS Distributions T_EXPECT_NE(tp->debugid, (unsigned int)TRACE_LOST_EVENTS,
362*fdd8201dSApple OSS Distributions "event debugid 0x%08x (%s) should not be TRACE_LOST_EVENTS",
363*fdd8201dSApple OSS Distributions tp->debugid,
364*fdd8201dSApple OSS Distributions ktrace_name_for_eventid(s, tp->debugid & KDBG_EVENTID_MASK));
365*fdd8201dSApple OSS Distributions }
366*fdd8201dSApple OSS Distributions
367*fdd8201dSApple OSS Distributions events++;
368*fdd8201dSApple OSS Distributions if (events > WRAPPING_EVENTS_THRESHOLD) {
369*fdd8201dSApple OSS Distributions ktrace_end(s, 1);
370*fdd8201dSApple OSS Distributions }
371*fdd8201dSApple OSS Distributions });
372*fdd8201dSApple OSS Distributions
373*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^{
374*fdd8201dSApple OSS Distributions ktrace_session_destroy(s);
375*fdd8201dSApple OSS Distributions T_END;
376*fdd8201dSApple OSS Distributions });
377*fdd8201dSApple OSS Distributions
378*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_start(s, dispatch_get_main_queue()),
379*fdd8201dSApple OSS Distributions "started tracing");
380*fdd8201dSApple OSS Distributions
381*fdd8201dSApple OSS Distributions dispatch_main();
382*fdd8201dSApple OSS Distributions }
383*fdd8201dSApple OSS Distributions
384*fdd8201dSApple OSS Distributions static void
_assert_tracing_state(bool enable,const char * msg)385*fdd8201dSApple OSS Distributions _assert_tracing_state(bool enable, const char *msg)
386*fdd8201dSApple OSS Distributions {
387*fdd8201dSApple OSS Distributions kbufinfo_t bufinfo = { 0 };
388*fdd8201dSApple OSS Distributions T_QUIET;
389*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(sysctl(
390*fdd8201dSApple OSS Distributions (int[]){ CTL_KERN, KERN_KDEBUG, KERN_KDGETBUF }, 3,
391*fdd8201dSApple OSS Distributions &bufinfo, &(size_t){ sizeof(bufinfo) }, NULL, 0),
392*fdd8201dSApple OSS Distributions "get kdebug buffer info");
393*fdd8201dSApple OSS Distributions T_QUIET;
394*fdd8201dSApple OSS Distributions T_ASSERT_NE(bufinfo.nkdbufs, 0, "tracing should be configured");
395*fdd8201dSApple OSS Distributions T_ASSERT_NE(bufinfo.nolog, enable, "%s: tracing should%s be enabled",
396*fdd8201dSApple OSS Distributions msg, enable ? "" : "n't");
397*fdd8201dSApple OSS Distributions }
398*fdd8201dSApple OSS Distributions
399*fdd8201dSApple OSS Distributions #define DRAIN_TIMEOUT_NS (1 * NSEC_PER_SEC)
400*fdd8201dSApple OSS Distributions
401*fdd8201dSApple OSS Distributions static void
_drain_until_event(uint32_t debugid)402*fdd8201dSApple OSS Distributions _drain_until_event(uint32_t debugid)
403*fdd8201dSApple OSS Distributions {
404*fdd8201dSApple OSS Distributions static kd_buf events[256] = { 0 };
405*fdd8201dSApple OSS Distributions size_t events_size = sizeof(events);
406*fdd8201dSApple OSS Distributions uint64_t start_time_ns = clock_gettime_nsec_np(CLOCK_MONOTONIC);
407*fdd8201dSApple OSS Distributions while (true) {
408*fdd8201dSApple OSS Distributions T_QUIET;
409*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(sysctl(
410*fdd8201dSApple OSS Distributions (int[]){ CTL_KERN, KERN_KDEBUG, KERN_KDREADTR, }, 3,
411*fdd8201dSApple OSS Distributions events, &events_size, NULL, 0), "reading trace data");
412*fdd8201dSApple OSS Distributions size_t events_count = events_size;
413*fdd8201dSApple OSS Distributions for (size_t i = 0; i < events_count; i++) {
414*fdd8201dSApple OSS Distributions if (events[i].debugid == debugid) {
415*fdd8201dSApple OSS Distributions T_LOG("draining found event 0x%x", debugid);
416*fdd8201dSApple OSS Distributions return;
417*fdd8201dSApple OSS Distributions }
418*fdd8201dSApple OSS Distributions }
419*fdd8201dSApple OSS Distributions uint64_t cur_time_ns = clock_gettime_nsec_np(CLOCK_MONOTONIC);
420*fdd8201dSApple OSS Distributions if (cur_time_ns - start_time_ns < DRAIN_TIMEOUT_NS) {
421*fdd8201dSApple OSS Distributions T_ASSERT_FAIL("timed out while waiting for event 0x%x", debugid);
422*fdd8201dSApple OSS Distributions }
423*fdd8201dSApple OSS Distributions }
424*fdd8201dSApple OSS Distributions }
425*fdd8201dSApple OSS Distributions
426*fdd8201dSApple OSS Distributions T_DECL(disabling_event_match,
427*fdd8201dSApple OSS Distributions "ensure that ktrace is disabled when an event disable matcher fires")
428*fdd8201dSApple OSS Distributions {
429*fdd8201dSApple OSS Distributions start_controlling_ktrace();
430*fdd8201dSApple OSS Distributions
431*fdd8201dSApple OSS Distributions T_SETUPBEGIN;
432*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
433*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "created session");
434*fdd8201dSApple OSS Distributions ktrace_events_single(s, TRACE_DEBUGID,
435*fdd8201dSApple OSS Distributions ^(struct trace_point *tp __unused) {});
436*fdd8201dSApple OSS Distributions int error = ktrace_configure(s);
437*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(error, "configured session");
438*fdd8201dSApple OSS Distributions kd_event_matcher matchers[2] = { {
439*fdd8201dSApple OSS Distributions .kem_debugid = TRACE_DEBUGID,
440*fdd8201dSApple OSS Distributions .kem_args[0] = 0xff,
441*fdd8201dSApple OSS Distributions }, {
442*fdd8201dSApple OSS Distributions .kem_debugid = UINT32_MAX,
443*fdd8201dSApple OSS Distributions .kem_args[0] = 0xfff,
444*fdd8201dSApple OSS Distributions } };
445*fdd8201dSApple OSS Distributions size_t matchers_size = sizeof(matchers);
446*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(sysctl(
447*fdd8201dSApple OSS Distributions (int[]){ CTL_KERN, KERN_KDEBUG, KERN_KDSET_EDM, }, 3,
448*fdd8201dSApple OSS Distributions &matchers, &matchers_size, NULL, 0), "set event disable matcher");
449*fdd8201dSApple OSS Distributions size_t size = 0;
450*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(sysctl(
451*fdd8201dSApple OSS Distributions (int[]){ CTL_KERN, KERN_KDEBUG, KERN_KDEFLAGS, KDBG_MATCH_DISABLE, }, 4,
452*fdd8201dSApple OSS Distributions NULL, &size, NULL, 0), "enabled event disable matching");
453*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(sysctl(
454*fdd8201dSApple OSS Distributions (int[]){ CTL_KERN, KERN_KDEBUG, KERN_KDENABLE, 1, }, 4,
455*fdd8201dSApple OSS Distributions NULL, NULL, NULL, 0), "enabled tracing");
456*fdd8201dSApple OSS Distributions _assert_tracing_state(true, "after enabling trace");
457*fdd8201dSApple OSS Distributions T_SETUPEND;
458*fdd8201dSApple OSS Distributions
459*fdd8201dSApple OSS Distributions kdebug_trace(TRACE_DEBUGID + 8, 0xff, 0, 0, 0);
460*fdd8201dSApple OSS Distributions _drain_until_event(TRACE_DEBUGID + 8);
461*fdd8201dSApple OSS Distributions _assert_tracing_state(true, "with wrong debugid");
462*fdd8201dSApple OSS Distributions kdebug_trace(TRACE_DEBUGID, 0, 0, 0, 0);
463*fdd8201dSApple OSS Distributions _drain_until_event(TRACE_DEBUGID);
464*fdd8201dSApple OSS Distributions _assert_tracing_state(true, "with wrong argument");
465*fdd8201dSApple OSS Distributions kdebug_trace(TRACE_DEBUGID, 0xff, 0, 0, 0);
466*fdd8201dSApple OSS Distributions _drain_until_event(TRACE_DEBUGID);
467*fdd8201dSApple OSS Distributions _assert_tracing_state(false, "after disabling event");
468*fdd8201dSApple OSS Distributions }
469*fdd8201dSApple OSS Distributions
470*fdd8201dSApple OSS Distributions T_DECL(reject_old_events,
471*fdd8201dSApple OSS Distributions "ensure that kdebug rejects events from before tracing began",
472*fdd8201dSApple OSS Distributions T_META_CHECK_LEAKS(false))
473*fdd8201dSApple OSS Distributions {
474*fdd8201dSApple OSS Distributions __block uint64_t event_horizon_ts;
475*fdd8201dSApple OSS Distributions
476*fdd8201dSApple OSS Distributions start_controlling_ktrace();
477*fdd8201dSApple OSS Distributions
478*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
479*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "created session");
480*fdd8201dSApple OSS Distributions
481*fdd8201dSApple OSS Distributions __block int events = 0;
482*fdd8201dSApple OSS Distributions ktrace_events_single(s, KDBG_EVENTID(DBG_BSD, DBG_BSD_KDEBUG_TEST, 1),
483*fdd8201dSApple OSS Distributions ^(struct trace_point *tp) {
484*fdd8201dSApple OSS Distributions events++;
485*fdd8201dSApple OSS Distributions T_EXPECT_GT(tp->timestamp, event_horizon_ts,
486*fdd8201dSApple OSS Distributions "events in trace should be from after tracing began");
487*fdd8201dSApple OSS Distributions });
488*fdd8201dSApple OSS Distributions
489*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^{
490*fdd8201dSApple OSS Distributions T_EXPECT_EQ(events, 2, "should see only two events");
491*fdd8201dSApple OSS Distributions ktrace_session_destroy(s);
492*fdd8201dSApple OSS Distributions T_END;
493*fdd8201dSApple OSS Distributions });
494*fdd8201dSApple OSS Distributions
495*fdd8201dSApple OSS Distributions event_horizon_ts = mach_absolute_time();
496*fdd8201dSApple OSS Distributions
497*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_start(s, dispatch_get_main_queue()), NULL);
498*fdd8201dSApple OSS Distributions /* first, try an old event at the beginning of trace */
499*fdd8201dSApple OSS Distributions assert_kdebug_test(KDBG_TEST_OLD_TIMES, "induce old event at beginning");
500*fdd8201dSApple OSS Distributions /* after a good event has been traced, old events should be rejected */
501*fdd8201dSApple OSS Distributions assert_kdebug_test(KDBG_TEST_OLD_TIMES, "induce old event to be rejected");
502*fdd8201dSApple OSS Distributions ktrace_end(s, 0);
503*fdd8201dSApple OSS Distributions
504*fdd8201dSApple OSS Distributions dispatch_main();
505*fdd8201dSApple OSS Distributions }
506*fdd8201dSApple OSS Distributions
507*fdd8201dSApple OSS Distributions #define ORDERING_TIMEOUT_SEC 5
508*fdd8201dSApple OSS Distributions
509*fdd8201dSApple OSS Distributions T_DECL(ascending_time_order,
510*fdd8201dSApple OSS Distributions "ensure that kdebug events are in ascending order based on time",
511*fdd8201dSApple OSS Distributions T_META_CHECK_LEAKS(false))
512*fdd8201dSApple OSS Distributions {
513*fdd8201dSApple OSS Distributions __block uint64_t prev_ts = 0;
514*fdd8201dSApple OSS Distributions __block uint32_t prev_debugid = 0;
515*fdd8201dSApple OSS Distributions __block unsigned int prev_cpu = 0;
516*fdd8201dSApple OSS Distributions __block bool in_order = true;
517*fdd8201dSApple OSS Distributions
518*fdd8201dSApple OSS Distributions start_controlling_ktrace();
519*fdd8201dSApple OSS Distributions
520*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
521*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "created session");
522*fdd8201dSApple OSS Distributions
523*fdd8201dSApple OSS Distributions ktrace_events_all(s, ^(struct trace_point *tp) {
524*fdd8201dSApple OSS Distributions if (tp->timestamp < prev_ts) {
525*fdd8201dSApple OSS Distributions in_order = false;
526*fdd8201dSApple OSS Distributions T_LOG("%" PRIu64 ": %#" PRIx32 " (cpu %d)",
527*fdd8201dSApple OSS Distributions prev_ts, prev_debugid, prev_cpu);
528*fdd8201dSApple OSS Distributions T_LOG("%" PRIu64 ": %#" PRIx32 " (cpu %d)",
529*fdd8201dSApple OSS Distributions tp->timestamp, tp->debugid, tp->cpuid);
530*fdd8201dSApple OSS Distributions ktrace_end(s, 1);
531*fdd8201dSApple OSS Distributions }
532*fdd8201dSApple OSS Distributions });
533*fdd8201dSApple OSS Distributions
534*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^{
535*fdd8201dSApple OSS Distributions ktrace_session_destroy(s);
536*fdd8201dSApple OSS Distributions T_EXPECT_TRUE(in_order, "event timestamps were in-order");
537*fdd8201dSApple OSS Distributions T_END;
538*fdd8201dSApple OSS Distributions });
539*fdd8201dSApple OSS Distributions
540*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_start(s, dispatch_get_main_queue()),
541*fdd8201dSApple OSS Distributions "started tracing");
542*fdd8201dSApple OSS Distributions
543*fdd8201dSApple OSS Distributions /* try to inject old timestamps into trace */
544*fdd8201dSApple OSS Distributions assert_kdebug_test(KDBG_TEST_OLD_TIMES, "inject old time");
545*fdd8201dSApple OSS Distributions
546*fdd8201dSApple OSS Distributions dispatch_after(dispatch_time(DISPATCH_TIME_NOW, ORDERING_TIMEOUT_SEC * NSEC_PER_SEC),
547*fdd8201dSApple OSS Distributions dispatch_get_main_queue(), ^{
548*fdd8201dSApple OSS Distributions T_LOG("ending test after timeout");
549*fdd8201dSApple OSS Distributions ktrace_end(s, 1);
550*fdd8201dSApple OSS Distributions });
551*fdd8201dSApple OSS Distributions
552*fdd8201dSApple OSS Distributions dispatch_main();
553*fdd8201dSApple OSS Distributions }
554*fdd8201dSApple OSS Distributions
555*fdd8201dSApple OSS Distributions #pragma mark dyld tracing
556*fdd8201dSApple OSS Distributions
557*fdd8201dSApple OSS Distributions __attribute__((aligned(8)))
558*fdd8201dSApple OSS Distributions static const char map_uuid[16] = "map UUID";
559*fdd8201dSApple OSS Distributions
560*fdd8201dSApple OSS Distributions __attribute__((aligned(8)))
561*fdd8201dSApple OSS Distributions static const char unmap_uuid[16] = "unmap UUID";
562*fdd8201dSApple OSS Distributions
563*fdd8201dSApple OSS Distributions __attribute__((aligned(8)))
564*fdd8201dSApple OSS Distributions static const char sc_uuid[16] = "shared UUID";
565*fdd8201dSApple OSS Distributions
566*fdd8201dSApple OSS Distributions static fsid_t map_fsid = { .val = { 42, 43 } };
567*fdd8201dSApple OSS Distributions static fsid_t unmap_fsid = { .val = { 44, 45 } };
568*fdd8201dSApple OSS Distributions static fsid_t sc_fsid = { .val = { 46, 47 } };
569*fdd8201dSApple OSS Distributions
570*fdd8201dSApple OSS Distributions static fsobj_id_t map_fsobjid = { .fid_objno = 42, .fid_generation = 43 };
571*fdd8201dSApple OSS Distributions static fsobj_id_t unmap_fsobjid = { .fid_objno = 44, .fid_generation = 45 };
572*fdd8201dSApple OSS Distributions static fsobj_id_t sc_fsobjid = { .fid_objno = 46, .fid_generation = 47 };
573*fdd8201dSApple OSS Distributions
574*fdd8201dSApple OSS Distributions #define MAP_LOAD_ADDR 0xabadcafe
575*fdd8201dSApple OSS Distributions #define UNMAP_LOAD_ADDR 0xfeedface
576*fdd8201dSApple OSS Distributions #define SC_LOAD_ADDR 0xfedfaced
577*fdd8201dSApple OSS Distributions
578*fdd8201dSApple OSS Distributions __unused
579*fdd8201dSApple OSS Distributions static void
expect_dyld_image_info(struct trace_point * tp,const uint64_t * exp_uuid,uint64_t exp_load_addr,fsid_t * exp_fsid,fsobj_id_t * exp_fsobjid,int order)580*fdd8201dSApple OSS Distributions expect_dyld_image_info(struct trace_point *tp, const uint64_t *exp_uuid,
581*fdd8201dSApple OSS Distributions uint64_t exp_load_addr, fsid_t *exp_fsid, fsobj_id_t *exp_fsobjid,
582*fdd8201dSApple OSS Distributions int order)
583*fdd8201dSApple OSS Distributions {
584*fdd8201dSApple OSS Distributions #if defined(__LP64__) || defined(__arm64__)
585*fdd8201dSApple OSS Distributions if (order == 0) {
586*fdd8201dSApple OSS Distributions uint64_t uuid[2];
587*fdd8201dSApple OSS Distributions uint64_t load_addr;
588*fdd8201dSApple OSS Distributions fsid_t fsid;
589*fdd8201dSApple OSS Distributions
590*fdd8201dSApple OSS Distributions uuid[0] = (uint64_t)tp->arg1;
591*fdd8201dSApple OSS Distributions uuid[1] = (uint64_t)tp->arg2;
592*fdd8201dSApple OSS Distributions load_addr = (uint64_t)tp->arg3;
593*fdd8201dSApple OSS Distributions fsid.val[0] = (int32_t)(tp->arg4 & UINT32_MAX);
594*fdd8201dSApple OSS Distributions fsid.val[1] = (int32_t)((uint64_t)tp->arg4 >> 32);
595*fdd8201dSApple OSS Distributions
596*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(uuid[0], exp_uuid[0], NULL);
597*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(uuid[1], exp_uuid[1], NULL);
598*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(load_addr, exp_load_addr, NULL);
599*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(fsid.val[0], exp_fsid->val[0], NULL);
600*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(fsid.val[1], exp_fsid->val[1], NULL);
601*fdd8201dSApple OSS Distributions } else if (order == 1) {
602*fdd8201dSApple OSS Distributions fsobj_id_t fsobjid;
603*fdd8201dSApple OSS Distributions
604*fdd8201dSApple OSS Distributions fsobjid.fid_objno = (uint32_t)(tp->arg1 & UINT32_MAX);
605*fdd8201dSApple OSS Distributions fsobjid.fid_generation = (uint32_t)((uint64_t)tp->arg1 >> 32);
606*fdd8201dSApple OSS Distributions
607*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(fsobjid.fid_objno, exp_fsobjid->fid_objno, NULL);
608*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(fsobjid.fid_generation,
609*fdd8201dSApple OSS Distributions exp_fsobjid->fid_generation, NULL);
610*fdd8201dSApple OSS Distributions } else {
611*fdd8201dSApple OSS Distributions T_ASSERT_FAIL("unrecognized order of events %d", order);
612*fdd8201dSApple OSS Distributions }
613*fdd8201dSApple OSS Distributions #else /* defined(__LP64__) */
614*fdd8201dSApple OSS Distributions if (order == 0) {
615*fdd8201dSApple OSS Distributions uint32_t uuid[4];
616*fdd8201dSApple OSS Distributions
617*fdd8201dSApple OSS Distributions uuid[0] = (uint32_t)tp->arg1;
618*fdd8201dSApple OSS Distributions uuid[1] = (uint32_t)tp->arg2;
619*fdd8201dSApple OSS Distributions uuid[2] = (uint32_t)tp->arg3;
620*fdd8201dSApple OSS Distributions uuid[3] = (uint32_t)tp->arg4;
621*fdd8201dSApple OSS Distributions
622*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(uuid[0], (uint32_t)exp_uuid[0], NULL);
623*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(uuid[1], (uint32_t)(exp_uuid[0] >> 32), NULL);
624*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(uuid[2], (uint32_t)exp_uuid[1], NULL);
625*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(uuid[3], (uint32_t)(exp_uuid[1] >> 32), NULL);
626*fdd8201dSApple OSS Distributions } else if (order == 1) {
627*fdd8201dSApple OSS Distributions uint32_t load_addr;
628*fdd8201dSApple OSS Distributions fsid_t fsid;
629*fdd8201dSApple OSS Distributions fsobj_id_t fsobjid;
630*fdd8201dSApple OSS Distributions
631*fdd8201dSApple OSS Distributions load_addr = (uint32_t)tp->arg1;
632*fdd8201dSApple OSS Distributions fsid.val[0] = (int32_t)tp->arg2;
633*fdd8201dSApple OSS Distributions fsid.val[1] = (int32_t)tp->arg3;
634*fdd8201dSApple OSS Distributions fsobjid.fid_objno = (uint32_t)tp->arg4;
635*fdd8201dSApple OSS Distributions
636*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(load_addr, (uint32_t)exp_load_addr, NULL);
637*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(fsid.val[0], exp_fsid->val[0], NULL);
638*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(fsid.val[1], exp_fsid->val[1], NULL);
639*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(fsobjid.fid_objno, exp_fsobjid->fid_objno, NULL);
640*fdd8201dSApple OSS Distributions } else if (order == 2) {
641*fdd8201dSApple OSS Distributions fsobj_id_t fsobjid;
642*fdd8201dSApple OSS Distributions
643*fdd8201dSApple OSS Distributions fsobjid.fid_generation = tp->arg1;
644*fdd8201dSApple OSS Distributions
645*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(fsobjid.fid_generation,
646*fdd8201dSApple OSS Distributions exp_fsobjid->fid_generation, NULL);
647*fdd8201dSApple OSS Distributions } else {
648*fdd8201dSApple OSS Distributions T_ASSERT_FAIL("unrecognized order of events %d", order);
649*fdd8201dSApple OSS Distributions }
650*fdd8201dSApple OSS Distributions #endif /* defined(__LP64__) */
651*fdd8201dSApple OSS Distributions }
652*fdd8201dSApple OSS Distributions
653*fdd8201dSApple OSS Distributions #if defined(__LP64__) || defined(__arm64__)
654*fdd8201dSApple OSS Distributions #define DYLD_CODE_OFFSET (0)
655*fdd8201dSApple OSS Distributions #define DYLD_EVENTS (2)
656*fdd8201dSApple OSS Distributions #else
657*fdd8201dSApple OSS Distributions #define DYLD_CODE_OFFSET (2)
658*fdd8201dSApple OSS Distributions #define DYLD_EVENTS (3)
659*fdd8201dSApple OSS Distributions #endif
660*fdd8201dSApple OSS Distributions
661*fdd8201dSApple OSS Distributions static void
expect_dyld_events(ktrace_session_t s,const char * name,uint32_t base_code,const char * exp_uuid,uint64_t exp_load_addr,fsid_t * exp_fsid,fsobj_id_t * exp_fsobjid,uint8_t * saw_events)662*fdd8201dSApple OSS Distributions expect_dyld_events(ktrace_session_t s, const char *name, uint32_t base_code,
663*fdd8201dSApple OSS Distributions const char *exp_uuid, uint64_t exp_load_addr, fsid_t *exp_fsid,
664*fdd8201dSApple OSS Distributions fsobj_id_t *exp_fsobjid, uint8_t *saw_events)
665*fdd8201dSApple OSS Distributions {
666*fdd8201dSApple OSS Distributions for (int i = 0; i < DYLD_EVENTS; i++) {
667*fdd8201dSApple OSS Distributions ktrace_events_single(s, KDBG_EVENTID(DBG_DYLD, DBG_DYLD_UUID,
668*fdd8201dSApple OSS Distributions base_code + DYLD_CODE_OFFSET + (unsigned int)i),
669*fdd8201dSApple OSS Distributions ^(struct trace_point *tp) {
670*fdd8201dSApple OSS Distributions T_LOG("checking %s event %c", name, 'A' + i);
671*fdd8201dSApple OSS Distributions expect_dyld_image_info(tp, (const void *)exp_uuid, exp_load_addr,
672*fdd8201dSApple OSS Distributions exp_fsid, exp_fsobjid, i);
673*fdd8201dSApple OSS Distributions *saw_events |= (1U << i);
674*fdd8201dSApple OSS Distributions });
675*fdd8201dSApple OSS Distributions }
676*fdd8201dSApple OSS Distributions }
677*fdd8201dSApple OSS Distributions
678*fdd8201dSApple OSS Distributions T_DECL(dyld_events, "test that dyld registering libraries emits events")
679*fdd8201dSApple OSS Distributions {
680*fdd8201dSApple OSS Distributions dyld_kernel_image_info_t info;
681*fdd8201dSApple OSS Distributions
682*fdd8201dSApple OSS Distributions /*
683*fdd8201dSApple OSS Distributions * Use pointers instead of __block variables in order to use these variables
684*fdd8201dSApple OSS Distributions * in the completion block below _and_ pass pointers to them to the
685*fdd8201dSApple OSS Distributions * expect_dyld_events function.
686*fdd8201dSApple OSS Distributions */
687*fdd8201dSApple OSS Distributions uint8_t saw_events[3] = { 0 };
688*fdd8201dSApple OSS Distributions uint8_t *saw_mapping = &(saw_events[0]);
689*fdd8201dSApple OSS Distributions uint8_t *saw_unmapping = &(saw_events[1]);
690*fdd8201dSApple OSS Distributions uint8_t *saw_shared_cache = &(saw_events[2]);
691*fdd8201dSApple OSS Distributions
692*fdd8201dSApple OSS Distributions start_controlling_ktrace();
693*fdd8201dSApple OSS Distributions
694*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
695*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "created session");
696*fdd8201dSApple OSS Distributions
697*fdd8201dSApple OSS Distributions T_QUIET;
698*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_filter_pid(s, getpid()),
699*fdd8201dSApple OSS Distributions "filtered to current process");
700*fdd8201dSApple OSS Distributions
701*fdd8201dSApple OSS Distributions expect_dyld_events(s, "mapping", DBG_DYLD_UUID_MAP_A, map_uuid,
702*fdd8201dSApple OSS Distributions MAP_LOAD_ADDR, &map_fsid, &map_fsobjid, saw_mapping);
703*fdd8201dSApple OSS Distributions expect_dyld_events(s, "unmapping", DBG_DYLD_UUID_UNMAP_A, unmap_uuid,
704*fdd8201dSApple OSS Distributions UNMAP_LOAD_ADDR, &unmap_fsid, &unmap_fsobjid, saw_unmapping);
705*fdd8201dSApple OSS Distributions expect_dyld_events(s, "shared cache", DBG_DYLD_UUID_SHARED_CACHE_A,
706*fdd8201dSApple OSS Distributions sc_uuid, SC_LOAD_ADDR, &sc_fsid, &sc_fsobjid, saw_shared_cache);
707*fdd8201dSApple OSS Distributions
708*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^{
709*fdd8201dSApple OSS Distributions ktrace_session_destroy(s);
710*fdd8201dSApple OSS Distributions
711*fdd8201dSApple OSS Distributions T_EXPECT_EQ(__builtin_popcount(*saw_mapping), DYLD_EVENTS, NULL);
712*fdd8201dSApple OSS Distributions T_EXPECT_EQ(__builtin_popcount(*saw_unmapping), DYLD_EVENTS, NULL);
713*fdd8201dSApple OSS Distributions T_EXPECT_EQ(__builtin_popcount(*saw_shared_cache), DYLD_EVENTS, NULL);
714*fdd8201dSApple OSS Distributions T_END;
715*fdd8201dSApple OSS Distributions });
716*fdd8201dSApple OSS Distributions
717*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_start(s, dispatch_get_main_queue()), NULL);
718*fdd8201dSApple OSS Distributions
719*fdd8201dSApple OSS Distributions info.load_addr = MAP_LOAD_ADDR;
720*fdd8201dSApple OSS Distributions memcpy(info.uuid, map_uuid, sizeof(info.uuid));
721*fdd8201dSApple OSS Distributions info.fsid = map_fsid;
722*fdd8201dSApple OSS Distributions info.fsobjid = map_fsobjid;
723*fdd8201dSApple OSS Distributions T_EXPECT_MACH_SUCCESS(task_register_dyld_image_infos(mach_task_self(),
724*fdd8201dSApple OSS Distributions &info, 1), "registered dyld image info");
725*fdd8201dSApple OSS Distributions
726*fdd8201dSApple OSS Distributions info.load_addr = UNMAP_LOAD_ADDR;
727*fdd8201dSApple OSS Distributions memcpy(info.uuid, unmap_uuid, sizeof(info.uuid));
728*fdd8201dSApple OSS Distributions info.fsid = unmap_fsid;
729*fdd8201dSApple OSS Distributions info.fsobjid = unmap_fsobjid;
730*fdd8201dSApple OSS Distributions T_EXPECT_MACH_SUCCESS(task_unregister_dyld_image_infos(mach_task_self(),
731*fdd8201dSApple OSS Distributions &info, 1), "unregistered dyld image info");
732*fdd8201dSApple OSS Distributions
733*fdd8201dSApple OSS Distributions info.load_addr = SC_LOAD_ADDR;
734*fdd8201dSApple OSS Distributions memcpy(info.uuid, sc_uuid, sizeof(info.uuid));
735*fdd8201dSApple OSS Distributions info.fsid = sc_fsid;
736*fdd8201dSApple OSS Distributions info.fsobjid = sc_fsobjid;
737*fdd8201dSApple OSS Distributions T_EXPECT_MACH_SUCCESS(task_register_dyld_shared_cache_image_info(
738*fdd8201dSApple OSS Distributions mach_task_self(), info, FALSE, FALSE),
739*fdd8201dSApple OSS Distributions "registered dyld shared cache image info");
740*fdd8201dSApple OSS Distributions
741*fdd8201dSApple OSS Distributions ktrace_end(s, 0);
742*fdd8201dSApple OSS Distributions
743*fdd8201dSApple OSS Distributions dispatch_main();
744*fdd8201dSApple OSS Distributions }
745*fdd8201dSApple OSS Distributions
746*fdd8201dSApple OSS Distributions #pragma mark kdebug kernel macros
747*fdd8201dSApple OSS Distributions
748*fdd8201dSApple OSS Distributions #define EXP_KERNEL_EVENTS 5U
749*fdd8201dSApple OSS Distributions
750*fdd8201dSApple OSS Distributions static const uint32_t dev_evts[EXP_KERNEL_EVENTS] = {
751*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 0),
752*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 1),
753*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 2),
754*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 3),
755*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 4),
756*fdd8201dSApple OSS Distributions };
757*fdd8201dSApple OSS Distributions
758*fdd8201dSApple OSS Distributions static const uint32_t rel_evts[EXP_KERNEL_EVENTS] = {
759*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 5),
760*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 6),
761*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 7),
762*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 8),
763*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 9),
764*fdd8201dSApple OSS Distributions };
765*fdd8201dSApple OSS Distributions
766*fdd8201dSApple OSS Distributions static const uint32_t filt_evts[EXP_KERNEL_EVENTS] = {
767*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 10),
768*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 11),
769*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 12),
770*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 13),
771*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 14),
772*fdd8201dSApple OSS Distributions };
773*fdd8201dSApple OSS Distributions
774*fdd8201dSApple OSS Distributions static const uint32_t noprocfilt_evts[EXP_KERNEL_EVENTS] = {
775*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 15),
776*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 16),
777*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 17),
778*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 18),
779*fdd8201dSApple OSS Distributions BSDDBG_CODE(DBG_BSD_KDEBUG_TEST, 19),
780*fdd8201dSApple OSS Distributions };
781*fdd8201dSApple OSS Distributions
782*fdd8201dSApple OSS Distributions static void
expect_event(struct trace_point * tp,const char * name,unsigned int * events,const uint32_t * event_ids,size_t event_ids_len)783*fdd8201dSApple OSS Distributions expect_event(struct trace_point *tp, const char *name, unsigned int *events,
784*fdd8201dSApple OSS Distributions const uint32_t *event_ids, size_t event_ids_len)
785*fdd8201dSApple OSS Distributions {
786*fdd8201dSApple OSS Distributions unsigned int event_idx = *events;
787*fdd8201dSApple OSS Distributions bool event_found = false;
788*fdd8201dSApple OSS Distributions size_t i;
789*fdd8201dSApple OSS Distributions for (i = 0; i < event_ids_len; i++) {
790*fdd8201dSApple OSS Distributions if (event_ids[i] == (tp->debugid & KDBG_EVENTID_MASK)) {
791*fdd8201dSApple OSS Distributions T_LOG("found %s event 0x%x", name, tp->debugid);
792*fdd8201dSApple OSS Distributions event_found = true;
793*fdd8201dSApple OSS Distributions }
794*fdd8201dSApple OSS Distributions }
795*fdd8201dSApple OSS Distributions
796*fdd8201dSApple OSS Distributions if (!event_found) {
797*fdd8201dSApple OSS Distributions return;
798*fdd8201dSApple OSS Distributions }
799*fdd8201dSApple OSS Distributions
800*fdd8201dSApple OSS Distributions *events += 1;
801*fdd8201dSApple OSS Distributions for (i = 0; i < event_idx; i++) {
802*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(((uint64_t *)&tp->arg1)[i], (uint64_t)i + 1,
803*fdd8201dSApple OSS Distributions NULL);
804*fdd8201dSApple OSS Distributions }
805*fdd8201dSApple OSS Distributions for (; i < 4; i++) {
806*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(((uint64_t *)&tp->arg1)[i], (uint64_t)0, NULL);
807*fdd8201dSApple OSS Distributions }
808*fdd8201dSApple OSS Distributions }
809*fdd8201dSApple OSS Distributions
810*fdd8201dSApple OSS Distributions static void
expect_release_event(struct trace_point * tp,unsigned int * events)811*fdd8201dSApple OSS Distributions expect_release_event(struct trace_point *tp, unsigned int *events)
812*fdd8201dSApple OSS Distributions {
813*fdd8201dSApple OSS Distributions expect_event(tp, "release", events, rel_evts,
814*fdd8201dSApple OSS Distributions sizeof(rel_evts) / sizeof(rel_evts[0]));
815*fdd8201dSApple OSS Distributions }
816*fdd8201dSApple OSS Distributions
817*fdd8201dSApple OSS Distributions static void
expect_development_event(struct trace_point * tp,unsigned int * events)818*fdd8201dSApple OSS Distributions expect_development_event(struct trace_point *tp, unsigned int *events)
819*fdd8201dSApple OSS Distributions {
820*fdd8201dSApple OSS Distributions expect_event(tp, "dev", events, dev_evts, sizeof(dev_evts) / sizeof(dev_evts[0]));
821*fdd8201dSApple OSS Distributions }
822*fdd8201dSApple OSS Distributions
823*fdd8201dSApple OSS Distributions static void
expect_filtered_event(struct trace_point * tp,unsigned int * events)824*fdd8201dSApple OSS Distributions expect_filtered_event(struct trace_point *tp, unsigned int *events)
825*fdd8201dSApple OSS Distributions {
826*fdd8201dSApple OSS Distributions expect_event(tp, "filtered", events, filt_evts,
827*fdd8201dSApple OSS Distributions sizeof(filt_evts) / sizeof(filt_evts[0]));
828*fdd8201dSApple OSS Distributions }
829*fdd8201dSApple OSS Distributions
830*fdd8201dSApple OSS Distributions static void
expect_noprocfilt_event(struct trace_point * tp,unsigned int * events)831*fdd8201dSApple OSS Distributions expect_noprocfilt_event(struct trace_point *tp, unsigned int *events)
832*fdd8201dSApple OSS Distributions {
833*fdd8201dSApple OSS Distributions expect_event(tp, "noprocfilt", events, noprocfilt_evts,
834*fdd8201dSApple OSS Distributions sizeof(noprocfilt_evts) / sizeof(noprocfilt_evts[0]));
835*fdd8201dSApple OSS Distributions }
836*fdd8201dSApple OSS Distributions
837*fdd8201dSApple OSS Distributions static void
838*fdd8201dSApple OSS Distributions expect_kdbg_test_events(ktrace_session_t s, bool use_all_callback,
839*fdd8201dSApple OSS Distributions void (^cb)(unsigned int dev_seen, unsigned int rel_seen,
840*fdd8201dSApple OSS Distributions unsigned int filt_seen, unsigned int noprocfilt_seen))
841*fdd8201dSApple OSS Distributions {
842*fdd8201dSApple OSS Distributions __block unsigned int dev_seen = 0;
843*fdd8201dSApple OSS Distributions __block unsigned int rel_seen = 0;
844*fdd8201dSApple OSS Distributions __block unsigned int filt_seen = 0;
845*fdd8201dSApple OSS Distributions __block unsigned int noprocfilt_seen = 0;
846*fdd8201dSApple OSS Distributions
847*fdd8201dSApple OSS Distributions void (^evtcb)(struct trace_point *tp) = ^(struct trace_point *tp) {
848*fdd8201dSApple OSS Distributions expect_development_event(tp, &dev_seen);
849*fdd8201dSApple OSS Distributions expect_release_event(tp, &rel_seen);
850*fdd8201dSApple OSS Distributions expect_filtered_event(tp, &filt_seen);
851*fdd8201dSApple OSS Distributions expect_noprocfilt_event(tp, &noprocfilt_seen);
852*fdd8201dSApple OSS Distributions };
853*fdd8201dSApple OSS Distributions
854*fdd8201dSApple OSS Distributions if (use_all_callback) {
855*fdd8201dSApple OSS Distributions ktrace_events_all(s, evtcb);
856*fdd8201dSApple OSS Distributions } else {
857*fdd8201dSApple OSS Distributions ktrace_events_range(s, KDBG_EVENTID(DBG_BSD, DBG_BSD_KDEBUG_TEST, 0),
858*fdd8201dSApple OSS Distributions KDBG_EVENTID(DBG_BSD + 1, 0, 0), evtcb);
859*fdd8201dSApple OSS Distributions }
860*fdd8201dSApple OSS Distributions
861*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^{
862*fdd8201dSApple OSS Distributions ktrace_session_destroy(s);
863*fdd8201dSApple OSS Distributions cb(dev_seen, rel_seen, filt_seen, noprocfilt_seen);
864*fdd8201dSApple OSS Distributions T_END;
865*fdd8201dSApple OSS Distributions });
866*fdd8201dSApple OSS Distributions
867*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_start(s, dispatch_get_main_queue()), NULL);
868*fdd8201dSApple OSS Distributions assert_kdebug_test(KDBG_TEST_MACROS, "check test macros");
869*fdd8201dSApple OSS Distributions
870*fdd8201dSApple OSS Distributions ktrace_end(s, 0);
871*fdd8201dSApple OSS Distributions }
872*fdd8201dSApple OSS Distributions
873*fdd8201dSApple OSS Distributions T_DECL(kernel_events, "ensure kernel macros work")
874*fdd8201dSApple OSS Distributions {
875*fdd8201dSApple OSS Distributions start_controlling_ktrace();
876*fdd8201dSApple OSS Distributions
877*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
878*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "created session");
879*fdd8201dSApple OSS Distributions
880*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(ktrace_filter_pid(s, getpid()),
881*fdd8201dSApple OSS Distributions "filtered events to current process");
882*fdd8201dSApple OSS Distributions
883*fdd8201dSApple OSS Distributions expect_kdbg_test_events(s, false,
884*fdd8201dSApple OSS Distributions ^(unsigned int dev_seen, unsigned int rel_seen,
885*fdd8201dSApple OSS Distributions unsigned int filt_seen, unsigned int noprocfilt_seen) {
886*fdd8201dSApple OSS Distributions /*
887*fdd8201dSApple OSS Distributions * Development-only events are only filtered if running on an embedded
888*fdd8201dSApple OSS Distributions * OS.
889*fdd8201dSApple OSS Distributions */
890*fdd8201dSApple OSS Distributions unsigned int dev_exp;
891*fdd8201dSApple OSS Distributions #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
892*fdd8201dSApple OSS Distributions dev_exp = is_development_kernel() ? EXP_KERNEL_EVENTS : 0U;
893*fdd8201dSApple OSS Distributions #else
894*fdd8201dSApple OSS Distributions dev_exp = EXP_KERNEL_EVENTS;
895*fdd8201dSApple OSS Distributions #endif
896*fdd8201dSApple OSS Distributions
897*fdd8201dSApple OSS Distributions T_EXPECT_EQ(rel_seen, EXP_KERNEL_EVENTS,
898*fdd8201dSApple OSS Distributions "release and development events seen");
899*fdd8201dSApple OSS Distributions T_EXPECT_EQ(dev_seen, dev_exp, "development-only events %sseen",
900*fdd8201dSApple OSS Distributions dev_exp ? "" : "not ");
901*fdd8201dSApple OSS Distributions T_EXPECT_EQ(filt_seen, dev_exp, "filter-only events seen");
902*fdd8201dSApple OSS Distributions T_EXPECT_EQ(noprocfilt_seen, EXP_KERNEL_EVENTS,
903*fdd8201dSApple OSS Distributions "process filter-agnostic events seen");
904*fdd8201dSApple OSS Distributions });
905*fdd8201dSApple OSS Distributions
906*fdd8201dSApple OSS Distributions dispatch_main();
907*fdd8201dSApple OSS Distributions }
908*fdd8201dSApple OSS Distributions
909*fdd8201dSApple OSS Distributions T_DECL(kernel_events_filtered, "ensure that the filtered kernel macros work")
910*fdd8201dSApple OSS Distributions {
911*fdd8201dSApple OSS Distributions start_controlling_ktrace();
912*fdd8201dSApple OSS Distributions
913*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
914*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "created session");
915*fdd8201dSApple OSS Distributions
916*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(ktrace_filter_pid(s, getpid()),
917*fdd8201dSApple OSS Distributions "filtered events to current process");
918*fdd8201dSApple OSS Distributions
919*fdd8201dSApple OSS Distributions expect_kdbg_test_events(s, true,
920*fdd8201dSApple OSS Distributions ^(unsigned int dev_seen, unsigned int rel_seen,
921*fdd8201dSApple OSS Distributions unsigned int filt_seen, unsigned int noprocfilt_seen) {
922*fdd8201dSApple OSS Distributions T_EXPECT_EQ(rel_seen, EXP_KERNEL_EVENTS, NULL);
923*fdd8201dSApple OSS Distributions #if defined(__arm__) || defined(__arm64__)
924*fdd8201dSApple OSS Distributions T_EXPECT_EQ(dev_seen, is_development_kernel() ? EXP_KERNEL_EVENTS : 0U,
925*fdd8201dSApple OSS Distributions NULL);
926*fdd8201dSApple OSS Distributions #else
927*fdd8201dSApple OSS Distributions T_EXPECT_EQ(dev_seen, EXP_KERNEL_EVENTS,
928*fdd8201dSApple OSS Distributions "development-only events seen");
929*fdd8201dSApple OSS Distributions #endif /* defined(__arm__) || defined(__arm64__) */
930*fdd8201dSApple OSS Distributions T_EXPECT_EQ(filt_seen, 0U, "no filter-only events seen");
931*fdd8201dSApple OSS Distributions T_EXPECT_EQ(noprocfilt_seen, EXP_KERNEL_EVENTS,
932*fdd8201dSApple OSS Distributions "process filter-agnostic events seen");
933*fdd8201dSApple OSS Distributions });
934*fdd8201dSApple OSS Distributions
935*fdd8201dSApple OSS Distributions dispatch_main();
936*fdd8201dSApple OSS Distributions }
937*fdd8201dSApple OSS Distributions
938*fdd8201dSApple OSS Distributions T_DECL(kernel_events_noprocfilt,
939*fdd8201dSApple OSS Distributions "ensure that the no process filter kernel macros work")
940*fdd8201dSApple OSS Distributions {
941*fdd8201dSApple OSS Distributions start_controlling_ktrace();
942*fdd8201dSApple OSS Distributions
943*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
944*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "created session");
945*fdd8201dSApple OSS Distributions
946*fdd8201dSApple OSS Distributions /*
947*fdd8201dSApple OSS Distributions * Only allow launchd events through.
948*fdd8201dSApple OSS Distributions */
949*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_filter_pid(s, 1), "filtered events to launchd");
950*fdd8201dSApple OSS Distributions for (size_t i = 0; i < sizeof(noprocfilt_evts) / sizeof(noprocfilt_evts[0]); i++) {
951*fdd8201dSApple OSS Distributions T_QUIET;
952*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_ignore_process_filter_for_event(s,
953*fdd8201dSApple OSS Distributions noprocfilt_evts[i]),
954*fdd8201dSApple OSS Distributions "ignored process filter for noprocfilt event");
955*fdd8201dSApple OSS Distributions }
956*fdd8201dSApple OSS Distributions
957*fdd8201dSApple OSS Distributions expect_kdbg_test_events(s, false,
958*fdd8201dSApple OSS Distributions ^(unsigned int dev_seen, unsigned int rel_seen,
959*fdd8201dSApple OSS Distributions unsigned int filt_seen, unsigned int noprocfilt_seen) {
960*fdd8201dSApple OSS Distributions T_EXPECT_EQ(rel_seen, 0U, "release and development events not seen");
961*fdd8201dSApple OSS Distributions T_EXPECT_EQ(dev_seen, 0U, "development-only events not seen");
962*fdd8201dSApple OSS Distributions T_EXPECT_EQ(filt_seen, 0U, "filter-only events not seen");
963*fdd8201dSApple OSS Distributions
964*fdd8201dSApple OSS Distributions T_EXPECT_EQ(noprocfilt_seen, EXP_KERNEL_EVENTS,
965*fdd8201dSApple OSS Distributions "process filter-agnostic events seen");
966*fdd8201dSApple OSS Distributions });
967*fdd8201dSApple OSS Distributions
968*fdd8201dSApple OSS Distributions dispatch_main();
969*fdd8201dSApple OSS Distributions }
970*fdd8201dSApple OSS Distributions
971*fdd8201dSApple OSS Distributions static volatile bool continue_abuse = true;
972*fdd8201dSApple OSS Distributions
973*fdd8201dSApple OSS Distributions #define STRESS_DEBUGID (0xfeedfac0)
974*fdd8201dSApple OSS Distributions #define ABUSE_SECS (2)
975*fdd8201dSApple OSS Distributions #define TIMER_NS (100 * NSEC_PER_USEC)
976*fdd8201dSApple OSS Distributions /*
977*fdd8201dSApple OSS Distributions * Use the quantum as the gap threshold.
978*fdd8201dSApple OSS Distributions */
979*fdd8201dSApple OSS Distributions #define GAP_THRESHOLD_NS (10 * NSEC_PER_MSEC)
980*fdd8201dSApple OSS Distributions
981*fdd8201dSApple OSS Distributions static void *
kdebug_abuser_thread(void * ctx)982*fdd8201dSApple OSS Distributions kdebug_abuser_thread(void *ctx)
983*fdd8201dSApple OSS Distributions {
984*fdd8201dSApple OSS Distributions unsigned int id = (unsigned int)ctx;
985*fdd8201dSApple OSS Distributions uint64_t i = 0;
986*fdd8201dSApple OSS Distributions while (continue_abuse) {
987*fdd8201dSApple OSS Distributions kdebug_trace(STRESS_DEBUGID, id, i, 0, 0);
988*fdd8201dSApple OSS Distributions i++;
989*fdd8201dSApple OSS Distributions }
990*fdd8201dSApple OSS Distributions
991*fdd8201dSApple OSS Distributions return NULL;
992*fdd8201dSApple OSS Distributions }
993*fdd8201dSApple OSS Distributions
994*fdd8201dSApple OSS Distributions T_DECL(stress, "emit events on all but one CPU with a small buffer",
995*fdd8201dSApple OSS Distributions T_META_CHECK_LEAKS(false))
996*fdd8201dSApple OSS Distributions {
997*fdd8201dSApple OSS Distributions start_controlling_ktrace();
998*fdd8201dSApple OSS Distributions
999*fdd8201dSApple OSS Distributions T_SETUPBEGIN;
1000*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
1001*fdd8201dSApple OSS Distributions T_WITH_ERRNO; T_QUIET; T_ASSERT_NOTNULL(s, "ktrace_session_create");
1002*fdd8201dSApple OSS Distributions
1003*fdd8201dSApple OSS Distributions /* Let's not waste any time with pleasantries. */
1004*fdd8201dSApple OSS Distributions ktrace_set_uuid_map_enabled(s, KTRACE_FEATURE_DISABLED);
1005*fdd8201dSApple OSS Distributions
1006*fdd8201dSApple OSS Distributions /* Ouch. */
1007*fdd8201dSApple OSS Distributions ktrace_events_all(s, ^(__unused struct trace_point *tp) {});
1008*fdd8201dSApple OSS Distributions ktrace_set_vnode_paths_enabled(s, KTRACE_FEATURE_ENABLED);
1009*fdd8201dSApple OSS Distributions (void)atexit_b(^{ kperf_reset(); });
1010*fdd8201dSApple OSS Distributions (void)kperf_action_count_set(1);
1011*fdd8201dSApple OSS Distributions (void)kperf_timer_count_set(1);
1012*fdd8201dSApple OSS Distributions int kperror = kperf_timer_period_set(0, kperf_ns_to_ticks(TIMER_NS));
1013*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(kperror, "kperf_timer_period_set %llu ns",
1014*fdd8201dSApple OSS Distributions TIMER_NS);
1015*fdd8201dSApple OSS Distributions kperror = kperf_timer_action_set(0, 1);
1016*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(kperror, "kperf_timer_action_set");
1017*fdd8201dSApple OSS Distributions kperror = kperf_action_samplers_set(1, KPERF_SAMPLER_TINFO |
1018*fdd8201dSApple OSS Distributions KPERF_SAMPLER_TH_SNAPSHOT | KPERF_SAMPLER_KSTACK |
1019*fdd8201dSApple OSS Distributions KPERF_SAMPLER_USTACK | KPERF_SAMPLER_MEMINFO |
1020*fdd8201dSApple OSS Distributions KPERF_SAMPLER_TINFO_SCHED | KPERF_SAMPLER_TH_DISPATCH |
1021*fdd8201dSApple OSS Distributions KPERF_SAMPLER_TK_SNAPSHOT | KPERF_SAMPLER_SYS_MEM |
1022*fdd8201dSApple OSS Distributions KPERF_SAMPLER_TH_INSTRS_CYCLES);
1023*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(kperror, "kperf_action_samplers_set");
1024*fdd8201dSApple OSS Distributions /* You monster... */
1025*fdd8201dSApple OSS Distributions
1026*fdd8201dSApple OSS Distributions /* The coup-de-grace. */
1027*fdd8201dSApple OSS Distributions ktrace_set_buffer_size(s, 10);
1028*fdd8201dSApple OSS Distributions
1029*fdd8201dSApple OSS Distributions char filepath_arr[MAXPATHLEN] = "";
1030*fdd8201dSApple OSS Distributions strlcpy(filepath_arr, dt_tmpdir(), sizeof(filepath_arr));
1031*fdd8201dSApple OSS Distributions strlcat(filepath_arr, "/stress.ktrace", sizeof(filepath_arr));
1032*fdd8201dSApple OSS Distributions char *filepath = filepath_arr;
1033*fdd8201dSApple OSS Distributions
1034*fdd8201dSApple OSS Distributions int ncpus = 0;
1035*fdd8201dSApple OSS Distributions size_t ncpus_size = sizeof(ncpus);
1036*fdd8201dSApple OSS Distributions int ret = sysctlbyname("hw.logicalcpu_max", &ncpus, &ncpus_size, NULL, 0);
1037*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "sysctlbyname(\"hw.logicalcpu_max\"");
1038*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_GT(ncpus, 0, "realistic number of CPUs");
1039*fdd8201dSApple OSS Distributions
1040*fdd8201dSApple OSS Distributions pthread_t *threads = calloc((unsigned int)ncpus - 1, sizeof(pthread_t));
1041*fdd8201dSApple OSS Distributions T_WITH_ERRNO; T_QUIET; T_ASSERT_NOTNULL(threads, "calloc(%d threads)",
1042*fdd8201dSApple OSS Distributions ncpus - 1);
1043*fdd8201dSApple OSS Distributions
1044*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^{
1045*fdd8201dSApple OSS Distributions T_SETUPBEGIN;
1046*fdd8201dSApple OSS Distributions ktrace_session_destroy(s);
1047*fdd8201dSApple OSS Distributions
1048*fdd8201dSApple OSS Distributions T_LOG("trace ended, searching for gaps");
1049*fdd8201dSApple OSS Distributions
1050*fdd8201dSApple OSS Distributions ktrace_session_t sread = ktrace_session_create();
1051*fdd8201dSApple OSS Distributions T_WITH_ERRNO; T_QUIET; T_ASSERT_NOTNULL(sread, "ktrace_session_create");
1052*fdd8201dSApple OSS Distributions
1053*fdd8201dSApple OSS Distributions int error = ktrace_set_file(sread, filepath);
1054*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(error, "ktrace_set_file %s", filepath);
1055*fdd8201dSApple OSS Distributions
1056*fdd8201dSApple OSS Distributions ktrace_file_t f = ktrace_file_open(filepath, false);
1057*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(f, "ktrace_file_open %s",
1058*fdd8201dSApple OSS Distributions filepath);
1059*fdd8201dSApple OSS Distributions uint64_t first_timestamp = 0;
1060*fdd8201dSApple OSS Distributions error = ktrace_file_earliest_timestamp(f, &first_timestamp);
1061*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(error, "ktrace_file_earliest_timestamp");
1062*fdd8201dSApple OSS Distributions
1063*fdd8201dSApple OSS Distributions uint64_t last_timestamp = 0;
1064*fdd8201dSApple OSS Distributions (void)ktrace_file_latest_timestamp(f, &last_timestamp);
1065*fdd8201dSApple OSS Distributions
1066*fdd8201dSApple OSS Distributions __block uint64_t prev_timestamp = 0;
1067*fdd8201dSApple OSS Distributions __block uint64_t nevents = 0;
1068*fdd8201dSApple OSS Distributions ktrace_events_all(sread, ^(struct trace_point *tp) {
1069*fdd8201dSApple OSS Distributions nevents++;
1070*fdd8201dSApple OSS Distributions uint64_t delta_ns = 0;
1071*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_GE(tp->timestamp, prev_timestamp,
1072*fdd8201dSApple OSS Distributions "timestamps are monotonically increasing");
1073*fdd8201dSApple OSS Distributions int converror = ktrace_convert_timestamp_to_nanoseconds(sread,
1074*fdd8201dSApple OSS Distributions tp->timestamp - prev_timestamp, &delta_ns);
1075*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(converror, "convert timestamp to ns");
1076*fdd8201dSApple OSS Distributions if (prev_timestamp && delta_ns > GAP_THRESHOLD_NS) {
1077*fdd8201dSApple OSS Distributions if (tp->debugname) {
1078*fdd8201dSApple OSS Distributions T_LOG("gap: %gs at %llu - %llu on %d: %s (%#08x)",
1079*fdd8201dSApple OSS Distributions (double)delta_ns / 1e9, prev_timestamp,
1080*fdd8201dSApple OSS Distributions tp->timestamp, tp->cpuid, tp->debugname, tp->debugid);
1081*fdd8201dSApple OSS Distributions } else {
1082*fdd8201dSApple OSS Distributions T_LOG("gap: %gs at %llu - %llu on %d: %#x",
1083*fdd8201dSApple OSS Distributions (double)delta_ns / 1e9, prev_timestamp,
1084*fdd8201dSApple OSS Distributions tp->timestamp, tp->cpuid, tp->debugid);
1085*fdd8201dSApple OSS Distributions }
1086*fdd8201dSApple OSS Distributions
1087*fdd8201dSApple OSS Distributions /*
1088*fdd8201dSApple OSS Distributions * These gaps are ok -- they appear after CPUs are brought back
1089*fdd8201dSApple OSS Distributions * up.
1090*fdd8201dSApple OSS Distributions */
1091*fdd8201dSApple OSS Distributions #define INTERRUPT (0x1050000)
1092*fdd8201dSApple OSS Distributions #define PERF_CPU_IDLE (0x27001000)
1093*fdd8201dSApple OSS Distributions #define INTC_HANDLER (0x5000004)
1094*fdd8201dSApple OSS Distributions #define DECR_TRAP (0x1090000)
1095*fdd8201dSApple OSS Distributions uint32_t eventid = tp->debugid & KDBG_EVENTID_MASK;
1096*fdd8201dSApple OSS Distributions if (eventid != INTERRUPT && eventid != PERF_CPU_IDLE &&
1097*fdd8201dSApple OSS Distributions eventid != INTC_HANDLER && eventid != DECR_TRAP) {
1098*fdd8201dSApple OSS Distributions unsigned int lost_events = TRACE_LOST_EVENTS;
1099*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_EQ(tp->debugid, lost_events,
1100*fdd8201dSApple OSS Distributions "gaps should end with lost events");
1101*fdd8201dSApple OSS Distributions }
1102*fdd8201dSApple OSS Distributions }
1103*fdd8201dSApple OSS Distributions
1104*fdd8201dSApple OSS Distributions prev_timestamp = tp->timestamp;
1105*fdd8201dSApple OSS Distributions });
1106*fdd8201dSApple OSS Distributions ktrace_events_single(sread, TRACE_LOST_EVENTS, ^(struct trace_point *tp){
1107*fdd8201dSApple OSS Distributions T_LOG("lost: %llu on %d (%llu)", tp->timestamp, tp->cpuid, tp->arg1);
1108*fdd8201dSApple OSS Distributions });
1109*fdd8201dSApple OSS Distributions
1110*fdd8201dSApple OSS Distributions __block uint64_t last_write = 0;
1111*fdd8201dSApple OSS Distributions ktrace_events_single_paired(sread, TRACE_WRITING_EVENTS,
1112*fdd8201dSApple OSS Distributions ^(struct trace_point *start, struct trace_point *end) {
1113*fdd8201dSApple OSS Distributions uint64_t delta_ns;
1114*fdd8201dSApple OSS Distributions int converror = ktrace_convert_timestamp_to_nanoseconds(sread,
1115*fdd8201dSApple OSS Distributions start->timestamp - last_write, &delta_ns);
1116*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(converror, "convert timestamp to ns");
1117*fdd8201dSApple OSS Distributions
1118*fdd8201dSApple OSS Distributions uint64_t dur_ns;
1119*fdd8201dSApple OSS Distributions converror = ktrace_convert_timestamp_to_nanoseconds(sread,
1120*fdd8201dSApple OSS Distributions end->timestamp - start->timestamp, &dur_ns);
1121*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(converror, "convert timestamp to ns");
1122*fdd8201dSApple OSS Distributions
1123*fdd8201dSApple OSS Distributions T_LOG("write: %llu (+%gs): %gus on %d: %llu events", start->timestamp,
1124*fdd8201dSApple OSS Distributions (double)delta_ns / 1e9, (double)dur_ns / 1e3, end->cpuid, end->arg1);
1125*fdd8201dSApple OSS Distributions last_write = end->timestamp;
1126*fdd8201dSApple OSS Distributions });
1127*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(sread, ^{
1128*fdd8201dSApple OSS Distributions uint64_t duration_ns = 0;
1129*fdd8201dSApple OSS Distributions if (last_timestamp) {
1130*fdd8201dSApple OSS Distributions int converror = ktrace_convert_timestamp_to_nanoseconds(sread,
1131*fdd8201dSApple OSS Distributions last_timestamp - first_timestamp, &duration_ns);
1132*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(converror,
1133*fdd8201dSApple OSS Distributions "convert timestamp to ns");
1134*fdd8201dSApple OSS Distributions T_LOG("file was %gs long, %llu events: %g events/msec/cpu",
1135*fdd8201dSApple OSS Distributions (double)duration_ns / 1e9, nevents,
1136*fdd8201dSApple OSS Distributions (double)nevents / ((double)duration_ns / 1e6) / ncpus);
1137*fdd8201dSApple OSS Distributions }
1138*fdd8201dSApple OSS Distributions (void)unlink(filepath);
1139*fdd8201dSApple OSS Distributions ktrace_session_destroy(sread);
1140*fdd8201dSApple OSS Distributions T_END;
1141*fdd8201dSApple OSS Distributions });
1142*fdd8201dSApple OSS Distributions
1143*fdd8201dSApple OSS Distributions int starterror = ktrace_start(sread, dispatch_get_main_queue());
1144*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(starterror, "ktrace_start read session");
1145*fdd8201dSApple OSS Distributions
1146*fdd8201dSApple OSS Distributions T_SETUPEND;
1147*fdd8201dSApple OSS Distributions });
1148*fdd8201dSApple OSS Distributions
1149*fdd8201dSApple OSS Distributions /* Just kidding... for now. */
1150*fdd8201dSApple OSS Distributions #if 0
1151*fdd8201dSApple OSS Distributions kperror = kperf_sample_set(1);
1152*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(kperror,
1153*fdd8201dSApple OSS Distributions "started kperf timer sampling every %llu ns", TIMER_NS);
1154*fdd8201dSApple OSS Distributions #endif
1155*fdd8201dSApple OSS Distributions
1156*fdd8201dSApple OSS Distributions for (int i = 0; i < (ncpus - 1); i++) {
1157*fdd8201dSApple OSS Distributions int error = pthread_create(&threads[i], NULL, kdebug_abuser_thread,
1158*fdd8201dSApple OSS Distributions (void *)(uintptr_t)i);
1159*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(error,
1160*fdd8201dSApple OSS Distributions "pthread_create abuser thread %d", i);
1161*fdd8201dSApple OSS Distributions }
1162*fdd8201dSApple OSS Distributions
1163*fdd8201dSApple OSS Distributions int error = ktrace_start_writing_file(s, filepath,
1164*fdd8201dSApple OSS Distributions ktrace_compression_none, NULL, NULL);
1165*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(error, "started writing ktrace to %s", filepath);
1166*fdd8201dSApple OSS Distributions
1167*fdd8201dSApple OSS Distributions T_SETUPEND;
1168*fdd8201dSApple OSS Distributions
1169*fdd8201dSApple OSS Distributions dispatch_after(dispatch_time(DISPATCH_TIME_NOW, ABUSE_SECS * NSEC_PER_SEC),
1170*fdd8201dSApple OSS Distributions dispatch_get_main_queue(), ^{
1171*fdd8201dSApple OSS Distributions T_LOG("ending trace");
1172*fdd8201dSApple OSS Distributions ktrace_end(s, 1);
1173*fdd8201dSApple OSS Distributions
1174*fdd8201dSApple OSS Distributions continue_abuse = false;
1175*fdd8201dSApple OSS Distributions for (int i = 0; i < (ncpus - 1); i++) {
1176*fdd8201dSApple OSS Distributions int joinerror = pthread_join(threads[i], NULL);
1177*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_POSIX_ZERO(joinerror, "pthread_join thread %d",
1178*fdd8201dSApple OSS Distributions i);
1179*fdd8201dSApple OSS Distributions }
1180*fdd8201dSApple OSS Distributions });
1181*fdd8201dSApple OSS Distributions
1182*fdd8201dSApple OSS Distributions dispatch_main();
1183*fdd8201dSApple OSS Distributions }
1184*fdd8201dSApple OSS Distributions
1185*fdd8201dSApple OSS Distributions #define ROUND_TRIP_PERIOD UINT64_C(10 * 1000)
1186*fdd8201dSApple OSS Distributions #define ROUND_TRIPS_THRESHOLD UINT64_C(25)
1187*fdd8201dSApple OSS Distributions #define ROUND_TRIPS_TIMEOUT_SECS (2 * 60)
1188*fdd8201dSApple OSS Distributions #define COLLECTION_INTERVAL_MS 100
1189*fdd8201dSApple OSS Distributions
1190*fdd8201dSApple OSS Distributions /*
1191*fdd8201dSApple OSS Distributions * Test a sustained tracing session, involving multiple round-trips to the
1192*fdd8201dSApple OSS Distributions * kernel.
1193*fdd8201dSApple OSS Distributions *
1194*fdd8201dSApple OSS Distributions * Trace all events, and every `ROUND_TRIP_PERIOD` events, emit an event that's
1195*fdd8201dSApple OSS Distributions * unlikely to be emitted elsewhere. Look for this event, too, and make sure we
1196*fdd8201dSApple OSS Distributions * see as many of them as we emitted.
1197*fdd8201dSApple OSS Distributions *
1198*fdd8201dSApple OSS Distributions * After seeing `ROUND_TRIPS_THRESHOLD` of the unlikely events, end tracing.
1199*fdd8201dSApple OSS Distributions * In the failure mode, we won't see any of these, so set a timeout of
1200*fdd8201dSApple OSS Distributions * `ROUND_TRIPS_TIMEOUT_SECS` to prevent hanging, waiting for events that we'll
1201*fdd8201dSApple OSS Distributions * never see.
1202*fdd8201dSApple OSS Distributions */
1203*fdd8201dSApple OSS Distributions T_DECL(round_trips,
1204*fdd8201dSApple OSS Distributions "test sustained tracing with multiple round-trips through the kernel")
1205*fdd8201dSApple OSS Distributions {
1206*fdd8201dSApple OSS Distributions start_controlling_ktrace();
1207*fdd8201dSApple OSS Distributions
1208*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
1209*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "created session");
1210*fdd8201dSApple OSS Distributions
1211*fdd8201dSApple OSS Distributions /*
1212*fdd8201dSApple OSS Distributions * Set a small buffer and collection interval to increase the number of
1213*fdd8201dSApple OSS Distributions * round-trips.
1214*fdd8201dSApple OSS Distributions */
1215*fdd8201dSApple OSS Distributions ktrace_set_buffer_size(s, 50);
1216*fdd8201dSApple OSS Distributions ktrace_set_collection_interval(s, COLLECTION_INTERVAL_MS);
1217*fdd8201dSApple OSS Distributions
1218*fdd8201dSApple OSS Distributions __block uint64_t events = 0;
1219*fdd8201dSApple OSS Distributions __block uint64_t emitted = 0;
1220*fdd8201dSApple OSS Distributions __block uint64_t seen = 0;
1221*fdd8201dSApple OSS Distributions ktrace_events_all(s, ^(__unused struct trace_point *tp) {
1222*fdd8201dSApple OSS Distributions events++;
1223*fdd8201dSApple OSS Distributions if (events % ROUND_TRIP_PERIOD == 0) {
1224*fdd8201dSApple OSS Distributions T_LOG("emitting round-trip event %" PRIu64, emitted);
1225*fdd8201dSApple OSS Distributions kdebug_trace(TRACE_DEBUGID, events, 0, 0, 0);
1226*fdd8201dSApple OSS Distributions emitted++;
1227*fdd8201dSApple OSS Distributions }
1228*fdd8201dSApple OSS Distributions });
1229*fdd8201dSApple OSS Distributions
1230*fdd8201dSApple OSS Distributions ktrace_events_single(s, TRACE_DEBUGID, ^(__unused struct trace_point *tp) {
1231*fdd8201dSApple OSS Distributions T_LOG("saw round-trip event after %" PRIu64 " events", events);
1232*fdd8201dSApple OSS Distributions seen++;
1233*fdd8201dSApple OSS Distributions if (seen >= ROUND_TRIPS_THRESHOLD) {
1234*fdd8201dSApple OSS Distributions T_LOG("ending trace after seeing %" PRIu64 " events, "
1235*fdd8201dSApple OSS Distributions "emitting %" PRIu64, seen, emitted);
1236*fdd8201dSApple OSS Distributions ktrace_end(s, 1);
1237*fdd8201dSApple OSS Distributions }
1238*fdd8201dSApple OSS Distributions });
1239*fdd8201dSApple OSS Distributions
1240*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^{
1241*fdd8201dSApple OSS Distributions T_EXPECT_GE(emitted, ROUND_TRIPS_THRESHOLD,
1242*fdd8201dSApple OSS Distributions "emitted %" PRIu64 " round-trip events", emitted);
1243*fdd8201dSApple OSS Distributions T_EXPECT_GE(seen, ROUND_TRIPS_THRESHOLD,
1244*fdd8201dSApple OSS Distributions "saw %" PRIu64 " round-trip events", seen);
1245*fdd8201dSApple OSS Distributions ktrace_session_destroy(s);
1246*fdd8201dSApple OSS Distributions T_END;
1247*fdd8201dSApple OSS Distributions });
1248*fdd8201dSApple OSS Distributions
1249*fdd8201dSApple OSS Distributions int error = ktrace_start(s, dispatch_get_main_queue());
1250*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(error, "started tracing");
1251*fdd8201dSApple OSS Distributions
1252*fdd8201dSApple OSS Distributions dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
1253*fdd8201dSApple OSS Distributions ROUND_TRIPS_TIMEOUT_SECS * NSEC_PER_SEC), dispatch_get_main_queue(),
1254*fdd8201dSApple OSS Distributions ^{
1255*fdd8201dSApple OSS Distributions T_LOG("ending trace after %d seconds", ROUND_TRIPS_TIMEOUT_SECS);
1256*fdd8201dSApple OSS Distributions ktrace_end(s, 0);
1257*fdd8201dSApple OSS Distributions });
1258*fdd8201dSApple OSS Distributions
1259*fdd8201dSApple OSS Distributions dispatch_main();
1260*fdd8201dSApple OSS Distributions }
1261*fdd8201dSApple OSS Distributions
1262*fdd8201dSApple OSS Distributions #define HEARTBEAT_INTERVAL_SECS 1
1263*fdd8201dSApple OSS Distributions #define HEARTBEAT_COUNT 10
1264*fdd8201dSApple OSS Distributions
1265*fdd8201dSApple OSS Distributions /*
1266*fdd8201dSApple OSS Distributions * Ensure we see events periodically, checking for recent events on a
1267*fdd8201dSApple OSS Distributions * heart-beat.
1268*fdd8201dSApple OSS Distributions */
1269*fdd8201dSApple OSS Distributions T_DECL(event_coverage, "ensure events appear up to the end of tracing")
1270*fdd8201dSApple OSS Distributions {
1271*fdd8201dSApple OSS Distributions start_controlling_ktrace();
1272*fdd8201dSApple OSS Distributions
1273*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
1274*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "created session");
1275*fdd8201dSApple OSS Distributions
1276*fdd8201dSApple OSS Distributions __block uint64_t current_timestamp = 0;
1277*fdd8201dSApple OSS Distributions __block uint64_t events = 0;
1278*fdd8201dSApple OSS Distributions ktrace_events_all(s, ^(struct trace_point *tp) {
1279*fdd8201dSApple OSS Distributions current_timestamp = tp->timestamp;
1280*fdd8201dSApple OSS Distributions events++;
1281*fdd8201dSApple OSS Distributions });
1282*fdd8201dSApple OSS Distributions
1283*fdd8201dSApple OSS Distributions ktrace_set_buffer_size(s, 20);
1284*fdd8201dSApple OSS Distributions ktrace_set_collection_interval(s, COLLECTION_INTERVAL_MS);
1285*fdd8201dSApple OSS Distributions
1286*fdd8201dSApple OSS Distributions __block uint64_t last_timestamp = 0;
1287*fdd8201dSApple OSS Distributions __block uint64_t last_events = 0;
1288*fdd8201dSApple OSS Distributions __block unsigned int heartbeats = 0;
1289*fdd8201dSApple OSS Distributions
1290*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^{
1291*fdd8201dSApple OSS Distributions ktrace_session_destroy(s);
1292*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_GT(events, 0ULL, "should have seen some events");
1293*fdd8201dSApple OSS Distributions T_END;
1294*fdd8201dSApple OSS Distributions });
1295*fdd8201dSApple OSS Distributions
1296*fdd8201dSApple OSS Distributions dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
1297*fdd8201dSApple OSS Distributions 0, 0, dispatch_get_main_queue());
1298*fdd8201dSApple OSS Distributions dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW,
1299*fdd8201dSApple OSS Distributions HEARTBEAT_INTERVAL_SECS * NSEC_PER_SEC),
1300*fdd8201dSApple OSS Distributions HEARTBEAT_INTERVAL_SECS * NSEC_PER_SEC, 0);
1301*fdd8201dSApple OSS Distributions dispatch_source_set_cancel_handler(timer, ^{
1302*fdd8201dSApple OSS Distributions dispatch_release(timer);
1303*fdd8201dSApple OSS Distributions });
1304*fdd8201dSApple OSS Distributions
1305*fdd8201dSApple OSS Distributions dispatch_source_set_event_handler(timer, ^{
1306*fdd8201dSApple OSS Distributions heartbeats++;
1307*fdd8201dSApple OSS Distributions
1308*fdd8201dSApple OSS Distributions T_LOG("heartbeat %u at time %lld, seen %" PRIu64 " events, "
1309*fdd8201dSApple OSS Distributions "current event time %lld", heartbeats, mach_absolute_time(),
1310*fdd8201dSApple OSS Distributions events, current_timestamp);
1311*fdd8201dSApple OSS Distributions
1312*fdd8201dSApple OSS Distributions if (current_timestamp > 0) {
1313*fdd8201dSApple OSS Distributions T_EXPECT_GT(current_timestamp, last_timestamp,
1314*fdd8201dSApple OSS Distributions "event timestamps should be increasing");
1315*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_GT(events, last_events,
1316*fdd8201dSApple OSS Distributions "number of events should be increasing");
1317*fdd8201dSApple OSS Distributions }
1318*fdd8201dSApple OSS Distributions
1319*fdd8201dSApple OSS Distributions last_timestamp = current_timestamp;
1320*fdd8201dSApple OSS Distributions last_events = events;
1321*fdd8201dSApple OSS Distributions
1322*fdd8201dSApple OSS Distributions kdebug_trace(TRACE_DEBUGID, 0, 0, 0, 0);
1323*fdd8201dSApple OSS Distributions
1324*fdd8201dSApple OSS Distributions if (heartbeats >= HEARTBEAT_COUNT) {
1325*fdd8201dSApple OSS Distributions T_LOG("ending trace after %u heartbeats", HEARTBEAT_COUNT);
1326*fdd8201dSApple OSS Distributions ktrace_end(s, 0);
1327*fdd8201dSApple OSS Distributions }
1328*fdd8201dSApple OSS Distributions });
1329*fdd8201dSApple OSS Distributions
1330*fdd8201dSApple OSS Distributions int error = ktrace_start(s, dispatch_get_main_queue());
1331*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(error, "started tracing");
1332*fdd8201dSApple OSS Distributions
1333*fdd8201dSApple OSS Distributions dispatch_activate(timer);
1334*fdd8201dSApple OSS Distributions
1335*fdd8201dSApple OSS Distributions dispatch_main();
1336*fdd8201dSApple OSS Distributions }
1337*fdd8201dSApple OSS Distributions
1338*fdd8201dSApple OSS Distributions static unsigned int
set_nevents(unsigned int nevents)1339*fdd8201dSApple OSS Distributions set_nevents(unsigned int nevents)
1340*fdd8201dSApple OSS Distributions {
1341*fdd8201dSApple OSS Distributions T_QUIET;
1342*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(sysctl(
1343*fdd8201dSApple OSS Distributions (int[]){ CTL_KERN, KERN_KDEBUG, KERN_KDSETBUF, (int)nevents }, 4,
1344*fdd8201dSApple OSS Distributions NULL, 0, NULL, 0), "set kdebug buffer size");
1345*fdd8201dSApple OSS Distributions
1346*fdd8201dSApple OSS Distributions T_QUIET;
1347*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(sysctl(
1348*fdd8201dSApple OSS Distributions (int[]){ CTL_KERN, KERN_KDEBUG, KERN_KDSETUP, (int)nevents }, 4,
1349*fdd8201dSApple OSS Distributions NULL, 0, NULL, 0), "setup kdebug buffers");
1350*fdd8201dSApple OSS Distributions
1351*fdd8201dSApple OSS Distributions kbufinfo_t bufinfo = { 0 };
1352*fdd8201dSApple OSS Distributions T_QUIET;
1353*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(sysctl(
1354*fdd8201dSApple OSS Distributions (int[]){ CTL_KERN, KERN_KDEBUG, KERN_KDGETBUF }, 3,
1355*fdd8201dSApple OSS Distributions &bufinfo, &(size_t){ sizeof(bufinfo) }, NULL, 0),
1356*fdd8201dSApple OSS Distributions "get kdebug buffer size");
1357*fdd8201dSApple OSS Distributions
1358*fdd8201dSApple OSS Distributions T_QUIET;
1359*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(sysctl(
1360*fdd8201dSApple OSS Distributions (int[]){ CTL_KERN, KERN_KDEBUG, KERN_KDREMOVE }, 3,
1361*fdd8201dSApple OSS Distributions NULL, 0, NULL, 0),
1362*fdd8201dSApple OSS Distributions "remove kdebug buffers");
1363*fdd8201dSApple OSS Distributions
1364*fdd8201dSApple OSS Distributions return (unsigned int)bufinfo.nkdbufs;
1365*fdd8201dSApple OSS Distributions }
1366*fdd8201dSApple OSS Distributions
1367*fdd8201dSApple OSS Distributions T_DECL(set_buffer_size, "ensure large buffer sizes can be set")
1368*fdd8201dSApple OSS Distributions {
1369*fdd8201dSApple OSS Distributions T_SETUPBEGIN;
1370*fdd8201dSApple OSS Distributions uint64_t memsize = 0;
1371*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("hw.memsize", &memsize,
1372*fdd8201dSApple OSS Distributions &(size_t){ sizeof(memsize) }, NULL, 0), "sysctl hw.memsize");
1373*fdd8201dSApple OSS Distributions T_SETUPEND;
1374*fdd8201dSApple OSS Distributions
1375*fdd8201dSApple OSS Distributions #if TARGET_OS_IPHONE
1376*fdd8201dSApple OSS Distributions if (memsize >= (8ULL << 30)) {
1377*fdd8201dSApple OSS Distributions T_SKIP("skipping on iOS device with memory >= 8GB, rdar://79403304");
1378*fdd8201dSApple OSS Distributions }
1379*fdd8201dSApple OSS Distributions #endif // TARGET_OS_IPHONE
1380*fdd8201dSApple OSS Distributions
1381*fdd8201dSApple OSS Distributions start_controlling_ktrace();
1382*fdd8201dSApple OSS Distributions
1383*fdd8201dSApple OSS Distributions /*
1384*fdd8201dSApple OSS Distributions * Try to allocate up to one-eighth of available memory towards
1385*fdd8201dSApple OSS Distributions * tracing.
1386*fdd8201dSApple OSS Distributions */
1387*fdd8201dSApple OSS Distributions uint64_t maxevents_u64 = memsize / 8 / sizeof(kd_buf);
1388*fdd8201dSApple OSS Distributions if (maxevents_u64 > UINT32_MAX) {
1389*fdd8201dSApple OSS Distributions maxevents_u64 = UINT32_MAX;
1390*fdd8201dSApple OSS Distributions }
1391*fdd8201dSApple OSS Distributions unsigned int maxevents = (unsigned int)maxevents_u64;
1392*fdd8201dSApple OSS Distributions
1393*fdd8201dSApple OSS Distributions unsigned int minevents = set_nevents(0);
1394*fdd8201dSApple OSS Distributions T_ASSERT_GT(minevents, 0, "saw non-zero minimum event count of %u",
1395*fdd8201dSApple OSS Distributions minevents);
1396*fdd8201dSApple OSS Distributions
1397*fdd8201dSApple OSS Distributions unsigned int step = ((maxevents - minevents - 1) / 4);
1398*fdd8201dSApple OSS Distributions T_ASSERT_GT(step, 0, "stepping by %u events", step);
1399*fdd8201dSApple OSS Distributions
1400*fdd8201dSApple OSS Distributions for (unsigned int i = minevents + step; i < maxevents; i += step) {
1401*fdd8201dSApple OSS Distributions unsigned int actualevents = set_nevents(i);
1402*fdd8201dSApple OSS Distributions T_ASSERT_GE(actualevents, i - minevents,
1403*fdd8201dSApple OSS Distributions "%u events in kernel when %u requested", actualevents, i);
1404*fdd8201dSApple OSS Distributions }
1405*fdd8201dSApple OSS Distributions }
1406*fdd8201dSApple OSS Distributions
1407*fdd8201dSApple OSS Distributions static void *
donothing(__unused void * arg)1408*fdd8201dSApple OSS Distributions donothing(__unused void *arg)
1409*fdd8201dSApple OSS Distributions {
1410*fdd8201dSApple OSS Distributions return NULL;
1411*fdd8201dSApple OSS Distributions }
1412*fdd8201dSApple OSS Distributions
1413*fdd8201dSApple OSS Distributions T_DECL(long_names, "ensure long command names are reported")
1414*fdd8201dSApple OSS Distributions {
1415*fdd8201dSApple OSS Distributions start_controlling_ktrace();
1416*fdd8201dSApple OSS Distributions
1417*fdd8201dSApple OSS Distributions char longname[] = "thisisaverylongprocessname!";
1418*fdd8201dSApple OSS Distributions char *longname_ptr = longname;
1419*fdd8201dSApple OSS Distributions static_assert(sizeof(longname) > 16,
1420*fdd8201dSApple OSS Distributions "the name should be longer than MAXCOMLEN");
1421*fdd8201dSApple OSS Distributions
1422*fdd8201dSApple OSS Distributions int ret = sysctlbyname("kern.procname", NULL, NULL, longname,
1423*fdd8201dSApple OSS Distributions sizeof(longname));
1424*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ret,
1425*fdd8201dSApple OSS Distributions "use sysctl kern.procname to lengthen the name");
1426*fdd8201dSApple OSS Distributions
1427*fdd8201dSApple OSS Distributions ktrace_session_t ktsess = ktrace_session_create();
1428*fdd8201dSApple OSS Distributions
1429*fdd8201dSApple OSS Distributions /*
1430*fdd8201dSApple OSS Distributions * 32-bit kernels can only trace 16 bytes of the string in their event
1431*fdd8201dSApple OSS Distributions * arguments.
1432*fdd8201dSApple OSS Distributions */
1433*fdd8201dSApple OSS Distributions if (!ktrace_is_kernel_64_bit(ktsess)) {
1434*fdd8201dSApple OSS Distributions longname[16] = '\0';
1435*fdd8201dSApple OSS Distributions }
1436*fdd8201dSApple OSS Distributions
1437*fdd8201dSApple OSS Distributions ktrace_filter_pid(ktsess, getpid());
1438*fdd8201dSApple OSS Distributions
1439*fdd8201dSApple OSS Distributions __block bool saw_newthread = false;
1440*fdd8201dSApple OSS Distributions ktrace_events_single(ktsess, TRACE_STRING_NEWTHREAD,
1441*fdd8201dSApple OSS Distributions ^(struct trace_point *tp) {
1442*fdd8201dSApple OSS Distributions if (ktrace_get_pid_for_thread(ktsess, tp->threadid) ==
1443*fdd8201dSApple OSS Distributions getpid()) {
1444*fdd8201dSApple OSS Distributions saw_newthread = true;
1445*fdd8201dSApple OSS Distributions
1446*fdd8201dSApple OSS Distributions char argname[32] = {};
1447*fdd8201dSApple OSS Distributions strncat(argname, (char *)&tp->arg1, sizeof(tp->arg1));
1448*fdd8201dSApple OSS Distributions strncat(argname, (char *)&tp->arg2, sizeof(tp->arg2));
1449*fdd8201dSApple OSS Distributions strncat(argname, (char *)&tp->arg3, sizeof(tp->arg3));
1450*fdd8201dSApple OSS Distributions strncat(argname, (char *)&tp->arg4, sizeof(tp->arg4));
1451*fdd8201dSApple OSS Distributions
1452*fdd8201dSApple OSS Distributions T_EXPECT_EQ_STR((char *)argname, longname_ptr,
1453*fdd8201dSApple OSS Distributions "process name of new thread should be long");
1454*fdd8201dSApple OSS Distributions
1455*fdd8201dSApple OSS Distributions ktrace_end(ktsess, 1);
1456*fdd8201dSApple OSS Distributions }
1457*fdd8201dSApple OSS Distributions });
1458*fdd8201dSApple OSS Distributions
1459*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(ktsess, ^{
1460*fdd8201dSApple OSS Distributions ktrace_session_destroy(ktsess);
1461*fdd8201dSApple OSS Distributions T_EXPECT_TRUE(saw_newthread,
1462*fdd8201dSApple OSS Distributions "should have seen the new thread");
1463*fdd8201dSApple OSS Distributions T_END;
1464*fdd8201dSApple OSS Distributions });
1465*fdd8201dSApple OSS Distributions
1466*fdd8201dSApple OSS Distributions int error = ktrace_start(ktsess, dispatch_get_main_queue());
1467*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(error, "started tracing");
1468*fdd8201dSApple OSS Distributions
1469*fdd8201dSApple OSS Distributions pthread_t thread = NULL;
1470*fdd8201dSApple OSS Distributions error = pthread_create(&thread, NULL, donothing, NULL);
1471*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(error, "create new thread");
1472*fdd8201dSApple OSS Distributions
1473*fdd8201dSApple OSS Distributions dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC),
1474*fdd8201dSApple OSS Distributions dispatch_get_main_queue(), ^{
1475*fdd8201dSApple OSS Distributions ktrace_end(ktsess, 0);
1476*fdd8201dSApple OSS Distributions });
1477*fdd8201dSApple OSS Distributions
1478*fdd8201dSApple OSS Distributions error = pthread_join(thread, NULL);
1479*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(error, "join to thread");
1480*fdd8201dSApple OSS Distributions
1481*fdd8201dSApple OSS Distributions dispatch_main();
1482*fdd8201dSApple OSS Distributions }
1483*fdd8201dSApple OSS Distributions
1484*fdd8201dSApple OSS Distributions T_DECL(continuous_time, "make sure continuous time status can be queried",
1485*fdd8201dSApple OSS Distributions T_META_RUN_CONCURRENTLY(true))
1486*fdd8201dSApple OSS Distributions {
1487*fdd8201dSApple OSS Distributions bool cont_time = kdebug_using_continuous_time();
1488*fdd8201dSApple OSS Distributions T_ASSERT_FALSE(cont_time, "should not be using continuous time yet");
1489*fdd8201dSApple OSS Distributions }
1490*fdd8201dSApple OSS Distributions
1491*fdd8201dSApple OSS Distributions T_DECL(lookup_long_paths, "lookup long path names")
1492*fdd8201dSApple OSS Distributions {
1493*fdd8201dSApple OSS Distributions start_controlling_ktrace();
1494*fdd8201dSApple OSS Distributions
1495*fdd8201dSApple OSS Distributions int ret = chdir("/tmp");
1496*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "chdir to /tmp");
1497*fdd8201dSApple OSS Distributions const char *dir = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/";
1498*fdd8201dSApple OSS Distributions int i = 0;
1499*fdd8201dSApple OSS Distributions do {
1500*fdd8201dSApple OSS Distributions ret = mkdir(dir, S_IRUSR | S_IWUSR | S_IXUSR);
1501*fdd8201dSApple OSS Distributions if (ret >= 0 || errno != EEXIST) {
1502*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "mkdir of %d nested directory",
1503*fdd8201dSApple OSS Distributions i);
1504*fdd8201dSApple OSS Distributions }
1505*fdd8201dSApple OSS Distributions ret = chdir(dir);
1506*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "chdir to %d nested directory", i);
1507*fdd8201dSApple OSS Distributions } while (i++ < 40);
1508*fdd8201dSApple OSS Distributions
1509*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
1510*fdd8201dSApple OSS Distributions ktrace_set_collection_interval(s, 250);
1511*fdd8201dSApple OSS Distributions ktrace_filter_pid(s, getpid());
1512*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "created session");
1513*fdd8201dSApple OSS Distributions ktrace_events_single(s, VFS_LOOKUP, ^(struct trace_point *tp __unused){});
1514*fdd8201dSApple OSS Distributions ktrace_set_vnode_paths_enabled(s, KTRACE_FEATURE_ENABLED);
1515*fdd8201dSApple OSS Distributions
1516*fdd8201dSApple OSS Distributions dispatch_queue_t q = dispatch_queue_create("com.apple.kdebug-test", 0);
1517*fdd8201dSApple OSS Distributions
1518*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^{
1519*fdd8201dSApple OSS Distributions dispatch_release(q);
1520*fdd8201dSApple OSS Distributions T_END;
1521*fdd8201dSApple OSS Distributions });
1522*fdd8201dSApple OSS Distributions
1523*fdd8201dSApple OSS Distributions int error = ktrace_start(s, q);
1524*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(error, "started tracing");
1525*fdd8201dSApple OSS Distributions
1526*fdd8201dSApple OSS Distributions int fd = open("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", O_RDWR | O_CREAT);
1527*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(fd, "opened file at %d directories deep", i);
1528*fdd8201dSApple OSS Distributions
1529*fdd8201dSApple OSS Distributions sleep(5);
1530*fdd8201dSApple OSS Distributions
1531*fdd8201dSApple OSS Distributions T_LOG("ending tracing");
1532*fdd8201dSApple OSS Distributions ktrace_end(s, 0);
1533*fdd8201dSApple OSS Distributions dispatch_main();
1534*fdd8201dSApple OSS Distributions }
1535*fdd8201dSApple OSS Distributions
1536*fdd8201dSApple OSS Distributions #pragma mark - boot tracing
1537*fdd8201dSApple OSS Distributions
1538*fdd8201dSApple OSS Distributions static const char *expected_subsystems[] = {
1539*fdd8201dSApple OSS Distributions "tunables", "locks_early", "kprintf", "pmap_steal", "kmem", "zalloc",
1540*fdd8201dSApple OSS Distributions /* "percpu", only has a startup phase on Intel */
1541*fdd8201dSApple OSS Distributions "locks", "codesigning", "oslog", "early_boot",
1542*fdd8201dSApple OSS Distributions };
1543*fdd8201dSApple OSS Distributions #define EXPECTED_SUBSYSTEMS_LEN \
1544*fdd8201dSApple OSS Distributions (sizeof(expected_subsystems) / sizeof(expected_subsystems[0]))
1545*fdd8201dSApple OSS Distributions
1546*fdd8201dSApple OSS Distributions T_DECL(early_boot_tracing, "ensure early boot strings are present",
1547*fdd8201dSApple OSS Distributions T_META_BOOTARGS_SET("trace=100000"))
1548*fdd8201dSApple OSS Distributions {
1549*fdd8201dSApple OSS Distributions T_ATEND(reset_ktrace);
1550*fdd8201dSApple OSS Distributions
1551*fdd8201dSApple OSS Distributions T_SETUPBEGIN;
1552*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
1553*fdd8201dSApple OSS Distributions ktrace_set_collection_interval(s, 250);
1554*fdd8201dSApple OSS Distributions int error = ktrace_set_use_existing(s);
1555*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(error, "use existing trace buffer");
1556*fdd8201dSApple OSS Distributions
1557*fdd8201dSApple OSS Distributions #if defined(__x86_64__)
1558*fdd8201dSApple OSS Distributions #define FIRST_EVENT_STRING "i386_init"
1559*fdd8201dSApple OSS Distributions #else /* defined(__x86_64__) */
1560*fdd8201dSApple OSS Distributions #define FIRST_EVENT_STRING "kernel_startup_bootstrap"
1561*fdd8201dSApple OSS Distributions #endif /* !defined(__x86_64__) */
1562*fdd8201dSApple OSS Distributions
1563*fdd8201dSApple OSS Distributions __block bool seen_event = false;
1564*fdd8201dSApple OSS Distributions __block unsigned int cur_subsystem = 0;
1565*fdd8201dSApple OSS Distributions ktrace_events_single(s, TRACE_INFO_STRING, ^(struct trace_point *tp) {
1566*fdd8201dSApple OSS Distributions char early_str[33] = "";
1567*fdd8201dSApple OSS Distributions size_t argsize = ktrace_is_kernel_64_bit(s) ? 8 : 4;
1568*fdd8201dSApple OSS Distributions memcpy(early_str, &tp->arg1, argsize);
1569*fdd8201dSApple OSS Distributions memcpy(early_str + argsize, &tp->arg2, argsize);
1570*fdd8201dSApple OSS Distributions memcpy(early_str + argsize * 2, &tp->arg3, argsize);
1571*fdd8201dSApple OSS Distributions memcpy(early_str + argsize * 3, &tp->arg4, argsize);
1572*fdd8201dSApple OSS Distributions
1573*fdd8201dSApple OSS Distributions if (!seen_event) {
1574*fdd8201dSApple OSS Distributions T_LOG("found first string event with args: "
1575*fdd8201dSApple OSS Distributions "0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64,
1576*fdd8201dSApple OSS Distributions tp->arg1, tp->arg2, tp->arg3, tp->arg4);
1577*fdd8201dSApple OSS Distributions char expect_str[33] = FIRST_EVENT_STRING;
1578*fdd8201dSApple OSS Distributions if (!ktrace_is_kernel_64_bit(s)) {
1579*fdd8201dSApple OSS Distributions // Only the first 16 bytes of the string will be traced.
1580*fdd8201dSApple OSS Distributions expect_str[16] = '\0';
1581*fdd8201dSApple OSS Distributions }
1582*fdd8201dSApple OSS Distributions
1583*fdd8201dSApple OSS Distributions T_EXPECT_EQ_STR(early_str, expect_str,
1584*fdd8201dSApple OSS Distributions "first event in boot trace should be the bootstrap message");
1585*fdd8201dSApple OSS Distributions }
1586*fdd8201dSApple OSS Distributions seen_event = true;
1587*fdd8201dSApple OSS Distributions
1588*fdd8201dSApple OSS Distributions if (strcmp(early_str, expected_subsystems[cur_subsystem]) == 0) {
1589*fdd8201dSApple OSS Distributions T_LOG("found log for subsystem %s",
1590*fdd8201dSApple OSS Distributions expected_subsystems[cur_subsystem]);
1591*fdd8201dSApple OSS Distributions cur_subsystem++;
1592*fdd8201dSApple OSS Distributions }
1593*fdd8201dSApple OSS Distributions
1594*fdd8201dSApple OSS Distributions if (cur_subsystem == EXPECTED_SUBSYSTEMS_LEN) {
1595*fdd8201dSApple OSS Distributions T_LOG("ending after seeing all expected logs");
1596*fdd8201dSApple OSS Distributions ktrace_end(s, 1);
1597*fdd8201dSApple OSS Distributions }
1598*fdd8201dSApple OSS Distributions });
1599*fdd8201dSApple OSS Distributions
1600*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^{
1601*fdd8201dSApple OSS Distributions T_EXPECT_TRUE(seen_event, "should see an early boot string event");
1602*fdd8201dSApple OSS Distributions T_EXPECT_TRUE(cur_subsystem == EXPECTED_SUBSYSTEMS_LEN,
1603*fdd8201dSApple OSS Distributions "should see logs from all subsystems");
1604*fdd8201dSApple OSS Distributions if (cur_subsystem != EXPECTED_SUBSYSTEMS_LEN) {
1605*fdd8201dSApple OSS Distributions T_LOG("missing log for %s", expected_subsystems[cur_subsystem]);
1606*fdd8201dSApple OSS Distributions }
1607*fdd8201dSApple OSS Distributions T_END;
1608*fdd8201dSApple OSS Distributions });
1609*fdd8201dSApple OSS Distributions
1610*fdd8201dSApple OSS Distributions error = ktrace_start(s, dispatch_get_main_queue());
1611*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(error, "started tracing");
1612*fdd8201dSApple OSS Distributions
1613*fdd8201dSApple OSS Distributions T_SETUPEND;
1614*fdd8201dSApple OSS Distributions
1615*fdd8201dSApple OSS Distributions dispatch_main();
1616*fdd8201dSApple OSS Distributions }
1617*fdd8201dSApple OSS Distributions
1618*fdd8201dSApple OSS Distributions T_DECL(typefilter_boot_arg, "ensure typefilter is set up correctly at boot",
1619*fdd8201dSApple OSS Distributions T_META_BOOTARGS_SET("trace=100000 trace_typefilter=S0x0c00,C0xfe"))
1620*fdd8201dSApple OSS Distributions {
1621*fdd8201dSApple OSS Distributions T_ATEND(reset_ktrace);
1622*fdd8201dSApple OSS Distributions
1623*fdd8201dSApple OSS Distributions T_SETUPBEGIN;
1624*fdd8201dSApple OSS Distributions ktrace_config_t config = ktrace_config_create_current();
1625*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO;
1626*fdd8201dSApple OSS Distributions T_ASSERT_NOTNULL(config, "create config from current system");
1627*fdd8201dSApple OSS Distributions T_SETUPEND;
1628*fdd8201dSApple OSS Distributions
1629*fdd8201dSApple OSS Distributions T_LOG("ktrace configuration:");
1630*fdd8201dSApple OSS Distributions ktrace_config_print_description(config, stdout);
1631*fdd8201dSApple OSS Distributions
1632*fdd8201dSApple OSS Distributions uint8_t *typefilt = ktrace_config_kdebug_get_typefilter(config);
1633*fdd8201dSApple OSS Distributions T_ASSERT_NOTNULL(typefilt, "typefilter is active");
1634*fdd8201dSApple OSS Distributions T_EXPECT_TRUE(typefilt[0x0c00 / 8],
1635*fdd8201dSApple OSS Distributions "specified subclass is set in typefilter");
1636*fdd8201dSApple OSS Distributions T_MAYFAIL; // rdar://63625062 (UTD converts commas in boot-args to spaces)
1637*fdd8201dSApple OSS Distributions T_EXPECT_TRUE(typefilt[0xfeed / 8],
1638*fdd8201dSApple OSS Distributions "specified class is set in typefilter");
1639*fdd8201dSApple OSS Distributions
1640*fdd8201dSApple OSS Distributions ktrace_config_destroy(config);
1641*fdd8201dSApple OSS Distributions }
1642*fdd8201dSApple OSS Distributions
1643*fdd8201dSApple OSS Distributions #pragma mark - events present
1644*fdd8201dSApple OSS Distributions
1645*fdd8201dSApple OSS Distributions static int recvd_sigchild = 0;
1646*fdd8201dSApple OSS Distributions static void
sighandler(int sig)1647*fdd8201dSApple OSS Distributions sighandler(int sig)
1648*fdd8201dSApple OSS Distributions {
1649*fdd8201dSApple OSS Distributions if (sig != SIGCHLD) {
1650*fdd8201dSApple OSS Distributions T_ASSERT_FAIL("unexpected signal: %d", sig);
1651*fdd8201dSApple OSS Distributions }
1652*fdd8201dSApple OSS Distributions recvd_sigchild = 1;
1653*fdd8201dSApple OSS Distributions }
1654*fdd8201dSApple OSS Distributions
1655*fdd8201dSApple OSS Distributions T_DECL(instrs_and_cycles_on_proc_exit,
1656*fdd8201dSApple OSS Distributions "instructions and cycles should be traced on thread exit",
1657*fdd8201dSApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("kern.monotonic.supported", 1))
1658*fdd8201dSApple OSS Distributions {
1659*fdd8201dSApple OSS Distributions T_SETUPBEGIN;
1660*fdd8201dSApple OSS Distributions start_controlling_ktrace();
1661*fdd8201dSApple OSS Distributions int error;
1662*fdd8201dSApple OSS Distributions struct rusage_info_v4 *rusage = calloc(1, sizeof(*rusage));
1663*fdd8201dSApple OSS Distributions char *args[] = { "ls", "-l", NULL, };
1664*fdd8201dSApple OSS Distributions int status;
1665*fdd8201dSApple OSS Distributions dispatch_queue_t q = dispatch_queue_create("com.apple.kdebug-test",
1666*fdd8201dSApple OSS Distributions DISPATCH_QUEUE_SERIAL);
1667*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(signal(SIGCHLD, sighandler),
1668*fdd8201dSApple OSS Distributions "register signal handler");
1669*fdd8201dSApple OSS Distributions
1670*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
1671*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "ktrace_session_create");
1672*fdd8201dSApple OSS Distributions
1673*fdd8201dSApple OSS Distributions __block pid_t pid;
1674*fdd8201dSApple OSS Distributions __block bool seen_event = false;
1675*fdd8201dSApple OSS Distributions __block uint64_t proc_instrs = 0;
1676*fdd8201dSApple OSS Distributions __block uint64_t proc_cycles = 0;
1677*fdd8201dSApple OSS Distributions __block uint64_t proc_sys_time = 0;
1678*fdd8201dSApple OSS Distributions __block uint64_t proc_usr_time = 0;
1679*fdd8201dSApple OSS Distributions error = ktrace_events_single(s, DBG_MT_INSTRS_CYCLES_PROC_EXIT,
1680*fdd8201dSApple OSS Distributions ^(ktrace_event_t tp){
1681*fdd8201dSApple OSS Distributions if (tp->pid == pid) {
1682*fdd8201dSApple OSS Distributions seen_event = true;
1683*fdd8201dSApple OSS Distributions proc_instrs = tp->arg1;
1684*fdd8201dSApple OSS Distributions proc_cycles = tp->arg2;
1685*fdd8201dSApple OSS Distributions proc_sys_time = tp->arg3;
1686*fdd8201dSApple OSS Distributions proc_usr_time = tp->arg4;
1687*fdd8201dSApple OSS Distributions ktrace_end(s, 1);
1688*fdd8201dSApple OSS Distributions }
1689*fdd8201dSApple OSS Distributions });
1690*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_POSIX_ZERO(error, "trace single event");
1691*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^{
1692*fdd8201dSApple OSS Distributions // TODO Check for equality once rdar://61948669 is fixed.
1693*fdd8201dSApple OSS Distributions T_ASSERT_GE(proc_instrs, rusage->ri_instructions,
1694*fdd8201dSApple OSS Distributions "trace event instrs are >= to rusage instrs");
1695*fdd8201dSApple OSS Distributions T_ASSERT_GE(proc_cycles, rusage->ri_cycles,
1696*fdd8201dSApple OSS Distributions "trace event cycles are >= to rusage cycles");
1697*fdd8201dSApple OSS Distributions T_ASSERT_GE(proc_sys_time, rusage->ri_system_time,
1698*fdd8201dSApple OSS Distributions "trace event sys time is >= rusage sys time");
1699*fdd8201dSApple OSS Distributions T_ASSERT_GE(proc_usr_time, rusage->ri_user_time,
1700*fdd8201dSApple OSS Distributions "trace event usr time >= rusage usr time");
1701*fdd8201dSApple OSS Distributions T_EXPECT_TRUE(seen_event, "should see the proc exit trace event");
1702*fdd8201dSApple OSS Distributions
1703*fdd8201dSApple OSS Distributions free(rusage);
1704*fdd8201dSApple OSS Distributions ktrace_session_destroy(s);
1705*fdd8201dSApple OSS Distributions dispatch_release(q);
1706*fdd8201dSApple OSS Distributions T_END;
1707*fdd8201dSApple OSS Distributions });
1708*fdd8201dSApple OSS Distributions error = ktrace_start(s, q);
1709*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(error, "start tracing");
1710*fdd8201dSApple OSS Distributions T_SETUPEND;
1711*fdd8201dSApple OSS Distributions
1712*fdd8201dSApple OSS Distributions extern char **environ;
1713*fdd8201dSApple OSS Distributions status = posix_spawnp(&pid, args[0], NULL, NULL, args, environ);
1714*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(status, "spawn process");
1715*fdd8201dSApple OSS Distributions if (status == 0) {
1716*fdd8201dSApple OSS Distributions while (!recvd_sigchild) {
1717*fdd8201dSApple OSS Distributions pause();
1718*fdd8201dSApple OSS Distributions }
1719*fdd8201dSApple OSS Distributions error = proc_pid_rusage(pid, RUSAGE_INFO_V4, (rusage_info_t)rusage);
1720*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(error, "rusage");
1721*fdd8201dSApple OSS Distributions error = waitpid(pid, &status, 0);
1722*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(error, "waitpid");
1723*fdd8201dSApple OSS Distributions }
1724*fdd8201dSApple OSS Distributions dispatch_main();
1725*fdd8201dSApple OSS Distributions }
1726*fdd8201dSApple OSS Distributions
1727*fdd8201dSApple OSS Distributions #define NO_OF_THREADS 2
1728*fdd8201dSApple OSS Distributions
1729*fdd8201dSApple OSS Distributions struct thread_counters_info {
1730*fdd8201dSApple OSS Distributions struct thsc_cpi counts;
1731*fdd8201dSApple OSS Distributions uint64_t cpu_time;
1732*fdd8201dSApple OSS Distributions uint64_t thread_id;
1733*fdd8201dSApple OSS Distributions };
1734*fdd8201dSApple OSS Distributions typedef struct thread_counters_info *tc_info_t;
1735*fdd8201dSApple OSS Distributions
1736*fdd8201dSApple OSS Distributions static void*
get_thread_counters(void * ptr)1737*fdd8201dSApple OSS Distributions get_thread_counters(void* ptr)
1738*fdd8201dSApple OSS Distributions {
1739*fdd8201dSApple OSS Distributions extern uint64_t __thread_selfusage(void);
1740*fdd8201dSApple OSS Distributions extern uint64_t __thread_selfid(void);
1741*fdd8201dSApple OSS Distributions tc_info_t tc_info = (tc_info_t) ptr;
1742*fdd8201dSApple OSS Distributions tc_info->thread_id = __thread_selfid();
1743*fdd8201dSApple OSS Distributions // Just to increase the instr, cycle count
1744*fdd8201dSApple OSS Distributions T_LOG("printing %llu\n", tc_info->thread_id);
1745*fdd8201dSApple OSS Distributions tc_info->cpu_time = __thread_selfusage();
1746*fdd8201dSApple OSS Distributions (void)thread_selfcounts_cpi(&tc_info->counts);
1747*fdd8201dSApple OSS Distributions return NULL;
1748*fdd8201dSApple OSS Distributions }
1749*fdd8201dSApple OSS Distributions
1750*fdd8201dSApple OSS Distributions T_DECL(instrs_and_cycles_on_thread_exit,
1751*fdd8201dSApple OSS Distributions "instructions and cycles should be traced on thread exit",
1752*fdd8201dSApple OSS Distributions T_META_REQUIRES_SYSCTL_EQ("kern.monotonic.supported", 1))
1753*fdd8201dSApple OSS Distributions {
1754*fdd8201dSApple OSS Distributions T_SETUPBEGIN;
1755*fdd8201dSApple OSS Distributions start_controlling_ktrace();
1756*fdd8201dSApple OSS Distributions
1757*fdd8201dSApple OSS Distributions int error;
1758*fdd8201dSApple OSS Distributions pthread_t *threads = calloc((unsigned int)(NO_OF_THREADS),
1759*fdd8201dSApple OSS Distributions sizeof(pthread_t));
1760*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(threads, "calloc(%d threads)",
1761*fdd8201dSApple OSS Distributions NO_OF_THREADS);
1762*fdd8201dSApple OSS Distributions tc_info_t tc_infos = calloc((unsigned int) (NO_OF_THREADS),
1763*fdd8201dSApple OSS Distributions sizeof(struct thread_counters_info));
1764*fdd8201dSApple OSS Distributions T_WITH_ERRNO; T_QUIET; T_ASSERT_NOTNULL(tc_infos,
1765*fdd8201dSApple OSS Distributions "calloc(%d thread counters)", NO_OF_THREADS);
1766*fdd8201dSApple OSS Distributions
1767*fdd8201dSApple OSS Distributions ktrace_session_t s = ktrace_session_create();
1768*fdd8201dSApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(s, "ktrace_session_create");
1769*fdd8201dSApple OSS Distributions ktrace_filter_pid(s, getpid());
1770*fdd8201dSApple OSS Distributions
1771*fdd8201dSApple OSS Distributions __block int nevents = 0;
1772*fdd8201dSApple OSS Distributions error = ktrace_events_single(s, DBG_MT_INSTRS_CYCLES_THR_EXIT,
1773*fdd8201dSApple OSS Distributions ^(ktrace_event_t tp) {
1774*fdd8201dSApple OSS Distributions for (int i = 0; i < NO_OF_THREADS; i++) {
1775*fdd8201dSApple OSS Distributions if (tp->threadid == tc_infos[i].thread_id) {
1776*fdd8201dSApple OSS Distributions nevents++;
1777*fdd8201dSApple OSS Distributions uint64_t cpu_time = tp->arg3 + tp->arg4;
1778*fdd8201dSApple OSS Distributions /*
1779*fdd8201dSApple OSS Distributions * as we are getting counts before thread exit,
1780*fdd8201dSApple OSS Distributions * the counts at thread exit should be greater than
1781*fdd8201dSApple OSS Distributions * thread_selfcounts
1782*fdd8201dSApple OSS Distributions */
1783*fdd8201dSApple OSS Distributions T_ASSERT_GE(tp->arg1, tc_infos[i].counts.tcpi_instructions,
1784*fdd8201dSApple OSS Distributions "trace event instrs are >= to thread's instrs");
1785*fdd8201dSApple OSS Distributions T_ASSERT_GE(tp->arg2, tc_infos[i].counts.tcpi_cycles,
1786*fdd8201dSApple OSS Distributions "trace event cycles are >= to thread's cycles");
1787*fdd8201dSApple OSS Distributions T_ASSERT_GE(cpu_time, tc_infos[i].cpu_time,
1788*fdd8201dSApple OSS Distributions "trace event cpu time is >= thread's cpu time");
1789*fdd8201dSApple OSS Distributions }
1790*fdd8201dSApple OSS Distributions if (nevents == NO_OF_THREADS) {
1791*fdd8201dSApple OSS Distributions ktrace_end(s, 1);
1792*fdd8201dSApple OSS Distributions }
1793*fdd8201dSApple OSS Distributions }
1794*fdd8201dSApple OSS Distributions });
1795*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(error, "trace single event");
1796*fdd8201dSApple OSS Distributions ktrace_set_completion_handler(s, ^{
1797*fdd8201dSApple OSS Distributions T_EXPECT_EQ(NO_OF_THREADS, nevents, "seen %d thread exit trace events",
1798*fdd8201dSApple OSS Distributions NO_OF_THREADS);
1799*fdd8201dSApple OSS Distributions free(tc_infos);
1800*fdd8201dSApple OSS Distributions ktrace_session_destroy(s);
1801*fdd8201dSApple OSS Distributions T_END;
1802*fdd8201dSApple OSS Distributions });
1803*fdd8201dSApple OSS Distributions error = ktrace_start(s, dispatch_get_main_queue());
1804*fdd8201dSApple OSS Distributions T_ASSERT_POSIX_ZERO(error, "start tracing");
1805*fdd8201dSApple OSS Distributions
1806*fdd8201dSApple OSS Distributions for (int i = 0; i < NO_OF_THREADS; i++) {
1807*fdd8201dSApple OSS Distributions error = pthread_create(&threads[i], NULL, get_thread_counters,
1808*fdd8201dSApple OSS Distributions (void *)&tc_infos[i]);
1809*fdd8201dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(error, "pthread_create thread %d", i);
1810*fdd8201dSApple OSS Distributions }
1811*fdd8201dSApple OSS Distributions T_SETUPEND;
1812*fdd8201dSApple OSS Distributions for (int i = 0; i < NO_OF_THREADS; i++) {
1813*fdd8201dSApple OSS Distributions error = pthread_join(threads[i], NULL);
1814*fdd8201dSApple OSS Distributions T_QUIET; T_EXPECT_POSIX_ZERO(error, "pthread_join thread %d", i);
1815*fdd8201dSApple OSS Distributions }
1816*fdd8201dSApple OSS Distributions
1817*fdd8201dSApple OSS Distributions dispatch_main();
1818*fdd8201dSApple OSS Distributions }
1819