void dbrew_print_decoded(DBB* bb) { int i; for(i = 0; i < bb->count; i++) { Instr* instr = bb->instr + i; printf(" %18s: ", prettyAddress(instr->addr, bb->fc)); printf("%s %s\n", bytes2string(instr, 0, 7), instr2string(instr, 1, bb->fc)); if (instr->len > 7) printf(" %18s: %s\n", prettyAddress(instr->addr + 7, bb->fc), bytes2string(instr, 7, 7)); if (instr->len > 14) printf(" %18s: %s\n", prettyAddress(instr->addr + 14, bb->fc), bytes2string(instr, 14, 7)); } }
void printDecodedBBs(Rewriter* r) { int i; for(i=0; i< r->decBBCount; i++) { printf("BB %s (%d instructions):\n", prettyAddress(r->decBB[i].addr, r->decBB[i].fc), r->decBB[i].count); dbrew_print_decoded(r->decBB + i); } }
// if <fc> is not-null, use it to print immediates/displacement char* op2string(Operand* o, ValType t, FunctionConfig* fc) { static char buf[30]; int off = 0; uint64_t val; switch(o->type) { case OT_Reg8: case OT_Reg16: case OT_Reg32: case OT_Reg64: case OT_Reg128: case OT_Reg256: sprintf(buf, "%%%s", regName(o->reg, o->type)); break; case OT_Imm8: val = o->val; assert(val < (1l<<8)); switch(t) { case VT_None: case VT_8: break; case VT_16: case VT_32: if (val > 0x7F) val += 0xFFFFFF00; break; case VT_64: if (val > 0x7F) val += 0xFFFFFFFFFFFFFF00; break; default: assert(0); } sprintf(buf, "$0x%lx", val); break; case OT_Imm16: val = o->val; assert(val < (1l<<16)); switch(t) { case VT_32: if (val > 0x7FFF) val += 0xFFFF0000; break; case VT_64: if (val > 0x7FFF) val += 0xFFFFFFFFFFFF0000; break; case VT_16: case VT_None: break; default: assert(0); } sprintf(buf, "$0x%lx", val); break; case OT_Imm32: val = o->val; assert(val < (1l<<32)); switch(t) { case VT_None: case VT_32: break; case VT_64: if (val > 0x7FFFFFFF) val += 0xFFFFFFFF00000000; break; default: assert(0); } sprintf(buf, "$%s", prettyAddress(val, fc)); break; case OT_Imm64: sprintf(buf, "$%s", prettyAddress(o->val, fc)); break; case OT_Ind8: case OT_Ind16: case OT_Ind32: case OT_Ind64: case OT_Ind128: case OT_Ind256: off = 0; switch(o->seg) { case OSO_None: break; case OSO_UseFS: off += sprintf(buf+off, "fs:"); break; case OSO_UseGS: off += sprintf(buf+off, "gs:"); break; default: assert(0); } if (o->val != 0) { if (o->val & (1l<<63)) off += sprintf(buf+off, "-0x%lx", (~ o->val)+1); else off += sprintf(buf+off, "%s", prettyAddress(o->val, fc)); } if ((o->scale == 0) || (o->ireg == Reg_None)) { if (o->reg != Reg_None) sprintf(buf+off,"(%%%s)", regName(o->reg, OT_Reg64)); } else { const char* ri = regName(o->ireg, OT_Reg64); if (o->reg == Reg_None) { sprintf(buf+off,"(,%%%s,%d)", ri, o->scale); } else sprintf(buf+off,"(%%%s,%%%s,%d)", regName(o->reg, OT_Reg64), ri, o->scale); } break; default: assert(0); } return buf; }
// if <fc> is not-null, use it to print immediates/displacement char* op2string(Operand* o, Instr* instr, FunctionConfig* fc) { static char buf[30]; int off = 0; ValType t = instr->vtype; uint64_t val; switch(o->type) { case OT_Reg8: case OT_Reg16: case OT_Reg32: case OT_Reg64: case OT_Reg128: case OT_Reg256: case OT_Reg512: off += sprintf(buf, "%%%s", regName(o->reg)); break; case OT_Imm8: val = o->val; assert(val < (1l<<8)); switch(t) { case VT_None: case VT_8: break; case VT_16: case VT_32: if (val > 0x7F) val += 0xFFFFFF00; break; case VT_64: if (val > 0x7F) val += 0xFFFFFFFFFFFFFF00; break; default: assert(0); } off += sprintf(buf, "$0x%lx", val); break; case OT_Imm16: val = o->val; assert(val < (1l<<16)); switch(t) { case VT_32: if (val > 0x7FFF) val += 0xFFFF0000; break; case VT_64: if (val > 0x7FFF) val += 0xFFFFFFFFFFFF0000; break; case VT_16: case VT_None: break; default: assert(0); } off += sprintf(buf, "$0x%lx", val); break; case OT_Imm32: val = o->val; assert(val < (1l<<32)); switch(t) { case VT_None: case VT_32: break; case VT_64: if (val > 0x7FFFFFFF) val += 0xFFFFFFFF00000000; break; default: assert(0); } off += sprintf(buf, "$%s", prettyAddress(val, fc)); break; case OT_Imm64: off += sprintf(buf, "$%s", prettyAddress(o->val, fc)); break; case OT_Ind8: case OT_Ind16: case OT_Ind32: case OT_Ind64: case OT_Ind128: case OT_Ind256: case OT_Ind512: switch(o->seg) { case OSO_None: break; case OSO_UseFS: off += sprintf(buf+off, "%%fs:"); break; case OSO_UseGS: off += sprintf(buf+off, "%%gs:"); break; default: assert(0); } val = o->val; // for rip-relative addressing, shown displacement is adjusted if ((o->scale == 0) && (o->reg.rt == RT_IP)) { // addr+len is 0 if not decoded val += instr->addr + instr->len; } if (val != 0) { if (val & (1l<<63)) off += sprintf(buf+off, "-0x%lx", (~val)+1); else off += sprintf(buf+off, "%s", prettyAddress(val, fc)); } if ((o->scale == 0) || (o->ireg.rt == RT_None)) { if (o->reg.rt != RT_None) off += sprintf(buf+off,"(%%%s)", regName(o->reg)); else if (off == 0) { // nothing printed yet off += sprintf(buf, "0x0"); } } else { const char* ri = regName(o->ireg); if (o->reg.rt == RT_None) { off += sprintf(buf+off,"(,%%%s,%d)", ri, o->scale); } else off += sprintf(buf+off,"(%%%s,%%%s,%d)", regName(o->reg), ri, o->scale); } break; default: assert(0); } assert(off > 0); return buf; }