InjectFix 學習


unity版本: 2018.4.6f1

 

https://github.com/Tencent/InjectFix

學習項目  void87/InjectFixLearn (github.com)

 

安裝

編譯

  • Window下打開源碼包的Source\VSProj\build_for_unity.bat,UNITY_HOME變量的值修改為指向本機unity安裝目錄
  • 運行build_for_unity.bat

 

 

 

 

 

 

復制

這里對應的是一個Unity工程目錄

  • IFixToolKit拷貝到Unity項目的Assets同級目錄
  • Assets/IFix,Assets/Plugins拷貝到Unity項目的Assets下

 

 

HelloWorld

HelloWorld(編輯器下體驗iFix)

  1. 模擬有bug的項目

原始Calculator(加和乘都是錯的)

namespace IFix.Test
{
    //HelloworldCfg.cs里配置了這個類型
    public class Calculator
    {
        //修改成正確的邏輯后,打開如下注釋,生成的補丁將修正該函數
        //[Patch]
        public int Add(int a, int b)
        {
            return a * b;
        }

        public int Sub(int a, int b)
        {
            return a / b;
        }
    }
}
Calculator

配置類HelloworldCfg

using System.Collections.Generic;
using IFix;
using System;


// 1. 配置類必須打[Configure]標簽
// 2. 必須放Editor目錄
[Configure]
public class HelloworldCfg
{
    [IFix]
    static IEnumerable<Type> hotfix {
        get {
            return new List<Type>()
            {
                typeof(IFix.Test.Calculator)
            };
        }
    }
}
HelloworldCfg

Helloworld

using UnityEngine;
using IFix.Core;
using System.IO;
using System.Diagnostics;

// 跑不同仔細看文檔Doc/example.md
public class Helloworld : MonoBehaviour {

    // check and load patchs
    void Start () {
        VirtualMachine.Info = (s) => UnityEngine.Debug.Log(s);
        //try to load patch for Assembly-CSharp.dll
        var patch = Resources.Load<TextAsset>("Assembly-CSharp.patch");
        if (patch != null)
        {
            UnityEngine.Debug.Log("loading Assembly-CSharp.patch ...");
            var sw = Stopwatch.StartNew();
            PatchManager.Load(new MemoryStream(patch.bytes));
            UnityEngine.Debug.Log("patch Assembly-CSharp.patch, using " + sw.ElapsedMilliseconds + " ms");
        }
        test();
    }

    //[IFix.Patch]
    void test()
    {
        var calc = new IFix.Test.Calculator();
        //test calc.Add
        UnityEngine.Debug.Log("10 + 9 = " + calc.Add(10, 9));
        //test calc.Sub
        UnityEngine.Debug.Log("10 - 2 = " + calc.Sub(10, 2));
    }
}
Helloworld

  2. 修復Bug

 修改后的Calculator(模擬修bug后,生成文件 Assembly-CSharp.patch.bytes)

namespace IFix.Test
{
    //HelloworldCfg.cs里配置了這個類型
    public class Calculator
    {
        //修改成正確的邏輯后,打開如下注釋,生成的補丁將修正該函數
        [Patch]
        public int Add(int a, int b)
        {
            return a + b;
            // return a * b;
        }

        public int Sub(int a, int b)
        {
            return a / b;
        }
    }
}
Calculator

修復bug后,點擊生成 

  3. 回滾到有bug的代碼,模擬發包(包里有bug)

將代碼還原成有bug的代碼

namespace IFix.Test
{
    //HelloworldCfg.cs里配置了這個類型
    public class Calculator
    {
        //修改成正確的邏輯后,打開如下注釋,生成的補丁將修正該函數
        //[Patch]
        public int Add(int a, int b)
        {
            return a * b;
        }

        public int Sub(int a, int b)
        {
            return a / b;
        }
    }
Calculator

點擊.一個版本的包只需要點一次

將Assembly-CSharp.patch.bytes拷貝到

啟動帶有Assembly-CSharp.patch.bytes補丁的代碼

 

 

 

 

 

 

 

 

 

 

 

 

 

各種測試

  IFix.Patch 測試

  IFix.Patch 支持普通方法

        // IFix.Patch支持普通方法
        [IFix.Patch]
        public int Add(int a, int b)
        {
            return a * b;
        }
IFix.Patch 支持普通方法

  IFix.Patch 不支持泛型方法

        // IFix.Patch 不支持泛型方法
        [IFix.Patch]
        public void GenericMethod<T>(T t)
        {
            UnityEngine.Debug.Log("GenericMethod<T>: " + t);
        }
IFix.Patch 不支持泛型方法

參考

patch有泛用型參數的函數,unity編輯器報錯  

  IFix.Patch 支持普通方法中調用泛型方法

        // IFix.Patch 支持普通方法
        [IFix.Patch]
        public int Add(int a, int b)
        {
            // IFix.Patch 支持普通方法中調用泛型方法
            InnerGenericMethod<string>("arg");
            return a * b;
        }

        public void InnerGenericMethod<T>(T t)
        {
            UnityEngine.Debug.Log("InnerGenericMethod: " + t);
        }
IFix.Patch 支持普通方法中調用泛型方法

參考

請教,補丁中的方法內,調用泛型邏輯也不可以嗎?

  IFix.Patch 不支持字段

        // IFix.Patch 不支持字段
        [IFix.Patch]
        public string TestField = "TestField";
IFix.Patch 不支持字段

  IFix.Patch 支持普通協程 

    // IFix.Patch 支持普通協程
    [IFix.Patch]
    public IEnumerator PatchEnumerator()
    {
        yield return new WaitForSeconds(1);
        UnityEngine.Debug.Log("Wait 1 Second");
    }
IFix.Patch 支持普通協程

  IFix.Patch 不支持構造函數

        // IFix.Patch 不支持構造函數
        [IFix.Patch]
        public Calculator()
        {

        }
IFix.Patch 不支持構造函數

參考

private 構造函數無法patch

  IFix.Patch 支持getter,setter函數

    private string testField = "testField";

    public string TestProperty {
        [IFix.Patch]
        get { return testField; }
        [IFix.Patch]
        set {
            testField = value;
        }
    }
getter, setter

參考

對成員變量的get和set函數支持

 

 

 

 

  IFix.Interpret

  IFix.Interpret 支持不帶泛型方法的新憎類

// IFix.Interpret 支持不帶泛型方法的新增類 
[IFix.Interpret]
public class NewClass
{
    public Action<object> act;

    public string testField = "TestField";

    public NewClass(string cons)
    {
        UnityEngine.Debug.Log("NewClass.Constructor");
    }
}
IFix.Interpret 支持不帶泛型方法的新增類

  IFix.Interpret 不支持帶泛型方法的新增類

// IFix.Interpret 不支持帶泛型方法的新增類
[IFix.Interpret]
public class PatchClass
{
    public void PatchGenericMethod<T>(T t)
    {
        UnityEngine.Debug.Log(t);
    }
}
IFix.Interpret 不支持帶泛型方法的新增類

  IFix.Interpret 支持新增普通方法

        // IFix.Interpret 支持新增普通方法
        [IFix.Interpret]
        public void PatchMethod()
        {
            UnityEngine.Debug.Log("PatchMethod");
        }
IFix.Interpret 支持新增普通方法

參考

補丁里能否新增方法, 如果可以, 應該如何操作?

  IFix.Interpret 不支持新增泛型方法

        // IFix.Interpret 不支持新增泛型方法
        [IFix.Interpret]
        public void PatchGenericMethod<T>(T t)
        {
            UnityEngine.Debug.Log("PatchGenericMethod");
        }
IFix.Interpret 不支持新增泛型方法

  IFix.Interpret 支持新增類繼承新增類

[IFix.Interpret]
public class PatchBaseClass
{
    public void BaseMethod()
    {
        UnityEngine.Debug.Log("BaseMethod");
    }
}

// IFix.Interpret 支持新增類繼承新增類
[IFix.Interpret]
public class PatchChildClass : PatchBaseClass
{
    public void ChildMethod()
    {
        UnityEngine.Debug.Log("ChildMethod");
    }
}
IFix.Interpret 支持新增類繼承新增類

參考

實現新增類可以繼承新增類的功能

  IFix.Interpret 不支持字段

        // IFix.Patch 不支持字段
        [IFix.Interpret]
        public string TestField = "TestField";
IFix.Patch 不支持字段

參考

InjectFix 如何新增字段

如果要修復的腳本新增了成員變量,這個該如何更新呢

  IFix.Interpret 不支持構造函數

        // IFix.Interpret 不支持構造函數
        [IFix.Interpret]
        public Calculator()
        {

        }
IFix.Interpret 不支持構造函數

  IFix.Interpret支持協程,但有限制

    // 非熱更代碼里用過 IEnumerator
    private IEnumerator IE_Main()
    {
        yield return new WaitForEndOfFrame();
        Debug.Log("IE_Main");
    }

    [IFix.Interpret]
    private IEnumerator IE_Patch()
    {
        // 非熱更代碼里用過 IEnumerator, 熱更代碼里可以使用
        yield return new WaitForSeconds(1);
        yield return new WaitForEndOfFrame();
        yield return 0;
        yield return null;
        Debug.Log("IE_Patch");
        yield break;
    }
非熱更代碼里用過 IEnumerator, 熱更代碼里可以使用
    [IFix.Interpret]
    public IEnumerator IE_Patch()
    {
        // 非熱更代碼里沒有用過 IEnumerator, 熱更代碼里不可以使用
        yield return new WaitForSeconds(1);
        yield return new WaitForEndOfFrame();
        yield return 0;
        yield return null;
        Debug.Log("IE_Patch");
        yield break;
    }
非熱更代碼里沒有用過 IEnumerator, 熱更代碼里不可以使用

參考

不支持新增協程嗎?   

  IFix.Interpret不支持Struct

參考

如何新增一個struct類型 

  IFix.CustomBridge

  熱更代碼新增實現非熱更代碼里的接口時,需要在非熱更代碼里增加處理, 熱更代碼目前不支持繼承非熱更代碼里的原生類

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {
    
    [IFix.Patch]
    void Start() {
        PatchClassInheritInterface pcii = new PatchClassInheritInterface();
        pcii.TestInterfaceMethod();

        //PatchClassInheritClass pcic = new PatchClassInheritClass();
        //pcic.TestMethod();
    }
    
}

// 非熱更接口
public interface TestInterface {
    void TestInterfaceMethod();
}


// 熱更新增類能繼承非熱更原生接口
[IFix.Interpret]
public class PatchClassInheritInterface : TestInterface {
    public void TestInterfaceMethod() {
        UnityEngine.Debug.Log("TestInterfaceMethod");
    }
}

//// 非熱更類
//public class TestClass {
//    public virtual void TestMethod() {
//        Debug.Log("TestMethod");
//    }
//}

//// 熱更新增類不能繼承非熱更原生類
//[IFix.Interpret]
//public class PatchClassInheritClass : TestClass {
//    public override void TestMethod() {
//        Debug.Log("TestMethod");
//    }
//}

// 要在非熱更代碼里提前加上
[IFix.CustomBridge]
public static class AdditionalBridge {
    static List<Type> bridge = new List<Type>()
    {
        typeof(TestInterface),
        // typeof(TestClass)    // 目前不支持, 熱更新增類繼承非熱更原生接口
    };
}
熱更代碼支持繼承非熱更代碼里的接口,不支持非熱更代碼里的原生類

 

參考

[IFix.CustomBridge]

CustomBridge的新增類只支持interface,不支持class

 

 

 

 

  IL2CPP相關

支持IL2CPP嗎?

打包方式為IL2CPP,是否支持?

Some questions about Fix in IL2CPP mode

unity ios xcode工程編譯不通過

請問支持ios和android的il2cpp編譯方式嗎

 

  版本相關

InjectFix對Unity的版本要求

 

  async

    

 

 

  Instruction

使用 build_for_unity.bat 生成的 Instruction.cs

/*
 * Tencent is pleased to support the open source community by making InjectFix available.
 * Copyright (C) 2019 THL A29 Limited, a Tencent company.  All rights reserved.
 * InjectFix is licensed under the MIT License, except for the third-party components listed in the file 'LICENSE' which may be subject to their corresponding license terms. 
 * This file is subject to the terms and conditions defined in file 'LICENSE', which is part of this source code package.
 */

namespace IFix.Core
{
    public enum Code
    {
        Newobj,

        //Pseudo instruction
        StackSpace,
        Ldelem_I8,
        Pop,
        Ldelem_U4,
        Constrained,
        Throw,
        Ldc_R4,
        Cpblk,
        Sizeof,
        Stind_I8,
        Not,
        Cpobj,
        Unaligned,
        Ldelem_U1,
        Ldelem_I1,
        CallExtern,
        Ldelem_R4,
        Conv_Ovf_I2_Un,
        Sub,
        Sub_Ovf_Un,
        Stind_R8,
        Ldind_U1,
        Ldsflda,
        Ble,
        Localloc,
        Ldstr,
        Add,
        Stelem_R4,
        Unbox_Any,
        Conv_U,
        Initblk,
        Leave,
        Stind_I,
        Conv_I2,
        Cgt,
        Stind_I1,
        Stind_I2,
        Conv_Ovf_U1,
        Ckfinite,
        Ldind_U2,
        Ldfld,
        Box,
        Conv_Ovf_U,
        Bgt_Un,
        Bge_Un,
        Break,
        Blt,
        Ldc_I8,
        Conv_Ovf_U8_Un,
        Conv_R4,
        Stelem_Any,
        Beq,
        Volatile,
        Ldind_U4,
        //Calli,
        Ldloca,
        Ldtype, // custom
        Ldelema,
        Ldobj,
        Mkrefany,
        Newanon,
        Ldelem_I4,
        Stobj,
        Mul,
        Ldloc,
        Stind_Ref,
        Ldelem_R8,
        Stsfld,
        Rem_Un,
        Callvirt,
        Ldind_I2,
        Shr,
        No,
        Stind_R4,
        Ldind_I8,
        Conv_R_Un,
        Sub_Ovf,
        Initobj,
        Ldind_Ref,
        Refanytype,
        Stelem_I2,
        Ldlen,
        Stelem_I8,
        Ldind_I1,
        Ldarg,
        Conv_Ovf_I,
        Shl,
        Ldelem_Any,
        Stloc,
        Brfalse,
        Conv_Ovf_I4,
        Bge,
        Endfilter,
        Stelem_Ref,
        Conv_U1,
        Newarr,
        Ldelem_Ref,
        Conv_Ovf_I8_Un,
        Conv_Ovf_U8,
        Brtrue,
        Castclass,
        Conv_U8,
        Stelem_I,
        Dup,
        Conv_Ovf_I2,
        Readonly,
        Stelem_R8,
        Conv_Ovf_U1_Un,
        Conv_Ovf_I8,
        Ldind_R4,
        Clt_Un,
        Starg,
        Conv_I4,
        Add_Ovf,
        Conv_Ovf_I_Un,
        Ldtoken,
        Conv_Ovf_I4_Un,
        Ldind_R8,
        Conv_Ovf_U4_Un,
        Ldc_R8,
        Ldelem_U2,
        Div,
        Conv_I8,
        Mul_Ovf_Un,
        Cgt_Un,
        Unbox,
        Ldnull,
        Ldvirtftn,
        Callvirtvirt,
        Ble_Un,
        Conv_Ovf_U2,
        Endfinally,
        Div_Un,
        Bgt,
        Conv_Ovf_I1,
        Ldarga,
        Br,
        Conv_I1,
        Ldelem_I2,
        Arglist,
        Conv_Ovf_U4,
        Ceq,
        And,
        Stfld,
        Conv_R8,
        Stind_I4,
        Refanyval,
        Ldelem_I,
        Tail,
        Blt_Un,
        Rethrow,
        Call,
        Jmp,
        Conv_U4,
        Shr_Un,
        Stelem_I1,
        Stelem_I4,
        Ldsfld,
        Conv_Ovf_U2_Un,
        Mul_Ovf,
        Ldc_I4,
        Ldind_I,
        Ldflda,
        Ret,
        Nop,
        Conv_I,
        Neg,
        Conv_Ovf_I1_Un,
        Clt,
        Conv_U2,
        Bne_Un,
        Switch,
        Isinst,
        Ldftn,
        Conv_Ovf_U_Un,
        Rem,
        Ldind_I4,
        Xor,
        Add_Ovf_Un,
        Or,
    }

    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
    public struct Instruction
    {
        /// <summary>
        /// 指令MAGIC
        /// </summary>
        public const ulong INSTRUCTION_FORMAT_MAGIC = 5158825760788742785;

        /// <summary>
        /// 當前指令
        /// </summary>
        public Code Code;

        /// <summary>
        /// 操作數
        /// </summary>
        public int Operand;
    }

    public enum ExceptionHandlerType
    {
        Catch = 0,
        Filter = 1,
        Finally = 2,
        Fault = 4
    }

    public sealed class ExceptionHandler
    {
        public System.Type CatchType;
        public int CatchTypeId;
        public int HandlerEnd;
        public int HandlerStart;
        public ExceptionHandlerType HandlerType;
        public int TryEnd;
        public int TryStart;
    }
}
生成的 Instruction.cs

反編譯 IFix.exe 后的相關代碼

using System;

namespace IFix.Core
{
    // Token: 0x02000002 RID: 2
    public enum Code
    {
        // Token: 0x04000002 RID: 2
        Newobj,
        // Token: 0x04000003 RID: 3
        StackSpace,
        // Token: 0x04000004 RID: 4
        Ldelem_I8,
        // Token: 0x04000005 RID: 5
        Pop,
        // Token: 0x04000006 RID: 6
        Ldelem_U4,
        // Token: 0x04000007 RID: 7
        Constrained,
        // Token: 0x04000008 RID: 8
        Throw,
        // Token: 0x04000009 RID: 9
        Ldc_R4,
        // Token: 0x0400000A RID: 10
        Cpblk,
        // Token: 0x0400000B RID: 11
        Sizeof,
        // Token: 0x0400000C RID: 12
        Stind_I8,
        // Token: 0x0400000D RID: 13
        Not,
        // Token: 0x0400000E RID: 14
        Cpobj,
        // Token: 0x0400000F RID: 15
        Unaligned,
        // Token: 0x04000010 RID: 16
        Ldelem_U1,
        // Token: 0x04000011 RID: 17
        Ldelem_I1,
        // Token: 0x04000012 RID: 18
        CallExtern,
        // Token: 0x04000013 RID: 19
        Ldelem_R4,
        // Token: 0x04000014 RID: 20
        Conv_Ovf_I2_Un,
        // Token: 0x04000015 RID: 21
        Sub,
        // Token: 0x04000016 RID: 22
        Sub_Ovf_Un,
        // Token: 0x04000017 RID: 23
        Stind_R8,
        // Token: 0x04000018 RID: 24
        Ldind_U1,
        // Token: 0x04000019 RID: 25
        Ldsflda,
        // Token: 0x0400001A RID: 26
        Ble,
        // Token: 0x0400001B RID: 27
        Localloc,
        // Token: 0x0400001C RID: 28
        Ldstr,
        // Token: 0x0400001D RID: 29
        Add,
        // Token: 0x0400001E RID: 30
        Stelem_R4,
        // Token: 0x0400001F RID: 31
        Unbox_Any,
        // Token: 0x04000020 RID: 32
        Conv_U,
        // Token: 0x04000021 RID: 33
        Initblk,
        // Token: 0x04000022 RID: 34
        Leave,
        // Token: 0x04000023 RID: 35
        Stind_I,
        // Token: 0x04000024 RID: 36
        Conv_I2,
        // Token: 0x04000025 RID: 37
        Cgt,
        // Token: 0x04000026 RID: 38
        Stind_I1,
        // Token: 0x04000027 RID: 39
        Stind_I2,
        // Token: 0x04000028 RID: 40
        Conv_Ovf_U1,
        // Token: 0x04000029 RID: 41
        Ckfinite,
        // Token: 0x0400002A RID: 42
        Ldind_U2,
        // Token: 0x0400002B RID: 43
        Ldfld,
        // Token: 0x0400002C RID: 44
        Box,
        // Token: 0x0400002D RID: 45
        Conv_Ovf_U,
        // Token: 0x0400002E RID: 46
        Bgt_Un,
        // Token: 0x0400002F RID: 47
        Bge_Un,
        // Token: 0x04000030 RID: 48
        Break,
        // Token: 0x04000031 RID: 49
        Blt,
        // Token: 0x04000032 RID: 50
        Ldc_I8,
        // Token: 0x04000033 RID: 51
        Conv_Ovf_U8_Un,
        // Token: 0x04000034 RID: 52
        Conv_R4,
        // Token: 0x04000035 RID: 53
        Stelem_Any,
        // Token: 0x04000036 RID: 54
        Beq,
        // Token: 0x04000037 RID: 55
        Volatile,
        // Token: 0x04000038 RID: 56
        Ldind_U4,
        // Token: 0x04000039 RID: 57
        Ldloca,
        // Token: 0x0400003A RID: 58
        Ldtype,
        // Token: 0x0400003B RID: 59
        Ldelema,
        // Token: 0x0400003C RID: 60
        Ldobj,
        // Token: 0x0400003D RID: 61
        Mkrefany,
        // Token: 0x0400003E RID: 62
        Newanon,
        // Token: 0x0400003F RID: 63
        Ldelem_I4,
        // Token: 0x04000040 RID: 64
        Stobj,
        // Token: 0x04000041 RID: 65
        Mul,
        // Token: 0x04000042 RID: 66
        Ldloc,
        // Token: 0x04000043 RID: 67
        Stind_Ref,
        // Token: 0x04000044 RID: 68
        Ldelem_R8,
        // Token: 0x04000045 RID: 69
        Stsfld,
        // Token: 0x04000046 RID: 70
        Rem_Un,
        // Token: 0x04000047 RID: 71
        Callvirt,
        // Token: 0x04000048 RID: 72
        Ldind_I2,
        // Token: 0x04000049 RID: 73
        Shr,
        // Token: 0x0400004A RID: 74
        No,
        // Token: 0x0400004B RID: 75
        Stind_R4,
        // Token: 0x0400004C RID: 76
        Ldind_I8,
        // Token: 0x0400004D RID: 77
        Conv_R_Un,
        // Token: 0x0400004E RID: 78
        Sub_Ovf,
        // Token: 0x0400004F RID: 79
        Initobj,
        // Token: 0x04000050 RID: 80
        Ldind_Ref,
        // Token: 0x04000051 RID: 81
        Refanytype,
        // Token: 0x04000052 RID: 82
        Stelem_I2,
        // Token: 0x04000053 RID: 83
        Ldlen,
        // Token: 0x04000054 RID: 84
        Stelem_I8,
        // Token: 0x04000055 RID: 85
        Ldind_I1,
        // Token: 0x04000056 RID: 86
        Ldarg,
        // Token: 0x04000057 RID: 87
        Conv_Ovf_I,
        // Token: 0x04000058 RID: 88
        Shl,
        // Token: 0x04000059 RID: 89
        Ldelem_Any,
        // Token: 0x0400005A RID: 90
        Stloc,
        // Token: 0x0400005B RID: 91
        Brfalse,
        // Token: 0x0400005C RID: 92
        Conv_Ovf_I4,
        // Token: 0x0400005D RID: 93
        Bge,
        // Token: 0x0400005E RID: 94
        Endfilter,
        // Token: 0x0400005F RID: 95
        Stelem_Ref,
        // Token: 0x04000060 RID: 96
        Conv_U1,
        // Token: 0x04000061 RID: 97
        Newarr,
        // Token: 0x04000062 RID: 98
        Ldelem_Ref,
        // Token: 0x04000063 RID: 99
        Conv_Ovf_I8_Un,
        // Token: 0x04000064 RID: 100
        Conv_Ovf_U8,
        // Token: 0x04000065 RID: 101
        Brtrue,
        // Token: 0x04000066 RID: 102
        Castclass,
        // Token: 0x04000067 RID: 103
        Conv_U8,
        // Token: 0x04000068 RID: 104
        Stelem_I,
        // Token: 0x04000069 RID: 105
        Dup,
        // Token: 0x0400006A RID: 106
        Conv_Ovf_I2,
        // Token: 0x0400006B RID: 107
        Readonly,
        // Token: 0x0400006C RID: 108
        Stelem_R8,
        // Token: 0x0400006D RID: 109
        Conv_Ovf_U1_Un,
        // Token: 0x0400006E RID: 110
        Conv_Ovf_I8,
        // Token: 0x0400006F RID: 111
        Ldind_R4,
        // Token: 0x04000070 RID: 112
        Clt_Un,
        // Token: 0x04000071 RID: 113
        Starg,
        // Token: 0x04000072 RID: 114
        Conv_I4,
        // Token: 0x04000073 RID: 115
        Add_Ovf,
        // Token: 0x04000074 RID: 116
        Conv_Ovf_I_Un,
        // Token: 0x04000075 RID: 117
        Ldtoken,
        // Token: 0x04000076 RID: 118
        Conv_Ovf_I4_Un,
        // Token: 0x04000077 RID: 119
        Ldind_R8,
        // Token: 0x04000078 RID: 120
        Conv_Ovf_U4_Un,
        // Token: 0x04000079 RID: 121
        Ldc_R8,
        // Token: 0x0400007A RID: 122
        Ldelem_U2,
        // Token: 0x0400007B RID: 123
        Div,
        // Token: 0x0400007C RID: 124
        Conv_I8,
        // Token: 0x0400007D RID: 125
        Mul_Ovf_Un,
        // Token: 0x0400007E RID: 126
        Cgt_Un,
        // Token: 0x0400007F RID: 127
        Unbox,
        // Token: 0x04000080 RID: 128
        Ldnull,
        // Token: 0x04000081 RID: 129
        Ldvirtftn,
        // Token: 0x04000082 RID: 130
        Callvirtvirt,
        // Token: 0x04000083 RID: 131
        Ble_Un,
        // Token: 0x04000084 RID: 132
        Conv_Ovf_U2,
        // Token: 0x04000085 RID: 133
        Endfinally,
        // Token: 0x04000086 RID: 134
        Div_Un,
        // Token: 0x04000087 RID: 135
        Bgt,
        // Token: 0x04000088 RID: 136
        Conv_Ovf_I1,
        // Token: 0x04000089 RID: 137
        Ldarga,
        // Token: 0x0400008A RID: 138
        Br,
        // Token: 0x0400008B RID: 139
        Conv_I1,
        // Token: 0x0400008C RID: 140
        Ldelem_I2,
        // Token: 0x0400008D RID: 141
        Arglist,
        // Token: 0x0400008E RID: 142
        Conv_Ovf_U4,
        // Token: 0x0400008F RID: 143
        Ceq,
        // Token: 0x04000090 RID: 144
        And,
        // Token: 0x04000091 RID: 145
        Stfld,
        // Token: 0x04000092 RID: 146
        Conv_R8,
        // Token: 0x04000093 RID: 147
        Stind_I4,
        // Token: 0x04000094 RID: 148
        Refanyval,
        // Token: 0x04000095 RID: 149
        Ldelem_I,
        // Token: 0x04000096 RID: 150
        Tail,
        // Token: 0x04000097 RID: 151
        Blt_Un,
        // Token: 0x04000098 RID: 152
        Rethrow,
        // Token: 0x04000099 RID: 153
        Call,
        // Token: 0x0400009A RID: 154
        Jmp,
        // Token: 0x0400009B RID: 155
        Conv_U4,
        // Token: 0x0400009C RID: 156
        Shr_Un,
        // Token: 0x0400009D RID: 157
        Stelem_I1,
        // Token: 0x0400009E RID: 158
        Stelem_I4,
        // Token: 0x0400009F RID: 159
        Ldsfld,
        // Token: 0x040000A0 RID: 160
        Conv_Ovf_U2_Un,
        // Token: 0x040000A1 RID: 161
        Mul_Ovf,
        // Token: 0x040000A2 RID: 162
        Ldc_I4,
        // Token: 0x040000A3 RID: 163
        Ldind_I,
        // Token: 0x040000A4 RID: 164
        Ldflda,
        // Token: 0x040000A5 RID: 165
        Ret,
        // Token: 0x040000A6 RID: 166
        Nop,
        // Token: 0x040000A7 RID: 167
        Conv_I,
        // Token: 0x040000A8 RID: 168
        Neg,
        // Token: 0x040000A9 RID: 169
        Conv_Ovf_I1_Un,
        // Token: 0x040000AA RID: 170
        Clt,
        // Token: 0x040000AB RID: 171
        Conv_U2,
        // Token: 0x040000AC RID: 172
        Bne_Un,
        // Token: 0x040000AD RID: 173
        Switch,
        // Token: 0x040000AE RID: 174
        Isinst,
        // Token: 0x040000AF RID: 175
        Ldftn,
        // Token: 0x040000B0 RID: 176
        Conv_Ovf_U_Un,
        // Token: 0x040000B1 RID: 177
        Rem,
        // Token: 0x040000B2 RID: 178
        Ldind_I4,
        // Token: 0x040000B3 RID: 179
        Xor,
        // Token: 0x040000B4 RID: 180
        Add_Ovf_Un,
        // Token: 0x040000B5 RID: 181
        Or
    }
}
IFix.Core.Code
using System;

namespace IFix.Core
{
    // Token: 0x02000003 RID: 3
    public struct Instruction
    {
        // Token: 0x040000B6 RID: 182
        public const ulong INSTRUCTION_FORMAT_MAGIC = 5158825760788742785UL;

        // Token: 0x040000B7 RID: 183
        public Code Code;

        // Token: 0x040000B8 RID: 184
        public int Operand;
    }
}
IFix.Core.Instruction
using System;

namespace IFix.Core
{
    // Token: 0x02000004 RID: 4
    public enum ExceptionHandlerType
    {
        // Token: 0x040000BA RID: 186
        Catch,
        // Token: 0x040000BB RID: 187
        Filter,
        // Token: 0x040000BC RID: 188
        Finally,
        // Token: 0x040000BD RID: 189
        Fault = 4
    }
}
ExceptionHandlerType
using System;

namespace IFix.Core
{
    // Token: 0x02000005 RID: 5
    public sealed class ExceptionHandler
    {
        // Token: 0x06000001 RID: 1 RVA: 0x000020EC File Offset: 0x000002EC
        public ExceptionHandler()
        {
        }

        // Token: 0x040000BE RID: 190
        public Type CatchType;

        // Token: 0x040000BF RID: 191
        public int CatchTypeId;

        // Token: 0x040000C0 RID: 192
        public int HandlerEnd;

        // Token: 0x040000C1 RID: 193
        public int HandlerStart;

        // Token: 0x040000C2 RID: 194
        public ExceptionHandlerType HandlerType;

        // Token: 0x040000C3 RID: 195
        public int TryEnd;

        // Token: 0x040000C4 RID: 196
        public int TryStart;
    }
}
ExceptionHandler

參考

如何保證多次生成Instruction.cs內容一致 

 

 

 

 

 

各種Issue

  Close

和ILRunTime有什么區別呢?以及性能比較?

多個 Assembly Definition 的template file 怎么設置?

如何卸載補丁

添加配置文件,添加python構建腳本用於跨平台構建,添加混淆key支持

異步匿名函數不支持嗎?

對於已經注入的工程,如何取消注入呢?

fix后生成2個補丁文件

Warning: read ./Library/ScriptAssemblies/Assembly-CSharp.dll with symbol fail

執行"InjectFix/Fix"后提示please install the ToolKit

修改源碼導出新的dll后,xcode工程導出報錯,像是IL2CPP轉方法報錯了 IFix.Core.EvaluationStackOperation::ToObject

可以使用ILRuntime+injectfix方式嗎

編輯器下除了reimport unity工程,有沒有更好的方法回滾Inject了之后的dll

Unhandled Exception:System.Exception: Utils/<ReadBinaryFileAsync>d__0 is CompilerGenerated

帶out泛型參數的方法Patch不生效

在patch的函數中調用父類的函數會導致無限循環

The type or namespace name `IFix' could not be found

和xlua測試用例的比較

修改文本編碼,避免在其他平台顯示亂碼問題

Exception: instruction magic not match

IFix報錯日志,缺少源碼行信息,不方便排查問題

【優化IFix報錯日志】使用debug模式運行ifix.exe,報錯日志里包含源碼文件和行信息,方便查問題

求增加一個Inject和Fix時的UI效果!提醒用戶正在Inject或者Fix中!

項目在Unity可熱修復,在apk包中無法熱修復

【實現建議】不用IDMAP,只使用IDTagAttribute。

配置注入所有types,但是注入報錯!

熱更成功,但有個方法Patch會報錯

熱更成功,Debug信息正常,但是 Text 賦值失敗

【實用建議】為方法分配id,能否根據方法簽名生成唯一id

 

IFix.IDMAP問題求助

 

子類重寫時先執行帶泛型的方法會出錯

Inject引起Unity崩潰

Error: the new assembly must not be inject, please reimport the project!

當使用 .net4.x async await來進行異步編程時,inject 階段報異常

Enum的Equals方法

請問如何對預生成的dll進行注入

支持其他程序集的注入么?

支持代碼混淆之后打補丁嗎

> 我也碰到了類似的問題,最簡化代碼如下,當注入class A的時候將會報錯

引入第三方工具引發的一個編譯問題

Unity2019.2.15f1版本打包出來會出現未注入的情況

Unity2019.3.0f3 沒有Editor\Data\Mono\bin\gmcs

[Change] 

找不到IFix.Core.dll了

UnityEditor熱更沒問題,打包到Android后Load報錯

打包il2cpp的時候報錯

【BugReport】結構體初始化如果不使用new關鍵字,會報錯

虛函數中如果用關鍵詞in修飾struct類型的參數,inject后執行會報錯

注入方法過多時,ios在armv7結構的鏈接過程會報錯

補丁中調用Enum.Parse報錯

Fix 和 inject 時彈出 warnning ,並且在Editor下沒有看到效果

當hotfix的代碼導致游戲崩潰,幾乎無法查找明確的堆棧入口信息或者明確的方法信息

最新版本無法生成IFix.Core.dll和IFix.exe

命名空間下的方法fix報錯

在編輯器模式下初始化Inject報錯因為我使用了linq配置

foreach遍歷包含枚舉的容器會報錯

支持IL2CPP模式下打包的Android和ios包熱更嗎

子類沒有override父類的函數,打Interpret標簽不會生效

[求助]遇到一個問題

編譯報錯

2019.3安卓版本注入失敗

2019.3.3f1找不到gmcs

IEnumerator<T>的Current在解釋執行下報錯

打包資源和打包apk對於Inject的操作問題

Invoke不支持嗎?新方法調用新方法問題

[fixbug] CustomBridge 注入跨dll的delegate,InjectFix 時報錯

Unity2019 iOS注入失敗,Unity2018 iOS注入成功

兼容2017 沒有ISubsystem 添加新增類配置

驗證新增類的類名是否存在 

編輯器下體驗熱補丁,報錯,不知道哪一步出的問題

CustomBridge屬性可以做到自動給程序集的所有Delegate和Interface加上Wrapper嗎?

請教 Non-static method requires a target 錯誤

執行hotfix報錯

  Open

如果一個函數內有new int[]{1,2,3}類操作,會報Warning: not support il[IL_0008: ldtoken <PrivateImplementationDetails>/

針對不同平台進行Fix時報錯

多次打patch的問題

Unity 使用ILTocpp方式出現問題

自己生成的Dll在手機上fix有問題

子類方法里調用父類報錯

為什么說:InjectFix在對Unity協程,閉包的支持中其實是包含了對新增class的支持?

inject失敗彈Warning

是否支持c#匿名函數內的邏輯修改

!UNITY_EDITOR包含類或方法,無法生成patch

無法訪問Unity的 Debug.unityLogger.logEnabled 屬性

TargetException: Non-static method requires a target

使用了BurstCompile的類和結構體不能進行注入,否則加載patch之后會報burst的錯誤

只能在windows下使用嗎?mac環境怎么編譯呢

何時會開放新增類功能?

熱更新后log問題

demo里的新增類必然報錯,版本是2017

async Task 不支持嗎?

2017.4 真機 cound not load type

2019.3.8再編譯build_for_unity.bat時找不到gmcs目錄

DateTime.Now.AddSeconds打補丁失敗

Entities.ForEach 里的ref類修復報錯

希望盡快支持async await特性

 

IFix.Interpret新類內不能用到typeof

無法Patch返回協程衍生類的函數

關於對IFix實踐后的一些問題請教

按下標取struct數組解釋執行報錯

請教下GetTagMethods與GetTagClasses中assembly.CodeBase.IndexOf("ScriptAssemblies") != -1的用意。

//case Code.Stelem_Any: //0.03166702% 泛型中使用?泛型不支持解析,所以不會碰到這指令(我遇到了這個指令沒被實現的異常)

支持繼承時重寫object的虛函數

增加方法沒參數的情況會拋異常Exception: can not load field[*]

 

 

 

 

 

 

雜項

  對程序集里的所有方法Inject

// 1. 配置類必須打[Configure]標簽
// 2. 必須放Editor目錄
[Configure]
public class HelloworldCfg {
    [IFix]
    static IEnumerable<Type> hotfix {
        get {
            return (from type in Assembly.Load("Assembly-CSharp").GetTypes()
                    select type);
        }
    }
}

  [Patch](補丁修改方法)標簽,Inject前后DLL對比

為每個方法生成一個枚舉ID

 

 

 

2021.6.3 更新

現在已經支持新增字段

 

 

相關文章

 

https://m.ithome.com/html/444969.htm

https://www.zhihu.com/question/345639690/answer/825301379

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM