From 6cb7237ab9efb79118444796201924a2b785bf70 Mon Sep 17 00:00:00 2001 From: ds5678 <49847914+ds5678@users.noreply.github.com> Date: Fri, 25 Oct 2024 09:35:47 -0700 Subject: [PATCH] Add methods for resolving il2cpp definitions to their contexts --- Cpp2IL.Core.Tests/MemberResolutionTests.cs | 53 +++++++++++++++++++ .../Contexts/ApplicationAnalysisContext.cs | 27 +++++++++- .../ConcreteGenericMethodAnalysisContext.cs | 8 ++- 3 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 Cpp2IL.Core.Tests/MemberResolutionTests.cs diff --git a/Cpp2IL.Core.Tests/MemberResolutionTests.cs b/Cpp2IL.Core.Tests/MemberResolutionTests.cs new file mode 100644 index 00000000..02dfe20c --- /dev/null +++ b/Cpp2IL.Core.Tests/MemberResolutionTests.cs @@ -0,0 +1,53 @@ +using System.Linq; + +namespace Cpp2IL.Core.Tests; + +public class MemberResolutionTests +{ + [SetUp] + public void Setup() + { + Cpp2IlApi.ResetInternalState(); + TestGameLoader.LoadSimple2019Game(); + } + + [Test] + public void TestMethodResolving() + { + var appContext = Cpp2IlApi.CurrentAppContext; + + var methodContext = appContext!.AllTypes.SelectMany(t => t.Methods).First(m => m.Definition is not null); + + Assert.That(appContext.ResolveContextForMethod(methodContext.Definition), Is.EqualTo(methodContext)); + } + + [Test] + public void TestFieldResolving() + { + var appContext = Cpp2IlApi.CurrentAppContext; + + var fieldContext = appContext!.AllTypes.SelectMany(t => t.Fields).First(f => f.BackingData?.Field is not null); + + Assert.That(appContext.ResolveContextForField(fieldContext.BackingData!.Field), Is.EqualTo(fieldContext)); + } + + [Test] + public void TestEventResolving() + { + var appContext = Cpp2IlApi.CurrentAppContext; + + var eventContext = appContext!.AllTypes.SelectMany(t => t.Events).First(e => e.Definition is not null); + + Assert.That(appContext.ResolveContextForEvent(eventContext.Definition), Is.EqualTo(eventContext)); + } + + [Test] + public void TestPropertyResolving() + { + var appContext = Cpp2IlApi.CurrentAppContext; + + var propertyContext = appContext!.AllTypes.SelectMany(t => t.Properties).First(p => p.Definition is not null); + + Assert.That(appContext.ResolveContextForProperty(propertyContext.Definition), Is.EqualTo(propertyContext)); + } +} diff --git a/Cpp2IL.Core/Model/Contexts/ApplicationAnalysisContext.cs b/Cpp2IL.Core/Model/Contexts/ApplicationAnalysisContext.cs index 9af5d2ef..b5fd2f02 100644 --- a/Cpp2IL.Core/Model/Contexts/ApplicationAnalysisContext.cs +++ b/Cpp2IL.Core/Model/Contexts/ApplicationAnalysisContext.cs @@ -161,7 +161,32 @@ private void PopulateMethodsByAddressTable() return AssembliesByName[name]; } - public TypeAnalysisContext? ResolveContextForType(Il2CppTypeDefinition typeDefinition) => GetAssemblyByName(typeDefinition.DeclaringAssembly!.Name!)?.GetTypeByDefinition(typeDefinition); + public TypeAnalysisContext? ResolveContextForType(Il2CppTypeDefinition? typeDefinition) + { + return typeDefinition is not null + ? GetAssemblyByName(typeDefinition.DeclaringAssembly!.Name!)?.GetTypeByDefinition(typeDefinition) + : null; + } + + public MethodAnalysisContext? ResolveContextForMethod(Il2CppMethodDefinition? methodDefinition) + { + return ResolveContextForType(methodDefinition?.DeclaringType)?.Methods.FirstOrDefault(m => m.Definition == methodDefinition); + } + + public FieldAnalysisContext? ResolveContextForField(Il2CppFieldDefinition? field) + { + return ResolveContextForType(field?.DeclaringType)?.Fields.FirstOrDefault(f => f.BackingData?.Field == field); + } + + public EventAnalysisContext? ResolveContextForEvent(Il2CppEventDefinition? eventDefinition) + { + return ResolveContextForType(eventDefinition?.DeclaringType)?.Events.FirstOrDefault(e => e.Definition == eventDefinition); + } + + public PropertyAnalysisContext? ResolveContextForProperty(Il2CppPropertyDefinition? propertyDefinition) + { + return ResolveContextForType(propertyDefinition?.DeclaringType)?.Properties.FirstOrDefault(p => p.Definition == propertyDefinition); + } public BaseKeyFunctionAddresses GetOrCreateKeyFunctionAddresses() { diff --git a/Cpp2IL.Core/Model/Contexts/ConcreteGenericMethodAnalysisContext.cs b/Cpp2IL.Core/Model/Contexts/ConcreteGenericMethodAnalysisContext.cs index fea4dcd4..adffbcd2 100644 --- a/Cpp2IL.Core/Model/Contexts/ConcreteGenericMethodAnalysisContext.cs +++ b/Cpp2IL.Core/Model/Contexts/ConcreteGenericMethodAnalysisContext.cs @@ -35,8 +35,8 @@ private ConcreteGenericMethodAnalysisContext(Cpp2IlMethodRef methodRef, Assembly DeclaringAsm = declaringAssembly; BaseMethodContext = ResolveBaseMethod(methodRef, declaringAssembly.GetTypeByDefinition(methodRef.DeclaringType)!); - var genericTypeParameters = ResolveTypeArray(methodRef.TypeGenericParams, declaringAssembly); - var genericMethodParameters = ResolveTypeArray(methodRef.MethodGenericParams, declaringAssembly); + var genericTypeParameters = ResolveTypeGenericParameters(); + var genericMethodParameters = ResolveMethodGenericParameters(); for (var i = 0; i < BaseMethodContext.Parameters.Count; i++) { @@ -58,6 +58,10 @@ private ConcreteGenericMethodAnalysisContext(Cpp2IlMethodRef methodRef, Assembly rawMethodBody = AppContext.InstructionSet.GetRawBytesForMethod(this, false); } + public TypeAnalysisContext[] ResolveTypeGenericParameters() => ResolveTypeArray(MethodRef.TypeGenericParams, DeclaringAsm); + + public TypeAnalysisContext[] ResolveMethodGenericParameters() => ResolveTypeArray(MethodRef.MethodGenericParams, DeclaringAsm); + private static AssemblyAnalysisContext ResolveDeclaringAssembly(Cpp2IlMethodRef methodRef, ApplicationAnalysisContext context) { return context.GetAssemblyByName(methodRef.DeclaringType.DeclaringAssembly!.Name!)