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