/*
- * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#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')
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);
fmt++;
long_long = 0;
+ numeric_type = INT;
length = 0;
prec = -1;
ladjust = FALSE;
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;
}
case 'c':
- c = va_arg(argp, int);
+ c = (char)va_arg(argp, int);
(*putc)(c, arg);
nprinted++;
break;
case 'o':
truncate = _doprnt_truncates;
+ OS_FALLTHROUGH;
case 'O':
base = 8;
goto print_unsigned;
}
case 'd':
+ case 'i':
truncate = _doprnt_truncates;
base = 10;
goto print_signed;
case 'u':
truncate = _doprnt_truncates;
+ OS_FALLTHROUGH;
case 'U':
base = 10;
goto print_unsigned;
if (sizeof(int) < sizeof(void *)) {
long_long = 1;
}
+ OS_FALLTHROUGH;
case 'x':
truncate = _doprnt_truncates;
base = 16;
case 'r':
truncate = _doprnt_truncates;
+ OS_FALLTHROUGH;
case 'R':
base = radix;
goto print_signed;
case 'n':
truncate = _doprnt_truncates;
+ OS_FALLTHROUGH;
case 'N':
base = radix;
goto print_unsigned;
} else {
n = va_arg(argp, int);
}
+ 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 = 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:
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') {
{
void (*real_putc)(char) = arg;
- real_putc(ch);
+ /*
+ * 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
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);
+SIMPLE_LOCK_DECLARE(bsd_log_spinlock, 0);
-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, LCK_GRP_NULL);
+ (void) bsd_log_lock(true);
}
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(
int maxlen)
{
char *lp;
- int c;
+ 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':
va_list listp;
va_start(listp, fmt);
- _doprnt_log(fmt, &listp, consdebug_putc, 16);
+ _doprnt_log(fmt, &listp, consdebug_putc_unbuffered, 16);
va_end(listp);
return 0;
_doprnt_log(fmt, &listp, consdebug_putc, 16);
va_end(listp);
-#if CONFIG_EMBEDDED
+#if defined(__arm__) || defined(__arm64__)
paniclog_flush();
#endif
_doprnt(fmt, &listp, consdebug_log, 16);
va_end(listp);
-#if CONFIG_EMBEDDED
+#if defined(__arm__) || defined(__arm64__)
paniclog_flush();
#endif
_doprnt(fmt, &listp, consdebug_putc_unbuffered, 16);
va_end(listp);
-#if CONFIG_EMBEDDED
+#if defined(__arm__) || defined(__arm64__)
paniclog_flush();
#endif
return 0;
}
-#if !CONFIG_EMBEDDED
-
+#if CONFIG_VSPRINTF
static void
copybyte(int c, void *arg)
{
* the inside pointer.
*/
char** p = arg; /* cast outside pointer */
- **p = c; /* store character */
+ **p = (char)c; /* store character */
(*p)++; /* increment inside pointer */
}
*copybyte_str = '\0';
return (int)strlen(buf);
}
-#endif /* !CONFIG_EMBEDDED */
+#endif /* CONFIG_VSPRINTF */