golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
122.71k stars 17.5k forks source link

runtime: darwin using -buildmode=c-shared so got runtime: unexpected return pc for runtime.sigpanic called from 0x41e745a #40131

Open wangzz719 opened 4 years ago

wangzz719 commented 4 years ago

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

$ go version
go version go1.14.4 darwin/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
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/wangzhizhao/Library/Caches/go-build"
GOENV="/Users/wangzhizhao/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GONOPROXY="*.byted.org,*.everphoto.cn"
GONOSUMDB="*.byted.org,*.everphoto.cn"
GOOS="darwin"
GOPATH="/Users/wangzhizhao/go"
GOPRIVATE="*.byted.org,*.everphoto.cn"
GOPROXY="https://go-mod-proxy.byted.org,https://goproxy.cn,https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.google.cn"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/wangzhizhao/go/src/goscripts/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/c5/gc9h916j1578f82zvg1hgxf40000gp/T/go-build852002820=/tmp/go-build -gno-record-gcc-switches -fno-common"
uname -a Output
$uname -a
Darwin wangzhizhaodeMacBook-Pro.local 18.7.0 Darwin Kernel Version 18.7.0: Mon Apr 27 20:09:39 PDT 2020; root:xnu-4903.278.35~1/RELEASE_X86_64 x86_64

What did you do?

  1. source code is the following two files: verify.go
    
    package main

// #include import "C"

import ( "encoding/hex" "strings"

"verify/sec"

)

//export Verify func Verify(serviceNameC C.char, keyC C.char) *C.char { serviceName := C.GoString(serviceNameC)

key := []byte(C.GoString(keyC))
sec.InitWithKey(key)

res := "res"
return C.CString(strings.Join([]string{serviceName, res, hex.EncodeToString(key)}, "-"))

}

func main() {

}

sec/key.go

package sec

import ( "encoding/hex" "fmt" )

var CryptoKey []byte

func InitWithKey(key []byte) { CryptoKey = key fmt.Println(hex.EncodeToString(key)) }


2. go build genrate c-shared .so
`go build -buildmode=c-shared -a -o libverify.so verify.go`

3. using libverify.so

package main

// #cgo LDFLAGS: -lverify // #include </usr/local/lib/verify.h> import "C" import ( "fmt" "unsafe" )

func freeCString(cString *C.char) { C.free(unsafe.Pointer(cString)) }

func Init(serviceName string) { cServiceName := C.CString(serviceName) defer freeCString(cServiceName) key := C.CString("test") defer freeCString(key)

cRes := C.Verify(cServiceName, key)
defer freeCString(cRes)

fmt.Println(C.GoString(cRes))

}

func main() { Init("my-service") }


### What did you expect to see?
no panic, and print out a string.

### What did you see instead?

fatal error: unexpected signal during runtime execution [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x41e745a]

goroutine 1 [running, locked to thread]: runtime.throw(0x40d653d, 0x2a) /usr/local/go/src/runtime/panic.go:1116 +0x72 fp=0xc0000439b0 sp=0xc000043980 pc=0x4030dd2 runtime: unexpected return pc for runtime.sigpanic called from 0x41e745a stack: frame={sp:0xc0000439b0, fp:0xc0000439e0} stack=[0xc000043000,0xc000044000) 000000c0000438b0: 0000000000000000 0000000000000000 000000c0000438c0: 0000000000000000 0000000000000000 000000c0000438d0: 0000000000000000 0000000000000000 000000c0000438e0: 0000000000000000 0000000000000000 000000c0000438f0: 0000000000000000 0000000000000000 000000c000043900: 0000000000000000 0000000000000000 000000c000043910: 0000000000000000 0000000000000000 000000c000043920: 0000000000000000 0000000000000000 000000c000043930: 0000000000000000 0000000000000000 000000c000043940: 0000000004030f97 <runtime.fatalthrow+87> 000000c000043950 000000c000043950: 000000000405a860 <runtime.fatalthrow.func1+0> 000000c000000180 000000c000043960: 0000000004030dd2 <runtime.throw+114> 000000c000043980 000000c000043970: 000000c0000439a0 0000000004030dd2 <runtime.throw+114> 000000c000043980: 000000c000043988 000000000405a7e0 <runtime.throw.func1+0> 000000c000043990: 00000000040d653d 000000000000002a 000000c0000439a0: 000000c0000439d0 0000000004044f2a <runtime.sigpanic+1130> 000000c0000439b0: <00000000040d653d 000000000000002a 000000c0000439c0: 0000000000000000 0000000000000000 000000c0000439d0: 000000c000043aa8 !00000000041e745a 000000c0000439e0: >0000000000000000 0000000000000000 000000c0000439f0: 0000000000000000 0000000000000000 000000c000043a00: 0000000000000000 0000000000000000 000000c000043a10: 0000000000000000 0000000000000000 000000c000043a20: 000802aaaa00aaaa 0000000000000034 000000c000043a30: 0000000000000020 0000000000000000 000000c000043a40: 0000000000000000 0000000000000000 000000c000043a50: 0000000000000000 0000000000203000 000000c000043a60: 0000000000203000 0000000000203000 000000c000043a70: 0000000000000000 0000000000000000 000000c000043a80: 0000000000000008 0000000000000000 000000c000043a90: 0000000000000000 000000c000043b38 000000c000043aa0: 000000000400d726 <runtime.mallocgc+790> 000000c000043b48 000000c000043ab0: 00000000041df53e 000000c000012200 000000c000043ac0: 0000000000000010 0000000000000010 000000c000043ad0: 0000000004281340 0000000000000680 runtime.sigpanic() /usr/local/go/src/runtime/signal_unix.go:679 +0x46a fp=0xc0000439e0 sp=0xc0000439b0 pc=0x4044f2a

goroutine 2 [force gc (idle)]: runtime.gopark(0x40d7b98, 0x417f670, 0x1411, 0x1) /usr/local/go/src/runtime/proc.go:304 +0xe0 fp=0xc000030fb0 sp=0xc000030f90 pc=0x40337f0 runtime.goparkunlock(...) /usr/local/go/src/runtime/proc.go:310 runtime.forcegchelper() /usr/local/go/src/runtime/proc.go:253 +0xb7 fp=0xc000030fe0 sp=0xc000030fb0 pc=0x40336a7 runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc000030fe8 sp=0xc000030fe0 pc=0x405da91 created by runtime.init.6 /usr/local/go/src/runtime/proc.go:242 +0x35

goroutine 18 [GC sweep wait]: runtime.gopark(0x40d7b98, 0x417f7a0, 0x140c, 0x1) /usr/local/go/src/runtime/proc.go:304 +0xe0 fp=0xc00002c7a8 sp=0xc00002c788 pc=0x40337f0 runtime.goparkunlock(...) /usr/local/go/src/runtime/proc.go:310 runtime.bgsweep(0xc00008e000) /usr/local/go/src/runtime/mgcsweep.go:70 +0x9c fp=0xc00002c7d8 sp=0xc00002c7a8 pc=0x4021a4c runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc00002c7e0 sp=0xc00002c7d8 pc=0x405da91 created by runtime.gcenable /usr/local/go/src/runtime/mgc.go:214 +0x5c

goroutine 19 [GC scavenge wait]: runtime.gopark(0x40d7b98, 0x417f760, 0x140d, 0x1) /usr/local/go/src/runtime/proc.go:304 +0xe0 fp=0xc00002cf78 sp=0xc00002cf58 pc=0x40337f0 runtime.goparkunlock(...) /usr/local/go/src/runtime/proc.go:310 runtime.bgscavenge(0xc00008e000) /usr/local/go/src/runtime/mgcscavenge.go:237 +0xd0 fp=0xc00002cfd8 sp=0xc00002cf78 pc=0x401ffa0 runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc00002cfe0 sp=0xc00002cfd8 pc=0x405da91 created by runtime.gcenable /usr/local/go/src/runtime/mgc.go:215 +0x7e

goroutine 3 [finalizer wait]: runtime.gopark(0x40d7b98, 0x41a8ca8, 0x1410, 0x1) /usr/local/go/src/runtime/proc.go:304 +0xe0 fp=0xc000030758 sp=0xc000030738 pc=0x40337f0 runtime.goparkunlock(...) /usr/local/go/src/runtime/proc.go:310 runtime.runfinq() /usr/local/go/src/runtime/mfinal.go:175 +0xa3 fp=0xc0000307e0 sp=0xc000030758 pc=0x4017773 runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc0000307e8 sp=0xc0000307e0 pc=0x405da91 created by runtime.createfing /usr/local/go/src/runtime/mfinal.go:156 +0x61 exit status 2

odeke-em commented 4 years ago

Thank you for this report @wangzhione and welcome to the Go project!

I can reproduce this even for Go1.13.12, Go1.12.17, but for Go1.11.13 there are CGO errors.

Kindly paging @ianlancetaylor @cherrymui

luchsh commented 4 years ago

I tried to debug this problem, it crashed at method runtime.heapBitsSetType. After digging into the assembly,

(lldb) di -f -m
libverify.so`runtime.heapBitsSetType:
....
    0x4327139 <+2361>: cmpl   $0x20, %edi
    0x432713c <+2364>: sbbl   %eax, %eax
    0x432713e <+2366>: sbbl   %edx, %edx
    0x4327140 <+2368>: movzbl (%r10), %ebx
    0x4327144 <+2372>: andl   $0x3, %ebx
    0x4327147 <+2375>: orl    $0x10, %ebx
->  0x432714a <+2378>: movzbl (%rsi), %r8d
    0x432714e <+2382>: movl   %edi, %ecx
    0x4327150 <+2384>: movl   $0x33, %r9d
    0x4327156 <+2390>: shll   %cl, %r9d
    0x4327159 <+2393>: andl   %eax, %r9d

It looks like the heapAreana.bitmap corresponding to this newly allocated memory p is NULL.

I could not find an efficient debugger on Catalina to further dig into this problem; lldb cannot set breakpoints; dlv and gdb cannot display symbols; Pls let me know if you have a working debugger on Catalina.

Then I tried to add many print statements to the Go runtime and found:

But I still do not know why the shared library was accessing the wrong runtime.mheap_. I've tried to rewrite the executable and the shared library in C language, and the following scenarios all work well:

any thoughts?

ianlancetaylor commented 4 years ago

A shared library built with -buildmode=c-shared is intended to be used with a C program, not a Go program.

I don't know whether the Mach-O symbol visibility rules can support using -buildmode=c-shared with a Go program.

networkimprov commented 4 years ago

Emmanual @odeke-em found that Go 1.11 gave a CGO error, not a segfault.

anshuman-mor commented 2 years ago

@networkimprov - Did you get this working by any chance?

@ianlancetaylor - IMHO, If golang is providing a way to build native shared library, then it does not matter, whether caller is written in Go, C, C++ or any other language, as long as caller follow the rules.

ianlancetaylor commented 2 years ago

Unless we have strict symbol visibility control, it matters what language the caller is written, because a Go program and a Go shared library will define many symbols with the same names. Those symbols must be distinct, and not combined by the dynamic linker.

Linkangyis commented 2 years ago

这个问题,你在dll的代码里面只要用到了接口,必报错

Linkangyis commented 2 years ago

这个问题在go任何一个支持cgo的版本都会出现,包括最新的1.19

jiftle commented 8 months ago

go version: go1.20.5 darwin/amd64 os: uname -a Darwin macbookdeMacBook-Pro.local 20.6.0 Darwin Kernel Version 20.6.0: Thu Jul 6 22:12:47 PDT 2023; root:xnu-7195.141.49.702.12~1/RELEASE_X86_64 x86_64 golang call .dylib from golang code. this is .dylib is been golang generate.

this is Makefile

CGO_ENABLED=1 \
GOOS=darwin \
GOARCH=amd64 \
go build \
-buildmode=c-shared \
-o bin/darwin/*.dylib

error

fatal error: bad sweepgen in refill

goroutine 1 [running]:
runtime.throw({0x14ae9f7?, 0xc000666de0?})
    /usr/local/go/src/runtime/panic.go:1047 +0x5d fp=0xc000666d80 sp=0xc000666d50 pc=0x1035b3d
runtime.(*mcache).refill(0x9c005b8, 0x0?)
    /usr/local/go/src/runtime/mcache.go:157 +0x216 fp=0xc000666dc0 sp=0xc000666d80 pc=0x10167d6
runtime.(*mcache).nextFree(0x9c005b8, 0x5)
    /usr/local/go/src/runtime/malloc.go:855 +0x85 fp=0xc000666e08 sp=0xc000666dc0 pc=0x100d3a5
runtime.mallocgc(0x4, 0x140b3e0, 0x1)
    /usr/local/go/src/runtime/malloc.go:1017 +0x2c5 fp=0xc000666e70 sp=0xc000666e08 pc=0x100d805
reflect.unsafe_New(0xc0001c2840?)
    /usr/local/go/src/runtime/malloc.go:1259 +0x27 fp=0xc000666e98 sp=0xc000666e70 pc=0x1064807
reflect.New({0x15546e8?, 0x140b3e0})
    /usr/local/go/src/reflect/value.go:3194 +0x5f fp=0xc000666ec8 sp=0xc000666e98 pc=0x109b79f
github.com/ebitengine/purego.RegisterFunc.func1({0xc0001123f0?, 0x2?, 0x2?})
    /Users/mac/wsp/gowork/pkg/mod/github.com/ebitengine/purego@v0.5.0/func.go:259 +0xada fp=0xc000667238 sp=0xc000666ec8 pc=0x13777ba
reflect.callReflect(0xc00053fc50, 0xc0006677a0, 0xc000667678, 0xc000667680)
    /usr/local/go/src/reflect/value.go:772 +0x56d fp=0xc000667628 sp=0xc000667238 pc=0x109558d
reflect.callReflect(0xc00053fc50, 0xc0006677a0, 0xc000667678, 0xc000667680)
    <autogenerated>:1 +0x4b fp=0xc000667658 sp=0xc000667628 pc=0x10a012b
reflect.makeFuncStub()
    /usr/local/go/src/reflect/asm_amd64.s:47 +0x7a fp=0xc0006677a0 sp=0xc000667658 pc=0x109e79a