forsyth20121205-174063a80cc13 years agoHistory
839 lines · 15.2 KB · C
RawDownload
#include <lib9.h>#include <bio.h>#include "mach.h" static int debug = 0; typedef struct	Instr	Instr;struct	Instr{	Map	*map;	ulong	w;	ulong	addr;	uchar	op;			/* super opcode */ 	uchar	rd;	uchar	rn;	uchar	rs; 	long	imm;			/* imm */ 	char*	curr;			/* fill point in buffer */	char*	end;			/* end of buffer */	char*	err;			/* error message */}; typedef struct Opcode Opcode;struct Opcode{	char*	o;	void	(*fmt)(Opcode*, Instr*);	uvlong	(*foll)(Map*, Rgetter, Instr*, uvlong);	char*	a;}; static	void	format(char*, Instr*, char*);static	char	FRAMENAME[] = ".frame"; /* * Thumb-specific debugger interface */ static	char	*thumbexcep(Map*, Rgetter);static	int	thumbfoll(Map*, uvlong, Rgetter, uvlong*);static	int	thumbinst(Map*, uvlong, char, char*, int);static	int	thumbdas(Map*, uvlong, char*, int);static	int	thumbinstlen(Map*, uvlong); /* *	Debugger interface */Machdata thumbmach ={	{0x0, 0xE8},		/* break point */	2,				/* break point size */ 	leswab,			/* short to local byte order */	leswal,			/* long to local byte order */	leswav,			/* long to local byte order */	risctrace,		/* C traceback */	riscframe,		/* Frame finder */	thumbexcep,			/* print exception */	0,			/* breakpoint fixup */	0,			/* single precision float printer */	0,			/* double precision float printer */	thumbfoll,		/* following addresses */	thumbinst,		/* print instruction */	thumbdas,			/* dissembler */	thumbinstlen,		/* instruction size */}; static void thumbrrh(Opcode *, Instr *);static void thumbbcc(Opcode *, Instr *);static void thumbb(Opcode *, Instr *);static void thumbbl(Opcode *, Instr *); static char*thumbexcep(Map *map, Rgetter rget){	long c; 	c = (*rget)(map, "TYPE");	switch (c&0x1f) {	case 0x11:		return "Fiq interrupt";	case 0x12:		return "Mirq interrupt";	case 0x13:		return "SVC/SWI Exception";	case 0x17:		return "Prefetch Abort/Data Abort";	case 0x18:		return "Data Abort";	case 0x1b:		return "Undefined instruction/Breakpoint";	case 0x1f:		return "Sys trap";	default:		return "Undefined trap";	}} staticchar*	cond[16] ={	"EQ",	"NE",	"CS",	"CC",	"MI",	"PL",	"VS",	"VC",	"HI",	"LS",	"GE",	"LT",	"GT",	"LE",	"\0",	"NV"}; #define B(h, l)		bits(ins, h, l) static intbits(int i, int h, int l){	if(h < l)		print("h < l in bits");	return (i&(((1<<(h-l+1))-1)<<l))>>l;} intthumbclass(long w){	int o;	int ins = w; 	if(ins&0xffff0000)		return 3+2+2+4+16+4+1+8+6+2+2+2+4+1+1+1+2;	o = B(15, 13);	switch(o){	case 0:		o = B(12, 11);		switch(o){			case 0:			case 1:			case 2:				return B(12, 11);			case 3:				if(B(10, 10) == 0)					return 3+B(9, 9);				else					return 3+2+B(9, 9);		}	case 1:		return 3+2+2+B(12, 11);	case 2:		o = B(12, 10);		if(o == 0)			return 3+2+2+4+B(9, 6);		if(o == 1){			o = B(9, 8);			if(o == 3)				return 3+2+2+4+16+B(9, 8);			return 3+2+2+4+16+B(9, 8);		}		if(o == 2 || o == 3)			return 3+2+2+4+16+4;		return 3+2+2+4+16+4+1+B(11, 9);	case 3:		return 3+2+2+4+16+4+1+8+B(12, 11);	case 4:		if(B(12, 12) == 0)			return 3+2+2+4+16+4+1+8+4+B(11, 11);		return 3+2+2+4+16+4+1+8+6+B(11, 11);	case 5:		if(B(12, 12) == 0)			return 3+2+2+4+16+4+1+8+6+2+B(11, 11);		if(B(11, 8) == 0)			return 3+2+2+4+16+4+1+8+6+2+2+B(7, 7);		return 3+2+2+4+16+4+1+8+6+2+2+2+B(11, 11);	case 6:		if(B(12, 12) == 0)			return 3+2+2+4+16+4+1+8+6+2+2+2+2+B(11, 11);		if(B(11, 8) == 0xf)			return 3+2+2+4+16+4+1+8+6+2+2+2+4;		return 3+2+2+4+16+4+1+8+6+2+2+2+4+1;	case 7:		o = B(12, 11);		switch(o){			case 0:				return 3+2+2+4+16+4+1+8+6+2+2+2+4+1+1;			case 1:				return 3+2+2+4+16+4+1+8+6+2+2+2+4+1+1+1+2;			case 2:				return 3+2+2+4+16+4+1+8+6+2+2+2+4+1+1+1;			case 3:				return 3+2+2+4+16+4+1+8+6+2+2+2+4+1+1+1+1;		}	}	return 0;} static intdecode(Map *map, uvlong pc, Instr *i){	ushort w; 	if(get2(map, pc, &w) < 0) {		werrstr("can't read instruction: %r");		return -1;	}	i->w = w;	i->addr = pc;	i->op = thumbclass(w);	i->map = map;	return 1;} static voidbprint(Instr *i, char *fmt, ...){	va_list arg; 	va_start(arg, fmt);	i->curr = vseprint(i->curr, i->end, fmt, arg);	va_end(arg);} static intplocal(Instr *i){	char *reg;	Symbol s;	char *fn;	int class;	int offset; 	if(!findsym(i->addr, CTEXT, &s)) {		if(debug)fprint(2,"fn not found @%lux: %r\n", i->addr);		return 0;	}	fn = s.name;	if (!findlocal(&s, FRAMENAME, &s)) {		if(debug)fprint(2,"%s.%s not found @%s: %r\n", fn, FRAMENAME, s.name);			return 0;	}	if(s.value > i->imm) {		class = CAUTO;		offset = s.value-i->imm;		reg = "(SP)";	} else {		class = CPARAM;		offset = i->imm-s.value-4;		reg = "(FP)";	}	if(!getauto(&s, offset, class, &s)) {		if(debug)fprint(2,"%s %s not found @%ux: %r\n", fn,			class == CAUTO ? " auto" : "param", offset);		return 0;	}	bprint(i, "%s%c%d%s", s.name, class == CPARAM ? '+' : '-', s.value, reg);	return 1;} /* * Print value v as name[+offset] */static intgsymoff(char *buf, int n, long v, int space){	Symbol s;	int r;	long delta; 	r = delta = 0;		/* to shut compiler up */	if (v) {		r = findsym(v, space, &s);		if (r)			delta = v-s.value;		if (delta < 0)			delta = -delta;	}	if (v == 0 || r == 0 || delta >= 4096)		return snprint(buf, n, "#%lux", v);	if (strcmp(s.name, ".string") == 0)		return snprint(buf, n, "#%lux", v);	if (!delta)		return snprint(buf, n, "%s", s.name);	if (s.type != 't' && s.type != 'T')		return snprint(buf, n, "%s+%llux", s.name, v-s.value);	else		return snprint(buf, n, "#%lux", v);} static intthumbcondpass(Map *map, Rgetter rget, uchar cond){	ulong psr;	uchar n;	uchar z;	uchar c;	uchar v; 	psr = rget(map, "PSR");	n = (psr >> 31) & 1;	z = (psr >> 30) & 1;	c = (psr >> 29) & 1;	v = (psr >> 28) & 1; 	switch(cond) {		case 0:		return z;		case 1:		return !z;		case 2:		return c;		case 3:		return !c;		case 4:		return n;		case 5:		return !n;		case 6:		return v;		case 7:		return !v;		case 8:		return c && !z;		case 9:		return !c || z;		case 10:	return n == v;		case 11:	return n != v;		case 12:	return !z && (n == v);		case 13:	return z && (n != v);		case 14:	return 1;		case 15:	return 0;	}	return 0;} static uvlongthumbfbranch(Map *map, Rgetter rget, Instr *i, uvlong pc){	char buf[8]; 	if(i->op == 30){	// BX		thumbrrh(nil, i);		sprint(buf, "R%ud", i->rn);		return rget(map, buf)&~1;		// clear T bit	}	if(i->op == 57){	// Bcc		thumbbcc(nil, i);		if(thumbcondpass(map, rget, (i->w >> 8) & 0xf))			return i->imm;		return pc+2;	}	if(i->op == 58){	// B		thumbb(nil, i);		return i->imm;	}	if(i->op == 60){	// BL		thumbbl(nil, i);		return i->imm;	}	print("bad thumbfbranch call");	return 0;} static uvlongthumbfmov(Map *map, Rgetter rget, Instr *i, uvlong pc){	char buf[8];	ulong rd; 	thumbrrh(nil, i);	rd = i->rd;	if(rd != 15)		return pc+2;	sprint(buf, "R%ud", i->rn);	return rget(map, buf);} static uvlongthumbfadd(Map *map, Rgetter rget, Instr *i, uvlong pc){	char buf[8];	ulong rd, v; 	thumbrrh(nil, i);	rd = i->rd;	if(rd != 15)		return pc+2;	sprint(buf, "R%ud", i->rn);	v = rget(map, buf);	sprint(buf, "R15");	return rget(map, buf) + v;} static voidthumbshift(Opcode *o, Instr *i){	int ins = i->w; 	i->rd = B(2, 0);	i->rn = B(5, 3);	i->imm = B(10, 6);	format(o->o, i, o->a);} static voidthumbrrr(Opcode *o, Instr *i){	int ins = i->w; 	i->rd = B(2, 0);	i->rn = B(5, 3);	i->rs = B(8, 6);	format(o->o, i, o->a);} static voidthumbirr(Opcode *o, Instr *i){	int ins = i->w; 	i->rd = B(2, 0);	i->rn = B(5, 3);	i->imm = B(8, 6);	format(o->o, i, o->a);} static voidthumbir(Opcode *o, Instr *i){	int ins = i->w; 	i->rd = B(10, 8);	i->imm = B(7, 0);	format(o->o, i, o->a);} static voidthumbrr(Opcode *o, Instr *i){	int ins = i->w; 	i->rd = B(2, 0);	i->rn = B(5, 3);	format(o->o, i, o->a);} static voidthumbrrh(Opcode *o, Instr *i){	int ins = i->w; 	i->rd = B(2, 0);	i->rn = B(5, 3);	if(B(6, 6))		i->rn += 8;	if(B(7, 7))		i->rd += 8;	if(o != nil){		if(i->w == 0x46b7 || i->w == 0x46f7 || i->w == 0x4730 || i->w == 0x4770)	// mov r6, pc or mov lr, pc or bx r6 or bx lr			format("RET", i, "");		else			format(o->o, i, o->a);	}} static voidthumbpcrel(Opcode *o, Instr *i){	int ins = i->w; 	i->rn = 15;	i->rd = B(10, 8);	i->imm = 4*(B(7, 0)+1);	if(i->addr & 3)		i->imm -= 2;	format(o->o, i, o->a);} static voidthumbmovirr(Opcode *o, Instr *i){	int ins = i->w; 	i->rd = B(2, 0);	i->rn = B(5, 3);	i->imm = B(10, 6);	if(strcmp(o->o, "MOVW") == 0)		i->imm *= 4;	else if(strncmp(o->o, "MOVH", 4) == 0)		i->imm *= 2;	format(o->o, i, o->a);} static voidthumbmovsp(Opcode *o, Instr *i){	int ins = i->w; 	i->rn = 13;	i->rd = B(10, 8);	i->imm = 4*B(7, 0);	format(o->o, i, o->a);} static voidthumbaddsppc(Opcode *o, Instr *i){	int ins = i->w; 	i->rd = B(10, 8);	i->imm = 4*B(7, 0);	if(i->op == 48)		i->imm += 4;	format(o->o, i, o->a);}

Lines 1–500 of 839.