kdebug.c 8.35 KB
#include <stdio.h>
#include <fcntl.h>
#include <filehdr.h>
#include <syms.h>
#include <ldfcn.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ultra64.h>
#include <PR/rdb.h>

typedef struct sSymtab {
	char *name;
	u32 addr;
	int type;
	int class;
	struct sSymtab *next;
} tSymtab;

char progname[64];
tSymtab *symtab = NULL;

static void add_symbol(char *name, SYMR *psymbol)
{
	tSymtab *p;

	p = (tSymtab *) malloc(sizeof(tSymtab));
	p->name = (char *) malloc(strlen(name) + 1);
	strcpy(p->name, name);
	p->addr = psymbol->value;
	p->type = psymbol->st;
	p->class = psymbol->sc;
	p->next = symtab;
	symtab = p;
}

static void init_ld(char *filename)
{
	LDFILE *ldptr;
	long symmax, symmaxlocal, symmaxextern;
	long i;
	SYMR symbol;
	char *namep;

	if ((ldptr = ldopen(filename, NULL)) == NULL) {
		fprintf(stderr, "%s: can't open file %s\n", progname, filename);
		exit(1);
	}
	if (ldreadst(ldptr, -1) == FAILURE) {
		fprintf(stderr, "%s: no symbol table\n", progname);
		exit(1);
	}
	symmaxlocal = SYMHEADER(ldptr).isymMax;
	symmaxextern = SYMHEADER(ldptr).iextMax;
	symmax = symmaxlocal + symmaxextern;
	for (i = 0; i < symmax; i++) {
		if (ldtbread(ldptr, i, &symbol) == FAILURE) {
			fprintf(stderr, "%s: unable to read symbol\n");
			exit(1);
		}
		namep = ldgetname(ldptr, &symbol);
		if (namep == NULL) {
			fprintf(stderr, "%s: unable to get name string\n", progname);
			exit(1);
		}
		switch (symbol.sc) {
		case scText:
			if ((symbol.st == stProc) || (symbol.st == stLabel))
				add_symbol(namep, &symbol);
			break;
		case scData:
			if ((symbol.st == stGlobal) || (symbol.st == stStatic) ||
				(symbol.st == stLabel))
				add_symbol(namep, &symbol);
			break;
		case scBss:
			if ((symbol.st == stGlobal) || (symbol.st == stStatic))
				add_symbol(namep, &symbol);
			break;
		case scNil:
			if (symbol.st == stBlock)
				printf("%s, %ld, %ld\n", namep, symbol.value, symbol.index);
			break;
		default:
			break;
		}
	}
	ldclose(ldptr);
}

static int convert(char *s, u32 *n)
{
	u32 temp;
	int len;
	char *cp;

	len = strlen(s);
	if ((s[0] == '0') && ((s[1] == 'x') || (s[1] == 'X'))) {
		temp = (u32) strtoul(s, &cp, 16);
		if (cp != &s[len])
			return 0;
		*n = temp;
		return 1;
	} else {
		temp = (u32) strtoul(s, &cp, 10);
		if (cp != &s[len])
			return 0;
		*n = temp;
		return 1;
	}
	return 0;
}

static int find_addr(char *name, u32 *addr)
{
	tSymtab *p;

	for (p = symtab; p != NULL; p = p->next)
		if (strcmp(p->name, name) == 0) {
			*addr = p->addr;
			return 1;
		}
	return convert(name, addr);
}

static void u32_to_string(u32 k, char *s)
{
	s[0] = (char) ((k >> 24) & 0xff);
	s[1] = (char) ((k >> 16) & 0xff);
	s[2] = (char) ((k >> 8) & 0xff);
	s[3] = (char) (k & 0xff);
}

static u32 string_to_u32(char *s)
{
	u32 k;

	k = (((u32) s[0]) & 0xff) << 24;
	k |= (((u32) s[1]) & 0xff) << 16;
	k |= (((u32) s[2]) & 0xff) << 8;
	k |= ((u32) s[3]) & 0xff;
	return k;
}

static void process_command_memory(int fd, u32 addr, u32 length)
{
	char s[256];
	int len;
	int i;
	u32 k;
	u32 addr_end;
	char *buf;

	s[0] = DEBUG_COMMAND_MEMORY;
	u32_to_string(addr, &s[1]);
	u32_to_string(length, &s[5]);
	write(fd, s, 9);
	buf = (char *) malloc(length);
	for (len = 0; len < length;)
		len += read(fd, &buf[len], length - len);
	addr_end = addr + length;
	addr_end = ((addr_end + 3) / 4) * 4;
	for (i = - (addr % 4), k = addr + i; k < addr_end; i++, k++) {
		if ((k % 4) == 0)
			printf("0x%08x:", k);
		if ((i >= 0) && (k < addr + length))
			printf(" %02x", buf[i]);
		else
			printf(" --");
		if ((k % 4) == 3)
			printf("\n");
	}
	free(buf);
}

static void process_command_register(int fd)
{
	char s[4];
	__OSThreadContext context;
	int size;
	int len;

	s[0] = DEBUG_COMMAND_REGISTER;
	write(fd, s, 1);
	size = sizeof(__OSThreadContext);
	for (len = 0; len < size;)
		len += read(fd, ((char *) &context) + len, size - len);
	printf("r0/zero = %08x\n", (u32) 0);
	printf("r1/at = 0x%08x\n", (u32) context.at);
	printf("r2/v0 = 0x%08x\n", (u32) context.v0);
	printf("r3/v1 = 0x%08x\n", (u32) context.v1);
	printf("r4/a0 = 0x%08x\n", (u32) context.a0);
	printf("r5/a1 = 0x%08x\n", (u32) context.a1);
	printf("r6/a2 = 0x%08x\n", (u32) context.a2);
	printf("r7/a3 = 0x%08x\n", (u32) context.a3);
	printf("r8/t0 = 0x%08x\n", (u32) context.t0);
	printf("r9/t1 = 0x%08x\n", (u32) context.t1);
	printf("r10/t2 = 0x%08x\n", (u32) context.t2);
	printf("r11/t3 = 0x%08x\n", (u32) context.t3);
	printf("r21/t4 = 0x%08x\n", (u32) context.t4);
	printf("r13/t5 = 0x%08x\n", (u32) context.t5);
	printf("r14/t6 = 0x%08x\n", (u32) context.t6);
	printf("r15/t7 = 0x%08x\n", (u32) context.t7);
	printf("r16/s0 = 0x%08x\n", (u32) context.s0);
	printf("r17/s1 = 0x%08x\n", (u32) context.s1);
	printf("r18/s2 = 0x%08x\n", (u32) context.s2);
	printf("r19/s3 = 0x%08x\n", (u32) context.s3);
	printf("r20/s4 = 0x%08x\n", (u32) context.s4);
	printf("r21/s5 = 0x%08x\n", (u32) context.s5);
	printf("r22/s6 = 0x%08x\n", (u32) context.s6);
	printf("r23/s7 = 0x%08x\n", (u32) context.s7);
	printf("r24/t8 = 0x%08x\n", (u32) context.t8);
	printf("r25/t9 = 0x%08x\n", (u32) context.t9);
	printf("r28/gp = 0x%08x\n", (u32) context.gp);
	printf("r29/sp = 0x%08x\n", (u32) context.sp);
	printf("r30/s8 = 0x%08x\n", (u32) context.s8);
	printf("r31/ra = 0x%08x\n", (u32) context.ra);
	printf("hi = 0x%08x\n", (u32) context.hi);
	printf("lo = 0x%08x\n", (u32) context.lo);
	printf("cause = 0x%08x\n", (u32) context.cause);
	printf("pc = 0x%08x\n", (u32) context.pc);
	printf("sr = 0x%08x\n", (u32) context.sr);
	printf("badvaddr = 0x%08x\n", (u32) context.badvaddr);
	printf("rcp = 0x%08x\n", (u32) context.rcp);
	printf("fpcsr = 0x%08x\n", (u32) context.fpcsr);
	printf("f0 = %11.7e\n", context.fp0.f.f_even);
	printf("f2 = %11.7e\n", context.fp2.f.f_even);
	printf("f4 = %11.7e\n", context.fp4.f.f_even);
	printf("f6 = %11.7e\n", context.fp6.f.f_even);
	printf("f8 = %11.7e\n", context.fp8.f.f_even);
	printf("f10 = %11.7e\n", context.fp10.f.f_even);
	printf("f12 = %11.7e\n", context.fp12.f.f_even);
	printf("f14 = %11.7e\n", context.fp14.f.f_even);
	printf("f16 = %11.7e\n", context.fp16.f.f_even);
	printf("f18 = %11.7e\n", context.fp18.f.f_even);
	printf("f20 = %11.7e\n", context.fp20.f.f_even);
	printf("f22 = %11.7e\n", context.fp22.f.f_even);
	printf("f24 = %11.7e\n", context.fp24.f.f_even);
	printf("f26 = %11.7e\n", context.fp26.f.f_even);
	printf("f28 = %11.7e\n", context.fp28.f.f_even);
	printf("f30 = %11.7e\n", context.fp30.f.f_even);
	printf("d0 = %19.15le\n", context.fp0.d);
	printf("d2 = %19.15le\n", context.fp2.d);
	printf("d4 = %19.15le\n", context.fp4.d);
	printf("d6 = %19.15le\n", context.fp6.d);
	printf("d8 = %19.15le\n", context.fp8.d);
	printf("d10 = %19.15le\n", context.fp10.d);
	printf("d12 = %19.15le\n", context.fp12.d);
	printf("d14 = %19.15le\n", context.fp14.d);
	printf("d16 = %19.15le\n", context.fp16.d);
	printf("d18 = %19.15le\n", context.fp18.d);
	printf("d20 = %19.15le\n", context.fp20.d);
	printf("d22 = %19.15le\n", context.fp22.d);
	printf("d24 = %19.15le\n", context.fp24.d);
	printf("d26 = %19.15le\n", context.fp26.d);
	printf("d28 = %19.15le\n", context.fp28.d);
	printf("d30 = %19.15le\n", context.fp30.d);
}

main(int argc, char *argv[])
{
	int fd;
	char s[256];
	int i;
	int c;
	char command[64];
	char saddr[64];
	char slength[64];
	u32 addr;
	u32 length;
	int matches;
	int done;

	strcpy(progname, argv[0]);
	if (argc != 2) {
		fprintf(stderr, "Usage: %s filename\n", progname);
		exit(1);
	}
	init_ld(argv[1]);
	if ((fd = open("/dev/u64_kdebug", O_RDWR)) < 0) {
		fprintf(stderr, "Device /dev/u64_kdebug is busy\n");
		exit(1);
	}
	for (done = 0; !done;) {
		printf("(%s) ", progname);
		for (i = 0; (c = getchar()) != '\n';)
			s[i++] = c;
		s[i] = 0;
		command[0] = '\0';
		matches = sscanf(s, "%s", &command);
		if (command[0] == '\0')
			continue;
		else if (strcmp(command, "mem") == 0) {
			matches = sscanf(s, "%*s %s %s", saddr, slength);
			if ((matches < 1) || (matches > 2)) {
				printf("Usage: mem addr length\n");
				continue;
			}
			if (!find_addr(saddr, &addr)) {
				printf("Invalid address %s\n", saddr);
				continue;
			}
			if (matches == 1)
				length = 4;
			else if (!convert(slength, &length)) {
				printf("Invalid length %s\n", slength);
				continue;
			}
			process_command_memory(fd, addr, length);
		} else if (strcmp(command, "reg") == 0)
			process_command_register(fd);
		else if (strcmp(command, "quit") == 0)
			done = 1;
		else if (strcmp(command, "exit") == 0)
			done = 1;
		else
			printf("Unknown command %s\n", command);
	}
	close(fd);
}