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