kdebug.c 9.71 KB
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#ifdef __sgi
#include <filehdr.h>
#include <syms.h>
#include <ldfcn.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <ultra64.h>
#include <PR/rdb.h>
#ifdef BBPLAYER
#include "ultrahost.h"
#include <netinet/in.h>
#endif

static u64 ntohll(u64 a) {
    return (((a >>  0) & 0xff) << 56) |
           (((a >>  8) & 0xff) << 48) |
           (((a >> 16) & 0xff) << 40) |
           (((a >> 24) & 0xff) << 32) |
           (((a >> 32) & 0xff) << 24) |
           (((a >> 40) & 0xff) << 16) |
           (((a >> 48) & 0xff) <<  8) |
           (((a >> 56) & 0xff) <<  0);
}

static double ntohd(double a) {
    u64 x = ntohll(*(u64*)&a);
    return *(double*)&x;
}

static float ntohf(float a) {
    u32 x = ntohl(*(u32*)&a);
    return *(float*)&x;
}

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

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

#ifdef __sgi
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);
}
#endif

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

int
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);
	}
#ifndef BBPLAYER
	init_ld(argv[1]);
	if ((fd = open("/dev/u64_kdebug", O_RDWR)) < 0) {
		fprintf(stderr, "Device /dev/u64_kdebug is busy\n");
		exit(1);
	}
#else
	if ((fd = uhOpenGame("/tmp/u64_kdebug")) < 0) {
		fprintf(stderr, "Device /tmp/u64_kdebug is busy\n");
		exit(1);
	}
#endif
	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);
	return 0;
}