/*
 *  * Copyright (C) 2000-2002 ASANO Masahiro
 *   */

#include <string.h>
#include "asm/page.h"
#include "crash.h"
#include "stacksize.h"

PRIVATE addr_t trace();

struct commandtable command_trace =
        {"trace", trace, "address", "print kernel backtrace"};

PRIVATE char stack[STACKSIZE];

PRIVATE addr_t
trace()
{
	addr_t eip, esp, stacktop;
	const struct symtable *sym;
	int pid;

	if (argcnt < 2 || argcnt > 2) {
		THROW(usage);
	}

	eip = esp = stacktop = 0;
	pid = getinfo_fromtask(getaddr(args[1]), &eip, &esp, &stacktop);
	mprintf("PID = %d\n", pid);
	memread(stacktop, sizeof(stack), stack, "stack area");

	mprintf(" " FPTR "  " FPTR "  ", esp, eip);
	if ((sym = searchsym_byaddr(eip)) == NULL) {
		mprintf("?\n");
	} else {
		mprintf("%s+%lx ()\n", sym->name, eip - sym->addr);
	}

#define INTHESTACK(x) ((x) >= stacktop && (x) + sizeof(addr_t) <= stacktop + sizeof(stack))
	for (; INTHESTACK(esp); esp += sizeof(addr_t)) {
		addr_t addr = *(addr_t *)&stack[esp - stacktop];
		if ((sym = searchsym_byaddr(addr)) == NULL)
			continue;
		if (sym->type != 'T' && sym->type != 't')
			continue;
		mprintf("[" FPTR "] " FPTR "  ", esp, addr);
		mprintf("%s+%lx ()\n", sym->name, addr - sym->addr);
	}
	return 0;
}
