]>
Commit | Line | Data |
---|---|---|
39037602 A |
1 | /* |
2 | * Copyright (c) 2013-2015 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
24 | #ifndef __OS_TRACE_H__ | |
25 | #define __OS_TRACE_H__ | |
26 | ||
27 | #include <Availability.h> | |
28 | #include <os/base.h> | |
29 | #include <sys/types.h> | |
30 | #include <stdint.h> | |
31 | #include <stdbool.h> | |
32 | #include <stdarg.h> | |
33 | #if __has_include(<xpc/xpc.h>) | |
34 | #include <xpc/xpc.h> | |
35 | #else | |
36 | typedef void *xpc_object_t; | |
37 | #endif | |
38 | ||
39 | #if !__GNUC__ | |
40 | #error "must be GNU C compatible" | |
41 | #endif | |
42 | ||
43 | __BEGIN_DECLS | |
44 | ||
45 | extern void *__dso_handle; | |
46 | ||
47 | OS_ALWAYS_INLINE | |
48 | static inline void | |
49 | _os_trace_verify_printf(const char *msg, ...) __attribute__((format(printf, 1, 2))) | |
50 | { | |
51 | #pragma unused(msg) | |
52 | } | |
53 | ||
54 | #if !defined OS_COUNT_ARGS | |
55 | #define OS_COUNT_ARGS(...) OS_COUNT_ARGS1(, ##__VA_ARGS__, _8, _7, _6, _5, _4, _3, _2, _1, _0) | |
56 | #define OS_COUNT_ARGS1(z, a, b, c, d, e, f, g, h, cnt, ...) cnt | |
57 | #endif | |
58 | ||
59 | /* use old macros for anything less than iOS 10 and MacOS 10.12 */ | |
60 | #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0) \ | |
61 | || (defined(__WATCH_OS_VERSION_MIN_REQUIRED) && __WATCH_OS_VERSION_MIN_REQUIRED < __WATCHOS_3_0) \ | |
62 | || (defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < __TVOS_10_0) \ | |
63 | || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_12) | |
64 | ||
65 | #define _os_trace_0(_l, _m, _t) __extension__({ \ | |
66 | _os_trace_verify_printf(_l); \ | |
67 | _os_trace_with_buffer(&__dso_handle, _m, _t, NULL, 0, NULL); \ | |
68 | __asm__(""); /* avoid tailcall */ \ | |
69 | }) | |
70 | ||
71 | #define _os_trace_1(_l, _m, _t, _1) __extension__({ \ | |
72 | _Pragma("clang diagnostic push") \ | |
73 | _Pragma("clang diagnostic ignored \"-Wpacked\"") \ | |
74 | const __typeof__(_1) _c1 = _1; \ | |
75 | _os_trace_verify_printf(_l, _c1); \ | |
76 | const struct __attribute__((packed)) { \ | |
77 | __typeof__(_c1) _f1; \ | |
78 | uint8_t _s[1]; \ | |
79 | uint8_t _cnt; \ | |
80 | } _buf = { \ | |
81 | ._f1 = _c1, ._s[0] = sizeof(_c1), \ | |
82 | ._cnt = 1, \ | |
83 | }; \ | |
84 | _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), NULL); \ | |
85 | __asm__(""); /* avoid tailcall */ \ | |
86 | _Pragma("clang diagnostic pop") \ | |
87 | }) | |
88 | ||
89 | #define _os_trace_2(_l, _m, _t, _1, _2) __extension__({ \ | |
90 | _Pragma("clang diagnostic push") \ | |
91 | _Pragma("clang diagnostic ignored \"-Wpacked\"") \ | |
92 | const __typeof__(_1) _c1 = _1; \ | |
93 | const __typeof__(_2) _c2 = _2; \ | |
94 | _os_trace_verify_printf(_l, _c1, _c2); \ | |
95 | const struct __attribute__((packed)) { \ | |
96 | __typeof__(_c1) _f1; \ | |
97 | __typeof__(_c2) _f2; \ | |
98 | uint8_t _s[2]; \ | |
99 | uint8_t _cnt; \ | |
100 | } _buf = { \ | |
101 | ._f1 = _c1, ._s[0] = sizeof(_c1), \ | |
102 | ._f2 = _c2, ._s[1] = sizeof(_c2), \ | |
103 | ._cnt = 2, \ | |
104 | }; \ | |
105 | _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), NULL); \ | |
106 | __asm__(""); /* avoid tailcall */ \ | |
107 | _Pragma("clang diagnostic pop") \ | |
108 | }) | |
109 | ||
110 | #define _os_trace_3(_l, _m, _t, _1, _2, _3) __extension__({ \ | |
111 | _Pragma("clang diagnostic push") \ | |
112 | _Pragma("clang diagnostic ignored \"-Wpacked\"") \ | |
113 | const __typeof__(_1) _c1 = _1; \ | |
114 | const __typeof__(_2) _c2 = _2; \ | |
115 | const __typeof__(_3) _c3 = _3; \ | |
116 | _os_trace_verify_printf(_l, _c1, _c2, _c3); \ | |
117 | const struct __attribute__((packed)) { \ | |
118 | __typeof__(_c1) _f1; \ | |
119 | __typeof__(_c2) _f2; \ | |
120 | __typeof__(_c3) _f3; \ | |
121 | uint8_t _s[3]; \ | |
122 | uint8_t _cnt; \ | |
123 | } _buf = { \ | |
124 | ._f1 = _c1, ._s[0] = sizeof(_c1), \ | |
125 | ._f2 = _c2, ._s[1] = sizeof(_c2), \ | |
126 | ._f3 = _c3, ._s[2] = sizeof(_c3), \ | |
127 | ._cnt = 3, \ | |
128 | }; \ | |
129 | _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), NULL); \ | |
130 | __asm__(""); /* avoid tailcall */ \ | |
131 | _Pragma("clang diagnostic pop") \ | |
132 | }) | |
133 | ||
134 | #define _os_trace_4(_l, _m, _t, _1, _2, _3, _4) __extension__({ \ | |
135 | _Pragma("clang diagnostic push") \ | |
136 | _Pragma("clang diagnostic ignored \"-Wpacked\"") \ | |
137 | const __typeof__(_1) _c1 = _1; \ | |
138 | const __typeof__(_2) _c2 = _2; \ | |
139 | const __typeof__(_3) _c3 = _3; \ | |
140 | const __typeof__(_4) _c4 = _4; \ | |
141 | _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4); \ | |
142 | const struct __attribute__((packed)) { \ | |
143 | __typeof__(_c1) _f1; \ | |
144 | __typeof__(_c2) _f2; \ | |
145 | __typeof__(_c3) _f3; \ | |
146 | __typeof__(_c4) _f4; \ | |
147 | uint8_t _s[4]; \ | |
148 | uint8_t _cnt; \ | |
149 | } _buf = { \ | |
150 | ._f1 = _c1, ._s[0] = sizeof(_c1), \ | |
151 | ._f2 = _c2, ._s[1] = sizeof(_c2), \ | |
152 | ._f3 = _c3, ._s[2] = sizeof(_c3), \ | |
153 | ._f4 = _c4, ._s[3] = sizeof(_c4), \ | |
154 | ._cnt = 4, \ | |
155 | }; \ | |
156 | _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), NULL); \ | |
157 | __asm__(""); /* avoid tailcall */ \ | |
158 | _Pragma("clang diagnostic pop") \ | |
159 | }) | |
160 | ||
161 | #define _os_trace_5(_l, _m, _t, _1, _2, _3, _4, _5) __extension__({ \ | |
162 | _Pragma("clang diagnostic push") \ | |
163 | _Pragma("clang diagnostic ignored \"-Wpacked\"") \ | |
164 | const __typeof__(_1) _c1 = _1; \ | |
165 | const __typeof__(_2) _c2 = _2; \ | |
166 | const __typeof__(_3) _c3 = _3; \ | |
167 | const __typeof__(_4) _c4 = _4; \ | |
168 | const __typeof__(_5) _c5 = _5; \ | |
169 | _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4, _c5); \ | |
170 | const struct __attribute__((packed)) { \ | |
171 | __typeof__(_c1) _f1; \ | |
172 | __typeof__(_c2) _f2; \ | |
173 | __typeof__(_c3) _f3; \ | |
174 | __typeof__(_c4) _f4; \ | |
175 | __typeof__(_c5) _f5; \ | |
176 | uint8_t _s[5]; \ | |
177 | uint8_t _cnt; \ | |
178 | } _buf = { \ | |
179 | ._f1 = _c1, ._s[0] = sizeof(_c1), \ | |
180 | ._f2 = _c2, ._s[1] = sizeof(_c2), \ | |
181 | ._f3 = _c3, ._s[2] = sizeof(_c3), \ | |
182 | ._f4 = _c4, ._s[3] = sizeof(_c4), \ | |
183 | ._f5 = _c5, ._s[4] = sizeof(_c5), \ | |
184 | ._cnt = 5, \ | |
185 | }; \ | |
186 | _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), NULL); \ | |
187 | __asm__(""); /* avoid tailcall */ \ | |
188 | _Pragma("clang diagnostic pop") \ | |
189 | }) | |
190 | ||
191 | #define _os_trace_6(_l, _m, _t, _1, _2, _3, _4, _5, _6) __extension__({ \ | |
192 | _Pragma("clang diagnostic push") \ | |
193 | _Pragma("clang diagnostic ignored \"-Wpacked\"") \ | |
194 | const __typeof__(_1) _c1 = _1; \ | |
195 | const __typeof__(_2) _c2 = _2; \ | |
196 | const __typeof__(_3) _c3 = _3; \ | |
197 | const __typeof__(_4) _c4 = _4; \ | |
198 | const __typeof__(_5) _c5 = _5; \ | |
199 | const __typeof__(_6) _c6 = _6; \ | |
200 | _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4, _c5, _c6); \ | |
201 | const struct __attribute__((packed)) { \ | |
202 | __typeof__(_c1) _f1; \ | |
203 | __typeof__(_c2) _f2; \ | |
204 | __typeof__(_c3) _f3; \ | |
205 | __typeof__(_c4) _f4; \ | |
206 | __typeof__(_c5) _f5; \ | |
207 | __typeof__(_c6) _f6; \ | |
208 | uint8_t _s[6]; \ | |
209 | uint8_t _cnt; \ | |
210 | } _buf = { \ | |
211 | ._f1 = _c1, ._s[0] = sizeof(_c1), \ | |
212 | ._f2 = _c2, ._s[1] = sizeof(_c2), \ | |
213 | ._f3 = _c3, ._s[2] = sizeof(_c3), \ | |
214 | ._f4 = _c4, ._s[3] = sizeof(_c4), \ | |
215 | ._f5 = _c5, ._s[4] = sizeof(_c5), \ | |
216 | ._f6 = _c6, ._s[5] = sizeof(_c6), \ | |
217 | ._cnt = 6, \ | |
218 | }; \ | |
219 | _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), NULL); \ | |
220 | __asm__(""); /* avoid tailcall */ \ | |
221 | _Pragma("clang diagnostic pop") \ | |
222 | }) | |
223 | ||
224 | #define _os_trace_7(_l, _m, _t, _1, _2, _3, _4, _5, _6, _7) __extension__({ \ | |
225 | _Pragma("clang diagnostic push") \ | |
226 | _Pragma("clang diagnostic ignored \"-Wpacked\"") \ | |
227 | const __typeof__(_1) _c1 = _1; \ | |
228 | const __typeof__(_2) _c2 = _2; \ | |
229 | const __typeof__(_3) _c3 = _3; \ | |
230 | const __typeof__(_4) _c4 = _4; \ | |
231 | const __typeof__(_5) _c5 = _5; \ | |
232 | const __typeof__(_6) _c6 = _6; \ | |
233 | const __typeof__(_7) _c7 = _7; \ | |
234 | _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4, _c5, _c6, _c7); \ | |
235 | const struct __attribute__((packed)) { \ | |
236 | __typeof__(_c1) _f1; \ | |
237 | __typeof__(_c2) _f2; \ | |
238 | __typeof__(_c3) _f3; \ | |
239 | __typeof__(_c4) _f4; \ | |
240 | __typeof__(_c5) _f5; \ | |
241 | __typeof__(_c6) _f6; \ | |
242 | __typeof__(_c7) _f7; \ | |
243 | uint8_t _s[7]; \ | |
244 | uint8_t _cnt; \ | |
245 | } _buf = { \ | |
246 | ._f1 = _c1, ._s[0] = sizeof(_c1), \ | |
247 | ._f2 = _c2, ._s[1] = sizeof(_c2), \ | |
248 | ._f3 = _c3, ._s[2] = sizeof(_c3), \ | |
249 | ._f4 = _c4, ._s[3] = sizeof(_c4), \ | |
250 | ._f5 = _c5, ._s[4] = sizeof(_c5), \ | |
251 | ._f6 = _c6, ._s[5] = sizeof(_c6), \ | |
252 | ._f7 = _c7, ._s[6] = sizeof(_c7), \ | |
253 | ._cnt = 7, \ | |
254 | }; \ | |
255 | _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), NULL); \ | |
256 | __asm__(""); /* avoid tailcall */ \ | |
257 | _Pragma("clang diagnostic pop") \ | |
258 | }) | |
259 | ||
260 | #define _os_trace_with_payload_1(_l, _m, _t, _payload) __extension__({ \ | |
261 | _os_trace_verify_printf(_l); \ | |
262 | _os_trace_with_buffer(&__dso_handle, _m, _t, NULL, 0, _payload); \ | |
263 | __asm__(""); /* avoid tailcall */ \ | |
264 | }) | |
265 | ||
266 | #define _os_trace_with_payload_2(_l, _m, _t, _1, _payload) __extension__({ \ | |
267 | _Pragma("clang diagnostic push") \ | |
268 | _Pragma("clang diagnostic ignored \"-Wpacked\"") \ | |
269 | const __typeof__(_1) _c1 = _1; \ | |
270 | _os_trace_verify_printf(_l, _c1); \ | |
271 | const struct __attribute__((packed)) { \ | |
272 | __typeof__(_c1) _f1; \ | |
273 | uint8_t _s[1]; \ | |
274 | uint8_t _cnt; \ | |
275 | } _buf = { \ | |
276 | ._f1 = _c1, ._s[0] = sizeof(_c1), \ | |
277 | ._cnt = 1, \ | |
278 | }; \ | |
279 | _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), _payload); \ | |
280 | __asm__(""); /* avoid tailcall */ \ | |
281 | _Pragma("clang diagnostic pop") \ | |
282 | }) | |
283 | ||
284 | #define _os_trace_with_payload_3(_l, _m, _t, _1, _2, _payload) __extension__({ \ | |
285 | _Pragma("clang diagnostic push") \ | |
286 | _Pragma("clang diagnostic ignored \"-Wpacked\"") \ | |
287 | const __typeof__(_1) _c1 = _1; \ | |
288 | const __typeof__(_2) _c2 = _2; \ | |
289 | _os_trace_verify_printf(_l, _c1, _c2); \ | |
290 | const struct __attribute__((packed)) { \ | |
291 | __typeof__(_c1) _f1; \ | |
292 | __typeof__(_c2) _f2; \ | |
293 | uint8_t _s[2]; \ | |
294 | uint8_t _cnt; \ | |
295 | } _buf = { \ | |
296 | ._f1 = _c1, ._s[0] = sizeof(_c1), \ | |
297 | ._f2 = _c2, ._s[1] = sizeof(_c2), \ | |
298 | ._cnt = 2, \ | |
299 | }; \ | |
300 | _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), _payload); \ | |
301 | __asm__(""); /* avoid tailcall */ \ | |
302 | _Pragma("clang diagnostic pop") \ | |
303 | }) | |
304 | ||
305 | #define _os_trace_with_payload_4(_l, _m, _t, _1, _2, _3, _payload) __extension__({ \ | |
306 | _Pragma("clang diagnostic push") \ | |
307 | _Pragma("clang diagnostic ignored \"-Wpacked\"") \ | |
308 | const __typeof__(_1) _c1 = _1; \ | |
309 | const __typeof__(_2) _c2 = _2; \ | |
310 | const __typeof__(_3) _c3 = _3; \ | |
311 | _os_trace_verify_printf(_l, _c1, _c2, _c3); \ | |
312 | const struct __attribute__((packed)) { \ | |
313 | __typeof__(_c1) _f1; \ | |
314 | __typeof__(_c2) _f2; \ | |
315 | __typeof__(_c3) _f3; \ | |
316 | uint8_t _s[3]; \ | |
317 | uint8_t _cnt; \ | |
318 | } _buf = { \ | |
319 | ._f1 = _c1, ._s[0] = sizeof(_c1), \ | |
320 | ._f2 = _c2, ._s[1] = sizeof(_c2), \ | |
321 | ._f3 = _c3, ._s[2] = sizeof(_c3), \ | |
322 | ._cnt = 3, \ | |
323 | }; \ | |
324 | _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), _payload); \ | |
325 | __asm__(""); /* avoid tailcall */ \ | |
326 | _Pragma("clang diagnostic pop") \ | |
327 | }) | |
328 | ||
329 | #define _os_trace_with_payload_5(_l, _m, _t, _1, _2, _3, _4, _payload) __extension__({ \ | |
330 | _Pragma("clang diagnostic push") \ | |
331 | _Pragma("clang diagnostic ignored \"-Wpacked\"") \ | |
332 | const __typeof__(_1) _c1 = _1; \ | |
333 | const __typeof__(_2) _c2 = _2; \ | |
334 | const __typeof__(_3) _c3 = _3; \ | |
335 | const __typeof__(_4) _c4 = _4; \ | |
336 | _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4); \ | |
337 | const struct __attribute__((packed)) { \ | |
338 | __typeof__(_c1) _f1; \ | |
339 | __typeof__(_c2) _f2; \ | |
340 | __typeof__(_c3) _f3; \ | |
341 | __typeof__(_c4) _f4; \ | |
342 | uint8_t _s[4]; \ | |
343 | uint8_t _cnt; \ | |
344 | } _buf = { \ | |
345 | ._f1 = _c1, ._s[0] = sizeof(_c1), \ | |
346 | ._f2 = _c2, ._s[1] = sizeof(_c2), \ | |
347 | ._f3 = _c3, ._s[2] = sizeof(_c3), \ | |
348 | ._f4 = _c4, ._s[3] = sizeof(_c4), \ | |
349 | ._cnt = 4, \ | |
350 | }; \ | |
351 | _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), _payload); \ | |
352 | __asm__(""); /* avoid tailcall */ \ | |
353 | _Pragma("clang diagnostic pop") \ | |
354 | }) | |
355 | ||
356 | #define _os_trace_with_payload_6(_l, _m, _t, _1, _2, _3, _4, _5, _payload) __extension__({ \ | |
357 | _Pragma("clang diagnostic push") \ | |
358 | _Pragma("clang diagnostic ignored \"-Wpacked\"") \ | |
359 | const __typeof__(_1) _c1 = _1; \ | |
360 | const __typeof__(_2) _c2 = _2; \ | |
361 | const __typeof__(_3) _c3 = _3; \ | |
362 | const __typeof__(_4) _c4 = _4; \ | |
363 | const __typeof__(_4) _c5 = _5; \ | |
364 | _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4, _c5); \ | |
365 | const struct __attribute__((packed)) { \ | |
366 | __typeof__(_c1) _f1; \ | |
367 | __typeof__(_c2) _f2; \ | |
368 | __typeof__(_c3) _f3; \ | |
369 | __typeof__(_c4) _f4; \ | |
370 | __typeof__(_c5) _f5; \ | |
371 | uint8_t _s[5]; \ | |
372 | uint8_t _cnt; \ | |
373 | } _buf = { \ | |
374 | ._f1 = _c1, ._s[0] = sizeof(_c1), \ | |
375 | ._f2 = _c2, ._s[1] = sizeof(_c2), \ | |
376 | ._f3 = _c3, ._s[2] = sizeof(_c3), \ | |
377 | ._f4 = _c4, ._s[3] = sizeof(_c4), \ | |
378 | ._f5 = _c5, ._s[4] = sizeof(_c5), \ | |
379 | ._cnt = 5, \ | |
380 | }; \ | |
381 | _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), _payload); \ | |
382 | __asm__(""); /* avoid tailcall */ \ | |
383 | _Pragma("clang diagnostic pop") \ | |
384 | }) | |
385 | ||
386 | #define _os_trace_with_payload_7(_l, _m, _t, _1, _2, _3, _4, _5, _6, _payload) __extension__({ \ | |
387 | _Pragma("clang diagnostic push") \ | |
388 | _Pragma("clang diagnostic ignored \"-Wpacked\"") \ | |
389 | const __typeof__(_1) _c1 = _1; \ | |
390 | const __typeof__(_2) _c2 = _2; \ | |
391 | const __typeof__(_3) _c3 = _3; \ | |
392 | const __typeof__(_4) _c4 = _4; \ | |
393 | const __typeof__(_5) _c5 = _5; \ | |
394 | const __typeof__(_6) _c6 = _6; \ | |
395 | _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4, _c5, _c6); \ | |
396 | const struct __attribute__((packed)) { \ | |
397 | __typeof__(_c1) _f1; \ | |
398 | __typeof__(_c2) _f2; \ | |
399 | __typeof__(_c3) _f3; \ | |
400 | __typeof__(_c4) _f4; \ | |
401 | __typeof__(_c5) _f5; \ | |
402 | __typeof__(_c6) _f6; \ | |
403 | uint8_t _s[6]; \ | |
404 | uint8_t _cnt; \ | |
405 | } _buf = { \ | |
406 | ._f1 = _c1, ._s[0] = sizeof(_c1), \ | |
407 | ._f2 = _c2, ._s[1] = sizeof(_c2), \ | |
408 | ._f3 = _c3, ._s[2] = sizeof(_c3), \ | |
409 | ._f4 = _c4, ._s[3] = sizeof(_c4), \ | |
410 | ._f5 = _c5, ._s[4] = sizeof(_c5), \ | |
411 | ._f6 = _c6, ._s[5] = sizeof(_c6), \ | |
412 | ._cnt = 6, \ | |
413 | }; \ | |
414 | _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), _payload); \ | |
415 | __asm__(""); /* avoid tailcall */ \ | |
416 | _Pragma("clang diagnostic pop") \ | |
417 | }) | |
418 | ||
419 | #define _os_trace_with_payload_8(_l, _m, _t, _1, _2, _3, _4, _5, _6, _7, _payload) __extension__({ \ | |
420 | _Pragma("clang diagnostic push") \ | |
421 | _Pragma("clang diagnostic ignored \"-Wpacked\"") \ | |
422 | const __typeof__(_1) _c1 = _1; \ | |
423 | const __typeof__(_2) _c2 = _2; \ | |
424 | const __typeof__(_3) _c3 = _3; \ | |
425 | const __typeof__(_4) _c4 = _4; \ | |
426 | const __typeof__(_5) _c5 = _5; \ | |
427 | const __typeof__(_6) _c6 = _6; \ | |
428 | const __typeof__(_7) _c7 = _7; \ | |
429 | _os_trace_verify_printf(_l, _c1, _c2, _c3, _c4, _c5, _c6, _c7); \ | |
430 | const struct __attribute__((packed)) { \ | |
431 | __typeof__(_c1) _f1; \ | |
432 | __typeof__(_c2) _f2; \ | |
433 | __typeof__(_c3) _f3; \ | |
434 | __typeof__(_c4) _f4; \ | |
435 | __typeof__(_c5) _f5; \ | |
436 | __typeof__(_c6) _f6; \ | |
437 | __typeof__(_c7) _f7; \ | |
438 | uint8_t _s[7]; \ | |
439 | uint8_t _cnt; \ | |
440 | } _buf = { \ | |
441 | ._f1 = _c1, ._s[0] = sizeof(_c1), \ | |
442 | ._f2 = _c2, ._s[1] = sizeof(_c2), \ | |
443 | ._f3 = _c3, ._s[2] = sizeof(_c3), \ | |
444 | ._f4 = _c4, ._s[3] = sizeof(_c4), \ | |
445 | ._f5 = _c5, ._s[4] = sizeof(_c5), \ | |
446 | ._f6 = _c6, ._s[5] = sizeof(_c6), \ | |
447 | ._f7 = _c7, ._s[6] = sizeof(_c7), \ | |
448 | ._cnt = 7, \ | |
449 | }; \ | |
450 | _os_trace_with_buffer(&__dso_handle, _m, _t, &_buf, sizeof(_buf), _payload); \ | |
451 | __asm__(""); /* avoid tailcall */ \ | |
452 | _Pragma("clang diagnostic pop") \ | |
453 | }) | |
454 | ||
455 | #define OS_TRACE_CALL(format, _m, _t, ...) __extension__({ \ | |
456 | _Pragma("clang diagnostic push") \ | |
457 | _Pragma("clang diagnostic ignored \"-Wc++98-compat-pedantic\"") \ | |
458 | OS_CONCAT(_os_trace, OS_COUNT_ARGS(__VA_ARGS__))(format, _m, _t, ##__VA_ARGS__); \ | |
459 | _Pragma("clang diagnostic pop") \ | |
460 | }) | |
461 | ||
462 | #else | |
463 | ||
464 | // Use a new layout in Mac OS 10.12+ and iOS 10.0+ | |
465 | #define OS_TRACE_CALL(_l, _m, _t, ...) __extension__({ \ | |
466 | uint8_t buf[1024]; \ | |
467 | _os_trace_verify_printf(_l, ##__VA_ARGS__); \ | |
468 | size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, ##__VA_ARGS__); \ | |
469 | _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, NULL); \ | |
470 | __asm__(""); /* avoid tailcall */ \ | |
471 | }) | |
472 | ||
473 | #define _os_trace_with_payload_1(_l, _m, _t, _payload) __extension__({ \ | |
474 | _os_trace_verify_printf(_l); \ | |
475 | _os_trace_internal(&__dso_handle, _t, _m, NULL, 0, _payload); \ | |
476 | __asm__(""); /* avoid tailcall */ \ | |
477 | }) | |
478 | ||
479 | #define _os_trace_with_payload_2(_l, _m, _t, _1, _payload) __extension__({ \ | |
480 | _os_trace_verify_printf(_l, _1); \ | |
481 | uint8_t buf[1024]; \ | |
482 | size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, _1); \ | |
483 | _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, _payload); \ | |
484 | __asm__(""); /* avoid tailcall */ \ | |
485 | }) | |
486 | ||
487 | #define _os_trace_with_payload_3(_l, _m, _t, _1, _2, _payload) __extension__({ \ | |
488 | _os_trace_verify_printf(_l, _1, _2); \ | |
489 | uint8_t buf[1024]; \ | |
490 | size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, _1, _2); \ | |
491 | _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, _payload); \ | |
492 | __asm__(""); /* avoid tailcall */ \ | |
493 | }) | |
494 | ||
495 | #define _os_trace_with_payload_4(_l, _m, _t, _1, _2, _3, _payload) __extension__({ \ | |
496 | _os_trace_verify_printf(_l, _1, _2, _3); \ | |
497 | uint8_t buf[1024]; \ | |
498 | size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, _1, _2, _3); \ | |
499 | _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, _payload); \ | |
500 | __asm__(""); /* avoid tailcall */ \ | |
501 | }) | |
502 | ||
503 | #define _os_trace_with_payload_5(_l, _m, _t, _1, _2, _3, _4, _payload) __extension__({ \ | |
504 | _os_trace_verify_printf(_l, _1, _2, _3, _4); \ | |
505 | uint8_t buf[1024]; \ | |
506 | size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, _1, _2, _3, _4); \ | |
507 | _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, _payload); \ | |
508 | __asm__(""); /* avoid tailcall */ \ | |
509 | }) | |
510 | ||
511 | #define _os_trace_with_payload_6(_l, _m, _t, _1, _2, _3, _4, _5, _payload) __extension__({ \ | |
512 | _os_trace_verify_printf(_l, _1, _2, _3, _4, _5); \ | |
513 | uint8_t buf[1024]; \ | |
514 | size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, _1, _2, _3, _4, _5); \ | |
515 | _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, _payload); \ | |
516 | __asm__(""); /* avoid tailcall */ \ | |
517 | }) | |
518 | ||
519 | #define _os_trace_with_payload_7(_l, _m, _t, _1, _2, _3, _4, _5, _6, _payload) __extension__({ \ | |
520 | _os_trace_verify_printf(_l, _1, _2, _3, _4, _5, _6); \ | |
521 | uint8_t buf[1024]; \ | |
522 | size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, _1, _2, _3, _4, _5, _6); \ | |
523 | _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, _payload); \ | |
524 | __asm__(""); /* avoid tailcall */ \ | |
525 | }) | |
526 | ||
527 | #define _os_trace_with_payload_8(_l, _m, _t, _1, _2, _3, _4, _5, _6, _7, _payload) __extension__({ \ | |
528 | _os_trace_verify_printf(_l, _1, _2, _3, _4, _5, _6, _7); \ | |
529 | uint8_t buf[1024]; \ | |
530 | size_t buf_size = _os_trace_encode(buf, sizeof(buf), _m, _1, _2, _3, _4, _5, _6, _7); \ | |
531 | _os_trace_internal(&__dso_handle, _t, _m, buf, buf_size, _payload); \ | |
532 | __asm__(""); /* avoid tailcall */ \ | |
533 | }) | |
534 | ||
535 | #endif /* if Mac OS >= 10.12 or iPhone OS >= 10.0 */ | |
536 | ||
537 | /*! | |
538 | * | |
539 | * @abstract | |
540 | * Hashtags in trace messages | |
541 | * | |
542 | * @discussion | |
543 | * Developers are encouraged to include hashtags in log messages, regardless of what API you use. | |
544 | * A hashtag is composed of a hash (#) symbol, followed by at least three non-whitespace characters, | |
545 | * terminated by whitespace or the end of the message. Hashtags may not begin with a number. | |
546 | * | |
547 | * Below is the list of predefined tags: | |
548 | * #System - Message in the context of a system process. | |
549 | * #User - Message in the context of a user process. | |
550 | * #Developer - Message in the context of software development. For example, deprecated APIs and debugging messages. | |
551 | * #Attention - Message that should be investigated by a system administrator, because it may be a sign of a larger issue. | |
552 | * For example, errors from a hard drive controller that typically occur when the drive is about to fail. | |
553 | * #Critical - Message in the context of a critical event or critical failure. | |
554 | * #Error - Message that is a noncritical error. | |
555 | * #Comment - Message that is a comment. | |
556 | * #Marker - Message that marks a change to divide the messages around it into those before and those after the change. | |
557 | * #Clue - Message containing extra key/value pairs with additional information to help reconstruct the context. | |
558 | * #Security - Message related to security concerns. | |
559 | * #Filesystem - Message describing a file system related event. | |
560 | * #Network - Message describing a network-related event. | |
561 | * #Hardware - Message describing a hardware-related event. | |
562 | * #CPU - Message describing CPU related event, e.g., initiating heavy work load | |
563 | * #State - Message describing state changed, e.g., global state, preference, etc. | |
564 | * #Graphics - Message describing significant graphics event | |
565 | * #Disk - Message describing disk activity | |
566 | * | |
567 | */ | |
568 | ||
569 | #pragma mark - Other defines | |
570 | ||
571 | /*! | |
572 | * @define OS_TRACE_TYPE_RELEASE | |
573 | * Trace messages to be captured on a typical user install. These should be | |
574 | * limited to things which improve diagnosis of a failure/crash/hang. Trace | |
575 | * buffers are generally smaller on a production system. | |
576 | */ | |
577 | #define OS_TRACE_TYPE_RELEASE (1u << 0) | |
578 | ||
579 | /*! | |
580 | * @define OS_TRACE_TYPE_DEBUG | |
581 | * Trace messages to be captured while debugger or other development tool is | |
582 | * attached to the originator. | |
583 | */ | |
584 | #define OS_TRACE_TYPE_DEBUG (1u << 1) | |
585 | ||
586 | /*! | |
587 | * @define OS_TRACE_TYPE_INFO | |
588 | * Trace messages that are captured when a debugger is attached, system or | |
589 | * Application mode has been increased to include additional information. | |
590 | */ | |
591 | #define OS_TRACE_TYPE_INFO (1u << 2) | |
592 | ||
593 | /*! | |
594 | * @define OS_TRACE_TYPE_ERROR | |
595 | * Trace the message as an error and force a collection as a failure may be | |
596 | * imminent. | |
597 | */ | |
598 | #define OS_TRACE_TYPE_ERROR ((1u << 6) | (1u << 0)) | |
599 | ||
600 | /*! | |
601 | * @define OS_TRACE_TYPE_FAULT | |
602 | * Trace the message as a fatal error which forces a collection and a diagnostic | |
603 | * to be initiated. | |
604 | */ | |
605 | #define OS_TRACE_TYPE_FAULT ((1u << 7) | (1u << 6) | (1u << 0)) | |
606 | ||
607 | /*! | |
608 | * @typedef os_trace_payload_t | |
609 | * A block that populates an xpc_object_t of type XPC_TYPE_DICTIONARY to represent | |
610 | * complex data. This block will only be invoked under conditions where tools | |
611 | * have attached to the process. The payload can be used to send arbitrary data | |
612 | * via the trace call. Tools may use the data to validate state for integration | |
613 | * tests or provide other introspection services. No assumptions are made about | |
614 | * the format or structure of the data. | |
615 | */ | |
616 | typedef void (^os_trace_payload_t)(xpc_object_t xdict); | |
617 | ||
618 | #pragma mark - function declarations | |
619 | ||
620 | /*! | |
621 | * @function os_trace | |
622 | * | |
623 | * @abstract | |
624 | * Always inserts a trace message into a buffer pool for later decoding. | |
625 | * | |
626 | * @discussion | |
627 | * Trace message that will be recorded on a typical user install. These should | |
628 | * be limited to things which help diagnose a failure during postmortem | |
629 | * analysis. Trace buffers are generally smaller on a production system. | |
630 | * | |
631 | * @param format | |
632 | * A printf-style format string to generate a human-readable log message when | |
633 | * the trace line is decoded. Only scalar types are supported, attempts | |
634 | * to pass arbitrary strings will store a pointer that is unresolvable and | |
635 | * will generate an error during decode. | |
636 | * | |
637 | * os_trace("network event: %ld, last seen: %ld, avg: %g", event_id, last_seen, avg); | |
638 | */ | |
639 | #define os_trace(format, ...) __extension__({ \ | |
640 | _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \ | |
641 | __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \ | |
642 | OS_TRACE_CALL(format, _m, OS_TRACE_TYPE_RELEASE, ##__VA_ARGS__); \ | |
643 | }) | |
644 | ||
645 | ||
646 | #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_10_0) \ | |
647 | || (defined(__WATCH_OS_VERSION_MIN_REQUIRED) && __WATCH_OS_VERSION_MIN_REQUIRED >= __WATCHOS_3_0) \ | |
648 | || (defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED >= __TVOS_10_0) \ | |
649 | || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_12) | |
650 | ||
651 | /*! | |
652 | * @function os_trace_info | |
653 | * | |
654 | * @abstract | |
655 | * Optionally inserts a trace message containing additional information into a | |
656 | * buffer pool for later decoding. | |
657 | * | |
658 | * @discussion | |
659 | * Trace messages that will be captured when additional information is needed | |
660 | * and are not captured by default. They will only be captured if the | |
661 | * system/process/activity mode has been increased or if a Development tool has | |
662 | * been attached to the process. | |
663 | * | |
664 | * @param format | |
665 | * A printf-style format string that represents a human-readable message when | |
666 | * the trace line is decoded. Only scalar types are supported, attempts | |
667 | * to pass arbitrary strings will store a pointer that is unresolvable and | |
668 | * will generate an error during decode. | |
669 | * | |
670 | * os_trace_info("network interface status %ld", status); | |
671 | */ | |
672 | #define os_trace_info(format, ...) __extension__({ \ | |
673 | _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \ | |
674 | __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \ | |
675 | OS_TRACE_CALL(format, _m, OS_TRACE_TYPE_INFO, ##__VA_ARGS__); \ | |
676 | }) | |
677 | ||
678 | #endif | |
679 | ||
680 | /*! | |
681 | * @function os_trace_debug | |
682 | * | |
683 | * @abstract | |
684 | * Insert debug trace message into a buffer pool for later decoding. | |
685 | * | |
686 | * @discussion | |
687 | * Debug trace message to be recorded while debugger or other development tool is | |
688 | * attached to the originator. This is transported interprocess to help | |
689 | * diagnose the entire call chain including external helpers. | |
690 | * | |
691 | * @param format | |
692 | * A printf-style format string that represents a human-readable message when | |
693 | * the trace line is decoded. Only scalar types are supported, attempts | |
694 | * to pass arbitrary strings will store a pointer that is unresolvable and | |
695 | * will generate an error during decode. | |
696 | * | |
697 | * os_trace_debug("network interface status %ld", status); | |
698 | */ | |
699 | #define os_trace_debug(format, ...) __extension__({ \ | |
700 | _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \ | |
701 | __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \ | |
702 | OS_TRACE_CALL(format, _m, OS_TRACE_TYPE_DEBUG, ##__VA_ARGS__); \ | |
703 | }) | |
704 | ||
705 | /*! | |
706 | * @function os_trace_info_enabled | |
707 | * | |
708 | * @abstract | |
709 | * Avoid unnecessary work for a trace point by checking if additional information | |
710 | * is enabled. | |
711 | * | |
712 | * @discussion | |
713 | * Avoid unnecessary work for a trace point by checking if additional information | |
714 | * is enabled. Generally trace points should not involve expensive operations, but some | |
715 | * circumstances warrant it. Use this function to avoid doing the work unless | |
716 | * debug level trace messages are requested. | |
717 | * | |
718 | * if (os_trace_info_enabled()) { | |
719 | * os_trace_info("value = %d, average = %d", | |
720 | * [[dict objectForKey: @"myKey"] intValue], | |
721 | * (int) [self getAverage: dict]); | |
722 | * } | |
723 | * | |
724 | * @result | |
725 | * Returns true if development mode is enabled. | |
726 | */ | |
727 | __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0) | |
728 | OS_EXPORT OS_NOTHROW OS_WARN_RESULT | |
729 | bool | |
730 | os_trace_info_enabled(void); | |
731 | ||
732 | /*! | |
733 | * @function os_trace_debug_enabled | |
734 | * | |
735 | * @abstract | |
736 | * Avoid unnecessary work for a trace point by checking if debug level is enabled. | |
737 | * | |
738 | * @discussion | |
739 | * Avoid unnecessary work for a trace point by checking if debug level is enabled. | |
740 | * Generally trace points should not involve expensive operations, but some | |
741 | * circumstances warrant it. Use this function to avoid doing the work unless | |
742 | * debug level trace messages are requested. | |
743 | * | |
744 | * if (os_trace_debug_enabled()) { | |
745 | * os_trace_debug("value = %d, average = %d", | |
746 | * [[dict objectForKey: @"myKey"] intValue], | |
747 | * (int) [self getAverage: dict]); | |
748 | * } | |
749 | * | |
750 | * @result | |
751 | * Returns true if debug mode is enabled. | |
752 | */ | |
753 | __OSX_AVAILABLE(10.10) __IOS_AVAILABLE(8.0) __WATCHOS_AVAILABLE(1.0) __TVOS_AVAILABLE(9.0) | |
754 | OS_EXPORT OS_NOTHROW OS_WARN_RESULT | |
755 | bool | |
756 | os_trace_debug_enabled(void); | |
757 | ||
758 | /*! | |
759 | * @function os_trace_error | |
760 | * | |
761 | * @abstract | |
762 | * Trace the message as an error and force a collection of the trace buffer as a | |
763 | * failure may be imminent. | |
764 | * | |
765 | * @discussion | |
766 | * Trace the message as an error and force a collection of the trace buffer as a | |
767 | * failure may be imminent. | |
768 | * | |
769 | * @param format | |
770 | * A printf-style format string to generate a human-readable log message when | |
771 | * the trace line is decoded. Only scalar types are supported, attempts | |
772 | * to pass arbitrary strings will store a pointer that is unresolvable and | |
773 | * will generate an error during decode. | |
774 | * | |
775 | * os_trace_error("socket %d connection timeout %ld", fd, secs); | |
776 | */ | |
777 | #define os_trace_error(format, ...) __extension__({ \ | |
778 | _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \ | |
779 | __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \ | |
780 | OS_TRACE_CALL(format, _m, OS_TRACE_TYPE_ERROR, ##__VA_ARGS__); \ | |
781 | }) | |
782 | ||
783 | /*! | |
784 | * @function os_trace_fault | |
785 | * | |
786 | * @abstract | |
787 | * Trace the message as a fault which forces a collection of the trace buffer | |
788 | * and diagnostic of the activity. | |
789 | * | |
790 | * @discussion | |
791 | * Trace the message as a fault which forces a collection of the trace buffer | |
792 | * and diagnostic of the activity. | |
793 | * | |
794 | * @param format | |
795 | * A printf-style format string to generate a human-readable log message when | |
796 | * the trace line is decoded. Only scalar types are supported, attempts | |
797 | * to pass arbitrary strings will store a pointer that is unresolvable and | |
798 | * will generate an error during decode. | |
799 | * | |
800 | * os_trace_fault("failed to lookup uid %d - aborting", uid); | |
801 | */ | |
802 | #define os_trace_fault(format, ...) __extension__({ \ | |
803 | _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \ | |
804 | __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \ | |
805 | OS_TRACE_CALL(format, _m, OS_TRACE_TYPE_FAULT, ##__VA_ARGS__); \ | |
806 | }) | |
807 | ||
808 | #if __has_include(<xpc/xpc.h>) | |
809 | /*! | |
810 | * @function os_trace_with_payload | |
811 | * | |
812 | * @abstract | |
813 | * Add a trace entry containing the provided values and call the block if | |
814 | * appropriate. | |
815 | * | |
816 | * @discussion | |
817 | * Will insert a trace entry into a limited ring buffer for an activity or | |
818 | * process. Trace points are for recording interesting data that would improve | |
819 | * diagnosis of unexpected crashes, failures and hangs. The block will only be | |
820 | * called under the required conditions. | |
821 | * | |
822 | * @param trace_msg | |
823 | * A printf-style format string to generate a human-readable log message when | |
824 | * the trace line is decoded. Only scalar types are supported. Attempts | |
825 | * to pass arbitrary strings will store a pointer that is unresolvable and | |
826 | * will generate an error during decode. | |
827 | * | |
828 | * The final parameter must be a block of type os_trace_payload_t. | |
829 | * | |
830 | * os_trace_with_payload("network event %ld", event, ^(xpc_object_t xdict) { | |
831 | * | |
832 | * // validate the network interface and address where what was expected | |
833 | * xpc_dictionary_set_string(xdict, "network", ifp->ifa_name); | |
834 | * xpc_dictionary_set_string(xdict, "ip_address", _get_address(ifp)); | |
835 | * }); | |
836 | */ | |
837 | #define os_trace_with_payload(format, ...) __extension__({ \ | |
838 | _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \ | |
839 | __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \ | |
840 | OS_CONCAT(_os_trace_with_payload, OS_COUNT_ARGS(__VA_ARGS__))(format, _m, OS_TRACE_TYPE_RELEASE, ##__VA_ARGS__); \ | |
841 | }) | |
842 | ||
843 | #define os_trace_info_with_payload(format, ...) __extension__({ \ | |
844 | _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \ | |
845 | __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \ | |
846 | OS_CONCAT(_os_trace_with_payload, OS_COUNT_ARGS(__VA_ARGS__))(format, _m, OS_TRACE_TYPE_INFO, ##__VA_ARGS__); \ | |
847 | }) | |
848 | ||
849 | #define os_trace_debug_with_payload(format, ...) __extension__({ \ | |
850 | _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \ | |
851 | __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \ | |
852 | OS_CONCAT(_os_trace_with_payload, OS_COUNT_ARGS(__VA_ARGS__))(format, _m, OS_TRACE_TYPE_DEBUG, ##__VA_ARGS__); \ | |
853 | }) | |
854 | ||
855 | #define os_trace_error_with_payload(format, ...) __extension__({ \ | |
856 | _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \ | |
857 | __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \ | |
858 | OS_CONCAT(_os_trace_with_payload, OS_COUNT_ARGS(__VA_ARGS__))(format, _m, OS_TRACE_TYPE_ERROR, ##__VA_ARGS__); \ | |
859 | }) | |
860 | ||
861 | #define os_trace_fault_with_payload(format, ...) __extension__({ \ | |
862 | _Static_assert(__builtin_constant_p(format), "format must be a constant string"); \ | |
863 | __attribute__((section("__TEXT,__os_trace"))) static const char _m[] = format; \ | |
864 | OS_CONCAT(_os_trace_with_payload, OS_COUNT_ARGS(__VA_ARGS__))(format, _m, OS_TRACE_TYPE_FAULT, ##__VA_ARGS__); \ | |
865 | }) | |
866 | ||
867 | #endif // __has_include(<xpc/xpc.h>) | |
868 | ||
869 | // TODO: change this once we have compiler support | |
870 | __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0) | |
871 | OS_EXPORT OS_NOTHROW | |
872 | size_t | |
873 | _os_trace_encode(uint8_t *buf, size_t buf_size, const char *format, ...); | |
874 | ||
875 | __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0) | |
876 | OS_EXPORT OS_NOTHROW | |
877 | void | |
878 | _os_trace_internal(void *dso, uint8_t type, const char *format, const uint8_t *buf, size_t buf_size, os_trace_payload_t payload); | |
879 | ||
880 | /*! | |
881 | * @function _os_trace_with_buffer | |
882 | * | |
883 | * @abstract | |
884 | * Internal function to support pre-encoded buffer. | |
885 | */ | |
886 | __OSX_AVAILABLE(10.10) __IOS_AVAILABLE(8.0) __WATCHOS_AVAILABLE(1.0) __TVOS_AVAILABLE(9.0) | |
887 | OS_EXPORT OS_NOTHROW | |
888 | void | |
889 | _os_trace_with_buffer(void *dso, const char *message, uint8_t type, const void *buffer, size_t buffer_size, os_trace_payload_t payload); | |
890 | ||
891 | __END_DECLS | |
892 | ||
893 | #endif // __OS_TRACE_H__ |