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); }
public static TFields GetStructFields <TStruct, TFields>(DkmProcess process) where TStruct : StructProxy where TFields : class, new() { StructMetadata metadata = GetStructMetadata <TStruct>(process); return(GetStructFields <TFields>(metadata)); }
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; }
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); }
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); }
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); }
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); } }