/// <summary> /// Replaces the placeholder call in method with actual instruction sequence. /// </summary> /// <param name="method">The methodto process.</param> /// <param name="repl">The function replacing the argument of placeholder call with actual instruction sequence.</param> public static void ReplacePlaceholder(MethodDef method, Func<Instruction[], Instruction[]> repl) { MethodTrace trace = new MethodTrace(method).Trace(); for (int i = 0; i < method.Body.Instructions.Count; i++) { Instruction instr = method.Body.Instructions[i]; if (instr.OpCode == OpCodes.Call) { var operand = (IMethod)instr.Operand; if (operand.DeclaringType.FullName == mutationType && operand.Name == "Placeholder") { int[] argIndexes = trace.TraceArguments(instr); if (argIndexes == null) throw new ArgumentException("Failed to trace placeholder argument."); int argIndex = argIndexes[0]; Instruction[] arg = method.Body.Instructions.Skip(argIndex).Take(i - argIndex).ToArray(); for (int j = 0; j < arg.Length; j++) method.Body.Instructions.RemoveAt(argIndex); method.Body.Instructions.RemoveAt(argIndex); arg = repl(arg); for (int j = arg.Length - 1; j >= 0; j--) method.Body.Instructions.Insert(argIndex, arg[j]); return; } } } }
/// <inheritdoc /> public MethodTrace Trace(MethodDef method) { if (method == null) throw new ArgumentNullException("method"); return cache.GetValueOrDefaultLazy(method, m => cache[m] = new MethodTrace(m)).Trace(); }
LinkedList<Instruction[]> SpiltStatements(InstrBlock block, MethodTrace trace, CFContext ctx) { var statements = new LinkedList<Instruction[]>(); var currentStatement = new List<Instruction>(); for (int i = 0; i < block.Instructions.Count; i++) { Instruction instr = block.Instructions[i]; currentStatement.Add(instr); bool nextIsBrTarget = i + 1 < block.Instructions.Count && trace.IsBranchTarget(trace.OffsetToIndexMap(block.Instructions[i + 1].Offset)); if ((instr.OpCode.OpCodeType != OpCodeType.Prefix && trace.AfterStackDepths[trace.OffsetToIndexMap(instr.Offset)] == 0) && (nextIsBrTarget || ctx.Intensity > ctx.Random.NextDouble())) { statements.AddLast(currentStatement.ToArray()); currentStatement.Clear(); } } if (currentStatement.Count > 0) statements.AddLast(currentStatement.ToArray()); return statements; }