public unsafe static uint Size(AnyInstruction *pInstr, uint bcv) { switch (pInstr->Kind(bcv)) { case InstructionKind.SingleType: case InstructionKind.DoubleType: case InstructionKind.Goto: case InstructionKind.Break: case InstructionKind.Environment: return(1); case InstructionKind.Call: case InstructionKind.Set: return(2); case InstructionKind.Push: // 0xF? var pui = (PushInstruction *)pInstr; switch (pui->Type) { case DataType.Int16: return(1); case DataType.Variable: return(2); default: return(pui->Type.Size() / sizeof(uint) + 1); } default: return(0); } }
static CodeBlock[] SplitBlocks(CodeInfo code, uint bcv) { var blocks = new List <CodeBlock>(); var instr = code.Instructions; var jumpTo = FindJumpOffsets(code, bcv); for (int i = 0; i < jumpTo.Length; i++) { var instrs = new List <IntPtr>(); var br = jumpTo[i]; var ind = Utils.IndexOfPtr(instr, br); AnyInstruction *nextAddr = null; for (var j = ind; j != -1 && j < instr.Length; j++) { var ins = instr[j]; if (i != jumpTo.Length - 1 && ins == jumpTo[i + 1]) // sorted { nextAddr = ins; break; } instrs.Add((IntPtr)ins); } if (instrs.Count == 0) { continue; } if (i == jumpTo.Length - 1 && br > instr[instr.Length - 1]) // implicit 'ret' after last instruction { blocks.Add(new CodeBlock { Instructions = Utils.MPtrListToPtrArr(instrs), BranchTo = null, Type = BranchType.Unconditional }); } else { var lastI = (AnyInstruction *)(instrs[instrs.Count - 1]); blocks.Add(new CodeBlock { Instructions = Utils.MPtrListToPtrArr(instrs), BranchTo = lastI->Kind(bcv) == InstructionKind.Goto ? (AnyInstruction *)((long)lastI + lastI->Goto.Offset * 4L) : nextAddr /* can be null */, Type = lastI->Kind(bcv) == InstructionKind.Goto ? lastI->Goto.Type(bcv) : BranchType.Unconditional }); } } return(blocks.ToArray()); }
public static AnyInstruction *[] MPtrListToPtrArr(IList <IntPtr> l) { var r = new AnyInstruction *[l.Count]; for (int i = 0; i < r.Length; i++) { r[i] = (AnyInstruction *)l[i]; } return(r); }
public static int IndexOfPtr(AnyInstruction *[] arr, AnyInstruction *elem) { for (int i = 0; i < arr.Length; i++) { if (elem == arr[i]) { return(i); } } return(-1); }
public unsafe static uint Size(AnyInstruction *pInstr, uint bcv) { switch (pInstr->Kind(bcv)) { case InstructionKind.SingleType: case InstructionKind.DoubleType: case InstructionKind.Goto: case InstructionKind.Break: case InstructionKind.Environment: return(1); case InstructionKind.Call: return(2); case InstructionKind.Set: if (*(uint *)pInstr == SetArrayMagic) // some magic number that has something to do with arrays { return(1); } return(2); case InstructionKind.Push: // 0xF? var pui = (PushInstruction *)pInstr; switch (pui->Type) { case DataType.Int16: return(1); case DataType.Variable: return(2); default: return(pui->Type.Size() / sizeof(uint) + 1); } default: return(0); } }
static AnyInstruction*[] FindJumpOffsets(CodeInfo code) { var blocks = new List<CodeBlock>(); var instr = code.Instructions; var ret = new List<IntPtr>(); ret.Add((IntPtr)instr[0]); for (int i = 0; i < instr.Length; i++) { var ins = instr[i]; if (ins->Kind() == InstructionKind.Goto) { IntPtr p; // instructions after a 'goto' if (i < instr.Length - 1) { p = (IntPtr)instr[i + 1]; if (!ret.Contains(p)) ret.Add(p); } // goto targets p = (IntPtr)((long)ins + ins->Goto.Offset * 4L); if (!ret.Contains(p)) ret.Add(p); } } ret.Sort(Utils.ComparePtrs); var ret_ = new AnyInstruction*[ret.Count]; for (int i = 0; i < ret_.Length; i++) ret_[i] = (AnyInstruction*)ret[i]; return ret_; }