/// <summary> /// 执行Patch /// </summary> /// <returns></returns> public PatchInfoData Patch(PatchFlags flags) { PatchInfo patchInfo = null; lock (locker) { #if RECORD_PATCH_STATE patchInfo = HarmonySharedState.GetPatchInfo(original); if (patchInfo == null) { patchInfo = new PatchInfo(); } #endif patchInfo = new PatchInfo(); PatchFunctions.AddPrefix(patchInfo, instance.id, prefix); PatchFunctions.AddPostfix(patchInfo, instance.id, postfix); PatchFunctions.AddTranspiler(patchInfo, instance.id, transpiler); PatchFunctions.UpdateWrapper(original, patchInfo, flags); #if RECORD_PATCH_STATE HarmonySharedState.UpdatePatchInfo(original, patchInfo); #endif } return(patchInfo.patchdata); }
public PatchEntry(long address, long size, long sectionIndex, PatchFlags flags) { this.Address = address; this.Size = size; this.SectionIndex = sectionIndex; this.Flags = flags; }
public PatchHeader(uint index, uint address, int length, PatchCommand command, PatchFlags flags) { Index = index; Address = address; Length = length; Command = command; Flags = flags; }
public static void UpdateWrapper(MethodBase original, PatchInfo patchInfo, PatchFlags flags) { var sortedPrefixes = GetSortedPatchMethods(original, patchInfo.prefixes); var sortedPostfixes = GetSortedPatchMethods(original, patchInfo.postfixes); var sortedTranspilers = GetSortedPatchMethods(original, patchInfo.transpilers).Select(m => TranspilerImpl.From(m)).ToList(); var replacement = MethodPatcher.CreatePatchedMethod(original, sortedPrefixes, sortedPostfixes, sortedTranspilers, flags); if (replacement == null) { throw new MissingMethodException("Cannot create dynamic replacement for " + original); } patchInfo.patchdata.orgaddress = Memory.GetMethodStart(original); patchInfo.patchdata.jmpaddress = Memory.GetMethodStart(replacement); Memory.WriteJump(patchInfo.patchdata.orgaddress, patchInfo.patchdata.jmpaddress, out patchInfo.patchdata.orgbytes, out patchInfo.patchdata.jmpbytes); PatchTools.RememberObject(original, replacement); // no gc for new value + release old value to gc }
public PatchInfoData Patch(MethodBase original, HarmonyMethod prefix, HarmonyMethod postfix, HarmonyMethod transpiler, PatchFlags flags) { var processor = new PatchProcessor(this, original, prefix, postfix, transpiler); return(processor.Patch(flags)); }
public static DynamicMethod CreatePatchedMethod(MethodBase original, List <MethodInfo> prefixes, List <MethodInfo> postfixes, List <TranspilerImpl> transpilers, PatchFlags flags) { if (HarmonyInstance.DEBUG) { FileLog.Log("PATCHING " + original.DeclaringType + " " + original); } var idx = prefixes.Count() + postfixes.Count(); var patch = DynamicTools.CreateDynamicMethod(original, "_Patch" + idx); var il = patch.GetILGenerator(); var originalVariables = DynamicTools.DeclareLocalVariables(original, il); var privateVars = new Dictionary <string, LocalBuilder>(); LocalBuilder resultVariable = null; if (idx > 0) { resultVariable = DynamicTools.DeclareLocalVariable(il, AccessTools.GetReturnedType(original)); privateVars[RESULT_VAR] = resultVariable; } prefixes.ForEach(prefix => { prefix.GetParameters() .Where(patchParam => patchParam.Name == STATE_VAR) .Do(patchParam => { var privateStateVariable = DynamicTools.DeclareLocalVariable(il, patchParam.ParameterType); privateVars[prefix.DeclaringType.FullName] = privateStateVariable; }); }); var afterOriginal1 = il.DefineLabel(); var afterOriginal2 = il.DefineLabel(); bool canHaveJump = false; if (flags.HasFlag(PatchFlags.PF_Detour) == false) { canHaveJump = AddPrefixes(il, original, prefixes, privateVars, afterOriginal2); if (flags.HasFlag(PatchFlags.PF_NoOrigin) == false) { var copier = new MethodCopier(original, patch, originalVariables); foreach (var transpiler in transpilers) { copier.AddTranspiler(transpiler); } copier.Emit(afterOriginal1); Emitter.MarkLabel(il, afterOriginal1); if (resultVariable != null) { Emitter.Emit(il, OpCodes.Stloc, resultVariable); } } } if (canHaveJump) { Emitter.MarkLabel(il, afterOriginal2); } if (AddPostfixes(il, original, postfixes, privateVars)) { if (resultVariable != null) { Emitter.Emit(il, OpCodes.Stloc, resultVariable); } } if (resultVariable != null) { Emitter.Emit(il, OpCodes.Ldloc, resultVariable); } Emitter.Emit(il, OpCodes.Ret); if (HarmonyInstance.DEBUG) { FileLog.Log("DONE"); FileLog.Log(""); } DynamicTools.PrepareDynamicMethod(patch); return(patch); }