1 /*
2 * Copyright (c) 2015-2022 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_log_h
25 #define __os_log_h
26
27 #include <os/object.h>
28 #include <stdint.h>
29 #include <stdbool.h>
30
31 #ifndef __has_attribute
32 #define __has_attribute(x) 0
33 #endif
34
35 #ifndef __has_builtin
36 #define __has_builtin(x) 0
37 #endif
38
39 #if __has_attribute(not_tail_called)
40 #define OS_LOG_NOTAILCALL __attribute__((not_tail_called))
41 #define OS_LOG_NOTAILCALL_MARKER
42 #else
43 #define OS_LOG_NOTAILCALL
44 #define OS_LOG_NOTAILCALL_MARKER __asm__("")
45 #endif
46
47 __BEGIN_DECLS
48
49 extern void *__dso_handle;
50
51 #ifdef XNU_KERNEL_PRIVATE
52 extern bool startup_serial_logging_active;
53 extern uint64_t startup_serial_num_procs;
54 #endif /* XNU_KERNEL_PRIVATE */
55
56 #ifdef KERNEL
57 #define OS_LOG_BUFFER_MAX_SIZE 256
58 #else
59 #define OS_LOG_BUFFER_MAX_SIZE 1024
60 #endif
61
62 // The OS_LOG_BUFFER_MAX_SIZE limit includes the metadata that
63 // must be included in the os_log firehose buffer
64 #define OS_LOG_DATA_MAX_SIZE (OS_LOG_BUFFER_MAX_SIZE - 16)
65
66 OS_ALWAYS_INLINE static inline void
67 _os_log_verify_format_str(__unused const char *msg, ...) __osloglike(1, 2);
68 OS_ALWAYS_INLINE static inline void
_os_log_verify_format_str(__unused const char * msg,...)69 _os_log_verify_format_str(__unused const char *msg, ...) /* placeholder */
70 {
71 }
72
73 #if OS_OBJECT_USE_OBJC
74 OS_OBJECT_DECL(os_log);
75 #else
76 typedef struct os_log_s *os_log_t;
77 #endif /* OS_OBJECT_USE_OBJC */
78
79 /*!
80 * @const OS_LOG_DISABLED
81 *
82 * @discussion
83 * Use this to disable a specific log message.
84 */
85 #define OS_LOG_DISABLED NULL
86
87 /*!
88 * @const OS_LOG_DEFAULT
89 *
90 * @discussion
91 * Use this to log a message in accordance with current system settings.
92 */
93 #define OS_LOG_DEFAULT OS_OBJECT_GLOBAL_OBJECT(os_log_t, _os_log_default)
94 __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0)
95 OS_EXPORT
96 struct os_log_s _os_log_default;
97
98 /*!
99 * @enum os_log_type_t
100 *
101 * @discussion
102 * Supported log message types.
103 *
104 * @constant OS_LOG_TYPE_DEFAULT
105 * Equivalent type for "os_log()" messages, i.e., default messages that are always
106 * captured to memory or disk.
107 *
108 * @constant OS_LOG_TYPE_INFO
109 * Equivalent type for "os_log_info()" messages, i.e., Additional informational messages.
110 *
111 * @constant OS_LOG_TYPE_DEBUG
112 * Equivalent type for "os_log_debug()" messages, i.e., Debug messages.
113 *
114 * @constant OS_LOG_TYPE_ERROR
115 * Equivalent type for "os_log_error()" messages, i.e., local process error messages.
116 *
117 * @constant OS_LOG_TYPE_FAULT
118 * Equivalent type for "os_log_fault()" messages, i.e., a system error that involves
119 * potentially more than one process, usually used by daemons and services.
120 */
121 OS_ENUM(os_log_type, uint8_t,
122 OS_LOG_TYPE_DEFAULT = 0x00,
123 OS_LOG_TYPE_INFO = 0x01,
124 OS_LOG_TYPE_DEBUG = 0x02,
125 OS_LOG_TYPE_ERROR = 0x10,
126 OS_LOG_TYPE_FAULT = 0x11);
127
128 /*!
129 * @function os_log_create
130 *
131 * @abstract
132 * Creates a log object to be used with other log related functions.
133 *
134 * @discussion
135 * Creates a log object to be used with other log related functions. The
136 * log object serves two purposes: (1) tag related messages by subsystem
137 * and category name for easy filtering, and (2) control logging system
138 * behavior for messages.
139 *
140 * A log object may customize logging system behavior for its messages by
141 * adding a configuration file in /Library/LogPreferences. Most options
142 * accept 3 values: "Default", "Yes" or "No" as strings, where "Default"
143 * signifies follow system behavior for the level of messages.
144 *
145 * For log:
146 *
147 * os_log_create("com.company.mysubsystem", "connections");
148 *
149 * System-provided preferences are located in /System/Library/LogPreferences/<subsystem>.plist
150 *
151 * <dict>
152 *
153 * <!-- Default options applied to message types in each category, which can be overriden. -->
154 * <key>DEFAULT-OPTIONS</key>
155 * <dict>
156 * <key>Enabled</key> <!-- Enabled state follows system defaults -->
157 * <string>Default</string>
158 * <key>Persist</key> <!-- Do not persist to disk, use memory-only buffer if enabled -->
159 * <string>No</string>
160 * <key>TTL</key> <!-- Follow system default behavior if persistence is enabled -->
161 * <string>Default</string> <!-- Can specify in days with "d" or hours "h" (e.g., "4h" = 4 hours) -->
162 * </dict>
163 *
164 * <!-- category named “connections” -->
165 * <key>connections</key>
166 * <dict>
167 *
168 * <!-- Options that control "os_log()" behavior. The "Enabled" option is ignored. -->
169 * <key>Default</key>
170 * <dict>
171 * <key>Persist</key> <!-- Always persist to disk -->
172 * <string>Yes</string>
173 * <key>TTL</key> <!-- Store default messages for maximum 4 days -->
174 * <integer>4d</integer>
175 * </dict>
176 *
177 * <!-- Subdictionary of options that control "os_log_info()" behavior -->
178 * <key>Info</key>
179 * <dict>
180 * <key>Persist</key> <!-- If enabled persist to disk -->
181 * <string>Yes</string>
182 * <key>TTL</key> <!-- Store Info messages for 2 days -->
183 * <string>2d</string>
184 * </dict>
185 *
186 * <!-- Subdictionary of options that control "os_log_debug()" behavior -->
187 * <key>Debug</key>
188 * <dict>
189 * <key>Enabled</key> <!-- Not enabled, must be enabled specifically -->
190 * <string>No</string>
191 * </dict>
192 * </dict>
193 * </dict>
194 *
195 * All other preferences and system-overrides are stored in /Library/LogPreferences/.
196 *
197 * @param subsystem
198 * The identifier of the given subsystem should be in reverse DNS form
199 * (i.e., com.company.mysubsystem). This string must be a constant string,
200 * not dynamically generated.
201 *
202 * @param category
203 * The category within the given subsystem that specifies the settings for
204 * the log object. This string must be a constant string, not dynamically
205 * generated.
206 *
207 * @result
208 * Returns an os_log_t value to be passed to other os_log API calls. This
209 * should be called once at log initialization and rely on system to detect
210 * changes to settings. This object should be released when no longer used
211 * via os_release or -[release] method.
212 *
213 * A value will always be returned to allow for dynamic enablement.
214 */
215 __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0)
216 OS_EXPORT OS_NOTHROW OS_WARN_RESULT OS_OBJECT_RETURNS_RETAINED
217 os_log_t
218 os_log_create(const char *subsystem, const char *category);
219
220 /*!
221 * @function os_log_info_enabled
222 *
223 * @abstract
224 * Returns if additional information log messages are enabled for a particular
225 * log object.
226 *
227 * @discussion
228 * Returns if additional information log messages are enabled for a particular
229 * log object.
230 *
231 * @param log
232 * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
233 *
234 * @result
235 * Returns ‘true’ if additional information log messages are enabled.
236 */
237 __WATCHOS_AVAILABLE(3.0) __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0)
238 OS_EXPORT OS_NOTHROW OS_WARN_RESULT
239 bool
240 os_log_info_enabled(os_log_t log);
241
242 /*!
243 * @function os_log_debug_enabled
244 *
245 * @abstract
246 * Returns if debug log messages are enabled for a particular log object.
247 *
248 * @discussion
249 * Returns if debug log messages are enabled for a particular log object.
250 *
251 * @param log
252 * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
253 *
254 * @result
255 * Returns ‘true’ if debug log messages are enabled.
256 */
257 __WATCHOS_AVAILABLE(3.0) __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0)
258 OS_EXPORT OS_NOTHROW OS_WARN_RESULT
259 bool
260 os_log_debug_enabled(os_log_t log);
261
262 /*!
263 * @function os_log
264 *
265 * @abstract
266 * Insert a log message into the Unified Logging and Tracing system.
267 *
268 * @discussion
269 * Insert a log message into the Unified Logging and Tracing system in
270 * accordance with the preferences specified by the provided log object.
271 * These messages cannot be disabled and therefore always captured either
272 * to memory or disk.
273 *
274 * When an os_activity_id_t is present, the log message will also be scoped by
275 * that identifier. Activities provide granular filtering of log messages
276 * across threads and processes.
277 *
278 * There is a physical cap of 256 bytes per entry for dynamic content,
279 * i.e., %s and %@, that can be written to the persistence store. As such,
280 * all content exceeding the limit will be truncated before written to disk.
281 * Live streams will continue to show the full content.
282 *
283 * @param log
284 * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
285 *
286 * @param format
287 * A format string to generate a human-readable log message when the log
288 * line is decoded. This string must be a constant string, not dynamically
289 * generated. Supports all standard printf types and %@ (objects).
290 */
291 #define os_log(log, format, ...) __extension__({ \
292 _Static_assert(__builtin_constant_p(format), "format string must be constant"); \
293 __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format; \
294 _os_log_verify_format_str(format, ##__VA_ARGS__); \
295 _os_log_internal(&__dso_handle, log, OS_LOG_TYPE_DEFAULT, _os_log_fmt, ##__VA_ARGS__); \
296 __asm__(""); /* avoid tailcall */ \
297 })
298
299 /*!
300 * @function os_log_info
301 *
302 * @abstract
303 * Insert a development log message into the Unified Logging and Tracing system.
304 *
305 * @discussion
306 * Insert a log message into the Unified Logging and Tracing system in
307 * accordance with the preferences specified by the provided log object.
308 *
309 * When an os_activity_id_t is present, the log message will also be scoped by
310 * that identifier. Activities provide granular filtering of log messages
311 * across threads and processes.
312 *
313 * There is a physical cap of 256 bytes per entry for dynamic content,
314 * i.e., %s and %@, that can be written to the persistence store. As such,
315 * all content exceeding the limit will be truncated before written to disk.
316 * Live streams will continue to show the full content.
317 *
318 * @param log
319 * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
320 *
321 * @param format
322 * A format string to generate a human-readable log message when the log
323 * line is decoded. This string must be a constant string, not dynamically
324 * generated. Supports all standard printf types and %@ (objects).
325 */
326 #define os_log_info(log, format, ...) __extension__({ \
327 _Static_assert(__builtin_constant_p(format), "format string must be constant"); \
328 __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format; \
329 _os_log_verify_format_str(format, ##__VA_ARGS__); \
330 _os_log_internal(&__dso_handle, log, OS_LOG_TYPE_INFO, _os_log_fmt, ##__VA_ARGS__); \
331 __asm__(""); /* avoid tailcall */ \
332 })
333
334 /*!
335 * @function os_log_debug
336 *
337 * @abstract
338 * Insert a debug log message into the Unified Logging and Tracing system.
339 *
340 * @discussion
341 * Insert a debug log message into the Unified Logging and Tracing system in
342 * accordance with the preferences specified by the provided log object.
343 *
344 * When an os_activity_id_t is present, the log message will also be scoped by
345 * that identifier. Activities provide granular filtering of log messages
346 * across threads and processes.
347 *
348 * There is a physical cap of 256 bytes per entry for dynamic content,
349 * i.e., %s and %@, that can be written to the persistence store. As such,
350 * all content exceeding the limit will be truncated before written to disk.
351 * Live streams will continue to show the full content.
352 *
353 * @param log
354 * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
355 *
356 * @param format
357 * A format string to generate a human-readable log message when the log
358 * line is decoded. This string must be a constant string, not dynamically
359 * generated. Supports all standard printf types and %@ (objects).
360 */
361 #define os_log_debug(log, format, ...) __extension__({ \
362 _Static_assert(__builtin_constant_p(format), "format string must be constant"); \
363 __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format; \
364 _os_log_verify_format_str(format, ##__VA_ARGS__); \
365 _os_log_internal(&__dso_handle, log, OS_LOG_TYPE_DEBUG, _os_log_fmt, ##__VA_ARGS__); \
366 __asm__(""); /* avoid tailcall */ \
367 })
368
369 /*!
370 * @function os_log_error
371 *
372 * @abstract
373 * Insert an error log message into the Unified Logging and Tracing system.
374 *
375 * @discussion
376 * Insert an error log message into the Unified Logging and Tracing system.
377 *
378 * When an os_activity_id_t is present, the log message will also be scoped by
379 * that identifier. Activities provide granular filtering of log messages
380 * across threads and processes.
381 *
382 * There is a physical cap of 256 bytes per entry for dynamic content,
383 * i.e., %s and %@, that can be written to the persistence store. As such,
384 * all content exceeding the limit will be truncated before written to disk.
385 * Live streams will continue to show the full content.
386 *
387 * @param log
388 * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
389 *
390 * @param format
391 * A format string to generate a human-readable log message when the log
392 * line is decoded. This string must be a constant string, not dynamically
393 * generated. Supports all standard printf types and %@ (objects).
394 */
395 #define os_log_error(log, format, ...) __extension__({ \
396 _Static_assert(__builtin_constant_p(format), "format string must be constant"); \
397 __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format; \
398 _os_log_verify_format_str(format, ##__VA_ARGS__); \
399 _os_log_internal(&__dso_handle, log, OS_LOG_TYPE_ERROR, _os_log_fmt, ##__VA_ARGS__); \
400 __asm__(""); /* avoid tailcall */ \
401 })
402
403 /*!
404 * @function os_log_fault
405 *
406 * @abstract
407 * Insert a fault log message into the Unified Logging and Tracing system.
408 *
409 * @discussion
410 * Log a fault message issue into the Unified Logging and Tracing system
411 * signifying a multi-process (i.e., system error) related issue, either
412 * due to interaction via IPC or some other. Faults will gather information
413 * from the entire process chain and record it for later inspection.
414 *
415 * When an os_activity_id_t is present, the log message will also be scoped by
416 * that identifier. Activities provide granular filtering of log messages
417 * across threads and processes.
418 *
419 * There is a physical cap of 256 bytes per entry for dynamic content,
420 * i.e., %s and %@, that can be written to the persistence store. As such,
421 * all content exceeding the limit will be truncated before written to disk.
422 * Live streams will continue to show the full content.
423 *
424 * @param log
425 * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
426 *
427 * @param format
428 * A format string to generate a human-readable log message when the log
429 * line is decoded. This string must be a constant string, not dynamically
430 * generated. Supports all standard printf types and %@ (objects).
431 */
432 #define os_log_fault(log, format, ...) __extension__({ \
433 _Static_assert(__builtin_constant_p(format), "format string must be constant"); \
434 __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format; \
435 _os_log_verify_format_str(format, ##__VA_ARGS__); \
436 _os_log_internal(&__dso_handle, log, OS_LOG_TYPE_FAULT, _os_log_fmt, ##__VA_ARGS__); \
437 __asm__(""); /* avoid tailcall */ \
438 })
439
440 /*!
441 * @function os_log_with_type
442 *
443 * @abstract
444 * Log a message using a specific type.
445 *
446 * @discussion
447 * Will log a message with the provided os_log_type_t.
448 *
449 * @param log
450 * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
451 *
452 * @param type
453 * Pass a valid type from os_log_type_t.
454 *
455 * @param format
456 * A format string to generate a human-readable log message when the log
457 * line is decoded. This string must be a constant string, not dynamically
458 * generated. Supports all standard printf types and %@ (objects).
459 */
460 #define os_log_with_type(log, type, format, ...) __extension__({ \
461 _Static_assert(__builtin_constant_p(format), "format string must be constant"); \
462 __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format; \
463 _os_log_verify_format_str(format, ##__VA_ARGS__); \
464 _os_log_internal(&__dso_handle, log, type, _os_log_fmt, ##__VA_ARGS__); \
465 __asm__(""); /* avoid tailcall */ \
466 })
467
468 /*!
469 * @function os_log_at_time
470 *
471 * @abstract
472 * Log a message using a specific type and a timestamp.
473 *
474 * @discussion
475 * Will log a message with the provided os_log_type_t and a timestamp
476 * signifying a moment of a log message creation.
477 *
478 * @param log
479 * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
480 *
481 * @param type
482 * Pass a valid type from os_log_type_t.
483 *
484 * @param ts
485 * Pass a uint64_t value (timestamp) of mach continuous time clock.
486 *
487 * @param format
488 * A format string to generate a human-readable log message when the log
489 * line is decoded. This string must be a constant string, not dynamically
490 * generated. Supports all standard printf types.
491 */
492 #define os_log_at_time(log, type, ts, format, ...) __extension__({ \
493 _Static_assert(__builtin_constant_p(format), "format string must be constant"); \
494 __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format; \
495 _os_log_verify_format_str(format, ##__VA_ARGS__); \
496 _os_log_at_time(&__dso_handle, log, type, ts, _os_log_fmt, ##__VA_ARGS__); \
497 __asm__(""); /* avoid tailcall */ \
498 })
499
500 /*!
501 * @function os_log_driverKit
502 *
503 * @abstract
504 * Log a message using a specific type. This variant should be called only from dexts.
505 *
506 * @discussion
507 * Will log a message with the provided os_log_type_t.
508 *
509 * @param log
510 * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
511 *
512 * @param type
513 * Pass a valid type from os_log_type_t.
514 *
515 * @param format
516 * A format string to generate a human-readable log message when the log
517 * line is decoded. This string must be a constant string, not dynamically
518 * generated. Supports all standard printf types and %@ (objects).
519 *
520 * @result
521 * Returns EPERM if the caller is not a driverKit process, 0 in case of success.
522 */
523 #define os_log_driverKit(out, log, type, format, ...) __extension__({ \
524 _Static_assert(__builtin_constant_p(format), "format string must be constant"); \
525 __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format; \
526 _os_log_verify_format_str(format, ##__VA_ARGS__); \
527 (*(out)) = _os_log_internal_driverKit(&__dso_handle, log, type, _os_log_fmt, ##__VA_ARGS__); \
528 __asm__(""); /* avoid tailcall */ \
529 })
530
531 /*!
532 * @function os_log_coprocessor
533 *
534 * @abstract
535 * IOP logging function, intended for use by RTBuddy for
536 * coprocessor os log functionality only.
537 */
538 bool
539 os_log_coprocessor(void *buff, uint64_t buff_len, os_log_type_t type,
540 const char *uuid, uint64_t timestamp, uint32_t offset, bool stream_log);
541
542 /*!
543 * @function os_log_coprocessor_register
544 *
545 * @abstract
546 * IOP metadata registration, intended for use by RTBuddy for
547 * coprocessor os log functionality only.
548 * Will be removed after all user code will be updated to use os_log_coprocessor_register_with_type
549 */
550 void
551 os_log_coprocessor_register(const char *uuid, const char *file_path, bool copy);
552
553 typedef enum {
554 os_log_coproc_register_memory,
555 os_log_coproc_register_harvest_fs_ftab,
556 } os_log_coproc_reg_t;
557
558 /*!
559 * @function os_log_coprocessor_register_with_type
560 *
561 * @abstract
562 * IOP metadata registration, intended for use by RTBuddy for
563 * coprocessor os log functionality only.
564 */
565 void
566 os_log_coprocessor_register_with_type(const char *uuid, const char *file_path, os_log_coproc_reg_t register_type);
567
568 #ifdef XNU_KERNEL_PRIVATE
569 #define os_log_with_startup_serial_and_type(log, type, format, ...) __extension__({ \
570 if (startup_serial_logging_active) { printf(format, ##__VA_ARGS__); } \
571 else { os_log_with_type(log, type, format, ##__VA_ARGS__); } \
572 })
573 #define os_log_with_startup_serial(log, format, ...) \
574 os_log_with_startup_serial_and_type(log, OS_LOG_TYPE_DEFAULT, format, ##__VA_ARGS__)
575 #define os_log_info_with_startup_serial(log, format, ...) \
576 os_log_with_startup_serial_and_type(log, OS_LOG_TYPE_INFO, format, ##__VA_ARGS__)
577 #define os_log_debug_with_startup_serial(log, format, ...) \
578 os_log_with_startup_serial_and_type(log, OS_LOG_TYPE_DEBUG, format, ##__VA_ARGS__)
579 #define os_log_error_with_startup_serial(log, format, ...) \
580 os_log_with_startup_serial_and_type(log, OS_LOG_TYPE_ERROR, format, ##__VA_ARGS__)
581 #define os_log_fault_with_startup_serial(log, format, ...) \
582 os_log_with_startup_serial_and_type(log, OS_LOG_TYPE_FAULT, format, ##__VA_ARGS__)
583 #endif /* XNU_KERNEL_PRIVATE */
584
585 /*!
586 * @function _os_log_internal
587 *
588 * @abstract
589 * Internal function used by macros.
590 */
591 __WATCHOS_AVAILABLE(3.0) __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0)
592 OS_EXPORT OS_NOTHROW
593 void
594 _os_log_internal(void *dso, os_log_t log, os_log_type_t type, const char *message, ...) __osloglike(4, 5);
595
596 /*!
597 * @function _os_log_internal_driverKit
598 *
599 * @abstract
600 * Internal function used by macros.
601 */
602 __WATCHOS_AVAILABLE(6.0) __OSX_AVAILABLE(10.15) __IOS_AVAILABLE(13.0) __TVOS_AVAILABLE(13.0)
603 OS_EXPORT OS_NOTHROW
604 int
605 _os_log_internal_driverKit(void *dso, os_log_t log, os_log_type_t type, const char *message, ...) __osloglike(4, 5);
606
607 /*!
608 * @function _os_log_internal_props
609 *
610 * @abstract
611 * Internal function used by macros.
612 */
613 __WATCHOS_AVAILABLE(9.0) __OSX_AVAILABLE(13) __IOS_AVAILABLE(16.0) __TVOS_AVAILABLE(16.0)
614 OS_EXPORT OS_NOTHROW
615 void
616 _os_log_at_time(void *dso, os_log_t log, os_log_type_t type, uint64_t ts, const char *message, ...) __osloglike(5, 6);
617
618 __END_DECLS
619
620 #endif /* __os_log_h */
621