public MethodIL Add(OpCodeInfo opCodeInfo) { ArgumentValidator.ValidateNotNull("Op code info", opCodeInfo); this._opCodes.Add(opCodeInfo); this._branchTargetsCount += opCodeInfo.BranchTargetCount; return(this); }
public override string ToString() { var op = GET_OPCODE(); var a = GETARG_A(); var b = GETARG_B(); var c = GETARG_C(); var ax = GETARG_Ax(); var bx = GETARG_Bx(); var sbx = GETARG_sBx(); var mode = OpCodeInfo.GetMode(op); switch (mode.OpMode) { case OpMode.iABC: { string ret = string.Format("{0,-9} {1}" , op , a); if (mode.BMode != OpArgMask.OpArgN) { ret += " " + (ISK(b) ? MYK(INDEXK(b)) : b); } if (mode.CMode != OpArgMask.OpArgN) { ret += " " + (ISK(c) ? MYK(INDEXK(c)) : c); } return(ret); } case OpMode.iABx: { string ret = string.Format("{0,-9} {1}" , op , a); if (mode.BMode == OpArgMask.OpArgK) { ret += " " + MYK(bx); } else if (mode.BMode == OpArgMask.OpArgU) { ret += " " + bx; } return(ret); } case OpMode.iAsBx: { return(string.Format("{0,-9} {1} {2}" , op , a , sbx)); } case OpMode.iAx: { return(string.Format("{0,-9} {1}" , op , MYK(ax))); } default: throw new System.NotImplementedException(); } }
static void AppendTable(OpCodeInfo info, StringBuilder sb) { switch (info.Table) { case OpCodeTableKind.Normal: break; case OpCodeTableKind.T0F: AppendOpCode(sb, 0x0F); break; case OpCodeTableKind.T0F38: AppendOpCode(sb, 0x0F38); break; case OpCodeTableKind.T0F3A: AppendOpCode(sb, 0x0F3A); break; case OpCodeTableKind.XOP8: sb.Append("X8"); break; case OpCodeTableKind.XOP9: sb.Append("X9"); break; case OpCodeTableKind.XOPA: sb.Append("XA"); break; default: throw new InvalidOperationException(); } }
/// <summary> /// Do all registers of the given instruction fit in the size that is available for them? /// </summary> private static bool AllRegistersFit(Instruction ins) { var registers = ins.Registers; var count = registers.Count; if (count == 0) { return(true); } var info = OpCodeInfo.Get(ins.OpCode); for (var i = 0; i < count; i++) { var size = info.GetUsage(i) & RegisterFlags.SizeMask; switch (size) { case RegisterFlags.Bits4: if (!registers[i].IsBits4) { return(false); } break; case RegisterFlags.Bits8: if (!registers[i].IsBits8) { return(false); } break; } } return(true); }
static string ToString_VEX_XOP_EVEX(OpCodeInfo info, StringBuilder sb, bool l0l1, string encodingName) { sb.Length = 0; sb.Append(encodingName); sb.Append('.'); if (info.IsLIG) { sb.Append("LIG"); } else if (l0l1) { sb.Append('L'); sb.Append(info.L); } else { sb.Append(128U << (int)info.L); } switch (info.MandatoryPrefix) { case MandatoryPrefix.None: case MandatoryPrefix.PNP: break; case MandatoryPrefix.P66: sb.Append('.'); AppendHexByte(sb, 0x66); break; case MandatoryPrefix.PF3: sb.Append('.'); AppendHexByte(sb, 0xF3); break; case MandatoryPrefix.PF2: sb.Append('.'); AppendHexByte(sb, 0xF2); break; default: throw new InvalidOperationException(); } sb.Append('.'); AppendTable(info, sb); if (info.IsWIG) { sb.Append(".WIG"); } else { sb.Append(".W"); sb.Append(info.W); } sb.Append(' '); AppendOpCode(sb, info.OpCode); AppendRest(info, sb); return(sb.ToString()); }
public OpCodeFormatter(OpCodeInfo opCode, StringBuilder sb, LKind lkind, bool hasModrmInfo) { this.opCode = opCode; this.sb = sb; this.lkind = lkind; this.hasModrmInfo = hasModrmInfo; }
static string GetMode(StringBuilder sb, OpCodeInfo opCode) { sb.Clear(); if ((opCode.Flags & OpCodeFlags.Mode16) != 0) { sb.Append("16"); } if ((opCode.Flags & OpCodeFlags.Mode32) != 0) { if (sb.Length > 0) { sb.Append('/'); } sb.Append("32"); } if ((opCode.Flags & OpCodeFlags.Mode64) != 0) { if (sb.Length > 0) { sb.Append('/'); } sb.Append("64"); } if (sb.Length == 0) { throw new InvalidOperationException(); } sb.Append("-bit"); return(sb.ToString()); }
public bool DisassembleMethod() { if (selectedMethod == null && selection.selectedMethod != null) { SelectMethod(selection.selectedMethod); } if (selectedMethod == null) { return(false); } var reader = new MethodBodyReader(selectedMethod); byteCount = reader.ilByteCount; ilCode = reader.GetBodyCode(); localVariables.Clear(); if (string.IsNullOrWhiteSpace(ilCode)) { instructionInfo.Clear(); Updated?.Invoke(this); return(false); } if (reader.LocalVariables != null) { foreach (var local in reader.LocalVariables) { localVariables.Add(local.LocalIndex, local); } } var lines = ilCode?.Split('\n').ToList(); lines.RemoveAll(string.IsNullOrWhiteSpace); var ilCodeLines = lines.ToArray(); var ilLinesInfos = new OpCodeInfo[ilCodeLines?.Length ?? 0]; if (reader.instructions == null) { return(false); } for (var index = 0; index < reader.instructions.Count && index < ilLinesInfos.Length; index++) { var instruction = reader.instructions[index]; var d = TryGetOpCodeDescription(instruction.Code); if (d == null) { continue; } ilLinesInfos[index] = d; } FindBlocks(ilCodeLines, reader.instructions, ilLinesInfos); Updated?.Invoke(this); DisassemblyChanged?.Invoke(this); return(true); }
static string ToString_3DNow(OpCodeInfo info, StringBuilder sb) { sb.Length = 0; AppendOpCode(sb, 0x0F0F); sb.Append(" /r"); sb.Append(' '); AppendOpCode(sb, info.OpCode); return(sb.ToString()); }
/// <summary> /// Add instructions that spill registers (when needed). /// </summary> internal void Generate(MethodBody body) { // Go over each instruction in the block. var instructions = block.Instructions.ToList(); foreach (var ins in instructions) { var registers = ins.Registers; var count = registers.Count; if (count == 0) { // No registers, so no spilling continue; } var isInvoke = ins.OpCode.IsInvoke(); if (isInvoke) { if (ins.RequiresInvokeRange()) { ConvertInvoke(ins); } } else { var info = OpCodeInfo.Get(ins.OpCode); for (var i = 0; i < count; i++) { Register r; LowRegisterState state; var spill = TryGetLowRegister(registers[i], out r, out state); if (!spill) { var size = info.GetUsage(i) & RegisterFlags.SizeMask; switch (size) { case RegisterFlags.Bits4: spill = !registers[i].IsBits4; break; case RegisterFlags.Bits8: spill = !registers[i].IsBits8; break; } } if (spill) { // Insert spilling code AddCode(ins, registers[i], body); } } } } }
public InstructionDef(int opCount, EnumValue mnemonic, EnumValue mem, EnumValue bcst, OpCodeInfo opCodeInfo, InstrInfo instrInfo) { if (opCodeInfo.Code != instrInfo.Code) { throw new InvalidOperationException(); } OpCount = opCount; Mnemonic = mnemonic; Mem = mem; Bcst = bcst; OpCodeInfo = opCodeInfo; InstrInfo = instrInfo; }
static OpCodeInfo[] CreateInfos() { var infos = new OpCodeInfo[IcedConstants.NumberOfCodeValues]; var data = OpCodeHandlers.GetData(); Debug.Assert(data.Length == infos.Length * 3); var sb = new StringBuilder(); for (int i = 0; i < infos.Length; i++) { infos[i] = new OpCodeInfo((Code)i, data[i * 3 + 2], data[i * 3 + 1], data[i * 3], sb); } return(infos); }
public bool IsDestinationRegister(int index) { var info = OpCodeInfo.Get(Instruction.Code.ToDex()); var isDest = (info.GetUsage(index) & RegisterFlags.Destination) == RegisterFlags.Destination; // While not changing the value, check_cast changes the meaning of the // register. We treat it as a read-write instruction here. One should check if // check-cast should not always be treated as a read-write instruction. if (Instruction.Code == RCode.Check_cast) { isDest = true; } return(isDest); }
public static ILMethodInfo Disassemble(MethodInfo method) { if (method == null) { return(null); } var reader = new MethodBodyReader(method); var ilCode = reader.GetBodyCode(); if (string.IsNullOrWhiteSpace(ilCode)) { return(null); } var localVariables = new List <LocalVariableInfo>(); if (reader.LocalVariables != null) { localVariables.AddRange(reader.LocalVariables); } var lines = ilCode?.Split('\n').ToList(); lines.RemoveAll(string.IsNullOrWhiteSpace); var ilCodeLines = lines.ToArray(); var ilLinesInfos = new OpCodeInfo[ilCodeLines?.Length ?? 0]; if (reader.instructions == null) { return(null); } for (var index = 0; index < reader.instructions.Count && index < ilLinesInfos.Length; index++) { var instruction = reader.instructions[index]; var d = ILNavigator.TryGetOpCodeDescription(instruction.Code); if (d == null) { continue; } ilLinesInfos[index] = d; } var instructions = FindBlocks(ilCodeLines, reader.instructions, ilLinesInfos); return(new ILMethodInfo(localVariables, instructions)); }
static OpCodeInfo[] CreateInfos() { var infos = new OpCodeInfo[IcedConstants.CodeEnumCount]; var encFlags1 = EncoderData.EncFlags1; var encFlags2 = EncoderData.EncFlags2; var encFlags3 = EncoderData.EncFlags3; var opcFlags1 = OpCodeInfoData.OpcFlags1; var opcFlags2 = OpCodeInfoData.OpcFlags2; var sb = new StringBuilder(); for (int i = 0; i < infos.Length; i++) { infos[i] = new OpCodeInfo((Code)i, (EncFlags1)encFlags1[i], (EncFlags2)encFlags2[i], (EncFlags3)encFlags3[i], (OpCodeInfoFlags1)opcFlags1[i], (OpCodeInfoFlags2)opcFlags2[i], sb); } return(infos); }
static OpCodeOperandKind GetOpCodeBitsOperand(OpCodeInfo info) { int opCount = info.OpCount; for (int i = 0; i < opCount; i++) { var opKind = info.GetOpKind(i); switch (opKind) { case OpCodeOperandKind.r8_opcode: case OpCodeOperandKind.r16_opcode: case OpCodeOperandKind.r32_opcode: case OpCodeOperandKind.r64_opcode: return(opKind); } } return(OpCodeOperandKind.None); }
/// <summary> /// Gets the lowest size (in bitsX) that is available for the given register in the given instruction. /// </summary> private static RegisterFlags GetLowestSize(Instruction instruction, Register r) { var result = RegisterFlags.Bits16; var info = OpCodeInfo.Get(instruction.Code.ToDex()); var registers = instruction.Registers; for (var i = 0; i < registers.Count; i++) { if (registers[i] == r) { var size = info.GetUsage(i) & RegisterFlags.SizeMask; if (size < result) { result = size; } } } return(result); }
static bool HasVsib(OpCodeInfo info) { int opCount = info.OpCount; for (int i = 0; i < opCount; i++) { switch (info.GetOpKind(i)) { case OpCodeOperandKind.mem_vsib32x: case OpCodeOperandKind.mem_vsib64x: case OpCodeOperandKind.mem_vsib32y: case OpCodeOperandKind.mem_vsib64y: case OpCodeOperandKind.mem_vsib32z: case OpCodeOperandKind.mem_vsib64z: return(true); } } return(false); }
public ILInstructionInfo(string line, ILInstruction instruction, OpCodeInfo opInfo) { this.Line = line; this.OpInfo = opInfo; this.instruction = instruction; this.InstructionOffset = instruction.Offset; this.IsBrTarget = instruction.IsBrTarget; if (this.IsBrTarget) { this.BranchTarget = (int)instruction.Operand; } else if (instruction.IsVariableAccess) { var list = new List <int>(); var varIndex = Convert.ToInt32(instruction.Operand); // Debug.Log(instruction.Operand + " -> " + varIndex); if (!list.Contains(varIndex)) { list.Add(varIndex); } LocalVariableAccesses = list; } else if (instruction.Code.ToString().ToLowerInvariant().Contains("loc.")) { // getting local variable access in a hacky way: var str = instruction.Code.ToString().ToLowerInvariant(); // Debug.Log(instruction.Code); var indexOfDot = str.IndexOf('.'); var sub = str.Substring(indexOfDot + 1); if (!string.IsNullOrWhiteSpace(sub)) { var num = Convert.ToInt32(sub); var list = new List <int>(); if (!list.Contains(num)) { list.Add(num); } LocalVariableAccesses = list; } } }
public static string ToString(OpCodeInfo info, StringBuilder sb, bool l0l1) { if (!info.IsInstruction) { switch (info.Code) { case Code.INVALID: return("<invalid>"); case Code.DeclareByte: return("<db>"); case Code.DeclareWord: return("<dw>"); case Code.DeclareDword: return("<dd>"); case Code.DeclareQword: return("<dq>"); default: throw new InvalidOperationException(); } } switch (info.Encoding) { case EncodingKind.Legacy: return(ToString_Legacy(info, sb)); case EncodingKind.VEX: return(ToString_VEX_XOP_EVEX(info, sb, l0l1, "VEX")); case EncodingKind.EVEX: return(ToString_VEX_XOP_EVEX(info, sb, l0l1, "EVEX")); case EncodingKind.XOP: return(ToString_VEX_XOP_EVEX(info, sb, l0l1, "XOP")); case EncodingKind.D3NOW: return(ToString_3DNow(info, sb)); default: throw new InvalidOperationException(); } }
/// <summary> /// Is the given register used as source in the given instruction? /// </summary> public static bool IsSourceIn(this Register r, Instruction ins) { var registers = ins.Registers; var count = registers.Count; if (count == 0) { return(false); } var info = OpCodeInfo.Get(ins.Code.ToDex()); for (var i = 0; i < count; i++) { if (registers[i] == r) { if ((info.GetUsage(i) & RegisterFlags.Source) == RegisterFlags.Source) { return(true); } } } return(false); }
public OpCodeFormatter(OpCodeInfo opCode, StringBuilder sb, LKind lkind) { this.opCode = opCode; this.sb = sb; this.lkind = lkind; }
public InstructionFormatter(OpCodeInfo opCode, StringBuilder sb) { this.opCode = opCode; this.sb = sb; noVecIndex = false; swapVecIndex12 = false; startOpIndex = 0; bnd_count = 0; r32_count = 0; r64_count = 0; r32_index = 0; r64_index = 0; k_index = 0; vec_index = 0; bnd_index = 0; opCount = opCode.OpCount; opMaskIsK1 = false; if ((opCode.Op0Kind == OpCodeOperandKind.k_reg || opCode.Op0Kind == OpCodeOperandKind.kp1_reg) && opCode.OpCount > 2) { vec_index++; } switch (opCode.Code) { case Code.EVEX_Vfpclassps_k_k1_xmmm128b32_imm8: case Code.EVEX_Vfpclassps_k_k1_ymmm256b32_imm8: case Code.EVEX_Vfpclassps_k_k1_zmmm512b32_imm8: case Code.EVEX_Vfpclasspd_k_k1_xmmm128b64_imm8: case Code.EVEX_Vfpclasspd_k_k1_ymmm256b64_imm8: case Code.EVEX_Vfpclasspd_k_k1_zmmm512b64_imm8: case Code.EVEX_Vfpclassss_k_k1_xmmm32_imm8: case Code.EVEX_Vfpclasssd_k_k1_xmmm64_imm8: case Code.EVEX_Vptestmb_k_k1_xmm_xmmm128: case Code.EVEX_Vptestmb_k_k1_ymm_ymmm256: case Code.EVEX_Vptestmb_k_k1_zmm_zmmm512: case Code.EVEX_Vptestmw_k_k1_xmm_xmmm128: case Code.EVEX_Vptestmw_k_k1_ymm_ymmm256: case Code.EVEX_Vptestmw_k_k1_zmm_zmmm512: case Code.EVEX_Vptestnmb_k_k1_xmm_xmmm128: case Code.EVEX_Vptestnmb_k_k1_ymm_ymmm256: case Code.EVEX_Vptestnmb_k_k1_zmm_zmmm512: case Code.EVEX_Vptestnmw_k_k1_xmm_xmmm128: case Code.EVEX_Vptestnmw_k_k1_ymm_ymmm256: case Code.EVEX_Vptestnmw_k_k1_zmm_zmmm512: case Code.EVEX_Vptestmd_k_k1_xmm_xmmm128b32: case Code.EVEX_Vptestmd_k_k1_ymm_ymmm256b32: case Code.EVEX_Vptestmd_k_k1_zmm_zmmm512b32: case Code.EVEX_Vptestmq_k_k1_xmm_xmmm128b64: case Code.EVEX_Vptestmq_k_k1_ymm_ymmm256b64: case Code.EVEX_Vptestmq_k_k1_zmm_zmmm512b64: case Code.EVEX_Vptestnmd_k_k1_xmm_xmmm128b32: case Code.EVEX_Vptestnmd_k_k1_ymm_ymmm256b32: case Code.EVEX_Vptestnmd_k_k1_zmm_zmmm512b32: case Code.EVEX_Vptestnmq_k_k1_xmm_xmmm128b64: case Code.EVEX_Vptestnmq_k_k1_ymm_ymmm256b64: case Code.EVEX_Vptestnmq_k_k1_zmm_zmmm512b64: opMaskIsK1 = true; break; case Code.VEX_Vpextrw_r32m16_xmm_imm8: case Code.VEX_Vpextrw_r64m16_xmm_imm8: case Code.EVEX_Vpextrw_r32m16_xmm_imm8: case Code.EVEX_Vpextrw_r64m16_xmm_imm8: case Code.VEX_Vmovmskpd_r32_xmm: case Code.VEX_Vmovmskpd_r64_xmm: case Code.VEX_Vmovmskpd_r32_ymm: case Code.VEX_Vmovmskpd_r64_ymm: case Code.VEX_Vmovmskps_r32_xmm: case Code.VEX_Vmovmskps_r64_xmm: case Code.VEX_Vmovmskps_r32_ymm: case Code.VEX_Vmovmskps_r64_ymm: case Code.Pextrb_r32m8_xmm_imm8: case Code.Pextrb_r64m8_xmm_imm8: case Code.Pextrd_rm32_xmm_imm8: case Code.Pextrq_rm64_xmm_imm8: case Code.VEX_Vpextrb_r32m8_xmm_imm8: case Code.VEX_Vpextrb_r64m8_xmm_imm8: case Code.VEX_Vpextrd_rm32_xmm_imm8: case Code.VEX_Vpextrq_rm64_xmm_imm8: case Code.EVEX_Vpextrb_r32m8_xmm_imm8: case Code.EVEX_Vpextrb_r64m8_xmm_imm8: case Code.EVEX_Vpextrd_rm32_xmm_imm8: case Code.EVEX_Vpextrq_rm64_xmm_imm8: vec_index++; break; case Code.Pxor_mm_mmm64: case Code.Punpckldq_mm_mmm32: case Code.Punpcklwd_mm_mmm32: case Code.Punpcklbw_mm_mmm32: case Code.Punpckhdq_mm_mmm64: case Code.Punpckhwd_mm_mmm64: case Code.Punpckhbw_mm_mmm64: case Code.Psubusb_mm_mmm64: case Code.Psubusw_mm_mmm64: case Code.Psubsw_mm_mmm64: case Code.Psubsb_mm_mmm64: case Code.Psubd_mm_mmm64: case Code.Psubw_mm_mmm64: case Code.Psubb_mm_mmm64: case Code.Psrlq_mm_imm8: case Code.Psrlq_mm_mmm64: case Code.Psrld_mm_imm8: case Code.Psrld_mm_mmm64: case Code.Psrlw_mm_imm8: case Code.Psrlw_mm_mmm64: case Code.Psrad_mm_imm8: case Code.Psrad_mm_mmm64: case Code.Psraw_mm_imm8: case Code.Psraw_mm_mmm64: case Code.Psllq_mm_imm8: case Code.Psllq_mm_mmm64: case Code.Pslld_mm_imm8: case Code.Pslld_mm_mmm64: case Code.Psllw_mm_mmm64: case Code.Por_mm_mmm64: case Code.Pmullw_mm_mmm64: case Code.Pmulhw_mm_mmm64: case Code.Pmovmskb_r32_mm: case Code.Pmovmskb_r64_mm: case Code.Pmovmskb_r32_xmm: case Code.Pmovmskb_r64_xmm: case Code.Pmaddwd_mm_mmm64: case Code.Pinsrw_mm_r32m16_imm8: case Code.Pinsrw_mm_r64m16_imm8: case Code.Pinsrw_xmm_r32m16_imm8: case Code.Pinsrw_xmm_r64m16_imm8: case Code.Pextrw_r32_xmm_imm8: case Code.Pextrw_r64_xmm_imm8: case Code.Pextrw_r32m16_xmm_imm8: case Code.Pextrw_r64m16_xmm_imm8: case Code.Pextrw_r32_mm_imm8: case Code.Pextrw_r64_mm_imm8: case Code.Cvtpd2pi_mm_xmmm128: case Code.Cvtpi2pd_xmm_mmm64: case Code.Cvtpi2ps_xmm_mmm64: case Code.Cvtps2pi_mm_xmmm64: case Code.Cvttpd2pi_mm_xmmm128: case Code.Cvttps2pi_mm_xmmm64: case Code.Movd_mm_rm32: case Code.Movq_mm_rm64: case Code.Movd_rm32_mm: case Code.Movq_rm64_mm: case Code.Movd_xmm_rm32: case Code.Movq_xmm_rm64: case Code.Movd_rm32_xmm: case Code.Movq_rm64_xmm: case Code.Movdq2q_mm_xmm: case Code.Movmskpd_r32_xmm: case Code.Movmskpd_r64_xmm: case Code.Movmskps_r32_xmm: case Code.Movmskps_r64_xmm: case Code.Movntq_m64_mm: case Code.Movq_mm_mmm64: case Code.Movq_mmm64_mm: case Code.Movq2dq_xmm_mm: case Code.Packuswb_mm_mmm64: case Code.Paddb_mm_mmm64: case Code.Paddw_mm_mmm64: case Code.Paddd_mm_mmm64: case Code.Paddq_mm_mmm64: case Code.Paddsb_mm_mmm64: case Code.Paddsw_mm_mmm64: case Code.Paddusb_mm_mmm64: case Code.Paddusw_mm_mmm64: case Code.Pand_mm_mmm64: case Code.Pandn_mm_mmm64: case Code.Pcmpeqb_mm_mmm64: case Code.Pcmpeqw_mm_mmm64: case Code.Pcmpeqd_mm_mmm64: case Code.Pcmpgtb_mm_mmm64: case Code.Pcmpgtw_mm_mmm64: case Code.Pcmpgtd_mm_mmm64: noVecIndex = true; break; case Code.Movapd_xmmm128_xmm: case Code.VEX_Vmovapd_xmmm128_xmm: case Code.VEX_Vmovapd_ymmm256_ymm: case Code.EVEX_Vmovapd_xmmm128_k1z_xmm: case Code.EVEX_Vmovapd_ymmm256_k1z_ymm: case Code.EVEX_Vmovapd_zmmm512_k1z_zmm: case Code.Movaps_xmmm128_xmm: case Code.VEX_Vmovaps_xmmm128_xmm: case Code.VEX_Vmovaps_ymmm256_ymm: case Code.EVEX_Vmovaps_xmmm128_k1z_xmm: case Code.EVEX_Vmovaps_ymmm256_k1z_ymm: case Code.EVEX_Vmovaps_zmmm512_k1z_zmm: case Code.Movdqa_xmmm128_xmm: case Code.VEX_Vmovdqa_xmmm128_xmm: case Code.VEX_Vmovdqa_ymmm256_ymm: case Code.EVEX_Vmovdqa32_xmmm128_k1z_xmm: case Code.EVEX_Vmovdqa32_ymmm256_k1z_ymm: case Code.EVEX_Vmovdqa32_zmmm512_k1z_zmm: case Code.EVEX_Vmovdqa64_xmmm128_k1z_xmm: case Code.EVEX_Vmovdqa64_ymmm256_k1z_ymm: case Code.EVEX_Vmovdqa64_zmmm512_k1z_zmm: case Code.Movdqu_xmmm128_xmm: case Code.VEX_Vmovdqu_xmmm128_xmm: case Code.VEX_Vmovdqu_ymmm256_ymm: case Code.EVEX_Vmovdqu8_xmmm128_k1z_xmm: case Code.EVEX_Vmovdqu8_ymmm256_k1z_ymm: case Code.EVEX_Vmovdqu8_zmmm512_k1z_zmm: case Code.EVEX_Vmovdqu16_xmmm128_k1z_xmm: case Code.EVEX_Vmovdqu16_ymmm256_k1z_ymm: case Code.EVEX_Vmovdqu16_zmmm512_k1z_zmm: case Code.EVEX_Vmovdqu32_xmmm128_k1z_xmm: case Code.EVEX_Vmovdqu32_ymmm256_k1z_ymm: case Code.EVEX_Vmovdqu32_zmmm512_k1z_zmm: case Code.EVEX_Vmovdqu64_xmmm128_k1z_xmm: case Code.EVEX_Vmovdqu64_ymmm256_k1z_ymm: case Code.EVEX_Vmovdqu64_zmmm512_k1z_zmm: case Code.VEX_Vmovhpd_xmm_xmm_m64: case Code.EVEX_Vmovhpd_xmm_xmm_m64: case Code.VEX_Vmovhps_xmm_xmm_m64: case Code.EVEX_Vmovhps_xmm_xmm_m64: case Code.VEX_Vmovlpd_xmm_xmm_m64: case Code.EVEX_Vmovlpd_xmm_xmm_m64: case Code.VEX_Vmovlps_xmm_xmm_m64: case Code.EVEX_Vmovlps_xmm_xmm_m64: case Code.Movq_xmmm64_xmm: case Code.Movss_xmmm32_xmm: case Code.Movupd_xmmm128_xmm: case Code.VEX_Vmovupd_xmmm128_xmm: case Code.VEX_Vmovupd_ymmm256_ymm: case Code.EVEX_Vmovupd_xmmm128_k1z_xmm: case Code.EVEX_Vmovupd_ymmm256_k1z_ymm: case Code.EVEX_Vmovupd_zmmm512_k1z_zmm: case Code.Movups_xmmm128_xmm: case Code.VEX_Vmovups_xmmm128_xmm: case Code.VEX_Vmovups_ymmm256_ymm: case Code.EVEX_Vmovups_xmmm128_k1z_xmm: case Code.EVEX_Vmovups_ymmm256_k1z_ymm: case Code.EVEX_Vmovups_zmmm512_k1z_zmm: swapVecIndex12 = true; break; } for (int i = 0; i < opCode.OpCount; i++) { switch (opCode.GetOpKind(i)) { case OpCodeOperandKind.r32_reg: case OpCodeOperandKind.r32_rm: case OpCodeOperandKind.r32_opcode: case OpCodeOperandKind.r32_vvvv: r32_count++; break; case OpCodeOperandKind.r64_reg: case OpCodeOperandKind.r64_rm: case OpCodeOperandKind.r64_opcode: case OpCodeOperandKind.r64_vvvv: r64_count++; break; case OpCodeOperandKind.bnd_or_mem_mpx: case OpCodeOperandKind.bnd_reg: bnd_count++; break; case OpCodeOperandKind.st0: if (i == 0) { switch (opCode.Code) { case Code.Fcom_st0_sti: case Code.Fcomp_st0_sti: case Code.Fld_st0_sti: case Code.Fucom_st0_sti: case Code.Fucomp_st0_sti: case Code.Fxch_st0_sti: startOpIndex = 1; break; } } break; case OpCodeOperandKind.None: case OpCodeOperandKind.farbr2_2: case OpCodeOperandKind.farbr4_2: case OpCodeOperandKind.mem_offs: case OpCodeOperandKind.mem: case OpCodeOperandKind.mem_mpx: case OpCodeOperandKind.mem_vsib32x: case OpCodeOperandKind.mem_vsib64x: case OpCodeOperandKind.mem_vsib32y: case OpCodeOperandKind.mem_vsib64y: case OpCodeOperandKind.mem_vsib32z: case OpCodeOperandKind.mem_vsib64z: case OpCodeOperandKind.r8_or_mem: case OpCodeOperandKind.r16_or_mem: case OpCodeOperandKind.r32_or_mem: case OpCodeOperandKind.r32_or_mem_mpx: case OpCodeOperandKind.r64_or_mem: case OpCodeOperandKind.r64_or_mem_mpx: case OpCodeOperandKind.mm_or_mem: case OpCodeOperandKind.xmm_or_mem: case OpCodeOperandKind.ymm_or_mem: case OpCodeOperandKind.zmm_or_mem: case OpCodeOperandKind.k_or_mem: case OpCodeOperandKind.r8_reg: case OpCodeOperandKind.r8_opcode: case OpCodeOperandKind.r16_reg: case OpCodeOperandKind.r16_rm: case OpCodeOperandKind.r16_opcode: case OpCodeOperandKind.seg_reg: case OpCodeOperandKind.k_reg: case OpCodeOperandKind.kp1_reg: case OpCodeOperandKind.k_rm: case OpCodeOperandKind.k_vvvv: case OpCodeOperandKind.mm_reg: case OpCodeOperandKind.mm_rm: case OpCodeOperandKind.xmm_reg: case OpCodeOperandKind.xmm_rm: case OpCodeOperandKind.xmm_vvvv: case OpCodeOperandKind.xmmp3_vvvv: case OpCodeOperandKind.xmm_is4: case OpCodeOperandKind.xmm_is5: case OpCodeOperandKind.ymm_reg: case OpCodeOperandKind.ymm_rm: case OpCodeOperandKind.ymm_vvvv: case OpCodeOperandKind.ymm_is4: case OpCodeOperandKind.ymm_is5: case OpCodeOperandKind.zmm_reg: case OpCodeOperandKind.zmm_rm: case OpCodeOperandKind.zmm_vvvv: case OpCodeOperandKind.zmmp3_vvvv: case OpCodeOperandKind.cr_reg: case OpCodeOperandKind.dr_reg: case OpCodeOperandKind.tr_reg: case OpCodeOperandKind.es: case OpCodeOperandKind.cs: case OpCodeOperandKind.ss: case OpCodeOperandKind.ds: case OpCodeOperandKind.fs: case OpCodeOperandKind.gs: case OpCodeOperandKind.al: case OpCodeOperandKind.cl: case OpCodeOperandKind.ax: case OpCodeOperandKind.dx: case OpCodeOperandKind.eax: case OpCodeOperandKind.rax: case OpCodeOperandKind.sti_opcode: case OpCodeOperandKind.imm2_m2z: case OpCodeOperandKind.imm8: case OpCodeOperandKind.imm8_const_1: case OpCodeOperandKind.imm8sex16: case OpCodeOperandKind.imm8sex32: case OpCodeOperandKind.imm8sex64: case OpCodeOperandKind.imm16: case OpCodeOperandKind.imm32: case OpCodeOperandKind.imm32sex64: case OpCodeOperandKind.imm64: case OpCodeOperandKind.seg_rDI: case OpCodeOperandKind.br16_1: case OpCodeOperandKind.br32_1: case OpCodeOperandKind.br64_1: case OpCodeOperandKind.br16_2: case OpCodeOperandKind.br32_4: case OpCodeOperandKind.br64_4: case OpCodeOperandKind.xbegin_2: case OpCodeOperandKind.xbegin_4: case OpCodeOperandKind.brdisp_2: case OpCodeOperandKind.brdisp_4: break; case OpCodeOperandKind.seg_rSI: case OpCodeOperandKind.es_rDI: case OpCodeOperandKind.seg_rBX_al: // string instructions, xlat opCount = 0; break; default: throw new InvalidOperationException(); } } }
public ILStructure(MethodBody body) : this(ILStructureType.Root, 0, body.CodeSize) { // Build the tree of exception structures: for (int i = 0; i < body.ExceptionHandlers.Count; i++) { ExceptionHandler eh = body.ExceptionHandlers[i]; if (!body.ExceptionHandlers.Take(i).Any(oldEh => oldEh.TryStart == eh.TryStart && oldEh.TryEnd == eh.TryEnd)) { AddNestedStructure(new ILStructure(ILStructureType.Try, eh.TryStart.Offset, eh.TryEnd.Offset, eh)); } if (eh.HandlerType == ExceptionHandlerType.Filter) { AddNestedStructure(new ILStructure(ILStructureType.Filter, eh.FilterStart.Offset, eh.HandlerStart.Offset, eh)); } AddNestedStructure(new ILStructure(ILStructureType.Handler, eh.HandlerStart.Offset, eh.HandlerEnd == null ? body.CodeSize : eh.HandlerEnd.Offset, eh)); } // Very simple loop detection: look for backward branches List <KeyValuePair <Instruction, Instruction> > allBranches = FindAllBranches(body); // We go through the branches in reverse so that we find the biggest possible loop boundary first (think loops with "continue;") for (int i = allBranches.Count - 1; i >= 0; i--) { int loopEnd = allBranches[i].Key.GetEndOffset(); int loopStart = allBranches[i].Value.Offset; if (loopStart < loopEnd) { // We found a backward branch. This is a potential loop. // Check that is has only one entry point: Instruction entryPoint = null; // entry point is first instruction in loop if prev inst isn't an unconditional branch Instruction prev = allBranches[i].Value.Previous; if (prev != null && !OpCodeInfo.IsUnconditionalBranch(prev.OpCode)) { entryPoint = allBranches[i].Value; } bool multipleEntryPoints = false; foreach (var pair in allBranches) { if (pair.Key.Offset < loopStart || pair.Key.Offset >= loopEnd) { if (loopStart <= pair.Value.Offset && pair.Value.Offset < loopEnd) { // jump from outside the loop into the loop if (entryPoint == null) { entryPoint = pair.Value; } else if (pair.Value != entryPoint) { multipleEntryPoints = true; } } } } if (!multipleEntryPoints) { AddNestedStructure(new ILStructure(ILStructureType.Loop, loopStart, loopEnd, entryPoint)); } } } SortChildren(); }
/// <summary> /// Is the register with the given index being assigned a value in this instruction? /// </summary> public bool IsDestinationRegister(int index) { var info = OpCodeInfo.Get(Code.ToDex()); return((info.GetUsage(index) & RegisterFlags.Destination) == RegisterFlags.Destination); }
public void WriteReference(OpCodeInfo opCode) { Write(opCode.Name); }
public void WriteReference(OpCodeInfo opCode, bool omitSuffix = false) { actions.Add(target => target.WriteReference(opCode)); }
/// <summary> /// Transform the given body. /// </summary> public void Transform(Dex target, MethodBody body) { // Build the control flow graph var cfg = new ControlFlowGraph(body); // Go over each block to find registers that are initialized and may need initialization foreach (var iterator in cfg) { var block = iterator; var data = new BasicBlockData(block); block.Tag = data; // Go over all instructions in the block, finding source/destination registers foreach (var ins in block.Instructions) { var info = OpCodeInfo.Get(ins.Code.ToDex()); var count = ins.Registers.Count; for (var i = 0; i < count; i++) { var reg = ins.Registers[i]; if (reg.Category != RCategory.Argument) { var flags = info.GetUsage(i); if (flags.HasFlag(RegisterFlags.Source)) { // Must be initialize if (!data.Initialized.Contains(reg)) { data.MayNeedInitialization.Add(reg); } } if (flags.HasFlag(RegisterFlags.Destination)) { // Destination data.Initialized.Add(reg); } } } } } // Go over all blocks to collect the register that really need initialization var needInitialization = new HashSet <Register>(); foreach (var iterator in cfg) { var block = iterator; var data = (BasicBlockData)block.Tag; foreach (var regIterator in data.MayNeedInitialization) { // Short cut var reg = regIterator; if (needInitialization.Contains(reg)) { continue; } // If the register is initialized in all entry blocks, we do not need to initialize it if (block.EntryBlocks.Select(x => (BasicBlockData)x.Tag).Any(x => !x.IsInitialized(reg))) { // There is an entry block that does not initialize the register, so we have to initialize it needInitialization.Add(reg); } } } var index = 0; Register valueReg = null; Register objectReg = null; Register wideReg = null; var firstSourceLocation = body.Instructions[0].SequencePoint; foreach (var reg in needInitialization.OrderBy(x => x.Index)) { switch (reg.Type) { case RType.Value: if (valueReg == null) { body.Instructions.Insert(index++, new Instruction(RCode.Const, 0, new[] { reg }) { SequencePoint = firstSourceLocation }); valueReg = reg; } else if (valueReg != reg) { body.Instructions.Insert(index++, new Instruction(RCode.Move, reg, valueReg) { SequencePoint = firstSourceLocation }); } break; case RType.Object: if (objectReg == null) { body.Instructions.Insert(index++, new Instruction(RCode.Const, 0, new[] { reg }) { SequencePoint = firstSourceLocation }); objectReg = reg; } else if (objectReg != reg) { body.Instructions.Insert(index++, new Instruction(RCode.Move_object, reg, objectReg) { SequencePoint = firstSourceLocation }); } break; case RType.Wide: if (wideReg == null) { body.Instructions.Insert(index++, new Instruction(RCode.Const_wide, 0, new[] { reg }) { SequencePoint = firstSourceLocation }); wideReg = reg; } else if (wideReg != reg) { body.Instructions.Insert(index++, new Instruction(RCode.Move_wide, reg, wideReg) { SequencePoint = firstSourceLocation }); } break; } } }
public InstructionFormatter(OpCodeInfo opCode, InstrStrFmtOption fmtOption, StringBuilder sb) { this.opCode = opCode; this.sb = sb; noVecIndex = false; swapVecIndex12 = false; noGprSuffix = false; startOpIndex = 0; bnd_count = 0; r32_count = 0; r64_count = 0; r32_index = 0; r64_index = 0; k_index = 0; vec_index = 0; tmm_index = 0; bnd_index = 0; opCount = opCode.OpCount; opMaskIsK1 = false; switch (fmtOption) { case InstrStrFmtOption.None: break; case InstrStrFmtOption.OpMaskIsK1_or_NoGprSuffix: opMaskIsK1 = true; noGprSuffix = true; break; case InstrStrFmtOption.IncVecIndex: vec_index++; break; case InstrStrFmtOption.NoVecIndex: noVecIndex = true; break; case InstrStrFmtOption.SwapVecIndex12: swapVecIndex12 = true; break; case InstrStrFmtOption.SkipOp0: startOpIndex = 1; break; default: throw new InvalidOperationException(); } if ((opCode.Op0Kind == OpCodeOperandKind.k_reg || opCode.Op0Kind == OpCodeOperandKind.kp1_reg) && opCode.OpCount > 2) { vec_index++; } for (int i = 0; i < opCode.OpCount; i++) { switch (opCode.GetOpKind(i)) { case OpCodeOperandKind.r32_reg: case OpCodeOperandKind.r32_reg_mem: case OpCodeOperandKind.r32_rm: case OpCodeOperandKind.r32_opcode: case OpCodeOperandKind.r32_vvvv: r32_count++; break; case OpCodeOperandKind.r64_reg: case OpCodeOperandKind.r64_reg_mem: case OpCodeOperandKind.r64_rm: case OpCodeOperandKind.r64_opcode: case OpCodeOperandKind.r64_vvvv: r64_count++; break; case OpCodeOperandKind.bnd_or_mem_mpx: case OpCodeOperandKind.bnd_reg: bnd_count++; break; case OpCodeOperandKind.None: case OpCodeOperandKind.farbr2_2: case OpCodeOperandKind.farbr4_2: case OpCodeOperandKind.mem_offs: case OpCodeOperandKind.mem: case OpCodeOperandKind.mem_mpx: case OpCodeOperandKind.mem_mib: case OpCodeOperandKind.mem_vsib32x: case OpCodeOperandKind.mem_vsib64x: case OpCodeOperandKind.mem_vsib32y: case OpCodeOperandKind.mem_vsib64y: case OpCodeOperandKind.mem_vsib32z: case OpCodeOperandKind.mem_vsib64z: case OpCodeOperandKind.r8_or_mem: case OpCodeOperandKind.r16_or_mem: case OpCodeOperandKind.r32_or_mem: case OpCodeOperandKind.r32_or_mem_mpx: case OpCodeOperandKind.r64_or_mem: case OpCodeOperandKind.r64_or_mem_mpx: case OpCodeOperandKind.mm_or_mem: case OpCodeOperandKind.xmm_or_mem: case OpCodeOperandKind.ymm_or_mem: case OpCodeOperandKind.zmm_or_mem: case OpCodeOperandKind.k_or_mem: case OpCodeOperandKind.r8_reg: case OpCodeOperandKind.r8_opcode: case OpCodeOperandKind.r16_reg: case OpCodeOperandKind.r16_reg_mem: case OpCodeOperandKind.r16_rm: case OpCodeOperandKind.r16_opcode: case OpCodeOperandKind.seg_reg: case OpCodeOperandKind.k_reg: case OpCodeOperandKind.kp1_reg: case OpCodeOperandKind.k_rm: case OpCodeOperandKind.k_vvvv: case OpCodeOperandKind.mm_reg: case OpCodeOperandKind.mm_rm: case OpCodeOperandKind.xmm_reg: case OpCodeOperandKind.xmm_rm: case OpCodeOperandKind.xmm_vvvv: case OpCodeOperandKind.xmmp3_vvvv: case OpCodeOperandKind.xmm_is4: case OpCodeOperandKind.xmm_is5: case OpCodeOperandKind.ymm_reg: case OpCodeOperandKind.ymm_rm: case OpCodeOperandKind.ymm_vvvv: case OpCodeOperandKind.ymm_is4: case OpCodeOperandKind.ymm_is5: case OpCodeOperandKind.zmm_reg: case OpCodeOperandKind.zmm_rm: case OpCodeOperandKind.zmm_vvvv: case OpCodeOperandKind.zmmp3_vvvv: case OpCodeOperandKind.cr_reg: case OpCodeOperandKind.dr_reg: case OpCodeOperandKind.tr_reg: case OpCodeOperandKind.es: case OpCodeOperandKind.cs: case OpCodeOperandKind.ss: case OpCodeOperandKind.ds: case OpCodeOperandKind.fs: case OpCodeOperandKind.gs: case OpCodeOperandKind.al: case OpCodeOperandKind.cl: case OpCodeOperandKind.ax: case OpCodeOperandKind.dx: case OpCodeOperandKind.eax: case OpCodeOperandKind.rax: case OpCodeOperandKind.st0: case OpCodeOperandKind.sti_opcode: case OpCodeOperandKind.imm2_m2z: case OpCodeOperandKind.imm8: case OpCodeOperandKind.imm8_const_1: case OpCodeOperandKind.imm8sex16: case OpCodeOperandKind.imm8sex32: case OpCodeOperandKind.imm8sex64: case OpCodeOperandKind.imm16: case OpCodeOperandKind.imm32: case OpCodeOperandKind.imm32sex64: case OpCodeOperandKind.imm64: case OpCodeOperandKind.seg_rDI: case OpCodeOperandKind.br16_1: case OpCodeOperandKind.br32_1: case OpCodeOperandKind.br64_1: case OpCodeOperandKind.br16_2: case OpCodeOperandKind.br32_4: case OpCodeOperandKind.br64_4: case OpCodeOperandKind.xbegin_2: case OpCodeOperandKind.xbegin_4: case OpCodeOperandKind.brdisp_2: case OpCodeOperandKind.brdisp_4: case OpCodeOperandKind.sibmem: case OpCodeOperandKind.tmm_reg: case OpCodeOperandKind.tmm_rm: case OpCodeOperandKind.tmm_vvvv: break; case OpCodeOperandKind.seg_rSI: case OpCodeOperandKind.es_rDI: case OpCodeOperandKind.seg_rBX_al: // string instructions, xlat opCount = 0; break; default: throw new InvalidOperationException(); } } }
/// <summary> /// Is the register with the given index being assigned a value in this instruction? /// </summary> public bool IsSourceRegister(int index) { var info = OpCodeInfo.Get(Code.ToDex()); return((info.GetUsage(index) & RegisterFlags.Source) == RegisterFlags.Source); }