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); }
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); }