public void VisitInstruction(TypedInstruction instruction) { if (m_offset < 0) { m_offset = NullCheck.Check <NullDerefRule>(instruction, m_info.Tracker, out m_details); } }
// 02: call System.Int32 System.Array::IndexOf<*>(!!0[],!!0) // 07: stloc.N V_0 // 08: ldc.i4.0 // 09: ldloc.N V_0 // 0A: bge 1E private bool DoMatch3(int index) { bool match = false; do { if (index - 4 < 0) { break; } TypedInstruction instruction = m_info.Instructions[index - 0]; Code code = instruction.Untyped.OpCode.Code; if (code != Code.Bge_S && code != Code.Bge_Un_S && code != Code.Bge && code != Code.Bge_Un) { break; } instruction = m_info.Instructions[index - 1]; code = instruction.Untyped.OpCode.Code; if (code != Code.Ldloc_S && code != Code.Ldloc && code != Code.Ldloc_0 && code != Code.Ldloc_1 && code != Code.Ldloc_2 && code != Code.Ldloc_3) { break; } int varN = ((LoadLocal)instruction).Variable; instruction = m_info.Instructions[index - 2]; code = instruction.Untyped.OpCode.Code; if (code != Code.Ldc_I4_0) { break; } instruction = m_info.Instructions[index - 3]; code = instruction.Untyped.OpCode.Code; if (code != Code.Stloc_S && code != Code.Stloc && code != Code.Stloc_0 && code != Code.Stloc_1 && code != Code.Stloc_2 && code != Code.Stloc_3) { break; } if (varN != ((StoreLocal)instruction).Variable) { break; } instruction = m_info.Instructions[index - 4]; code = instruction.Untyped.OpCode.Code; if (code != Code.Call && code != Code.Callvirt) { break; } if (!((Call)instruction).Target.ToString().StartsWith("System.Int32 System.Array::IndexOf<") || !((Call)instruction).Target.ToString().EndsWith(">(!!0[],!!0)")) { break; } match = true; }while (false); return(match); }
private void DoCheck(TypedInstruction binary) { if (binary.Index >= 2) { int rhsEnd = binary.Index - 1; int rhsStart = rhsEnd - DoGetPushRange(m_info, rhsEnd); int lhsEnd = rhsStart - 1; int lhsStart = lhsEnd - DoGetPushRange(m_info, lhsEnd); Log.DebugLine(this, "{0} at {1:X}", binary.Untyped.OpCode.Code, binary.Untyped.Offset); Log.DebugLine(this, " lhs range: [{0:X}, {1:X}]", m_info.Instructions[lhsStart].Untyped.Offset, m_info.Instructions[lhsEnd].Untyped.Offset); Log.DebugLine(this, " rhs range: [{0:X}, {1:X}]", m_info.Instructions[rhsStart].Untyped.Offset, m_info.Instructions[rhsEnd].Untyped.Offset); bool matches = (rhsEnd - rhsStart) == (lhsEnd - lhsStart); for (int i = 0; i <= (rhsEnd - rhsStart) && matches; ++i) { TypedInstruction lhs = m_info.Instructions[lhsStart + i]; TypedInstruction rhs = m_info.Instructions[rhsStart + i]; matches = lhs.Untyped.Matches(rhs.Untyped); } if (matches) { m_offset = binary.Untyped.Offset; } } }
[DisableRule("D1042", "IdenticalMethods")] // TODO: matches RecursiveLock2Rule private bool DoMatchLock2(int index) { bool match = false; do { if (index - 4 < 0 || index >= m_info.Instructions.Length) { break; } TypedInstruction instruction = m_info.Instructions[index - 0]; Code code = instruction.Untyped.OpCode.Code; if (code != Code.Call && code != Code.Callvirt) { break; } if (((Call)instruction).Target.ToString() != "System.Void System.Threading.Monitor::Enter(System.Object)") { break; } instruction = m_info.Instructions[index - 1]; code = instruction.Untyped.OpCode.Code; if (code != Code.Ldloc_S && code != Code.Ldloc && code != Code.Ldloc_0 && code != Code.Ldloc_1 && code != Code.Ldloc_2 && code != Code.Ldloc_3) { break; } int varN = ((LoadLocal)instruction).Variable; instruction = m_info.Instructions[index - 2]; code = instruction.Untyped.OpCode.Code; if (code != Code.Stloc_S && code != Code.Stloc && code != Code.Stloc_0 && code != Code.Stloc_1 && code != Code.Stloc_2 && code != Code.Stloc_3) { break; } if (varN != ((StoreLocal)instruction).Variable) { break; } instruction = m_info.Instructions[index - 3]; code = instruction.Untyped.OpCode.Code; if (code != Code.Ldfld) { break; } instruction = m_info.Instructions[index - 4]; code = instruction.Untyped.OpCode.Code; if (code != Code.Ldarg_0) { break; } match = true; }while (false); return(match); }
public void VisitInstruction(TypedInstruction instruction) { if (m_needsCheck && !m_foundEarlyReturn && m_offset < 0) { m_offset = NullCheck.Check <EqualsRequiresNullCheckRule>(instruction, m_tracker, out m_details); } }
// 03: callvirt System.Int32 System.String::IndexOf(System.Char) // 08: stloc.N V_0 // 09: ldc.i4.0 // 0A: ldloc.N V_0 // 0B: bge 1F private bool DoMatch5(int index) { bool match = false; do { if (index - 4 < 0) { break; } TypedInstruction instruction = m_info.Instructions[index - 0]; Code code = instruction.Untyped.OpCode.Code; if (code != Code.Bge_S && code != Code.Bge_Un_S && code != Code.Bge && code != Code.Bge_Un) { break; } instruction = m_info.Instructions[index - 1]; code = instruction.Untyped.OpCode.Code; if (code != Code.Ldloc_S && code != Code.Ldloc && code != Code.Ldloc_0 && code != Code.Ldloc_1 && code != Code.Ldloc_2 && code != Code.Ldloc_3) { break; } int varN = ((LoadLocal)instruction).Variable; instruction = m_info.Instructions[index - 2]; code = instruction.Untyped.OpCode.Code; if (code != Code.Ldc_I4_0) { break; } instruction = m_info.Instructions[index - 3]; code = instruction.Untyped.OpCode.Code; if (code != Code.Stloc_S && code != Code.Stloc && code != Code.Stloc_0 && code != Code.Stloc_1 && code != Code.Stloc_2 && code != Code.Stloc_3) { break; } if (varN != ((StoreLocal)instruction).Variable) { break; } instruction = m_info.Instructions[index - 4]; code = instruction.Untyped.OpCode.Code; if (code != Code.Callvirt && code != Code.Call) { break; } if (((Call)instruction).Target.ToString() != "System.Int32 System.String::IndexOf(System.Char)") { break; } match = true; }while (false); return(match); }
// 0E: br 27 // 13: ldsfld System.Object Smokey.Tests.UnusualMonitor1Test/Good5::m_lock // 18: call System.Boolean System.Threading.Monitor::Wait(System.Object) // 1D: box System.Boolean // 22: call System.Void Smokey.Internal.Ignore::set_Value(System.Object) private bool DoMatch2a(int index) { bool match = false; do { if (index - 4 < 0 || index >= m_info.Instructions.Length) { break; } TypedInstruction instruction = m_info.Instructions[index - 0]; Code code = instruction.Untyped.OpCode.Code; if (code != Code.Call && code != Code.Callvirt) { break; } if (((Call)instruction).Target.ToString().IndexOf("Ignore::set_Value") < 0 && ((Call)instruction).Target.ToString().IndexOf("Unused::set_Value") < 0) { break; } instruction = m_info.Instructions[index - 1]; code = instruction.Untyped.OpCode.Code; if (code != Code.Box) { break; } instruction = m_info.Instructions[index - 2]; code = instruction.Untyped.OpCode.Code; if (code != Code.Call && code != Code.Callvirt) { break; } if (((Call)instruction).Target.ToString() != "System.Boolean System.Threading.Monitor::Wait(System.Object)") { break; } instruction = m_info.Instructions[index - 3]; code = instruction.Untyped.OpCode.Code; if (code != Code.Ldsfld) { break; } instruction = m_info.Instructions[index - 4]; code = instruction.Untyped.OpCode.Code; if (code != Code.Br_S && code != Code.Br) { break; } match = true; }while (false); return(match); }
private List <int> DoGetLeaders(TypedInstructionCollection instructions) { // The leaders will be: List <int> leaders = new List <int>(); // 1) the first instruction in the method, leaders.Add(0); for (int index = 0; index < instructions.Length; ++index) { TypedInstruction instruction = instructions[index]; // 2) the targets of branches, Branch branch = instruction as Branch; if (branch != null) { m_branchTargets.Add(branch.Target.Index); } else { Switch swtch = instruction as Switch; if (swtch != null) { foreach (TypedInstruction i in swtch.Targets) { m_branchTargets.Add(i.Index); } } } if (index > 0) { // 3) and instructions starting try, catch or finally blocks, TryCatch tc = instructions.TryCatchCollection.HandlerStartsAt(index); if (tc != null) { leaders.Add(index); } // 4) the instructions following branches or end instructions. else if (instructions[index - 1] is Branch || instructions[index - 1] is Switch || instructions[index - 1] is End) { leaders.Add(index); } } } foreach (int target in m_branchTargets) { if (leaders.IndexOf(target) < 0) { leaders.Add(target); } } return(leaders); }
private int DoGetStackDelta(TypedInstruction instruction) { int delta = 0; delta += DoGetStackCount(instruction, instruction.Untyped.OpCode.StackBehaviourPush); delta -= DoGetStackCount(instruction, instruction.Untyped.OpCode.StackBehaviourPop); // Log.DebugLine(this, "{0} (delta = {1})", instruction, delta); return(delta); }
public void VisitNew(NewObj obj) { if (m_offset < 0 && obj.Index + 1 < m_info.Instructions.Length) { TypedInstruction prev = m_info.Instructions[obj.Index + 1]; if (prev.Untyped.OpCode.Code == Code.Pop) { m_offset = obj.Untyped.Offset; Log.DebugLine(this, "Matched at {0:X2}", m_offset); } } }
private static void DoSpliceEq(TypedInstructionCollection instructions, BasicBlock block) { int index = block.Last.Index; // ldloc.0 V_0 // ldnull // beq 2F LoadArg arg = null; LoadLocal local = null; if (instructions[index - 1].Untyped.OpCode.Code == Code.Ldnull) { arg = instructions[block.Last.Index - 2] as LoadArg; local = instructions[block.Last.Index - 2] as LoadLocal; } else if (instructions[index - 2].Untyped.OpCode.Code == Code.Ldnull) { arg = instructions[block.Last.Index - 1] as LoadArg; local = instructions[block.Last.Index - 1] as LoadLocal; } if (arg != null || local != null) { TypedInstruction instruction = instructions[block.Last.Index]; Code code = instruction.Untyped.OpCode.Code; if (code == Code.Bne_Un || code == Code.Bne_Un_S) { if (arg != null) { DoSpliceNull(block, FirstNullArgBlockLen - arg.Arg, FirstNonNullArgBlockLen - arg.Arg); } else { DoSpliceNull(block, FirstNullLocalBlockLen - local.Variable, FirstNonNullLocalBlockLen - local.Variable); } } else { if (arg != null) { DoSpliceNull(block, FirstNonNullArgBlockLen - arg.Arg, FirstNullArgBlockLen - arg.Arg); } else { DoSpliceNull(block, FirstNonNullLocalBlockLen - local.Variable, FirstNullLocalBlockLen - local.Variable); } } } }
private static void DoTrySpliceNull(TypedInstructionCollection instructions, BasicBlock block) { TypedInstruction instruction = instructions[block.Last.Index]; Code code = instruction.Untyped.OpCode.Code; if (code == Code.Brtrue || code == Code.Brtrue_S || code == Code.Brfalse || code == Code.Brfalse_S) { DoSpliceTrue(instructions, block); } else if (code == Code.Beq || code == Code.Beq_S || code == Code.Bne_Un || code == Code.Bne_Un_S) { DoSpliceEq(instructions, block); } }
private void DoCheck(TypedInstruction call, MethodReference target, int nth) { int index = m_info.Tracker.GetStackIndex(call.Index, nth); if (index >= 0) { LoadString load = m_info.Instructions[index] as LoadString; if (load != null) { m_offset = call.Untyped.Offset; m_bad = target.ToString(); Log.DebugLine(this, "bad call at {0:X2}", m_offset); } } }
// 08: switch 26 35 53 44 44 44 // 21: br 53 // 26: ldstr "zero" // 2B: call System.Void System.Console::WriteLine(System.String) // 30: br 53 // 35: ldstr "zero" // 3A: call System.Void System.Console::WriteLine(System.String) // 3F: br 53 // 44: ldstr "zero" // 49: call System.Void System.Console::WriteLine(System.String) // 4E: br 53 // 53: ret public void VisitSwitch(Switch swtch) { if (m_offset < 0) { UnconditionalBranch unconditional = m_info.Instructions[swtch.Index + 1] as UnconditionalBranch; if (unconditional != null && unconditional.Target.Index > unconditional.Index) { TypedInstruction last = unconditional.Target; List <TypedInstruction> cases = new List <TypedInstruction>(); foreach (TypedInstruction ti in swtch.Targets) { if (ti.Index != last.Index) { if (cases.IndexOf(ti) < 0) { cases.Add(ti); } } } cases.Add(last); cases.Sort((lhs, rhs) => lhs.Index.CompareTo(rhs.Index)); for (int i = 0; i < cases.Count - 1 && m_offset < 0; ++i) { TypedInstruction ti1 = cases[i]; int len1 = cases[i + 1].Index - ti1.Index - 1; for (int j = i + 1; j < cases.Count - 1 && m_offset < 0; ++j) { TypedInstruction ti2 = cases[j]; int len2 = cases[j + 1].Index - ti2.Index - 1; if (len1 == len2) { if (DoMatches(ti1.Index, ti2.Index, len1)) { Log.DebugLine(this, "{0:X2} matches {1:X2}", ti1.Untyped.Offset, ti2.Untyped.Offset); m_offset = swtch.Untyped.Offset; } } } } } } }
private bool DoMatch(MethodCapture lhs, MethodCapture rhs) { if (lhs.Method.ReturnType.MetadataToken != rhs.Method.ReturnType.MetadataToken) { Log.DebugLine(this, " return type differs"); return(false); } if (lhs.Method.Parameters.Count != rhs.Method.Parameters.Count) { Log.DebugLine(this, " numParams differs"); return(false); } for (int i = 0; i < lhs.Method.Parameters.Count; ++i) { if (lhs.Method.Parameters[i].ParameterType.MetadataToken != rhs.Method.Parameters[i].ParameterType.MetadataToken) { Log.DebugLine(this, " param types differ"); return(false); } } if (lhs.Instructions.Length != rhs.Instructions.Length) { Log.DebugLine(this, " numInstructions differs"); return(false); } for (int i = 0; i < lhs.Instructions.Length; ++i) { TypedInstruction left = lhs.Instructions[i]; TypedInstruction right = rhs.Instructions[i]; if (!DoMatch(left, right)) { Log.DebugLine(this, " {0} != {1} at {2:X2} and {3:X2}", left, right, left.Untyped.Offset, right.Untyped.Offset); return(false); } } return(true); }
private static string DoTargetsToString(TypedInstructionCollection instructions, List <int> targets) { StringBuilder builder = new StringBuilder(); builder.Append('['); for (int i = 0; i < targets.Count; ++i) { int index = targets[i]; TypedInstruction instruction = instructions[index]; builder.Append(instruction.Untyped.Offset.ToString("X2")); if (i + 1 < targets.Count) { builder.Append(", "); } } builder.Append(']'); return(builder.ToString()); }
// 02: call System.Int32 System.Array::IndexOf<*>(!!0[],!!0) // 09: ldc.i4.0 // 0A: cgt private bool DoMatch2b(int index) { bool match = false; do { if (index - 2 < 0) { break; } TypedInstruction instruction = m_info.Instructions[index - 0]; Code code = instruction.Untyped.OpCode.Code; if (code != Code.Cgt && code != Code.Cgt_Un) { break; } instruction = m_info.Instructions[index - 1]; code = instruction.Untyped.OpCode.Code; if (code != Code.Ldc_I4_0) { break; } instruction = m_info.Instructions[index - 2]; code = instruction.Untyped.OpCode.Code; if (code != Code.Call && code != Code.Callvirt) { break; } if (!((Call)instruction).Target.ToString().StartsWith("System.Int32 System.Array::IndexOf<") || !((Call)instruction).Target.ToString().EndsWith(">(!!0[],!!0)")) { break; } match = true; }while (false); return(match); }
// 03: callvirt System.Int32 System.String::IndexOf(System.Char) // 0A: ldc.i4.0 // 0B: cgt private bool DoMatch4b(int index) { bool match = false; do { if (index - 2 < 0) { break; } TypedInstruction instruction = m_info.Instructions[index - 0]; Code code = instruction.Untyped.OpCode.Code; if (code != Code.Cgt && code != Code.Cgt_Un) { break; } instruction = m_info.Instructions[index - 1]; code = instruction.Untyped.OpCode.Code; if (code != Code.Ldc_I4_0) { break; } instruction = m_info.Instructions[index - 2]; code = instruction.Untyped.OpCode.Code; if (code != Code.Callvirt && code != Code.Call) { break; } if (((Call)instruction).Target.ToString() != "System.Int32 System.String::IndexOf(System.Char)") { break; } match = true; }while (false); return(match); }
private static void DoSpliceTrue(TypedInstructionCollection instructions, BasicBlock block) { int index = block.Last.Index; // ldarg.1 a1 // brtrue 10 (not taken is the first branch) LoadArg arg = instructions[index - 1] as LoadArg; LoadLocal local = instructions[index - 1] as LoadLocal; if (arg != null || local != null) { TypedInstruction instruction = instructions[index]; Code code = instruction.Untyped.OpCode.Code; if (code == Code.Brtrue || code == Code.Brtrue_S) { if (arg != null) { DoSpliceNull(block, FirstNullArgBlockLen - arg.Arg, FirstNonNullArgBlockLen - arg.Arg); } else { DoSpliceNull(block, FirstNullLocalBlockLen - local.Variable, FirstNonNullLocalBlockLen - local.Variable); } } else { if (arg != null) { DoSpliceNull(block, FirstNonNullArgBlockLen - arg.Arg, FirstNullArgBlockLen - arg.Arg); } else { DoSpliceNull(block, FirstNonNullLocalBlockLen - local.Variable, FirstNullLocalBlockLen - local.Variable); } } } }
private int DoCheckCatch(TypedInstructionCollection instructions, CatchBlock cb, int varIndex) { int offset = -1; // Loop through all of the instructions in the catch block, for (int index = cb.Index; index < cb.Index + cb.Length && offset < 0; ++index) { TypedInstruction instruction = instructions[index]; // if we find a throw instruction, if (instruction.Untyped.OpCode.Code == Code.Throw) { // and it's preceded by a load from varIndex then we have a problem. LoadLocal load = instructions[index - 1] as LoadLocal; if (load != null && load.Variable == varIndex) { offset = instruction.Untyped.Offset; Log.DebugLine(this, "bad throw at {0:X2}", offset); } } } return(offset); }
private void DoCheckLoad(TypedInstruction instruction) { LoadConstantInt load = m_info.Instructions[instruction.Index - 1] as LoadConstantInt; if (load != null) { if (load.Value < 0 || load.Value > 255) { m_offset = instruction.Untyped.Offset; Log.DebugLine(this, "bad exit at {0:X2}", m_offset); } } LoadLocal local = m_info.Instructions[instruction.Index - 1] as LoadLocal; if (local != null) { Log.DebugLine(this, "{0} at {1:X2}", instruction.Untyped.OpCode, instruction.Untyped.Offset); if (m_candidateLoads.IndexOf(local.Variable) < 0) { m_candidateLoads.Add(local.Variable); } } }
private bool DoMatch(TypedInstruction lhs, TypedInstruction rhs) { if (lhs.Untyped.OpCode.Code != rhs.Untyped.OpCode.Code) { return(false); } if (lhs.Untyped.Operand != null || rhs.Untyped.Operand != null) { if (lhs.Untyped.Operand != null && rhs.Untyped.Operand != null) { if (!DoMatchOperand(lhs.Untyped.Operand, rhs.Untyped.Operand)) { return(false); } } else { return(false); } } return(true); }
private bool DoMatch(CodeBlock lhs, CodeBlock rhs, int count) { Log.DebugLine(this, " lhs: {0} at {1:X2}", lhs.Method, lhs.Instructions[lhs.Index].Untyped.Offset); Log.DebugLine(this, " rhs: {0} at {1:X2}", rhs.Method, rhs.Instructions[rhs.Index].Untyped.Offset); Log.DebugLine(this, " count: {0}", count); for (int i = 0; i < count; ++i) { TypedInstruction left = lhs.Instructions[lhs.Index + i]; TypedInstruction right = rhs.Instructions[rhs.Index + i]; LoadLocal load1 = left as LoadLocal; LoadLocal load2 = right as LoadLocal; LoadLocalAddress load1b = left as LoadLocalAddress; LoadLocalAddress load2b = right as LoadLocalAddress; StoreLocal store1 = left as StoreLocal; StoreLocal store2 = right as StoreLocal; if (load1 != null && load2 != null) { // If we have real names for the local variables (from the mdb file) then // life is good and we can compare the names. If not we're stuck: we can't // simply use the variable index because we'll get false positives. if (!load1.RealName) { Log.DebugLine(this, " can't match local name"); return(false); } // This should be a temporary in which case we can't use the variable index. else if (load1.Name.StartsWith("V_") && load1.Type.FullName != load2.Type.FullName) { Log.DebugLine(this, " {0} != {1} ({2} and {3})", left, right, load1.Type.FullName, load2.Type.FullName); return(false); } else if (!load1.Name.StartsWith("V_") && load1.Name != load2.Name) { Log.DebugLine(this, " {0} != {1} ({2} and {3})", left, right, load1.Name, load2.Name); return(false); } } else if (load1b != null && load2b != null) { if (!load1b.RealName) { Log.DebugLine(this, " can't match local name"); return(false); } else if (load1b.Name.StartsWith("V_") && load1b.Type.FullName != load2b.Type.FullName) { Log.DebugLine(this, " {0} != {1} ({2} and {3})", left, right, load1b.Type.FullName, load2b.Type.FullName); return(false); } else if (!load1b.Name.StartsWith("V_") && load1b.Name != load2b.Name) { Log.DebugLine(this, " {0} != {1} ({2} and {3})", left, right, load1b.Name, load2b.Name); return(false); } } else if (store1 != null && store2 != null) { if (!store1.RealName) { Log.DebugLine(this, " can't match local name"); return(false); } else if (store1.Name.StartsWith("V_") && store1.Type.FullName != store2.Type.FullName) { Log.DebugLine(this, " {0} != {1} ({2} and {3})", left, right, store1.Type.FullName, store2.Type.FullName); return(false); } else if (!store1.Name.StartsWith("V_") && store1.Name != store2.Name) { Log.DebugLine(this, " {0} != {1} ({2} and {3})", left, right, store1.Name, store2.Name); return(false); } } else if (!left.Untyped.Matches(right.Untyped)) { Log.DebugLine(this, " {0} != {1}", left, right); return(false); } } return(true); }
private void DoVisit(TypedInstructionCollection instructions, BasicBlock block, int lastIndex, int prevIndex, int loopIndex) { DBC.Assert(m_visited.IndexOf(block) < 0, "{0} has already been visited", block); if (block.Length < 0 || block.First.Index <= lastIndex) { // Log.DebugLine(this, "visiting {0}", block); if (block.Length > 0) { if (block.First.Index < prevIndex) { if (prevIndex > loopIndex) { loopIndex = prevIndex; } } if (block.First.Index > loopIndex) { loopIndex = int.MinValue; } // Log.DebugLine(this, "prevIndex: {0}, loopIndex: {1}", prevIndex, loopIndex); // Visit each instruction in the block, m_visited.Add(block); for (int index = block.First.Index; index <= block.Last.Index; ++index) { TypedInstruction instruction = instructions[index]; if (instruction.Untyped.OpCode.Code == Code.Call || instruction.Untyped.OpCode.Code == Code.Callvirt) { MethodReference target = (MethodReference)instruction.Untyped.Operand; m_callGraph.Add(instructions.Method, target); } m_looping = index <= loopIndex; DoVisit(instruction); } // the finally block if we have one, if (block.Finally != null && m_visited.IndexOf(block.Finally) < 0) { DoVisit(instructions, block.Finally, lastIndex, block.Last.Index, int.MinValue); } // the fault block if we have one, else if (block.Fault != null && m_visited.IndexOf(block.Fault) < 0) { DoVisit(instructions, block.Fault, lastIndex, block.Last.Index, int.MinValue); } } // and each block this block leads to. for (int index = 0; index < block.Next.Length; ++index) { if (m_visited.IndexOf(block.Next[index]) < 0) { if (block.Length > 0) { DoVisit(instructions, block.Next[index], lastIndex, block.Last.Index, loopIndex); } else { DoVisit(instructions, block.Next[index], lastIndex, prevIndex, loopIndex); } } } } }
internal BasicBlock(TypedInstruction first, TypedInstruction last) { First = first; Last = last; Length = Last.Index - First.Index + 1; }
// 0F: br 29 // 14: Ldarg.0 this // 15: ldfld System.Object Smokey.Tests.UnusualMonitor1Test/Good1::m_lock // 1A: call System.Boolean System.Threading.Monitor::Wait(System.Object) // 1F: box System.Boolean // 24: call System.Void *(System.Object) private bool DoMatch1a(int index) { bool match = false; do { if (index - 5 < 0 || index >= m_info.Instructions.Length) { break; } TypedInstruction instruction = m_info.Instructions[index - 0]; Code code = instruction.Untyped.OpCode.Code; if (code != Code.Call && code != Code.Callvirt) { break; } if (!((Call)instruction).Target.ToString().StartsWith("System.Void ") || !((Call)instruction).Target.ToString().EndsWith("(System.Object)")) { break; } instruction = m_info.Instructions[index - 1]; code = instruction.Untyped.OpCode.Code; if (code != Code.Box) { break; } instruction = m_info.Instructions[index - 2]; code = instruction.Untyped.OpCode.Code; if (code != Code.Call && code != Code.Callvirt) { break; } if (((Call)instruction).Target.ToString() != "System.Boolean System.Threading.Monitor::Wait(System.Object)") { break; } instruction = m_info.Instructions[index - 3]; code = instruction.Untyped.OpCode.Code; if (code != Code.Ldfld) { break; } instruction = m_info.Instructions[index - 4]; code = instruction.Untyped.OpCode.Code; if (code != Code.Ldarg_0) { break; } instruction = m_info.Instructions[index - 5]; code = instruction.Untyped.OpCode.Code; if (code != Code.Br_S && code != Code.Br) { break; } match = true; }while (false); return(match); }
public DetermineTypesInstruction(TypedInstruction instruction) : this(instruction.inputTypes, instruction.outputTypes) { }
private int DoGetStackCount(TypedInstruction instruction, StackBehaviour behavior) { int count = 0; switch (behavior) { case StackBehaviour.Pop0: case StackBehaviour.Push0: break; case StackBehaviour.Pop1: case StackBehaviour.Popi: case StackBehaviour.Popref: case StackBehaviour.Push1: case StackBehaviour.Pushi: case StackBehaviour.Pushi8: case StackBehaviour.Pushr4: case StackBehaviour.Pushr8: case StackBehaviour.Pushref: count = 1; break; case StackBehaviour.Pop1_pop1: case StackBehaviour.Popi_pop1: case StackBehaviour.Popi_popi: case StackBehaviour.Popi_popi8: case StackBehaviour.Popi_popr4: case StackBehaviour.Popi_popr8: case StackBehaviour.Popref_pop1: case StackBehaviour.Popref_popi: case StackBehaviour.Push1_push1: count = 2; break; case StackBehaviour.Popi_popi_popi: case StackBehaviour.Popref_popi_popi: case StackBehaviour.Popref_popi_popi8: case StackBehaviour.Popref_popi_popr4: case StackBehaviour.Popref_popi_popr8: case StackBehaviour.Popref_popi_popref: count = 3; break; case StackBehaviour.PopAll: // leave count = int.MaxValue; break; case StackBehaviour.Varpop: // call, newobj, ret Call call = instruction as Call; if (call != null) { count = call.Target.Parameters.Count + (call.Target.HasThis ? 1 : 0); } else if (instruction.Untyped.OpCode.Code == Code.Ret) { count = int.MaxValue; } else { NewObj no = instruction as NewObj; DBC.Assert(no != null, "Varpop opcode should be call, ret, or newobj"); count = no.Ctor.Parameters.Count; } break; case StackBehaviour.Varpush: // call Call call2 = instruction as Call; DBC.Assert(call2 != null, "Varpush opcode should be call"); if (call2.Target.ReturnType.ReturnType.FullName != "System.Void") { count = 1; } break; default: DBC.Fail("Bad stack behavior: {0}", behavior); break; } return(count); }
// ldarg.0 // volatile. // stsfld bool Smokey.Tests.StaticSetterTest/Static::ms_vatomic private bool DoVolatileStore(StoreStaticField store) { TypedInstruction prior = m_info.Instructions[store.Index - 1]; return(prior.Untyped.OpCode.Code == Code.Volatile); }
private bool DoIsFloat(int index) { TypedInstruction instruction = m_info.Instructions[index]; TypeReference type = null; do { LoadArg arg = instruction as LoadArg; if (arg != null && arg.Arg >= 1) { type = m_info.Method.Parameters[arg.Arg - 1].ParameterType; break; } LoadLocal local = instruction as LoadLocal; if (local != null) { type = m_info.Method.Body.Variables[local.Variable].VariableType; break; } LoadField field = instruction as LoadField; if (field != null) { type = field.Field.FieldType; break; } LoadStaticField sfield = instruction as LoadStaticField; if (sfield != null) { type = sfield.Field.FieldType; break; } LoadConstantFloat cf = instruction as LoadConstantFloat; if (cf != null) { return(cf.Value != double.PositiveInfinity && cf.Value != double.NegativeInfinity); } BinaryOp binary = instruction as BinaryOp; if (binary != null) { int j = m_info.Tracker.GetStackIndex(instruction.Index, 0); int k = m_info.Tracker.GetStackIndex(instruction.Index, 1); if (j >= 0 && k >= 0) { if (DoIsFloat(j) && DoIsFloat(k)) { return(true); } } } if (instruction.Untyped.OpCode.Code == Code.Conv_R4 || instruction.Untyped.OpCode.Code == Code.Conv_R8 || instruction.Untyped.OpCode.Code == Code.Conv_R_Un) { return(true); } Call call = instruction as Call; if (call != null) { type = call.Target.ReturnType.ReturnType; break; } }while (false); return(type != null && (type.FullName == "System.Single" || type.FullName == "System.Double")); }