📄 toir.c
字号:
/*--- JMP helpers ---*//*------------------------------------------------------------*/static void jmp_lit( IRJumpKind kind, Addr32 d32 ){ irbb->next = mkU32(d32); irbb->jumpkind = kind;}static void jmp_treg( IRJumpKind kind, IRTemp t ){ irbb->next = mkexpr(t); irbb->jumpkind = kind;}static void jcc_01( X86Condcode cond, Addr32 d32_false, Addr32 d32_true ){ Bool invert; X86Condcode condPos; condPos = positiveIse_X86Condcode ( cond, &invert ); if (invert) { stmt( IRStmt_Exit( mk_x86g_calculate_condition(condPos), Ijk_Boring, IRConst_U32(d32_false) ) ); irbb->next = mkU32(d32_true); irbb->jumpkind = Ijk_Boring; } else { stmt( IRStmt_Exit( mk_x86g_calculate_condition(condPos), Ijk_Boring, IRConst_U32(d32_true) ) ); irbb->next = mkU32(d32_false); irbb->jumpkind = Ijk_Boring; }}/*------------------------------------------------------------*//*--- Disassembling addressing modes ---*//*------------------------------------------------------------*/static HChar* sorbTxt ( UChar sorb ){ switch (sorb) { case 0: return ""; /* no override */ case 0x3E: return "%ds"; case 0x26: return "%es:"; case 0x64: return "%fs:"; case 0x65: return "%gs:"; default: vpanic("sorbTxt(x86,guest)"); }}/* 'virtual' is an IRExpr* holding a virtual address. Convert it to a linear address by adding any required segment override as indicated by sorb. */staticIRExpr* handleSegOverride ( UChar sorb, IRExpr* virtual ){ Int sreg; IRType hWordTy; IRTemp ldt_ptr, gdt_ptr, seg_selector, r64; if (sorb == 0) /* the common case - no override */ return virtual; switch (sorb) { case 0x3E: sreg = R_DS; break; case 0x26: sreg = R_ES; break; case 0x64: sreg = R_FS; break; case 0x65: sreg = R_GS; break; default: vpanic("handleSegOverride(x86,guest)"); } hWordTy = sizeof(HWord)==4 ? Ity_I32 : Ity_I64; seg_selector = newTemp(Ity_I32); ldt_ptr = newTemp(hWordTy); gdt_ptr = newTemp(hWordTy); r64 = newTemp(Ity_I64); assign( seg_selector, unop(Iop_16Uto32, getSReg(sreg)) ); assign( ldt_ptr, IRExpr_Get( OFFB_LDT, hWordTy )); assign( gdt_ptr, IRExpr_Get( OFFB_GDT, hWordTy )); /* Call this to do the translation and limit checks: ULong x86g_use_seg_selector ( HWord ldt, HWord gdt, UInt seg_selector, UInt virtual_addr ) */ assign( r64, mkIRExprCCall( Ity_I64, 0/*regparms*/, "x86g_use_seg_selector", &x86g_use_seg_selector, mkIRExprVec_4( mkexpr(ldt_ptr), mkexpr(gdt_ptr), mkexpr(seg_selector), virtual) ) ); /* If the high 32 of the result are non-zero, there was a failure in address translation. In which case, make a quick exit. */ stmt( IRStmt_Exit( binop(Iop_CmpNE32, unop(Iop_64HIto32, mkexpr(r64)), mkU32(0)), Ijk_MapFail, IRConst_U32( guest_EIP_curr_instr ) ) ); /* otherwise, here's the translated result. */ return unop(Iop_64to32, mkexpr(r64));}/* Generate IR to calculate an address indicated by a ModRM and following SIB bytes. The expression, and the number of bytes in the address mode, are returned. Note that this fn should not be called if the R/M part of the address denotes a register instead of memory. If print_codegen is true, text of the addressing mode is placed in buf. The computed address is stored in a new tempreg, and the identity of the tempreg is returned. */static IRTemp disAMode_copy2tmp ( IRExpr* addr32 ){ IRTemp tmp = newTemp(Ity_I32); assign( tmp, addr32 ); return tmp;}static IRTemp disAMode ( Int* len, UChar sorb, Int delta, HChar* buf ){ UChar mod_reg_rm = getIByte(delta); delta++; buf[0] = (UChar)0; /* squeeze out the reg field from mod_reg_rm, since a 256-entry jump table seems a bit excessive. */ mod_reg_rm &= 0xC7; /* is now XX000YYY */ mod_reg_rm = toUChar(mod_reg_rm | (mod_reg_rm >> 3)); /* is now XX0XXYYY */ mod_reg_rm &= 0x1F; /* is now 000XXYYY */ switch (mod_reg_rm) { /* (%eax) .. (%edi), not including (%esp) or (%ebp). --> GET %reg, t */ case 0x00: case 0x01: case 0x02: case 0x03: /* ! 04 */ /* ! 05 */ case 0x06: case 0x07: { UChar rm = mod_reg_rm; DIS(buf, "%s(%s)", sorbTxt(sorb), nameIReg(4,rm)); *len = 1; return disAMode_copy2tmp( handleSegOverride(sorb, getIReg(4,rm))); } /* d8(%eax) ... d8(%edi), not including d8(%esp) --> GET %reg, t ; ADDL d8, t */ case 0x08: case 0x09: case 0x0A: case 0x0B: /* ! 0C */ case 0x0D: case 0x0E: case 0x0F: { UChar rm = toUChar(mod_reg_rm & 7); UInt d = getSDisp8(delta); DIS(buf, "%s%d(%s)", sorbTxt(sorb), (Int)d, nameIReg(4,rm)); *len = 2; return disAMode_copy2tmp( handleSegOverride(sorb, binop(Iop_Add32,getIReg(4,rm),mkU32(d)))); } /* d32(%eax) ... d32(%edi), not including d32(%esp) --> GET %reg, t ; ADDL d8, t */ case 0x10: case 0x11: case 0x12: case 0x13: /* ! 14 */ case 0x15: case 0x16: case 0x17: { UChar rm = toUChar(mod_reg_rm & 7); UInt d = getUDisp32(delta); DIS(buf, "%s0x%x(%s)", sorbTxt(sorb), (Int)d, nameIReg(4,rm)); *len = 5; return disAMode_copy2tmp( handleSegOverride(sorb, binop(Iop_Add32,getIReg(4,rm),mkU32(d)))); } /* a register, %eax .. %edi. This shouldn't happen. */ case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F: vpanic("disAMode(x86): not an addr!"); /* a 32-bit literal address --> MOV d32, tmp */ case 0x05: { UInt d = getUDisp32(delta); *len = 5; DIS(buf, "%s(0x%x)", sorbTxt(sorb), d); return disAMode_copy2tmp( handleSegOverride(sorb, mkU32(d))); } case 0x04: { /* SIB, with no displacement. Special cases: -- %esp cannot act as an index value. If index_r indicates %esp, zero is used for the index. -- when mod is zero and base indicates EBP, base is instead a 32-bit literal. It's all madness, I tell you. Extract %index, %base and scale from the SIB byte. The value denoted is then: | %index == %ESP && %base == %EBP = d32 following SIB byte | %index == %ESP && %base != %EBP = %base | %index != %ESP && %base == %EBP = d32 following SIB byte + (%index << scale) | %index != %ESP && %base != %ESP = %base + (%index << scale) What happens to the souls of CPU architects who dream up such horrendous schemes, do you suppose? */ UChar sib = getIByte(delta); UChar scale = toUChar((sib >> 6) & 3); UChar index_r = toUChar((sib >> 3) & 7); UChar base_r = toUChar(sib & 7); delta++; if (index_r != R_ESP && base_r != R_EBP) { DIS(buf, "%s(%s,%s,%d)", sorbTxt(sorb), nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale); *len = 2; return disAMode_copy2tmp( handleSegOverride(sorb, binop(Iop_Add32, getIReg(4,base_r), binop(Iop_Shl32, getIReg(4,index_r), mkU8(scale))))); } if (index_r != R_ESP && base_r == R_EBP) { UInt d = getUDisp32(delta); DIS(buf, "%s0x%x(,%s,%d)", sorbTxt(sorb), d, nameIReg(4,index_r), 1<<scale); *len = 6; return disAMode_copy2tmp( handleSegOverride(sorb, binop(Iop_Add32, binop(Iop_Shl32, getIReg(4,index_r), mkU8(scale)), mkU32(d)))); } if (index_r == R_ESP && base_r != R_EBP) { DIS(buf, "%s(%s,,)", sorbTxt(sorb), nameIReg(4,base_r)); *len = 2; return disAMode_copy2tmp( handleSegOverride(sorb, getIReg(4,base_r))); } if (index_r == R_ESP && base_r == R_EBP) { UInt d = getUDisp32(delta); DIS(buf, "%s0x%x()", sorbTxt(sorb), d); *len = 6; vpanic("disAMode(x86):untested amode: 8"); return disAMode_copy2tmp( handleSegOverride(sorb, mkU32(d))); } /*NOTREACHED*/ vassert(0); } /* SIB, with 8-bit displacement. Special cases: -- %esp cannot act as an index value. If index_r indicates %esp, zero is used for the index. Denoted value is: | %index == %ESP = d8 + %base | %index != %ESP = d8 + %base + (%index << scale) */ case 0x0C: { UChar sib = getIByte(delta); UChar scale = toUChar((sib >> 6) & 3); UChar index_r = toUChar((sib >> 3) & 7); UChar base_r = toUChar(sib & 7); UInt d = getSDisp8(delta+1); if (index_r == R_ESP) { DIS(buf, "%s%d(%s,,)", sorbTxt(sorb), (Int)d, nameIReg(4,base_r)); *len = 3; return disAMode_copy2tmp( handleSegOverride(sorb, binop(Iop_Add32, getIReg(4,base_r), mkU32(d)) )); } else { DIS(buf, "%s%d(%s,%s,%d)", sorbTxt(sorb), (Int)d, nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale); *len = 3; return disAMode_copy2tmp( handleSegOverride(sorb, binop(Iop_Add32, binop(Iop_Add32, getIReg(4,base_r), binop(Iop_Shl32, getIReg(4,index_r), mkU8(scale))), mkU32(d)))); } /*NOTREACHED*/ vassert(0); } /* SIB, with 32-bit displacement. Special cases: -- %esp cannot act as an index value. If index_r indicates %esp, zero is used for the index. Denoted value is: | %index == %ESP = d32 + %base | %index != %ESP = d32 + %base + (%index << scale) */ case 0x14: { UChar sib = getIByte(delta); UChar scale = toUChar((sib >> 6) & 3); UChar index_r = toUChar((sib >> 3) & 7); UChar base_r = toUChar(sib & 7); UInt d = getUDisp32(delta+1); if (index_r == R_ESP) { DIS(buf, "%s%d(%s,,)", sorbTxt(sorb), (Int)d, nameIReg(4,base_r)); *len = 6; return disAMode_copy2tmp( handleSegOverride(sorb, binop(Iop_Add32, getIReg(4,base_r), mkU32(d)) )); } else { DIS(buf, "%s%d(%s,%s,%d)", sorbTxt(sorb), (Int)d, nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale); *len = 6; return disAMode_copy2tmp( handleSegOverride(sorb, binop(Iop_Add32, binop(Iop_Add32, getIReg(4,base_r), binop(Iop_Shl32, getIReg(4,index_r), mkU8(scale))), mkU32(d)))); } /*NOTREACHED*/ vassert(0); } default: vpanic("disAMode(x86)"); return 0; /*notreached*/ }}/* Figure out the number of (insn-stream) bytes constituting the amode beginning at delta. Is useful for getting hold of literals beyond the end of the amode before it has been disassembled. */static UInt lengthAMode ( Int delta ){ UChar mod_reg_rm = getIByte(delta); delta++; /* squeeze out the reg field from mod_reg_rm, since a 256-entry jump table seems a bit excessive. */ mod_reg_rm &= 0xC7; /* is now XX000YYY */ mod_reg_rm = toUChar(mod_reg_rm | (mod_reg_rm >> 3)); /* is now XX0XXYYY */ mod_reg_rm &= 0x1F; /* is now 000XXYYY */ switch (mod_reg_rm) { /* (%eax) .. (%edi), not including (%esp) or (%ebp). */ case 0x00: case 0x01: case 0x02: case 0x03: /* ! 04 */ /* ! 05 */ case 0x06: case 0x07: return 1; /* d8(%eax) ... d8(%edi), not including d8(%esp). */ case 0x08: case 0x09: case 0x0A: case 0x0B: /* ! 0C */ case 0x0D: case 0x0E: case 0x0F: return 2; /* d32(%eax) ... d32(%edi), not including d32(%esp). */ case 0x10: case 0x11: case 0x12: case 0x13: /* ! 14 */ case 0x15: case 0x16: case 0x17: return 5; /* a register, %eax .. %edi. (Not an addr, but still handled.) */ case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F: return 1; /* a 32-bit literal address. */ case 0x05: return 5;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -