ebitengine / purego

Apache License 2.0
1.94k stars 63 forks source link

Dynamic linking error on amd64 #254

Closed zoncoen closed 2 weeks ago

zoncoen commented 3 weeks ago

PureGo Version

v0.7.1

Operating System

Go Version (go version)

go version go1.22.4 linux/amd64

What steps will reproduce the problem?

Build the following code with -buildmode=plugin option. (ref. https://pkg.go.dev/plugin)

package main

import _ "github.com/ebitengine/purego"

func main() {}

purego@v0.5.1 succeeds building, but purego@v0.6.1 and purego@v0.7.1 raise the error.

The complete reproduction code is here. sample error log

What is the expected result?

go build -buildmode=plugin -o plugin.so . succeeds without error.

What happens instead?

# github.com/ebitengine/purego
asm: sys_amd64.s:134: when dynamic linking, R15 is clobbered by a global variable access and is used here: 000[8](https://github.com/zoncoen-sample/purego-plugin-issue/actions/runs/9460766406/job/26060171519#step:4:9)6 (/home/runner/go/pkg/mod/github.com/ebitengine/purego@v0.7.1/sys_amd64.s:134)    MOVQ    R15, 32(SP)
asm: assembly failed

Anything else you feel useful to add?

No response

TotallyGamerJet commented 3 weeks ago

Thanks for reporting! When I get some time I'll look into this.

TotallyGamerJet commented 2 weeks ago

Just quickly looked into it and was able to reproduce on M1 by setting GOARCH=amd64. Haven't found a cause yet

TotallyGamerJet commented 2 weeks ago

So, R15 is a scratch register normally but is the GOT register in when linking dynamically see Go ABI. The issue that introduced this change is here: https://github.com/golang/go/issues/43661

The fix is to save the R15 register before we access any global which clobber the R15 register

zoncoen commented 2 weeks ago

Thank you for your quick support! It works for our case with replace directive. 👍