示例#1
0
        private static TFields GetStructFields <TFields>(StructMetadata metadata)
            where TFields : class, new()
        {
            if (metadata.Fields != null)
            {
                return((TFields)metadata.Fields);
            }

            var fields = new TFields();

            foreach (var fieldInfo in typeof(TFields).GetFields())
            {
                var fieldType = fieldInfo.FieldType;
                if (fieldType.GetInterfaces().Contains(typeof(IStructField)))
                {
                    Debug.Assert(!fieldInfo.IsInitOnly);
                    long offset = metadata.Symbol.GetFieldOffset(fieldInfo.Name);
                    var  field  = (IStructField)Activator.CreateInstance(fieldType);
                    field.Process = metadata.Process;
                    field.Offset  = offset;
                    fieldInfo.SetValue(fields, field);
                }
            }

            metadata.Fields = fields;
            return(fields);
        }
示例#2
0
        public static TFields GetStructFields <TStruct, TFields>(DkmProcess process)
            where TStruct : StructProxy
            where TFields : class, new()
        {
            StructMetadata metadata = GetStructMetadata <TStruct>(process);

            return(GetStructFields <TFields>(metadata));
        }
示例#3
0
        protected void InitializeStruct <TStruct, TFields>(TStruct this_, out TFields fields)
            where TStruct : StructProxy
            where TFields : class, new()
        {
            Debug.Assert(this == this_);

            var metadata = GetStructMetadata <TStruct>(Process);

            fields    = GetStructFields <TFields>(metadata);
            _metadata = metadata;
        }
示例#4
0
        public static StructMetadata GetStructMetadata <TStruct>(DkmProcess process)
            where TStruct : StructProxy
        {
            var metadata = process.GetDataItem <StructMetadata <TStruct> >();

            if (metadata != null)
            {
                return(metadata);
            }

            metadata = new StructMetadata <TStruct>(process);
            process.SetDataItem(DkmDataCreationDisposition.CreateNew, metadata);
            return(metadata);
        }
示例#5
0
        private static StructMetadata GetStructMetadata(Type structType)
        {
            var structMetadata = new StructMetadata(
                structType.Name,
                structType.Namespace,
                GetLongTypeName(structType),
                GetProtectionLevel(structType)
                )
            {
            };

            s_typeCache[structType] = structMetadata;

            structMetadata.DeclaringType = (DefinedTypeMetadata)FromType(structType.DeclaringType);
            structMetadata.Constructors  = GetConstructorMetadata(structType);
            structMetadata.Fields        = GetFieldMetadata(structType);
            (structMetadata.Indexers, structMetadata.Properties) = GetPropertyMetadata(structType);
            structMetadata.Methods = GetMethodMetadata(structType);

            return(structMetadata);
        }
示例#6
0
        private static TFields GetStructFields <TFields>(StructMetadata metadata)
            where TFields : class, new()
        {
            if (metadata.Fields != null)
            {
                return((TFields)metadata.Fields);
            }

            var pyVersion = metadata.Process.GetPythonRuntimeInfo().LanguageVersion;

            var fields = new TFields();

            foreach (var fieldInfo in typeof(TFields).GetFields())
            {
                var fieldType = fieldInfo.FieldType;
                if (fieldType.GetInterfaces().Contains(typeof(IStructField)))
                {
                    Debug.Assert(!fieldInfo.IsInitOnly);

                    var name = GetFieldName(fieldInfo, pyVersion);
                    if (string.IsNullOrEmpty(name))
                    {
                        continue;
                    }

                    long offset = metadata.Symbol.GetFieldOffset(name);
                    var  field  = (IStructField)Activator.CreateInstance(fieldType);
                    field.Process = metadata.Process;
                    field.Offset  = offset;
                    fieldInfo.SetValue(fields, field);
                }
            }

            metadata.Fields = fields;
            return(fields);
        }
示例#7
0
        static void ProcessAssembly(AssemblyDefinition bindingsAssembly, string assemblyPath, string outputPath, BaseAssemblyResolver resolver, string [] knownPaths, NativeTypeManifest manifest, bool verify)
        {
            string metadataFileName = Path.ChangeExtension(outputPath, "json");

            var readerParams = new ReaderParameters {
                AssemblyResolver     = resolver,
                ReadSymbols          = true,
                SymbolReaderProvider = new PortablePdbReaderProvider(),
                ReadingMode          = ReadingMode.Deferred
            };

            var assembly = AssemblyDefinition.ReadAssembly(assemblyPath, readerParams);
            var metadata = new AssemblyMetadata {
                AssemblyName = assembly.Name.Name,
                AssemblyPath = assemblyPath,
                References   = (from module in assembly.Modules
                                from reference in module.AssemblyReferences
                                select AssemblyReferenceMetadata.ResolveReference(reference, resolver, assembly.Name.Name, knownPaths)).ToArray()
            };


            ///////////////////////////////////////////////////////////////////

            //Enums
            var unrealEnums = (from module in assembly.Modules
                               from type in module.Types
                               where type.IsEnum && IsUnrealEnum(type)
                               select type);

            unrealEnums = manifest.CheckForCollisions(unrealEnums, "Enum");

            //Generate metadata
            bool errorGeneratingEnumMetadata = false;
            var  enumMetadata = unrealEnums.ToDictionaryErrorEmit(type => type, type => new EnumMetadata(type), out errorGeneratingEnumMetadata);

            metadata.Enums = enumMetadata.Values.ToArray();

            ///////////////////////////////////////////////////////////////////

            //Structs

            // Capture the current struct list in an array, as IL rewriting for UStructs may add array marshaler types.
            var unrealStructs = (from module in assembly.Modules
                                 from type in module.Types
                                 where type.IsValueType && IsUnrealStruct(type)
                                 select type);


            unrealStructs = manifest.CheckForCollisions(unrealStructs, "Struct");



            // We need to create struct metadata in the correct order to ensure that blittable structs have
            // their UStruct attributes updated before other referencing structs use them to create UnrealTypes.
            var  structStack                    = new Stack <TypeDefinition> ();
            var  pushedStructs                  = new HashSet <TypeDefinition> ();
            var  structHandlingOrder            = new List <TypeDefinition> ();
            var  structMetadata                 = new Dictionary <TypeDefinition, StructMetadata> ();
            bool errorsGeneratingStructMetadata = false;

            foreach (var unrealStruct in unrealStructs)
            {
                if (!pushedStructs.Contains(unrealStruct))
                {
                    structStack.Push(unrealStruct);
                    pushedStructs.Add(unrealStruct);

                    PushReferencedStructsFromAssembly(assembly, unrealStruct, structStack, pushedStructs);

                    while (structStack.Count > 0)
                    {
                        var currentStruct = structStack.Pop();
                        try {
                            if (structMetadata.ContainsKey(currentStruct))
                            {
                                throw new InternalRewriteException(currentStruct, "Attempted to create struct metadata twice");
                            }
                            var currentMetadata = new StructMetadata(currentStruct);

                            structHandlingOrder.Add(currentStruct);
                            structMetadata.Add(currentStruct, currentMetadata);
                        } catch (MonoAssemblyProcessError error) {
                            errorsGeneratingStructMetadata = true;
                            ErrorEmitter.Error(error);
                        }
                    }
                }
            }
            metadata.Structs = structMetadata.Values.ToArray();

            // Rewrite as a separate pass.  For substructs, we need access to metadata.Structs to propagate hashes.
            foreach (var currentStruct in structHandlingOrder)
            {
                StructMetadata currentMetadata = structMetadata [currentStruct];
                RewriteUnrealStruct(metadata, assembly, currentStruct, currentMetadata, bindingsAssembly);
            }

            ///////////////////////////////////////////////////////////////////

            //Classes

            bool unrealClassError;
            // get all the unreal classes (we don't care if they are exported)
            var unrealClasses = assembly.Modules.SelectMany(x => x.Types).SelectWhereErrorEmit(type => type.IsClass && type.BaseType != null && IsUnrealClass(type), type => type, out unrealClassError);

            unrealClasses = manifest.CheckForCollisions(unrealClasses, "Class");

            bool errorGeneratingMetadata;
            var  unrealClassDictionary = unrealClasses.ToDictionaryErrorEmit(type => type, type => ClassMetadata.Create(type, GetUnrealClass(type)), out errorGeneratingMetadata);

            if (errorGeneratingMetadata || errorsGeneratingStructMetadata || errorGeneratingEnumMetadata)
            {
                throw new MetaDataGenerationException();
            }
            metadata.Classes = unrealClassDictionary.Values.ToArray();

            if (unrealClassDictionary.Count > 0)
            {
                var rewriteStack     = new Stack <KeyValuePair <TypeDefinition, ClassMetadata> > ();
                var rewrittenClasses = new HashSet <TypeDefinition> ();

                // make sure we write base classes before derived ones
                foreach (var pair in unrealClassDictionary)
                {
                    var  currentPair = pair;
                    bool needRewrite = true;
                    while (needRewrite)
                    {
                        if (!rewrittenClasses.Contains(currentPair.Key))
                        {
                            rewriteStack.Push(currentPair);
                            var baseType = currentPair.Key.BaseType.Resolve();

                            if (unrealClassDictionary.ContainsKey(baseType))
                            {
                                ClassMetadata baseClassMetadata = unrealClassDictionary [baseType];

                                currentPair = new KeyValuePair <TypeDefinition, ClassMetadata> (baseType, baseClassMetadata);
                            }
                            else
                            {
                                needRewrite = false;
                            }
                        }
                        else
                        {
                            needRewrite = false;
                        }
                    }

                    while (rewriteStack.Count > 0)
                    {
                        currentPair = rewriteStack.Pop();
                        if (rewrittenClasses.Contains(currentPair.Key))
                        {
                            throw new InternalRewriteException(currentPair.Key, "Attempted to rewrite class twice");
                        }
                        var baseType = currentPair.Key.BaseType;
                        if (baseType != null && unrealClassDictionary.ContainsKey(baseType.Resolve()))
                        {
                            ClassMetadata superClassMetadata = unrealClassDictionary [baseType.Resolve()];
                            currentPair.Value.SetSuperClassHash(superClassMetadata);
                        }

                        RewriteUnrealClass(metadata, assembly, currentPair.Key, currentPair.Value, bindingsAssembly);
                        rewrittenClasses.Add(currentPair.Key);
                    }
                }

                var writer = new WriterParameters {
                    WriteSymbols = true, SymbolWriterProvider = new PortablePdbWriterProvider()
                };
                assembly.Write(outputPath, writer);

                VerifyAssembly(outputPath, knownPaths, verify);

                //for some reason msbuild uses creation time or incrementral builds, not mtime
                //but cecil preserves the creation time from the original so we have to reset it
                File.SetCreationTimeUtc(outputPath, DateTime.UtcNow);

                string metadataContents = fastJSON.JSON.ToNiceJSON(metadata, new fastJSON.JSONParameters {
                    UseExtensions = false
                });
                File.WriteAllText(metadataFileName, metadataContents);
            }
            else
            {
                File.Delete(metadataFileName);
            }
        }