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