Example #1
0
        public static TypeDefinitionHandle FindTestType(MetadataReader reader, Type type)
        {
            if (type.DeclaringType == null)
            {
                foreach (TypeDefinitionHandle handle in reader.TypeDefinitions)
                {
                    TypeDefinition definition = reader.GetTypeDefinition(handle);
                    if (reader.StringComparer.Equals(definition.Namespace, type.Namespace) &&
                        reader.StringComparer.Equals(definition.Name, type.Name))
                    {
                        return handle;
                    }
                }
            }
            else
            {
                TypeDefinitionHandle declaringHandle = FindTestType(reader, type.DeclaringType);
                TypeDefinition declaringDefinition = reader.GetTypeDefinition(declaringHandle);
                foreach (TypeDefinitionHandle handle in declaringDefinition.GetNestedTypes())
                {
                    TypeDefinition definition = reader.GetTypeDefinition(handle);
                    if (reader.StringComparer.Equals(definition.Name, type.Name))
                    {
                        return handle;
                    }
                }
            }

            Assert.True(false, "Cannot find test type:" + type);
            return default(TypeDefinitionHandle);
        }
Example #2
0
 public static bool HasGeneratedName(this TypeDefinitionHandle handle, MetadataReader metadata)
 {
     return(metadata.GetTypeDefinition(handle).Name.IsGeneratedName(metadata));
 }
Example #3
0
 public static bool IsCompilerGenerated(this TypeDefinitionHandle handle, MetadataReader metadata)
 {
     return(metadata.GetTypeDefinition(handle).IsCompilerGenerated(metadata));
 }
Example #4
0
        public override string GetEntityName(PEFile module, EntityHandle handle, bool fullName)
        {
            MetadataReader metadata = module.Metadata;

            switch (handle.Kind)
            {
            case HandleKind.TypeDefinition:
                return(ToCSharpString(metadata, (TypeDefinitionHandle)handle, fullName));

            case HandleKind.FieldDefinition:
                var fd            = metadata.GetFieldDefinition((FieldDefinitionHandle)handle);
                var declaringType = fd.GetDeclaringType();
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + metadata.GetString(fd.Name));
                }
                return(metadata.GetString(fd.Name));

            case HandleKind.MethodDefinition:
                var md = metadata.GetMethodDefinition((MethodDefinitionHandle)handle);
                declaringType = md.GetDeclaringType();
                string methodName = metadata.GetString(md.Name);
                switch (methodName)
                {
                case ".ctor":
                case ".cctor":
                    var td = metadata.GetTypeDefinition(declaringType);
                    methodName = ReflectionHelper.SplitTypeParameterCountFromReflectionName(metadata.GetString(td.Name));
                    break;

                case "Finalize":
                    const MethodAttributes finalizerAttributes = (MethodAttributes.Virtual | MethodAttributes.Family | MethodAttributes.HideBySig);
                    if ((md.Attributes & finalizerAttributes) != finalizerAttributes)
                    {
                        goto default;
                    }
                    MethodSignature <IType> methodSignature = md.DecodeSignature(MetadataExtensions.MinimalSignatureTypeProvider, default);
                    if (methodSignature.GenericParameterCount != 0 || methodSignature.ParameterTypes.Length != 0)
                    {
                        goto default;
                    }
                    td         = metadata.GetTypeDefinition(declaringType);
                    methodName = "~" + ReflectionHelper.SplitTypeParameterCountFromReflectionName(metadata.GetString(td.Name));
                    break;

                default:
                    var genericParams = md.GetGenericParameters();
                    if (genericParams.Count > 0)
                    {
                        methodName += "<";
                        int i = 0;
                        foreach (var h in genericParams)
                        {
                            if (i > 0)
                            {
                                methodName += ",";
                            }
                            var gp = metadata.GetGenericParameter(h);
                            methodName += metadata.GetString(gp.Name);
                        }
                        methodName += ">";
                    }
                    break;
                }
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + methodName);
                }
                return(methodName);

            case HandleKind.EventDefinition:
                var ed = metadata.GetEventDefinition((EventDefinitionHandle)handle);
                declaringType = metadata.GetMethodDefinition(ed.GetAccessors().GetAny()).GetDeclaringType();
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + metadata.GetString(ed.Name));
                }
                return(metadata.GetString(ed.Name));

            case HandleKind.PropertyDefinition:
                var pd = metadata.GetPropertyDefinition((PropertyDefinitionHandle)handle);
                declaringType = metadata.GetMethodDefinition(pd.GetAccessors().GetAny()).GetDeclaringType();
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + metadata.GetString(pd.Name));
                }
                return(metadata.GetString(pd.Name));

            default:
                return(null);
            }
        }
Example #5
0
 public static bool IsValueType(this TypeDefinitionHandle handle, MetadataReader reader)
 {
     return(reader.GetTypeDefinition(handle).IsValueType(reader));
 }
        internal unsafe IList <TypeModel> ProcessAssembly(string packageId, string packageVersion, IEnumerable <FrameworkName> targetFrameworks, Stream assemblyStream)
        {
            var assemblyName = "";

            try
            {
                var targetFrameworkNames = targetFrameworks == null
                    ? new List <string>()
                    : targetFrameworks.Select(x => VersionUtility.GetShortFrameworkName(x));

                using (var peReader = new PEReader(assemblyStream))
                {
                    if (!peReader.HasMetadata)
                    {
                        return(null);
                    }

                    var metadataBlock = peReader.GetMetadata();
                    if (metadataBlock.Pointer == (byte *)IntPtr.Zero || metadataBlock.Length <= 0)
                    {
                        return(null);
                    }

                    var reader = new MetadataReader(metadataBlock.Pointer, metadataBlock.Length);

                    assemblyName = reader.GetString(reader.GetModuleDefinition().Name);
                    var typeHandlers = reader.TypeDefinitions;
                    var typeEntities = new List <TypeModel>();
                    foreach (var typeHandler in typeHandlers)
                    {
                        var typeDef = reader.GetTypeDefinition(typeHandler);

                        if ((typeDef.Attributes & System.Reflection.TypeAttributes.Public) != System.Reflection.TypeAttributes.Public)
                        {
                            continue;
                        }

                        var typeName      = reader.GetString(typeDef.Name);
                        var typeNamespace = reader.GetString(typeDef.Namespace);

                        var newModel = new TypeModel
                        {
                            Name           = typeName,
                            FullName       = string.IsNullOrEmpty(typeNamespace) ? typeName : typeNamespace + "." + typeName,
                            AssemblyName   = assemblyName,
                            PackageName    = packageId,
                            PackageVersion = packageVersion
                        };

                        newModel.TargetFrameworks.AddRange(targetFrameworkNames);

                        typeEntities.Add(newModel);
                    }
                    return(typeEntities);
                }
            }
            catch (Exception ex)
            {
                Logger.WriteError("Types discovery error: {0}. Package: {1} {2}, assembly: {3}", ex.Message, packageId, packageVersion, assemblyName);
            }

            return(null);
        }
Example #7
0
            private void LookupMetadataDefinitions(
                TypeDefinition typeDefinition,
                OrderPreservingMultiDictionary <string, MetadataDefinition> definitionMap)
            {
                // Only bother looking for extension methods in static types.
                // Note this check means we would ignore extension methods declared in assemblies
                // compiled from VB code, since a module in VB is compiled into class with
                // "sealed" attribute but not "abstract".
                // Although this can be addressed by checking custom attributes,
                // we believe this is not a common scenario to warrant potential perf impact.
                if ((typeDefinition.Attributes & TypeAttributes.Abstract) != 0 &&
                    (typeDefinition.Attributes & TypeAttributes.Sealed) != 0)
                {
                    foreach (var child in typeDefinition.GetMethods())
                    {
                        var method = _metadataReader.GetMethodDefinition(child);
                        if ((method.Attributes & MethodAttributes.SpecialName) != 0 ||
                            (method.Attributes & MethodAttributes.RTSpecialName) != 0)
                        {
                            continue;
                        }

                        // SymbolTreeInfo is only searched for types and extension methods.
                        // So we don't want to pull in all methods here.  As a simple approximation
                        // we just pull in methods that have attributes on them.
                        if ((method.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public &&
                            (method.Attributes & MethodAttributes.Static) != 0 &&
                            method.GetParameters().Count > 0 &&
                            method.GetCustomAttributes().Count > 0)
                        {
                            // Decode method signature to get the receiver type name (i.e. type name for the first parameter)
                            var blob      = _metadataReader.GetBlobReader(method.Signature);
                            var decoder   = new SignatureDecoder <ParameterTypeInfo, object>(ParameterTypeInfoProvider.Instance, _metadataReader, genericContext: null);
                            var signature = decoder.DecodeMethodSignature(ref blob);

                            // It'd be good if we don't need to go through all parameters and make unnecessary allocations.
                            // However, this is not possible with meatadata reader API right now (although it's possible by copying code from meatadata reader implementaion)
                            if (signature.ParameterTypes.Length > 0)
                            {
                                _containsExtensionsMethod = true;
                                var firstParameterTypeInfo = signature.ParameterTypes[0];
                                var definition             = new MetadataDefinition(MetadataDefinitionKind.Member, _metadataReader.GetString(method.Name), firstParameterTypeInfo);
                                definitionMap.Add(definition.Name, definition);
                            }
                        }
                    }
                }

                foreach (var child in typeDefinition.GetNestedTypes())
                {
                    var type = _metadataReader.GetTypeDefinition(child);

                    // We don't include internals from metadata assemblies.  It's less likely that
                    // a project would have IVT to it and so it helps us save on memory.  It also
                    // means we can avoid loading lots and lots of obfuscated code in the case the
                    // dll was obfuscated.
                    if (IsPublic(type.Attributes))
                    {
                        var definition = MetadataDefinition.Create(_metadataReader, type);
                        definitionMap.Add(definition.Name, definition);
                        _allTypeDefinitions.Add(definition);
                    }
                }
            }
        private void AddPdb(string moduleName, MetadataReader peMetadataReader, MetadataReader pdbMetadataReader)
        {
            // Add all the documents (source files)
            var tempDocNameToSourceFileMap = new Dictionary <string, SourceFileInfo>();

            foreach (var docHandle in pdbMetadataReader.Documents)
            {
                var doc        = pdbMetadataReader.GetDocument(docHandle);
                var docRawName = pdbMetadataReader.GetString(doc.Name);
                var filenameWithForwardSlashes = docRawName.Replace('\\', '/');
                var url        = $"{DotnetSourceFilePrefix}//{moduleName}/{filenameWithForwardSlashes}";
                var sourceFile = new SourceFileInfo
                {
                    Id           = $"{DotnetSourceFilePrefix}{nextSourceFileId++}",
                    AssemblyName = moduleName,
                    FileName     = filenameWithForwardSlashes,
                    Url          = url,
                    PossibleBreakpointLocationsByLine = new Dictionary <int, List <PossibleBreakpointLocation> >()
                };
                _sourceFiles.Add(sourceFile.Id, sourceFile);
                tempDocNameToSourceFileMap.Add(docRawName, sourceFile);
            }

            // Add all the debug sequence points
            foreach (var methodDebugInfoHandle in pdbMetadataReader.MethodDebugInformation)
            {
                var    methodDebugInfo = pdbMetadataReader.GetMethodDebugInformation(methodDebugInfoHandle);
                var    methodDefHandle = methodDebugInfoHandle.ToDefinitionHandle();
                var    methodDef       = peMetadataReader.GetMethodDefinition(methodDefHandle);
                var    document        = pdbMetadataReader.GetDocument(methodDebugInfo.Document);
                string documentName    = null;
                try
                {
                    documentName = pdbMetadataReader.GetString(document.Name);
                }
                catch (Exception)
                {
                    // If the document name isn't readable, don't process it
                }
                if (documentName != null && tempDocNameToSourceFileMap.TryGetValue(documentName, out var sourceFile))
                {
                    // Construct the DNA method identifier string
                    var methodDefToken       = MetadataTokens.GetToken(methodDefHandle);
                    var methodDebugInfoToken = MetadataTokens.GetToken(methodDefHandle);
                    var declaringType        = peMetadataReader.GetTypeDefinition(methodDef.GetDeclaringType());
                    var namespaceName        = peMetadataReader.GetString(declaringType.Namespace);
                    var className            = peMetadataReader.GetString(declaringType.Name);
                    var methodName           = peMetadataReader.GetString(methodDef.Name);
                    var dnaMethodIdentifier  = moduleName + namespaceName + className + methodName;

                    // Add PossibleBreakpointLocation objects to the sourcefile
                    int sequencePointIndex = 0;
                    foreach (var sequencePoint in methodDebugInfo.GetSequencePoints().Where(sp => !sp.IsHidden))
                    {
                        var possibleBreakpointLocations = sourceFile.PossibleBreakpointLocationsByLine;
                        var lineNumber = sequencePoint.StartLine;
                        if (!possibleBreakpointLocations.TryGetValue(lineNumber, out _))
                        {
                            possibleBreakpointLocations.Add(lineNumber, new List <PossibleBreakpointLocation>());
                        }
                        possibleBreakpointLocations[lineNumber].Add(new PossibleBreakpointLocation
                        {
                            DnaMethodIdentifier = dnaMethodIdentifier,
                            SequencePointIndex  = sequencePointIndex,
                            SequencePointInfo   = sequencePoint,
                            MethodName          = methodName,
                            SourceFile          = sourceFile,
                        });

                        sequencePointIndex++;
                    }
                }
            }
        }
Example #9
0
        internal void Resolve(TRequest request, RequestSignature signature)
        {
            QualifiedName           qualifiedTypeName;
            ImmutableArray <string> memberTypeParameters;

            GetNameAndTypeParameters(signature.MemberName, out qualifiedTypeName, out memberTypeParameters);

            var typeName         = qualifiedTypeName.Qualifier;
            var memberName       = qualifiedTypeName.Name;
            var memberParameters = signature.Parameters;

            var allTypeParameters = GetAllGenericTypeParameters(typeName);

            foreach (var typeHandle in _reader.TypeDefinitions)
            {
                var typeDef         = _reader.GetTypeDefinition(typeHandle);
                int containingArity = CompareToTypeDefinition(typeDef, typeName);
                if (containingArity < 0)
                {
                    continue;
                }

                // Visit methods.
                foreach (var methodHandle in typeDef.GetMethods())
                {
                    var methodDef = _reader.GetMethodDefinition(methodHandle);
                    if (!IsResolvableMethod(methodDef))
                    {
                        continue;
                    }
                    if (MatchesMethod(typeDef, methodDef, memberName, allTypeParameters, containingArity, memberTypeParameters, memberParameters))
                    {
                        OnFunctionResolved(request, methodHandle);
                    }
                }

                if (memberTypeParameters.IsEmpty)
                {
                    // Visit properties.
                    foreach (var propertyHandle in typeDef.GetProperties())
                    {
                        var propertyDef = _reader.GetPropertyDefinition(propertyHandle);
                        var accessors   = propertyDef.GetAccessors();
                        if (MatchesPropertyOrEvent(propertyDef.Name, accessors.Getter, memberName, allTypeParameters, containingArity, memberParameters))
                        {
                            OnAccessorResolved(request, accessors.Getter);
                            OnAccessorResolved(request, accessors.Setter);
                        }
                    }

                    // Visit events.
                    foreach (var eventHandle in typeDef.GetEvents())
                    {
                        var eventDef  = _reader.GetEventDefinition(eventHandle);
                        var accessors = eventDef.GetAccessors();

                        if (MatchesPropertyOrEvent(eventDef.Name, accessors.Adder, memberName, allTypeParameters, containingArity, memberParameters))
                        {
                            OnAccessorResolved(request, accessors.Adder);
                            OnAccessorResolved(request, accessors.Remover);
                        }
                    }
                }
            }
        }
        // internal for testing
        internal static void GetAnonymousTypeMapFromMetadata(
            MetadataReader reader,
            MetadataDecoder metadataDecoder,
            out IReadOnlyDictionary <AnonymousTypeKey, AnonymousTypeValue> anonymousTypes,
            out IReadOnlyDictionary <string, AnonymousTypeValue> anonymousDelegatesWithFixedTypes)
        {
            // In general, the anonymous type name is "<{module-id}>f__AnonymousType{index}#{submission-index}",
            // but EnC is not supported for modules nor submissions. Hence we only look for type names with no module id and no submission index.
            const string AnonymousTypeOrDelegateNamePrefix        = "<>f__Anonymous";
            const string AnonymousTypeNameWithoutModulePrefix     = AnonymousTypeOrDelegateNamePrefix + "Type";
            const string AnonymousDelegateNameWithoutModulePrefix = AnonymousTypeOrDelegateNamePrefix + "Delegate";

            var types     = new Dictionary <AnonymousTypeKey, AnonymousTypeValue>();
            var delegates = new Dictionary <string, AnonymousTypeValue>();

            foreach (var handle in reader.TypeDefinitions)
            {
                var def = reader.GetTypeDefinition(handle);
                if (!def.Namespace.IsNil)
                {
                    continue;
                }

                if (!reader.StringComparer.StartsWith(def.Name, AnonymousTypeOrDelegateNamePrefix))
                {
                    continue;
                }

                var metadataName = reader.GetString(def.Name);
                var name         = MetadataHelpers.InferTypeArityAndUnmangleMetadataName(metadataName, out _);

                if (name.StartsWith(AnonymousTypeNameWithoutModulePrefix, StringComparison.Ordinal))
                {
                    if (int.TryParse(name.Substring(AnonymousTypeNameWithoutModulePrefix.Length), NumberStyles.None, CultureInfo.InvariantCulture, out int index))
                    {
                        var builder = ArrayBuilder <AnonymousTypeKeyField> .GetInstance();

                        if (TryGetAnonymousTypeKey(reader, def, builder))
                        {
                            var type  = (NamedTypeSymbol)metadataDecoder.GetTypeOfToken(handle);
                            var key   = new AnonymousTypeKey(builder.ToImmutable());
                            var value = new AnonymousTypeValue(name, index, type.GetCciAdapter());
                            types.Add(key, value);
                        }
                        builder.Free();
                    }
                }
                else if (name.StartsWith(AnonymousDelegateNameWithoutModulePrefix, StringComparison.Ordinal))
                {
                    if (int.TryParse(name.Substring(AnonymousDelegateNameWithoutModulePrefix.Length), NumberStyles.None, CultureInfo.InvariantCulture, out int index))
                    {
                        var type  = (NamedTypeSymbol)metadataDecoder.GetTypeOfToken(handle);
                        var value = new AnonymousTypeValue(name, index, type.GetCciAdapter());
                        delegates.Add(name, value);
                    }
                }
            }

            anonymousTypes = types;
            anonymousDelegatesWithFixedTypes = delegates;
        }
Example #11
0
        public override string GetEntityName(PEFile module, EntityHandle handle, bool fullName)
        {
            MetadataReader metadata = module.Metadata;

            switch (handle.Kind)
            {
            case HandleKind.TypeDefinition:
                return(ToCSharpString(metadata, (TypeDefinitionHandle)handle, fullName));

            case HandleKind.FieldDefinition:
                var fd            = metadata.GetFieldDefinition((FieldDefinitionHandle)handle);
                var declaringType = fd.GetDeclaringType();
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + metadata.GetString(fd.Name));
                }
                return(metadata.GetString(fd.Name));

            case HandleKind.MethodDefinition:
                var md = metadata.GetMethodDefinition((MethodDefinitionHandle)handle);
                declaringType = md.GetDeclaringType();
                string methodName = metadata.GetString(md.Name);
                if (methodName == ".ctor" || methodName == ".cctor")
                {
                    var td = metadata.GetTypeDefinition(declaringType);
                    methodName = ReflectionHelper.SplitTypeParameterCountFromReflectionName(metadata.GetString(td.Name));
                }
                else
                {
                    var genericParams = md.GetGenericParameters();
                    if (genericParams.Count > 0)
                    {
                        methodName += "<";
                        int i = 0;
                        foreach (var h in genericParams)
                        {
                            if (i > 0)
                            {
                                methodName += ",";
                            }
                            var gp = metadata.GetGenericParameter(h);
                            methodName += metadata.GetString(gp.Name);
                        }
                        methodName += ">";
                    }
                }
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + methodName);
                }
                return(methodName);

            case HandleKind.EventDefinition:
                var ed = metadata.GetEventDefinition((EventDefinitionHandle)handle);
                declaringType = metadata.GetMethodDefinition(ed.GetAccessors().GetAny()).GetDeclaringType();
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + metadata.GetString(ed.Name));
                }
                return(metadata.GetString(ed.Name));

            case HandleKind.PropertyDefinition:
                var pd = metadata.GetPropertyDefinition((PropertyDefinitionHandle)handle);
                declaringType = metadata.GetMethodDefinition(pd.GetAccessors().GetAny()).GetDeclaringType();
                if (fullName)
                {
                    return(ToCSharpString(metadata, declaringType, fullName) + "." + metadata.GetString(pd.Name));
                }
                return(metadata.GetString(pd.Name));

            default:
                return(null);
            }
        }
Example #12
0
        public async Task Populate()
        {
            this.IsMefAssembly    = true;
            this.fullAssemblyName = this.metadataReader.GetFullAssemblyName();

            this.knownExportAttributeOrDerivedType = new HashSet <string>()
            {
                "System.ComponentModel.Composition.ExportAttribute",
                "System.ComponentModel.Composition.InheritedExportAttribute"
            };
            this.knownImportAttributeOrDerivedType = new HashSet <string>()
            {
                "System.ComponentModel.Composition.ImportAttribute",
                "System.ComponentModel.Composition.ImportManyAttribute"
            };

            var referenceFullNames = metadataReader.GetReferenceAssemblyFullNames();
            var tasks = new List <Task <AssemblyCatalogInfo> >();

            foreach (var referenceAssemblyFullName in referenceFullNames)
            {
                var referenceCatalog = this.discovery.GetAssemblyCatalogInfoFromAssemblyName(referenceAssemblyFullName);
                if (referenceCatalog != null)
                {
                    tasks.Add(referenceCatalog);
                }
            }

            foreach (var task in tasks)
            {
                var referenceCatalog = await task.ConfigureAwait(false);

                if (referenceCatalog == null)
                {
                    continue;
                }

                var knownExportAttributes = referenceCatalog.KnownExportOrDerived;
                foreach (var known in knownExportAttributes)
                {
                    knownExportAttributeOrDerivedType.Add(known);
                }

                var knownImportAttributes = referenceCatalog.KnownImportOrDerived;
                foreach (var known in knownImportAttributes)
                {
                    knownImportAttributeOrDerivedType.Add(known);
                }
            }

            foreach (var typeHandle in metadataReader.TypeDefinitions)
            {
                var typeDefinition = metadataReader.GetTypeDefinition(typeHandle);
                Walk(typeDefinition);
            }

            foreach (var customAttributeHandle in metadataReader.CustomAttributes)
            {
                var customAttribute     = metadataReader.GetCustomAttribute(customAttributeHandle);
                var attributeTypeHandle = metadataReader.GetAttributeTypeHandle(customAttribute);

                if (TryHandleImportAttribute(customAttribute, attributeTypeHandle))
                {
                    continue;
                }

                if (TryHandleExportAttribute(customAttribute, attributeTypeHandle))
                {
                    continue;
                }
            }
        }
 public static StringHandle[] GetTypeDefNames(this MetadataReader reader)
 {
     return(reader.TypeDefinitions.Select(handle => reader.GetTypeDefinition(handle).Name).ToArray());
 }
Example #14
0
 public static string ToString(this MetadataReader reader, TypeDefinitionHandle x) => reader.ToString(reader.GetTypeDefinition(x));
Example #15
0
        public static bool CompareTypeReferenceToDefinition(TypeReferenceHandle tr1, MetadataReader mr1, TypeDefinitionHandle td2, MetadataReader mr2)
        {
            // TODO! The correct implementation here is probably to call into the assembly binder, but that's not available due to layering.
            // For now, just implement comparison, which will be equivalent in all cases until we support loading multiple copies of the same assembly

            TypeReference trData1 = mr1.GetTypeReference(tr1);
            TypeDefinition tdData2 = mr2.GetTypeDefinition(td2);

            if (!trData1.TypeName.StringEquals(tdData2.Name.GetConstantStringValue(mr2).Value, mr1))
                return false;

            switch (trData1.ParentNamespaceOrType.HandleType)
            {
                case HandleType.TypeReference:
                    if (tdData2.EnclosingType.IsNull(mr2))
                        return false;

                    return CompareTypeReferenceToDefinition(trData1.ParentNamespaceOrType.ToTypeReferenceHandle(mr1), mr1, tdData2.EnclosingType, mr2);

                case HandleType.NamespaceReference:
                    return CompareNamespaceReferenceToDefinition(trData1.ParentNamespaceOrType.ToNamespaceReferenceHandle(mr1), mr1, tdData2.NamespaceDefinition, mr2);

                default:
                    Debug.Assert(false);
                    throw new BadImageFormatException();
            }
        }
Example #16
0
        private void PrintVerifyMethodsResult(VerificationResult result, EcmaModule module, string pathOrModuleName)
        {
            Write("[IL]: Error [");
            if (result.Code != VerifierError.None)
            {
                Write(result.Code);
            }
            else
            {
                Write(result.ExceptionID);
            }
            Write("]: ");

            Write("[");
            Write(pathOrModuleName);
            Write(" : ");

            MetadataReader metadataReader = module.MetadataReader;

            TypeDefinition typeDef       = metadataReader.GetTypeDefinition(metadataReader.GetMethodDefinition(result.Method).GetDeclaringType());
            string         typeNamespace = metadataReader.GetString(typeDef.Namespace);

            Write(typeNamespace);
            Write(".");
            string typeName = metadataReader.GetString(typeDef.Name);

            Write(typeName);

            Write("::");
            var method = (EcmaMethod)module.GetMethod(result.Method);

            PrintMethod(method);
            Write("]");

            if (result.Code != VerifierError.None)
            {
                Write("[offset 0x");
                Write(result.GetArgumentValue <int>("Offset").ToString("X8"));
                Write("]");

                if (result.TryGetArgumentValue("Found", out string found))
                {
                    Write("[found ");
                    Write(found);
                    Write("]");
                }

                if (result.TryGetArgumentValue("Expected", out string expected))
                {
                    Write("[expected ");
                    Write(expected);
                    Write("]");
                }

                if (result.TryGetArgumentValue("Token", out int token))
                {
                    Write("[token  0x");
                    Write(token.ToString("X8"));
                    Write("]");
                }
            }

            Write(" ");
            WriteLine(result.Message);
        }
Example #17
0
        /// <summary>
        /// Helper method that will validate that a NamespaceDefinition (and all NamespaceDefinitions considered children
        /// of it) report correct values for their child namespaces, types, etc. All namespaces in the module are expected
        /// to be listed in the allNamespaces array. Additionally, the global namespace is expected to have type definitions
        /// for GlobalClassA, GlobalClassB, and Module. No type forwarder declarations are expected.
        /// 
        /// All namespaces that aren't the global NS are expected to have type definitions equal to the array
        /// @namespaceName.Split('.')
        /// So, ns1.Ns2.NS3 is expected to have type definitions
        /// {"ns1", "Ns2", "NS3"}.
        /// 
        /// definitionExceptions and forwarderExceptions may be used to override the default expectations. Pass in 
        /// namespace (key) and what is expected (list of strings) for each exception.
        /// </summary>
        private void ValidateNamespaceChildren(
            MetadataReader reader,
            NamespaceDefinitionHandle initHandle,
            string[] allNamespaces,
            IReadOnlyDictionary<string, IList<string>> definitionExceptions = null,
            IReadOnlyDictionary<string, IList<string>> forwarderExceptions = null)
        {
            // Don't want to have to deal with null.
            if (definitionExceptions == null)
            {
                definitionExceptions = new Dictionary<string, IList<string>>();
            }

            if (forwarderExceptions == null)
            {
                forwarderExceptions = new Dictionary<string, IList<string>>();
            }

            var rootNamespaceDefinition = reader.GetNamespaceDefinition(initHandle);
            string rootNamespaceName = reader.GetString(initHandle);

            // We need to be in the table of all namespaces...
            Assert.Contains(rootNamespaceName, allNamespaces);

            // Cool. Now check to make sure that .Name only returns the last bit of our namespace name.
            var expNamespaceNameSegment = rootNamespaceName.Split('.').Last();
            var rootNamespaceNameSegment = reader.GetString(rootNamespaceDefinition.Name);
            Assert.Equal(expNamespaceNameSegment, rootNamespaceNameSegment);

            bool isGlobalNamespace = rootNamespaceName.Length == 0;
            string[] expTypeDefinitions = null;
            // Special case: Global NS has GlobalClassA, GlobalClassB. Others just have autogenerated classes.
            if (definitionExceptions.ContainsKey(rootNamespaceName))
            {
                expTypeDefinitions = definitionExceptions[rootNamespaceName].ToArray();
            }
            else if (isGlobalNamespace)
            {
                expTypeDefinitions = new[] { "GlobalClassA", "GlobalClassB", "<Module>" };
            }
            else
            {
                expTypeDefinitions = rootNamespaceName.Split('.');
            }

            // Validating type definitions inside the namespace...
            int numberOfTypeDefinitions = 0;
            foreach (var definitionHandle in rootNamespaceDefinition.TypeDefinitions)
            {
                var definition = reader.GetTypeDefinition(definitionHandle);
                var definitionName = reader.GetString(definition.Name);
                var definitionFullNamespaceName = reader.GetString(definition.Namespace);
                Assert.Equal(rootNamespaceName, definitionFullNamespaceName);
                Assert.Contains(definitionName, expTypeDefinitions);
                numberOfTypeDefinitions += 1;
            }

            // Guarantee that there are no extra unexpected members...
            Assert.Equal(numberOfTypeDefinitions, expTypeDefinitions.Length);

            string[] expTypeForwarders = null;
            if (forwarderExceptions.ContainsKey(rootNamespaceName))
            {
                expTypeForwarders = forwarderExceptions[rootNamespaceName].ToArray();
            }
            else
            {
                expTypeForwarders = new string[] { };
            }

            int numberOfTypeForwarders = 0;
            foreach (var forwarderHandle in rootNamespaceDefinition.ExportedTypes)
            {
                var forwarder = reader.GetExportedType(forwarderHandle);
                Assert.True(reader.StringComparer.Equals(forwarder.Namespace, rootNamespaceName));
                var forwarderName = reader.GetString(forwarder.Name);
                Assert.Contains(forwarderName, expTypeForwarders);
                numberOfTypeForwarders += 1;
            }
            Assert.Equal(expTypeForwarders.Length, numberOfTypeForwarders);

            // Validate sub-namespaces

            // If the last index of '.' in a namespace name is == the current name's length, then
            // that ns is a direct child of the current one!
            IList<String> expChildren = null;

            // Special case: Global NS's children won't have .s in them.
            if (isGlobalNamespace)
            {
                expChildren = allNamespaces.Where(ns => !String.IsNullOrEmpty(ns) && !ns.Contains('.')).ToList();
            }
            else
            {
                expChildren = allNamespaces
                    .Where(ns => ns.StartsWith(rootNamespaceName) && ns.LastIndexOf('.') == rootNamespaceName.Length)
                    .ToList();
            }

            int numberOfSubNamespaces = 0;
            foreach (var subNamespaceHandle in rootNamespaceDefinition.NamespaceDefinitions)
            {
                Assert.False(subNamespaceHandle.IsNil);
                string subNamespaceFullName = reader.GetString(subNamespaceHandle);
                NamespaceDefinition subNamespace = reader.GetNamespaceDefinition(subNamespaceHandle);

                string subNamespaceName = subNamespaceFullName.Split('.').Last();
                Assert.Equal(subNamespaceName, reader.GetString(subNamespace.Name));
                Assert.True(reader.StringComparer.Equals(subNamespace.Name, subNamespaceName));
                Assert.True(reader.StringComparer.StartsWith(subNamespace.Name, subNamespaceName));
                Assert.True(reader.StringComparer.StartsWith(subNamespace.Name, subNamespaceName.Substring(0, subNamespaceName.Length - 1)));

                Assert.Equal(subNamespace.Parent, initHandle);
                Assert.Contains(subNamespaceFullName, expChildren);
                ValidateNamespaceChildren(reader, subNamespaceHandle, allNamespaces, definitionExceptions, forwarderExceptions);
                numberOfSubNamespaces += 1;
            }
            // Guarantee no extra unexpected namespaces...
            Assert.Equal(expChildren.Count, numberOfSubNamespaces);
        }
Example #18
0
        /*
         * Go through all reference assemblies of .NET Core and generate the type catalog -> Dictionary<NamespaceQualifiedTypeName, TPAStrongName>
         * Then auto-generate the partial class 'PowerShellAssemblyLoadContext' that has the code to initialize the type catalog cache.
         *
         * In CoreCLR, there is no way to get all loaded TPA assemblies (.NET Framework Assemblies). In order to get type based on type name, powershell needs to know what .NET
         * types are available and in which TPA assemblies. So we have to generate the type catalog based on the reference assemblies of .NET Core.
         */
        public static void Main(string[] args)
        {
            if (args.Length < 2 || args.Length > 3)
            {
                string message = string.Format(CultureInfo.CurrentCulture, HelpMessage,
                                               Param_TargetCSharpFilePath,
                                               Param_ReferenceListPath,
                                               Param_PrintDebugMessage);
                Console.WriteLine(message);
                return;
            }

            bool          printDebugMessage = args.Length == 3 && string.Equals(Param_PrintDebugMessage, args[2], StringComparison.OrdinalIgnoreCase);
            string        targetFilePath    = ResolveTargetFilePath(args[0]);
            List <string> refAssemblyFiles  = ResolveReferenceAssemblies(args[1]);

            Dictionary <string, TypeMetadata> typeNameToAssemblyMap = new Dictionary <string, TypeMetadata>(StringComparer.OrdinalIgnoreCase);

            // mscorlib.metadata_dll doesn't contain any type definition.
            foreach (string filePath in refAssemblyFiles)
            {
                if (!filePath.EndsWith(".METADATA_DLL", StringComparison.OrdinalIgnoreCase) &&
                    !filePath.EndsWith(".DLL", StringComparison.OrdinalIgnoreCase))
                {
                    string message = string.Format(CultureInfo.CurrentCulture, UnexpectedFileExtension, filePath);
                    throw new InvalidOperationException(message);
                }

                using (Stream stream = File.OpenRead(filePath))
                    using (PEReader peReader = new PEReader(stream))
                    {
                        MetadataReader metadataReader     = peReader.GetMetadataReader();
                        string         strongAssemblyName = GetAssemblyStrongName(metadataReader);

                        foreach (TypeDefinitionHandle typeHandle in metadataReader.TypeDefinitions)
                        {
                            // We only care about public types
                            TypeDefinition typeDefinition = metadataReader.GetTypeDefinition(typeHandle);
                            // The visibility mask is used to mask out the bits that contain the visibility.
                            // The visibilities are not combineable, e.g. you can't be both public and private, which is why these aren't independent powers of two.
                            TypeAttributes visibilityBits = typeDefinition.Attributes & TypeAttributes.VisibilityMask;
                            if (visibilityBits != TypeAttributes.Public && visibilityBits != TypeAttributes.NestedPublic)
                            {
                                continue;
                            }

                            string fullName       = GetTypeFullName(metadataReader, typeDefinition);
                            bool   isTypeObsolete = IsTypeObsolete(metadataReader, typeDefinition);

                            if (!typeNameToAssemblyMap.ContainsKey(fullName))
                            {
                                // Add unique type.
                                typeNameToAssemblyMap.Add(fullName, new TypeMetadata(strongAssemblyName, isTypeObsolete));
                            }
                            else if (typeNameToAssemblyMap[fullName].IsObsolete && !isTypeObsolete)
                            {
                                // Duplicate types found defined in different assemblies, but the previous one is obsolete while the current one is not.
                                // Replace the existing type with the current one.
                                if (printDebugMessage)
                                {
                                    var existingTypeMetadata = typeNameToAssemblyMap[fullName];
                                    Console.WriteLine($@"
REPLACE '{fullName}' from '{existingTypeMetadata.AssemblyName}' (IsObsolete? {existingTypeMetadata.IsObsolete})
  WITH '{strongAssemblyName}' (IsObsolete? {isTypeObsolete})");
                                }

                                typeNameToAssemblyMap[fullName] = new TypeMetadata(strongAssemblyName, isTypeObsolete);
                            }
                            else if (printDebugMessage)
                            {
                                // Duplicate types found defined in different assemblies, and fall into one of the following conditions:
                                //  - both are obsolete
                                //  - both are not obsolete
                                //  - the existing type is not obsolete while the new one is obsolete
                                var existingTypeMetadata = typeNameToAssemblyMap[fullName];
                                Console.WriteLine($@"
DUPLICATE key '{fullName}' from '{strongAssemblyName}' (IsObsolete? {isTypeObsolete}).
  -- Already exist in '{existingTypeMetadata.AssemblyName}' (IsObsolete? {existingTypeMetadata.IsObsolete})");
                            }
                        }
                    }
            }

            WritePowerShellAssemblyLoadContextPartialClass(targetFilePath, typeNameToAssemblyMap);
        }