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
49extern void *__dso_handle;
50
51#ifdef XNU_KERNEL_PRIVATE
52extern bool startup_serial_logging_active;
53extern 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
66OS_ALWAYS_INLINE
67static inline void
68 _os_log_verify_format_str(__unused const char *msg, ...)
69__osloglike(1, 2);
70
71OS_ALWAYS_INLINE
72static inline void
73_os_log_verify_format_str(__unused const char *msg, ...) /* placeholder */
74{
75}
76
77#if OS_OBJECT_USE_OBJC
78OS_OBJECT_DECL(os_log);
79#else
80typedef 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)
98OS_EXPORT
99struct 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 */
124OS_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 */
159OS_EXPORT OS_NOTHROW OS_WARN_RESULT OS_OBJECT_RETURNS_RETAINED
160os_log_t
161os_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 */
180OS_EXPORT OS_NOTHROW OS_WARN_RESULT
181bool
182os_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 */
199OS_EXPORT OS_NOTHROW OS_WARN_RESULT
200bool
201os_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 */
479bool
480os_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 */
491void
492os_log_coprocessor_register(const char *uuid, const char *file_path, bool copy);
493
494typedef 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 */
506void
507os_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 */
532OS_EXPORT OS_NOTHROW
533void
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 */
543OS_EXPORT OS_NOTHROW
544int
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 */
554OS_EXPORT OS_NOTHROW
555void
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