InjectFix实现原理

InjectFix实现bug修复主要靠这两部分:虚拟机负责新逻辑的解析执行;注入代码负责把调用重定向到虚拟机;下面我们结合最简单的例子介绍下这两部分。

虚拟机

关键部分用几行伪码就可以描述清楚:

导读

  • pc指向的是函数的第一条指令;

  • argumentBase指向的是第一个参数;

  • while+switch一条条指令往下执行,具体指令的操作在case那;

argumentBase指向的是求值栈该函数的栈帧,栈帧是这么安排的:

先放参数(如果有的话),再放本地变量(如果有的话),接着是临时区域,当函数返回时弹掉所有东西,如果有返回值就放到栈顶(函数执行前参数0的位置)。

用如下一个静态方法来演示下虚拟机怎么运行:

public static float Add(float a, float b)
{   return a - b;}

这函数编译后是这四条指令

Add函数的执行过程

指令1把参数0 Push到栈顶;

指令2把参数1 Push到栈顶;

指令3把两个栈顶元素弹出(Pop)并相加,结果Push到栈顶;

指令4把栈顶拷贝到参数0的位置,清理栈,退出循环,Execute函数执行结束。

代码注入

上面的Add函数注入后是这样的

public static float Add(float a, float b)
{
    if (WrappersManagerImpl.IsPatched(92))
    {
        return WrappersManagerImpl.GetPatch(92).__Gen_Wrap_25(a, b);
    }
    return a - b;
}

比较简单,发现这函数有patch的话,就重定向到虚拟机。

而__Gen_Wrap_25是个适配器函数,赋值把参数压栈,调用虚拟机的Execute函数,并把结果返回。__Gen_Wrap_25的实现如下:

public float __Gen_Wrap_25(float P0, float P1)
{
    Call call = Call.Begin();
    call.PushSingle(P0);
    call.PushSingle(P1);
    this.virtualMachine.Execute(this.methodId, ref call, 2, 0);
    return call.GetSingle(0);
}

PS:我们的例子仅有三种指令,和这几条指令无关的代码全部简化了,真正复杂得多,有兴趣可以看源码了解。

总结

InjectFix使用简单,小巧,合规且安全。即使你不打算用它来更新线上版本,只要你程序有原生部分,接入也能一定程度上提高开发效率,没什么拒绝它的理由,是吧?

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kerven_HKW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值