📄 toir.c
字号:
mk_armg_calculate_flags_c(), mkU8(ARMG_CC_SHIFT_C)) ); assign( *carry_out, mkexpr(oldFlagC) ); } else { assign( *carry_out, binop(Iop_Shr32, mkU32(imm), mkU8(31)) ); } DIS(buf, "#%u", imm); return mkU32(imm); } else { // We shouldn't have any 'op' with bits 4=1 and 7=1 : 1xx1 switch (shift_op) { case 0x0: case 0x8: case 0x1: case 0x2: case 0xA: case 0x3: case 0x4: case 0xC: case 0x5: return dis_shift( decode_ok, theInstr, carry_out, buf ); case 0x6: case 0xE: case 0x7: return dis_rotate( decode_ok, theInstr, carry_out, buf ); default: // Error: Any other value shouldn't be here. *decode_ok = False; vex_printf("dis_shifter_op(arm): shift: No such case: 0x%x\n", shift_op); return mkU32(0); } }}/* -------------- Helper for DPI's. --------------*/staticBool dis_dataproc ( UInt theInstr ){ UChar opc = toUChar((theInstr >> 21) & 0xF); UChar set_flags = toUChar((theInstr >> 20) & 1); UChar Rn_addr = toUChar((theInstr >> 16) & 0xF); UChar Rd_addr = toUChar((theInstr >> 12) & 0xF); IRTemp Rn = newTemp(Ity_I32); IRTemp Rd = newTemp(Ity_I32); IRTemp alu_out = newTemp(Ity_I32); IRTemp shifter_op = newTemp(Ity_I32); IRTemp carry_out = newTemp(Ity_I32); IROp op_set_flags = ARMG_CC_OP_LOGIC; Bool testing_instr = False; Bool decode_ok = True; HChar* cond_name = name_ARMCondcode( (theInstr >> 28) & 0xF ); HChar* ch_set_flags = (set_flags == 1) ? "S" : ""; HChar dis_buf[50]; assign( shifter_op, dis_shifter_op( &decode_ok, theInstr, &carry_out, dis_buf ) ); if (!decode_ok) return False; assign( Rd, getIReg(Rd_addr) ); assign( Rn, getIReg(Rn_addr) ); switch (opc) { case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0xC: case 0xE: DIP("%s%s%s R%d, R%d, %s\n", name_ARMDataProcOp(opc), cond_name, ch_set_flags, Rd_addr, Rn_addr, dis_buf); break; case 0x5: case 0x6: case 0x7: // CAB: Unimplemented break; case 0x8: case 0x9: case 0xA: case 0xB: DIP("%s%s R%d, %s\n", name_ARMDataProcOp(opc), cond_name, Rn_addr, dis_buf); break; case 0xD: case 0xF: DIP("%s%s%s R%d, %s\n", name_ARMDataProcOp(opc), cond_name, ch_set_flags, Rd_addr, dis_buf); break; default:break; } switch (opc) { case 0x0: // AND assign( alu_out, binop(Iop_And32, getIReg(Rn_addr), mkexpr(shifter_op)) ); break; case 0x1: // EOR assign( alu_out, binop(Iop_Xor32, getIReg(Rn_addr), mkexpr(shifter_op)) ); break; case 0x2: // SUB assign( alu_out, binop( Iop_Sub32, getIReg(Rn_addr), mkexpr(shifter_op) ) ); op_set_flags = ARMG_CC_OP_SUB; break; case 0x3: // RSB assign( alu_out, binop( Iop_Sub32, mkexpr(shifter_op), getIReg(Rn_addr) ) ); op_set_flags = ARMG_CC_OP_SUB; /* set_flags(), below, switches the args for this case */ break; case 0x4: // ADD assign( alu_out, binop( Iop_Add32, getIReg(Rn_addr), mkexpr(shifter_op) ) ); op_set_flags = ARMG_CC_OP_ADD; break; case 0x5: // ADC // CAB: Unimplemented case 0x6: // SBC // CAB: Unimplemented case 0x7: // RSC // CAB: Unimplemented goto decode_failure; case 0x8: // TST vassert(set_flags==1); assign( alu_out, binop(Iop_And32, getIReg(Rn_addr), mkexpr(shifter_op)) ); testing_instr = True; break; case 0x9: // TEQ vassert(set_flags==1); assign( alu_out, binop(Iop_Xor32, getIReg(Rn_addr), mkexpr(shifter_op)) ); testing_instr = True; break; case 0xA: // CMP vassert(set_flags==1); op_set_flags = ARMG_CC_OP_SUB; testing_instr = True; break; case 0xB: // CMN vassert(set_flags==1); op_set_flags = ARMG_CC_OP_ADD; testing_instr = True; break; case 0xC: // ORR assign( alu_out, binop(Iop_Or32, getIReg(Rn_addr), mkexpr(shifter_op)) ); break; case 0xD: // MOV assign( alu_out, mkexpr(shifter_op) ); break; case 0xE: // BIC assign( alu_out, binop(Iop_And32, getIReg(Rn_addr), unop( Iop_Not32, mkexpr(shifter_op))) ); break; case 0xF: // MVN assign( alu_out, unop(Iop_Not32, mkexpr(shifter_op)) ); break; default: decode_failure: vex_printf("dis_dataproc(arm): unhandled opcode: 0x%x\n", opc); return False; } if (!testing_instr) { if ( Rd_addr == 15) { // dest reg == PC // CPSR = SPSR: Unpredictable in User | System mode (no SPSR!) // Unpredictable - We're only supporting user mode... vex_printf("dis_dataproc(arm): Unpredictable - Rd_addr==15\n"); return False; } putIReg( Rd_addr, mkexpr(alu_out) ); } if (set_flags) { if (op_set_flags == ARMG_CC_OP_LOGIC) { setFlags_DEP1_DEP2( op_set_flags, alu_out, carry_out ); } else { if (opc == 0x3) { setFlags_DEP1_DEP2( op_set_flags, shifter_op, Rn ); } else { setFlags_DEP1_DEP2( op_set_flags, Rn, shifter_op ); } } } return decode_ok;}/* -------------- Helper for Branch. --------------*/staticvoid dis_branch ( UInt theInstr ){ UChar link = toUChar((theInstr >> 24) & 1); UInt signed_immed_24 = theInstr & 0xFFFFFF; UInt branch_offset; IRTemp addr = newTemp(Ity_I32); IRTemp dest = newTemp(Ity_I32); if (link) { // LR (R14) = addr of instr after branch instr assign( addr, binop(Iop_Add32, getIReg(15), mkU32(4)) ); putIReg( 14, mkexpr(addr) ); } // PC = PC + (SignExtend(signed_immed_24) << 2) branch_offset = extend_s_24to32( signed_immed_24 ) << 2; assign( dest, binop(Iop_Add32, getIReg(15), mkU32(branch_offset)) ); irbb->jumpkind = link ? Ijk_Call : Ijk_Boring; irbb->next = mkexpr(dest); // Note: Not actually writing to R15 - let the IR stuff do that. DIP("b%s%s 0x%x\n", link ? "l" : "", name_ARMCondcode( (theInstr >> 28) & 0xF ), branch_offset);}/*------------------------------------------------------------*//*--- Disassemble a single instruction ---*//*------------------------------------------------------------*//* Disassemble a single instruction into IR. The instruction is located in host memory at &guest_code[delta]. Set *size to be the size of the instruction. If the returned value is Dis_Resteer, the next guest address is assigned to *whereNext. If resteerOK is False, disInstr may not return Dis_Resteer. */ static DisResult disInstr ( /*IN*/ Bool resteerOK, /*IN*/ Bool (*resteerOkFn) ( Addr64 ), /*IN*/ Long delta, /*OUT*/ Int* size, /*OUT*/ Addr64* whereNext ){ // IRType ty; // IRTemp addr, t1, t2; // Int alen; UChar opc1, opc2, opc_tmp; //, modrm, abyte; ARMCondcode cond; // UInt d32; // UChar dis_buf[50]; // Int am_sz, d_sz; DisResult whatNext = Dis_Continue; UInt theInstr; /* At least this is simple on ARM: insns are all 4 bytes long, and 4-aligned. So just fish the whole thing out of memory right now and have done. */ /* We will set *size to 4 if the insn is successfully decoded. Setting it to 0 by default makes bbToIR_ARM abort if we fail the decode. */ *size = 0; theInstr = *(UInt*)(&guest_code[delta]);// vex_printf("START: 0x%x, %,b\n", theInstr, theInstr ); DIP("\t0x%x: ", toUInt(guest_pc_bbstart+delta)); // TODO: fix the client-request stuff, else nothing will work /* Spot the client-request magic sequence. */ // Essentially a v. unlikely sequence of noops that we can catch { UInt* code = (UInt*)(guest_code + delta); /* Spot this: E1A00EE0 mov r0, r0, ror #29 E1A001E0 mov r0, r0, ror #3 E1A00DE0 mov r0, r0, ror #27 E1A002E0 mov r0, r0, ror #5 E1A006E0 mov r0, r0, ror #13 E1A009E0 mov r0, r0, ror #19 */ /* I suspect these will have to be turned the other way round to work on little-endian arm. */ if (code[0] == 0xE1A00EE0 && code[1] == 0xE1A001E0 && code[2] == 0xE1A00DE0 && code[3] == 0xE1A002E0 && code[4] == 0xE1A006E0 && code[5] == 0xE1A009E0) { // uh ... I'll figure this out later. possibly r0 = client_request(r0) */ DIP("?CAB? = client_request ( ?CAB? )\n"); *size = 24; irbb->next = mkU32(toUInt(guest_pc_bbstart+delta)); irbb->jumpkind = Ijk_ClientReq; whatNext = Dis_StopHere; goto decode_success; } } /* Deal with condition first */ cond = (theInstr >> 28) & 0xF; /* opcode: bits 31:28 */// vex_printf("\ndisInstr(arm): cond: 0x%x, %b\n", cond, cond ); switch (cond) { case 0xF: // => Illegal instruction prior to v5 (see ARM ARM A3-5) vex_printf("disInstr(arm): illegal condition\n"); goto decode_failure; case 0xE: // => Unconditional: go translate the instruction break; default: // => Valid condition: translate the condition test first stmt( IRStmt_Exit( mk_armg_calculate_condition(cond), Ijk_Boring, IRConst_U32(toUInt(guest_pc_bbstart+delta+4)) ) ); //irbb->next = mkU32(guest_pc_bbstart+delta+4); //irbb->jumpkind = Ijk_Boring; } /* Primary opcode is roughly bits 27:20 (ARM ARM(v2) A3-2) secondary opcode is bits 4:0 */ opc1 = toUChar((theInstr >> 20) & 0xFF); /* opcode1: bits 27:20 */ opc2 = toUChar((theInstr >> 4 ) & 0xF); /* opcode2: bits 7:4 */// vex_printf("disInstr(arm): opcode1: 0x%2x, %,09b\n", opc1, opc1 );// vex_printf("disInstr(arm): opcode2: 0x%02x, %,04b\n", opc2, opc2 ); switch (opc1 >> 4) { // instr[27:24] case 0x0: case 0x1: /* Multiplies, extra load/store instructions: ARM ARM A3-3 */ if ( (opc1 & 0xE0) == 0x0 && (opc2 & 0x9) == 0x9 ) { // 000xxxxx && 1xx1 if (opc2 == 0x9) { if ((opc1 & 0x1C) == 0x00) { // multiply (accumulate) goto decode_failure; } if ((opc1 & 0x18) == 0x08) { // multiply (accumulate) long goto decode_failure; } if ((opc1 & 0x1B) == 0x10) { // swap/swap byte goto decode_failure; } } if ( opc2 == 0xB ) { if ((opc1 & 0x04) == 0x00) { // load/store 1/2word reg offset goto decode_failure; } else { // load/store 1/2word imm offset goto decode_failure; } } if ((opc2 & 0xD) == 0xD) { if ((opc1 & 0x05) == 0x00) { // load/store 2 words reg offset goto decode_failure; } if ((opc1 & 0x05) == 0x04) { // load/store 2 words imm offset goto decode_failure; } if ((opc1 & 0x05) == 0x01) { // load/store signed 1/2word/byte reg offset goto decode_failure; } if ((opc1 & 0x05) == 0x05) { // load/store signed 1/2word/byte imm offset goto decode_failure; } } } /* endif: Multiplies, extra load/store... */ /* 'Misc' Instructions: ARM ARM A3-4 */ if ((opc1 & 0xF9) == 0x10) { // 0001 0xx0 opc_tmp = toUChar((opc1 >> 1) & 0x3); switch (opc2) { case 0x0: if ((opc_tmp & 0x1) == 0x0) { // move stat reg -> reg goto decode_failure; } else { // move reg -> stat reg goto decode_failure; } case 0x1: if (opc_tmp == 0x1) { // branch/exchange instr set goto decode_failure; } if (opc_tmp == 0x3) { // count leading zeros goto decode_failure; } break; case 0x3:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -