xref: /xnu-12377.41.6/libkern/os/log.h (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
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, ...) \
233     os_log_with_type(log, OS_LOG_TYPE_DEFAULT, format, ##__VA_ARGS__)
234 
235 /*!
236  * @function os_log_info
237  *
238  * @abstract
239  * Insert a development log message into the Unified Logging and Tracing system.
240  *
241  * @discussion
242  * Insert a log message into the Unified Logging and Tracing system in
243  * accordance with the preferences specified by the provided log object.
244  *
245  * When an os_activity_id_t is present, the log message will also be scoped by
246  * that identifier.  Activities provide granular filtering of log messages
247  * across threads and processes.
248  *
249  * There is a physical cap of 256 bytes per entry for dynamic content,
250  * i.e., %s and %@, that can be written to the persistence store.  As such,
251  * all content exceeding the limit will be truncated before written to disk.
252  * Live streams will continue to show the full content.
253  *
254  * @param log
255  * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
256  *
257  * @param format
258  * A format string to generate a human-readable log message when the log
259  * line is decoded.  This string must be a constant string, not dynamically
260  * generated.  Supports all standard printf types and %@ (objects).
261  */
262 #define os_log_info(log, format, ...) \
263     os_log_with_type(log, OS_LOG_TYPE_INFO, format, ##__VA_ARGS__)
264 
265 /*!
266  * @function os_log_debug
267  *
268  * @abstract
269  * Insert a debug log message into the Unified Logging and Tracing system.
270  *
271  * @discussion
272  * Insert a debug log message into the Unified Logging and Tracing system in
273  * accordance with the preferences specified by the provided log object.
274  *
275  * When an os_activity_id_t is present, the log message will also be scoped by
276  * that identifier.  Activities provide granular filtering of log messages
277  * across threads and processes.
278  *
279  * There is a physical cap of 256 bytes per entry for dynamic content,
280  * i.e., %s and %@, that can be written to the persistence store.  As such,
281  * all content exceeding the limit will be truncated before written to disk.
282  * Live streams will continue to show the full content.
283  *
284  * @param log
285  * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
286  *
287  * @param format
288  * A format string to generate a human-readable log message when the log
289  * line is decoded.  This string must be a constant string, not dynamically
290  * generated.  Supports all standard printf types and %@ (objects).
291  */
292 #define os_log_debug(log, format, ...) \
293     os_log_with_type(log, OS_LOG_TYPE_DEBUG, format, ##__VA_ARGS__)
294 
295 /*!
296  * @function os_log_error
297  *
298  * @abstract
299  * Insert an error log message into the Unified Logging and Tracing system.
300  *
301  * @discussion
302  * Insert an error log message into the Unified Logging and Tracing system.
303  *
304  * When an os_activity_id_t is present, the log message will also be scoped by
305  * that identifier.  Activities provide granular filtering of log messages
306  * across threads and processes.
307  *
308  * There is a physical cap of 256 bytes per entry for dynamic content,
309  * i.e., %s and %@, that can be written to the persistence store.  As such,
310  * all content exceeding the limit will be truncated before written to disk.
311  * Live streams will continue to show the full content.
312  *
313  * @param log
314  * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
315  *
316  * @param format
317  * A format string to generate a human-readable log message when the log
318  * line is decoded.  This string must be a constant string, not dynamically
319  * generated.  Supports all standard printf types and %@ (objects).
320  */
321 #define os_log_error(log, format, ...) \
322     os_log_with_type(log, OS_LOG_TYPE_ERROR, format, ##__VA_ARGS__)
323 
324 /*!
325  * @function os_log_fault
326  *
327  * @abstract
328  * Insert a fault log message into the Unified Logging and Tracing system.
329  *
330  * @discussion
331  * Log a fault message issue into the Unified Logging and Tracing system
332  * signifying a multi-process (i.e., system error) related issue, either
333  * due to interaction via IPC or some other.  Faults will gather information
334  * from the entire process chain and record it for later inspection.
335  *
336  * When an os_activity_id_t is present, the log message will also be scoped by
337  * that identifier.  Activities provide granular filtering of log messages
338  * across threads and processes.
339  *
340  * There is a physical cap of 256 bytes per entry for dynamic content,
341  * i.e., %s and %@, that can be written to the persistence store.  As such,
342  * all content exceeding the limit will be truncated before written to disk.
343  * Live streams will continue to show the full content.
344  *
345  * @param log
346  * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
347  *
348  * @param format
349  * A format string to generate a human-readable log message when the log
350  * line is decoded.  This string must be a constant string, not dynamically
351  * generated.  Supports all standard printf types and %@ (objects).
352  */
353 #define os_log_fault(log, format, ...) \
354     os_log_with_type(log, OS_LOG_TYPE_FAULT, format, ##__VA_ARGS__)
355 
356 /*!
357  * @function os_log_with_type
358  *
359  * @abstract
360  * Log a message using a specific type.
361  *
362  * @discussion
363  * Will log a message with the provided os_log_type_t.
364  *
365  * @param log
366  * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
367  *
368  * @param type
369  * Pass a valid type from os_log_type_t.
370  *
371  * @param format
372  * A format string to generate a human-readable log message when the log
373  * line is decoded.  This string must be a constant string, not dynamically
374  * generated.  Supports all standard printf types and %@ (objects).
375  */
376 #define os_log_with_type(log, type, format, ...) __extension__({                            \
377     _Static_assert(__builtin_constant_p(format), "format string must be constant");         \
378     __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format;   \
379     if (0) {                                                                                \
380 	_os_log_verify_format_str(format, ##__VA_ARGS__);                                   \
381     } else {                                                                                  \
382 	_os_log_internal(&__dso_handle, log, type, _os_log_fmt, ##__VA_ARGS__);             \
383     }                                                                                       \
384     __asm__(""); /* avoid tailcall */                                                       \
385 })
386 
387 /*!
388  * @function os_log_at_time
389  *
390  * @abstract
391  * Log a message using a specific type and a timestamp.
392  *
393  * @discussion
394  * Will log a message with the provided os_log_type_t and a timestamp
395  * signifying a moment of a log message creation.
396  *
397  * @param log
398  * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
399  *
400  * @param type
401  * Pass a valid type from os_log_type_t.
402  *
403  * @param ts
404  * Pass a uint64_t value (timestamp) of mach continuous time clock.
405  *
406  * @param format
407  * A format string to generate a human-readable log message when the log
408  * line is decoded. This string must be a constant string, not dynamically
409  * generated. Supports all standard printf types.
410  */
411 #define os_log_at_time(log, type, ts, format, ...) __extension__({                          \
412     _Static_assert(__builtin_constant_p(format), "format string must be constant");         \
413     __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format;   \
414     if (0) {                                                                                \
415 	_os_log_verify_format_str(format, ##__VA_ARGS__);                                   \
416     } else {                                                                                  \
417 	_os_log_at_time(&__dso_handle, log, type, ts, _os_log_fmt, ##__VA_ARGS__);          \
418     }                                                                                       \
419     __asm__(""); /* avoid tailcall */                                                       \
420 })
421 
422 /*!
423  * @function os_log_driverKit
424  *
425  * @abstract
426  * Log a message using a specific type. This variant should be called only from dexts.
427  *
428  * @discussion
429  * Will log a message with the provided os_log_type_t.
430  *
431  * @param log
432  * Pass OS_LOG_DEFAULT or a log object previously created with os_log_create.
433  *
434  * @param type
435  * Pass a valid type from os_log_type_t.
436  *
437  * @param format
438  * A format string to generate a human-readable log message when the log
439  * line is decoded.  This string must be a constant string, not dynamically
440  * generated.  Supports all standard printf types and %@ (objects).
441  *
442  * @result
443  * Returns EPERM if the caller is not a driverKit process, 0 in case of success.
444  */
445 #define os_log_driverKit(out, log, type, format, ...) __extension__({                            \
446     _Static_assert(__builtin_constant_p(format), "format string must be constant");         \
447     __attribute__((section("__TEXT,__os_log"))) static const char _os_log_fmt[] = format;   \
448     if (0) {                                                                                \
449 	_os_log_verify_format_str(format, ##__VA_ARGS__);                                   \
450     } else {                                                                                  \
451 	(*(out)) = _os_log_internal_driverKit(&__dso_handle, log, type, _os_log_fmt, ##__VA_ARGS__);                 \
452     }                                                                                       \
453     __asm__(""); /* avoid tailcall */                                                       \
454 })
455 
456 /*!
457  * @function os_log_coprocessor
458  *
459  * @abstract
460  * IOP logging function, intended for use by RTBuddy for coprocessor os log
461  * functionality only.
462  */
463 bool
464 os_log_coprocessor(void *buff, uint64_t buff_len, os_log_type_t type,
465     const char *uuid, uint64_t timestamp, uint32_t offset, bool stream_log);
466 
467 /*!
468  * @function os_log_coprocessor_register
469  *
470  * @abstract
471  * IOP metadata registration, intended for use by RTBuddy for coprocessor os log
472  * functionality only. Will be removed after all user code will be updated to
473  * use os_log_coprocessor_register_with_type.
474  */
475 void
476 os_log_coprocessor_register(const char *uuid, const char *file_path, bool copy);
477 
478 typedef enum {
479 	os_log_coproc_register_memory,
480 	os_log_coproc_register_harvest_fs_ftab,
481 } os_log_coproc_reg_t;
482 
483 /*!
484  * @function os_log_coprocessor_register_with_type
485  *
486  * @abstract
487  * IOP metadata registration, intended for use by RTBuddy for coprocessor os log
488  * functionality only.
489  */
490 void
491 os_log_coprocessor_register_with_type(const char *uuid, const char *file_path, os_log_coproc_reg_t register_type);
492 
493 #ifdef XNU_KERNEL_PRIVATE
494 #define os_log_with_startup_serial_and_type(log, type, format, ...) __extension__({ \
495     if (startup_serial_logging_active) { printf(format, ##__VA_ARGS__); }           \
496     else { os_log_with_type(log, type, format, ##__VA_ARGS__); }                    \
497 })
498 #define os_log_with_startup_serial(log, format, ...) \
499     os_log_with_startup_serial_and_type(log, OS_LOG_TYPE_DEFAULT, format, ##__VA_ARGS__)
500 #define os_log_info_with_startup_serial(log, format, ...) \
501     os_log_with_startup_serial_and_type(log, OS_LOG_TYPE_INFO, format, ##__VA_ARGS__)
502 #define os_log_debug_with_startup_serial(log, format, ...) \
503     os_log_with_startup_serial_and_type(log, OS_LOG_TYPE_DEBUG, format, ##__VA_ARGS__)
504 #define os_log_error_with_startup_serial(log, format, ...) \
505     os_log_with_startup_serial_and_type(log, OS_LOG_TYPE_ERROR, format, ##__VA_ARGS__)
506 #define os_log_fault_with_startup_serial(log, format, ...) \
507     os_log_with_startup_serial_and_type(log, OS_LOG_TYPE_FAULT, format, ##__VA_ARGS__)
508 #endif /* XNU_KERNEL_PRIVATE */
509 
510 /*!
511  * @function _os_log_internal
512  *
513  * @abstract
514  * Internal function used by macros.
515  */
516 OS_EXPORT OS_NOTHROW
517 void
518 _os_log_internal(void *dso, os_log_t log, os_log_type_t type, const char *message, ...)
519 __osloglike(4, 5);
520 
521 /*!
522  * @function _os_log_internal_driverKit
523  *
524  * @abstract
525  * Internal function used by macros.
526  */
527 OS_EXPORT OS_NOTHROW
528 int
529 _os_log_internal_driverKit(void *dso, os_log_t log, os_log_type_t type, const char *message, ...)
530 __osloglike(4, 5);
531 
532 /*!
533  * @function _os_log_internal_props
534  *
535  * @abstract
536  * Internal function used by macros.
537  */
538 OS_EXPORT OS_NOTHROW
539 void
540 _os_log_at_time(void *dso, os_log_t log, os_log_type_t type, uint64_t ts, const char *message, ...)
541 __osloglike(5, 6);
542 
543 __END_DECLS
544 
545 #endif /* __os_log_h */
546