LinkedList <Instruction[]> SpiltStatements(InstrBlock block, Trace trace, CFContext ctx) { var statements = new LinkedList <Instruction[]>(); var currentStatement = new List <Instruction>(); // Instructions that must be included in the ccurrent statement to ensure all outgoing // branches have stack = 0 var requiredInstr = new HashSet <Instruction>(); for (int i = 0; i < block.Instructions.Count; i++) { Instruction instr = block.Instructions[i]; currentStatement.Add(instr); bool shouldSpilt = i + 1 < block.Instructions.Count && trace.HasMultipleSources(block.Instructions[i + 1].Offset); switch (instr.OpCode.FlowControl) { case FlowControl.Branch: case FlowControl.Cond_Branch: case FlowControl.Return: case FlowControl.Throw: shouldSpilt = true; if (trace.AfterStack[instr.Offset] != 0) { if (instr.Operand is Instruction) { requiredInstr.Add((Instruction)instr.Operand); } else if (instr.Operand is Instruction[]) { foreach (var target in (Instruction[])instr.Operand) { requiredInstr.Add(target); } } } break; } requiredInstr.Remove(instr); if ((instr.OpCode.OpCodeType != OpCodeType.Prefix && trace.AfterStack[instr.Offset] == 0 && requiredInstr.Count == 0) && (shouldSpilt || ctx.Intensity > ctx.Random.NextDouble())) { statements.AddLast(currentStatement.ToArray()); currentStatement.Clear(); } } if (currentStatement.Count > 0) { statements.AddLast(currentStatement.ToArray()); } return(statements); }
LinkedList <Instruction[]> SpiltFragments(InstrBlock block, CFContext ctx) { var fragments = new LinkedList <Instruction[]>(); var currentFragment = new List <Instruction>(); int skipCount = -1; for (int i = 0; i < block.Instructions.Count; i++) { if (skipCount != -1) { if (skipCount > 0) { currentFragment.Add(block.Instructions[i]); skipCount--; continue; } fragments.AddLast(currentFragment.ToArray()); currentFragment.Clear(); skipCount = -1; } if (block.Instructions[i].OpCode.OpCodeType == OpCodeType.Prefix) { skipCount = 1; currentFragment.Add(block.Instructions[i]); } if (i + 2 < block.Instructions.Count && block.Instructions[i + 0].OpCode.Code == Code.Dup && block.Instructions[i + 1].OpCode.Code == Code.Ldvirtftn && block.Instructions[i + 2].OpCode.Code == Code.Newobj) { skipCount = 2; currentFragment.Add(block.Instructions[i]); } if (i + 4 < block.Instructions.Count && block.Instructions[i + 0].OpCode.Code == Code.Ldc_I4 && block.Instructions[i + 1].OpCode.Code == Code.Newarr && block.Instructions[i + 2].OpCode.Code == Code.Dup && block.Instructions[i + 3].OpCode.Code == Code.Ldtoken && block.Instructions[i + 4].OpCode.Code == Code.Call) // Array initializer { skipCount = 4; currentFragment.Add(block.Instructions[i]); } if (i + 1 < block.Instructions.Count && block.Instructions[i + 0].OpCode.Code == Code.Ldftn && block.Instructions[i + 1].OpCode.Code == Code.Newobj) { skipCount = 1; currentFragment.Add(block.Instructions[i]); } currentFragment.Add(block.Instructions[i]); if (ctx.Intensity > ctx.Random.NextDouble()) { fragments.AddLast(currentFragment.ToArray()); currentFragment.Clear(); } } if (currentFragment.Count > 0) { fragments.AddLast(currentFragment.ToArray()); } return(fragments); }
public static ScopeBlock ParseBody(CilBody body) { var ehScopes = new Dictionary <ExceptionHandler, Tuple <ScopeBlock, ScopeBlock, ScopeBlock> >(); foreach (ExceptionHandler eh in body.ExceptionHandlers) { var tryBlock = new ScopeBlock(BlockType.Try, eh); var handlerType = BlockType.Handler; if (eh.HandlerType == ExceptionHandlerType.Finally) { handlerType = BlockType.Finally; } else if (eh.HandlerType == ExceptionHandlerType.Fault) { handlerType = BlockType.Fault; } var handlerBlock = new ScopeBlock(handlerType, eh); if (eh.FilterStart != null) { var filterBlock = new ScopeBlock(BlockType.Filter, eh); ehScopes[eh] = Tuple.Create(tryBlock, handlerBlock, filterBlock); } else { ehScopes[eh] = Tuple.Create(tryBlock, handlerBlock, (ScopeBlock)null); } } var root = new ScopeBlock(BlockType.Normal, null); var scopeStack = new Stack <ScopeBlock>(); scopeStack.Push(root); foreach (Instruction instr in body.Instructions) { foreach (ExceptionHandler eh in body.ExceptionHandlers) { Tuple <ScopeBlock, ScopeBlock, ScopeBlock> ehScope = ehScopes[eh]; if (instr == eh.TryEnd) { scopeStack.Pop(); } if (instr == eh.HandlerEnd) { scopeStack.Pop(); } if (eh.FilterStart != null && instr == eh.HandlerStart) { // Filter must precede handler immediately Debug.Assert(scopeStack.Peek().Type == BlockType.Filter); scopeStack.Pop(); } } foreach (ExceptionHandler eh in body.ExceptionHandlers.Reverse()) { Tuple <ScopeBlock, ScopeBlock, ScopeBlock> ehScope = ehScopes[eh]; ScopeBlock parent = scopeStack.Count > 0 ? scopeStack.Peek() : null; if (instr == eh.TryStart) { if (parent != null) { parent.Children.Add(ehScope.Item1); } scopeStack.Push(ehScope.Item1); } if (instr == eh.HandlerStart) { if (parent != null) { parent.Children.Add(ehScope.Item2); } scopeStack.Push(ehScope.Item2); } if (instr == eh.FilterStart) { if (parent != null) { parent.Children.Add(ehScope.Item3); } scopeStack.Push(ehScope.Item3); } } ScopeBlock scope = scopeStack.Peek(); var block = scope.Children.LastOrDefault() as InstrBlock; if (block == null) { scope.Children.Add(block = new InstrBlock()); } block.Instructions.Add(instr); } foreach (ExceptionHandler eh in body.ExceptionHandlers) { if (eh.TryEnd == null) { scopeStack.Pop(); } if (eh.HandlerEnd == null) { scopeStack.Pop(); } } Debug.Assert(scopeStack.Count == 1); return(root); }