- unsigned frame;
-
-#if __ppc__
- vm_offset_t stackptr, stackptr_prev;
- const vm_offset_t * const mem = (vm_offset_t *) 0;
- unsigned i = 0;
-
- __asm__ volatile("mflr %0" : "=r" (stackptr));
- bt[i++] = (void *) stackptr;
-
- __asm__ volatile("mr %0,r1" : "=r" (stackptr));
- for ( ; i < maxAddrs; i++) {
- // Validate we have a reasonable stackptr
- if ( !(minstackaddr <= stackptr && stackptr < maxstackaddr)
- || (stackptr & 3))
- break;
-
- stackptr_prev = stackptr;
- stackptr = mem[stackptr_prev >> 2];
- if ((stackptr_prev ^ stackptr) > 8 * 1024) // Sanity check
- break;
-
- vm_offset_t addr = mem[(stackptr >> 2) + 2];
- if ((addr & 3) || (addr < 0x8000)) // More sanity checks
- break;
- bt[i] = (void *) addr;
- }
- frame = i;
-
- for ( ; i < maxAddrs; i++)
- bt[i] = (void *) 0;
-#elif 0 && __i386__ // Note that this should be ported for i386
- // This function is not safe, we should get this code ported appropriately
- if (maxAddrs > 16) {
- for (frame = 16; frame < maxAddrs; frame++)
- bt[frame] = __builtin_return_address(frame);
- maxAddrs = 16;
- }
-
- switch(maxAddrs) {
- case 15+1: bt[15] = __builtin_return_address(15);
- case 14+1: bt[14] = __builtin_return_address(14);
- case 13+1: bt[13] = __builtin_return_address(13);
- case 12+1: bt[12] = __builtin_return_address(12);
- case 11+1: bt[11] = __builtin_return_address(11);
- case 10+1: bt[10] = __builtin_return_address(10);
- case 9+1: bt[ 9] = __builtin_return_address( 9);
- case 8+1: bt[ 8] = __builtin_return_address( 8);
- case 7+1: bt[ 7] = __builtin_return_address( 7);
- case 6+1: bt[ 6] = __builtin_return_address( 6);
- case 5+1: bt[ 5] = __builtin_return_address( 5);
- case 4+1: bt[ 4] = __builtin_return_address( 4);
- case 3+1: bt[ 3] = __builtin_return_address( 3);
- case 2+1: bt[ 2] = __builtin_return_address( 2);
- case 1+1: bt[ 1] = __builtin_return_address( 1);
- case 0+1: bt[ 0] = __builtin_return_address( 0);
- case 0: default: break;
- }
-
- frame = maxAddrs;
+ unsigned frame;
+ if (!current_thread()) {
+ return 0;
+ }
+
+#if __x86_64__
+#define SANE_x86_64_FRAME_SIZE (kernel_stack_size >> 1)
+ vm_offset_t stackptr, stackptr_prev, raddr;
+ unsigned frame_index = 0;
+/* Obtain current frame pointer */
+
+ __asm__ volatile ("movq %%rbp, %0" : "=m" (stackptr));
+
+ if (!x86_64_validate_stackptr(stackptr)) {
+ goto pad;
+ }
+
+ raddr = *((vm_offset_t *) (stackptr + x86_64_RETURN_OFFSET));
+
+ if (!x86_64_validate_raddr(raddr)) {
+ goto pad;
+ }
+
+ bt[frame_index++] = (void *) raddr;
+
+ for (; frame_index < maxAddrs; frame_index++) {
+ stackptr_prev = stackptr;
+ stackptr = *((vm_offset_t *) stackptr_prev);
+
+ if (!x86_64_validate_stackptr(stackptr)) {
+ break;
+ }
+ /* Stack grows downwards */
+ if (stackptr < stackptr_prev) {
+ break;
+ }
+
+ if ((stackptr - stackptr_prev) > SANE_x86_64_FRAME_SIZE) {
+ break;
+ }
+
+ raddr = *((vm_offset_t *) (stackptr + x86_64_RETURN_OFFSET));
+
+ if (!x86_64_validate_raddr(raddr)) {
+ break;
+ }
+
+ bt[frame_index] = (void *) raddr;
+ }
+pad:
+ frame = frame_index;
+
+ for (; frame_index < maxAddrs; frame_index++) {
+ bt[frame_index] = (void *) NULL;
+ }
+#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));