public static unsafe DecomposedInstruction FromUnsafe(DecomposedInstructionStruct* srcInst) { var di = new DecomposedInstruction { Address = srcInst->Address, Flags = srcInst->Flags, Size = srcInst->Size, _segment = srcInst->segment, Base = srcInst->ibase, Scale = srcInst->scale, Opcode = srcInst->Opcode, UnusedPrefixesMask = srcInst->UnusedPrefixesMask, Meta = srcInst->meta, RegistersMask = srcInst->UsedRegistersMask, ModifiedFlagsMask = srcInst->modifiedFlagsMask, TestedFlagsMask = srcInst->testedFlagsMask, UndefinedFlagsMask = srcInst->undefinedFlagsMask }; /* Simple fields: */ /* Immediate variant. */ var immVariant = new ImmVariant { ImmediateValue = srcInst->ImmediateValue, Size = 0 }; /* The size of the immediate is in one of the operands, if at all. Look for it below. Zero by default. */ /* Count operands. */ var operandsNo = 0; for (operandsNo = 0; operandsNo < DecomposedInstructionStruct.OPERANDS_NO; operandsNo++) { if (srcInst->Operands[operandsNo].Type == OperandType.None) break; } var ops = new Operand[operandsNo]; for (var j = 0; j < operandsNo; j++) { var srcOp = srcInst->Operands[j]; if (srcOp.Type == OperandType.Immediate) { /* Set the size of the immediate operand. */ immVariant.Size = srcInst->Operands[j].Size; } var op = new Operand { Type = srcOp.Type, Index = srcOp.index, Size = srcOp.Size }; ops[j] = op; } di.Operands = ops; /* Attach the immediate variant. */ di.ImmediateValue = immVariant; /* Displacement variant. */ var disp = new DispVariant { Displacement = srcInst->Displacement, Size = srcInst->dispSize }; di.Displacement = disp; return di; }
public static unsafe void Decompose(CodeInfo nci, DecomposedResult ndr) { _CodeInfo* ci = null; _DInst* insts = null; var gch = new GCHandle(); var usedInstructionsCount = 0; try { if ((ci = AcquireCodeInfoStruct(nci, out gch)) == null) throw new OutOfMemoryException(); var maxInstructions = ndr.MaxInstructions; if ((insts = (_DInst*) Malloc(maxInstructions*sizeof (_DInst))) == null) throw new OutOfMemoryException(); distorm_decompose64(ci, insts, maxInstructions, &usedInstructionsCount); var dinsts = new DecomposedInst[usedInstructionsCount]; for (var i = 0; i < usedInstructionsCount; i++) { var di = new DecomposedInst { Address = insts[i].addr, Flags = insts[i].flags, Size = insts[i].size, _segment = insts[i].segment, Base = insts[i].ibase, Scale = insts[i].scale, Opcode = (Opcode) insts[i].opcode, UnusedPrefixesMask = insts[i].unusedPrefixesMask, Meta = insts[i].meta, RegistersMask = insts[i].usedRegistersMask, ModifiedFlagsMask = insts[i].modifiedFlagsMask, TestedFlagsMask = insts[i].testedFlagsMask, UndefinedFlagsMask = insts[i].undefinedFlagsMask }; /* Simple fields: */ /* Immediate variant. */ var immVariant = new DecomposedInst.ImmVariant { Imm = insts[i].imm.qword, Size = 0 }; /* The size of the immediate is in one of the operands, if at all. Look for it below. Zero by default. */ /* Count operands. */ var operandsNo = 0; for (operandsNo = 0; operandsNo < _DInst.OPERANDS_NO; operandsNo++) { if (insts[i].ops[operandsNo].type == OperandType.None) break; } var ops = new Operand[operandsNo]; for (var j = 0; j < operandsNo; j++) { if (insts[i].ops[j].type == OperandType.Imm) { /* Set the size of the immediate operand. */ immVariant.Size = insts[i].ops[j].size; } var op = new Operand { Type = insts[i].ops[j].type, Index = insts[i].ops[j].index, Size = insts[i].ops[j].size }; ops[j] = op; } di.Operands = ops; /* Attach the immediate variant. */ di.Imm = immVariant; /* Displacement variant. */ var disp = new DecomposedInst.DispVariant { Displacement = insts[i].disp, Size = insts[i].dispSize }; di.Disp = disp; dinsts[i] = di; } ndr.Instructions = dinsts; } finally { if (gch.IsAllocated) gch.Free(); if (ci != null) Free(ci); if (insts != null) Free(insts); } }