diff --git a/Il2CppInspector.Common/IL2CPP/Il2CppInspector.cs b/Il2CppInspector.Common/IL2CPP/Il2CppInspector.cs index 90f45f2..e502399 100644 --- a/Il2CppInspector.Common/IL2CPP/Il2CppInspector.cs +++ b/Il2CppInspector.Common/IL2CPP/Il2CppInspector.cs @@ -60,9 +60,9 @@ namespace Il2CppInspector public List GenericInstances => Binary.GenericInstances; public Dictionary Modules => Binary.Modules; public ulong[] CustomAttributeGenerators { get; } - public ulong[] MethodInvokePointers => Binary.MethodInvokePointers; + public ulong[] MethodInvokePointers { get; } public Il2CppMethodSpec[] MethodSpecs => Binary.MethodSpecs; - public Dictionary GenericMethodPointers => Binary.GenericMethodPointers; + public Dictionary GenericMethodPointers { get; } public Dictionary GenericMethodInvokerIndices => Binary.GenericMethodInvokerIndices; // TODO: Finish all file access in the constructor and eliminate the need for this @@ -218,6 +218,14 @@ namespace Il2CppInspector return null; } + // Thumb instruction pointers have the bottom bit set to signify a switch from ARM to Thumb when jumping + private ulong getDecodedAddress(ulong addr) { + if (BinaryImage.Arch != "ARM" && BinaryImage.Arch != "ARM64") + return addr; + + return addr & 0xffff_ffff_ffff_fffe; + } + public Il2CppInspector(Il2CppBinary binary, Metadata metadata) { // Store stream representations Binary = binary; @@ -277,11 +285,16 @@ namespace Il2CppInspector } } + // Decode addresses for Thumb etc. without altering the Il2CppBinary structure data + CustomAttributeGenerators = CustomAttributeGenerators.Select(a => getDecodedAddress(a)).ToArray(); + MethodInvokePointers = Binary.MethodInvokePointers.Select(a => getDecodedAddress(a)).ToArray(); + GenericMethodPointers = Binary.GenericMethodPointers.ToDictionary(a => a.Key, a => getDecodedAddress(a.Value)); + // Get sorted list of function pointers from all sources // TODO: This does not include IL2CPP API functions var sortedFunctionPointers = (Version <= 24.1)? - Binary.GlobalMethodPointers.ToList() : - Binary.ModuleMethodPointers.SelectMany(module => module.Value).ToList(); + Binary.GlobalMethodPointers.Select(a => getDecodedAddress(a)).ToList() : + Binary.ModuleMethodPointers.SelectMany(module => module.Value).Select(a => getDecodedAddress(a)).ToList(); sortedFunctionPointers.AddRange(CustomAttributeGenerators); sortedFunctionPointers.AddRange(MethodInvokePointers); @@ -354,13 +367,14 @@ namespace Il2CppInspector // Consider the end of the method to be the start of the next method (or zero) // The last method end will be wrong but there is no way to calculate it - return (start & 0xffff_ffff_ffff_fffe, FunctionAddresses[start]); + start = getDecodedAddress(start); + return (start, FunctionAddresses[start]); } // Get a concrete generic method pointer if available public (ulong Start, ulong End)? GetGenericMethodPointer(Il2CppMethodSpec spec) { if (GenericMethodPointers.TryGetValue(spec, out var start)) { - return (start & 0xffff_ffff_ffff_fffe, FunctionAddresses[start]); + return (start, FunctionAddresses[start]); } return null; } diff --git a/Il2CppInspector.Common/Reflection/MethodInvoker.cs b/Il2CppInspector.Common/Reflection/MethodInvoker.cs index afd05fe..02eb3df 100644 --- a/Il2CppInspector.Common/Reflection/MethodInvoker.cs +++ b/Il2CppInspector.Common/Reflection/MethodInvoker.cs @@ -47,7 +47,7 @@ namespace Il2CppInspector.Reflection ParameterTypes = exampleMethod.DeclaredParameters.Select(p => mapParameterType(model, p.ParameterType)).ToArray(); var start = Package.MethodInvokePointers[Index]; - VirtualAddress = (start & 0xffff_ffff_ffff_fffe, Package.FunctionAddresses[start]); + VirtualAddress = (start, Package.FunctionAddresses[start]); } // The invokers use Object for all reference types, and SByte for booleans