internal static (long FlagRva, long TokenRva) FindMetadataInitForMethod(MethodRewriteContext method, long gameAssemblyBase) { if (MetadataInitForMethodRva == 0) { FindMetadataInitForMethod(method.DeclaringType.AssemblyContext.GlobalContext, gameAssemblyBase); } var codeStart = (IntPtr)(gameAssemblyBase + method.FileOffset); var firstCall = XrefScannerLowLevel.JumpTargets(codeStart).FirstOrDefault(); if (firstCall != MetadataInitForMethodFileOffset || firstCall == IntPtr.Zero) { return(0, 0); } var tokenPointer = XrefScanUtilFinder.FindLastRcxReadAddressBeforeCallTo(codeStart, MetadataInitForMethodFileOffset); var initFlagPointer = XrefScanUtilFinder.FindByteWriteTargetRightAfterCallTo(codeStart, MetadataInitForMethodFileOffset); if (tokenPointer == IntPtr.Zero || initFlagPointer == IntPtr.Zero) { return(0, 0); } return((long)initFlagPointer - gameAssemblyBase - method.FileOffset + method.Rva, (long)tokenPointer - gameAssemblyBase - method.FileOffset + method.Rva); }
private static void FindMetadataInitForMethod(RewriteGlobalContext context, long gameAssemblyBase) { var unityObjectCctor = context.Assemblies .Single(it => it.OriginalAssembly.Name.Name == "UnityEngine.CoreModule").GetTypeByName("UnityEngine.Object").OriginalType.Methods.Single(it => it.Name == ".cctor"); MetadataInitForMethodFileOffset = (IntPtr)((long)XrefScannerLowLevel.JumpTargets((IntPtr)(gameAssemblyBase + unityObjectCctor.ExtractOffset())).First()); MetadataInitForMethodRva = (long)MetadataInitForMethodFileOffset - gameAssemblyBase - unityObjectCctor.ExtractOffset() + unityObjectCctor.ExtractRva(); }
private static unsafe void FindMetadataInitForMethod() { var unityObjectCctor = AppDomain.CurrentDomain.GetAssemblies() .Single(it => it.GetSimpleName() == "UnityEngine.CoreModule").GetType("UnityEngine.Object") .GetConstructors(BindingFlags.Static | BindingFlags.NonPublic).Single(); var nativeMethodInfo = IL2CPP.il2cpp_method_get_from_reflection(unityObjectCctor.Pointer); ourMetadataInitForMethodPointer = XrefScannerLowLevel.JumpTargets(*(IntPtr *)nativeMethodInfo).First(); ourMetadataInitForMethodDelegate = Marshal.GetDelegateForFunctionPointer <InitMetadataForMethod>(ourMetadataInitForMethodPointer); }
internal static unsafe bool CallMetadataInitForMethod(MethodBase method) { if (ourMetadataInitForMethodPointer == IntPtr.Zero) { FindMetadataInitForMethod(); } var nativeMethodInfoObject = UnhollowerUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(method)?.GetValue(null); if (nativeMethodInfoObject == null) { return(false); } var nativeMethodInfo = (IntPtr)nativeMethodInfoObject; var codeStart = *(IntPtr *)nativeMethodInfo; var firstCall = XrefScannerLowLevel.JumpTargets(codeStart).FirstOrDefault(); if (firstCall != ourMetadataInitForMethodPointer || firstCall == IntPtr.Zero) { return(false); } var tokenPointer = XrefScanUtilFinder.FindLastRcxReadAddressBeforeCallTo(codeStart, ourMetadataInitForMethodPointer); var initFlagPointer = XrefScanUtilFinder.FindByteWriteTargetRightAfterCallTo(codeStart, ourMetadataInitForMethodPointer); if (tokenPointer == IntPtr.Zero || initFlagPointer == IntPtr.Zero) { return(false); } if (Marshal.ReadByte(initFlagPointer) == 0) { ourMetadataInitForMethodDelegate(Marshal.ReadInt32(tokenPointer)); Marshal.WriteByte(initFlagPointer, 1); } return(true); }