xref: /xnu-11215/osfmk/kern/printf.c (revision 1031c584)
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 #define isdigit(d) ((d) >= '0' && (d) <= '9')
188 #define Ctod(c) ((c) - '0')
189 
190 #define MAXBUF (sizeof(long long int) * 8)      /* enough for binary */
191 static char digs[] = "0123456789abcdef";
192 
193 #if CONFIG_NO_PRINTF_STRINGS
194 /* Prevent CPP from breaking the definition below */
195 #undef printf
196 #endif
197 
198 int
_consume_printf_args(int a __unused,...)199 _consume_printf_args(int a __unused, ...)
200 {
201 	return 0;
202 }
203 void
_consume_kprintf_args(int a __unused,...)204 _consume_kprintf_args(int a __unused, ...)
205 {
206 }
207 
208 static int
printnum(unsigned long long int u,int base,void (* putc)(int,void *),void * arg)209 printnum(
210 	unsigned long long int  u,      /* number to print */
211 	int             base,
212 	void                    (*putc)(int, void *),
213 	void                    *arg)
214 {
215 	char    buf[MAXBUF];    /* build number here */
216 	char *  p = &buf[MAXBUF - 1];
217 	int nprinted = 0;
218 
219 	do {
220 		*p-- = digs[u % base];
221 		u /= base;
222 	} while (u != 0);
223 
224 	while (++p != &buf[MAXBUF]) {
225 		(*putc)(*p, arg);
226 		nprinted++;
227 	}
228 
229 	return nprinted;
230 }
231 
232 boolean_t       _doprnt_truncates = FALSE;
233 
234 #if (DEVELOPMENT || DEBUG)
235 boolean_t       doprnt_hide_pointers = FALSE;
236 #else
237 boolean_t       doprnt_hide_pointers = TRUE;
238 #endif
239 
240 int
__doprnt(const char * fmt,va_list argp,void (* putc)(int,void * arg),void * arg,int radix,int is_log)241 __doprnt(
242 	const char      *fmt,
243 	va_list                 argp,
244 	/* character output routine */
245 	void                    (*putc)(int, void *arg),
246 	void                    *arg,
247 	int                     radix,          /* default radix - for '%r' */
248 	int                     is_log)
249 {
250 	int             length;
251 	int             prec;
252 	boolean_t       ladjust;
253 	char            padc;
254 	long long               n;
255 	unsigned long long      u;
256 	int             plus_sign;
257 	int             sign_char;
258 	boolean_t       altfmt, truncate;
259 	int             base;
260 	char    c;
261 	int             capitals;
262 	int             long_long;
263 	enum {
264 		INT,
265 		SHORT,
266 		CHAR,
267 	} numeric_type = INT;
268 	int             nprinted = 0;
269 
270 	if (radix < 2 || radix > 36) {
271 		radix = 10;
272 	}
273 
274 	while ((c = *fmt) != '\0') {
275 		if (c != '%') {
276 			(*putc)(c, arg);
277 			nprinted++;
278 			fmt++;
279 			continue;
280 		}
281 
282 		fmt++;
283 
284 		long_long = 0;
285 		numeric_type = INT;
286 		length = 0;
287 		prec = -1;
288 		ladjust = FALSE;
289 		padc = ' ';
290 		plus_sign = 0;
291 		sign_char = 0;
292 		altfmt = FALSE;
293 
294 		while (TRUE) {
295 			c = *fmt;
296 			if (c == '#') {
297 				altfmt = TRUE;
298 			} else if (c == '-') {
299 				ladjust = TRUE;
300 			} else if (c == '+') {
301 				plus_sign = '+';
302 			} else if (c == ' ') {
303 				if (plus_sign == 0) {
304 					plus_sign = ' ';
305 				}
306 			} else {
307 				break;
308 			}
309 			fmt++;
310 		}
311 
312 		if (c == '0') {
313 			padc = '0';
314 			c = *++fmt;
315 		}
316 
317 		if (isdigit(c)) {
318 			while (isdigit(c)) {
319 				length = 10 * length + Ctod(c);
320 				c = *++fmt;
321 			}
322 		} else if (c == '*') {
323 			length = va_arg(argp, int);
324 			c = *++fmt;
325 			if (length < 0) {
326 				ladjust = !ladjust;
327 				length = -length;
328 			}
329 		}
330 
331 		if (c == '.') {
332 			c = *++fmt;
333 			if (isdigit(c)) {
334 				prec = 0;
335 				while (isdigit(c)) {
336 					prec = 10 * prec + Ctod(c);
337 					c = *++fmt;
338 				}
339 			} else if (c == '*') {
340 				prec = va_arg(argp, int);
341 				c = *++fmt;
342 			}
343 		}
344 
345 		if (c == 'l') {
346 			c = *++fmt; /* need it if sizeof(int) < sizeof(long) */
347 			if (sizeof(int) < sizeof(long)) {
348 				long_long = 1;
349 			}
350 			if (c == 'l') {
351 				long_long = 1;
352 				c = *++fmt;
353 			}
354 		} else if (c == 'h') {
355 			c = *++fmt;
356 			numeric_type = SHORT;
357 			if (c == 'h') {
358 				numeric_type = CHAR;
359 				c = *++fmt;
360 			}
361 		} else if (c == 'q' || c == 'L') {
362 			long_long = 1;
363 			c = *++fmt;
364 		}
365 
366 		if (c == 'z' || c == 'Z') {
367 			c = *++fmt;
368 			if (sizeof(size_t) == sizeof(unsigned long long)) {
369 				long_long = 1;
370 			}
371 		} else if (c == 't') {
372 			c = *++fmt;
373 			if (sizeof(ptrdiff_t) == sizeof(unsigned long long)) {
374 				long_long = 1;
375 			}
376 		} else if (c == 'j') {
377 			c = *++fmt;
378 			if (sizeof(intmax_t) == sizeof(unsigned long long)) {
379 				long_long = 1;
380 			}
381 		}
382 
383 		truncate = FALSE;
384 		capitals = 0;   /* Assume lower case printing */
385 
386 		switch (c) {
387 		case 'b':
388 		case 'B':
389 		{
390 			char *p;
391 			boolean_t     any;
392 			int  i;
393 
394 			if (long_long) {
395 				u = va_arg(argp, unsigned long long);
396 			} else {
397 				u = va_arg(argp, unsigned int);
398 			}
399 			p = va_arg(argp, char *);
400 			base = *p++;
401 			nprinted += printnum(u, base, putc, arg);
402 
403 			if (u == 0) {
404 				break;
405 			}
406 
407 			any = FALSE;
408 			while ((i = *p++) != '\0') {
409 				if (*fmt == 'B') {
410 					i = 33 - i;
411 				}
412 				if (*p <= 32) {
413 					/*
414 					 * Bit field
415 					 */
416 					int j;
417 					if (any) {
418 						(*putc)(',', arg);
419 					} else {
420 						(*putc)('<', arg);
421 						any = TRUE;
422 					}
423 					nprinted++;
424 					j = *p++;
425 					if (*fmt == 'B') {
426 						j = 32 - j;
427 					}
428 					for (; (c = *p) > 32; p++) {
429 						(*putc)(c, arg);
430 						nprinted++;
431 					}
432 					nprinted += printnum((unsigned)((u >> (j - 1)) & ((2 << (i - j)) - 1)),
433 					    base, putc, arg);
434 				} else if (u & (1 << (i - 1))) {
435 					if (any) {
436 						(*putc)(',', arg);
437 					} else {
438 						(*putc)('<', arg);
439 						any = TRUE;
440 					}
441 					nprinted++;
442 					for (; (c = *p) > 32; p++) {
443 						(*putc)(c, arg);
444 						nprinted++;
445 					}
446 				} else {
447 					for (; *p > 32; p++) {
448 						continue;
449 					}
450 				}
451 			}
452 			if (any) {
453 				(*putc)('>', arg);
454 				nprinted++;
455 			}
456 			break;
457 		}
458 
459 		case 'c':
460 			c = (char)va_arg(argp, int);
461 			(*putc)(c, arg);
462 			nprinted++;
463 			break;
464 
465 		case 's':
466 		{
467 			const char *p;
468 			const char *p2;
469 
470 			if (prec == -1) {
471 				prec = 0x7fffffff; /* MAXINT */
472 			}
473 			p = va_arg(argp, char *);
474 
475 			if (p == NULL) {
476 				p = "";
477 			}
478 
479 			if (length > 0 && !ladjust) {
480 				n = 0;
481 				p2 = p;
482 
483 				for (; *p != '\0' && n < prec; p++) {
484 					n++;
485 				}
486 
487 				p = p2;
488 
489 				while (n < length) {
490 					(*putc)(' ', arg);
491 					n++;
492 					nprinted++;
493 				}
494 			}
495 
496 			n = 0;
497 
498 			while ((n < prec) && (!(length > 0 && n >= length))) {
499 				if (*p == '\0') {
500 					break;
501 				}
502 				(*putc)(*p++, arg);
503 				nprinted++;
504 				n++;
505 			}
506 
507 			if (n < length && ladjust) {
508 				while (n < length) {
509 					(*putc)(' ', arg);
510 					n++;
511 					nprinted++;
512 				}
513 			}
514 
515 			break;
516 		}
517 
518 		case 'o':
519 			truncate = _doprnt_truncates;
520 			OS_FALLTHROUGH;
521 		case 'O':
522 			base = 8;
523 			goto print_unsigned;
524 
525 		case 'D': {
526 			unsigned char *up;
527 			char *q, *p;
528 
529 			up = (unsigned char *)va_arg(argp, unsigned char *);
530 			p = (char *)va_arg(argp, char *);
531 			if (length == -1) {
532 				length = 16;
533 			}
534 			while (length--) {
535 				(*putc)(digs[(*up >> 4)], arg);
536 				(*putc)(digs[(*up & 0x0f)], arg);
537 				nprinted += 2;
538 				up++;
539 				if (length) {
540 					for (q = p; *q; q++) {
541 						(*putc)(*q, arg);
542 						nprinted++;
543 					}
544 				}
545 			}
546 			break;
547 		}
548 
549 		case 'd':
550 		case 'i':
551 			truncate = _doprnt_truncates;
552 			base = 10;
553 			goto print_signed;
554 
555 		case 'u':
556 			truncate = _doprnt_truncates;
557 			OS_FALLTHROUGH;
558 		case 'U':
559 			base = 10;
560 			goto print_unsigned;
561 
562 		case 'p':
563 			altfmt = TRUE;
564 			if (sizeof(int) < sizeof(void *)) {
565 				long_long = 1;
566 			}
567 			OS_FALLTHROUGH;
568 		case 'x':
569 			truncate = _doprnt_truncates;
570 			base = 16;
571 			goto print_unsigned;
572 
573 		case 'X':
574 			base = 16;
575 			capitals = 16;  /* Print in upper case */
576 			goto print_unsigned;
577 
578 		case 'r':
579 			truncate = _doprnt_truncates;
580 			OS_FALLTHROUGH;
581 		case 'R':
582 			base = radix;
583 			goto print_signed;
584 
585 		case 'n':
586 			truncate = _doprnt_truncates;
587 			OS_FALLTHROUGH;
588 		case 'N':
589 			base = radix;
590 			goto print_unsigned;
591 
592 print_signed:
593 			if (long_long) {
594 				n = va_arg(argp, long long);
595 			} else {
596 				n = va_arg(argp, int);
597 			}
598 			switch (numeric_type) {
599 			case SHORT:
600 				n = (short)n;
601 				break;
602 			case CHAR:
603 				n = (char)n;
604 				break;
605 			default:
606 				break;
607 			}
608 			if (n >= 0) {
609 				u = n;
610 				sign_char = plus_sign;
611 			} else {
612 				u = -n;
613 				sign_char = '-';
614 			}
615 			goto print_num;
616 
617 print_unsigned:
618 			if (long_long) {
619 				u = va_arg(argp, unsigned long long);
620 			} else {
621 				u = va_arg(argp, unsigned int);
622 			}
623 			switch (numeric_type) {
624 			case SHORT:
625 				u = (unsigned short)u;
626 				break;
627 			case CHAR:
628 				u = (unsigned char)u;
629 				break;
630 			default:
631 				break;
632 			}
633 			goto print_num;
634 
635 print_num:
636 			{
637 				char        buf[MAXBUF];/* build number here */
638 				char *      p = &buf[MAXBUF - 1];
639 				static char digits[] = "0123456789abcdef0123456789ABCDEF";
640 				const char *prefix = NULL;
641 
642 				if (truncate) {
643 					u = (long long)((int)(u));
644 				}
645 
646 				if (doprnt_hide_pointers && is_log) {
647 					const char str[] = "<ptr>";
648 					const char* strp = str;
649 					int strl = sizeof(str) - 1;
650 					unsigned long long u_stripped = u;
651 #ifdef HAS_APPLE_PAC
652 					/**
653 					 * Strip out the pointer authentication code before
654 					 * checking whether the pointer is a kernel address.
655 					 */
656 					u_stripped = (unsigned long long)VM_KERNEL_STRIP_PTR(u);
657 #endif /* HAS_APPLE_PAC */
658 
659 					if (u_stripped >= VM_MIN_KERNEL_AND_KEXT_ADDRESS && u_stripped <= VM_MAX_KERNEL_ADDRESS) {
660 						while (*strp != '\0') {
661 							(*putc)(*strp, arg);
662 							strp++;
663 						}
664 						nprinted += strl;
665 						break;
666 					}
667 				}
668 
669 				if (u != 0 && altfmt) {
670 					if (base == 8) {
671 						prefix = "0";
672 					} else if (base == 16) {
673 						prefix = "0x";
674 					}
675 				}
676 
677 				do {
678 					/* Print in the correct case */
679 					*p-- = digits[(u % base) + capitals];
680 					u /= base;
681 				} while (u != 0);
682 
683 				length -= (int)(&buf[MAXBUF - 1] - p);
684 				if (sign_char) {
685 					length--;
686 				}
687 				if (prefix) {
688 					length -= (int)strlen(prefix);
689 				}
690 
691 				if (padc == ' ' && !ladjust) {
692 					/* blank padding goes before prefix */
693 					while (--length >= 0) {
694 						(*putc)(' ', arg);
695 						nprinted++;
696 					}
697 				}
698 				if (sign_char) {
699 					(*putc)(sign_char, arg);
700 					nprinted++;
701 				}
702 				if (prefix) {
703 					while (*prefix) {
704 						(*putc)(*prefix++, arg);
705 						nprinted++;
706 					}
707 				}
708 				if (padc == '0') {
709 					/* zero padding goes after sign and prefix */
710 					while (--length >= 0) {
711 						(*putc)('0', arg);
712 						nprinted++;
713 					}
714 				}
715 				while (++p != &buf[MAXBUF]) {
716 					(*putc)(*p, arg);
717 					nprinted++;
718 				}
719 
720 				if (ladjust) {
721 					while (--length >= 0) {
722 						(*putc)(' ', arg);
723 						nprinted++;
724 					}
725 				}
726 				break;
727 			}
728 
729 		case '\0':
730 			fmt--;
731 			break;
732 
733 		default:
734 			(*putc)(c, arg);
735 			nprinted++;
736 		}
737 		fmt++;
738 	}
739 
740 	return nprinted;
741 }
742 
743 static void
dummy_putc(int ch,void * arg)744 dummy_putc(int ch, void *arg)
745 {
746 	void (*real_putc)(char) = arg;
747 
748 	/*
749 	 * Attempts to panic (or otherwise log to console) during early boot
750 	 * can result in _doprnt() and _doprnt_log() being called from
751 	 * _kprintf() before PE_init_kprintf() has been called. This causes
752 	 * the "putc" param to _doprnt() and _doprnt_log() to be passed as
753 	 * NULL. That NULL makes its way here, and we would try jump to it.
754 	 * Given that this is a poor idea, and this happens at very early
755 	 * boot, there is not a way to report this easily (we are likely
756 	 * already panicing), so we'll just do nothing instead of crashing.
757 	 */
758 	if (real_putc) {
759 		real_putc((char)ch);
760 	}
761 }
762 
763 void
_doprnt(const char * fmt,va_list * argp,void (* putc)(char),int radix)764 _doprnt(
765 	const char      *fmt,
766 	va_list                 *argp,
767 	/* character output routine */
768 	void                    (*putc)(char),
769 	int                     radix)          /* default radix - for '%r' */
770 {
771 	__doprnt(fmt, *argp, dummy_putc, putc, radix, FALSE);
772 }
773 
774 void
_doprnt_log(const char * fmt,va_list * argp,void (* putc)(char),int radix)775 _doprnt_log(
776 	const char      *fmt,
777 	va_list                 *argp,
778 	/* character output routine */
779 	void                    (*putc)(char),
780 	int                     radix)          /* default radix - for '%r' */
781 {
782 	__doprnt(fmt, *argp, dummy_putc, putc, radix, TRUE);
783 }
784 
785 #if     MP_PRINTF
786 boolean_t       new_printf_cpu_number = FALSE;
787 #endif  /* MP_PRINTF */
788 
789 LCK_GRP_DECLARE(log_lock_grp, "log_group");
790 
791 #if defined(__x86_64__)
792 SIMPLE_LOCK_DECLARE(log_lock, 0);
793 #else
794 LCK_TICKET_DECLARE(log_lock, &log_lock_grp);
795 #endif /* __x86_64__ */
796 
797 bool bsd_log_lock(bool);
798 void bsd_log_lock_safe(void);
799 void bsd_log_unlock(void);
800 
801 /*
802  * Locks OS log lock and returns true if successful, false otherwise. Locking
803  * always succeeds in a safe context but may block. Locking in an unsafe context
804  * never blocks but fails if someone else is already holding the lock.
805  *
806  * A caller is responsible to decide whether the context is safe or not.
807  *
808  * As a rule of thumb following cases are *not* considered safe:
809  *   - Interrupts are disabled
810  *   - Pre-emption is disabled
811  *   - When in a debugger
812  *   - During a panic
813  */
814 bool
bsd_log_lock(bool safe)815 bsd_log_lock(bool safe)
816 {
817 	if (!safe) {
818 		assert(!oslog_is_safe());
819 #if defined(__x86_64__)
820 		return simple_lock_try(&log_lock, &log_lock_grp);
821 #else
822 		return lck_ticket_lock_try(&log_lock, &log_lock_grp);
823 #endif /* __x86_64__ */
824 	}
825 #if defined(__x86_64__)
826 	simple_lock(&log_lock, &log_lock_grp);
827 #else
828 	lck_ticket_lock(&log_lock, &log_lock_grp);
829 #endif /* __x86_64__ */
830 	return true;
831 }
832 
833 /*
834  * Locks OS log lock assuming the context is safe. See bsd_log_lock() comment
835  * for details.
836  */
837 void
bsd_log_lock_safe(void)838 bsd_log_lock_safe(void)
839 {
840 	(void) bsd_log_lock(true);
841 }
842 
843 void
bsd_log_unlock(void)844 bsd_log_unlock(void)
845 {
846 #if defined(__x86_64__)
847 	simple_unlock(&log_lock);
848 #else
849 	lck_ticket_unlock(&log_lock);
850 #endif /* __x86_64__ */
851 }
852 
853 void
conslog_putc(char c)854 conslog_putc(char c)
855 {
856 	console_write_char(c);
857 
858 #ifdef MACH_BSD
859 	if (!kernel_debugger_entry_count) {
860 		log_putc(c);
861 	}
862 #endif
863 }
864 
865 void
cons_putc_locked(char c)866 cons_putc_locked(char c)
867 {
868 	console_write_char(c);
869 }
870 
871 __printflike(1, 0)
872 static int
vprintf_internal(const char * fmt,va_list ap_in,void * caller)873 vprintf_internal(const char *fmt, va_list ap_in, void *caller)
874 {
875 	if (fmt) {
876 		struct console_printbuf_state info_data;
877 
878 		va_list ap;
879 		va_copy(ap, ap_in);
880 
881 #pragma clang diagnostic push
882 #pragma clang diagnostic ignored "-Wformat-nonliteral"
883 		os_log_with_args(OS_LOG_DEFAULT, OS_LOG_TYPE_DEFAULT, fmt, ap_in, caller);
884 #pragma clang diagnostic pop
885 
886 		console_printbuf_state_init(&info_data, TRUE, TRUE);
887 		__doprnt(fmt, ap, console_printbuf_putc, &info_data, 16, TRUE);
888 		console_printbuf_clear(&info_data);
889 
890 		va_end(ap);
891 	}
892 	return 0;
893 }
894 
895 __attribute__((noinline, not_tail_called))
896 int
printf(const char * fmt,...)897 printf(const char *fmt, ...)
898 {
899 	int ret;
900 
901 	va_list ap;
902 	va_start(ap, fmt);
903 	ret = vprintf_internal(fmt, ap, __builtin_return_address(0));
904 	va_end(ap);
905 
906 	return ret;
907 }
908 
909 __attribute__((noinline, not_tail_called))
910 int
vprintf(const char * fmt,va_list ap)911 vprintf(const char *fmt, va_list ap)
912 {
913 	return vprintf_internal(fmt, ap, __builtin_return_address(0));
914 }
915 
916 void
consdebug_putc(char c)917 consdebug_putc(char c)
918 {
919 	console_write_char(c);
920 
921 	debug_putc(c);
922 
923 	if (!console_is_serial() && !disable_serial_output) {
924 		PE_kputc(c);
925 	}
926 }
927 
928 void
consdebug_putc_unbuffered(char c)929 consdebug_putc_unbuffered(char c)
930 {
931 	console_write_unbuffered(c);
932 
933 	debug_putc(c);
934 
935 	if (!console_is_serial() && !disable_serial_output) {
936 		PE_kputc(c);
937 	}
938 }
939 
940 void
consdebug_log(char c)941 consdebug_log(char c)
942 {
943 	debug_putc(c);
944 }
945 
946 /*
947  * Append contents to the paniclog buffer but don't flush
948  * it. This is mainly used for writing the actual paniclog
949  * contents since flushing once for every line written
950  * would be prohibitively expensive for the paniclog
951  */
952 int
paniclog_append_noflush(const char * fmt,...)953 paniclog_append_noflush(const char *fmt, ...)
954 {
955 	va_list listp;
956 
957 	va_start(listp, fmt);
958 	_doprnt_log(fmt, &listp, consdebug_putc_unbuffered, 16);
959 	va_end(listp);
960 
961 	return 0;
962 }
963 
964 int
kdb_printf(const char * fmt,...)965 kdb_printf(const char *fmt, ...)
966 {
967 	va_list listp;
968 
969 	va_start(listp, fmt);
970 	_doprnt_log(fmt, &listp, consdebug_putc, 16);
971 	va_end(listp);
972 
973 #if defined(__arm64__)
974 	paniclog_flush();
975 #endif
976 
977 	return 0;
978 }
979 
980 int
kdb_log(const char * fmt,...)981 kdb_log(const char *fmt, ...)
982 {
983 	va_list listp;
984 
985 	va_start(listp, fmt);
986 	_doprnt(fmt, &listp, consdebug_log, 16);
987 	va_end(listp);
988 
989 #if defined(__arm64__)
990 	paniclog_flush();
991 #endif
992 
993 	return 0;
994 }
995 
996 int
kdb_printf_unbuffered(const char * fmt,...)997 kdb_printf_unbuffered(const char *fmt, ...)
998 {
999 	va_list listp;
1000 
1001 	va_start(listp, fmt);
1002 	_doprnt(fmt, &listp, consdebug_putc_unbuffered, 16);
1003 	va_end(listp);
1004 
1005 #if defined(__arm64__)
1006 	paniclog_flush();
1007 #endif
1008 
1009 	return 0;
1010 }
1011 
1012 #if CONFIG_VSPRINTF
1013 static void
copybyte(int c,void * arg)1014 copybyte(int c, void *arg)
1015 {
1016 	/*
1017 	 * arg is a pointer (outside pointer) to the pointer
1018 	 * (inside pointer) which points to the character.
1019 	 * We pass a double pointer, so that we can increment
1020 	 * the inside pointer.
1021 	 */
1022 	char** p = arg; /* cast outside pointer */
1023 	**p = (char)c;  /* store character */
1024 	(*p)++;         /* increment inside pointer */
1025 }
1026 
1027 /*
1028  * Deprecation Warning:
1029  *	sprintf() is being deprecated. Please use snprintf() instead.
1030  */
1031 int
sprintf(char * buf,const char * fmt,...)1032 sprintf(char *buf, const char *fmt, ...)
1033 {
1034 	va_list listp;
1035 	char *copybyte_str;
1036 
1037 	va_start(listp, fmt);
1038 	copybyte_str = buf;
1039 	__doprnt(fmt, listp, copybyte, &copybyte_str, 16, FALSE);
1040 	va_end(listp);
1041 	*copybyte_str = '\0';
1042 	return (int)strlen(buf);
1043 }
1044 #endif /* CONFIG_VSPRINTF */
1045