golang / golang/go

cmd/link: can't dynamically import static CFString constants using the internal linker

Open
#71,471 6 comments 0 reactions 0 assignees View on GitHub
BugReport cgo compiler/runtime FixPending NeedsInvestigation OS-Darwin
Dominant language
Go
Stars
139k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

### Go version

go version devel go1.24-2b3b5305c6 Fri Jan 24 12:35:21 2025 +0100 darwin/arm64

### Output of `go env` in your module/workspace:

```shell
AR='ar'
CC='clang'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='clang++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/Users/qmuntaldiaz/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/qmuntaldiaz/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/6_/bk27w0c510ld88800_hfj6j00000gn/T/go-build3109590806=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/Users/qmuntaldiaz/code/golang-go/src/go.mod'
GOMODCACHE='/Users/qmuntaldiaz/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/qmuntaldiaz/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/Users/qmuntaldiaz/code/golang-go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='on'
GOTELEMETRYDIR='/Users/qmuntaldiaz/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/Users/qmuntaldiaz/code/golang-go/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='devel go1.24-2b3b5305c6 Fri Jan 24 12:35:21 2025 +0100'
GOWORK=''
PKG_CONFIG='pkg-config'
```

### What did you do?

Execute the following code with `go run -ldflags=-linkmode=internal .`.

```go
package main

// #cgo LDFLAGS: -framework CoreFoundation
// #include
import "C"
import "unsafe"

//go:cgo_import_dynamic main._kCFErrorUnderlyingErrorKey kCFErrorUnderlyingErrorKey "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation"

var _kCFErrorUnderlyingErrorKey byte
var kCFErrorUnderlyingErrorKey = C.CFStringRef(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(&__kCFErrorUnderlyingErrorKey))))

func main() {
out := make([]byte, C.CFStringGetLength(kCFErrorUnderlyingErrorKey))
var used C.CFIndex
C.CFStringGetBytes(kCFErrorUnderlyingErrorKey, C.CFRange{0, C.CFIndex(len(out))},
C.kCFStringEncodingUTF8, 0, 0,
(*C.UInt8)(&out[0]), C.CFIndex(len(out)), &used)

want := "NSUnderlyingError"
got := string(out[:used])
if got != want {
println("got", got, "want", want)
panic("FAIL")
}
}
```

Note that I'm using some C functions (`C.CFStringGetLength` and `C.CFStringGetBytes `) to make the reproducer self-contained. What I really do is define all external functions using `cgo_import_dynamic`, which doesn't modify the failure described here.

@golang/compiler

### What did you see happen?

```
main.init: program too large, address relocation distance = -4295397376
```

### What did you expect to see?

The execution succeeds.

Contributor guide

Open the contributing guide

Research direction

Reproduce the failure on darwin/arm64 with the provided program and -ldflags=-linkmode=internal. Start at the internal linker handling of cgo_import_dynamic references to static CFString constants; done means the program links and executes successfully with the expected NSUnderlyingError output.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.