📄 qdb.c
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <mach.h>/* * PowerPC-specific debugger interface * forsyth@terzarima.net */static char *powerexcep(Map*, Rgetter);static int powerfoll(Map*, uvlong, Rgetter, uvlong*);static int powerinst(Map*, uvlong, char, char*, int);static int powerinstlen(Map*, uvlong);static int powerdas(Map*, uvlong, char*, int);/* * Machine description */Machdata powermach ={ {0x02, 0x8f, 0xff, 0xff}, /* break point */ /* BUG */ 4, /* break point size */ beswab, /* short to local byte order */ beswal, /* long to local byte order */ beswav, /* vlong to local byte order */ risctrace, /* print C traceback */ riscframe, /* frame finder */ powerexcep, /* print exception */ 0, /* breakpoint fixup */ beieeesftos, /* single precision float printer */ beieeedftos, /* double precisioin float printer */ powerfoll, /* following addresses */ powerinst, /* print instruction */ powerdas, /* dissembler */ powerinstlen, /* instruction size */};static char *excname[] ={ "reserved 0", "system reset", "machine check", "data access", "instruction access", "external interrupt", "alignment", "program exception", "floating-point unavailable", "decrementer", "i/o controller interface error", "reserved B", "system call", "trace trap", "floating point assist", "reserved", "ITLB miss", "DTLB load miss", "DTLB store miss", "instruction address breakpoint" "SMI interrupt" "reserved 15", "reserved 16", "reserved 17", "reserved 18", "reserved 19", "reserved 1A", /* the following are made up on a program exception */ "floating point exception", /* FPEXC */ "illegal instruction", "privileged instruction", "trap", "illegal operation",};static char*powerexcep(Map *map, Rgetter rget){ long c; static char buf[32]; c = (*rget)(map, "CAUSE") >> 8; if(c < nelem(excname)) return excname[c]; sprint(buf, "unknown trap #%lx", c); return buf;}/* * disassemble PowerPC opcodes */#define REGSP 1 /* should come from q.out.h, but there's a clash */#define REGSB 2static char FRAMENAME[] = ".frame";static Map *mymap;/* * ibm conventions for these: bit 0 is top bit * from table 10-1 */typedef struct { uchar aa; /* bit 30 */ uchar crba; /* bits 11-15 */ uchar crbb; /* bits 16-20 */ long bd; /* bits 16-29 */ uchar crfd; /* bits 6-8 */ uchar crfs; /* bits 11-13 */ uchar bi; /* bits 11-15 */ uchar bo; /* bits 6-10 */ uchar crbd; /* bits 6-10 */ union { short d; /* bits 16-31 */ short simm; ushort uimm; }; uchar fm; /* bits 7-14 */ uchar fra; /* bits 11-15 */ uchar frb; /* bits 16-20 */ uchar frc; /* bits 21-25 */ uchar frs; /* bits 6-10 */ uchar frd; /* bits 6-10 */ uchar crm; /* bits 12-19 */ long li; /* bits 6-29 || b'00' */ uchar lk; /* bit 31 */ uchar mb; /* bits 21-25 */ uchar me; /* bits 26-30 */ uchar nb; /* bits 16-20 */ uchar op; /* bits 0-5 */ uchar oe; /* bit 21 */ uchar ra; /* bits 11-15 */ uchar rb; /* bits 16-20 */ uchar rc; /* bit 31 */ union { uchar rs; /* bits 6-10 */ uchar rd; }; uchar sh; /* bits 16-20 */ ushort spr; /* bits 11-20 */ uchar to; /* bits 6-10 */ uchar imm; /* bits 16-19 */ ushort xo; /* bits 21-30, 22-30, 26-30, or 30 (beware) */ long immediate; long w0; long w1; uvlong addr; /* pc of instruction */ short target; char *curr; /* current fill level in output buffer */ char *end; /* end of buffer */ int size; /* number of longs in instr */ char *err; /* errmsg */} Instr;#define IBF(v,a,b) (((ulong)(v)>>(32-(b)-1)) & ~(~0L<<(((b)-(a)+1))))#define IB(v,b) IBF((v),(b),(b))#pragma varargck argpos bprint 2static 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 intdecode(uvlong pc, Instr *i){ ulong w; if (get4(mymap, pc, &w) < 0) { werrstr("can't read instruction: %r"); return -1; } i->aa = IB(w, 30); i->crba = IBF(w, 11, 15); i->crbb = IBF(w, 16, 20); i->bd = IBF(w, 16, 29)<<2; if(i->bd & 0x8000) i->bd |= ~0L<<16; i->crfd = IBF(w, 6, 8); i->crfs = IBF(w, 11, 13); i->bi = IBF(w, 11, 15); i->bo = IBF(w, 6, 10); i->crbd = IBF(w, 6, 10); i->uimm = IBF(w, 16, 31); /* also d, simm */ i->fm = IBF(w, 7, 14); i->fra = IBF(w, 11, 15); i->frb = IBF(w, 16, 20); i->frc = IBF(w, 21, 25); i->frs = IBF(w, 6, 10); i->frd = IBF(w, 6, 10); i->crm = IBF(w, 12, 19); i->li = IBF(w, 6, 29)<<2; if(IB(w, 6)) i->li |= ~0<<25; i->lk = IB(w, 31); i->mb = IBF(w, 21, 25); i->me = IBF(w, 26, 30); i->nb = IBF(w, 16, 20); i->op = IBF(w, 0, 5); i->oe = IB(w, 21); i->ra = IBF(w, 11, 15); i->rb = IBF(w, 16, 20); i->rc = IB(w, 31); i->rs = IBF(w, 6, 10); /* also rd */ i->sh = IBF(w, 16, 20); i->spr = IBF(w, 11, 20); i->to = IBF(w, 6, 10); i->imm = IBF(w, 16, 19); i->xo = IBF(w, 21, 30); /* bits 21-30, 22-30, 26-30, or 30 (beware) */ i->immediate = i->simm; if(i->op == 15) i->immediate <<= 16; i->w0 = w; i->target = -1; i->addr = pc; i->size = 1; return 1;}static intmkinstr(uvlong pc, Instr *i){ Instr x; if(decode(pc, i) < 0) return -1; /* * combine ADDIS/ORI (CAU/ORIL) into MOVW */ if (i->op == 15 && i->ra==0) { if(decode(pc+4, &x) < 0) return -1; if (x.op == 24 && x.rs == x.ra && x.ra == i->rd) { i->immediate |= (x.immediate & 0xFFFF); i->w1 = x.w0; i->target = x.rd; i->size++; return 1; } } return 1;}static intplocal(Instr *i){ long offset; Symbol s; if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) return -1; offset = s.value - i->immediate; if (offset > 0) { if(getauto(&s, offset, CAUTO, &s)) { bprint(i, "%s+%lld(SP)", s.name, s.value); return 1; } } else { if (getauto(&s, -offset-4, CPARAM, &s)) { bprint(i, "%s+%ld(FP)", s.name, -offset); return 1; } } return -1;}static intpglobal(Instr *i, uvlong off, int anyoff, char *reg){ Symbol s, s2; uvlong off1; if(findsym(off, CANY, &s) && s.value-off < 4096 && (s.class == CDATA || s.class == CTEXT)) { if(off==s.value && s.name[0]=='$'){ off1 = 0; geta(mymap, s.value, &off1); if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){ bprint(i, "$%s%s", s2.name, reg); return 1; } } bprint(i, "%s", s.name); if (s.value != off) bprint(i, "+%llux", off-s.value); bprint(i, reg); return 1; } if(!anyoff) return 0; bprint(i, "%llux%s", off, reg); return 1;}static voidaddress(Instr *i){ if (i->ra == REGSP && plocal(i) >= 0) return; if (i->ra == REGSB && mach->sb && pglobal(i, mach->sb+i->immediate, 0, "(SB)") >= 0) return; if(i->simm < 0) bprint(i, "-%x(R%d)", -i->simm, i->ra); else bprint(i, "%lux(R%d)", i->immediate, i->ra);}static char *tcrbits[] = {"LT", "GT", "EQ", "VS"};static char *fcrbits[] = {"GE", "LE", "NE", "VC"};typedef struct Opcode Opcode;struct Opcode { uchar op; ushort xo; ushort xomask; char *mnemonic; void (*f)(Opcode *, Instr *); char *ken; int flags;};static void format(char *, Instr *, char *);static voidbranch(Opcode *o, Instr *i){ char buf[8]; int bo, bi; bo = i->bo & ~1; /* ignore prediction bit */ if(bo==4 || bo==12 || bo==20) { /* simple forms */ if(bo != 20) { bi = i->bi&3; sprint(buf, "B%s%%L", bo==12? tcrbits[bi]: fcrbits[bi]); format(buf, i, 0); bprint(i, "\t"); if(i->bi > 4) bprint(i, "CR(%d),", i->bi/4); } else format("BR%L\t", i, 0); if(i->op == 16) format(0, i, "%J"); else if(i->op == 19 && i->xo == 528) format(0, i, "(CTR)"); else if(i->op == 19 && i->xo == 16) format(0, i, "(LR)"); } else format(o->mnemonic, i, o->ken);}static voidaddi(Opcode *o, Instr *i){ if (i->op==14 && i->ra == 0) format("MOVW", i, "%i,R%d"); else if (i->ra == REGSB) { bprint(i, "MOVW\t$"); address(i); bprint(i, ",R%d", i->rd); } else if(i->op==14 && i->simm < 0) { bprint(i, "SUB\t$%d,R%d", -i->simm, i->ra); if(i->rd != i->ra) bprint(i, ",R%d", i->rd); } else if(i->ra == i->rd) { format(o->mnemonic, i, "%i"); bprint(i, ",R%d", i->rd); } else format(o->mnemonic, i, o->ken);}static voidaddis(Opcode *o, Instr *i){ long v; v = i->immediate; if (i->op==15 && i->ra == 0) bprint(i, "MOVW\t$%lux,R%d", v, i->rd); else if (i->op==15 && i->ra == REGSB) { bprint(i, "MOVW\t$"); address(i); bprint(i, ",R%d", i->rd); } else if(i->op==15 && v < 0) { bprint(i, "SUB\t$%ld,R%d", -v, i->ra); if(i->rd != i->ra) bprint(i, ",R%d", i->rd); } else { format(o->mnemonic, i, 0); bprint(i, "\t$%ld,R%d", v, i->ra); if(i->rd != i->ra) bprint(i, ",R%d", i->rd); }}static voidandi(Opcode *o, Instr *i){ if (i->ra == i->rs) format(o->mnemonic, i, "%I,R%d"); else format(o->mnemonic, i, o->ken);}static voidgencc(Opcode *o, Instr *i){ format(o->mnemonic, i, o->ken);}static voidgen(Opcode *o, Instr *i){ format(o->mnemonic, i, o->ken); if (i->rc) bprint(i, " [illegal Rc]");}static voidldx(Opcode *o, Instr *i){ if(i->ra == 0) format(o->mnemonic, i, "(R%b),R%d"); else format(o->mnemonic, i, "(R%b+R%a),R%d"); if(i->rc) bprint(i, " [illegal Rc]");}static voidstx(Opcode *o, Instr *i){ if(i->ra == 0) format(o->mnemonic, i, "R%d,(R%b)"); else format(o->mnemonic, i, "R%d,(R%b+R%a)"); if(i->rc && i->xo != 150) bprint(i, " [illegal Rc]");}static voidfldx(Opcode *o, Instr *i){ if(i->ra == 0) format(o->mnemonic, i, "(R%b),F%d"); else format(o->mnemonic, i, "(R%b+R%a),F%d"); if(i->rc) bprint(i, " [illegal Rc]");}static voidfstx(Opcode *o, Instr *i){ if(i->ra == 0) format(o->mnemonic, i, "F%d,(R%b)"); else format(o->mnemonic, i, "F%d,(R%b+R%a)"); if(i->rc) bprint(i, " [illegal Rc]");}static voiddcb(Opcode *o, Instr *i){ if(i->ra == 0) format(o->mnemonic, i, "(R%b)"); else format(o->mnemonic, i, "(R%b+R%a)"); if(i->rd) bprint(i, " [illegal Rd]"); if(i->rc) bprint(i, " [illegal Rc]");}static voidlw(Opcode *o, Instr *i, char r){ bprint(i, "%s\t", o->mnemonic); address(i); bprint(i, ",%c%d", r, i->rd);}static voidload(Opcode *o, Instr *i){ lw(o, i, 'R');}static voidfload(Opcode *o, Instr *i){ lw(o, i, 'F');}static voidsw(Opcode *o, Instr *i, char r){ int offset; char *m; Symbol s; m = o->mnemonic; if (i->rs == REGSP) { if (findsym(i->addr, CTEXT, &s) && findlocal(&s, FRAMENAME, &s)) { offset = s.value-i->immediate; if (offset > 0 && getauto(&s, offset, CAUTO, &s)) { bprint(i, "%s\t%c%d,%s-%d(SP)", m, r, i->rd, s.name, offset); return; } } } if (i->rs == REGSB && mach->sb) { bprint(i, "%s\t%c%d,", m, r, i->rd); address(i); return; } if (r == 'F') format(m, i, "F%d,%l"); else format(m, i, o->ken);}static voidstore(Opcode *o, Instr *i){ sw(o, i, 'R');}static voidfstore(Opcode *o, Instr *i){ sw(o, i, 'F');}static voidshifti(Opcode *o, Instr *i){ if (i->ra == i->rs) format(o->mnemonic, i, "$%k,R%a"); else format(o->mnemonic, i, o->ken);}static voidshift(Opcode *o, Instr *i){ if (i->ra == i->rs) format(o->mnemonic, i, "R%b,R%a"); else format(o->mnemonic, i, o->ken);}static voidadd(Opcode *o, Instr *i){ if (i->rd == i->ra) format(o->mnemonic, i, "R%b,R%d"); else if (i->rd == i->rb) format(o->mnemonic, i, "R%a,R%d"); else format(o->mnemonic, i, o->ken);}static voidsub(Opcode *o, Instr *i){ format(o->mnemonic, i, 0); bprint(i, "\t"); if(i->op == 31) { bprint(i, "\tR%d,R%d", i->ra, i->rb); /* subtract Ra from Rb */ if(i->rd != i->rb) bprint(i, ",R%d", i->rd); } else bprint(i, "\tR%d,$%d,R%d", i->ra, i->simm, i->rd);}static voidqdiv(Opcode *o, Instr *i){ format(o->mnemonic, i, 0); if(i->op == 31) bprint(i, "\tR%d,R%d", i->rb, i->ra); else bprint(i, "\t$%d,R%d", i->simm, i->ra); if(i->ra != i->rd) bprint(i, ",R%d", i->rd);}static voidand(Opcode *o, Instr *i){ if (i->op == 31) { /* Rb,Rs,Ra */ if (i->ra == i->rs) format(o->mnemonic, i, "R%b,R%a"); else if (i->ra == i->rb) format(o->mnemonic, i, "R%s,R%a"); else format(o->mnemonic, i, o->ken); } else { /* imm,Rs,Ra */ if (i->ra == i->rs) format(o->mnemonic, i, "%I,R%a"); else format(o->mnemonic, i, o->ken); }}static voidor(Opcode *o, Instr *i){ if (i->op == 31) { /* Rb,Rs,Ra */ if (i->rs == 0 && i->ra == 0 && i->rb == 0) format("NOP", i, 0); else if (i->rs == i->rb) format("MOVW", i, "R%b,R%a"); else and(o, i); } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -