X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/d7e50217d7adf6e52786a38bcaa4cd698cb9a79e..d26ffc64f583ab2d29df48f13518685602bc8832:/osfmk/kern/printf.c diff --git a/osfmk/kern/printf.c b/osfmk/kern/printf.c index ece7a7806..54a3220d3 100644 --- a/osfmk/kern/printf.c +++ b/osfmk/kern/printf.c @@ -1,16 +1,19 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * @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. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * 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 @@ -20,7 +23,7 @@ * Please see the License for the specific language governing rights and * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ @@ -91,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. * @@ -140,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' * @@ -154,14 +155,11 @@ */ #include -#include #include -#include #include -#include #include -#include #include +#include #include #include #include @@ -170,9 +168,15 @@ #ifdef MACH_BSD #include #endif +#include +#include + +#ifdef __x86_64__ +#include +#endif /* __x86_64__ */ -#ifdef __ppc__ -#include +#if __arm__ || __arm64__ +#include #endif #define isdigit(d) ((d) >= '0' && (d) <= '9') @@ -181,15 +185,28 @@ #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, + 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 * p = &buf[MAXBUF-1]; int nprinted = 0; do { @@ -207,14 +224,21 @@ printnum( 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, + 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; @@ -226,7 +250,7 @@ __doprnt( int sign_char; boolean_t altfmt, truncate; int base; - register char c; + char c; int capitals; int long_long; int nprinted = 0; @@ -282,7 +306,7 @@ __doprnt( } } else if (c == '*') { - length = va_arg(*argp, int); + length = va_arg(argp, int); c = *++fmt; if (length < 0) { ladjust = !ladjust; @@ -300,13 +324,15 @@ __doprnt( } } else if (c == '*') { - prec = va_arg(*argp, int); + prec = va_arg(argp, int); c = *++fmt; } } if (c == 'l') { c = *++fmt; /* need it if sizeof(int) < sizeof(long) */ + if (sizeof(int) 0 && !ladjust) { @@ -427,12 +460,13 @@ __doprnt( n = 0; - while (*p != '\0') { - if (++n > prec || (length > 0 && n > length)) - break; - - (*putc)(*p++, arg); - nprinted++; + while ((n < prec) && (!(length > 0 && n >= length))) { + if (*p == '\0') { + break; + } + (*putc)(*p++, arg); + nprinted++; + n++; } if (n < length && ladjust) { @@ -456,8 +490,8 @@ __doprnt( unsigned char *up; char *q, *p; - up = (unsigned char *)va_arg(*argp, unsigned char *); - p = (char *)va_arg(*argp, char *); + up = (unsigned char *)va_arg(argp, unsigned char *); + p = (char *)va_arg(argp, char *); if (length == -1) length = 16; while(length--) { @@ -488,6 +522,9 @@ __doprnt( case 'p': altfmt = TRUE; + if (sizeof(int)= 0) { u = n; @@ -538,21 +565,36 @@ __doprnt( print_unsigned: if (long_long) { - u = va_arg(*argp, unsigned long long); + u = va_arg(argp, unsigned long long); } else { - u = va_arg(*argp, unsigned long); + u = va_arg(argp, unsigned int); } goto print_num; print_num: { char buf[MAXBUF]; /* build number here */ - register char * p = &buf[MAXBUF-1]; + char * p = &buf[MAXBUF-1]; static char digits[] = "0123456789abcdef0123456789ABCDEF"; - char *prefix = 0; + 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; + + 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"; @@ -566,11 +608,11 @@ __doprnt( u /= base; } while (u != 0); - length -= (&buf[MAXBUF-1] - p); + length -= (int)(&buf[MAXBUF-1] - p); if (sign_char) length--; if (prefix) - length -= strlen((const char *) prefix); + length -= (int)strlen(prefix); if (padc == ' ' && !ladjust) { /* blank padding goes before prefix */ @@ -634,31 +676,73 @@ dummy_putc(int ch, void *arg) void _doprnt( - register const char *fmt, + 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, FALSE); +} + +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); + __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_mutex_data(,sprintf_lock) +decl_simple_lock_data(,bsd_log_spinlock) + +/* + * Defined here to allow lock group to be statically allocated. + */ +static lck_grp_t oslog_stream_lock_grp; +decl_lck_spin_data(,oslog_stream_lock) +void oslog_lock_init(void); + +extern void bsd_log_init(void); +void bsd_log_lock(void); +void bsd_log_unlock(void); void + printf_init(void) { /* * Lock is only really needed after the first thread is created. */ - simple_lock_init(&printf_lock, ETAP_MISC_PRINTF); - mutex_init(&sprintf_lock, ETAP_MISC_PRINTF); + simple_lock_init(&printf_lock, 0); + simple_lock_init(&bsd_log_spinlock, 0); + bsd_log_init(); +} + +void +bsd_log_lock(void) +{ + simple_lock(&bsd_log_spinlock); +} + +void +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 */ @@ -667,8 +751,8 @@ safe_gets( 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; @@ -710,90 +794,208 @@ 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); + 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(); + } + + va_end(ap); + + os_log_with_args(OS_LOG_DEFAULT, OS_LOG_TYPE_DEFAULT, fmt, ap_in, caller); + } + return 0; +} + +__attribute__((noinline,not_tail_called)) +int +printf(const char *fmt, ...) +{ + int ret; + + va_list ap; + va_start(ap, fmt); + ret = vprintf_internal(fmt, ap, __builtin_return_address(0)); + va_end(ap); + + return ret; +} + +__attribute__((noinline,not_tail_called)) +int +vprintf(const char *fmt, va_list ap) +{ + return vprintf_internal(fmt, ap, __builtin_return_address(0)); +} - extern void db_putchar(char c); +void +consdebug_putc(char c) +{ + if (!disableConsoleOutput) + cnputc(c); + + debug_putc(c); + + 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(fmt, &listp, db_putchar, 16); + _doprnt_log(fmt, &listp, consdebug_putc, 16); va_end(listp); -#endif - return; + + return 0; } -void -printf(const char *fmt, ...) +int +kdb_printf(const char *fmt, ...) { va_list listp; - disable_preemption(); va_start(listp, fmt); - _doprnt(fmt, &listp, conslog_putc, 16); + _doprnt_log(fmt, &listp, consdebug_putc, 16); va_end(listp); - enable_preemption(); + +#if CONFIG_EMBEDDED + paniclog_flush(); +#endif + + return 0; } -void -consdebug_putc( - char c) +int +kdb_log(const char *fmt, ...) { - extern unsigned int debug_mode, disableDebugOuput, disableConsoleOutput; + va_list listp; - if ((debug_mode && !disableDebugOuput) || !disableConsoleOutput) - cnputc(c); + va_start(listp, fmt); + _doprnt(fmt, &listp, consdebug_log, 16); + va_end(listp); - debug_putc(c); +#if CONFIG_EMBEDDED + paniclog_flush(); +#endif + + return 0; } -void -kdb_printf(const char *fmt, ...) +int +kdb_printf_unbuffered(const char *fmt, ...) { va_list listp; va_start(listp, fmt); - _doprnt(fmt, &listp, consdebug_putc, 16); + _doprnt(fmt, &listp, consdebug_putc_unbuffered, 16); va_end(listp); + +#if CONFIG_EMBEDDED + paniclog_flush(); +#endif + + return 0; } -static char *copybyte_str; +#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; + char *copybyte_str; va_start(listp, fmt); - mutex_lock(&sprintf_lock); copybyte_str = buf; - _doprnt(fmt, &listp, copybyte, 16); - mutex_unlock(&sprintf_lock); + __doprnt(fmt, listp, copybyte, ©byte_str, 16, FALSE); va_end(listp); - return strlen(buf); + *copybyte_str = '\0'; + return (int)strlen(buf); } +#endif /* !CONFIG_EMBEDDED */