diff --git a/Editor/ObfuscateUtil.cs b/Editor/ObfuscateUtil.cs index a7815e2..c68a923 100644 --- a/Editor/ObfuscateUtil.cs +++ b/Editor/ObfuscateUtil.cs @@ -1,17 +1,23 @@ -using HybridCLR.Editor; -using Obfuz.Settings; +using dnlib.DotNet; +using dnlib.DotNet.PolymorphicWriter; +using HybridCLR.Editor; using Obfuz; +using Obfuz.Settings; +using Obfuz.Unity; using System; using System.Collections.Generic; -using UnityEditor; using System.IO; +using UnityEditor; using UnityEngine; -using Obfuz.Unity; namespace Obfuz4HybridCLR { public static class ObfuscateUtil { + public static string PackageName { get; } = "com.code-philosophy.obfuz4hybridclr"; + + public static string TemplatePathInPackage => $"Packages/{PackageName}/Templates~"; + public static bool AreSameDirectory(string path1, string path2) { try @@ -75,5 +81,38 @@ namespace Obfuz4HybridCLR Obfuscator obfuz = builder.Build(); obfuz.Run(); } + + public static void GeneratePolymorphicDll(string originalDllPath, string outputDllPath) + { + ModuleDef oldMod = ModuleDefMD.Load(originalDllPath); + var obfuzSettings = ObfuzSettings.Instance; + + var opt = new NewDllModuleWriterOptions(oldMod) + { + MetadataWriter = new PolymorphicMetadataWriter(obfuzSettings.polymorphicDllSettings.codeGenerationSecretKey), + }; + PolymorphicModuleWriter writer = new PolymorphicModuleWriter(oldMod, opt); + writer.Write(outputDllPath); + Debug.Log($"GeneratePolymorphicDll {originalDllPath} => {outputDllPath}"); + } + + public static void GeneratePolymorphicCodes(string libil2cppDir) + { + PolymorphicDllSettings settings = ObfuzSettings.Instance.polymorphicDllSettings; + if (!settings.enable) + { + UnityEngine.Debug.LogWarning("Polymorphic code generation is disabled in Obfuz settings."); + return; + } + var options = new PolymorphicCodeGenerator.Options + { + GenerationSecretKey = settings.codeGenerationSecretKey, + Libil2cppDir = libil2cppDir, + TemplateDir = ObfuscateUtil.TemplatePathInPackage, + DisableLoadStandardDll = settings.disableLoadStandardDll, + }; + var generator = new PolymorphicCodeGenerator(options); + generator.Generate(); + } } } diff --git a/Editor/Polymorphic.meta b/Editor/Polymorphic.meta new file mode 100644 index 0000000..6a8a589 --- /dev/null +++ b/Editor/Polymorphic.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 52d353fb8d6d94c4aa03452a2cd9773f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Polymorphic/PolymorphicCodeGenerator.cs b/Editor/Polymorphic/PolymorphicCodeGenerator.cs new file mode 100644 index 0000000..23d9c22 --- /dev/null +++ b/Editor/Polymorphic/PolymorphicCodeGenerator.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using dnlib.DotNet.PolymorphicWriter; +using HybridCLR.Editor.Template; + +public class PolymorphicCodeGenerator +{ + public class Options + { + public string GenerationSecretKey { get; set; } + + public string Libil2cppDir { get; set; } + + public string TemplateDir { get; set; } + + public bool DisableLoadStandardDll { get; set; } = true; + } + + private readonly string _libil2cppDir; + private readonly string _metadataDir; + private readonly string _templateDir; + + private readonly string _generationSecretKey; + private readonly bool _disableLoadStandardImage; + + private readonly PolymorphicMetadataWriter writer; + + public PolymorphicCodeGenerator(Options options) + { + _libil2cppDir = options.Libil2cppDir; + _metadataDir = Path.Combine(_libil2cppDir, "hybridclr", "metadata"); + _templateDir = options.TemplateDir; + + _generationSecretKey = options.GenerationSecretKey; + _disableLoadStandardImage = options.DisableLoadStandardDll; + + writer = new PolymorphicMetadataWriter(_generationSecretKey); + } + + private void CopyMetadataReaderHeader() + { + string srcFile = $"{_templateDir}/MetadataReader.h.tpl"; + string dstFile = $"{_metadataDir}/MetadataReader.h"; + File.Copy(srcFile, dstFile, true); + UnityEngine.Debug.Log($"Copy MetadataReader header from {srcFile} to {dstFile}"); + } + + private void GeneratePolymorphicDefs() + { + string tplFile = $"{_templateDir}/PolymorphicDefs.h.tpl"; + var frr = new FileRegionReplace(File.ReadAllText(tplFile, Encoding.UTF8)); + var lines = new List(); + lines.Add($"#define POLYMORPHIC_IMAGE_SIGNATURE \"{writer.ImageSignature}\""); + lines.Add($"\tconstexpr uint32_t kPolymorphicImageVersion = {writer.FormatVersion};"); + lines.Add($"\tconstexpr uint32_t kFormatVariantVersion = {writer.FormatVariant};"); + string codes = string.Join("\n", lines); + frr.Replace("POLYMORPHIC_DEFINES", codes); + + string outputFile = $"{_metadataDir}/PolymorphicDefs.h"; + frr.Commit(outputFile); + } + + private void GeneratePolymorphicDatas() + { + string tplFile = $"{_templateDir}/PolymorphicDatas.h.tpl"; + var frr = new FileRegionReplace(File.ReadAllText(tplFile, Encoding.UTF8)); + List lines = new List(); + var sb = new StringBuilder(); + foreach (var type in writer.GetPolymorphicTypes()) + { + var polymorphicType = writer.GetPolymorphicClassDef(type); + lines.Add($"\tstruct {type.Name}"); + lines.Add("\t{"); + foreach (var field in polymorphicType.Fields) + { + lines.Add($"\t\t{field.fieldWriter.CppTypeName} {field.name};"); + } + + lines.Add("\t\tvoid Read(MetadataReader& reader)"); + lines.Add("\t\t{"); + + foreach (var field in polymorphicType.Fields) + { + lines.Add($"\t\t\t{field.fieldWriter.GetMarshalCode(field.name, "reader")};"); + } + lines.Add("\t\t}"); + lines.Add("\t};"); + lines.Add(""); + } + + string codes = string.Join("\n", lines); + frr.Replace("POLYMORPHIC_DATA", codes); + + + string outputFile = $"{_metadataDir}/PolymorphicDatas.h"; + frr.Commit(outputFile); + } + + private void GeneratePolymorphicRawImageHeader() + { + string tplFile = $"{_templateDir}/PolymorphicRawImage.h.tpl"; + var frr = new FileRegionReplace(File.ReadAllText(tplFile, Encoding.UTF8)); + + + var tableMetaInfoMap = TableMetaInfos.tableMetaInfos.ToDictionary(t => "Raw" + t.csharpTypeName + "Row"); + List lines = new List(); + foreach (Type rowType in writer.GetPolymorphicTableRowTypes()) + { + TableMetaInfo table = tableMetaInfoMap[rowType.Name]; + + lines.Add($"\t\tvirtual Tb{table.cppTypeName} Read{table.cppTypeName}(uint32_t rawIndex) override;"); + } + + frr.Replace("READ_TABLES_OVERRIDES", string.Join("\n", lines)); + + string outputFile = $"{_metadataDir}/PolymorphicRawImage.h"; + frr.Commit(outputFile); + } + + private void GeneratePolymorphicRawImageSource() + { + string tplFile = $"{_templateDir}/PolymorphicRawImage.cpp.tpl"; + var frr = new FileRegionReplace(File.ReadAllText(tplFile, Encoding.UTF8)); + + var tableMetaInfoMap = TableMetaInfos.tableMetaInfos.ToDictionary(t => "Raw" + t.csharpTypeName + "Row"); + { + List lines = new List(); + + foreach (Type rowType in writer.GetAllTableRowTypes()) + { + TableMetaInfo table = tableMetaInfoMap[rowType.Name]; + PolymorphicClassDef polymorphicClassDef = writer.CreateTableRowClassDefForCodeGeneration(rowType); + lines.Add("\t\t{"); + lines.Add($"\t\t\tauto& table = _tableRowMetas[(int)TableType::{table.cppEnumName}];"); + foreach (var fieldDef in polymorphicClassDef.Fields) + { + FieldMetaInfo field = table.fields.First(f => f.csharpName == fieldDef.name); + lines.Add($"\t\t\ttable.push_back({{{field.cppRowSize}}});"); + } + lines.Add("\t\t}"); + } + string codes = string.Join("\n", lines); + frr.Replace("TABLE_ROW_METADS", codes); + } + { + List lines = new List(); + foreach (Type rowType in writer.GetPolymorphicTableRowTypes()) + { + TableMetaInfo table = tableMetaInfoMap[rowType.Name]; + PolymorphicClassDef polymorphicClassDef = writer.CreateTableRowClassDefForCodeGeneration(rowType); + + lines.Add($"\tTb{table.cppTypeName} PolymorphicRawImage::Read{table.cppTypeName}(uint32_t rawIndex)"); + lines.Add("\t{"); + lines.Add($"\t\tIL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::{table.cppEnumName}).rowNum);"); + lines.Add($"\t\tconst byte* rowPtr = GetTableRowPtr(TableType::{table.cppEnumName}, rawIndex);"); + lines.Add($"\t\tauto& rowSchema = GetRowSchema(TableType::{table.cppEnumName});"); + lines.Add($"\t\tTb{table.cppTypeName} data;"); + for (int i = 0; i < polymorphicClassDef.Fields.Count; i++) + { + var fieldDef = polymorphicClassDef.Fields[i]; + FieldMetaInfo field = table.fields.First(f => f.csharpName == fieldDef.name); + lines.Add($"\t\tdata.{field.cppName} = ReadColumn(rowPtr, rowSchema[{i}]);"); + } + lines.Add("\t\treturn data;"); + lines.Add("\t}"); + } + + frr.Replace("READ_TABLES_IMPLEMENTATIONS", string.Join("\n", lines)); + } + string outputFile = $"{_metadataDir}/PolymorphicRawImage.cpp"; + frr.Commit(outputFile); + } + + private void GenerateRawImageInit() + { + string tplFile = $"{_metadataDir}/Image.cpp"; + var frr = new FileRegionReplace(File.ReadAllText(tplFile, Encoding.UTF8)); + + { + List lines = new List(); + lines.Add(@"#include ""PolymorphicRawImage.h"""); + + frr.Replace("INCLUDE_RAW_IMAGE_HEADERS", string.Join("\n", lines)); + } + { + List lines = new List(); + + lines.Add("\t\tif (std::strncmp((const char*)imageData, \"CODEPHPY\", 8) == 0)"); + lines.Add("\t\t{"); + lines.Add("\t\t\t_rawImage = new PolymorphicRawImage();"); + lines.Add("\t\t}"); + lines.Add("\t\telse"); + lines.Add("\t\t{"); + if (_disableLoadStandardImage) + { + lines.Add("\t\t\treturn LoadImageErrorCode::UNKNOWN_IMAGE_FORMAT;"); + } + else + { + lines.Add("\t\t\t_rawImage = new RawImage();"); + } + lines.Add("\t\t}"); + lines.Add("\t\treturn LoadImageErrorCode::OK;"); + + frr.Replace("INIT_RAW_IMAGE", string.Join("\n", lines)); + } + + + frr.Commit(tplFile); + } + + public void Generate() + { + CopyMetadataReaderHeader(); + GeneratePolymorphicDefs(); + GeneratePolymorphicDatas(); + GeneratePolymorphicRawImageHeader(); + GeneratePolymorphicRawImageSource(); + GenerateRawImageInit(); + } +} diff --git a/Editor/Polymorphic/PolymorphicCodeGenerator.cs.meta b/Editor/Polymorphic/PolymorphicCodeGenerator.cs.meta new file mode 100644 index 0000000..6d7baec --- /dev/null +++ b/Editor/Polymorphic/PolymorphicCodeGenerator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b66b21680bfc8744682ea6536aa2ec77 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Polymorphic/TableMetaInfos.cs b/Editor/Polymorphic/TableMetaInfos.cs new file mode 100644 index 0000000..440cb7b --- /dev/null +++ b/Editor/Polymorphic/TableMetaInfos.cs @@ -0,0 +1,300 @@ +using System.Collections.Generic; + +class FieldMetaInfo { + public readonly string csharpName; + public readonly string cppName; + public readonly string cppRowSize; + public FieldMetaInfo(string csharpName, string cppName, string cppRowSize) { + this.csharpName = csharpName; + this.cppName = cppName; + this.cppRowSize = cppRowSize; + } + + public FieldMetaInfo(string csharpName, string cppRowSize) : this(csharpName, csharpName.Substring(0, 1).ToLower() + csharpName.Substring(1), cppRowSize) { + } +} + +class TableMetaInfo { + public readonly string csharpTypeName; + public readonly string cppTypeName; + public readonly string cppEnumName; + public readonly List fields; + + public TableMetaInfo(string csharpTypeName, string cppTypeName, string cppEnumName, List fields) { + this.csharpTypeName = csharpTypeName; + this.cppTypeName = cppTypeName; + this.cppEnumName = cppEnumName; + this.fields = fields; + } + + + public TableMetaInfo(string csharpTypeName, List fields) : this(csharpTypeName, csharpTypeName, csharpTypeName.ToUpper(), fields) { + } +} + +class TableMetaInfos { + public static readonly List tableMetaInfos = new List { + new TableMetaInfo("Module", new List { + new FieldMetaInfo("Generation", "2"), + new FieldMetaInfo("Name", "ComputStringIndexByte()"), + new FieldMetaInfo("Mvid", "ComputGUIDIndexByte()"), + new FieldMetaInfo("EncId", "ComputGUIDIndexByte()"), + new FieldMetaInfo("EncBaseId", "ComputGUIDIndexByte()"), + }), + new TableMetaInfo("TypeRef", new List { + new FieldMetaInfo("ResolutionScope", "ComputTableIndexByte(TableType::MODULE, TableType::MODULEREF, TableType::ASSEMBLYREF, TableType::TYPEREF, TagBits::ResoulutionScope)"), + new FieldMetaInfo("Name", "typeName", "ComputStringIndexByte()"), + new FieldMetaInfo("Namespace", "typeNamespace", "ComputStringIndexByte()"), + }), + new TableMetaInfo("TypeDef", new List { + new FieldMetaInfo("Flags", "4"), + new FieldMetaInfo("Name", "typeName", "ComputStringIndexByte()"), + new FieldMetaInfo("Namespace", "typeNamespace", "ComputStringIndexByte()"), + new FieldMetaInfo("Extends", "ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)"), + new FieldMetaInfo("FieldList", "ComputTableIndexByte(TableType::FIELD)"), + new FieldMetaInfo("MethodList", "ComputTableIndexByte(TableType::METHOD)"), + }), + new TableMetaInfo("FieldPtr", new List { + new FieldMetaInfo("Field", "ComputTableIndexByte(TableType::FIELD)"), + }), + new TableMetaInfo("Field", new List { + new FieldMetaInfo("Flags", "2"), + new FieldMetaInfo("Name", "ComputStringIndexByte()"), + new FieldMetaInfo("Signature", "ComputBlobIndexByte()"), + }), + new TableMetaInfo("MethodPtr", new List { + new FieldMetaInfo("Method", "ComputTableIndexByte(TableType::METHOD)"), + }), + new TableMetaInfo("Method", new List { + new FieldMetaInfo("RVA", "rva", "4"), + new FieldMetaInfo("ImplFlags", "2"), + new FieldMetaInfo("Flags", "2"), + new FieldMetaInfo("Name", "ComputStringIndexByte()"), + new FieldMetaInfo("Signature", "ComputBlobIndexByte()"), + new FieldMetaInfo("ParamList", "ComputTableIndexByte(TableType::PARAM)"), + }), + new TableMetaInfo("ParamPtr", new List { + new FieldMetaInfo("Param", "ComputTableIndexByte(TableType::PARAM)"), + }), + new TableMetaInfo("Param", new List { + new FieldMetaInfo("Flags", "2"), + new FieldMetaInfo("Sequence", "2"), + new FieldMetaInfo("Name", "ComputStringIndexByte()"), + }), + new TableMetaInfo("InterfaceImpl", new List { + new FieldMetaInfo("Class", "classIdx", "ComputTableIndexByte(TableType::TYPEDEF)"), + new FieldMetaInfo("Interface", "interfaceIdx", "ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)"), + }), + new TableMetaInfo("MemberRef", new List { + new FieldMetaInfo("Class", "classIdx", "ComputTableIndexByte(TableType::METHOD, TableType::MODULEREF, TableType::TYPEDEF, TableType::TYPEREF, TagBits::MemberRefParent)"), + new FieldMetaInfo("Name", "ComputStringIndexByte()"), + new FieldMetaInfo("Signature", "ComputBlobIndexByte()"), + }), + new TableMetaInfo("Constant", new List { + new FieldMetaInfo("Type", "1"), + new FieldMetaInfo("Padding", "1"), + new FieldMetaInfo("Parent", "ComputTableIndexByte(TableType::PARAM, TableType::FIELD, TableType::PROPERTY, TagBits::HasConstant)"), + new FieldMetaInfo("Value", "ComputBlobIndexByte()"), + }), + new TableMetaInfo("CustomAttribute", new List { + new FieldMetaInfo("Parent", "ComputTableIndexByte(HasCustomAttributeAssociateTables, sizeof(HasCustomAttributeAssociateTables) / sizeof(TableType), TagBits::HasCustomAttribute)"), + new FieldMetaInfo("Type", "ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::CustomAttributeType)"), + new FieldMetaInfo("Value", "ComputBlobIndexByte()"), + }), + new TableMetaInfo("FieldMarshal", new List { + new FieldMetaInfo("Parent", "ComputTableIndexByte(TableType::FIELD, TableType::PARAM, TagBits::HasFieldMarshal)"), + new FieldMetaInfo("NativeType", "ComputBlobIndexByte()"), + }), + new TableMetaInfo("DeclSecurity", new List { + new FieldMetaInfo("Action", "2"), + new FieldMetaInfo("Parent", "ComputTableIndexByte(TableType::TYPEDEF, TableType::METHOD, TableType::ASSEMBLY, TagBits::HasDeclSecurity)"), + new FieldMetaInfo("PermissionSet", "ComputBlobIndexByte()"), + }), + new TableMetaInfo("ClassLayout", new List { + new FieldMetaInfo("PackingSize", "2"), + new FieldMetaInfo("ClassSize", "4"), + new FieldMetaInfo("Parent", "ComputTableIndexByte(TableType::TYPEDEF)"), + }), + new TableMetaInfo("FieldLayout", new List { + new FieldMetaInfo("OffSet", "offset", "4"), + new FieldMetaInfo("Field", "ComputTableIndexByte(TableType::FIELD)"), + }), + new TableMetaInfo("StandAloneSig", new List { + new FieldMetaInfo("Signature", "ComputBlobIndexByte()"), + }), + new TableMetaInfo("EventMap", new List { + new FieldMetaInfo("Parent", "ComputTableIndexByte(TableType::TYPEDEF)"), + new FieldMetaInfo("EventList", "ComputTableIndexByte(TableType::EVENT)"), + }), + new TableMetaInfo("EventPtr", new List { + new FieldMetaInfo("Event", "ComputTableIndexByte(TableType::EVENT)"), + }), + new TableMetaInfo("Event", new List { + new FieldMetaInfo("EventFlags", "2"), + new FieldMetaInfo("Name", "ComputStringIndexByte()"), + new FieldMetaInfo("EventType", "ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)"), + }), + new TableMetaInfo("PropertyMap", new List { + new FieldMetaInfo("Parent", "ComputTableIndexByte(TableType::TYPEDEF)"), + new FieldMetaInfo("PropertyList", "ComputTableIndexByte(TableType::PROPERTY)"), + }), + new TableMetaInfo("PropertyPtr", new List { + new FieldMetaInfo("Property", "ComputTableIndexByte(TableType::PROPERTY)"), + }), + new TableMetaInfo("Property", new List { + new FieldMetaInfo("PropFlags", "flags", "2"), + new FieldMetaInfo("Name", "ComputStringIndexByte()"), + new FieldMetaInfo("Type", "ComputBlobIndexByte()"), + }), + new TableMetaInfo("MethodSemantics", new List { + new FieldMetaInfo("Semantic", "semantics", "2"), + new FieldMetaInfo("Method", "ComputTableIndexByte(TableType::METHOD)"), + new FieldMetaInfo("Association", "ComputTableIndexByte(TableType::EVENT, TableType::PROPERTY, TagBits::HasSemantics)"), + }), + new TableMetaInfo("MethodImpl", new List { + new FieldMetaInfo("Class", "classIdx", "ComputTableIndexByte(TableType::TYPEDEF)"), + new FieldMetaInfo("MethodBody", "ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::MethodDefOrRef)"), + new FieldMetaInfo("MethodDeclaration", "ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::MethodDefOrRef)"), + }), + new TableMetaInfo("ModuleRef", new List { + new FieldMetaInfo("Name", "ComputStringIndexByte()"), + }), + new TableMetaInfo("TypeSpec", new List { + new FieldMetaInfo("Signature", "ComputBlobIndexByte()"), + }), + new TableMetaInfo("ImplMap", new List { + new FieldMetaInfo("MappingFlags", "2"), + new FieldMetaInfo("MemberForwarded", "ComputTableIndexByte(TableType::FIELD, TableType::METHOD, TagBits::MemberForwarded)"), + new FieldMetaInfo("ImportName", "ComputStringIndexByte()"), + new FieldMetaInfo("ImportScope", "ComputTableIndexByte(TableType::MODULEREF)"), + }), + new TableMetaInfo("FieldRVA", new List { + new FieldMetaInfo("RVA", "rva", "4"), + new FieldMetaInfo("Field", "ComputTableIndexByte(TableType::FIELD)"), + }), + new TableMetaInfo("ENCLog","EncLog", "ENCLOG", new List { + new FieldMetaInfo("Token", "4"), + new FieldMetaInfo("FuncCode", "4"), + }), + new TableMetaInfo("ENCMap", "EncMap", "ENCMAP", new List { + new FieldMetaInfo("Token", "4"), + }), + new TableMetaInfo("Assembly", new List { + new FieldMetaInfo("HashAlgId", "4"), + new FieldMetaInfo("MajorVersion", "2"), + new FieldMetaInfo("MinorVersion", "2"), + new FieldMetaInfo("BuildNumber", "2"), + new FieldMetaInfo("RevisionNumber", "2"), + new FieldMetaInfo("Flags", "4"), + new FieldMetaInfo("PublicKey", "ComputBlobIndexByte()"), + new FieldMetaInfo("Name", "ComputStringIndexByte()"), + new FieldMetaInfo("Locale", "ComputStringIndexByte()"), + }), + new TableMetaInfo("AssemblyProcessor", new List { + new FieldMetaInfo("Processor", "4"), + }), + new TableMetaInfo("AssemblyOS", new List { + new FieldMetaInfo("OSPlatformId", "osPlatformId", "4"), + new FieldMetaInfo("OSMajorVersion", "osMajorVersion", "4"), + new FieldMetaInfo("OSMinorVersion", "osMinorVersion", "4"), + }), + new TableMetaInfo("AssemblyRef", new List { + new FieldMetaInfo("MajorVersion", "2"), + new FieldMetaInfo("MinorVersion", "2"), + new FieldMetaInfo("BuildNumber", "2"), + new FieldMetaInfo("RevisionNumber", "2"), + new FieldMetaInfo("Flags", "4"), + new FieldMetaInfo("PublicKeyOrToken", "ComputBlobIndexByte()"), + new FieldMetaInfo("Name", "ComputStringIndexByte()"), + new FieldMetaInfo("Locale", "ComputStringIndexByte()"), + new FieldMetaInfo("HashValue", "ComputBlobIndexByte()"), + }), + new TableMetaInfo("AssemblyRefProcessor", new List { + new FieldMetaInfo("AssemblyRef", "4"), + new FieldMetaInfo("Processor", "ComputTableIndexByte(TableType::ASSEMBLYREF)"), + }), + new TableMetaInfo("AssemblyRefOS", new List { + new FieldMetaInfo("OSPlatformId", "osPlatformId", "4"), + new FieldMetaInfo("OSMajorVersion", "osMajorVersion", "4"), + new FieldMetaInfo("OSMinorVersion", "osMinorVersion", "4"), + new FieldMetaInfo("AssemblyRef", "ComputTableIndexByte(TableType::ASSEMBLYREF)"), + }), + new TableMetaInfo("File", new List { + new FieldMetaInfo("Flags", "4"), + new FieldMetaInfo("Name", "ComputStringIndexByte()"), + new FieldMetaInfo("HashValue", "ComputBlobIndexByte()"), + }), + new TableMetaInfo("ExportedType", new List { + new FieldMetaInfo("Flags", "4"), + new FieldMetaInfo("TypeDefId", "4"), + new FieldMetaInfo("TypeName", "ComputStringIndexByte()"), + new FieldMetaInfo("TypeNamespace", "ComputStringIndexByte()"), + new FieldMetaInfo("Implementation", "ComputTableIndexByte(TableType::FILE, TableType::EXPORTEDTYPE, TableType::ASSEMBLY, TagBits::Implementation)"), + }), + new TableMetaInfo("ManifestResource", new List { + new FieldMetaInfo("Offset", "4"), + new FieldMetaInfo("Flags", "4"), + new FieldMetaInfo("Name", "ComputStringIndexByte()"), + new FieldMetaInfo("Implementation", "ComputTableIndexByte(TableType::FILE, TableType::ASSEMBLYREF, TagBits::Implementation)"), + }), + new TableMetaInfo("NestedClass", new List { + new FieldMetaInfo("NestedClass", "ComputTableIndexByte(TableType::TYPEDEF)"), + new FieldMetaInfo("EnclosingClass", "ComputTableIndexByte(TableType::TYPEDEF)"), + }), + new TableMetaInfo("GenericParam", new List { + new FieldMetaInfo("Number", "2"), + new FieldMetaInfo("Flags", "2"), + new FieldMetaInfo("Owner", "ComputTableIndexByte(TableType::TYPEDEF, TableType::METHOD, TagBits::TypeOrMethodDef)"), + new FieldMetaInfo("Name", "ComputStringIndexByte()"), + }), + new TableMetaInfo("MethodSpec", new List { + new FieldMetaInfo("Method", "ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::MethodDefOrRef)"), + new FieldMetaInfo("Instantiation", "ComputBlobIndexByte()"), + }), + new TableMetaInfo("GenericParamConstraint", new List { + new FieldMetaInfo("Owner", "ComputTableIndexByte(TableType::GENERICPARAM)"), + new FieldMetaInfo("Constraint", "ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)"), + }), + + new TableMetaInfo("Document", new List { + new FieldMetaInfo("Name", "ComputBlobIndexByte()"), + new FieldMetaInfo("HashAlgorithm", "ComputGUIDIndexByte()"), + new FieldMetaInfo("Hash", "ComputBlobIndexByte()"), + new FieldMetaInfo("Language", "ComputGUIDIndexByte()"), + }), + new TableMetaInfo("MethodDebugInformation", new List { + new FieldMetaInfo("Document", "ComputTableIndexByte(TableType::DOCUMENT)"), + new FieldMetaInfo("SequencePoints", "ComputBlobIndexByte()"), + }), + new TableMetaInfo("LocalScope", new List { + new FieldMetaInfo("Method", "ComputTableIndexByte(TableType::METHOD)"), + new FieldMetaInfo("ImportScope", "ComputTableIndexByte(TableType::IMPORTSCOPE)"), + new FieldMetaInfo("VariableList", "variables", "ComputTableIndexByte(TableType::LOCALVARIABLE)"), + new FieldMetaInfo("ConstantList", "constants", "ComputTableIndexByte(TableType::LOCALCONSTANT)"), + new FieldMetaInfo("StartOffset", "4"), + new FieldMetaInfo("Length", "4"), + }), + new TableMetaInfo("LocalVariable", new List { + new FieldMetaInfo("Attributes", "2"), + new FieldMetaInfo("Index", "2"), + new FieldMetaInfo("Name", "ComputStringIndexByte()"), + }), + new TableMetaInfo("LocalConstant", new List { + new FieldMetaInfo("Name", "ComputStringIndexByte()"), + new FieldMetaInfo("Signature", "ComputBlobIndexByte()"), + }), + new TableMetaInfo("ImportScope", new List { + new FieldMetaInfo("Parent", "ComputTableIndexByte(TableType::IMPORTSCOPE)"), + new FieldMetaInfo("Imports", "ComputBlobIndexByte()"), + }), + new TableMetaInfo("StateMachineMethod", new List { + new FieldMetaInfo("MoveNextMethod", "ComputTableIndexByte(TableType::METHOD)"), + new FieldMetaInfo("KickoffMethod", "ComputTableIndexByte(TableType::METHOD)"), + }), + new TableMetaInfo("CustomDebugInformation", new List { + new FieldMetaInfo("Parent", "ComputTableIndexByte(HasCustomDebugInformation, sizeof(HasCustomDebugInformation) / sizeof(TableType), TagBits::HasCustomDebugInformation)"), + new FieldMetaInfo("Kind", "ComputGUIDIndexByte()"), + new FieldMetaInfo("Value", "ComputBlobIndexByte()"), + }), + }; +} diff --git a/Editor/Polymorphic/TableMetaInfos.cs.meta b/Editor/Polymorphic/TableMetaInfos.cs.meta new file mode 100644 index 0000000..a3a2a88 --- /dev/null +++ b/Editor/Polymorphic/TableMetaInfos.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef98af767d086bd428f52503188789b1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/PrebuildCommandExt.cs b/Editor/PrebuildCommandExt.cs index f060597..85ce25b 100644 --- a/Editor/PrebuildCommandExt.cs +++ b/Editor/PrebuildCommandExt.cs @@ -47,6 +47,7 @@ namespace Obfuz4HybridCLR BuildTarget target = EditorUserBuildSettings.activeBuildTarget; CompileDllCommand.CompileDll(target); Il2CppDefGeneratorCommand.GenerateIl2CppDef(); + GeneratePolymorphicCodesWhenEnable(); LinkGeneratorCommand.GenerateLinkXml(target); StripAOTDllCommand.GenerateStripedAOTDlls(target); @@ -66,6 +67,23 @@ namespace Obfuz4HybridCLR ObfuscateUtil.ObfuscateHotUpdateAssemblies(target, obfuscatedHotUpdateDllPath); } + [MenuItem("HybridCLR/ObfuzExtension/GeneratePolymorphicCodes")] + public static void GeneratePolymorphicCodes() + { + ObfuscateUtil.GeneratePolymorphicCodes($"{SettingsUtil.LocalIl2CppDir}/libil2cpp"); + } + + private static void GeneratePolymorphicCodesWhenEnable() + { + PolymorphicDllSettings settings = ObfuzSettings.Instance.polymorphicDllSettings; + if (!settings.enable) + { + UnityEngine.Debug.LogWarning("Polymorphic code generation is disabled."); + return; + } + GeneratePolymorphicCodes(); + } + public static IAssemblyResolver CreateObfuscatedHotUpdateAssemblyResolver(BuildTarget target, List obfuscatedHotUpdateAssemblies, string obfuscatedHotUpdateDllPath) { return new FixedSetAssemblyResolver(obfuscatedHotUpdateDllPath, obfuscatedHotUpdateAssemblies); diff --git a/Templates~/MetadataReader.h.tpl b/Templates~/MetadataReader.h.tpl new file mode 100644 index 0000000..0a63002 --- /dev/null +++ b/Templates~/MetadataReader.h.tpl @@ -0,0 +1,96 @@ +#pragma once + +#include "MetadataUtil.h" + +namespace hybridclr +{ +namespace metadata +{ + struct ByteSpan + { + const byte* data; + uint32_t length; + ByteSpan() : data(nullptr), length(0) {} + ByteSpan(const byte* data, uint32_t length) : data(data), length(length) {} + }; + + class MetadataReader + { + private: + const byte* _data; + public: + MetadataReader(const byte* data) : _data(data) {} + int16_t ReadInt16() + { + int16_t value = GetI2LittleEndian(_data); + _data += 2; + return value; + } + + bool ReadBool() + { + return *(_data++) != 0; + } + + uint8_t ReadUInt8() + { + return *(_data++); + } + + uint16_t ReadUInt16() + { + uint16_t value = GetU2LittleEndian(_data); + _data += 2; + return value; + } + + int32_t ReadInt32() + { + int32_t value = GetI4LittleEndian(_data); + _data += 4; + return value; + } + + uint32_t ReadUInt32() + { + uint32_t value = GetU4LittleEndian(_data); + _data += 4; + return value; + } + + int64_t ReadInt64() + { + int64_t value = GetI8LittleEndian(_data); + _data += 8; + return value; + } + + uint64_t ReadUInt64() + { + uint64_t value = GetU8LittleEndian(_data); + _data += 8; + return value; + } + + const byte* ReadFixedBytes(int32_t byteCount) + { + const byte* value = _data; + _data += byteCount; + return value; + } + + ByteSpan ReadBytes() + { + uint32_t byteCount = ReadUInt32(); + const byte* buffer = _data; + _data += byteCount; + return ByteSpan(buffer, byteCount); + } + + const byte* CurrentDataPtr() const + { + return _data; + } + }; +} +} \ No newline at end of file diff --git a/Templates~/PolymorphicDatas.h.tpl b/Templates~/PolymorphicDatas.h.tpl new file mode 100644 index 0000000..bb91b78 --- /dev/null +++ b/Templates~/PolymorphicDatas.h.tpl @@ -0,0 +1,88 @@ +#pragma once +#include "MetadataReader.h" + +namespace hybridclr +{ +namespace metadata +{ + //!!!{{POLYMORPHIC_DATA + struct HeaderBaseData + { + uint32_t metadataSize; + uint32_t sectionCount; + const byte* dummyData; + uint32_t metadataRva; + uint32_t entryPointToken; + void Read(MetadataReader& reader) + { + metadataSize = reader.ReadUInt32(); + sectionCount = reader.ReadUInt32(); + dummyData = reader.ReadFixedBytes(8); + metadataRva = reader.ReadUInt32(); + entryPointToken = reader.ReadUInt32(); + } + }; + + struct SectionData + { + uint32_t rva; + uint32_t fileOffset; + uint32_t virtualSize; + uint32_t fileLength; + void Read(MetadataReader& reader) + { + rva = reader.ReadUInt32(); + fileOffset = reader.ReadUInt32(); + virtualSize = reader.ReadUInt32(); + fileLength = reader.ReadUInt32(); + } + }; + + struct MetadataHeaderBaseData + { + uint32_t signature; + uint8_t reserved2; + ByteSpan versionString; + uint16_t majorVersion; + uint16_t heapsCount; + uint32_t reserved1; + uint8_t storageFlags; + uint16_t minorVersion; + void Read(MetadataReader& reader) + { + signature = reader.ReadUInt32(); + reserved2 = reader.ReadUInt8(); + versionString = reader.ReadBytes(); + majorVersion = reader.ReadUInt16(); + heapsCount = reader.ReadUInt16(); + reserved1 = reader.ReadUInt32(); + storageFlags = reader.ReadUInt8(); + minorVersion = reader.ReadUInt16(); + } + }; + + struct TablesHeapHeaderBaseData + { + uint64_t validMask; + uint32_t reserved1; + uint8_t streamFlags; + uint8_t majorVersion; + uint64_t sortedMask; + uint8_t minorVersion; + uint8_t log2Rid; + void Read(MetadataReader& reader) + { + validMask = reader.ReadUInt64(); + reserved1 = reader.ReadUInt32(); + streamFlags = reader.ReadUInt8(); + majorVersion = reader.ReadUInt8(); + sortedMask = reader.ReadUInt64(); + minorVersion = reader.ReadUInt8(); + log2Rid = reader.ReadUInt8(); + } + }; + + + //!!!}}POLYMORPHIC_DATA +} +} \ No newline at end of file diff --git a/Templates~/PolymorphicDefs.h.tpl b/Templates~/PolymorphicDefs.h.tpl new file mode 100644 index 0000000..a88b8a7 --- /dev/null +++ b/Templates~/PolymorphicDefs.h.tpl @@ -0,0 +1,28 @@ +#pragma once +#include "MetadataReader.h" + +namespace hybridclr +{ +namespace metadata +{ + //!!!{{POLYMORPHIC_DEFINES +#define POLYMORPHIC_IMAGE_SIGNATURE "CODEPHPY" + constexpr uint32_t kPolymorphicImageVersion = 1; + constexpr uint32_t kFormatVariantVersion = 0; + + //!!!}}POLYMORPHIC_DEFINES + + struct PolymorphicImageHeaderData + { + const byte* signature; + uint32_t formatVersion; + uint32_t formatVariant; + void Read(MetadataReader& reader) + { + signature = reader.ReadFixedBytes(8); + formatVersion = reader.ReadUInt32(); + formatVariant = reader.ReadUInt32(); + } + }; +} +} \ No newline at end of file diff --git a/Templates~/PolymorphicRawImage.cpp.tpl b/Templates~/PolymorphicRawImage.cpp.tpl new file mode 100644 index 0000000..ef091f5 --- /dev/null +++ b/Templates~/PolymorphicRawImage.cpp.tpl @@ -0,0 +1,897 @@ +#include "PolymorphicRawImage.h" + +#include + +#include "PolymorphicDefs.h" +#include "PolymorphicDatas.h" + +namespace hybridclr +{ +namespace metadata +{ + + struct RawSectionHeader + { + uint32_t fileOffset; + uint32_t fileLength; + uint32_t rva; + uint32_t virtualSize; + }; + + LoadImageErrorCode PolymorphicRawImage::LoadCLIHeader(uint32_t& entryPointToken, uint32_t& metadataRva, uint32_t& metadataSize) + { + if (_imageLength < 0x100) + { + return LoadImageErrorCode::BAD_IMAGE; + } + + MetadataReader reader(_imageData); + + PolymorphicImageHeaderData imageHeaderData = {}; + imageHeaderData.Read(reader); + + const char* sig = (const char*)_imageData; + if (std::strncmp((const char*)imageHeaderData.signature, POLYMORPHIC_IMAGE_SIGNATURE, sizeof(POLYMORPHIC_IMAGE_SIGNATURE) - 1)) + { + return LoadImageErrorCode::BAD_IMAGE; + } + if (imageHeaderData.formatVersion != kPolymorphicImageVersion) + { + return LoadImageErrorCode::UNSUPPORT_FORMAT_VERSION; + } + if (imageHeaderData.formatVariant != kFormatVariantVersion) + { + return LoadImageErrorCode::UNMATCH_FORMAT_VARIANT; + } + + //reader.ReadFixedBytes(polymorphic::kImageHeaderDummyDataSize); // Skip dummy data + + PolymorphicHeaderBaseData headerBaseData = {}; + headerBaseData.Read(reader); + + const size_t kEntryPointTokenOffset = 16; + entryPointToken = headerBaseData.entryPointToken; + metadataRva = headerBaseData.metadataRva; + metadataSize = headerBaseData.metadataSize; + + uint32_t sectionCount = headerBaseData.sectionCount; + for (uint32_t i = 0; i < sectionCount; i++) + { + PolymorphicSectionData sectionData = {}; + sectionData.Read(reader); + _sections.push_back({ sectionData.rva, sectionData.rva + sectionData.virtualSize, sectionData.fileOffset - sectionData.rva }); + } + return LoadImageErrorCode::OK; + } + + LoadImageErrorCode PolymorphicRawImage::LoadStreamHeaders(uint32_t metadataRva, uint32_t metadataSize) + { + uint32_t metaOffset; + if (!TranslateRVAToImageOffset(metadataRva, metaOffset)) + { + return LoadImageErrorCode::BAD_IMAGE; + } + if (metaOffset >= _imageLength) + { + return LoadImageErrorCode::BAD_IMAGE; + } + + const byte* ptrMetaData = _imageData + metaOffset; + MetadataReader reader(ptrMetaData); + + PolymorphicMetadataHeaderBaseData metadataHeader = {}; + metadataHeader.Read(reader); + if (metadataHeader.signature != 0x424A5342) + { + return LoadImageErrorCode::BAD_IMAGE; + } + + uint16_t numStreamHeader = metadataHeader.heapsCount; + const StreamHeader* ptrStreamHeaders = (const StreamHeader*)(reader.CurrentDataPtr()); + + const StreamHeader* curSH = ptrStreamHeaders; + const size_t maxStreamNameSize = 16; + for (int i = 0; i < numStreamHeader; i++) + { + //std::cout << "name:" << (char*)curSH->name << ", offset:" << curSH->offset << ", size:" << curSH->size << std::endl; + + if (curSH->offset >= metadataSize) + { + return LoadImageErrorCode::BAD_IMAGE; + } + CliStream* rs = nullptr; + CliStream nonStandardStream; + CliStream pdbStream; + if (!std::strncmp(curSH->name, "#~", maxStreamNameSize)) + { + rs = &_streamTables; + } + else if (!std::strncmp(curSH->name, "#Strings", maxStreamNameSize)) + { + rs = &_streamStringHeap; + } + else if (!std::strncmp(curSH->name, "#US", maxStreamNameSize)) + { + rs = &_streamUS; + } + else if (!std::strncmp(curSH->name, "#GUID", maxStreamNameSize)) + { + rs = &_streamGuidHeap; + if (curSH->size % 16 != 0) + { + return LoadImageErrorCode::BAD_IMAGE; + } + } + else if (!std::strncmp(curSH->name, "#Blob", maxStreamNameSize)) + { + rs = &_streamBlobHeap; + } + else if (!std::strncmp(curSH->name, "#-", maxStreamNameSize)) + { + rs = &nonStandardStream; + } + else if (!std::strncmp(curSH->name, "#Pdb", maxStreamNameSize)) + { + rs = &pdbStream; + } + else + { + //std::cerr << "unknown stream name:" << curSH->name << std::endl; + return LoadImageErrorCode::BAD_IMAGE; + } + rs->data = ptrMetaData + curSH->offset; + rs->size = curSH->size; + rs->name = curSH->name; + size_t sizeOfStream = 8 + (std::strlen(curSH->name) / 4 + 1) * 4; + curSH = (const StreamHeader*)((byte*)curSH + sizeOfStream); + } + return LoadImageErrorCode::OK; + } + + LoadImageErrorCode PolymorphicRawImage::LoadTables() + { + MetadataReader reader(_streamTables.data); + + PolymorphicTablesHeapHeaderBaseData heapHeader = {}; + heapHeader.Read(reader); + + if (heapHeader.reserved1 != 0 || heapHeader.majorVersion != 2 || heapHeader.minorVersion != 0) + { + return LoadImageErrorCode::BAD_IMAGE; + } + if ((heapHeader.streamFlags & ~0x7)) + { + return LoadImageErrorCode::BAD_IMAGE; + } + _4byteStringIndex = heapHeader.streamFlags & 0x1; + _4byteGUIDIndex = heapHeader.streamFlags & 0x2; + _4byteBlobIndex = heapHeader.streamFlags & 0x4; + + uint64_t validMask = ((uint64_t)1 << TABLE_NUM) - 1; + if (heapHeader.validMask & ~validMask) + { + return LoadImageErrorCode::BAD_IMAGE; + } + // sorted include not exist table, so check is not need. + //if (heapHeader.sorted & ~validMask) + //{ + // return LoadImageErrorCode::BAD_IMAGE; + //} + + uint32_t validTableNum = GetNotZeroBitCount(heapHeader.validMask); + //std::cout << "valid table num:" << validTableNum << std::endl; + //printf("#~ size:%0x\n", _streamTables.size); + const uint32_t* tableRowNums = (uint32_t*)(reader.CurrentDataPtr()); + const byte* tableDataBegin = (const byte*)(tableRowNums + validTableNum); + + { + int curValidTableIndex = 0; + for (int i = 0; i <= MAX_TABLE_INDEX; i++) + { + uint64_t mask = (uint64_t)1 << i; + _tables[i] = {}; + if (heapHeader.validMask & mask) + { + uint32_t rowNum = tableRowNums[curValidTableIndex]; + _tables[i].rowNum = rowNum; + ++curValidTableIndex; + } + } + } + + BuildTableRowMetas(); + + int curValidTableIndex = 0; + const byte* curTableData = tableDataBegin; + for (int i = 0; i <= MAX_TABLE_INDEX; i++) + { + uint64_t mask = (uint64_t)1 << i; + bool sorted = heapHeader.sortedMask & mask; + if (heapHeader.validMask & mask) + { + uint32_t rowNum = tableRowNums[curValidTableIndex]; + uint32_t totalSize = 0; + auto& table = _tableRowMetas[i]; + for (auto& col : table) + { + col.offset = totalSize; + totalSize += col.size; + } + uint32_t metaDataRowSize = totalSize; + //uint64_t offset = curTableData - _imageData; + _tables[i] = { curTableData, metaDataRowSize, rowNum, true, sorted }; + curTableData += metaDataRowSize * rowNum; + //std::cout << "table:" << i << " ," << curValidTableIndex << ", row_size:" << metaDataRowSize << ", row_num:" << rowNum << std::endl; + //printf("table:[%d][%d] offset:%0llx row_size:%d row_count:%d\n", i, curValidTableIndex, offset, metaDataRowSize, rowNum); + ++curValidTableIndex; + } + else + { + _tables[i] = { nullptr, 0, 0, false, sorted }; + } + } + + return LoadImageErrorCode::OK; + } + + void PolymorphicRawImage::BuildTableRowMetas() + { + //!!!{{TABLE_ROW_METADS + { + auto& table = _tableRowMetas[(int)TableType::MODULE]; + table.push_back({2}); + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputGUIDIndexByte()}); + table.push_back({ComputGUIDIndexByte()}); + table.push_back({ComputGUIDIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::TYPEREF]; + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputTableIndexByte(TableType::MODULE, TableType::MODULEREF, TableType::ASSEMBLYREF, TableType::TYPEREF, TagBits::ResoulutionScope)}); + } + { + auto& table = _tableRowMetas[(int)TableType::TYPEDEF]; + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputTableIndexByte(TableType::FIELD)}); + table.push_back({ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)}); + table.push_back({4}); + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputTableIndexByte(TableType::METHOD)}); + } + { + auto& table = _tableRowMetas[(int)TableType::FIELDPTR]; + table.push_back({ComputTableIndexByte(TableType::FIELD)}); + } + { + auto& table = _tableRowMetas[(int)TableType::FIELD]; + table.push_back({ComputBlobIndexByte()}); + table.push_back({2}); + table.push_back({ComputStringIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::METHODPTR]; + table.push_back({ComputTableIndexByte(TableType::METHOD)}); + } + { + auto& table = _tableRowMetas[(int)TableType::METHOD]; + table.push_back({ComputBlobIndexByte()}); + table.push_back({2}); + table.push_back({2}); + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputTableIndexByte(TableType::PARAM)}); + table.push_back({4}); + } + { + auto& table = _tableRowMetas[(int)TableType::PARAMPTR]; + table.push_back({ComputTableIndexByte(TableType::PARAM)}); + } + { + auto& table = _tableRowMetas[(int)TableType::PARAM]; + table.push_back({2}); + table.push_back({ComputStringIndexByte()}); + table.push_back({2}); + } + { + auto& table = _tableRowMetas[(int)TableType::INTERFACEIMPL]; + table.push_back({ComputTableIndexByte(TableType::TYPEDEF)}); + table.push_back({ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)}); + } + { + auto& table = _tableRowMetas[(int)TableType::MEMBERREF]; + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputBlobIndexByte()}); + table.push_back({ComputTableIndexByte(TableType::METHOD, TableType::MODULEREF, TableType::TYPEDEF, TableType::TYPEREF, TagBits::MemberRefParent)}); + } + { + auto& table = _tableRowMetas[(int)TableType::CONSTANT]; + table.push_back({1}); + table.push_back({1}); + table.push_back({ComputTableIndexByte(TableType::PARAM, TableType::FIELD, TableType::PROPERTY, TagBits::HasConstant)}); + table.push_back({ComputBlobIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::CUSTOMATTRIBUTE]; + table.push_back({ComputTableIndexByte(HasCustomAttributeAssociateTables, sizeof(HasCustomAttributeAssociateTables) / sizeof(TableType), TagBits::HasCustomAttribute)}); + table.push_back({ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::CustomAttributeType)}); + table.push_back({ComputBlobIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::FIELDMARSHAL]; + table.push_back({ComputTableIndexByte(TableType::FIELD, TableType::PARAM, TagBits::HasFieldMarshal)}); + table.push_back({ComputBlobIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::DECLSECURITY]; + table.push_back({2}); + table.push_back({ComputTableIndexByte(TableType::TYPEDEF, TableType::METHOD, TableType::ASSEMBLY, TagBits::HasDeclSecurity)}); + table.push_back({ComputBlobIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::CLASSLAYOUT]; + table.push_back({4}); + table.push_back({2}); + table.push_back({ComputTableIndexByte(TableType::TYPEDEF)}); + } + { + auto& table = _tableRowMetas[(int)TableType::FIELDLAYOUT]; + table.push_back({ComputTableIndexByte(TableType::FIELD)}); + table.push_back({4}); + } + { + auto& table = _tableRowMetas[(int)TableType::STANDALONESIG]; + table.push_back({ComputBlobIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::EVENTMAP]; + table.push_back({ComputTableIndexByte(TableType::TYPEDEF)}); + table.push_back({ComputTableIndexByte(TableType::EVENT)}); + } + { + auto& table = _tableRowMetas[(int)TableType::EVENTPTR]; + table.push_back({ComputTableIndexByte(TableType::EVENT)}); + } + { + auto& table = _tableRowMetas[(int)TableType::EVENT]; + table.push_back({ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)}); + table.push_back({ComputStringIndexByte()}); + table.push_back({2}); + } + { + auto& table = _tableRowMetas[(int)TableType::PROPERTYMAP]; + table.push_back({ComputTableIndexByte(TableType::PROPERTY)}); + table.push_back({ComputTableIndexByte(TableType::TYPEDEF)}); + } + { + auto& table = _tableRowMetas[(int)TableType::PROPERTYPTR]; + table.push_back({ComputTableIndexByte(TableType::PROPERTY)}); + } + { + auto& table = _tableRowMetas[(int)TableType::PROPERTY]; + table.push_back({2}); + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputBlobIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::METHODSEMANTICS]; + table.push_back({ComputTableIndexByte(TableType::EVENT, TableType::PROPERTY, TagBits::HasSemantics)}); + table.push_back({ComputTableIndexByte(TableType::METHOD)}); + table.push_back({2}); + } + { + auto& table = _tableRowMetas[(int)TableType::METHODIMPL]; + table.push_back({ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::MethodDefOrRef)}); + table.push_back({ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::MethodDefOrRef)}); + table.push_back({ComputTableIndexByte(TableType::TYPEDEF)}); + } + { + auto& table = _tableRowMetas[(int)TableType::MODULEREF]; + table.push_back({ComputStringIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::TYPESPEC]; + table.push_back({ComputBlobIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::IMPLMAP]; + table.push_back({2}); + table.push_back({ComputTableIndexByte(TableType::MODULEREF)}); + table.push_back({ComputTableIndexByte(TableType::FIELD, TableType::METHOD, TagBits::MemberForwarded)}); + table.push_back({ComputStringIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::FIELDRVA]; + table.push_back({ComputTableIndexByte(TableType::FIELD)}); + table.push_back({4}); + } + { + auto& table = _tableRowMetas[(int)TableType::ENCLOG]; + table.push_back({4}); + table.push_back({4}); + } + { + auto& table = _tableRowMetas[(int)TableType::ENCMAP]; + table.push_back({4}); + } + { + auto& table = _tableRowMetas[(int)TableType::ASSEMBLY]; + table.push_back({2}); + table.push_back({4}); + table.push_back({2}); + table.push_back({2}); + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputBlobIndexByte()}); + table.push_back({2}); + table.push_back({4}); + } + { + auto& table = _tableRowMetas[(int)TableType::ASSEMBLYPROCESSOR]; + table.push_back({4}); + } + { + auto& table = _tableRowMetas[(int)TableType::ASSEMBLYOS]; + table.push_back({4}); + table.push_back({4}); + table.push_back({4}); + } + { + auto& table = _tableRowMetas[(int)TableType::ASSEMBLYREF]; + table.push_back({4}); + table.push_back({2}); + table.push_back({2}); + table.push_back({ComputBlobIndexByte()}); + table.push_back({ComputBlobIndexByte()}); + table.push_back({2}); + table.push_back({2}); + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputStringIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::ASSEMBLYREFPROCESSOR]; + table.push_back({ComputTableIndexByte(TableType::ASSEMBLYREF)}); + table.push_back({4}); + } + { + auto& table = _tableRowMetas[(int)TableType::ASSEMBLYREFOS]; + table.push_back({4}); + table.push_back({4}); + table.push_back({4}); + table.push_back({ComputTableIndexByte(TableType::ASSEMBLYREF)}); + } + { + auto& table = _tableRowMetas[(int)TableType::FILE]; + table.push_back({4}); + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputBlobIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::EXPORTEDTYPE]; + table.push_back({4}); + table.push_back({4}); + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputTableIndexByte(TableType::FILE, TableType::EXPORTEDTYPE, TableType::ASSEMBLY, TagBits::Implementation)}); + } + { + auto& table = _tableRowMetas[(int)TableType::MANIFESTRESOURCE]; + table.push_back({4}); + table.push_back({4}); + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputTableIndexByte(TableType::FILE, TableType::ASSEMBLYREF, TagBits::Implementation)}); + } + { + auto& table = _tableRowMetas[(int)TableType::NESTEDCLASS]; + table.push_back({ComputTableIndexByte(TableType::TYPEDEF)}); + table.push_back({ComputTableIndexByte(TableType::TYPEDEF)}); + } + { + auto& table = _tableRowMetas[(int)TableType::GENERICPARAM]; + table.push_back({2}); + table.push_back({2}); + table.push_back({ComputTableIndexByte(TableType::TYPEDEF, TableType::METHOD, TagBits::TypeOrMethodDef)}); + table.push_back({ComputStringIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::METHODSPEC]; + table.push_back({ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::MethodDefOrRef)}); + table.push_back({ComputBlobIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::GENERICPARAMCONSTRAINT]; + table.push_back({ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)}); + table.push_back({ComputTableIndexByte(TableType::GENERICPARAM)}); + } + { + auto& table = _tableRowMetas[(int)TableType::DOCUMENT]; + table.push_back({ComputBlobIndexByte()}); + table.push_back({ComputGUIDIndexByte()}); + table.push_back({ComputBlobIndexByte()}); + table.push_back({ComputGUIDIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::METHODDEBUGINFORMATION]; + table.push_back({ComputTableIndexByte(TableType::DOCUMENT)}); + table.push_back({ComputBlobIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::LOCALSCOPE]; + table.push_back({ComputTableIndexByte(TableType::METHOD)}); + table.push_back({ComputTableIndexByte(TableType::IMPORTSCOPE)}); + table.push_back({ComputTableIndexByte(TableType::LOCALVARIABLE)}); + table.push_back({ComputTableIndexByte(TableType::LOCALCONSTANT)}); + table.push_back({4}); + table.push_back({4}); + } + { + auto& table = _tableRowMetas[(int)TableType::LOCALVARIABLE]; + table.push_back({2}); + table.push_back({2}); + table.push_back({ComputStringIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::LOCALCONSTANT]; + table.push_back({ComputStringIndexByte()}); + table.push_back({ComputBlobIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::IMPORTSCOPE]; + table.push_back({ComputTableIndexByte(TableType::IMPORTSCOPE)}); + table.push_back({ComputBlobIndexByte()}); + } + { + auto& table = _tableRowMetas[(int)TableType::STATEMACHINEMETHOD]; + table.push_back({ComputTableIndexByte(TableType::METHOD)}); + table.push_back({ComputTableIndexByte(TableType::METHOD)}); + } + { + auto& table = _tableRowMetas[(int)TableType::CUSTOMDEBUGINFORMATION]; + table.push_back({ComputTableIndexByte(HasCustomDebugInformation, sizeof(HasCustomDebugInformation) / sizeof(TableType), TagBits::HasCustomDebugInformation)}); + table.push_back({ComputGUIDIndexByte()}); + table.push_back({ComputBlobIndexByte()}); + } + + //!!!}}TABLE_ROW_METADS + + for (int i = 0; i < TABLE_NUM; i++) + { + auto& table = _tableRowMetas[i]; + if (table.empty()) + { + IL2CPP_ASSERT(_tables[i].rowNum == 0 && _tables[i].rowMetaDataSize == 0); + } + else + { + uint32_t totalSize = 0; + for (auto& col : table) + { + col.offset = totalSize; + totalSize += col.size; + } + uint32_t computSize = ComputTableRowMetaDataSize((TableType)i); + IL2CPP_ASSERT(totalSize == computSize); + } + } + } + + //!!!{{READ_TABLES_IMPLEMENTATIONS + TbTypeRef PolymorphicRawImage::ReadTypeRef(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::TYPEREF).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::TYPEREF, rawIndex); + auto& rowSchema = GetRowSchema(TableType::TYPEREF); + TbTypeRef data; + data.typeNamespace = ReadColumn(rowPtr, rowSchema[0]); + data.typeName = ReadColumn(rowPtr, rowSchema[1]); + data.resolutionScope = ReadColumn(rowPtr, rowSchema[2]); + return data; + } + TbTypeDef PolymorphicRawImage::ReadTypeDef(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::TYPEDEF).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::TYPEDEF, rawIndex); + auto& rowSchema = GetRowSchema(TableType::TYPEDEF); + TbTypeDef data; + data.typeName = ReadColumn(rowPtr, rowSchema[0]); + data.fieldList = ReadColumn(rowPtr, rowSchema[1]); + data.extends = ReadColumn(rowPtr, rowSchema[2]); + data.flags = ReadColumn(rowPtr, rowSchema[3]); + data.typeNamespace = ReadColumn(rowPtr, rowSchema[4]); + data.methodList = ReadColumn(rowPtr, rowSchema[5]); + return data; + } + TbField PolymorphicRawImage::ReadField(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::FIELD).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::FIELD, rawIndex); + auto& rowSchema = GetRowSchema(TableType::FIELD); + TbField data; + data.signature = ReadColumn(rowPtr, rowSchema[0]); + data.flags = ReadColumn(rowPtr, rowSchema[1]); + data.name = ReadColumn(rowPtr, rowSchema[2]); + return data; + } + TbMethod PolymorphicRawImage::ReadMethod(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::METHOD).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::METHOD, rawIndex); + auto& rowSchema = GetRowSchema(TableType::METHOD); + TbMethod data; + data.signature = ReadColumn(rowPtr, rowSchema[0]); + data.flags = ReadColumn(rowPtr, rowSchema[1]); + data.implFlags = ReadColumn(rowPtr, rowSchema[2]); + data.name = ReadColumn(rowPtr, rowSchema[3]); + data.paramList = ReadColumn(rowPtr, rowSchema[4]); + data.rva = ReadColumn(rowPtr, rowSchema[5]); + return data; + } + TbParam PolymorphicRawImage::ReadParam(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::PARAM).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::PARAM, rawIndex); + auto& rowSchema = GetRowSchema(TableType::PARAM); + TbParam data; + data.flags = ReadColumn(rowPtr, rowSchema[0]); + data.name = ReadColumn(rowPtr, rowSchema[1]); + data.sequence = ReadColumn(rowPtr, rowSchema[2]); + return data; + } + TbInterfaceImpl PolymorphicRawImage::ReadInterfaceImpl(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::INTERFACEIMPL).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::INTERFACEIMPL, rawIndex); + auto& rowSchema = GetRowSchema(TableType::INTERFACEIMPL); + TbInterfaceImpl data; + data.classIdx = ReadColumn(rowPtr, rowSchema[0]); + data.interfaceIdx = ReadColumn(rowPtr, rowSchema[1]); + return data; + } + TbMemberRef PolymorphicRawImage::ReadMemberRef(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::MEMBERREF).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::MEMBERREF, rawIndex); + auto& rowSchema = GetRowSchema(TableType::MEMBERREF); + TbMemberRef data; + data.name = ReadColumn(rowPtr, rowSchema[0]); + data.signature = ReadColumn(rowPtr, rowSchema[1]); + data.classIdx = ReadColumn(rowPtr, rowSchema[2]); + return data; + } + TbConstant PolymorphicRawImage::ReadConstant(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::CONSTANT).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::CONSTANT, rawIndex); + auto& rowSchema = GetRowSchema(TableType::CONSTANT); + TbConstant data; + data.padding = ReadColumn(rowPtr, rowSchema[0]); + data.type = ReadColumn(rowPtr, rowSchema[1]); + data.parent = ReadColumn(rowPtr, rowSchema[2]); + data.value = ReadColumn(rowPtr, rowSchema[3]); + return data; + } + TbCustomAttribute PolymorphicRawImage::ReadCustomAttribute(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::CUSTOMATTRIBUTE).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::CUSTOMATTRIBUTE, rawIndex); + auto& rowSchema = GetRowSchema(TableType::CUSTOMATTRIBUTE); + TbCustomAttribute data; + data.parent = ReadColumn(rowPtr, rowSchema[0]); + data.type = ReadColumn(rowPtr, rowSchema[1]); + data.value = ReadColumn(rowPtr, rowSchema[2]); + return data; + } + TbClassLayout PolymorphicRawImage::ReadClassLayout(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::CLASSLAYOUT).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::CLASSLAYOUT, rawIndex); + auto& rowSchema = GetRowSchema(TableType::CLASSLAYOUT); + TbClassLayout data; + data.classSize = ReadColumn(rowPtr, rowSchema[0]); + data.packingSize = ReadColumn(rowPtr, rowSchema[1]); + data.parent = ReadColumn(rowPtr, rowSchema[2]); + return data; + } + TbFieldLayout PolymorphicRawImage::ReadFieldLayout(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::FIELDLAYOUT).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::FIELDLAYOUT, rawIndex); + auto& rowSchema = GetRowSchema(TableType::FIELDLAYOUT); + TbFieldLayout data; + data.field = ReadColumn(rowPtr, rowSchema[0]); + data.offset = ReadColumn(rowPtr, rowSchema[1]); + return data; + } + TbStandAloneSig PolymorphicRawImage::ReadStandAloneSig(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::STANDALONESIG).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::STANDALONESIG, rawIndex); + auto& rowSchema = GetRowSchema(TableType::STANDALONESIG); + TbStandAloneSig data; + data.signature = ReadColumn(rowPtr, rowSchema[0]); + return data; + } + TbEventMap PolymorphicRawImage::ReadEventMap(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::EVENTMAP).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::EVENTMAP, rawIndex); + auto& rowSchema = GetRowSchema(TableType::EVENTMAP); + TbEventMap data; + data.parent = ReadColumn(rowPtr, rowSchema[0]); + data.eventList = ReadColumn(rowPtr, rowSchema[1]); + return data; + } + TbEvent PolymorphicRawImage::ReadEvent(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::EVENT).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::EVENT, rawIndex); + auto& rowSchema = GetRowSchema(TableType::EVENT); + TbEvent data; + data.eventType = ReadColumn(rowPtr, rowSchema[0]); + data.name = ReadColumn(rowPtr, rowSchema[1]); + data.eventFlags = ReadColumn(rowPtr, rowSchema[2]); + return data; + } + TbPropertyMap PolymorphicRawImage::ReadPropertyMap(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::PROPERTYMAP).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::PROPERTYMAP, rawIndex); + auto& rowSchema = GetRowSchema(TableType::PROPERTYMAP); + TbPropertyMap data; + data.propertyList = ReadColumn(rowPtr, rowSchema[0]); + data.parent = ReadColumn(rowPtr, rowSchema[1]); + return data; + } + TbProperty PolymorphicRawImage::ReadProperty(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::PROPERTY).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::PROPERTY, rawIndex); + auto& rowSchema = GetRowSchema(TableType::PROPERTY); + TbProperty data; + data.flags = ReadColumn(rowPtr, rowSchema[0]); + data.name = ReadColumn(rowPtr, rowSchema[1]); + data.type = ReadColumn(rowPtr, rowSchema[2]); + return data; + } + TbMethodSemantics PolymorphicRawImage::ReadMethodSemantics(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::METHODSEMANTICS).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::METHODSEMANTICS, rawIndex); + auto& rowSchema = GetRowSchema(TableType::METHODSEMANTICS); + TbMethodSemantics data; + data.association = ReadColumn(rowPtr, rowSchema[0]); + data.method = ReadColumn(rowPtr, rowSchema[1]); + data.semantics = ReadColumn(rowPtr, rowSchema[2]); + return data; + } + TbMethodImpl PolymorphicRawImage::ReadMethodImpl(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::METHODIMPL).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::METHODIMPL, rawIndex); + auto& rowSchema = GetRowSchema(TableType::METHODIMPL); + TbMethodImpl data; + data.methodDeclaration = ReadColumn(rowPtr, rowSchema[0]); + data.methodBody = ReadColumn(rowPtr, rowSchema[1]); + data.classIdx = ReadColumn(rowPtr, rowSchema[2]); + return data; + } + TbModuleRef PolymorphicRawImage::ReadModuleRef(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::MODULEREF).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::MODULEREF, rawIndex); + auto& rowSchema = GetRowSchema(TableType::MODULEREF); + TbModuleRef data; + data.name = ReadColumn(rowPtr, rowSchema[0]); + return data; + } + TbTypeSpec PolymorphicRawImage::ReadTypeSpec(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::TYPESPEC).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::TYPESPEC, rawIndex); + auto& rowSchema = GetRowSchema(TableType::TYPESPEC); + TbTypeSpec data; + data.signature = ReadColumn(rowPtr, rowSchema[0]); + return data; + } + TbImplMap PolymorphicRawImage::ReadImplMap(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::IMPLMAP).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::IMPLMAP, rawIndex); + auto& rowSchema = GetRowSchema(TableType::IMPLMAP); + TbImplMap data; + data.mappingFlags = ReadColumn(rowPtr, rowSchema[0]); + data.importScope = ReadColumn(rowPtr, rowSchema[1]); + data.memberForwarded = ReadColumn(rowPtr, rowSchema[2]); + data.importName = ReadColumn(rowPtr, rowSchema[3]); + return data; + } + TbFieldRVA PolymorphicRawImage::ReadFieldRVA(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::FIELDRVA).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::FIELDRVA, rawIndex); + auto& rowSchema = GetRowSchema(TableType::FIELDRVA); + TbFieldRVA data; + data.field = ReadColumn(rowPtr, rowSchema[0]); + data.rva = ReadColumn(rowPtr, rowSchema[1]); + return data; + } + TbAssembly PolymorphicRawImage::ReadAssembly(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::ASSEMBLY).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::ASSEMBLY, rawIndex); + auto& rowSchema = GetRowSchema(TableType::ASSEMBLY); + TbAssembly data; + data.minorVersion = ReadColumn(rowPtr, rowSchema[0]); + data.hashAlgId = ReadColumn(rowPtr, rowSchema[1]); + data.buildNumber = ReadColumn(rowPtr, rowSchema[2]); + data.revisionNumber = ReadColumn(rowPtr, rowSchema[3]); + data.locale = ReadColumn(rowPtr, rowSchema[4]); + data.name = ReadColumn(rowPtr, rowSchema[5]); + data.publicKey = ReadColumn(rowPtr, rowSchema[6]); + data.majorVersion = ReadColumn(rowPtr, rowSchema[7]); + data.flags = ReadColumn(rowPtr, rowSchema[8]); + return data; + } + TbAssemblyRef PolymorphicRawImage::ReadAssemblyRef(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::ASSEMBLYREF).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::ASSEMBLYREF, rawIndex); + auto& rowSchema = GetRowSchema(TableType::ASSEMBLYREF); + TbAssemblyRef data; + data.flags = ReadColumn(rowPtr, rowSchema[0]); + data.majorVersion = ReadColumn(rowPtr, rowSchema[1]); + data.buildNumber = ReadColumn(rowPtr, rowSchema[2]); + data.publicKeyOrToken = ReadColumn(rowPtr, rowSchema[3]); + data.hashValue = ReadColumn(rowPtr, rowSchema[4]); + data.revisionNumber = ReadColumn(rowPtr, rowSchema[5]); + data.minorVersion = ReadColumn(rowPtr, rowSchema[6]); + data.locale = ReadColumn(rowPtr, rowSchema[7]); + data.name = ReadColumn(rowPtr, rowSchema[8]); + return data; + } + TbNestedClass PolymorphicRawImage::ReadNestedClass(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::NESTEDCLASS).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::NESTEDCLASS, rawIndex); + auto& rowSchema = GetRowSchema(TableType::NESTEDCLASS); + TbNestedClass data; + data.enclosingClass = ReadColumn(rowPtr, rowSchema[0]); + data.nestedClass = ReadColumn(rowPtr, rowSchema[1]); + return data; + } + TbGenericParam PolymorphicRawImage::ReadGenericParam(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::GENERICPARAM).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::GENERICPARAM, rawIndex); + auto& rowSchema = GetRowSchema(TableType::GENERICPARAM); + TbGenericParam data; + data.flags = ReadColumn(rowPtr, rowSchema[0]); + data.number = ReadColumn(rowPtr, rowSchema[1]); + data.owner = ReadColumn(rowPtr, rowSchema[2]); + data.name = ReadColumn(rowPtr, rowSchema[3]); + return data; + } + TbMethodSpec PolymorphicRawImage::ReadMethodSpec(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::METHODSPEC).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::METHODSPEC, rawIndex); + auto& rowSchema = GetRowSchema(TableType::METHODSPEC); + TbMethodSpec data; + data.method = ReadColumn(rowPtr, rowSchema[0]); + data.instantiation = ReadColumn(rowPtr, rowSchema[1]); + return data; + } + TbGenericParamConstraint PolymorphicRawImage::ReadGenericParamConstraint(uint32_t rawIndex) + { + IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::GENERICPARAMCONSTRAINT).rowNum); + const byte* rowPtr = GetTableRowPtr(TableType::GENERICPARAMCONSTRAINT, rawIndex); + auto& rowSchema = GetRowSchema(TableType::GENERICPARAMCONSTRAINT); + TbGenericParamConstraint data; + data.constraint = ReadColumn(rowPtr, rowSchema[0]); + data.owner = ReadColumn(rowPtr, rowSchema[1]); + return data; + } + + //!!!}}READ_TABLES_IMPLEMENTATIONS +} +} \ No newline at end of file diff --git a/Templates~/PolymorphicRawImage.h.tpl b/Templates~/PolymorphicRawImage.h.tpl new file mode 100644 index 0000000..f0bf420 --- /dev/null +++ b/Templates~/PolymorphicRawImage.h.tpl @@ -0,0 +1,58 @@ +#pragma once + +#include "RawImageBase.h" + +namespace hybridclr +{ +namespace metadata +{ + + class PolymorphicRawImage : public RawImageBase + { + public: + PolymorphicRawImage() : RawImageBase() + { + + } + + LoadImageErrorCode LoadCLIHeader(uint32_t& entryPointToken, uint32_t& metadataRva, uint32_t& metadataSize) override; + virtual LoadImageErrorCode LoadStreamHeaders(uint32_t metadataRva, uint32_t metadataSize) override; + virtual LoadImageErrorCode LoadTables() override; + virtual void BuildTableRowMetas() override; + + //!!!{{READ_TABLES_OVERRIDES + virtual TbTypeRef ReadTypeRef(uint32_t rawIndex) override; + virtual TbTypeDef ReadTypeDef(uint32_t rawIndex) override; + virtual TbField ReadField(uint32_t rawIndex) override; + virtual TbMethod ReadMethod(uint32_t rawIndex) override; + virtual TbParam ReadParam(uint32_t rawIndex) override; + virtual TbInterfaceImpl ReadInterfaceImpl(uint32_t rawIndex) override; + virtual TbMemberRef ReadMemberRef(uint32_t rawIndex) override; + virtual TbConstant ReadConstant(uint32_t rawIndex) override; + virtual TbCustomAttribute ReadCustomAttribute(uint32_t rawIndex) override; + virtual TbClassLayout ReadClassLayout(uint32_t rawIndex) override; + virtual TbFieldLayout ReadFieldLayout(uint32_t rawIndex) override; + virtual TbStandAloneSig ReadStandAloneSig(uint32_t rawIndex) override; + virtual TbEventMap ReadEventMap(uint32_t rawIndex) override; + virtual TbEvent ReadEvent(uint32_t rawIndex) override; + virtual TbPropertyMap ReadPropertyMap(uint32_t rawIndex) override; + virtual TbProperty ReadProperty(uint32_t rawIndex) override; + virtual TbMethodSemantics ReadMethodSemantics(uint32_t rawIndex) override; + virtual TbMethodImpl ReadMethodImpl(uint32_t rawIndex) override; + virtual TbModuleRef ReadModuleRef(uint32_t rawIndex) override; + virtual TbTypeSpec ReadTypeSpec(uint32_t rawIndex) override; + virtual TbImplMap ReadImplMap(uint32_t rawIndex) override; + virtual TbFieldRVA ReadFieldRVA(uint32_t rawIndex) override; + virtual TbAssembly ReadAssembly(uint32_t rawIndex) override; + virtual TbAssemblyRef ReadAssemblyRef(uint32_t rawIndex) override; + virtual TbNestedClass ReadNestedClass(uint32_t rawIndex) override; + virtual TbGenericParam ReadGenericParam(uint32_t rawIndex) override; + virtual TbMethodSpec ReadMethodSpec(uint32_t rawIndex) override; + virtual TbGenericParamConstraint ReadGenericParamConstraint(uint32_t rawIndex) override; + + //!!!}}READ_TABLES_OVERRIDES + private: + + }; +} +}