예제 #1
0
        private static Dictionary <string, List <ITypeDefinition> > GetShortNamesToTypeDefinitions(DecompilerTypeSystem winmd)
        {
            Dictionary <string, List <ITypeDefinition> > ret = new Dictionary <string, List <ITypeDefinition> >();

            foreach (var type1 in winmd.GetTopLevelTypeDefinitions())
            {
                if (type1.FullName == "<Module>")
                {
                    continue;
                }

                if (type1.ParentModule != winmd.MainModule)
                {
                    continue;
                }

                string name = type1.Name;
                if (!ret.TryGetValue(name, out var list))
                {
                    list      = new List <ITypeDefinition>();
                    ret[name] = list;
                }

                list.Add(type1);
            }

            return(ret);
        }
예제 #2
0
        private static Dictionary <string, List <IMember> > GetApiMemberNamesToMethodDefinitions(DecompilerTypeSystem winmd)
        {
            Dictionary <string, List <IMember> > ret = new Dictionary <string, List <IMember> >();

            foreach (var type1 in winmd.GetTopLevelTypeDefinitions())
            {
                if (type1.FullName == "<Module>")
                {
                    continue;
                }

                if (type1.ParentModule != winmd.MainModule)
                {
                    continue;
                }

                if (type1.Kind != TypeKind.Class || type1.Name != "Apis")
                {
                    continue;
                }

                foreach (var m in type1.Members)
                {
                    string name     = m.Name;
                    string archInfo = GetArchInfo(m.GetAttributes());
                    if (!string.IsNullOrEmpty(archInfo))
                    {
                        name += $"({archInfo})";
                    }

                    if (!ret.TryGetValue(name, out var list))
                    {
                        list      = new List <IMember>();
                        ret[name] = list;
                    }

                    list.Add(m);
                }
            }

            return(ret);
        }
예제 #3
0
        private static Dictionary <string, ITypeDefinition> GetNamesToTypeDefinitions(DecompilerTypeSystem winmd)
        {
            Dictionary <string, ITypeDefinition> ret = new Dictionary <string, ITypeDefinition>();

            foreach (var type1 in winmd.GetTopLevelTypeDefinitions())
            {
                if (type1.FullName == "<Module>")
                {
                    continue;
                }

                if (type1.ParentModule != winmd.MainModule)
                {
                    continue;
                }

                string name = GetFullTypeName(type1);
                ret[name] = type1;
            }

            return(ret);
        }
예제 #4
0
        public static int CompareWinmds(FileInfo first, FileInfo second, string exclusions, IConsole console)
        {
            bool same = true;

            DecompilerSettings settings = new DecompilerSettings()
            {
                ThrowOnAssemblyResolveErrors = false
            };
            DecompilerTypeSystem winmd1 = CreateTypeSystemFromFile(first.FullName, settings);
            DecompilerTypeSystem winmd2 = CreateTypeSystemFromFile(second.FullName, settings);
            Dictionary <string, ITypeDefinition>         winmd2NamesToTypes      = GetNamesToTypeDefinitions(winmd2);
            Dictionary <string, List <ITypeDefinition> > winmd2ShortNamesToTypes = GetShortNamesToTypeDefinitions(winmd2);

            HashSet <string> visitedNames = new HashSet <string>();

            foreach (var type1 in winmd1.GetTopLevelTypeDefinitions())
            {
                if (type1.FullName == "<Module>")
                {
                    continue;
                }

                if (type1.ParentModule != winmd1.MainModule)
                {
                    continue;
                }

                var type1Name = GetFullTypeName(type1);
                visitedNames.Add(type1Name);

                winmd2NamesToTypes.TryGetValue(type1Name, out var type2);
                if (type2 == null)
                {
                    if (winmd2ShortNamesToTypes.TryGetValue(type1.Name, out var list))
                    {
                        foreach (var t2 in list)
                        {
                            if (CompareTypes(type1, t2, null))
                            {
                                var type2Name = GetFullTypeName(t2);
                                console?.Out.Write($"{type1Name} => {type2Name}\r\n");
                                visitedNames.Add(type2Name);
                                same  = false;
                                type2 = t2;
                                break;
                            }
                        }
                    }

                    if (type2 == null)
                    {
                        console?.Out.Write($"{type1Name} not found in 2nd winmd\r\n");
                        same = false;
                    }

                    continue;
                }

                same &= CompareTypes(type1, type2, console);
            }

            Dictionary <string, ITypeDefinition> winmd1NamesToTypes = GetNamesToTypeDefinitions(winmd1);

            foreach (var type2 in winmd2.GetTopLevelTypeDefinitions())
            {
                if (type2.FullName == "<Module>")
                {
                    continue;
                }

                var type2FullName = GetFullTypeName(type2);
                if (type2.ParentModule != winmd2.MainModule)
                {
                    continue;
                }

                if (visitedNames.Contains(type2FullName))
                {
                    continue;
                }

                winmd1NamesToTypes.TryGetValue(type2FullName, out var type1);
                if (type1 == null)
                {
                    console?.Out.Write($"{type2FullName} not found in 1st winmd\r\n");
                    same = false;
                }
            }

            if (same)
            {
                console.Out.Write($"No differences in winmd contents.\r\n");
            }

            return(same ? 0 : -1);
        }
예제 #5
0
        public static int ShowDuplicateImports(FileInfo winmd, IConsole console)
        {
            DecompilerSettings settings = new DecompilerSettings()
            {
                ThrowOnAssemblyResolveErrors = false
            };
            DecompilerTypeSystem winmd1 = CreateTypeSystemFromFile(winmd.FullName, settings);

            Dictionary <string, List <string> > dllImportsToClassNames = new Dictionary <string, List <string> >();

            foreach (var type1 in winmd1.GetTopLevelTypeDefinitions())
            {
                if (type1.FullName == "<Module>")
                {
                    continue;
                }

                if (type1.ParentModule != winmd1.MainModule)
                {
                    continue;
                }

                if (type1.Kind != TypeKind.Class)
                {
                    continue;
                }

                foreach (var method in type1.GetMethods())
                {
                    if (!method.IsStatic)
                    {
                        continue;
                    }

                    var dllImportAttr = method.GetAttribute(KnownAttribute.DllImport);
                    if (dllImportAttr != null)
                    {
                        string entryPoint    = method.Name;
                        var    dllName       = (string)(dllImportAttr.FixedArguments[0].Value);
                        var    entryPointVar = dllImportAttr.NamedArguments.FirstOrDefault(a => a.Name == "EntryPoint");
                        if (entryPointVar.Name != null)
                        {
                            entryPoint = (string)entryPointVar.Value;
                        }

                        string fullImport = $"{dllName}:{entryPoint}";
                        string archInfo   = GetArchInfo(method.GetAttributes());
                        if (!string.IsNullOrEmpty(archInfo))
                        {
                            fullImport += $"({archInfo})";
                        }

                        if (!dllImportsToClassNames.TryGetValue(fullImport, out var classNames))
                        {
                            classNames = new List <string>();
                            dllImportsToClassNames[fullImport] = classNames;
                        }

                        classNames.Add(type1.FullName);
                    }
                }
            }

            bool dupsFound = false;

            foreach (var pair in dllImportsToClassNames)
            {
                if (pair.Value.Count > 1)
                {
                    if (dupsFound == false)
                    {
                        dupsFound = true;
                        console.Out.Write("Duplicated imports detected:\r\n");
                    }

                    pair.Value.Sort();

                    console?.Out.Write($"{pair.Key}\r\n");
                    foreach (var imp in pair.Value)
                    {
                        console?.Out.Write($"  {imp}\r\n");
                    }
                }
            }

            if (!dupsFound)
            {
                console.Out.Write("No duplicate imports found.\r\n");
            }

            return(dupsFound ? -1 : 0);
        }
예제 #6
0
        public static int ShowDuplicateTypes(FileInfo winmd, IConsole console)
        {
            DecompilerSettings settings = new DecompilerSettings()
            {
                ThrowOnAssemblyResolveErrors = false
            };
            DecompilerTypeSystem winmd1 = CreateTypeSystemFromFile(winmd.FullName, settings);

            Dictionary <string, List <string> > nameToNamespaces = new Dictionary <string, List <string> >();

            foreach (var type1 in winmd1.GetTopLevelTypeDefinitions())
            {
                if (type1.FullName == "<Module>")
                {
                    continue;
                }

                if (type1.ParentModule != winmd1.MainModule)
                {
                    continue;
                }

                var typeName = type1.Name;
                if (type1.Kind == TypeKind.Class && typeName == "Apis")
                {
                    continue;
                }

                StringBuilder members = new StringBuilder();
                foreach (var m in type1.Members)
                {
                    if (type1.Kind == TypeKind.Enum && m.Name == "value__")
                    {
                        continue;
                    }

                    if (m.Name == ".ctor")
                    {
                        continue;
                    }

                    if (members.Length != 0)
                    {
                        members.Append(',');
                    }

                    members.Append(m.Name);
                }

                if (members.Length != 0)
                {
                    typeName += $"({members})";
                }

                string archInfo = GetArchInfo(type1.GetAttributes());
                if (!string.IsNullOrEmpty(archInfo))
                {
                    typeName += $"({archInfo})";
                }

                if (!nameToNamespaces.TryGetValue(typeName, out var namespaces))
                {
                    namespaces = new List <string>();
                    nameToNamespaces[typeName] = namespaces;
                }

                namespaces.Add(type1.Namespace);
            }

            bool dupsFound = false;

            foreach (var pair in nameToNamespaces)
            {
                if (pair.Value.Count > 1)
                {
                    if (dupsFound == false)
                    {
                        dupsFound = true;
                        console.Out.Write("Duplicate types detected:\r\n");
                    }

                    pair.Value.Sort();

                    console?.Out.Write($"{pair.Key}\r\n");
                    foreach (var ns in pair.Value)
                    {
                        console?.Out.Write($"  {ns}\r\n");
                    }
                }
            }

            if (!dupsFound)
            {
                console.Out.Write("No duplicate types found.\r\n");
            }

            return(dupsFound ? -1 : 0);
        }
예제 #7
0
        public static int ShowDuplicateConstants(FileInfo winmd, IConsole console)
        {
            DecompilerSettings settings = new DecompilerSettings()
            {
                ThrowOnAssemblyResolveErrors = false
            };
            DecompilerTypeSystem winmd1 = CreateTypeSystemFromFile(winmd.FullName, settings);
            Dictionary <string, List <string> > nameToOwner = new Dictionary <string, List <string> >();

            foreach (var type in winmd1.GetTopLevelTypeDefinitions())
            {
                if (type.FullName == "<Module>")
                {
                    continue;
                }

                if (type.ParentModule != winmd1.MainModule)
                {
                    continue;
                }

                // Skip enums marked as a scoped enum (like a C++ class enum).
                // We don't count these in the duplicated constants
                if (type.Kind == TypeKind.Enum)
                {
                    if (type.GetAttributes().Any(a => a.AttributeType.Name == "ScopedEnumAttribute"))
                    {
                        continue;
                    }
                }

                if (type.Kind == TypeKind.Enum || (type.Kind == TypeKind.Class && type.Name == "Apis"))
                {
                    foreach (var field in type.GetFields())
                    {
                        if (field.Name == "value__")
                        {
                            continue;
                        }

                        if (!nameToOwner.TryGetValue(field.Name, out var owners))
                        {
                            owners = new List <string>();
                            nameToOwner[field.Name] = owners;
                        }

                        owners.Add(type.FullName);
                    }
                }
            }

            bool dupsFound = false;

            foreach (var pair in nameToOwner)
            {
                if (pair.Value.Count > 1)
                {
                    if (dupsFound == false)
                    {
                        dupsFound = true;
                        console.Out.Write("Duplicate constants/enum names detected:\r\n");
                    }

                    pair.Value.Sort();

                    console?.Out.Write($"{pair.Key}\r\n");
                    foreach (var owner in pair.Value)
                    {
                        console?.Out.Write($"  {owner}\r\n");
                    }
                }
            }

            if (!dupsFound)
            {
                console.Out.Write("No duplicate constants/enum names found.\r\n");
            }

            return(dupsFound ? -1 : 0);
        }
예제 #8
0
        public static int CompareWinmds(FileInfo first, FileInfo second, string exclusions, IConsole console)
        {
            bool same = true;

            DecompilerSettings settings = new DecompilerSettings()
            {
                ThrowOnAssemblyResolveErrors = false
            };
            DecompilerTypeSystem winmd1 = CreateTypeSystemFromFile(first.FullName, settings);
            DecompilerTypeSystem winmd2 = CreateTypeSystemFromFile(second.FullName, settings);
            Dictionary <string, ITypeDefinition>         winmd2NamesToTypes      = GetNamesToTypeDefinitions(winmd2);
            Dictionary <string, List <ITypeDefinition> > winmd2ShortNamesToTypes = GetShortNamesToTypeDefinitions(winmd2);

            HashSet <string> visitedNames = new HashSet <string>();

            foreach (var type1 in winmd1.GetTopLevelTypeDefinitions())
            {
                if (type1.FullName == "<Module>")
                {
                    continue;
                }

                if (type1.ParentModule != winmd1.MainModule)
                {
                    continue;
                }

                // We'll compare the members of Apis in their own way
                if (type1.Name == "Apis")
                {
                    continue;
                }

                var type1Name = GetFullTypeName(type1);
                visitedNames.Add(type1Name);

                winmd2NamesToTypes.TryGetValue(type1Name, out var type2);
                if (type2 == null)
                {
                    if (winmd2ShortNamesToTypes.TryGetValue(type1.Name, out var list))
                    {
                        foreach (var t2 in list)
                        {
                            if (CompareTypes(type1, t2, null))
                            {
                                var type2Name = GetFullTypeName(t2);
                                console?.Out.Write($"{type1Name} => {type2Name}\r\n");
                                visitedNames.Add(type2Name);
                                same  = false;
                                type2 = t2;
                                break;
                            }
                        }
                    }

                    if (type2 == null)
                    {
                        console?.Out.Write($"{type1Name} not found in 2nd winmd\r\n");
                        same = false;
                    }

                    continue;
                }

                same &= CompareTypes(type1, type2, console);
            }

            Dictionary <string, ITypeDefinition> winmd1NamesToTypes = GetNamesToTypeDefinitions(winmd1);

            foreach (var type2 in winmd2.GetTopLevelTypeDefinitions())
            {
                if (type2.FullName == "<Module>")
                {
                    continue;
                }

                if (type2.ParentModule != winmd2.MainModule)
                {
                    continue;
                }

                // We'll compare the members of Apis in their own way
                if (type2.Name == "Apis")
                {
                    continue;
                }

                var type2FullName = GetFullTypeName(type2);
                if (visitedNames.Contains(type2FullName))
                {
                    continue;
                }

                winmd1NamesToTypes.TryGetValue(type2FullName, out var type1);
                if (type1 == null)
                {
                    console?.Out.Write($"{type2FullName} not found in 1st winmd\r\n");
                    same = false;
                }
            }

            var apiNameToMembers1 = GetApiMemberNamesToMethodDefinitions(winmd1);
            var apiNameToMembers2 = GetApiMemberNamesToMethodDefinitions(winmd2);

            HashSet <string> visitedM2Names = new HashSet <string>();

            foreach (var api1MemberInfo in apiNameToMembers1)
            {
                if (apiNameToMembers2.TryGetValue(api1MemberInfo.Key, out var api2Members))
                {
                    foreach (var m1 in api1MemberInfo.Value)
                    {
                        string m1FullName = GetFullMemberName(m1);
                        bool   found      = false;

                        foreach (var m2 in api2Members)
                        {
                            if (m1.GetType() == m2.GetType())
                            {
                                string m2FullName = GetFullMemberName(m2);

                                bool membersSame;
                                if (m1 is IField)
                                {
                                    membersSame = CompareFields((IField)m1, (IField)m2, console);
                                }
                                else
                                {
                                    membersSame = CompareMethods((IMethod)m1, (IMethod)m2, null);

                                    // If the members aren't the same on the methods and the namespaces also aren't
                                    // the same, then assume these aren't the same methods and keep going
                                    if (!membersSame && (m1.Namespace != m2.Namespace))
                                    {
                                        continue;
                                    }

                                    if (!membersSame && console != null)
                                    {
                                        CompareMethods((IMethod)m1, (IMethod)m2, console);
                                    }
                                }

                                if (membersSame)
                                {
                                    if (m1.Namespace != m2.Namespace)
                                    {
                                        console?.Out.Write($"{m1FullName} => {m2FullName}\r\n");
                                        membersSame = false;
                                    }
                                }

                                same &= membersSame;

                                visitedM2Names.Add(m2FullName);
                                found = true;
                                break;
                            }
                        }

                        if (!found)
                        {
                            console?.Out.Write($"{m1FullName} not found in 2nd winmd\r\n");
                        }
                    }
                }
                else
                {
                    foreach (var m1 in api1MemberInfo.Value)
                    {
                        string m1FullName = GetFullMemberName(m1);
                        console?.Out.Write($"{m1FullName} not found in 2nd winmd\r\n");
                        same = false;
                    }
                }
            }

            foreach (var api2MemberInfo in apiNameToMembers2)
            {
                foreach (var api2Member in api2MemberInfo.Value)
                {
                    string m2FullName = GetFullMemberName(api2Member);
                    if (!visitedM2Names.Contains(m2FullName))
                    {
                        console?.Out.Write($"{m2FullName} not found in 1st winmd\r\n");
                        same = false;
                    }
                }
            }

            if (same)
            {
                console.Out.Write($"No differences in winmd contents.\r\n");
            }

            return(same ? 0 : -1);
        }
예제 #9
0
            public IEnumerable <DependenciesInNamespace> GetNamespaceDependencies(string winmdFileName)
            {
                DecompilerTypeSystem winmd1 = DecompilerTypeSystemUtils.CreateTypeSystemFromFile(winmdFileName);

                foreach (var type1 in winmd1.GetTopLevelTypeDefinitions())
                {
                    if (type1.FullName == "<Module>")
                    {
                        continue;
                    }

                    if (type1.ParentModule != winmd1.MainModule)
                    {
                        continue;
                    }

                    var typeNamespace = type1.Namespace;
                    if (!this.namespacesToDepends.TryGetValue(typeNamespace, out var depends))
                    {
                        depends = new(typeNamespace);
                        this.namespacesToDepends[typeNamespace] = depends;
                    }

                    if (type1.Kind == TypeKind.Struct)
                    {
                        foreach (var field in type1.GetFields())
                        {
                            string broughtInBy = $"{type1.Name}.{field.Name}";
                            this.AddTypeDependency(type1, depends, broughtInBy, field.Type);
                        }
                    }
                    else if (type1.Kind == TypeKind.Class && type1.Name == "Apis")
                    {
                        foreach (var method in type1.GetMethods().Where(m => m.IsStatic && m.DeclaringType == type1))
                        {
                            string returnBroughtInBy = $"{method.Name}::return";
                            this.AddTypeDependency(type1, depends, returnBroughtInBy, method.ReturnType);

                            foreach (var p in method.Parameters)
                            {
                                string paramBroughtInBy = $"{method.Name}(...{p.Name}...)";
                                this.AddTypeDependency(type1, depends, paramBroughtInBy, p.Type);
                            }
                        }
                    }
                    else if (type1.Kind == TypeKind.Interface)
                    {
                        foreach (var directBaseType in type1.DirectBaseTypes)
                        {
                            if (directBaseType.FullName == "System.Object")
                            {
                                continue;
                            }

                            string inheritBroughtInBy = $"{type1.Name} inherits";
                            this.AddTypeDependency(type1, depends, inheritBroughtInBy, directBaseType);
                        }

                        foreach (var method in type1.GetMethods().Where(m => m.DeclaringType == type1))
                        {
                            string returnBroughtInBy = $"{type1.Name}::{method.Name}::return";
                            this.AddTypeDependency(type1, depends, returnBroughtInBy, method.ReturnType);

                            foreach (var p in method.Parameters)
                            {
                                string paramBroughtInBy = $"{type1.Name}::{method.Name}(...{p.Name}...)";
                                this.AddTypeDependency(type1, depends, paramBroughtInBy, p.Type);
                            }
                        }
                    }
                }

                var finalDepends = this.namespacesToDepends.Values.OrderBy(d => d.Namespace);

                Dictionary <string, IEnumerable <string> > namespaceToDepends = new();

                foreach (var dependsInNamespace in finalDepends)
                {
                    namespaceToDepends.Add(dependsInNamespace.Namespace, dependsInNamespace.GetDependenciesByNamespace().Select(p => p.Key));
                }

                foreach (var dependsInNamespace in finalDepends)
                {
                    dependsInNamespace.LoadAllDependendencyNamespaces(namespaceToDepends);
                }

                return(finalDepends);
            }
예제 #10
0
 private static IEnumerable <ITypeDefinition> GetSelfDefinedWinmdToplevelTypes(DecompilerTypeSystem winmd)
 {
     return(winmd.GetTopLevelTypeDefinitions().Where(
                type => type.ParentModule == winmd.MainModule && type.FullName != "<Module>"));
 }