]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/kern/printf.c
xnu-7195.81.3.tar.gz
[apple/xnu.git] / osfmk / kern / printf.c
index 8772a0251d0df6eeb23655670914a460f61c1dec..898086d8ec3518c91e525bcb24f601d1f0228443 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple 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
  * 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,
  * 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.
  */
  *     +       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_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 __x86_64__
+#include <i386/cpu_data.h>
+#endif /* __x86_64__ */
+
+#if __arm__ || __arm64__
+#include <arm/cpu_data_internal.h>
+#endif
+
+#ifdef HAS_APPLE_PAC
+#include <mach/vm_param.h>
+#include <ptrauth.h>
+#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
@@ -182,458 +195,536 @@ static char digs[] = "0123456789abcdef";
 #undef printf
 #endif
 
-int _consume_printf_args(int a __unused, ...)
+int
+_consume_printf_args(int a __unused, ...)
 {
-    return 0;
+       return 0;
 }
-void _consume_kprintf_args(int a __unused, ...)
+void
+_consume_kprintf_args(int a __unused, ...)
 {
 }
 
 static int
 printnum(
-       unsigned long long int  u,      /* number to print */
-       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 */
-       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(
-       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;
-       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;
 
+       if (radix < 2 || radix > 36) {
+               radix = 10;
+       }
+
        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 (sizeof(int)<sizeof(long))
-                   long_long = 1;
                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 int);
-                   }
-                   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 = (char)va_arg(argp, int);
+                       (*putc)(c, arg);
+                       nprinted++;
+                       break;
 
                case 's':
                {
-                   register const char *p;
-                   register const char *p2;
+                       const char *p;
+                       const char *p2;
 
-                   if (prec == -1)
-                       prec = 0x7fffffff;      /* MAXINT */
+                       if (prec == -1) {
+                               prec = 0x7fffffff; /* MAXINT */
+                       }
+                       p = va_arg(argp, char *);
 
-                   p = va_arg(argp, char *);
+                       if (p == NULL) {
+                               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++;
+                               }
+
+                               p = p2;
 
-                       for (; *p != '\0' && n < prec; p++)
-                           n++;
+                               while (n < length) {
+                                       (*putc)(' ', arg);
+                                       n++;
+                                       nprinted++;
+                               }
+                       }
 
-                       p = p2;
+                       n = 0;
 
-                       while (n < length) {
-                           (*putc)(' ', arg);
-                           n++;
-                           nprinted++;
+                       while ((n < prec) && (!(length > 0 && n >= length))) {
+                               if (*p == '\0') {
+                                       break;
+                               }
+                               (*putc)(*p++, arg);
+                               nprinted++;
+                               n++;
                        }
-                   }
-
-                   n = 0;
-
-                   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;
+                       OS_FALLTHROUGH;
                case 'O':
-                   base = 8;
-                   goto print_unsigned;
+                       base = 8;
+                       goto print_unsigned;
 
                case 'D': {
-                   unsigned char *up;
-                   char *q, *p;
-                   
+                       unsigned char *up;
+                       char *q, *p;
+
                        up = (unsigned char *)va_arg(argp, unsigned char *);
                        p = (char *)va_arg(argp, char *);
-                       if (length == -1)
+                       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;
+               case 'i':
+                       truncate = _doprnt_truncates;
+                       base = 10;
+                       goto print_signed;
 
                case 'u':
-                   truncate = _doprnt_truncates;
+                       truncate = _doprnt_truncates;
+                       OS_FALLTHROUGH;
                case 'U':
-                   base = 10;
-                   goto print_unsigned;
+                       base = 10;
+                       goto print_unsigned;
 
                case 'p':
-                   altfmt = TRUE;
-                   if (sizeof(int)<sizeof(void *)) {
-                       long_long = 1;
-                   }
+                       altfmt = TRUE;
+                       if (sizeof(int) < sizeof(void *)) {
+                               long_long = 1;
+                       }
+                       OS_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;
+                       OS_FALLTHROUGH;
                case 'R':
-                   base = radix;
-                   goto print_signed;
+                       base = radix;
+                       goto print_signed;
 
                case 'n':
-                   truncate = _doprnt_truncates;
+                       truncate = _doprnt_truncates;
+                       OS_FALLTHROUGH;
                case 'N':
-                   base = radix;
-                   goto print_unsigned;
-
-               print_signed:
-                   if (long_long) {
-                       n = va_arg(argp, long long);
-                   } else {
-                       n = va_arg(argp, int);
-                   }
-                   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);
-                   }
-                   goto print_num;
-
-               print_num:
-               {
-                   char        buf[MAXBUF];    /* build number here */
-                   register char *     p = &buf[MAXBUF-1];
-                   static char digits[] = "0123456789abcdef0123456789ABCDEF";
-                   const char *prefix = NULL;
-
-                   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 -= (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++;
+                       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[] = "<ptr>";
+                                       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;
@@ -642,48 +733,87 @@ __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((char)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, 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 */
+#if     MP_PRINTF
+boolean_t       new_printf_cpu_number = FALSE;
+#endif  /* MP_PRINTF */
 
+SIMPLE_LOCK_DECLARE(bsd_log_spinlock, 0);
 
-decl_simple_lock_data(,printf_lock)
-decl_simple_lock_data(,bsd_log_spinlock)
-extern void bsd_log_init(void);
-void bsd_log_lock(void);
+bool bsd_log_lock(bool);
+void bsd_log_lock_safe(void);
 void bsd_log_unlock(void);
 
-void
-printf_init(void)
+/*
+ * Locks OS log lock and returns true if successful, false otherwise. Locking
+ * always succeeds in a safe context but may block. Locking in an unsafe context
+ * never blocks but fails if someone else is already holding the lock.
+ *
+ * A caller is responsible to decide whether the context is safe or not.
+ *
+ * As a rule of thumb following cases are *not* considered safe:
+ *   - Interrupts are disabled
+ *   - Pre-emption is disabled
+ *   - When in a debugger
+ *   - During a panic
+ */
+bool
+bsd_log_lock(bool safe)
 {
-       /*
-        * Lock is only really needed after the first thread is created.
-        */
-       simple_lock_init(&printf_lock, 0);
-       simple_lock_init(&bsd_log_spinlock, 0);
-       bsd_log_init();
+       if (!safe) {
+               assert(!oslog_is_safe());
+               return simple_lock_try(&bsd_log_spinlock, LCK_GRP_NULL);
+       }
+       simple_lock(&bsd_log_spinlock, LCK_GRP_NULL);
+       return true;
 }
 
+/*
+ * Locks OS log lock assuming the context is safe. See bsd_log_lock() comment
+ * for details.
+ */
 void
-bsd_log_lock(void)
+bsd_log_lock_safe(void)
 {
-       simple_lock(&bsd_log_spinlock);
+       (void) bsd_log_lock(true);
 }
 
 void
@@ -695,23 +825,23 @@ bsd_log_unlock(void)
 /* derived from boot_gets */
 void
 safe_gets(
-       char    *str,
-       int     maxlen)
+       char    *str,
+       int     maxlen)
 {
-       register char *lp;
-       register int c;
+       char *lp;
+       char c;
        char *strmax = str + maxlen - 1; /* allow space for trailing 0 */
 
        lp = str;
        for (;;) {
-               c = cngetc();
+               c = (char)cngetc();
                switch (c) {
                case '\n':
                case '\r':
                        printf("\n");
                        *lp++ = 0;
                        return;
-                       
+
                case '\b':
                case '#':
                case '\177':
@@ -732,8 +862,7 @@ safe_gets(
                                if (lp < strmax) {
                                        *lp++ = c;
                                        printf("%c", c);
-                               }
-                               else {
+                               } else {
                                        printf("%c", '\007'); /* beep */
                                }
                        }
@@ -747,12 +876,14 @@ void
 conslog_putc(
        char c)
 {
-       if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
+       if (!disableConsoleOutput) {
                cnputc(c);
+       }
 
-#ifdef MACH_BSD
-       if (debug_mode == 0)
+#ifdef  MACH_BSD
+       if (!kernel_debugger_entry_count) {
                log_putc(c);
+       }
 #endif
 }
 
@@ -760,49 +891,89 @@ void
 cons_putc_locked(
        char c)
 {
-       if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
+       if (!disableConsoleOutput) {
                cnputc(c);
+       }
 }
 
-int
-printf(const char *fmt, ...)
+static int
+vprintf_internal(const char *fmt, va_list ap_in, void *caller)
 {
-       va_list listp;
-
+       cpu_data_t * cpu_data_p;
        if (fmt) {
-               disable_preemption();
-               va_start(listp, fmt);
-               _doprnt(fmt, &listp, conslog_putc, 16);
-               va_end(listp);
-               enable_preemption();
+               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));
+}
+
 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)
-                       PE_kputc(c);
+       if (!console_is_serial() && !disable_serial_output) {
+               PE_kputc(c);
+       }
 }
 
 void
@@ -811,40 +982,73 @@ 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_unbuffered, 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 defined(__arm__) || defined(__arm64__)
+       paniclog_flush();
+#endif
+
        return 0;
 }
 
 int
 kdb_log(const char *fmt, ...)
 {
-       va_list listp;
+       va_list listp;
 
        va_start(listp, fmt);
        _doprnt(fmt, &listp, consdebug_log, 16);
        va_end(listp);
+
+#if defined(__arm__) || defined(__arm64__)
+       paniclog_flush();
+#endif
+
        return 0;
 }
 
 int
 kdb_printf_unbuffered(const char *fmt, ...)
 {
-       va_list listp;
+       va_list listp;
 
        va_start(listp, fmt);
        _doprnt(fmt, &listp, consdebug_putc_unbuffered, 16);
        va_end(listp);
+
+#if defined(__arm__) || defined(__arm64__)
+       paniclog_flush();
+#endif
+
        return 0;
 }
 
-
+#if CONFIG_VSPRINTF
 static void
 copybyte(int c, void *arg)
 {
@@ -854,9 +1058,9 @@ copybyte(int c, void *arg)
         * 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 */
+       char** p = arg; /* cast outside pointer */
+       **p = (char)c;  /* store character */
+       (*p)++;         /* increment inside pointer */
 }
 
 /*
@@ -866,13 +1070,14 @@ copybyte(int c, void *arg)
 int
 sprintf(char *buf, const char *fmt, ...)
 {
-        va_list listp;
+       va_list listp;
        char *copybyte_str;
 
-        va_start(listp, fmt);
-        copybyte_str = buf;
-        __doprnt(fmt, listp, copybyte, &copybyte_str, 16);
-        va_end(listp);
+       va_start(listp, fmt);
+       copybyte_str = buf;
+       __doprnt(fmt, listp, copybyte, &copybyte_str, 16, FALSE);
+       va_end(listp);
        *copybyte_str = '\0';
-        return (int)strlen(buf);
+       return (int)strlen(buf);
 }
+#endif /* CONFIG_VSPRINTF */