]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/kern/printf.c
xnu-4903.231.4.tar.gz
[apple/xnu.git] / osfmk / kern / printf.c
index fd04f883a2c1a27cd4f2ab8afaf0c4729a872a04..c8abeb624fd7f4d0e07cbc7665d95d8d09a5b754 100644 (file)
  *     +       print '+' if positive
  *     blank   print ' ' if positive
  *
- *     z       signed hexadecimal
+ *     z       set length equal to size_t
  *     r       signed, 'radix'
  *     n       unsigned, 'radix'
  *
  */
 
 #include <debug.h>
-#include <mach_kdb.h>
 #include <mach_kdp.h>
-#include <platforms.h>
 #include <mach/boolean.h>
 #include <kern/cpu_number.h>
-#include <kern/lock.h>
 #include <kern/thread.h>
+#include <kern/debug.h>
 #include <kern/sched_prim.h>
 #include <kern/misc_protos.h>
 #include <stdarg.h>
 #include <sys/msgbuf.h>
 #endif
 #include <console/serial_protos.h>
+#include <os/log_private.h>
 
-#ifdef __ppc__
-#include <ppc/Firmware.h>
+#ifdef __x86_64__
+#include <i386/cpu_data.h>
+#endif /* __x86_64__ */
+
+#if __arm__ || __arm64__
+#include <arm/cpu_data_internal.h>
 #endif
 
+
 #define isdigit(d) ((d) >= '0' && (d) <= '9')
 #define Ctod(c) ((c) - '0')
 
 #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
@@ -222,6 +225,12 @@ 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(
        const char      *fmt,
@@ -229,7 +238,8 @@ __doprnt(
                                                /* 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;
@@ -331,7 +341,14 @@ __doprnt(
            } 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 */
@@ -340,9 +357,9 @@ __doprnt(
                case 'b':
                case 'B':
                {
-                   register char *p;
+                   char *p;
                    boolean_t     any;
-                   register int  i;
+                   int  i;
 
                    if (long_long) {
                        u = va_arg(argp, unsigned long long);
@@ -364,7 +381,7 @@ __doprnt(
                            /*
                             * Bit field
                             */
-                           register int j;
+                           int j;
                            if (any)
                                (*putc)(',', arg);
                            else {
@@ -415,8 +432,8 @@ __doprnt(
 
                case 's':
                {
-                   register const char *p;
-                   register const char *p2;
+                   const char *p;
+                   const char *p2;
 
                    if (prec == -1)
                        prec = 0x7fffffff;      /* MAXINT */
@@ -518,17 +535,7 @@ __doprnt(
                    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;
-
                case 'r':
                    truncate = _doprnt_truncates;
                case 'R':
@@ -568,12 +575,28 @@ __doprnt(
                print_num:
                {
                    char        buf[MAXBUF];    /* build number here */
-                   register char *     p = &buf[MAXBUF-1];
+                   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[] = "<ptr>";
+                       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";
@@ -655,27 +678,46 @@ 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_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)
 {
        /*
@@ -698,14 +740,21 @@ 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)
 {
-       register char *lp;
-       register int c;
+       char *lp;
+       int c;
        char *strmax = str + maxlen - 1; /* allow space for trailing 0 */
 
        lp = str;
@@ -753,71 +802,96 @@ void
 conslog_putc(
        char c)
 {
-       if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
+       if (!disableConsoleOutput)
                cnputc(c);
 
 #ifdef MACH_BSD
-       if (debug_mode == 0)
+       if (!kernel_debugger_entry_count)
                log_putc(c);
 #endif
 }
 
-#if    MACH_KDB
-extern void db_putchar(char c);
-#endif
-
 void
-dbugprintf(__unused const char *fmt, ...)
+cons_putc_locked(
+       char c)
 {
+       if (!disableConsoleOutput)
+               cnputc(c);
+}
 
-#if    MACH_KDB
-       va_list listp;
+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_start(listp, fmt);
-       _doprnt(fmt, &listp, db_putchar, 16);
-       va_end(listp);
-#endif
-       return;
+               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, ...)
 {
-       va_list listp;
+       int ret;
 
-       if (fmt) {
-               disable_preemption();
-               va_start(listp, fmt);
-               _doprnt(fmt, &listp, conslog_putc, 16);
-               va_end(listp);
-               enable_preemption();
-       }
-       return 0;
+       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));
 }
 
 void
 consdebug_putc(char c)
 {
-       if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
+       if (!disableConsoleOutput)
                cnputc(c);
 
        debug_putc(c);
 
-       if (!console_is_serial())
-               if (!disable_serial_output)
-                       PE_kputc(c);
+       if (!console_is_serial() && !disable_serial_output)
+               PE_kputc(c);
 }
 
 void
 consdebug_putc_unbuffered(char c)
 {
-       if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
+       if (!disableConsoleOutput)
                cnputc_unbuffered(c);
 
        debug_putc(c);
 
-       if (!console_is_serial())
-               if (!disable_serial_output)
+       if (!console_is_serial() && !disable_serial_output)
                        PE_kputc(c);
 }
 
@@ -827,14 +901,37 @@ 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_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;
 }
 
@@ -846,6 +943,11 @@ kdb_log(const char *fmt, ...)
        va_start(listp, fmt);
        _doprnt(fmt, &listp, consdebug_log, 16);
        va_end(listp);
+
+#if CONFIG_EMBEDDED
+       paniclog_flush();
+#endif
+
        return 0;
 }
 
@@ -857,9 +959,16 @@ kdb_printf_unbuffered(const char *fmt, ...)
        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(int c, void *arg)
 {
@@ -886,8 +995,9 @@ sprintf(char *buf, const char *fmt, ...)
 
         va_start(listp, fmt);
         copybyte_str = buf;
-        __doprnt(fmt, listp, copybyte, &copybyte_str, 16);
+        __doprnt(fmt, listp, copybyte, &copybyte_str, 16, FALSE);
         va_end(listp);
        *copybyte_str = '\0';
         return (int)strlen(buf);
 }
+#endif /* !CONFIG_EMBEDDED */