* %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.
*
* + 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
-#undef printf(x, ...)
+/* 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(
unsigned long long int u, /* number to print */
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,
+ 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;
}
}
else if (c == '*') {
- length = va_arg(*argp, int);
+ length = va_arg(argp, int);
c = *++fmt;
if (length < 0) {
ladjust = !ladjust;
}
}
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)<sizeof(long))
+ long_long = 1;
if (c == 'l') {
long_long = 1;
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 */
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);
+ u = va_arg(argp, unsigned long long);
} else {
- u = va_arg(*argp, unsigned long);
+ u = va_arg(argp, unsigned int);
}
- p = va_arg(*argp, char *);
+ p = va_arg(argp, char *);
base = *p++;
nprinted += printnum(u, base, putc, arg);
/*
* Bit field
*/
- register int j;
+ int j;
if (any)
(*putc)(',', arg);
else {
}
case 'c':
- c = va_arg(*argp, int);
+ c = 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 */
- p = va_arg(*argp, char *);
+ p = va_arg(argp, char *);
if (p == NULL)
p = "";
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) {
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--) {
case 'p':
altfmt = TRUE;
+ if (sizeof(int)<sizeof(void *)) {
+ long_long = 1;
+ }
case 'x':
truncate = _doprnt_truncates;
base = 16;
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':
print_signed:
if (long_long) {
- n = va_arg(*argp, long long);
+ n = va_arg(argp, long long);
} else {
- n = va_arg(*argp, long);
+ n = va_arg(argp, int);
}
if (n >= 0) {
u = n;
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";
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";
u /= base;
} while (u != 0);
- length -= (&buf[MAXBUF-1] - p);
+ length -= (int)(&buf[MAXBUF-1] - p);
if (sign_char)
length--;
if (prefix)
- length -= strlen(prefix);
+ length -= (int)strlen(prefix);
if (padc == ' ' && !ladjust) {
/* blank padding goes before prefix */
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);
+ __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, 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)
{
/*
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;
conslog_putc(
char c)
{
- if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
+ if (!disableConsoleOutput)
cnputc(c);
#ifdef MACH_BSD
- log_putc(c);
+ 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)
+ 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_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;
+}
+
+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(int c, void *arg)
{
va_start(listp, fmt);
copybyte_str = buf;
- __doprnt(fmt, &listp, copybyte, ©byte_str, 16);
+ __doprnt(fmt, listp, copybyte, ©byte_str, 16, FALSE);
va_end(listp);
*copybyte_str = '\0';
- return strlen(buf);
+ return (int)strlen(buf);
}
+#endif /* !CONFIG_EMBEDDED */