/// <summary>Returns true if lhs is a subclass of rhs. Returns false if they are the same class. /// Interfaces are ignored.</summary> public static bool IsSubclassOf(this TypeReference lhs, string rhs, AssemblyCache cache) { DBC.Pre(lhs != null, "lhs is null"); DBC.Pre(rhs != null, "rhs is null"); DBC.Pre(cache != null, "cache is null"); TypeDefinition type = cache.FindType(lhs); if (type != null && type.BaseType != null) { type = cache.FindType(type.BaseType); while (type != null) { if (type.FullName == rhs) { return(true); } type = cache.FindType(type.BaseType); } } return(false); }
internal void Register(object rule, string method, string name, string checkID) { DBC.Pre(rule != null, "rule is null"); DBC.Pre(!string.IsNullOrEmpty(method), "method is null or empty"); DBC.Pre(!string.IsNullOrEmpty(name), "name is null or empty"); DBC.Pre(!string.IsNullOrEmpty(checkID), "checkID is null or empty"); System.Reflection.MethodInfo mi = rule.GetType().GetMethod(method, BindingFlags.Public | BindingFlags.Instance); DBC.Pre(mi != null, "{0} isn't a public instance method of {1}", method, rule.GetType()); // Console.WriteLine("binding to {0}.{1}", rule.GetType(), method); // UntypedCallback callback = (UntypedCallback) Delegate.CreateDelegate(typeof(UntypedCallback), rule, mi); ParameterInfo[] pis = mi.GetParameters(); DBC.Pre(pis.Length == 1, "{0}::{1} should only have one argument", rule.GetType().Name, method); Type type = pis[0].ParameterType; List <RuleCallback> callbacks; if (!m_callbackTable.TryGetValue(type, out callbacks)) { callbacks = new List <RuleCallback>(); m_callbackTable.Add(type, callbacks); } callbacks.Add(new RuleCallback(name, checkID, rule, mi)); }
public override Lattice Meet(Lattice lhs, Lattice rhs) { DBC.Pre(lhs != null, "lhs is null"); DBC.Pre(rhs != null, "rhs is null"); // If one side is top then return the other side. if (lhs.IsTop) { return(rhs); } else if (rhs.IsTop) { return(lhs); } // Otherwise we have to meet the two sides. The result is // indeterminate if one side is indeterminate or if the values // differ. if (!lhs.m_state.HasValue && !rhs.m_state.HasValue) // strictly speaking this case is not necessary but it saves us an allocation { return(lhs); } else if (!lhs.m_state.HasValue || !rhs.m_state.HasValue) { return(new Lattice(lhs.m_instructions, Indeterminate)); } else if (lhs.m_state.Value == rhs.m_state.Value) { return(lhs); } return(new Lattice(lhs.m_instructions, Indeterminate)); }
public void VisitBegin(BeginMethod begin) { DBC.Pre(begin != null, "begin is null"); Log.DebugLine(this, "-----------------------------------"); Log.DebugLine(this, "{0:F}", begin.Info.Instructions); m_info = begin.Info; MethodDefinition method = begin.Info.Method; if (method.Name == "Finalize") { Log.DebugLine(this, "found finalizer: {0}", method); m_threadRoots.Add(method); } else if (method.ReturnType.ReturnType.ToString() == "System.Void") { if (method.Parameters.Count == 1 && method.Parameters[0].ParameterType.FullName == "System.IAsyncResult") { Log.DebugLine(this, "found asynchronous thread function: {0}", method); m_threadRoots.Add(method); } } }
/// <summary>Returns the assembly the type is defined in.</summary> /// <summary>Returns null if the assembly cannot be found.</summary> public AssemblyDefinition FindAssembly(TypeReference type) { DBC.Pre(type != null, "type is null"); AssemblyDefinition assembly = null; string name = type.FullName; if (!m_assemblies.TryGetValue(name, out assembly)) { foreach (AssemblyDefinition candidate in m_depedent) { foreach (ModuleDefinition module in candidate.Modules) { if (module.Types.Contains(name)) { assembly = candidate; m_assemblies.Add(name, assembly); return(assembly); // it's possible for internal types to have the exact same name in different assemblies so we'll bail as soon as we find one } } } } return(assembly); }
/// <summary>Returns true if lhs is a subclass of rhs. Returns false if they are the same class. /// Interfaces are ignored.</summary> public static bool IsSubclassOf(this TypeReference lhs, TypeReference rhs, AssemblyCache cache) { DBC.Pre(lhs != null, "lhs is null"); DBC.Pre(rhs != null, "rhs is null"); DBC.Pre(cache != null, "cache is null"); if (lhs.FullName != "System.Object" && rhs.FullName == "System.Object") // everything is a subclass of object { return(true); } while (lhs != null) { TypeDefinition type = cache.FindType(lhs); lhs = type != null && !type.IsInterface ? type.BaseType : null; if (lhs != null) { var key1 = new AssemblyCache.TypeKey(lhs); var key2 = new AssemblyCache.TypeKey(rhs); if (key1 == key2) { return(true); } } } return(false); }
/// <summary>Returns the interface or type the method was first declared in.</summary> public static TypeReference GetDeclaredIn(this MethodReference method, AssemblyCache cache) { DBC.Pre(method != null, "method is null"); DBC.Pre(cache != null, "cache is null"); TypeReference declared = method.DeclaringType; TypeReference candidate = DoGetDeclaringInterface(declared, new MethodMatcher(method), cache); if (candidate != null) { declared = candidate; } else { TypeDefinition baseType = cache.FindType(declared); if (baseType != null) { Log.DebugLine(true, " type: {0}", baseType); baseType = cache.FindType(baseType.BaseType); while (baseType != null && declared.FullName == method.DeclaringType.FullName) { Log.DebugLine(true, " checking {0} for {1}", baseType, method.Name); if (DoDeclares(baseType, new MethodMatcher(method))) { declared = baseType; } baseType = cache.FindType(baseType.BaseType); } } } return(declared); }
public Lattice(TypedInstructionCollection instructions, State state) { DBC.Pre(instructions != null, "instructions is null"); m_instructions = instructions; m_state = state; }
/// <summary>Returns a TryCatch if the a block, catch block, or finally block /// starts at index. If a suitable TryCatch cannot be found null is returned.</summary> public TryCatch HandlerStartsAt(int index) { DBC.Pre(index >= 0, "index is negative"); for (int i = 0; i < m_trys.Count; ++i) { if (m_trys[i].Try.Index == index) { return(m_trys[i]); } for (int j = 0; j < m_trys[i].Catchers.Count; ++j) { if (m_trys[i].Catchers[j].Index == index) { return(m_trys[i]); } } if (m_trys[i].Finally.Index == index && m_trys[i].Finally.Length > 0) { return(m_trys[i]); } else if (m_trys[i].Fault.Index == index && m_trys[i].Fault.Length > 0) { return(m_trys[i]); } } return(null); }
public override Lattice Meet(Lattice lhs, Lattice rhs) { DBC.Pre(lhs != null, "lhs is null"); DBC.Pre(rhs != null, "rhs is null"); // If one side is top then return the other side. if (lhs.IsTop) { return(rhs); } else if (rhs.IsTop) { return(lhs); } // Otherwise we have to meet the two sides. The result is // indeterminate if one side is indeterminate or if the // values differ. long?[] args = DoMeetVars(lhs.m_state.Arguments, rhs.m_state.Arguments); long?[] locals = DoMeetVars(lhs.m_state.Locals, rhs.m_state.Locals); List <StackEntry> stack = DoMeetStack(lhs.m_state.Stack, rhs.m_state.Stack); State state = new State(args, locals, stack); return(new Lattice(lhs.m_instructions, state)); }
public static bool Match(MethodReference lhs, MethodReference rhs) { DBC.Pre(lhs != null, "lhs is null"); DBC.Pre(rhs != null, "rhs is null"); if (lhs.Name != rhs.Name) { return(false); } if (lhs.Parameters.Count != rhs.Parameters.Count) { return(false); } for (int i = 0; i < lhs.Parameters.Count; ++i) { if (!DoMatchTypes(lhs, rhs, lhs.Parameters[i].ParameterType, rhs.Parameters[i].ParameterType)) { return(false); } } if (!DoMatchTypes(lhs, rhs, lhs.ReturnType.ReturnType, rhs.ReturnType.ReturnType)) { return(false); } return(true); }
// Typical usage is Add("-help", "-h", "-?", "blah blah"). The first string // is the primary option key used to identify the option. The middle strings // are aliaii for the primary key. The last string is the help text. Note // that the option can have a value if and only if the primary key ends with // '='. If the '=' is followed by text then that text is used as the default // value. public void Add(params string[] strs) { DBC.Pre(strs.Length >= 2, "{0} should have both a primary key and a help string", string.Join(", ", strs)); DBC.Pre(!m_options.ContainsKey(strs[0]), "{0} was already added", strs[0]); string key = strs[0]; string value = null; int i = key.IndexOf("="); if (i >= 0) { key = strs[0].Substring(0, i); if (i + 1 < strs[0].Length) { value = strs[0].Substring(i + 1); } } string help = strs[strs.Length - 1]; string[] aliaii = new string[strs.Length - 2]; // TODO: should assert that there are no = in aliaii Array.Copy(strs, 1, aliaii, 0, strs.Length - 2); m_options[key] = new Option(key, value, help, i >= 0, aliaii); }
public static bool HasDisableRule(this TypeDefinition derived, string checkID, AssemblyCache cache) { DBC.Pre(derived != null, "derived is null"); DBC.Pre(checkID != null, "checkID is null"); DBC.Pre(cache != null, "cache is null"); TypeDefinition type = derived; while (type != null) { if (HasDisableRule(type.CustomAttributes, checkID)) { return(true); } foreach (TypeReference t in type.Interfaces) { TypeDefinition td = cache.FindType(t); if (td != null && HasDisableRule(td.CustomAttributes, checkID)) { return(true); } } type = cache.FindType(type.BaseType); } return(false); }
public Tracker(TypedInstructionCollection instructions) { DBC.Pre(instructions != null, "instructions is null"); m_instructions = instructions; m_initialState = DoGetInitialState(m_instructions); }
public static bool IsCompilerGenerated(this TypeReference type) { DBC.Pre(type != null, "type is null"); if (type.Name.Contains("CompilerGenerated")) { return(true); } else if (type.Name.Contains("AnonType")) { return(true); } else if (type.Name.Contains("AnonStore")) { return(true); } else if (type.Name.Contains(">c__")) { return(true); } else if (type.FullName.Contains("<PrivateImplementationDetails>")) { return(true); } return(false); }
/// <summary>Returns true if the method has the specified result type, name, and argument types. /// Also see Reuses.</summary> public static bool Matches(this MethodReference method, string rtype, string mname, params string[] atypes) { DBC.Pre(method != null, "method is null"); DBC.Pre(!string.IsNullOrEmpty(rtype), "rtype is null or empty"); DBC.Pre(!string.IsNullOrEmpty(mname), "mname is null or empty"); DBC.Pre(atypes != null, "atypes is null"); bool match = false; if (method.ReturnType.ReturnType.FullName == rtype) { if (method.Name == mname) { if (method.Parameters.Count == atypes.Length) { match = true; for (int i = 0; i < atypes.Length && match; ++i) { match = atypes[i] == method.Parameters[i].ParameterType.FullName; } } } } return(match); }
internal AssemblyCache(SymbolTable symbols, AssemblyDefinition assembly, Rule.KeepAliveCallback callback) { DBC.Pre(symbols != null, "symbols is null"); DBC.Pre(assembly != null, "assembly is null"); Profile.Start("AssemblyCache ctor"); m_symbols = symbols; m_assembly = assembly; // For some reason we have to force the Mdb assembly to load. If we don't it // isn't found. Unused.Value = typeof(Mono.Cecil.Mdb.MdbFactory); foreach (ModuleDefinition module in assembly.Modules) { try { module.LoadSymbols(); } catch { Console.Error.WriteLine("Couldn't load symbols so there will be no file or line numbers."); } // Note that if the type is generic it will be listed once with a name like SomeType`1 // where the number of the number of generic arguments. foreach (TypeDefinition type in module.Types) { DoCheckForPublics(type); TypeKey key = new TypeKey(type); if (!m_types.ContainsKey(key)) { m_types.Add(key, type); } else if (!type.FullName.Contains("CompilerGenerated")) { m_types[key] = type; // replace Database`1/<>c__CompilerGenerated5 with Database`1 } Log.DebugLine(this, "adding {0}", type.FullName); if (callback != null) { callback(string.Format("adding {0}", type.Name)); } List <MethodInfo> ml = new List <MethodInfo>(); DoAddMethods(symbols, type, type.Constructors, ml); DoAddMethods(symbols, type, type.Methods, ml); m_typeMethods.Add(type, ml); } } DoLoadDependentAssemblies(callback); Profile.Stop("AssemblyCache ctor"); }
internal State(long?[] args, long?[] locals, List <StackEntry> stack) { DBC.Pre(args != null, "args is null"); DBC.Pre(locals != null, "locals is null"); DBC.Pre(stack != null, "stack is null"); m_args = args; m_locals = locals; m_stack = stack; }
protected Rule(AssemblyCache cache, IReportViolations reporter, string checkID) { DBC.Pre(cache != null, "cache is null"); DBC.Pre(reporter != null, "reporter is null"); DBC.Pre(!string.IsNullOrEmpty(checkID), "checkID is null or empty"); Cache = cache; Reporter = reporter; CheckID = checkID; Runtime = TargetRuntime.NET_1_0; }
/// <summary>Returns the index of the instruction which pushed the method call's /// this argument onto the stack. May return -1 if a single such instruction /// could not be found.</summary> public int GetThisIndex(MethodInfo info) { DBC.Pre(info != null, "info is null"); DBC.Pre(Target.HasThis, "the method is static"); if (!m_thisIndex.HasValue) { m_thisIndex = info.Tracker.GetStackIndex(Index, Target.Parameters.Count); } return(m_thisIndex.Value); }
/// <summary>Returns true if type is IntPtr, IntPtr[], List<IntPtr>, etc.</summary> public static bool IsNative(this TypeReference type) { DBC.Pre(type != null, "type is null"); if (type.FullName.Contains("System.IntPtr") || type.FullName.Contains("System.UIntPtr") || type.FullName.Contains("System.Runtime.InteropServices.HandleRef")) { return(true); } return(false); }
// This method is used by the Transform above and later on when we // need to compute the state for each instruction in a method. public Lattice Transform(int index) { DBC.Pre(index >= 0 && index < m_instructions.Length, "index is out of range"); // real code would probably use FastPre long?[] args = DoTransformArgs(index); long?[] locals = DoTransformLocals(index); List <StackEntry> stack = DoTransformStack(index); State state = new State(args, locals, stack); Log.DebugLine(this, "{0:X2}: {1}", m_instructions[index].Untyped.Offset, state); return(new Lattice(m_instructions, state)); }
public override bool DiffersFrom(Lattice lhs, Lattice rhs) { DBC.Pre(lhs != null, "lhs is null"); DBC.Pre(rhs != null, "rhs is null"); if (lhs.IsTop || rhs.IsTop) // if either side is indeterminate then we cant say the two sides are equal { return(true); } else { return(lhs.m_state != rhs.m_state); } }
private Dictionary <int, BasicBlock> DoGetWiredBlocks(TypedInstructionCollection instructions) { DBC.Pre(instructions.Length > 0, "Can't get a root if there are no instructions"); m_branchTargets = new List <int>(); Dictionary <int, BasicBlock> blocks = DoGetUnwiredBlocks(instructions); // index -> block foreach (KeyValuePair <int, BasicBlock> entry in blocks) { DoWireBlock(instructions, blocks, entry.Value); } return(blocks); }
public void Analyze(ControlFlowGraph graph) { DBC.Pre(graph != null, "graph is null"); Profile.Start("Splicing"); var visited = new List <BasicBlock>(); foreach (BasicBlock root in graph.Roots) { DoSpliceHandlers(m_instructions, root, visited); } visited.Clear(); foreach (BasicBlock root in graph.Roots) { DoSpliceNullCheck(m_instructions, root, visited); } var data = new DataFlow <Lattice>(m_instructions, graph.Roots); m_skipped = data.Skipped; Profile.Stop("Splicing"); var functions = new Lattice.Functions(); Dictionary <BasicBlock, Lattice> lattices = data.Analyze(functions, m_initialState); Profile.Start("Post Transform"); m_states = new State[m_instructions.Length]; foreach (var entry in lattices) { BasicBlock block = entry.Key; if (block.Length > 0) { Lattice lattice = entry.Value; for (int index = block.First.Index; index <= block.Last.Index; ++index) // it'd be nice to assert that every index was set, but methods often have dead code so it's a little difficult { m_states[index] = lattice.State; lattice = lattice.Transform(index); } } } Profile.Stop("Post Transform"); for (int index = 0; index < m_instructions.Length; ++index) { Log.DebugLine(this, "{0:X2}: {1}", m_instructions[index].Untyped.Offset, m_states[index]); } }
public static bool Has(this CustomAttributeCollection attrs, string name) { DBC.Pre(attrs != null, "attrs is null"); DBC.Pre(name != null, "name is null"); foreach (CustomAttribute attr in attrs) { // Log.InfoLine(true, " {0}", attr.Constructor.DeclaringType.Name); if (attr.Constructor.DeclaringType.Name == name) // note that this is the type name, not the full name { return(true); } } return(false); }
public static bool IsCompilerGenerated(this MethodReference method) { DBC.Pre(method != null, "method is null"); if (IsCompilerGenerated(method.DeclaringType)) { return(true); } else if (method.Name[0] == '<') // with 2.0 started getting weird names like <ArrayToStr>m__0 { return(true); } return(false); }
/// <summary>Returns true if field is created by type's constructor(s).</summary> public static bool IsOwnedBy(this FieldDefinition field, TypeDefinition type) { DBC.Pre(field != null, "field is null"); DBC.Pre(type != null, "type is null"); List <string> tested = new List <string>(); for (int i = 0; i < type.Constructors.Count; ++i) { if (DoOwnsField(type, type.Constructors[i], field, tested)) { return(true); } } return(false); }
public override Lattice Transform(Lattice lhs, BasicBlock block) { DBC.Pre(lhs != null, "lhs is null"); DBC.Pre(block != null, "block is null"); Lattice result = lhs; if (!lhs.IsTop) { for (int i = 0; i < block.Length; ++i) { result = result.Transform(block.First.Index + i); } } return(result); }
/// <summary>Returns true if type is an enum with the Flags attribute.</summary> public static bool IsFlagsEnum(this TypeDefinition type) { DBC.Pre(type != null, "type is null"); if (type.IsEnum) { foreach (CustomAttribute attr in type.CustomAttributes) { if (attr.Constructor.ToString().Contains("System.FlagsAttribute::.ctor")) { return(true); } } } return(false); }