📄 5db.c
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <mach.h>static int debug = 0;#define BITS(a, b) ((1<<(b+1))-(1<<a))#define LSR(v, s) ((ulong)(v) >> (s))#define ASR(v, s) ((long)(v) >> (s))#define ROR(v, s) (LSR((v), (s)) | (((v) & ((1 << (s))-1)) << (32 - (s))))typedef struct Instr Instr;struct Instr{ Map *map; ulong w; uvlong addr; uchar op; /* super opcode */ uchar cond; /* bits 28-31 */ uchar store; /* bit 20 */ uchar rd; /* bits 12-15 */ uchar rn; /* bits 16-19 */ uchar rs; /* bits 0-11 (shifter operand) */ long imm; /* rotated 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";/* * Arm-specific debugger interface */static char *armexcep(Map*, Rgetter);static int armfoll(Map*, uvlong, Rgetter, uvlong*);static int arminst(Map*, uvlong, char, char*, int);static int armdas(Map*, uvlong, char*, int);static int arminstlen(Map*, uvlong);/* * Debugger interface */Machdata armmach ={ {0, 0, 0, 0xD}, /* break point */ 4, /* 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 */ armexcep, /* print exception */ 0, /* breakpoint fixup */ 0, /* single precision float printer */ 0, /* double precision float printer */ armfoll, /* following addresses */ arminst, /* print instruction */ armdas, /* dissembler */ arminstlen, /* instruction size */};static char*armexcep(Map *map, Rgetter rget){ uvlong c; c = (*rget)(map, "TYPE"); switch ((int)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"};staticchar* shtype[4] ={ "<<", ">>", "->", "@>"};staticchar *hb[4] ={ "???", "HU", "B", "H"};staticchar* addsub[2] ={ "-", "+",};intarmclass(long w){ int op; op = (w >> 25) & 0x7; switch(op) { case 0: /* data processing r,r,r */ op = ((w >> 4) & 0xf); if(op == 0x9) { op = 48+16; /* mul */ if(w & (1<<24)) { op += 2; if(w & (1<<22)) op++; /* swap */ break; } if(w & (1<<23)) { /* mullu */ op = (48+24+4+4+2+2+4); if(w & (1<<22)) /* mull */ op += 2; } if(w & (1<<21)) op++; /* mla */ break; } if((op & 0x9) == 0x9) /* ld/st byte/half s/u */ { op = (48+16+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2); break; } op = (w >> 21) & 0xf; if(w & (1<<4)) op += 32; else if((w & (31<<7)) || (w & (1<<5))) op += 16; break; case 1: /* data processing i,r,r */ op = (48) + ((w >> 21) & 0xf); break; case 2: /* load/store byte/word i(r) */ op = (48+24) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2); break; case 3: /* load/store byte/word (r)(r) */ op = (48+24+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2); break; case 4: /* block data transfer (r)(r) */ op = (48+24+4+4) + ((w >> 20) & 0x1); break; case 5: /* branch / branch link */ op = (48+24+4+4+2) + ((w >> 24) & 0x1); break; case 7: /* coprocessor crap */ op = (48+24+4+4+2+2) + ((w >> 3) & 0x2) + ((w >> 20) & 0x1); break; default: op = (48+24+4+4+2+2+4+4); break; } return op;}static intdecode(Map *map, uvlong pc, Instr *i){ ulong w; if(get4(map, pc, &w) < 0) { werrstr("can't read instruction: %r"); return -1; } i->w = w; i->addr = pc; i->cond = (w >> 28) & 0xF; i->op = armclass(w); i->map = map; return 1;}#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 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 @%llux: %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%lld%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 voidarmdps(Opcode *o, Instr *i){ i->store = (i->w >> 20) & 1; i->rn = (i->w >> 16) & 0xf; i->rd = (i->w >> 12) & 0xf; i->rs = (i->w >> 0) & 0xf; if(i->rn == 15 && i->rs == 0) { if(i->op == 8) { format("MOVW", i,"CPSR, R%d"); return; } else if(i->op == 10) { format("MOVW", i,"SPSR, R%d"); return; } } else if(i->rn == 9 && i->rd == 15) { if(i->op == 9) { format("MOVW", i, "R%s, CPSR"); return; } else if(i->op == 11) { format("MOVW", i, "R%s, SPSR"); return; } } format(o->o, i, o->a);}static voidarmdpi(Opcode *o, Instr *i){ ulong v; int c; v = (i->w >> 0) & 0xff; c = (i->w >> 8) & 0xf; while(c) { v = (v<<30) | (v>>2); c--; } i->imm = v; i->store = (i->w >> 20) & 1; i->rn = (i->w >> 16) & 0xf; i->rd = (i->w >> 12) & 0xf; i->rs = i->w&0x0f; /* RET is encoded as ADD #0,R14,R15 */ if((i->w & 0x0fffffff) == 0x028ef000){ format("RET%C", i, ""); return; } if((i->w & 0x0ff0ffff) == 0x0280f000){ format("B%C", i, "0(R%n)"); return; } format(o->o, i, o->a);}static voidarmsdti(Opcode *o, Instr *i){ ulong v; v = i->w & 0xfff; if(!(i->w & (1<<23))) v = -v; i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1); i->imm = v; i->rn = (i->w >> 16) & 0xf; i->rd = (i->w >> 12) & 0xf; /* RET is encoded as LW.P x,R13,R15 */ if ((i->w & 0x0ffff000) == 0x049df000) { format("RET%C%p", i, "%I"); return; } format(o->o, i, o->a);}/* arm V4 ld/st halfword, signed byte */static voidarmhwby(Opcode *o, Instr *i){ i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1); i->imm = (i->w & 0xf) | ((i->w >> 8) & 0xf); if (!(i->w & (1 << 23))) i->imm = - i->imm; i->rn = (i->w >> 16) & 0xf; i->rd = (i->w >> 12) & 0xf; i->rs = (i->w >> 0) & 0xf; format(o->o, i, o->a);}static voidarmsdts(Opcode *o, Instr *i){ i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1); i->rs = (i->w >> 0) & 0xf; i->rn = (i->w >> 16) & 0xf; i->rd = (i->w >> 12) & 0xf; format(o->o, i, o->a);}static voidarmbdt(Opcode *o, Instr *i){ i->store = (i->w >> 21) & 0x3; /* S & W bits */ i->rn = (i->w >> 16) & 0xf; i->imm = i->w & 0xffff; if(i->w == 0xe8fd8000) format("RFE", i, ""); else format(o->o, i, o->a);}static voidarmund(Opcode *o, Instr *i){ format(o->o, i, o->a);}static voidarmcdt(Opcode *o, Instr *i){ format(o->o, i, o->a);}static voidarmunk(Opcode *o, Instr *i){ format(o->o, i, o->a);}static voidarmb(Opcode *o, Instr *i){ ulong v; v = i->w & 0xffffff; if(v & 0x800000) v |= ~0xffffff; i->imm = (v<<2) + i->addr + 8; format(o->o, i, o->a);}static voidarmco(Opcode *o, Instr *i) /* coprocessor instructions */{ int op, p, cp; char buf[1024]; i->rn = (i->w >> 16) & 0xf; i->rd = (i->w >> 12) & 0xf; i->rs = i->w&0xf; cp = (i->w >> 8) & 0xf; p = (i->w >> 5) & 0x7; if(i->w&(1<<4)) { op = (i->w >> 21) & 0x07; snprint(buf, sizeof(buf), "#%x, #%x, R%d, C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p); } else { op = (i->w >> 20) & 0x0f; snprint(buf, sizeof(buf), "#%x, #%x, C(%d), C(%d), C(%d), #%x\n", cp, op, i->rd, i->rn, i->rs, p); } format(o->o, i, buf);}static intarmcondpass(Map *map, Rgetter rget, uchar cond){ uvlong 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) { default: 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; }}static ulongarmshiftval(Map *map, Rgetter rget, Instr *i){ if(i->w & (1 << 25)) { /* immediate */ ulong imm = i->w & BITS(0, 7); ulong s = (i->w & BITS(8, 11)) >> 7; /* this contains the *2 */ return ROR(imm, s); } else { char buf[8]; ulong v; ulong s = (i->w & BITS(7,11)) >> 7; sprint(buf, "R%ld", i->w & 0xf); v = rget(map, buf); switch((i->w & BITS(4, 6)) >> 4) { default: case 0: /* LSLIMM */ return v << s; case 1: /* LSLREG */ sprint(buf, "R%lud", s >> 1); s = rget(map, buf) & 0xFF; if(s >= 32) return 0; return v << s; case 2: /* LSRIMM */ return LSR(v, s); case 3: /* LSRREG */ sprint(buf, "R%ld", s >> 1); s = rget(map, buf) & 0xFF; if(s >= 32) return 0; return LSR(v, s); case 4: /* ASRIMM */ if(s == 0) { if((v & (1U<<31)) == 0) return 0; return 0xFFFFFFFF; } return ASR(v, s); case 5: /* ASRREG */ sprint(buf, "R%ld", s >> 1); s = rget(map, buf) & 0xFF; if(s >= 32) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -