public void VisitBranch(ConditionalBranch branch) { if (m_needsCheck && !m_foundSingle && branch.Index >= 2 && m_numLocks == 1) { // Look for the if within the lock: // call System.Void System.Threading.Monitor::Enter(System.Object) // ldsfld field // brtrue 2A if (branch.Untyped.OpCode.Code == Code.Brtrue || branch.Untyped.OpCode.Code == Code.Brtrue_S) { LoadStaticField load = m_info.Instructions[branch.Index - 1] as LoadStaticField; Call call = m_info.Instructions[branch.Index - 2] as Call; if (load != null && call != null && call.Target.ToString() == "System.Void System.Threading.Monitor::Enter(System.Object)") { m_field = load.Field; Log.DebugLine(this, "found candidate lock at {0:X2}", branch.Untyped.Offset); // If we found the inner if then we need to look for a new // and a store within the if, if (DoFindNew(branch.Index + 1, branch.Target.Index - branch.Index - 1)) { m_foundSingle = true; // and a second guard before the lock. if (DoFindGuard(call.Index - 1)) { m_foundGuard = true; } } } } } }
private bool DoIsEmptyString(Call call, int nth) { bool empty = false; int index = m_info.Tracker.GetStackIndex(call.Index, nth); if (index >= 0) { LoadString str = m_info.Instructions[index] as LoadString; if (str != null) { empty = str.Value.Length == 0; } else { LoadStaticField field = m_info.Instructions[index] as LoadStaticField; if (field != null) { empty = field.Field.DeclaringType.FullName == "System.String" && field.Field.Name == "Empty"; } } } return(empty); }
private TypeReference DoGetType(int index, int nth) { TypeReference type = null; int i = m_info.Tracker.GetStackIndex(index, nth); if (i >= 0) { do // TODO: would be nice to do something with load constant instructions as well { LoadArg arg = m_info.Instructions[i] as LoadArg; if (arg != null && arg.Arg >= 1) { ParameterDefinition p = m_info.Method.Parameters[arg.Arg - 1]; type = p.ParameterType; break; } LoadField field = m_info.Instructions[i] as LoadField; if (field != null) { type = field.Field.FieldType; break; } LoadLocal local = m_info.Instructions[i] as LoadLocal; if (local != null) { VariableDefinition v = m_info.Method.Body.Variables[local.Variable]; type = v.VariableType; break; } LoadStaticField sfield = m_info.Instructions[i] as LoadStaticField; if (sfield != null) { type = sfield.Field.FieldType; break; } Box box = m_info.Instructions[i] as Box; if (box != null) { type = box.Type; break; } }while (false); } return(type); }
// match: // ldsfld field // ret public void VisitRet(End end) { if (m_needsCheck && !m_foundRet && m_foundSingle) { if (end.Untyped.OpCode.Code == Code.Ret && end.Index > 1) { LoadStaticField load = m_info.Instructions[end.Index - 1] as LoadStaticField; if (load != null && load.Field == m_field) { Log.DebugLine(this, "found return at {0:X2}", end.Untyped.Offset); m_foundRet = true; } } } }
public void VisitCall(Call call) { if (m_fields.Count > 0 && !m_info.Method.IsConstructor && call.Target.HasThis) { int index = call.GetThisIndex(m_info); if (index >= 0) { LoadStaticField load = m_info.Instructions[index] as LoadStaticField; if (load != null && m_fields.IndexOf(load.Field) >= 0) { Entry entry = m_table[load.Field]; if (m_adders[entry.Key].IndexOf(call.Target.Name) >= 0) { if (!DoIsNullSet(call.Index, call.Target.Name)) { if (!entry.FoundAdd) { Log.DebugLine(this, "found an add at {0:X2}", call.Untyped.Offset); entry.FoundAdd = true; } } else { if (!entry.FoundRemove) { Log.DebugLine(this, "found a null set at {0:X2}", call.Untyped.Offset); entry.FoundRemove = true; } } } if (!entry.FoundRemove) { if (m_removers[entry.Key].IndexOf(call.Target.Name) >= 0) { Log.DebugLine(this, "found a remove at {0:X2}", call.Untyped.Offset); entry.FoundRemove = true; } } } } } }
private TypeReference DoGetThisType(Call call) { TypeReference self = null; if (call.Target.HasThis) { int index = call.GetThisIndex(m_info); if (index >= 0) { do { LoadArg arg = m_info.Instructions[index] as LoadArg; if (arg != null) { self = arg.Type; break; } LoadField field = m_info.Instructions[index] as LoadField; if (field != null) { self = field.Field.FieldType; break; } LoadStaticField sfield = m_info.Instructions[index] as LoadStaticField; if (sfield != null) { self = sfield.Field.FieldType; break; } LoadLocal local = m_info.Instructions[index] as LoadLocal; if (local != null) { self = local.Type; break; } }while (false); } } return(self); }
public void VisitLoadStaticField(LoadStaticField load) { if (m_needsCheck) { State state; if (m_fields.TryGetValue(load.Field, out state)) { if (state == State.Defined) { m_fields[load.Field] = State.Used; } } else { m_fields.Add(load.Field, State.Referenced); } } }
// Find the following working backwards from index: // ldsfld field // brtrue 36 private bool DoFindGuard(int index) { while (index > 0) { ConditionalBranch branch = m_info.Instructions[index] as ConditionalBranch; if (branch != null && (branch.Untyped.OpCode.Code == Code.Brtrue || branch.Untyped.OpCode.Code == Code.Brtrue_S)) { LoadStaticField load = m_info.Instructions[index - 1] as LoadStaticField; if (load != null && load.Field == m_field) { Log.DebugLine(this, "found the guard at {0:X2}", branch.Untyped.Offset); return(true); } } --index; } return(false); }
private FieldReference DoSaveLocks(Call call) { FieldReference field = null; // Look for a lock using one of our fields. if (DoMatchLock1(call.Index)) { LoadStaticField sload = (LoadStaticField)m_info.Instructions[call.Index - 3]; if (sload.Field.DeclaringType == m_info.Type) { field = sload.Field; } } else if (DoMatchLock2(call.Index)) { LoadField load = (LoadField)m_info.Instructions[call.Index - 3]; field = load.Field; } // If we found one then record that the method locked the field. if (field != null) { List <FieldReference> fields; if (!m_current.Locked.TryGetValue(m_info.Method, out fields)) { fields = new List <FieldReference>(); m_current.Locked.Add(m_info.Method, fields); } fields.Add(field); Log.DebugLine(this, "{0} locks {1}", m_info.Method.Name, field.Name); } return(field); }
public void VisitSLoadField(LoadStaticField load) { DoAddField(load.Field); }
public void VisitLoadStaticField(LoadStaticField field) { DoAdd(field.Field.FieldType); }
public static bool IsIntOperand(MethodInfo info, int index, int nth) { bool isInt = false; int i = info.Tracker.GetStackIndex(index, nth); if (i >= 0) { do { LoadArg arg = info.Instructions[i] as LoadArg; if (arg != null && arg.Arg >= 1) { ParameterDefinition p = info.Method.Parameters[arg.Arg - 1]; if (p.ParameterType.FullName == "System.Int32") { isInt = true; } break; } LoadConstantInt constant = info.Instructions[i] as LoadConstantInt; if (constant != null) { Code code = constant.Untyped.OpCode.Code; switch (code) { case Code.Ldc_I4_M1: case Code.Ldc_I4_0: case Code.Ldc_I4_1: case Code.Ldc_I4_2: case Code.Ldc_I4_3: case Code.Ldc_I4_4: case Code.Ldc_I4_5: case Code.Ldc_I4_6: case Code.Ldc_I4_7: case Code.Ldc_I4_8: case Code.Ldc_I4_S: case Code.Ldc_I4: isInt = true; break; } break; } LoadField field = info.Instructions[i] as LoadField; if (field != null) { if (field.Field.FieldType.FullName == "System.Int32") { isInt = true; } break; } LoadLocal local = info.Instructions[i] as LoadLocal; if (local != null) { VariableDefinition v = info.Method.Body.Variables[local.Variable]; if (v.VariableType.FullName == "System.Int32") { isInt = true; } break; } LoadStaticField sfield = info.Instructions[i] as LoadStaticField; if (sfield != null) { if (sfield.Field.FieldType.FullName == "System.Int32") { isInt = true; } break; } }while (false); } return(isInt); }
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")); }
private bool DoIsBad(int index) { bool bad = false; do { LoadArg arg = m_info.Instructions[index] as LoadArg; if (arg != null && arg.Arg >= 1) { Log.DebugLine(this, "arg: {0}", arg.Arg); ParameterDefinition p = m_info.Method.Parameters[arg.Arg - 1]; Log.DebugLine(this, "param {0} is of type {1}", arg.Arg, p.ParameterType.FullName); if (DoIsBad(p.ParameterType)) { bad = true; } break; } LoadLocal local = m_info.Instructions[index] as LoadLocal; if (local != null) { Log.DebugLine(this, "local: {0}", local.Variable); TypeReference type = m_info.Method.Body.Variables[local.Variable].VariableType; Log.DebugLine(this, "local {0} is of type {1}", local.Variable, type.FullName); if (DoIsBad(type)) { bad = true; } break; } LoadField field = m_info.Instructions[index] as LoadField; if (field != null) { Log.DebugLine(this, "field: {0}", field.Field.Name); TypeReference type = field.Field.FieldType; Log.DebugLine(this, "field {0} is of type {1}", field.Field.Name, type.FullName); if (DoIsBad(type)) { bad = true; } break; } LoadStaticField sfield = m_info.Instructions[index] as LoadStaticField; if (sfield != null) { Log.DebugLine(this, "static field: {0}", sfield.Field.Name); TypeReference type = sfield.Field.FieldType; Log.DebugLine(this, "static field {0} is of type {1}", sfield.Field.Name, type.FullName); if (DoIsBad(type)) { bad = true; } break; } }while (false); return(bad); }