From d388f8ceab6abb4506ccc132668adc439327e00a Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Sun, 7 Jun 2026 16:56:27 -0500 Subject: [PATCH] Add support for exported type defintions --- .../Model/Contexts/AssemblyAnalysisContext.cs | 7 ++++++- .../AsmResolver/AsmResolverAssemblyPopulator.cs | 8 ++++++++ LibCpp2IL/Metadata/Il2CppImageDefinition.cs | 9 ++++++++- LibCpp2IL/Metadata/Il2CppMetadata.cs | 13 +++++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Cpp2IL.Core/Model/Contexts/AssemblyAnalysisContext.cs b/Cpp2IL.Core/Model/Contexts/AssemblyAnalysisContext.cs index a04f496b..0beb8817 100644 --- a/Cpp2IL.Core/Model/Contexts/AssemblyAnalysisContext.cs +++ b/Cpp2IL.Core/Model/Contexts/AssemblyAnalysisContext.cs @@ -30,6 +30,11 @@ public class AssemblyAnalysisContext : HasCustomAttributesAndName /// public IEnumerable TopLevelTypes => Types.Where(t => t.DeclaringType == null); + /// + /// The analysis context objects for all types exported by this assembly. + /// + public IEnumerable ExportedTypes => (Definition?.Image.ExportedTypes ?? []).Select(t => AppContext.ResolveContextForType(t)!); + /// /// The code gen module for this assembly. /// @@ -185,7 +190,7 @@ public AssemblyAnalysisContext(Il2CppAssemblyDefinition? assemblyDefinition, App InitCustomAttributeData(); - foreach (var il2CppTypeDefinition in Definition.Image.Types!) + foreach (var il2CppTypeDefinition in Definition.Image.Types) { var typeContext = new TypeAnalysisContext(il2CppTypeDefinition, this); Types.Add(typeContext); diff --git a/Cpp2IL.Core/Utils/AsmResolver/AsmResolverAssemblyPopulator.cs b/Cpp2IL.Core/Utils/AsmResolver/AsmResolverAssemblyPopulator.cs index 37843b43..1eeeccf0 100644 --- a/Cpp2IL.Core/Utils/AsmResolver/AsmResolverAssemblyPopulator.cs +++ b/Cpp2IL.Core/Utils/AsmResolver/AsmResolverAssemblyPopulator.cs @@ -41,6 +41,14 @@ public static void ConfigureHierarchy(AssemblyAnalysisContext asmCtx) foreach (var interfaceType in typeCtx.InterfaceContexts) typeDefinition.Interfaces.Add(new(interfaceType.ToTypeSignature(typeDefinition.DeclaringModule!).ToTypeDefOrRef())); } + + var assemblyDefinition = asmCtx.GetExtraData("AsmResolverAssembly") ?? throw new("AsmResolver assembly not found in assembly analysis context for " + asmCtx); + var moduleDefinition = assemblyDefinition.ManifestModule!; + foreach (var typeCtx in asmCtx.ExportedTypes) + { + var owningAssembly = typeCtx.DeclaringAssembly.GetExtraData("AsmResolverAssembly") ?? throw new("AsmResolver assembly not found in assembly analysis context for " + typeCtx.DeclaringAssembly); + moduleDefinition.ExportedTypes.Add(new ExportedType(owningAssembly.ToAssemblyReference(), typeCtx.Namespace, typeCtx.Name)); + } } private static void PopulateGenericParamsForType(TypeAnalysisContext cppTypeDefinition, TypeDefinition ilTypeDefinition) diff --git a/LibCpp2IL/Metadata/Il2CppImageDefinition.cs b/LibCpp2IL/Metadata/Il2CppImageDefinition.cs index 25ab0ee5..dcf40b56 100644 --- a/LibCpp2IL/Metadata/Il2CppImageDefinition.cs +++ b/LibCpp2IL/Metadata/Il2CppImageDefinition.cs @@ -21,12 +21,19 @@ public class Il2CppImageDefinition : ReadableClass public string? Name => OwningContext.Metadata.GetStringFromIndex(nameIndex); - public Il2CppTypeDefinition[]? Types => Enumerable + public Il2CppTypeDefinition[] Types => Enumerable .Range(firstTypeIndex.Value, (int)typeCount) .Select(Il2CppVariableWidthIndex.MakeTemporaryForFixedWidthUsage) // DynWidth: using Enumerable.Range, not read from file, so making temp is ok .Select(OwningContext.Metadata.GetTypeDefinitionFromIndex) .ToArray(); + public Il2CppTypeDefinition[]? ExportedTypes => IsAtLeast(24) + ? Enumerable + .Range(exportedTypeStart.Value, (int)exportedTypeCount) + .Select(OwningContext.Metadata.GetExportedTypeDefintionFromIndex) + .ToArray() + : null; + public override string ToString() { return $"Il2CppImageDefinition[Name={Name}]"; diff --git a/LibCpp2IL/Metadata/Il2CppMetadata.cs b/LibCpp2IL/Metadata/Il2CppMetadata.cs index 6644a2f4..ad1aad25 100644 --- a/LibCpp2IL/Metadata/Il2CppMetadata.cs +++ b/LibCpp2IL/Metadata/Il2CppMetadata.cs @@ -52,6 +52,7 @@ public class Il2CppMetadata : ClassReadingBinaryReader public Il2CppFieldRef[] fieldRefs; private Il2CppGenericParameter[] genericParameters; public Il2CppVariableWidthIndex[] constraintIndices; + public int[] exportedTypes; public int[] referencedAssemblies; @@ -370,6 +371,16 @@ private Il2CppMetadata(MemoryStream stream, UnityVersion unityVersion, float met stringLiterals = ReadMetadataClassArray(metadataHeader.stringLiteral); LibLogger.VerboseNewline($"OK ({(DateTime.Now - start).TotalMilliseconds} ms)"); + if (MetadataVersion > 24) + { + LibLogger.Verbose("\tReading exported types..."); + start = DateTime.Now; + + exportedTypes = ReadClassArrayAtRawAddr(metadataHeader.exportedTypeDefinitions.Offset, metadataHeader.exportedTypeDefinitions.Size / sizeof(int)); + + LibLogger.VerboseNewline($"OK ({(DateTime.Now - start).TotalMilliseconds} ms)"); + } + if (MetadataVersion < 24.2f) { LibLogger.Verbose("\tReading RGCTX data..."); @@ -685,6 +696,8 @@ internal string ReadStringFromIndexNoReadLock(int index) } public Il2CppTypeDefinition GetTypeDefinitionFromIndex(Il2CppVariableWidthIndex index) => typeDefs[index.Value]; + + public Il2CppTypeDefinition GetExportedTypeDefintionFromIndex(int index) => typeDefs[exportedTypes[index]]; public Il2CppGenericContainer GetGenericContainerFromIndex(Il2CppVariableWidthIndex index) => genericContainers[index.Value];