rem: addr_t diff = nextEbp - ebp;
add: if (get_next_frame(ebp, &nextEbp, &eip) != B_OK) { kprintf("%08lx -- read fault\n", ebp); break; }
context: stack_trace(int argc, char **argv){	uint32 previousLocations[NUM_PREVIOUS_LOCATIONS];	struct iframe_stack *frameStack;	struct thread *thread;	uint32 ebp;	int32 i, num = 0, last = 0;	if (argc < 2) {		thread = thread_get_current_thread();		if (thread != NULL)			frameStack = &thread->arch_info.iframes;		else			frameStack = &gBootFrameStack;	} else {		kprintf("not supported\n");		return 0;	}	for (i = 0; i < frameStack->index; i++) {		kprintf("iframe %p (end = %p)\n",			frameStack->frames[i], frameStack->frames[i] + 1);	}	// We don't have a thread pointer early in the boot process	if (thread != NULL) {		kprintf("stack trace for thread 0x%lx \"%s\"\n", thread->id, thread->name);		kprintf("    kernel stack: %p to %p\n", 			(void *)thread->kernel_stack_base, (void *)(thread->kernel_stack_base + KERNEL_STACK_SIZE));		if (thread->user_stack_base != 0) {			kprintf("      user stack: %p to %p\n", (void *)thread->user_stack_base,				(void *)(thread->user_stack_base + thread->user_stack_size));		}	}	kprintf("frame            caller     <image>:function + offset\n");	read_ebp(ebp);	for (;;) {		bool isIFrame = false;		// see if the ebp matches the iframe		for (i = 0; i < frameStack->index; i++) {			if (ebp == ((uint32)frameStack->frames[i] - 8)) {				// it's an iframe				isIFrame = true;			}		}		if (isIFrame) {			struct iframe *frame = (struct iframe *)(ebp + 8);			kprintf("iframe at %p\n", frame);			kprintf(" eax 0x%-9x    ebx 0x%-9x     ecx 0x%-9x  edx 0x%x\n",				frame->eax, frame->ebx, frame->ecx, frame->edx);			kprintf(" esi 0x%-9x    edi 0x%-9x     ebp 0x%-9x  esp 0x%x\n",				frame->esi, frame->edi, frame->ebp, frame->esp);			kprintf(" eip 0x%-9x eflags 0x%-9x", frame->eip, frame->flags);			if ((frame->error_code & 0x4) != 0) {				// from user space				kprintf("user esp 0x%x", frame->user_esp);			}			kprintf("\n");			kprintf(" vector: 0x%x, error code: 0x%x\n", frame->vector, frame->error_code); 			ebp = frame->ebp;		} else {			addr_t eip = ((struct stack_frame *)ebp)->return_address;			const char *symbol, *image;			addr_t nextEbp = (addr_t)((struct stack_frame *)ebp)->previous;			addr_t baseAddress;			bool exactMatch;			addr_t diff = nextEbp - ebp;			if (eip == 0 || ebp == 0)				break;			if (elf_lookup_symbol_address(eip, &baseAddress, &symbol,					&image, &exactMatch) == B_OK) {				if (symbol != NULL) {					kprintf("%08lx (+%4ld) %08lx   <%s>:%s + 0x%04lx%s\n", ebp, diff, eip,						image, symbol, eip - baseAddress, exactMatch ? "" : " (nearest)");				} else {					kprintf("%08lx (+%4ld) %08lx   <%s@%p>:unknown + 0x%04lx\n", ebp, diff, eip,						image, (void *)baseAddress, eip - baseAddress);				}			} else				kprintf("%08lx   %08lx\n", ebp, eip);			ebp = nextEbp;		}		if (already_visited(previousLocations, &last, &num, ebp)) {			kprintf("circular stack frame: %p!\n", (void *)ebp);			break;		}		if (ebp == 0)			break;	}	return 0;}