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