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

 

posted on 2020-05-29 10:23  void87  阅读(4081)  评论(0编辑  收藏  举报

导航