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

cmd/link: cgo_import_dynamic with internal linking provides wrong symbol #61220

Closed
TotallyGamerJet opened this issue Jul 7, 2023 · 4 comments
Labels
compiler/runtime Issues related to the Go compiler and/or runtime.

Comments

@TotallyGamerJet
Copy link

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

$ go version
go version go1.21rc2 darwin/arm64

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='on'
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/jarrettkuklis/Library/Caches/go-build'
GOENV='/Users/jarrettkuklis/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/jarrettkuklis/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/jarrettkuklis/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/Users/jarrettkuklis/go/go1.21rc2'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/Users/jarrettkuklis/go/go1.21rc2/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.21rc2'
GCCGO='gccgo'
AR='ar'
CC='clang'
CXX='clang++'
CGO_ENABLED='1'
GOMOD='/Users/jarrettkuklis/Documents/GolandProjects/purego/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/kw/8msl9lzx7wbdbq4xxtz3rhvr0000gn/T/go-build3905000783=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOROOT/bin/go version: go version go1.21rc2 darwin/arm64
GOROOT/bin/go tool compile -V: compile version go1.21rc2
uname -v: Darwin Kernel Version 22.5.0: Thu Jun  8 22:22:20 PDT 2023; root:xnu-8796.121.3~7/RELEASE_ARM64_T6000
ProductName:		macOS
ProductVersion:		13.4.1
BuildVersion:		22F82
lldb --version: lldb version 16.0.1

What did you do?

Run the following code with command:

go run -trimpath -gcflags="-std" -ldflags="-linkmode internal" main.go

package main

import (
	"fmt"
	"unsafe"
)

//go:linkname __NSDefaultRunLoopMode NSDefaultRunLoopMode
//go:cgo_import_dynamic NSDefaultRunLoopMode NSDefaultRunLoopMode "Cocoa.framework/Cocoa"
//go:cgo_import_static NSDefaultRunLoopMode
var __NSDefaultRunLoopMode byte
var NSDefaultRunLoopMode = (*struct{ _ uintptr })(unsafe.Pointer(&__NSDefaultRunLoopMode))

func main() {
	fmt.Printf("%#x\n", unsafe.Pointer(NSDefaultRunLoopMode)) // Show pointer address
	fmt.Printf("%x\n", NSDefaultRunLoopMode)                  // Dereference struct
}

What did you expect to see?

Program run without issue with output similar to what you get from external linking.

$ go run -trimpath -gcflags="-std" -ldflags="-linkmode external" main.go
0x1eb3299f8
&{1ed12dc58}

What did you see instead?

Program crashed when dereferencing the pointer.

$ go run -trimpath -gcflags="-std" -ldflags="-linkmode internal" main.go
0x2d2c000
unexpected fault address 0x2d2c000
fatal error: fault
[signal SIGSEGV: segmentation violation code=0x2 addr=0x2d2c000 pc=0x102d8a0e8]

goroutine 1 [running]:
runtime.throw({0x102db47b0?, 0x0?})
        runtime/panic.go:1077 +0x40 fp=0x14000094710 sp=0x140000946e0 pc=0x102d5bd20
runtime.sigpanic()
        runtime/signal_unix.go:875 +0x22c fp=0x14000094770 sp=0x14000094710 pc=0x102d7152c
runtime.memmove()
        runtime/memmove_arm64.s:57 +0x48 fp=0x14000094780 sp=0x14000094780 pc=0x102d8a0e8
runtime.typedmemmove(0x8?, 0x102de4560?, 0x1?)
        runtime/mbarrier.go:166 +0x64 fp=0x140000947b0 sp=0x14000094780 pc=0x102d3c144
reflect.typedmemmove(0x14000094818?, 0x102d36b24?, 0x0?)
        runtime/mbarrier.go:206 +0x1c fp=0x140000947e0 sp=0x140000947b0 pc=0x102d84b7c
reflect.packEface({0x102de4560?, 0x2d2c000?, 0x0?})
        reflect/value.go:135 +0x58 fp=0x14000094830 sp=0x140000947e0 pc=0x102d98198
reflect.valueInterface({0x102de4560?, 0x2d2c000?, 0x140000948e8?}, 0x90?)
        reflect/value.go:1520 +0xa8 fp=0x14000094870 sp=0x14000094830 pc=0x102d99cc8
reflect.Value.Interface(...)
        reflect/value.go:1490
fmt.(*pp).printValue(0x140000a6410, {0x102de4560?, 0x2d2c000?, 0x102dde680?}, 0x78, 0x1)
        fmt/print.go:769 +0x68 fp=0x14000094a90 sp=0x14000094870 pc=0x102db0d18
fmt.(*pp).printValue(0x140000a6410, {0x102dde680?, 0x2d2c000?, 0x102d9eb30?}, 0x78, 0x0)
        fmt/print.go:923 +0x9f8 fp=0x14000094cb0 sp=0x14000094a90 pc=0x102db16a8
fmt.(*pp).printArg(0x140000a6410, {0x102dde680?, 0x2d2c000}, 0x78)
        fmt/print.go:759 +0x664 fp=0x14000094d50 sp=0x14000094cb0 pc=0x102db0c34
fmt.(*pp).doPrintf(0x140000a6410, {0x102db45c7, 0x3}, {0x14000094f08?, 0x1, 0x1})
        fmt/print.go:1077 +0x2dc fp=0x14000094e60 sp=0x14000094d50 pc=0x102db33cc
fmt.Fprintf({0x102df2d68, 0x140000a2000}, {0x102db45c7, 0x3}, {0x14000094f08, 0x1, 0x1})
        fmt/print.go:224 +0x54 fp=0x14000094ec0 sp=0x14000094e60 pc=0x102dade54
fmt.Printf(...)
        fmt/print.go:233
main.main()
        ./main.go:16 +0xa8 fp=0x14000094f30 sp=0x14000094ec0 pc=0x102db42b8
runtime.main()
        runtime/proc.go:267 +0x2bc fp=0x14000094fd0 sp=0x14000094f30 pc=0x102d5e58c
runtime.goexit()
        runtime/asm_arm64.s:1197 +0x4 fp=0x14000094fd0 sp=0x14000094fd0 pc=0x102d89834

goroutine 2 [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        runtime/proc.go:398 +0xc8 fp=0x14000042f90 sp=0x14000042f70 pc=0x102d5e9b8
runtime.goparkunlock(...)
        runtime/proc.go:404
runtime.forcegchelper()
        runtime/proc.go:322 +0xb8 fp=0x14000042fd0 sp=0x14000042f90 pc=0x102d5e848
runtime.goexit()
        runtime/asm_arm64.s:1197 +0x4 fp=0x14000042fd0 sp=0x14000042fd0 pc=0x102d89834
created by runtime.init.6 in goroutine 1
        runtime/proc.go:310 +0x24

goroutine 3 [GC sweep wait]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        runtime/proc.go:398 +0xc8 fp=0x14000043760 sp=0x14000043740 pc=0x102d5e9b8
runtime.goparkunlock(...)
        runtime/proc.go:404
runtime.bgsweep(0x0?)
        runtime/mgcsweep.go:280 +0xa0 fp=0x140000437b0 sp=0x14000043760 pc=0x102d4bdc0
runtime.gcenable.func1()
        runtime/mgc.go:200 +0x28 fp=0x140000437d0 sp=0x140000437b0 pc=0x102d40b18
runtime.goexit()
        runtime/asm_arm64.s:1197 +0x4 fp=0x140000437d0 sp=0x140000437d0 pc=0x102d89834
created by runtime.gcenable in goroutine 1
        runtime/mgc.go:200 +0x6c

goroutine 4 [GC scavenge wait]:
runtime.gopark(0x1400005a000?, 0x102dd3690?, 0x1?, 0x0?, 0x14000003040?)
        runtime/proc.go:398 +0xc8 fp=0x14000043f50 sp=0x14000043f30 pc=0x102d5e9b8
runtime.goparkunlock(...)
        runtime/proc.go:404
runtime.(*scavengerState).park(0x102e61a60)
        runtime/mgcscavenge.go:425 +0x5c fp=0x14000043f80 sp=0x14000043f50 pc=0x102d4962c
runtime.bgscavenge(0x0?)
        runtime/mgcscavenge.go:653 +0x44 fp=0x14000043fb0 sp=0x14000043f80 pc=0x102d49b84
runtime.gcenable.func2()
        runtime/mgc.go:201 +0x28 fp=0x14000043fd0 sp=0x14000043fb0 pc=0x102d40ab8
runtime.goexit()
        runtime/asm_arm64.s:1197 +0x4 fp=0x14000043fd0 sp=0x14000043fd0 pc=0x102d89834
created by runtime.gcenable in goroutine 1
        runtime/mgc.go:201 +0xac

goroutine 17 [finalizer wait]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        runtime/proc.go:398 +0xc8 fp=0x1400003e580 sp=0x1400003e560 pc=0x102d5e9b8
runtime.runfinq()
        runtime/mfinal.go:193 +0x108 fp=0x1400003e7d0 sp=0x1400003e580 pc=0x102d3fc08
runtime.goexit()
        runtime/asm_arm64.s:1197 +0x4 fp=0x1400003e7d0 sp=0x1400003e7d0 pc=0x102d89834
created by runtime.createfing in goroutine 1
        runtime/mfinal.go:163 +0x80
exit status 2

additional information

If cgo_import_dynamic uses the one argument version the linker produces an undefined symbol.

# command-line-arguments
main.NSDefaultRunLoopMode: relocation target NSDefaultRunLoopMode not defined

Of course, the std flag is only kept in both to limit the number of differences and doesn't affect the output. This issue affects purego#114.

@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Jul 7, 2023
@ianlancetaylor
Copy link
Contributor

To be clear, the //go:cgo_import_dynamic and //go:cgo_import_static directives are not documented and are not supported in user code. We do not support code that uses them.

@TotallyGamerJet
Copy link
Author

To be clear, the //go:cgo_import_dynamic and //go:cgo_import_static directives are not documented

I thought their documentation was found at cmd/cgo/doc.go?

and are not supported in user code. We do not support code that uses them.

I understand they are not supported in user code. However, they are used in the runtime and packages like golang.org/x/sys/unix which may be affected by this issue.

@cherrymui
Copy link
Member

Currently, on macOS we only support cgo_import_dynamic for functions that are directly called. We don't yet support variables or taking address of a function. CL https://golang.org/cl/501855 may help. (Even with that, it probably only works if the code is written in a specific way.)

As @ianlancetaylor said, generally we don't support it in user code. We do handle the use cases that the runtime and syscall packages need. If you believe that is handled incorrectly, please file a specific issue for that. Thanks.

@cherrymui cherrymui closed this as not planned Won't fix, can't repro, duplicate, stale Jul 7, 2023
@ianlancetaylor
Copy link
Contributor

To be clear, the //go:cgo_import_dynamic and //go:cgo_import_static directives are not documented

I thought their documentation was found at cmd/cgo/doc.go?

True. I meant that they aren't publicly documented. The documentation in cmd/cgo/doc.go is in a comment that describes the implementation but is not part of the user visible docs (https://pkg.go.dev/cmd/cgo).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime.
Projects
None yet
Development

No branches or pull requests

4 participants