xref: /xnu-12377.41.6/osfmk/kern/printf.c (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
1 /*
2  * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_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. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /*
29  * @OSF_COPYRIGHT@
30  */
31 
32 /*
33  * Mach Operating System
34  * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
35  * All Rights Reserved.
36  *
37  * Permission to use, copy, modify and distribute this software and its
38  * documentation is hereby granted, provided that both the copyright
39  * notice and this permission notice appear in all copies of the
40  * software, derivative works or modified versions, and any portions
41  * thereof, and that both notices appear in supporting documentation.
42  *
43  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
44  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
45  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
46  *
47  * Carnegie Mellon requests users of this software to return to
48  *
49  *  Software Distribution Coordinator  or  [email protected]
50  *  School of Computer Science
51  *  Carnegie Mellon University
52  *  Pittsburgh PA 15213-3890
53  *
54  * any improvements or extensions that they make and grant Carnegie Mellon
55  * the rights to redistribute these changes.
56  */
57 
58 /*
59  *  Common code for printf et al.
60  *
61  *  The calling routine typically takes a variable number of arguments,
62  *  and passes the address of the first one.  This implementation
63  *  assumes a straightforward, stack implementation, aligned to the
64  *  machine's wordsize.  Increasing addresses are assumed to point to
65  *  successive arguments (left-to-right), as is the case for a machine
66  *  with a downward-growing stack with arguments pushed right-to-left.
67  *
68  *  To write, for example, fprintf() using this routine, the code
69  *
70  *	fprintf(fd, format, args)
71  *	FILE *fd;
72  *	char *format;
73  *	{
74  *	_doprnt(format, &args, fd);
75  *	}
76  *
77  *  would suffice.  (This example does not handle the fprintf's "return
78  *  value" correctly, but who looks at the return value of fprintf
79  *  anyway?)
80  *
81  *  This version implements the following printf features:
82  *
83  *	%d	decimal conversion
84  *	%u	unsigned conversion
85  *	%x	hexadecimal conversion
86  *	%X	hexadecimal conversion with capital letters
87  *      %D      hexdump, ptr & separator string ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
88  *              if you use, "%*D" then there's a length, the data ptr and then the separator
89  *	%o	octal conversion
90  *	%c	character
91  *	%s	string
92  *	%m.n	field width, precision
93  *	%-m.n	left adjustment
94  *	%0m.n	zero-padding
95  *	%*.*	width and precision taken from arguments
96  *
97  *  This version does not implement %f, %e, or %g.
98  *
99  *  As mentioned, this version does not return any reasonable value.
100  *
101  *  Permission is granted to use, modify, or propagate this code as
102  *  long as this notice is incorporated.
103  *
104  *  Steve Summit 3/25/87
105  *
106  *  Tweaked for long long support and extended to support the hexdump %D
107  *  specifier by dbg 05/02/02.
108  */
109 
110 /*
111  * Added formats for decoding device registers:
112  *
113  * printf("reg = %b", regval, "<base><arg>*")
114  *
115  * where <base> is the output base expressed as a control character:
116  * i.e. '\10' gives octal, '\20' gives hex.  Each <arg> is a sequence of
117  * characters, the first of which gives the bit number to be inspected
118  * (origin 1), and the rest (up to a control character (<= 32)) give the
119  * name of the register.  Thus
120  *	printf("reg = %b\n", 3, "\10\2BITTWO\1BITONE")
121  * would produce
122  *	reg = 3<BITTWO,BITONE>
123  *
124  * If the second character in <arg> is also a control character, it
125  * indicates the last bit of a bit field.  In this case, printf will extract
126  * bits <1> to <2> and print it.  Characters following the second control
127  * character are printed before the bit field.
128  *	printf("reg = %b\n", 0xb, "\10\4\3FIELD1=\2BITTWO\1BITONE")
129  * would produce
130  *	reg = b<FIELD1=2,BITONE>
131  *
132  * The %B format is like %b but the bits are numbered from the most
133  * significant (the bit weighted 31), which is called 1, to the least
134  * significant, called 32.
135  */
136 /*
137  * Added for general use:
138  *	#	prefix for alternate format:
139  *		0x (0X) for hex
140  *		leading 0 for octal
141  *	+	print '+' if positive
142  *	blank	print ' ' if positive
143  *
144  *	z	set length equal to size_t
145  *	r	signed, 'radix'
146  *	n	unsigned, 'radix'
147  *
148  *	D,U,O,Z	same as corresponding lower-case versions
149  *		(compatibility)
150  */
151 /*
152  * Added support for print long long (64-bit) integers.
153  * Use %lld, %Ld or %qd to print a 64-bit int.  Other
154  * output bases such as x, X, u, U, o, and O also work.
155  */
156 
157 #include <debug.h>
158 #include <mach_kdp.h>
159 #include <mach/boolean.h>
160 #include <kern/cpu_number.h>
161 #include <kern/thread.h>
162 #include <kern/debug.h>
163 #include <kern/sched_prim.h>
164 #include <kern/misc_protos.h>
165 #include <stdarg.h>
166 #include <string.h>
167 #include <mach_assert.h>
168 #ifdef  MACH_BSD
169 #include <sys/msgbuf.h>
170 #endif
171 #include <console/serial_protos.h>
172 #include <os/log_private.h>
173 
174 #ifdef __x86_64__
175 #include <i386/cpu_data.h>
176 #endif /* __x86_64__ */
177 
178 #if __arm64__
179 #include <arm/cpu_data_internal.h>
180 #endif
181 
182 #ifdef HAS_APPLE_PAC
183 #include <mach/vm_param.h>
184 #include <ptrauth.h>
185 #endif /* HAS_APPLE_PAC */
186 
187 #if CONFIG_SPTM
188 #include <sptm/sptm_xnu.h>
189 #endif /* CONFIG_SPTM */
190 
191 #define isdigit(d) ((d) >= '0' && (d) <= '9')
192 #define Ctod(c) ((c) - '0')
193 
194 #define MAXBUF (sizeof(long long int) * 8)      /* enough for binary */
195 static char digs[] = "0123456789abcdef";
196 
197 #if CONFIG_NO_PRINTF_STRINGS
198 /* Prevent CPP from breaking the definition below */
199 #undef printf
200 #endif
201 
202 int
_consume_printf_args(int a __unused,...)203 _consume_printf_args(int a __unused, ...)
204 {
205 	return 0;
206 }
207 void
_consume_kprintf_args(int a __unused,...)208 _consume_kprintf_args(int a __unused, ...)
209 {
210 }
211 
212 static int
printnum(unsigned long long int u,int base,void (* putc)(int,void *),void * arg)213 printnum(
214 	unsigned long long int  u,      /* number to print */
215 	int             base,
216 	void                    (*putc)(int, void *),
217 	void                    *arg)
218 {
219 	char    buf[MAXBUF];    /* build number here */
220 	char *  p = &buf[MAXBUF - 1];
221 	int nprinted = 0;
222 
223 	do {
224 		*p-- = digs[u % base];
225 		u /= base;
226 	} while (u != 0);
227 
228 	while (++p != &buf[MAXBUF]) {
229 		(*putc)(*p, arg);
230 		nprinted++;
231 	}
232 
233 	return nprinted;
234 }
235 
236 boolean_t       _doprnt_truncates = FALSE;
237 
238 #if (DEVELOPMENT || DEBUG)
239 boolean_t       doprnt_hide_pointers = FALSE;
240 #else
241 boolean_t       doprnt_hide_pointers = TRUE;
242 #endif
243 
244 int
__doprnt(const char * fmt,va_list argp,void (* putc)(int,void * arg),void * arg,int radix,int is_log)245 __doprnt(
246 	const char      *fmt,
247 	va_list                 argp,
248 	/* character output routine */
249 	void                    (*putc)(int, void *arg),
250 	void                    *arg,
251 	int                     radix,          /* default radix - for '%r' */
252 	int                     is_log)
253 {
254 	int             length;
255 	int             prec;
256 	boolean_t       ladjust;
257 	char            padc;
258 	long long               n;
259 	unsigned long long      u;
260 	int             plus_sign;
261 	int             sign_char;
262 	boolean_t       altfmt, truncate;
263 	int             base;
264 	char    c;
265 	int             capitals;
266 	int             long_long;
267 	enum {
268 		INT,
269 		SHORT,
270 		CHAR,
271 	} numeric_type = INT;
272 	int             nprinted = 0;
273 
274 	if (radix < 2 || radix > 36) {
275 		radix = 10;
276 	}
277 
278 	while ((c = *fmt) != '\0') {
279 		if (c != '%') {
280 			(*putc)(c, arg);
281 			nprinted++;
282 			fmt++;
283 			continue;
284 		}
285 
286 		fmt++;
287 
288 		long_long = 0;
289 		numeric_type = INT;
290 		length = 0;
291 		prec = -1;
292 		ladjust = FALSE;
293 		padc = ' ';
294 		plus_sign = 0;
295 		sign_char = 0;
296 		altfmt = FALSE;
297 
298 		while (TRUE) {
299 			c = *fmt;
300 			if (c == '#') {
301 				altfmt = TRUE;
302 			} else if (c == '-') {
303 				ladjust = TRUE;
304 			} else if (c == '+') {
305 				plus_sign = '+';
306 			} else if (c == ' ') {
307 				if (plus_sign == 0) {
308 					plus_sign = ' ';
309 				}
310 			} else {
311 				break;
312 			}
313 			fmt++;
314 		}
315 
316 		if (c == '0') {
317 			padc = '0';
318 			c = *++fmt;
319 		}
320 
321 		if (isdigit(c)) {
322 			while (isdigit(c)) {
323 				length = 10 * length + Ctod(c);
324 				c = *++fmt;
325 			}
326 		} else if (c == '*') {
327 			length = va_arg(argp, int);
328 			c = *++fmt;
329 			if (length < 0) {
330 				ladjust = !ladjust;
331 				length = -length;
332 			}
333 		}
334 
335 		if (c == '.') {
336 			c = *++fmt;
337 			if (isdigit(c)) {
338 				prec = 0;
339 				while (isdigit(c)) {
340 					prec = 10 * prec + Ctod(c);
341 					c = *++fmt;
342 				}
343 			} else if (c == '*') {
344 				prec = va_arg(argp, int);
345 				c = *++fmt;
346 			}
347 		}
348 
349 		if (c == 'l') {
350 			c = *++fmt; /* need it if sizeof(int) < sizeof(long) */
351 			if (sizeof(int) < sizeof(long)) {
352 				long_long = 1;
353 			}
354 			if (c == 'l') {
355 				long_long = 1;
356 				c = *++fmt;
357 			}
358 		} else if (c == 'h') {
359 			c = *++fmt;
360 			numeric_type = SHORT;
361 			if (c == 'h') {
362 				numeric_type = CHAR;
363 				c = *++fmt;
364 			}
365 		} else if (c == 'q' || c == 'L') {
366 			long_long = 1;
367 			c = *++fmt;
368 		}
369 
370 		if (c == 'z' || c == 'Z') {
371 			c = *++fmt;
372 			if (sizeof(size_t) == sizeof(unsigned long long)) {
373 				long_long = 1;
374 			}
375 		} else if (c == 't') {
376 			c = *++fmt;
377 			if (sizeof(ptrdiff_t) == sizeof(unsigned long long)) {
378 				long_long = 1;
379 			}
380 		} else if (c == 'j') {
381 			c = *++fmt;
382 			if (sizeof(intmax_t) == sizeof(unsigned long long)) {
383 				long_long = 1;
384 			}
385 		}
386 
387 		truncate = FALSE;
388 		capitals = 0;   /* Assume lower case printing */
389 
390 		switch (c) {
391 		case 'b':
392 		case 'B':
393 		{
394 			char *p;
395 			boolean_t     any;
396 			int  i;
397 
398 			if (long_long) {
399 				u = va_arg(argp, unsigned long long);
400 			} else {
401 				u = va_arg(argp, unsigned int);
402 			}
403 			p = va_arg(argp, char *);
404 			base = *p++;
405 			nprinted += printnum(u, base, putc, arg);
406 
407 			if (u == 0) {
408 				break;
409 			}
410 
411 			any = FALSE;
412 			while ((i = *p++) != '\0') {
413 				if (*fmt == 'B') {
414 					i = 33 - i;
415 				}
416 				if (*p <= 32) {
417 					/*
418 					 * Bit field
419 					 */
420 					int j;
421 					if (any) {
422 						(*putc)(',', arg);
423 					} else {
424 						(*putc)('<', arg);
425 						any = TRUE;
426 					}
427 					nprinted++;
428 					j = *p++;
429 					if (*fmt == 'B') {
430 						j = 32 - j;
431 					}
432 					for (; (c = *p) > 32; p++) {
433 						(*putc)(c, arg);
434 						nprinted++;
435 					}
436 					nprinted += printnum((unsigned)((u >> (j - 1)) & ((2 << (i - j)) - 1)),
437 					    base, putc, arg);
438 				} else if (u & (1 << (i - 1))) {
439 					if (any) {
440 						(*putc)(',', arg);
441 					} else {
442 						(*putc)('<', arg);
443 						any = TRUE;
444 					}
445 					nprinted++;
446 					for (; (c = *p) > 32; p++) {
447 						(*putc)(c, arg);
448 						nprinted++;
449 					}
450 				} else {
451 					for (; *p > 32; p++) {
452 						continue;
453 					}
454 				}
455 			}
456 			if (any) {
457 				(*putc)('>', arg);
458 				nprinted++;
459 			}
460 			break;
461 		}
462 
463 		case 'c':
464 			c = (char)va_arg(argp, int);
465 			(*putc)(c, arg);
466 			nprinted++;
467 			break;
468 
469 		case 's':
470 		{
471 			const char *p;
472 			const char *p2;
473 
474 			if (prec == -1) {
475 				prec = 0x7fffffff; /* MAXINT */
476 			}
477 			p = va_arg(argp, char *);
478 
479 			if (p == NULL) {
480 				p = "";
481 			}
482 
483 			if (length > 0 && !ladjust) {
484 				n = 0;
485 				p2 = p;
486 
487 				for (; *p != '\0' && n < prec; p++) {
488 					n++;
489 				}
490 
491 				p = p2;
492 
493 				while (n < length) {
494 					(*putc)(' ', arg);
495 					n++;
496 					nprinted++;
497 				}
498 			}
499 
500 			n = 0;
501 
502 			while ((n < prec) && (!(length > 0 && n >= length))) {
503 				if (*p == '\0') {
504 					break;
505 				}
506 				(*putc)(*p++, arg);
507 				nprinted++;
508 				n++;
509 			}
510 
511 			if (n < length && ladjust) {
512 				while (n < length) {
513 					(*putc)(' ', arg);
514 					n++;
515 					nprinted++;
516 				}
517 			}
518 
519 			break;
520 		}
521 
522 		case 'o':
523 			truncate = _doprnt_truncates;
524 			OS_FALLTHROUGH;
525 		case 'O':
526 			base = 8;
527 			goto print_unsigned;
528 
529 		case 'D': {
530 			unsigned char *up;
531 			char *q, *p;
532 
533 			up = (unsigned char *)va_arg(argp, unsigned char *);
534 			p = (char *)va_arg(argp, char *);
535 			if (length == -1) {
536 				length = 16;
537 			}
538 			while (length--) {
539 				(*putc)(digs[(*up >> 4)], arg);
540 				(*putc)(digs[(*up & 0x0f)], arg);
541 				nprinted += 2;
542 				up++;
543 				if (length) {
544 					for (q = p; *q; q++) {
545 						(*putc)(*q, arg);
546 						nprinted++;
547 					}
548 				}
549 			}
550 			break;
551 		}
552 
553 		case 'd':
554 		case 'i':
555 			truncate = _doprnt_truncates;
556 			base = 10;
557 			goto print_signed;
558 
559 		case 'u':
560 			truncate = _doprnt_truncates;
561 			OS_FALLTHROUGH;
562 		case 'U':
563 			base = 10;
564 			goto print_unsigned;
565 
566 		case 'p':
567 			altfmt = TRUE;
568 			if (sizeof(int) < sizeof(void *)) {
569 				long_long = 1;
570 			}
571 			OS_FALLTHROUGH;
572 		case 'x':
573 			truncate = _doprnt_truncates;
574 			base = 16;
575 			goto print_unsigned;
576 
577 		case 'X':
578 			base = 16;
579 			capitals = 16;  /* Print in upper case */
580 			goto print_unsigned;
581 
582 		case 'r':
583 			truncate = _doprnt_truncates;
584 			OS_FALLTHROUGH;
585 		case 'R':
586 			base = radix;
587 			goto print_signed;
588 
589 		case 'n':
590 			truncate = _doprnt_truncates;
591 			OS_FALLTHROUGH;
592 		case 'N':
593 			base = radix;
594 			goto print_unsigned;
595 
596 print_signed:
597 			if (long_long) {
598 				n = va_arg(argp, long long);
599 			} else {
600 				n = va_arg(argp, int);
601 			}
602 			switch (numeric_type) {
603 			case SHORT:
604 				n = (short)n;
605 				break;
606 			case CHAR:
607 				n = (char)n;
608 				break;
609 			default:
610 				break;
611 			}
612 			if (n >= 0) {
613 				u = n;
614 				sign_char = plus_sign;
615 			} else {
616 				u = -n;
617 				sign_char = '-';
618 			}
619 			goto print_num;
620 
621 print_unsigned:
622 			if (long_long) {
623 				u = va_arg(argp, unsigned long long);
624 			} else {
625 				u = va_arg(argp, unsigned int);
626 			}
627 			switch (numeric_type) {
628 			case SHORT:
629 				u = (unsigned short)u;
630 				break;
631 			case CHAR:
632 				u = (unsigned char)u;
633 				break;
634 			default:
635 				break;
636 			}
637 			goto print_num;
638 
639 print_num:
640 			{
641 				char        buf[MAXBUF];/* build number here */
642 				char *      p = &buf[MAXBUF - 1];
643 				static char digits[] = "0123456789abcdef0123456789ABCDEF";
644 				const char *prefix = NULL;
645 
646 				if (truncate) {
647 					u = (long long)((int)(u));
648 				}
649 
650 				if (doprnt_hide_pointers && is_log) {
651 					const char str[] = "<ptr>";
652 					const char* strp = str;
653 					int strl = sizeof(str) - 1;
654 					unsigned long long u_stripped = u;
655 #ifdef HAS_APPLE_PAC
656 					/**
657 					 * Strip out the pointer authentication code before
658 					 * checking whether the pointer is a kernel address.
659 					 */
660 					u_stripped = (unsigned long long)VM_KERNEL_STRIP_PTR(u);
661 #endif /* HAS_APPLE_PAC */
662 
663 					if (u_stripped >= VM_MIN_KERNEL_AND_KEXT_ADDRESS && u_stripped <= VM_MAX_KERNEL_ADDRESS) {
664 						while (*strp != '\0') {
665 							(*putc)(*strp, arg);
666 							strp++;
667 						}
668 						nprinted += strl;
669 						break;
670 					}
671 				}
672 
673 				if (u != 0 && altfmt) {
674 					if (base == 8) {
675 						prefix = "0";
676 					} else if (base == 16) {
677 						prefix = "0x";
678 					}
679 				}
680 
681 				do {
682 					/* Print in the correct case */
683 					*p-- = digits[(u % base) + capitals];
684 					u /= base;
685 				} while (u != 0);
686 
687 				length -= (int)(&buf[MAXBUF - 1] - p);
688 				if (sign_char) {
689 					length--;
690 				}
691 				if (prefix) {
692 					length -= (int)strlen(prefix);
693 				}
694 
695 				if (padc == ' ' && !ladjust) {
696 					/* blank padding goes before prefix */
697 					while (--length >= 0) {
698 						(*putc)(' ', arg);
699 						nprinted++;
700 					}
701 				}
702 				if (sign_char) {
703 					(*putc)(sign_char, arg);
704 					nprinted++;
705 				}
706 				if (prefix) {
707 					while (*prefix) {
708 						(*putc)(*prefix++, arg);
709 						nprinted++;
710 					}
711 				}
712 				if (padc == '0') {
713 					/* zero padding goes after sign and prefix */
714 					while (--length >= 0) {
715 						(*putc)('0', arg);
716 						nprinted++;
717 					}
718 				}
719 				while (++p != &buf[MAXBUF]) {
720 					(*putc)(*p, arg);
721 					nprinted++;
722 				}
723 
724 				if (ladjust) {
725 					while (--length >= 0) {
726 						(*putc)(' ', arg);
727 						nprinted++;
728 					}
729 				}
730 				break;
731 			}
732 
733 		case '\0':
734 			fmt--;
735 			break;
736 
737 		default:
738 			(*putc)(c, arg);
739 			nprinted++;
740 		}
741 		fmt++;
742 	}
743 
744 	return nprinted;
745 }
746 
747 static void
dummy_putc(int ch,void * arg)748 dummy_putc(int ch, void *arg)
749 {
750 	void (*real_putc)(char) = arg;
751 
752 	/*
753 	 * Attempts to panic (or otherwise log to console) during early boot
754 	 * can result in _doprnt() and _doprnt_log() being called from
755 	 * _kprintf() before PE_init_kprintf() has been called. This causes
756 	 * the "putc" param to _doprnt() and _doprnt_log() to be passed as
757 	 * NULL. That NULL makes its way here, and we would try jump to it.
758 	 * Given that this is a poor idea, and this happens at very early
759 	 * boot, there is not a way to report this easily (we are likely
760 	 * already panicing), so we'll just do nothing instead of crashing.
761 	 */
762 	if (real_putc) {
763 		real_putc((char)ch);
764 	}
765 }
766 
767 void
_doprnt(const char * fmt,va_list * argp,void (* putc)(char),int radix)768 _doprnt(
769 	const char      *fmt,
770 	va_list                 *argp,
771 	/* character output routine */
772 	void                    (*putc)(char),
773 	int                     radix)          /* default radix - for '%r' */
774 {
775 	__doprnt(fmt, *argp, dummy_putc, putc, radix, FALSE);
776 }
777 
778 void
_doprnt_log(const char * fmt,va_list * argp,void (* putc)(char),int radix)779 _doprnt_log(
780 	const char      *fmt,
781 	va_list                 *argp,
782 	/* character output routine */
783 	void                    (*putc)(char),
784 	int                     radix)          /* default radix - for '%r' */
785 {
786 	__doprnt(fmt, *argp, dummy_putc, putc, radix, TRUE);
787 }
788 
789 #if     MP_PRINTF
790 boolean_t       new_printf_cpu_number = FALSE;
791 #endif  /* MP_PRINTF */
792 
793 LCK_GRP_DECLARE(log_lock_grp, "log_group");
794 
795 #if defined(__x86_64__)
796 SIMPLE_LOCK_DECLARE(log_lock, 0);
797 #else
798 LCK_TICKET_DECLARE(log_lock, &log_lock_grp);
799 #endif /* __x86_64__ */
800 
801 bool bsd_log_lock(bool);
802 void bsd_log_lock_safe(void);
803 void bsd_log_unlock(void);
804 
805 /*
806  * Locks OS log lock and returns true if successful, false otherwise. Locking
807  * always succeeds in a safe context but may block. Locking in an unsafe context
808  * never blocks but fails if someone else is already holding the lock.
809  *
810  * A caller is responsible to decide whether the context is safe or not.
811  *
812  * As a rule of thumb following cases are *not* considered safe:
813  *   - Interrupts are disabled
814  *   - Pre-emption is disabled
815  *   - When in a debugger
816  *   - During a panic
817  */
818 bool
bsd_log_lock(bool safe)819 bsd_log_lock(bool safe)
820 {
821 	if (!safe) {
822 		assert(!oslog_is_safe());
823 #if defined(__x86_64__)
824 		return simple_lock_try(&log_lock, &log_lock_grp);
825 #else
826 		return lck_ticket_lock_try(&log_lock, &log_lock_grp);
827 #endif /* __x86_64__ */
828 	}
829 #if defined(__x86_64__)
830 	simple_lock(&log_lock, &log_lock_grp);
831 #else
832 	lck_ticket_lock(&log_lock, &log_lock_grp);
833 #endif /* __x86_64__ */
834 	return true;
835 }
836 
837 /*
838  * Locks OS log lock assuming the context is safe. See bsd_log_lock() comment
839  * for details.
840  */
841 void
bsd_log_lock_safe(void)842 bsd_log_lock_safe(void)
843 {
844 	(void) bsd_log_lock(true);
845 }
846 
847 void
bsd_log_unlock(void)848 bsd_log_unlock(void)
849 {
850 #if defined(__x86_64__)
851 	simple_unlock(&log_lock);
852 #else
853 	lck_ticket_unlock(&log_lock);
854 #endif /* __x86_64__ */
855 }
856 
857 void
conslog_putc(char c)858 conslog_putc(char c)
859 {
860 	console_write_char(c);
861 
862 #ifdef MACH_BSD
863 	if (!kernel_debugger_entry_count) {
864 		log_putc(c);
865 	}
866 #endif
867 }
868 
869 void
cons_putc_locked(char c)870 cons_putc_locked(char c)
871 {
872 	console_write_char(c);
873 }
874 
875 __printflike(1, 0)
876 static int
vprintf_internal(const char * fmt,va_list ap_in,void * caller)877 vprintf_internal(const char *fmt, va_list ap_in, void *caller)
878 {
879 	if (fmt) {
880 		struct console_printbuf_state info_data;
881 
882 		va_list ap;
883 		va_copy(ap, ap_in);
884 
885 #pragma clang diagnostic push
886 #pragma clang diagnostic ignored "-Wformat-nonliteral"
887 #pragma clang diagnostic ignored "-Wformat"
888 		os_log_with_args(OS_LOG_DEFAULT, OS_LOG_TYPE_DEFAULT, fmt, ap_in, caller);
889 #pragma clang diagnostic pop
890 
891 		console_printbuf_state_init(&info_data, TRUE, TRUE);
892 		__doprnt(fmt, ap, console_printbuf_putc, &info_data, 16, TRUE);
893 		console_printbuf_clear(&info_data);
894 
895 		va_end(ap);
896 	}
897 	return 0;
898 }
899 
900 __attribute__((noinline, not_tail_called))
901 int
printf(const char * fmt,...)902 printf(const char *fmt, ...)
903 {
904 	int ret;
905 
906 	va_list ap;
907 	va_start(ap, fmt);
908 	ret = vprintf_internal(fmt, ap, __builtin_return_address(0));
909 	va_end(ap);
910 
911 	return ret;
912 }
913 
914 __attribute__((noinline, not_tail_called))
915 int
vprintf(const char * fmt,va_list ap)916 vprintf(const char *fmt, va_list ap)
917 {
918 	return vprintf_internal(fmt, ap, __builtin_return_address(0));
919 }
920 
921 #if !CONFIG_SPTM
922 #define sptm_serial_putc(c)
923 #endif
924 
925 void
consdebug_putc(char c)926 consdebug_putc(char c)
927 {
928 	console_write_char(c);
929 
930 	debug_putc(c);
931 
932 	/* Ignore `disable_serial_output` for early panic serial output from `sptm_serial_putc()`. */
933 	if (!console_is_serial() && !disable_serial_output && (PE_kputc != NULL)) {
934 		PE_kputc(c);
935 	} else if (!console_is_serial() && (PE_kputc == NULL)) {
936 		/* Use SPTM's serial interface for early serial output. */
937 		sptm_serial_putc(c);
938 	}
939 }
940 
941 void
consdebug_putc_unbuffered(char c)942 consdebug_putc_unbuffered(char c)
943 {
944 	console_write_unbuffered(c);
945 
946 	debug_putc(c);
947 
948 	/* Ignore `disable_serial_output` for early panic serial output from `sptm_serial_putc()`. */
949 	if (!console_is_serial() && !disable_serial_output && (PE_kputc != NULL)) {
950 		PE_kputc(c);
951 	} else if (!console_is_serial() && (PE_kputc == NULL)) {
952 		/* Use SPTM's serial interface for early serial output. */
953 		sptm_serial_putc(c);
954 	}
955 }
956 
957 void
consdebug_log(char c)958 consdebug_log(char c)
959 {
960 	debug_putc(c);
961 }
962 
963 /*
964  * Append contents to the paniclog buffer but don't flush
965  * it. This is mainly used for writing the actual paniclog
966  * contents since flushing once for every line written
967  * would be prohibitively expensive for the paniclog
968  */
969 int
paniclog_append_noflush(const char * fmt,...)970 paniclog_append_noflush(const char *fmt, ...)
971 {
972 	va_list listp;
973 
974 	va_start(listp, fmt);
975 	_doprnt_log(fmt, &listp, consdebug_putc_unbuffered, 16);
976 	va_end(listp);
977 
978 	return 0;
979 }
980 
981 int
kdb_printf(const char * fmt,...)982 kdb_printf(const char *fmt, ...)
983 {
984 	va_list listp;
985 
986 	va_start(listp, fmt);
987 	_doprnt_log(fmt, &listp, consdebug_putc, 16);
988 	va_end(listp);
989 
990 #if defined(__arm64__)
991 	paniclog_flush();
992 #endif
993 
994 	return 0;
995 }
996 
997 int
kdb_log(const char * fmt,...)998 kdb_log(const char *fmt, ...)
999 {
1000 	va_list listp;
1001 
1002 	va_start(listp, fmt);
1003 	_doprnt(fmt, &listp, consdebug_log, 16);
1004 	va_end(listp);
1005 
1006 #if defined(__arm64__)
1007 	paniclog_flush();
1008 #endif
1009 
1010 	return 0;
1011 }
1012 
1013 int
kdb_printf_unbuffered(const char * fmt,...)1014 kdb_printf_unbuffered(const char *fmt, ...)
1015 {
1016 	va_list listp;
1017 
1018 	va_start(listp, fmt);
1019 	_doprnt(fmt, &listp, consdebug_putc_unbuffered, 16);
1020 	va_end(listp);
1021 
1022 #if defined(__arm64__)
1023 	paniclog_flush();
1024 #endif
1025 
1026 	return 0;
1027 }
1028 
1029 #if CONFIG_VSPRINTF
1030 static void
copybyte(int c,void * arg)1031 copybyte(int c, void *arg)
1032 {
1033 	/*
1034 	 * arg is a pointer (outside pointer) to the pointer
1035 	 * (inside pointer) which points to the character.
1036 	 * We pass a double pointer, so that we can increment
1037 	 * the inside pointer.
1038 	 */
1039 	char** p = arg; /* cast outside pointer */
1040 	**p = (char)c;  /* store character */
1041 	(*p)++;         /* increment inside pointer */
1042 }
1043 
1044 /*
1045  * Deprecation Warning:
1046  *	sprintf() is being deprecated. Please use snprintf() instead.
1047  */
1048 int
sprintf(char * buf,const char * fmt,...)1049 sprintf(char *buf, const char *fmt, ...)
1050 {
1051 	va_list listp;
1052 	char *copybyte_str;
1053 
1054 	va_start(listp, fmt);
1055 	copybyte_str = buf;
1056 	__doprnt(fmt, listp, copybyte, &copybyte_str, 16, FALSE);
1057 	va_end(listp);
1058 	*copybyte_str = '\0';
1059 	return (int)strlen(buf);
1060 }
1061 #endif /* CONFIG_VSPRINTF */
1062