📄 8db.c
字号:
ip->disp = s&0xffff; } if (igets(map, ip, (ushort*)&ip->seg) < 0) return 0; ip->jumptype = PTR; break; case AUXMM: /* Multi-byte op code; prefix determines table selection */ if (igetc(map, ip, &c) < 0) return 0; obase = (Optable*)op->proto; switch (ip->opre) { case 0x66: op = optab660F; break; case 0xF2: op = optabF20F; break; case 0xF3: op = optabF30F; break; default: op = nil; break; } if(op != nil && op[c].proto != nil) obase = op; norex = 1; /* no more rex prefixes */ /* otherwise the optab entry captures it */ goto newop; case AUX: /* Multi-byte op code - Auxiliary table */ obase = (Optable*)op->proto; if (igetc(map, ip, &c) < 0) return 0; goto newop; case OPRE: /* Instr Prefix or media op */ ip->opre = c; /* fall through */ case PRE: /* Instr Prefix */ ip->prefix = (char*)op->proto; if (igetc(map, ip, &c) < 0) return 0; if (ip->opre && c == 0x0F) ip->prefix = 0; goto newop; case SEG: /* Segment Prefix */ ip->segment = (char*)op->proto; if (igetc(map, ip, &c) < 0) return 0; goto newop; case OPOVER: /* Operand size override */ ip->opre = c; ip->osize = 'W'; if (igetc(map, ip, &c) < 0) return 0; if (c == 0x0F) ip->osize = 'L'; else if (ip->amd64 && (c&0xF0) == 0x40) ip->osize = 'Q'; goto newop; case ADDOVER: /* Address size override */ ip->asize = 0; if (igetc(map, ip, &c) < 0) return 0; goto newop; case JUMP: /* mark instruction as JUMP or RET */ case RET: ip->jumptype = op->operand[i]; break; default: werrstr("bad operand type %d", op->operand[i]); return 0; } } return op;}#pragma varargck argpos bprint 2static voidbprint(Instr *ip, char *fmt, ...){ va_list arg; va_start(arg, fmt); ip->curr = vseprint(ip->curr, ip->end, fmt, arg); va_end(arg);}/* * if we want to call 16 bit regs AX,BX,CX,... * and 32 bit regs EAX,EBX,ECX,... then * change the defs of ANAME and ONAME to: * #define ANAME(ip) ((ip->asize == 'E' ? "E" : "") * #define ONAME(ip) ((ip)->osize == 'L' ? "E" : "") */#define ANAME(ip) ""#define ONAME(ip) ""static char *reg[] = {[AX] "AX",[CX] "CX",[DX] "DX",[BX] "BX",[SP] "SP",[BP] "BP",[SI] "SI",[DI] "DI", /* amd64 */[R8] "R8",[R9] "R9",[R10] "R10",[R11] "R11",[R12] "R12",[R13] "R13",[R14] "R14",[R15] "R15",};static char *breg[] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" };static char *breg64[] = { "AL", "CL", "DL", "BL", "SPB", "BPB", "SIB", "DIB", "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B" };static char *sreg[] = { "ES", "CS", "SS", "DS", "FS", "GS" };static voidplocal(Instr *ip){ int ret; long offset; Symbol s; char *reg; offset = ip->disp; if (!findsym(ip->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) { bprint(ip, "%lux(SP)", offset); return; } if (s.value > ip->disp) { ret = getauto(&s, s.value-ip->disp-mach->szaddr, CAUTO, &s); reg = "(SP)"; } else { offset -= s.value; ret = getauto(&s, offset, CPARAM, &s); reg = "(FP)"; } if (ret) bprint(ip, "%s+", s.name); else offset = ip->disp; bprint(ip, "%lux%s", offset, reg);}static intisjmp(Instr *ip){ switch(ip->jumptype){ case Iwds: case Jbs: case JUMP: return 1; default: return 0; }}/* * This is too smart for its own good, but it really is nice * to have accurate translations when debugging, and it * helps us identify which code is different in binaries that * are changed on sources. */static intissymref(Instr *ip, Symbol *s, long w, long val){ Symbol next, tmp; long isstring, size; if (isjmp(ip)) return 1; if (s->class==CTEXT && w==0) return 1; if (s->class==CDATA) { /* use first bss symbol (or "end") rather than edata */ if (s->name[0]=='e' && strcmp(s->name, "edata") == 0){ if((s ->index >= 0 && globalsym(&tmp, s->index+1) && tmp.value==s->value) || (s->index > 0 && globalsym(&tmp, s->index-1) && tmp.value==s->value)) *s = tmp; } if (w == 0) return 1; for (next=*s; next.value==s->value; next=tmp) if (!globalsym(&tmp, next.index+1)) break; size = next.value - s->value; if (w >= size) return 0; if (w > size-w) w = size-w; /* huge distances are usually wrong except in .string */ isstring = (s->name[0]=='.' && strcmp(s->name, ".string") == 0); if (w > 8192 && !isstring) return 0; /* medium distances are tricky - look for constants */ /* near powers of two */ if ((val&(val-1)) == 0 || (val&(val+1)) == 0) return 0; return 1; } return 0;}static voidimmediate(Instr *ip, vlong val){ Symbol s; long w; if (findsym(val, CANY, &s)) { /* TO DO */ w = val - s.value; if (w < 0) w = -w; if (issymref(ip, &s, w, val)) { if (w) bprint(ip, "%s+%lux(SB)", s.name, w); else bprint(ip, "%s(SB)", s.name); return; }/* if (s.class==CDATA && globalsym(&s, s.index+1)) { w = s.value - val; if (w < 0) w = -w; if (w < 4096) { bprint(ip, "%s-%lux(SB)", s.name, w); return; } }*/ } if((ip->rex & REXW) == 0) bprint(ip, "%lux", (long)val); else bprint(ip, "%llux", val);}static voidpea(Instr *ip){ if (ip->mod == 3) { if (ip->osize == 'B') bprint(ip, (ip->rex & REXB? breg64: breg)[ip->base]); else if(ip->rex & REXB) bprint(ip, "%s%s", ANAME(ip), reg[ip->base+8]); else bprint(ip, "%s%s", ANAME(ip), reg[ip->base]); return; } if (ip->segment) bprint(ip, ip->segment); if (ip->asize == 'E' && ip->base == SP) plocal(ip); else { if (ip->base < 0) immediate(ip, ip->disp); else { bprint(ip, "%lux", ip->disp); if(ip->rip) bprint(ip, "(RIP)"); bprint(ip,"(%s%s)", ANAME(ip), reg[ip->rex&REXB? ip->base+8: ip->base]); } } if (ip->index >= 0) bprint(ip,"(%s%s*%d)", ANAME(ip), reg[ip->rex&REXX? ip->index+8: ip->index], 1<<ip->ss);}static voidprinstr(Instr *ip, char *fmt){ vlong v; if (ip->prefix) bprint(ip, "%s ", ip->prefix); for (; *fmt && ip->curr < ip->end; fmt++) { if (*fmt != '%'){ *ip->curr++ = *fmt; continue; } switch(*++fmt){ case '%': *ip->curr++ = '%'; break; case 'A': bprint(ip, "%s", ANAME(ip)); break; case 'C': bprint(ip, "CR%d", ip->reg); break; case 'D': if (ip->reg < 4 || ip->reg == 6 || ip->reg == 7) bprint(ip, "DR%d",ip->reg); else bprint(ip, "???"); break; case 'I': bprint(ip, "$"); immediate(ip, ip->imm2); break; case 'O': bprint(ip,"%s", ONAME(ip)); break; case 'i': bprint(ip, "$"); v = ip->imm; if(ip->rex & REXW) v = ip->imm64; immediate(ip, v); break; case 'R': bprint(ip, "%s%s", ONAME(ip), reg[ip->rex&REXR? ip->reg+8: ip->reg]); break; case 'S': if(ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW) bprint(ip, "Q"); else bprint(ip, "%c", ip->osize); break; case 's': if(ip->opre == 0 || ip->opre == 0x66) bprint(ip, "P"); else bprint(ip, "S"); if(ip->opre == 0xf2 || ip->opre == 0x66) bprint(ip, "D"); else bprint(ip, "S"); break; case 'T': if (ip->reg == 6 || ip->reg == 7) bprint(ip, "TR%d",ip->reg); else bprint(ip, "???"); break; case 'W': if (ip->osize == 'Q' || ip->osize == 'L' && ip->rex & REXW) bprint(ip, "CDQE"); else if (ip->osize == 'L') bprint(ip,"CWDE"); else bprint(ip, "CBW"); break; case 'd': bprint(ip,"%ux:%lux",ip->seg,ip->disp); break; case 'm': if (ip->mod == 3 && ip->osize != 'B') { if(fmt[1] != '*'){ if(ip->opre != 0) { bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base); break; } } else fmt++; bprint(ip, "M%d", ip->base); break; } pea(ip); break; case 'e': pea(ip); break; case 'f': bprint(ip, "F%d", ip->base); break; case 'g': if (ip->reg < 6) bprint(ip,"%s",sreg[ip->reg]); else bprint(ip,"???"); break; case 'p': /* * signed immediate in the ulong ip->imm. */ v = (long)ip->imm; immediate(ip, v+ip->addr+ip->n); break; case 'r': if (ip->osize == 'B') bprint(ip,"%s", (ip->rex? breg64: breg)[ip->rex&REXR? ip->reg+8: ip->reg]); else bprint(ip, reg[ip->rex&REXR? ip->reg+8: ip->reg]); break; case 'w': if (ip->osize == 'Q' || ip->rex & REXW) bprint(ip, "CQO"); else if (ip->osize == 'L') bprint(ip,"CDQ"); else bprint(ip, "CWD"); break; case 'M': if(ip->opre != 0) bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg); else bprint(ip, "M%d", ip->reg); break; case 'x': if (ip->mod == 3 && ip->osize != 'B') { bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base); break; } pea(ip); break; case 'X': bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg); break; default: bprint(ip, "%%%c", *fmt); break; } } *ip->curr = 0; /* there's always room for 1 byte */}static inti386inst(Map *map, uvlong pc, char modifier, char *buf, int n){ Instr instr; Optable *op; USED(modifier); op = mkinstr(map, &instr, pc); if (op == 0) { errstr(buf, n); return -1; } instr.curr = buf; instr.end = buf+n-1; prinstr(&instr, op->proto); return instr.n;}static inti386das(Map *map, uvlong pc, char *buf, int n){ Instr instr; int i; if (mkinstr(map, &instr, pc) == 0) { errstr(buf, n); return -1; } for(i = 0; i < instr.n && n > 2; i++) { _hexify(buf, instr.mem[i], 1); buf += 2; n -= 2; } *buf = 0; return instr.n;}static inti386instlen(Map *map, uvlong pc){ Instr i; if (mkinstr(map, &i, pc)) return i.n; return -1;}static inti386foll(Map *map, uvlong pc, Rgetter rget, uvlong *foll){ Instr i; Optable *op; ushort s; uvlong l, addr; vlong v; int n; op = mkinstr(map, &i, pc); if (!op) return -1; n = 0; switch(i.jumptype) { case RET: /* RETURN or LEAVE */ case Iw: /* RETURN */ if (strcmp(op->proto, "LEAVE") == 0) { if (geta(map, (*rget)(map, "BP"), &l) < 0) return -1; } else if (geta(map, (*rget)(map, mach->sp), &l) < 0) return -1; foll[0] = l; return 1; case Iwds: /* pc relative JUMP or CALL*/ case Jbs: /* pc relative JUMP or CALL */ v = (long)i.imm; foll[0] = pc+v+i.n; n = 1; break; case PTR: /* seg:displacement JUMP or CALL */ foll[0] = (i.seg<<4)+i.disp; return 1; case JUMP: /* JUMP or CALL EA */ if(i.mod == 3) { foll[0] = (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]); return 1; } /* calculate the effective address */ addr = i.disp; if (i.base >= 0) { if (geta(map, (*rget)(map, reg[i.rex&REXB? i.base+8: i.base]), &l) < 0) return -1; addr += l; } if (i.index >= 0) { if (geta(map, (*rget)(map, reg[i.rex&REXX? i.index+8: i.index]), &l) < 0) return -1; addr += l*(1<<i.ss); } /* now retrieve a seg:disp value at that address */ if (get2(map, addr, &s) < 0) /* seg */ return -1; foll[0] = s<<4; addr += 2; if (i.asize == 'L') { if (geta(map, addr, &l) < 0) /* disp32 */ return -1; foll[0] += l; } else { /* disp16 */ if (get2(map, addr, &s) < 0) return -1; foll[0] += s; } return 1; default: break; } if (strncmp(op->proto,"JMP", 3) == 0 || strncmp(op->proto,"CALL", 4) == 0) return 1; foll[n++] = pc+i.n; return n;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -