Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/sys/windows: call 32bit dll in 64bit windows panic when pass float64(double) parameter #29092

Closed
winxxp opened this issue Dec 4, 2018 · 4 comments

Comments

@winxxp
Copy link

@winxxp winxxp commented Dec 4, 2018

What version of Go are you using (go version)?

$ go version
go version go1.11.2 windows/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
set GOARCH=386
set GOBIN=
set GOCACHE=C:\Users\1\AppData\Local\go-build
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=D:\Golib
set GOPROXY=
set GORACE=
set GOROOT=D:\Go
set GOTMPDIR=
set GOTOOLDIR=D:\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set GO386=sse2
set CC=gcc
set CXX=g++
set CGO_ENABLED=0
set GOMOD=E:\workspace\998-source\gowork\src\github.com\go.mod
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m32 -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=T:\Temp\go-build953563306=/tmp/go-build -gno-record-gcc-switches

What did you do?

https://play.golang.org/p/roPsAJFuQpU

What did you expect to see?

f32: 3f800000, f64: 3ff0000000000000
out = 1

What did you see instead?

In Windows DebugView: [20868] f32 3f800000, f64:1105008000000000

Output
GOROOT=D:\Go #gosetup
GOPATH=D:\Golib #gosetup
D:\Go\bin\go.exe build -o T:\Temp\___go_build_m_go.exe E:/workspace/998-source/gowork/src/github.com/winxxp/dll/ex/m.go #gosetup
"D:\Program Files\JetBrains\IntelliJ IDEA 2018.3\bin\runnerw64.exe" T:\Temp\___go_build_m_go.exe #gosetup
f32: 3f800000, f64: 3ff0000000000000
Exception 0xc0000005 0x1 0x446b0e 0x8213e7
PC=0x8213e7

syscall.Syscall(0x821320, 0x3, 0x3f800000, 0x0, 0x11050080, 0x0, 0x0, 0x0)
D:/Go/src/runtime/syscall_windows.go:172 +0xcf
golang.org/x/sys/windows.(*Proc).Call(0x1104e120, 0x110500c0, 0x3, 0x3, 0x10, 0x494040, 0x1, 0x110500c0)
D:/Golib/pkg/mod/golang.org/x/sys@v0.0.0-20180830151530-49385e6e1522/windows/dll_windows.go:135 +0x21e
golang.org/x/sys/windows.(*LazyProc).Call(0x110754a0, 0x110500c0, 0x3, 0x3, 0x2, 0x25, 0x0, 0x0)
D:/Golib/pkg/mod/golang.org/x/sys@v0.0.0-20180830151530-49385e6e1522/windows/dll_windows.go:309 +0x48
main.main()
E:/workspace/998-source/gowork/src/github.com/winxxp/dll/ex/m.go:22 +0x192
eax 0x1
ebx 0x535994
ecx 0xc5327b32
edx 0x0
edi 0x446b0e
esi 0x76cb5a30
ebp 0x19fea8
esp 0x19fd40
eip 0x8213e7
eflags 0x10246
cs 0x23
fs 0x53
gs 0x2b

Process finished with exit code 2

@tklauser tklauser changed the title call 32bit dll in 64bit windows panic when pass float64(double) parameter x/sys/windows: call 32bit dll in 64bit windows panic when pass float64(double) parameter Dec 4, 2018
@gopherbot gopherbot added this to the Unreleased milestone Dec 4, 2018
@tklauser tklauser added the OS-Windows label Dec 4, 2018
@tklauser
Copy link
Member

@tklauser tklauser commented Dec 4, 2018

@alexbrainman
Copy link
Member

@alexbrainman alexbrainman commented Dec 5, 2018

@winxxp

When you call any function, your arguments must match function parameters. I think, some of yours do not match.

From https://play.golang.org/p/roPsAJFuQpU

C has

DllExport int DllFunc(float f32, double f64, float* f32out)

and Go passes

r1, _, err := dllFunc.Call(
uintptr(f32),
uintptr(f64),
uintptr(unsafe.Pointer(&out)),
)

First C f32 parameter looks OK, because (according to https://docs.microsoft.com/en-us/previous-versions/cc953fe1(v=vs.140) ) C float expects 4 bytes, and you pass uintptr (4 bytes). So match here.

But C f64 takes 8 bytes, while Go parameter is uintptr (4 bytes). This is not allowed. I think you want to split Go f64 into 2 uintptr values (upper and lower 4 bytes), and pass them to dllFunc.Call as separate parameters.

I did not look passed C f64, but similar logic would apply.

I do not have Visual C to build your DLL, and you did not provide the DLL source, so I cannot verify my theory. But I don't think there is anything to fix here - this is all working as expected. Let me know, if I am wrong.

Thank you.

Alex

@alexbrainman
Copy link
Member

@alexbrainman alexbrainman commented Dec 5, 2018

There is TestFloatArgs in runtime package, if anyone wants to play with this.

Alex

@winxxp
Copy link
Author

@winxxp winxxp commented Dec 5, 2018

@alexbrainman

  1. change to call 64bit dll, passed
  2. double split into 2 uint32, passed (https://play.golang.org/p/mfsa_RzDRpz)
@winxxp winxxp closed this Dec 10, 2018
@golang golang locked and limited conversation to collaborators Dec 10, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants
You can’t perform that action at this time.