Skip to content

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

@TotallyGamerJet

Description

@TotallyGamerJet

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions