X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6601e61aa18bf4f09af135ff61fc7f4771d23b06..4ba76501152d51ccb5647018f3192c6096367d48:/osfmk/kern/printf.c diff --git a/osfmk/kern/printf.c b/osfmk/kern/printf.c index e154b7501..0feea0aeb 100644 --- a/osfmk/kern/printf.c +++ b/osfmk/kern/printf.c @@ -1,50 +1,56 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2019 Apple Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ */ -/* +/* * Mach Operating System * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University * All Rights Reserved. - * + * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. - * + * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * + * * Carnegie Mellon requests users of this software to return to - * + * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 - * + * * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ @@ -88,9 +94,7 @@ * %0m.n zero-padding * %*.* width and precision taken from arguments * - * This version does not implement %f, %e, or %g. It accepts, but - * ignores, an `l' as in %ld, %lo, %lx, and %lu, and therefore will not - * work correctly on machines for which sizeof(long) != sizeof(int). + * This version does not implement %f, %e, or %g. * * As mentioned, this version does not return any reasonable value. * @@ -137,7 +141,7 @@ * + print '+' if positive * blank print ' ' if positive * - * z signed hexadecimal + * z set length equal to size_t * r signed, 'radix' * n unsigned, 'radix' * @@ -151,13 +155,11 @@ */ #include -#include #include -#include #include #include -#include #include +#include #include #include #include @@ -166,455 +168,557 @@ #ifdef MACH_BSD #include #endif +#include +#include + +#ifdef __x86_64__ +#include +#endif /* __x86_64__ */ -#ifdef __ppc__ -#include +#if __arm__ || __arm64__ +#include #endif +#ifdef HAS_APPLE_PAC +#include +#include +#endif /* HAS_APPLE_PAC */ + #define isdigit(d) ((d) >= '0' && (d) <= '9') #define Ctod(c) ((c) - '0') -#define MAXBUF (sizeof(long long int) * 8) /* enough for binary */ +#define MAXBUF (sizeof(long long int) * 8) /* enough for binary */ static char digs[] = "0123456789abcdef"; +#if CONFIG_NO_PRINTF_STRINGS +/* Prevent CPP from breaking the definition below */ +#undef printf +#endif + +int +_consume_printf_args(int a __unused, ...) +{ + return 0; +} +void +_consume_kprintf_args(int a __unused, ...) +{ +} + static int printnum( - register unsigned long long int u, /* number to print */ - register int base, - void (*putc)(int, void *), + unsigned long long int u, /* number to print */ + int base, + void (*putc)(int, void *), void *arg) { - char buf[MAXBUF]; /* build number here */ - register char * p = &buf[MAXBUF-1]; + char buf[MAXBUF]; /* build number here */ + char * p = &buf[MAXBUF - 1]; int nprinted = 0; do { - *p-- = digs[u % base]; - u /= base; + *p-- = digs[u % base]; + u /= base; } while (u != 0); while (++p != &buf[MAXBUF]) { - (*putc)(*p, arg); - nprinted++; + (*putc)(*p, arg); + nprinted++; } return nprinted; } -boolean_t _doprnt_truncates = FALSE; +boolean_t _doprnt_truncates = FALSE; + +#if (DEVELOPMENT || DEBUG) +boolean_t doprnt_hide_pointers = FALSE; +#else +boolean_t doprnt_hide_pointers = TRUE; +#endif int __doprnt( - register const char *fmt, - va_list *argp, - /* character output routine */ - void (*putc)(int, void *arg), + const char *fmt, + va_list argp, + /* character output routine */ + void (*putc)(int, void *arg), void *arg, - int radix) /* default radix - for '%r' */ + int radix, /* default radix - for '%r' */ + int is_log) { - int length; - int prec; - boolean_t ladjust; - char padc; - long long n; - unsigned long long u; - int plus_sign; - int sign_char; - boolean_t altfmt, truncate; - int base; - register char c; - int capitals; - int long_long; + int length; + int prec; + boolean_t ladjust; + char padc; + long long n; + unsigned long long u; + int plus_sign; + int sign_char; + boolean_t altfmt, truncate; + int base; + char c; + int capitals; + int long_long; + enum { + INT, + SHORT, + CHAR, + } numeric_type = INT; int nprinted = 0; while ((c = *fmt) != '\0') { - if (c != '%') { - (*putc)(c, arg); - nprinted++; - fmt++; - continue; - } - - fmt++; - - long_long = 0; - length = 0; - prec = -1; - ladjust = FALSE; - padc = ' '; - plus_sign = 0; - sign_char = 0; - altfmt = FALSE; - - while (TRUE) { - c = *fmt; - if (c == '#') { - altfmt = TRUE; - } - else if (c == '-') { - ladjust = TRUE; - } - else if (c == '+') { - plus_sign = '+'; - } - else if (c == ' ') { - if (plus_sign == 0) - plus_sign = ' '; + if (c != '%') { + (*putc)(c, arg); + nprinted++; + fmt++; + continue; } - else - break; - fmt++; - } - if (c == '0') { - padc = '0'; - c = *++fmt; - } + fmt++; - if (isdigit(c)) { - while(isdigit(c)) { - length = 10 * length + Ctod(c); - c = *++fmt; + long_long = 0; + numeric_type = INT; + length = 0; + prec = -1; + ladjust = FALSE; + padc = ' '; + plus_sign = 0; + sign_char = 0; + altfmt = FALSE; + + while (TRUE) { + c = *fmt; + if (c == '#') { + altfmt = TRUE; + } else if (c == '-') { + ladjust = TRUE; + } else if (c == '+') { + plus_sign = '+'; + } else if (c == ' ') { + if (plus_sign == 0) { + plus_sign = ' '; + } + } else { + break; + } + fmt++; } - } - else if (c == '*') { - length = va_arg(*argp, int); - c = *++fmt; - if (length < 0) { - ladjust = !ladjust; - length = -length; + + if (c == '0') { + padc = '0'; + c = *++fmt; } - } - if (c == '.') { - c = *++fmt; if (isdigit(c)) { - prec = 0; - while(isdigit(c)) { - prec = 10 * prec + Ctod(c); + while (isdigit(c)) { + length = 10 * length + Ctod(c); + c = *++fmt; + } + } else if (c == '*') { + length = va_arg(argp, int); c = *++fmt; - } + if (length < 0) { + ladjust = !ladjust; + length = -length; + } } - else if (c == '*') { - prec = va_arg(*argp, int); - c = *++fmt; + + if (c == '.') { + c = *++fmt; + if (isdigit(c)) { + prec = 0; + while (isdigit(c)) { + prec = 10 * prec + Ctod(c); + c = *++fmt; + } + } else if (c == '*') { + prec = va_arg(argp, int); + c = *++fmt; + } } - } - if (c == 'l') { - c = *++fmt; /* need it if sizeof(int) < sizeof(long) */ if (c == 'l') { - long_long = 1; - c = *++fmt; - } - } else if (c == 'q' || c == 'L') { - long_long = 1; - c = *++fmt; - } - - truncate = FALSE; - capitals=0; /* Assume lower case printing */ - - switch(c) { + c = *++fmt; /* need it if sizeof(int) < sizeof(long) */ + if (sizeof(int) < sizeof(long)) { + long_long = 1; + } + if (c == 'l') { + long_long = 1; + c = *++fmt; + } + } else if (c == 'h') { + c = *++fmt; + numeric_type = SHORT; + if (c == 'h') { + numeric_type = CHAR; + c = *++fmt; + } + } else if (c == 'q' || c == 'L') { + long_long = 1; + c = *++fmt; + } + + if (c == 'z' || c == 'Z') { + c = *++fmt; + if (sizeof(size_t) == sizeof(unsigned long)) { + long_long = 1; + } + } + + truncate = FALSE; + capitals = 0; /* Assume lower case printing */ + + switch (c) { case 'b': case 'B': { - register char *p; - boolean_t any; - register int i; - - if (long_long) { - u = va_arg(*argp, unsigned long long); - } else { - u = va_arg(*argp, unsigned long); - } - p = va_arg(*argp, char *); - base = *p++; - nprinted += printnum(u, base, putc, arg); - - if (u == 0) - break; + char *p; + boolean_t any; + int i; + + if (long_long) { + u = va_arg(argp, unsigned long long); + } else { + u = va_arg(argp, unsigned int); + } + p = va_arg(argp, char *); + base = *p++; + nprinted += printnum(u, base, putc, arg); - any = FALSE; - while ((i = *p++) != '\0') { - if (*fmt == 'B') - i = 33 - i; - if (*p <= 32) { - /* - * Bit field - */ - register int j; - if (any) - (*putc)(',', arg); - else { - (*putc)('<', arg); - any = TRUE; - } - nprinted++; - j = *p++; - if (*fmt == 'B') - j = 32 - j; - for (; (c = *p) > 32; p++) { - (*putc)(c, arg); - nprinted++; - } - nprinted += printnum((unsigned)( (u>>(j-1)) & ((2<<(i-j))-1)), - base, putc, arg); + if (u == 0) { + break; } - else if (u & (1<<(i-1))) { - if (any) - (*putc)(',', arg); - else { - (*putc)('<', arg); - any = TRUE; - } - nprinted++; - for (; (c = *p) > 32; p++) { - (*putc)(c, arg); - nprinted++; - } + + any = FALSE; + while ((i = *p++) != '\0') { + if (*fmt == 'B') { + i = 33 - i; + } + if (*p <= 32) { + /* + * Bit field + */ + int j; + if (any) { + (*putc)(',', arg); + } else { + (*putc)('<', arg); + any = TRUE; + } + nprinted++; + j = *p++; + if (*fmt == 'B') { + j = 32 - j; + } + for (; (c = *p) > 32; p++) { + (*putc)(c, arg); + nprinted++; + } + nprinted += printnum((unsigned)((u >> (j - 1)) & ((2 << (i - j)) - 1)), + base, putc, arg); + } else if (u & (1 << (i - 1))) { + if (any) { + (*putc)(',', arg); + } else { + (*putc)('<', arg); + any = TRUE; + } + nprinted++; + for (; (c = *p) > 32; p++) { + (*putc)(c, arg); + nprinted++; + } + } else { + for (; *p > 32; p++) { + continue; + } + } } - else { - for (; *p > 32; p++) - continue; + if (any) { + (*putc)('>', arg); + nprinted++; } - } - if (any) { - (*putc)('>', arg); - nprinted++; - } - break; + break; } case 'c': - c = va_arg(*argp, int); - (*putc)(c, arg); - nprinted++; - break; + c = va_arg(argp, int); + (*putc)(c, arg); + nprinted++; + break; case 's': { - register char *p; - register char *p2; + const char *p; + const char *p2; - if (prec == -1) - prec = 0x7fffffff; /* MAXINT */ - - p = va_arg(*argp, char *); + if (prec == -1) { + prec = 0x7fffffff; /* MAXINT */ + } + p = va_arg(argp, char *); - if (p == (char *)0) - p = ""; + if (p == NULL) { + p = ""; + } - if (length > 0 && !ladjust) { - n = 0; - p2 = p; + if (length > 0 && !ladjust) { + n = 0; + p2 = p; - for (; *p != '\0' && n < prec; p++) - n++; + for (; *p != '\0' && n < prec; p++) { + n++; + } - p = p2; + p = p2; - while (n < length) { - (*putc)(' ', arg); - n++; - nprinted++; + while (n < length) { + (*putc)(' ', arg); + n++; + nprinted++; + } } - } - - n = 0; - while (*p != '\0') { - if (++n > prec || (length > 0 && n > length)) - break; + n = 0; - (*putc)(*p++, arg); - nprinted++; - } + while ((n < prec) && (!(length > 0 && n >= length))) { + if (*p == '\0') { + break; + } + (*putc)(*p++, arg); + nprinted++; + n++; + } - if (n < length && ladjust) { - while (n < length) { - (*putc)(' ', arg); - n++; - nprinted++; + if (n < length && ladjust) { + while (n < length) { + (*putc)(' ', arg); + n++; + nprinted++; + } } - } - break; + break; } case 'o': - truncate = _doprnt_truncates; + truncate = _doprnt_truncates; case 'O': - base = 8; - goto print_unsigned; + base = 8; + goto print_unsigned; case 'D': { - unsigned char *up; - char *q, *p; - - up = (unsigned char *)va_arg(*argp, unsigned char *); - p = (char *)va_arg(*argp, char *); - if (length == -1) + unsigned char *up; + char *q, *p; + + up = (unsigned char *)va_arg(argp, unsigned char *); + p = (char *)va_arg(argp, char *); + if (length == -1) { length = 16; - while(length--) { + } + while (length--) { (*putc)(digs[(*up >> 4)], arg); (*putc)(digs[(*up & 0x0f)], arg); nprinted += 2; up++; if (length) { - for (q=p;*q;q++) { + for (q = p; *q; q++) { (*putc)(*q, arg); nprinted++; - } + } } } break; } case 'd': - truncate = _doprnt_truncates; - base = 10; - goto print_signed; + truncate = _doprnt_truncates; + base = 10; + goto print_signed; case 'u': - truncate = _doprnt_truncates; + truncate = _doprnt_truncates; + /* FALLTHROUGH */ case 'U': - base = 10; - goto print_unsigned; + base = 10; + goto print_unsigned; case 'p': - altfmt = TRUE; + altfmt = TRUE; + if (sizeof(int) < sizeof(void *)) { + long_long = 1; + } + /* FALLTHROUGH */ case 'x': - truncate = _doprnt_truncates; - base = 16; - goto print_unsigned; + truncate = _doprnt_truncates; + base = 16; + goto print_unsigned; case 'X': - base = 16; - capitals=16; /* Print in upper case */ - goto print_unsigned; - - case 'z': - truncate = _doprnt_truncates; - base = 16; - goto print_signed; - - case 'Z': - base = 16; - capitals=16; /* Print in upper case */ - goto print_signed; + base = 16; + capitals = 16; /* Print in upper case */ + goto print_unsigned; case 'r': - truncate = _doprnt_truncates; + truncate = _doprnt_truncates; + /* FALLTHROUGH */ case 'R': - base = radix; - goto print_signed; + base = radix; + goto print_signed; case 'n': - truncate = _doprnt_truncates; + truncate = _doprnt_truncates; + /* FALLTHROUGH */ case 'N': - base = radix; - goto print_unsigned; - - print_signed: - if (long_long) { - n = va_arg(*argp, long long); - } else { - n = va_arg(*argp, long); - } - if (n >= 0) { - u = n; - sign_char = plus_sign; - } - else { - u = -n; - sign_char = '-'; - } - goto print_num; - - print_unsigned: - if (long_long) { - u = va_arg(*argp, unsigned long long); - } else { - u = va_arg(*argp, unsigned long); - } - goto print_num; - - print_num: - { - char buf[MAXBUF]; /* build number here */ - register char * p = &buf[MAXBUF-1]; - static char digits[] = "0123456789abcdef0123456789ABCDEF"; - char *prefix = 0; - - if (truncate) u = (long long)((int)(u)); - - if (u != 0 && altfmt) { - if (base == 8) - prefix = "0"; - else if (base == 16) - prefix = "0x"; - } - - do { - /* Print in the correct case */ - *p-- = digits[(u % base)+capitals]; - u /= base; - } while (u != 0); - - length -= (&buf[MAXBUF-1] - p); - if (sign_char) - length--; - if (prefix) - length -= strlen((const char *) prefix); - - if (padc == ' ' && !ladjust) { - /* blank padding goes before prefix */ - while (--length >= 0) { - (*putc)(' ', arg); - nprinted++; - } - } - if (sign_char) { - (*putc)(sign_char, arg); - nprinted++; - } - if (prefix) { - while (*prefix) { - (*putc)(*prefix++, arg); - nprinted++; + base = radix; + goto print_unsigned; + +print_signed: + if (long_long) { + n = va_arg(argp, long long); + } else { + n = va_arg(argp, int); } - } - if (padc == '0') { - /* zero padding goes after sign and prefix */ - while (--length >= 0) { - (*putc)('0', arg); - nprinted++; - } - } - while (++p != &buf[MAXBUF]) { - (*putc)(*p, arg); - nprinted++; - } - - if (ladjust) { - while (--length >= 0) { - (*putc)(' ', arg); - nprinted++; + switch (numeric_type) { + case SHORT: + n = (short)n; + break; + case CHAR: + n = (char)n; + break; + default: + break; + } + if (n >= 0) { + u = n; + sign_char = plus_sign; + } else { + u = -n; + sign_char = '-'; + } + goto print_num; + +print_unsigned: + if (long_long) { + u = va_arg(argp, unsigned long long); + } else { + u = va_arg(argp, unsigned int); + } + switch (numeric_type) { + case SHORT: + u = (unsigned short)u; + break; + case CHAR: + u = (unsigned char)u; + break; + default: + break; + } + goto print_num; + +print_num: + { + char buf[MAXBUF];/* build number here */ + char * p = &buf[MAXBUF - 1]; + static char digits[] = "0123456789abcdef0123456789ABCDEF"; + const char *prefix = NULL; + + if (truncate) { + u = (long long)((int)(u)); + } + + if (doprnt_hide_pointers && is_log) { + const char str[] = ""; + const char* strp = str; + int strl = sizeof(str) - 1; + +#ifdef HAS_APPLE_PAC + /** + * Strip out the pointer authentication code before + * checking whether the pointer is a kernel address. + */ + u = (unsigned long long)VM_KERNEL_STRIP_PTR(u); +#endif /* HAS_APPLE_PAC */ + + if (u >= VM_MIN_KERNEL_AND_KEXT_ADDRESS && u <= VM_MAX_KERNEL_ADDRESS) { + while (*strp != '\0') { + (*putc)(*strp, arg); + strp++; + } + nprinted += strl; + break; + } + } + + if (u != 0 && altfmt) { + if (base == 8) { + prefix = "0"; + } else if (base == 16) { + prefix = "0x"; + } + } + + do { + /* Print in the correct case */ + *p-- = digits[(u % base) + capitals]; + u /= base; + } while (u != 0); + + length -= (int)(&buf[MAXBUF - 1] - p); + if (sign_char) { + length--; + } + if (prefix) { + length -= (int)strlen(prefix); + } + + if (padc == ' ' && !ladjust) { + /* blank padding goes before prefix */ + while (--length >= 0) { + (*putc)(' ', arg); + nprinted++; + } + } + if (sign_char) { + (*putc)(sign_char, arg); + nprinted++; + } + if (prefix) { + while (*prefix) { + (*putc)(*prefix++, arg); + nprinted++; + } + } + if (padc == '0') { + /* zero padding goes after sign and prefix */ + while (--length >= 0) { + (*putc)('0', arg); + nprinted++; + } + } + while (++p != &buf[MAXBUF]) { + (*putc)(*p, arg); + nprinted++; + } + + if (ladjust) { + while (--length >= 0) { + (*putc)(' ', arg); + nprinted++; + } + } + break; } - } - break; - } case '\0': - fmt--; - break; + fmt--; + break; default: - (*putc)(c, arg); - nprinted++; - } - fmt++; + (*putc)(c, arg); + nprinted++; + } + fmt++; } return nprinted; @@ -623,30 +727,56 @@ __doprnt( static void dummy_putc(int ch, void *arg) { - void (*real_putc)(char) = arg; - - real_putc(ch); + void (*real_putc)(char) = arg; + + /* + * Attempts to panic (or otherwise log to console) during early boot + * can result in _doprnt() and _doprnt_log() being called from + * _kprintf() before PE_init_kprintf() has been called. This causes + * the "putc" param to _doprnt() and _doprnt_log() to be passed as + * NULL. That NULL makes its way here, and we would try jump to it. + * Given that this is a poor idea, and this happens at very early + * boot, there is not a way to report this easily (we are likely + * already panicing), so we'll just do nothing instead of crashing. + */ + if (real_putc) { + real_putc(ch); + } } -void +void _doprnt( - register const char *fmt, - va_list *argp, - /* character output routine */ - void (*putc)(char), - int radix) /* default radix - for '%r' */ + const char *fmt, + va_list *argp, + /* character output routine */ + void (*putc)(char), + int radix) /* default radix - for '%r' */ { - __doprnt(fmt, argp, dummy_putc, putc, radix); + __doprnt(fmt, *argp, dummy_putc, putc, radix, FALSE); } -#if MP_PRINTF -boolean_t new_printf_cpu_number = FALSE; -#endif /* MP_PRINTF */ +void +_doprnt_log( + const char *fmt, + va_list *argp, + /* character output routine */ + void (*putc)(char), + int radix) /* default radix - for '%r' */ +{ + __doprnt(fmt, *argp, dummy_putc, putc, radix, TRUE); +} + +#if MP_PRINTF +boolean_t new_printf_cpu_number = FALSE; +#endif /* MP_PRINTF */ + +decl_simple_lock_data(, printf_lock); +decl_simple_lock_data(, bsd_log_spinlock); +lck_grp_t oslog_stream_lock_grp; +decl_lck_spin_data(, oslog_stream_lock); +void oslog_lock_init(void); -decl_simple_lock_data(,printf_lock) -decl_simple_lock_data(,bsd_log_spinlock) -decl_mutex_data(,sprintf_lock) extern void bsd_log_init(void); void bsd_log_lock(void); void bsd_log_unlock(void); @@ -660,29 +790,35 @@ printf_init(void) simple_lock_init(&printf_lock, 0); simple_lock_init(&bsd_log_spinlock, 0); bsd_log_init(); - mutex_init(&sprintf_lock, 0); } void -bsd_log_lock() +bsd_log_lock(void) { - simple_lock(&bsd_log_spinlock); + simple_lock(&bsd_log_spinlock, LCK_GRP_NULL); } void -bsd_log_unlock() +bsd_log_unlock(void) { simple_unlock(&bsd_log_spinlock); } +void +oslog_lock_init(void) +{ + lck_grp_init(&oslog_stream_lock_grp, "oslog stream", LCK_GRP_ATTR_NULL); + lck_spin_init(&oslog_stream_lock, &oslog_stream_lock_grp, LCK_ATTR_NULL); +} + /* derived from boot_gets */ void safe_gets( - char *str, - int maxlen) + char *str, + int maxlen) { - register char *lp; - register int c; + char *lp; + int c; char *strmax = str + maxlen - 1; /* allow space for trailing 0 */ lp = str; @@ -694,7 +830,7 @@ safe_gets( printf("\n"); *lp++ = 0; return; - + case '\b': case '#': case '\177': @@ -715,8 +851,7 @@ safe_gets( if (lp < strmax) { *lp++ = c; printf("%c", c); - } - else { + } else { printf("%c", '\007'); /* beep */ } } @@ -724,95 +859,215 @@ safe_gets( } } +extern int disableConsoleOutput; + void conslog_putc( char c) { - extern unsigned int debug_mode, disableDebugOuput, disableConsoleOutput; - - if ((debug_mode && !disableDebugOuput) || !disableConsoleOutput) + if (!disableConsoleOutput) { cnputc(c); + } -#ifdef MACH_BSD - log_putc(c); +#ifdef MACH_BSD + if (!kernel_debugger_entry_count) { + log_putc(c); + } #endif } void -dbugprintf(const char *fmt, ...) +cons_putc_locked( + char c) { + if (!disableConsoleOutput) { + cnputc(c); + } +} -#if MACH_KDB +static int +vprintf_internal(const char *fmt, va_list ap_in, void *caller) +{ + cpu_data_t * cpu_data_p; + if (fmt) { + struct console_printbuf_state info_data; + cpu_data_p = current_cpu_datap(); + + va_list ap; + va_copy(ap, ap_in); + /* + * for early boot printf()s console may not be setup, + * fallback to good old cnputc + */ + if (cpu_data_p->cpu_console_buf != NULL) { + console_printbuf_state_init(&info_data, TRUE, TRUE); + __doprnt(fmt, ap, console_printbuf_putc, &info_data, 16, TRUE); + console_printbuf_clear(&info_data); + } else { + disable_preemption(); + _doprnt_log(fmt, &ap, cons_putc_locked, 16); + enable_preemption(); + } - extern void db_putchar(char c); - va_list listp; + va_end(ap); - va_start(listp, fmt); - _doprnt(fmt, &listp, db_putchar, 16); - va_end(listp); -#endif - return; + os_log_with_args(OS_LOG_DEFAULT, OS_LOG_TYPE_DEFAULT, fmt, ap_in, caller); + } + return 0; } -void +__attribute__((noinline, not_tail_called)) +int printf(const char *fmt, ...) { - va_list listp; + int ret; - disable_preemption(); - va_start(listp, fmt); - _doprnt(fmt, &listp, conslog_putc, 16); - va_end(listp); - enable_preemption(); + va_list ap; + va_start(ap, fmt); + ret = vprintf_internal(fmt, ap, __builtin_return_address(0)); + va_end(ap); + + return ret; } -void -consdebug_putc( - char c) +__attribute__((noinline, not_tail_called)) +int +vprintf(const char *fmt, va_list ap) { - extern unsigned int debug_mode, disableDebugOuput, disableConsoleOutput; + return vprintf_internal(fmt, ap, __builtin_return_address(0)); +} - if ((debug_mode && !disableDebugOuput) || !disableConsoleOutput) +void +consdebug_putc(char c) +{ + if (!disableConsoleOutput) { cnputc(c); + } debug_putc(c); -#ifdef __ppc__ - if (!console_is_serial()) - PE_kputc(c); -#endif + if (!console_is_serial() && !disable_serial_output) { + PE_kputc(c); + } +} + +void +consdebug_putc_unbuffered(char c) +{ + if (!disableConsoleOutput) { + cnputc_unbuffered(c); + } + + debug_putc(c); + + if (!console_is_serial() && !disable_serial_output) { + PE_kputc(c); + } } void +consdebug_log(char c) +{ + debug_putc(c); +} + +/* + * Append contents to the paniclog buffer but don't flush + * it. This is mainly used for writing the actual paniclog + * contents since flushing once for every line written + * would be prohibitively expensive for the paniclog + */ +int +paniclog_append_noflush(const char *fmt, ...) +{ + va_list listp; + + va_start(listp, fmt); + _doprnt_log(fmt, &listp, consdebug_putc, 16); + va_end(listp); + + return 0; +} + +int kdb_printf(const char *fmt, ...) { - va_list listp; + va_list listp; va_start(listp, fmt); - _doprnt(fmt, &listp, consdebug_putc, 16); + _doprnt_log(fmt, &listp, consdebug_putc, 16); va_end(listp); + +#if CONFIG_EMBEDDED + paniclog_flush(); +#endif + + return 0; } -static char *copybyte_str; +int +kdb_log(const char *fmt, ...) +{ + va_list listp; + + va_start(listp, fmt); + _doprnt(fmt, &listp, consdebug_log, 16); + va_end(listp); + +#if CONFIG_EMBEDDED + paniclog_flush(); +#endif + + return 0; +} + +int +kdb_printf_unbuffered(const char *fmt, ...) +{ + va_list listp; + + va_start(listp, fmt); + _doprnt(fmt, &listp, consdebug_putc_unbuffered, 16); + va_end(listp); + +#if CONFIG_EMBEDDED + paniclog_flush(); +#endif + + return 0; +} + +#if !CONFIG_EMBEDDED static void -copybyte( - char byte) +copybyte(int c, void *arg) { - *copybyte_str++ = byte; - *copybyte_str = '\0'; + /* + * arg is a pointer (outside pointer) to the pointer + * (inside pointer) which points to the character. + * We pass a double pointer, so that we can increment + * the inside pointer. + */ + char** p = arg; /* cast outside pointer */ + **p = c; /* store character */ + (*p)++; /* increment inside pointer */ } +/* + * Deprecation Warning: + * sprintf() is being deprecated. Please use snprintf() instead. + */ int sprintf(char *buf, const char *fmt, ...) { - va_list listp; - - va_start(listp, fmt); - mutex_lock(&sprintf_lock); - copybyte_str = buf; - _doprnt(fmt, &listp, copybyte, 16); - mutex_unlock(&sprintf_lock); - va_end(listp); - return strlen(buf); + va_list listp; + char *copybyte_str; + + va_start(listp, fmt); + copybyte_str = buf; + __doprnt(fmt, listp, copybyte, ©byte_str, 16, FALSE); + va_end(listp); + *copybyte_str = '\0'; + return (int)strlen(buf); } +#endif /* !CONFIG_EMBEDDED */