Skip to content

Error when calling go DLL from go using cgo #36157

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

Closed
DaLynX opened this issue Dec 16, 2019 · 1 comment
Closed

Error when calling go DLL from go using cgo #36157

DaLynX opened this issue Dec 16, 2019 · 1 comment

Comments

@DaLynX
Copy link

DaLynX commented Dec 16, 2019

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

$ go version
go version go1.13.5 windows/amd64

Does this issue reproduce with the latest release?

I believe it is the latest release, so yes.

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

go env Output
$ go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\xxx\AppData\Local\go-build
set GOENV=C:\Users\xxx\AppData\Roaming\go\env
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\xxx\Documents\B - Dev\Go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Users\xxx\scoop\apps\go\current
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=C:\Users\xxx\scoop\apps\go\current\pkg\tool\windows_amd64
set GCCGO=gccgo
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=
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=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\xxx\AppData\Local\Temp\go-build988957846=/tmp/go-build -gno-record-gcc-switches

What did you do?

I am trying to call a DLL made with go from another program in go.

DLL code

package main

import "fmt"
import "C"
import "unsafe"
import "syscall"

// MessageBox of Win32 API.
func MessageBox(hwnd uintptr, caption, title string, flags uint) int {
	ret, _, _ := syscall.NewLazyDLL("user32.dll").NewProc("MessageBoxW").Call(
		uintptr(hwnd),
		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(caption))),
		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(title))),
		uintptr(flags))

	return int(ret)
}

// MessageBoxPlain of Win32 API.
func MessageBoxPlain(title, caption string) int {
	const (
		NULL  = 0
		MB_OK = 0
	)
	return MessageBox(NULL, caption, title, MB_OK)
}

//export hello
func hello () {
	MessageBoxPlain("Hello", "Hello world!")
}

func main() {
	fmt.Println("main: Hello world!")
	hello()
}

Caller code

package main

// #include <Windows.h>
//
// typedef void (*pfunc)();
//
// void callfunc(pfunc pf)
// {
//		pf();
// }
import "C"
import "fmt"
import "os"

func main() {
	var hModule C.HINSTANCE
	var hProc C.FARPROC
	var dllname, procname string
	var cDLLName, cProcName *C.char

	dllname = os.Args[1]
	procname = os.Args[2]

	fmt.Println("[i] DLL file to be loaded:", dllname)
	cDLLName = C.CString(dllname)
	hModule = C.LoadLibrary(cDLLName)
	if hModule == nil {
		fmt.Println("[!] Error loading library.")
		return
	}
	fmt.Println("[i] Got hModule:", fmt.Sprintf("%p", hModule))

	fmt.Println("[i] Procedure to be called:", procname)
	cProcName = C.CString(procname)
	hProc = C.GetProcAddress(hModule, cProcName)
	if hProc == nil {
		fmt.Println("[!] Error finding procedure:", procname)
		return
	}
	fmt.Println("[i] Got procedure", procname, "at address:", fmt.Sprintf("%p", hProc))

	fmt.Printf("[i] Calling %s:\n>\t", procname)
	C.callfunc(hProc)
	fmt.Println("[i] Done.")

}

What did you expect to see?

I expected to see the following output in the console, and the Hello World dialog.

C:\Users\xxx\Documents\B - Dev\Go\bin>goCaller.exe hello.dll hello
[i] DLL file to be loaded: hello.dll
[i] Got hModule: 0x62400000
[i] Procedure to be called: hello
[i] Got procedure hello at address: 0x6249cb90
[i] Calling hello:
>       [i] Done.

What did you see instead?

I get the following output:

C:\Users\xxx\Documents\B - Dev\Go\bin>goCaller.exe hello.dll hello
[i] DLL file to be loaded: hello.dll
[i] Got hModule: 0x62400000
[i] Procedure to be called: hello
[i] Got procedure hello at address: 0x6249cb90
[i] Calling hello:
>       fatal error: unexpected signal during runtime execution
[signal 0xc0000005 code=0x1 addr=0x0 pc=0x62456d38]

goroutine 1 [running, locked to thread]:
runtime.throw(0x624f0d48, 0x2a)
        C:/Users/xxx/scoop/apps/go/current/src/runtime/panic.go:774 +0x79 fp=0xc0000898d8 sp=0xc0000898a8 pc=0x6242d469
runtime.sigpanic()
        C:/Users/xxx/scoop/apps/go/current/src/runtime/signal_windows.go:227 +0x25a fp=0xc000089908 sp=0xc0000898d8 pc=0x6243de6a
runtime.memmove(0x0, 0xc0000044e0, 0x1)
        C:/Users/xxx/scoop/apps/go/current/src/runtime/memmove_amd64.s:146 +0x108 fp=0xc000089910 sp=0xc000089908 pc=0x62456d38
runtime.heapBitsSetType(0xc0000044e0, 0x20, 0x20, 0x624d7ae0)
        C:/Users/xxx/scoop/apps/go/current/src/runtime/mbitmap.go:1400 +0x4bb fp=0xc000089a18 sp=0xc000089910 pc=0x62413d4b
runtime.mallocgc(0x20, 0x624d7ae0, 0x1, 0x0)
        C:/Users/xxx/scoop/apps/go/current/src/runtime/malloc.go:1052 +0x57d fp=0xc000089ab8 sp=0xc000089a18 pc=0x6240becd
runtime.newobject(0x624d7ae0, 0x0)
        C:/Users/xxx/scoop/apps/go/current/src/runtime/malloc.go:1151 +0x3f fp=0xc000089ae8 sp=0xc000089ab8 pc=0x6240c53f
syscall.NewLazyDLL(...)
        C:/Users/xxx/scoop/apps/go/current/src/syscall/dll_windows.go:269
main.MessageBox(0x0, 0x624ea697, 0xc, 0x624e9723, 0x5, 0x0, 0x0)
        C:/Users/xxx/Documents/B - Dev/Go/src/hello/main.go:10 +0x38 fp=0xc000089b58 sp=0xc000089ae8 pc=0x6249c938
main.MessageBoxPlain(...)
        C:/Users/xxx/Documents/B - Dev/Go/src/hello/main.go:25
main.hello(...)
        C:/Users/xxx/Documents/B - Dev/Go/src/hello/main.go:30
main._cgoexpwrap_d3a9d25dfce7_hello()
        _cgo_gotypes.go:45 +0x65 fp=0xc000089ba0 sp=0xc000089b58 pc=0x6249c8e5
runtime.call32(0x0, 0x93fc00, 0x93fd7f, 0x0)
        C:/Users/xxx/scoop/apps/go/current/src/runtime/asm_amd64.s:539 +0x42 fp=0xc000089bd0 sp=0xc000089ba0 pc=0x62453c72
runtime.cgocallbackg1(0x0)
        C:/Users/xxx/scoop/apps/go/current/src/runtime/cgocall.go:314 +0x1c5 fp=0xc000089cb8 sp=0xc000089bd0 pc=0x62403ff5
runtime.cgocallbackg(0x0)
        C:/Users/xxx/scoop/apps/go/current/src/runtime/cgocall.go:191 +0xd5 fp=0xc000089d28 sp=0xc000089cb8 pc=0x62403d75
runtime: unexpected return pc for runtime.cgocallback_gofunc called from 0x454f57
stack: frame={sp:0xc000089d28, fp:0xc000089d48} stack=[0xc000082000,0xc00008a000)
000000c000089c28:  0000000000000000  0000000000000008
000000c000089c38:  000000c000089bd0  0000000062403fa3 <runtime.cgocallbackg1+371>
000000c000089c48:  00000000624f27a8  0000000000000000
000000c000089c58:  000000c000089f90  000000c000089c17
000000c000089c68:  0000000000000000  0000000000000000
000000c000089c78:  000000c000089ca8  00000000624361d3 <runtime.exitsyscall+435>
000000c000089c88:  000000c000036000  0000000200000003
000000c000089c98:  000000c000036000  000000c000036000
000000c000089ca8:  000000c000089d18  0000000062403d75 <runtime.cgocallbackg+213>
000000c000089cb8:  0000000000000000  0000000000000000
000000c000089cc8:  000000c00000a280  0000000000403e15
000000c000089cd8:  00007ffcac342900  0000000000000005
000000c000089ce8:  000000c0000896b8  0000000000000001
000000c000089cf8:  0000000000000000  0000000000000000
000000c000089d08:  000000c000089d50  000000c000036000
000000c000089d18:  000000000093fbc0  00000000624552d2 <runtime.cgocallback_gofunc+178>
000000c000089d28: <0000000000000000  0000000000582560
000000c000089d38:  000000c000089d50 !0000000000454f57
000000c000089d48: >0000000000403e39  000000000049d9b0
000000c000089d58:  000000c000089db8  0000000000000015
000000c000089d68:  0000000000000040  0000000000582560
000000c000089d78:  000000c000089da8  000000000049ceb8
000000c000089d88:  000000000049d9b0  000000c000089db8
000000c000089d98:  000000c00005e820  000000c000089db8
000000c000089da8:  000000c000089f50  000000000049d4aa
000000c000089db8:  000000006249cb90  000000c000006018
000000c000089dc8:  00000000004ecf8c  0000000000000012
000000c000089dd8:  000000c000089e80  0000000000000001
000000c000089de8:  0000000000000001  0000000000000015
000000c000089df8:  0000000000000000  0000000000000000
000000c000089e08:  0000000000000005  0000000000000009
000000c000089e18:  000000000000000a  000000c0000100f0
000000c000089e28:  000000006249cb90  0000000062400000
000000c000089e38:  000000c0000100e0  000000c000040220
runtime.cgocallback_gofunc(0x403e39, 0x49d9b0, 0xc000089db8, 0x15)
        C:/Users/xxx/scoop/apps/go/current/src/runtime/asm_amd64.s:793 +0xb2 fp=0xc000089d48 sp=0xc000089d28 pc=0x624552d2

goroutine 1 [runnable, locked to thread]:
syscall.getSystemDirectory(0x1c000064000, 0x104, 0x104, 0x1c000064000, 0x6246b30b)
        C:/Users/xxx/scoop/apps/go/current/src/syscall/zsyscall_windows.go:1921 +0xf6
syscall.init.0()
        C:/Users/xxx/scoop/apps/go/current/src/syscall/dll_windows.go:48 +0x73

It gets weirder!

If I replace the cgo code in the caller by the following, it works:

// #include <Windows.h>
//
// typedef void (*pfunc)();
//
// void callfunc(pfunc pf)
// {
//		MessageBox(0, "Calling...", "goCaller", 0);
//		pf();
// }
import "C"
@DaLynX
Copy link
Author

DaLynX commented Dec 16, 2019

Found it this has already been opened for more than 2 years: #22192

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants