extern vm_offset_t min_valid_stack_address(void);
extern vm_offset_t max_valid_stack_address(void);
+// From osfmk/kern/printf.c
+extern boolean_t doprnt_hide_pointers;
+
// From osfmk/kmod.c
-extern void kmod_dump_log(vm_offset_t *addr, unsigned int cnt);
+extern void kmod_dump_log(vm_offset_t *addr, unsigned int cnt, boolean_t doUnslide);
extern addr64_t kvtophys(vm_offset_t va);
+#if __arm__
+extern int copyinframe(vm_address_t fp, char *frame);
+#elif defined(__arm64__)
+extern int copyinframe(vm_address_t fp, char *frame, boolean_t is64bit);
+#endif
__END_DECLS
OSReportWithBacktrace(const char *str, ...)
{
char buf[128];
- void *bt[9];
+ void *bt[9] = {};
const unsigned cnt = sizeof(bt) / sizeof(bt[0]);
va_list listp;
lck_mtx_lock(sOSReportLock);
{
+ boolean_t old_doprnt_hide_pointers = doprnt_hide_pointers;
+ doprnt_hide_pointers = FALSE;
printf("%s\nBacktrace 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", buf,
(unsigned long) VM_KERNEL_UNSLIDE(bt[2]), (unsigned long) VM_KERNEL_UNSLIDE(bt[3]),
(unsigned long) VM_KERNEL_UNSLIDE(bt[4]), (unsigned long) VM_KERNEL_UNSLIDE(bt[5]),
(unsigned long) VM_KERNEL_UNSLIDE(bt[6]), (unsigned long) VM_KERNEL_UNSLIDE(bt[7]),
(unsigned long) VM_KERNEL_UNSLIDE(bt[8]));
- kmod_dump_log((vm_offset_t *) &bt[2], cnt - 2);
+ kmod_dump_log((vm_offset_t *) &bt[2], cnt - 2, TRUE);
+ doprnt_hide_pointers = old_doprnt_hide_pointers;
}
lck_mtx_unlock(sOSReportLock);
}
unsigned OSBacktrace(void **bt, unsigned maxAddrs)
{
unsigned frame;
+ if (!current_thread()) return 0;
#if __x86_64__
#define SANE_x86_64_FRAME_SIZE (kernel_stack_size >> 1)
for ( ; frame_index < maxAddrs; frame_index++)
bt[frame_index] = (void *) 0;
+#elif __arm__ || __arm64__
+ uint32_t i = 0;
+ uintptr_t frameb[2];
+ uintptr_t fp = 0;
+
+ // get the current frame pointer for this thread
+#if defined(__arm__)
+#define OSBacktraceFrameAlignOK(x) (((x) & 0x3) == 0)
+ __asm__ volatile("mov %0,r7" : "=r" (fp));
+#elif defined(__arm64__)
+#define OSBacktraceFrameAlignOK(x) (((x) & 0xf) == 0)
+ __asm__ volatile("mov %0, fp" : "=r" (fp));
+#else
+#error Unknown architecture.
+#endif
+
+ // now crawl up the stack recording the link value of each frame
+ do {
+ // check bounds
+ if ((fp == 0) || (!OSBacktraceFrameAlignOK(fp)) || (fp > VM_MAX_KERNEL_ADDRESS) || (fp < VM_MIN_KERNEL_AND_KEXT_ADDRESS)) {
+ break;
+ }
+ // safely read frame
+#ifdef __arm64__
+ if (copyinframe(fp, (char*)frameb, TRUE) != 0) {
+#else
+ if (copyinframe(fp, (char*)frameb) != 0) {
+#endif
+ break;
+ }
+
+ // No need to use copyin as this is always a kernel address, see check above
+ bt[i] = (void*)frameb[1]; // link register
+ fp = frameb[0];
+ } while (++i < maxAddrs);
+ frame= i;
#else
#error arch
#endif