go-kiss / monkey

Go语言猴子补丁框架
https://taoshu.in/go/monkey/
MIT License
119 stars 18 forks source link

支持 go1.20 下泛型打桩 #14

Closed taoso closed 11 months ago

taoso commented 11 months ago

Go 调用泛型函数时会先执行 LEA 指令,再执行 CALL 指令。我在上次提交

1f9d72d787e9444e1c249acee84a2b31b5c10485

中基于此特点跳过了跟 struct 传值产生的 CALL 指令,修复了 struct 传值导致 泛型打桩卡住的问题。

判断的依据是看 CALL 指令前面是否还有 LEA 指令且第一个参数为 RAX。

根据 Ruomenger 的调查,Go1.20 在执行 LEA 指令时,其目的寄存器由 RAX 改为 RBX,从而导致泛型 mock 出错。我还没找到对应的改动以及改动的原因。

Ruomenger 提议在检查 LEA 指令时同时支持 RAX 和 RBX 两种情况。但我认为 这样做不能根除问题,以后 Go 编译器改版可能还会引出新问题。

经过一番研究,我感觉使用函数名来判断可能是一个比较稳定的的办法。 getFirstCallFunc 最终找到泛型底层函数的地址。该地址对应的函数名包含[...]

github.com/go-kiss/monkey_test.add2[...]
github.com/go-kiss/monkey/demo.Add[...]
github.com/go-kiss/monkey_test.(*S2__monkey__[...]).Foo
github.com/go-kiss/monkey/demo.(*S2[...]).Foo

以此为基准来确定函数指针应该没问题。而且 Go 语言提供 runtime.FuncForPC 非常方便。

Fix #12

Ruomenger commented 11 months ago

另外有个小提议,用不同的go版本如1.18、1.19、1.20、1.21进行测试,这样如果有哪个版本下的代码有问题也能及时发现

taoso commented 11 months ago

另外有个小提议,用不同的go版本如1.18、1.19、1.20、1.21进行测试,这样如果有哪个版本下的代码有问题也能及时发现

@Ruomenger 这个没问题。不过最近愚到了另一个困难。monkey 在 go1.20 之后的 win 平台上无法正常运行。我对 win 平台不熟,也没有 win 环境。之前还是 @kkbblzq 出手解决了 win 平台的兼容问题 https://github.com/go-kiss/monkey/pull/3

这次是不是考虑不再支持 win 平台了?可以引导 win 用户使用 wsl 😭

Ruomenger commented 11 months ago

另外有个小提议,用不同的go版本如1.18、1.19、1.20、1.21进行测试,这样如果有哪个版本下的代码有问题也能及时发现

@Ruomenger 这个没问题。不过最近愚到了另一个困难。monkey 在 go1.20 之后的 win 平台上无法正常运行。我对 win 平台不熟,也没有 win 环境。之前还是 @kkbblzq 出手解决了 win 平台的兼容问题 #3

这次是不是考虑不再支持 win 平台了?可以引导 win 用户使用 wsl 😭

我是有windows平台(虽然平常写代码是在wsl2里),这个问题我可以先看下,看是否能解决(如果可以后续再提PR解决)。

感觉目前可以先合并把windows平台下的问题标明在README里,大部分人应该还是在linuxmacos下使用的。