static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
{
	return p > (void *)tinfo &&
		p < (void *)tinfo + THREAD_SIZE - 3;
}

int (*evil___kernel_text_address)(unsigned long addr) = (void *)0xc0130d70;

void print_calltrace(void)
{
	struct thread_info *context;
	unsigned long addr, *stack, awwcrap = 0;
#ifdef CONFIG_FRAME_POINTER
	unsigned long ebp;
#endif

	stack = (unsigned long *)&stack;

	printk("(here)");

	for (;;) {
		context = (struct thread_info *)((unsigned long)stack & ~(THREAD_SIZE - 1));

#ifdef CONFIG_FRAME_POINTER
		asm("movl %%ebp, %0" : "=r" (ebp) : ); //"
		while (valid_stack_ptr(context, (void *)ebp)) {
			addr = *(unsigned long *)(ebp + 4);

			print_symbol( "<- %s", addr);

			ebp = *(unsigned long *)ebp;
			if (++awwcrap > 500) {
				printk("[infinite recursion!]");
				return;
			}
		}
#else
		while (valid_stack_ptr(context, stack)) {
			addr = *stack++;
			if (evil___kernel_text_address(addr)) {
				print_symbol(" <- %s", addr);
			}
			if (++awwcrap > 500) {
				printk("[infinite recursion!]");
				return;
			}
		}
#endif
		stack = (unsigned long *)context->previous_esp;
		
		if (stack == NULL)
			break;
	}
}
