diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index a6dc87b..5bb21b9 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -1,42 +1,18 @@ name: Go on: [pull_request] jobs: - test-linux: - name: Test on Linux - runs-on: ubuntu-latest + test: + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + version: [1.18, 1.19, "1.20", 1.21] + runs-on: ${{ matrix.os }} steps: - - name: Set up Go 1.18 - uses: actions/setup-go@v1 - with: - go-version: 1.18 - id: go - - name: Check out code into the Go module directory - uses: actions/checkout@v1 - - name: Test - run: go test -gcflags=-l - test-macos: - name: Test on Mac - runs-on: macos-latest - steps: - - name: Set up Go 1.18 - uses: actions/setup-go@v1 - with: - go-version: 1.18 - id: go - - name: Check out code into the Go module directory - uses: actions/checkout@v1 - - name: Test - run: go test -gcflags=-l - test-windows: - name: Test on Windows - runs-on: windows-latest - steps: - - name: Set up Go 1.18 - uses: actions/setup-go@v1 - with: - go-version: 1.18 - id: go - - name: Check out code into the Go module directory - uses: actions/checkout@v1 - - name: Test - run: go test -gcflags=-l + - name: Set up Go ${{ matrix.version }} + uses: actions/setup-go@v1 + with: + go-version: ${{ matrix.version }} + - name: Check out code into the Go module directory + uses: actions/checkout@v1 + - name: Test + run: go test -gcflags='all=-N -l' diff --git a/README.md b/README.md index a8724e5..f033834 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,6 @@ Go 语言猴子补丁(monkey patching)框架。 Bouke 已经不再维护原项目,所以只能开一个新项目了🤣。 -有兴趣的同学也可以加微信 `taoshu-in` 讨论,拉你进群。 - ## 快速入门 首先,引入 monkey 包 @@ -62,7 +60,9 @@ func main() { ## 注意事项 -1. Monkey 需要关闭 Go 语言的内联优化才能生效,比如测试的时候需要:`go test -gcflags=all=-l`。 +1. Monkey 需要关闭 Go 语言的内联优化才能生效,比如测试的时候需要:`go test -gcflags='all=-N -l'`。 2. Monkey 需要在运行的时候修改内存代码段,因而无法在一些对安全性要求比较高的系统上工作。 3. Monkey 不应该用于生产系统,但用来 mock 测试代码还是没有问题的。 -4. Monkey 目前仅支持 amd64 指令架构,支持 linux/macos/windows 平台。 +4. Monkey 目前仅支持 amd64 指令架构,支持 linux/macos/~~windows~~[^win] 平台。 + +[^win]: 目前在 Win 平台下 Go 1.20 版本之后会报错。欢迎熟悉 Win 平台的同学提供 PR。问题解决之前建议 Win 用户使用 WSL。 diff --git a/go.sum b/go.sum index db5cb5f..75a53c4 100644 --- a/go.sum +++ b/go.sum @@ -3,4 +3,3 @@ github.com/huandu/go-tls v1.0.1/go.mod h1:WeItecBdaIdUBRb7cSMMk+rq41iFKhf6Q9mDRD golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1 h1:MwxAfiDvuwX8Nnnc6iRDhzyMyyc2tz5tYyCP/pZcPCg= golang.org/x/arch v0.0.0-20210901143047-ebb09ed340f1/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/monkey_amd64.go b/monkey_amd64.go index 66efaf3..c5511d0 100644 --- a/monkey_amd64.go +++ b/monkey_amd64.go @@ -1,6 +1,9 @@ package monkey import ( + "runtime" + "strings" + "golang.org/x/arch/x86/x86asm" ) @@ -95,13 +98,12 @@ func getFirstCallFunc(from uintptr) uintptr { f := rawMemoryAccess(from, 1024) s := 0 - var lastLea x86asm.Inst for { i, err := x86asm.Decode(f[s:], 64) if err != nil { panic(err) } - if i.Op == x86asm.CALL && lastLea.Args[0].(x86asm.Reg) == x86asm.RAX { + if i.Op == x86asm.CALL { arg := i.Args[0] imm := arg.(x86asm.Rel) next := from + uintptr(s+i.Len) @@ -111,15 +113,15 @@ func getFirstCallFunc(from uintptr) uintptr { } else { to = next - uintptr(-imm) } - return to + f := runtime.FuncForPC(to) + // 泛型函数的名字中包含 [...] + if strings.Index(f.Name(), "[") > 0 { + return to + } } s += i.Len if s >= 1024 { panic("Can not find CALL instruction") } - // 有些情况下会生成 NOPW 指令,需要跳过 - if i.Op == x86asm.LEA { - lastLea = i - } } }