Skip to content

cmd/link: windows/arm64 internal linking rejects Clang COFF NODUPLICATES and ASSOCIATIVE sections #81365

Description

@ClayWarren

Go version

go version go1.27.1 darwin/arm64 (Homebrew)

Clang 23.1.0, targeting aarch64-pc-windows-msvc.

Output of go env in your module/workspace:

Relevant values under the reproduction command below:

GO111MODULE='off'
GOARCH='arm64'
GOARM64='v8.0'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOOS='windows'
GOEXE='.exe'
GOEXPERIMENT=''
GOFLAGS=''
GOFIPS140='off'
GOTOOLCHAIN='local'
GOVERSION='go1.27.1'
GOWORK='off'
CGO_ENABLED='0'

GOENV=off disables saved Go configuration. Clang is invoked separately, so
the reduction does not need a Windows SDK or a configured CGo environment.

What did you do?

Reduced an internal-link failure seen while testing native Windows ARM64 CGo
with MSVC-target Clang in
conda-forge/go-feedstock#339.
The following reduction uses the stock Go toolchain, without the feedstock's
patches, and can be cross-linked from macOS ARM64.

Create this layout:

repro/
  functions.c
  smoke/
    main.go

functions.c:

__declspec(noinline) int repro_leaf(int n) { return n + 1; }

__declspec(noinline) int repro_nonleaf(int n) {
    return repro_leaf(n) + 1;
}

smoke/main.go:

package main

func main() {}

From repro/, using Clang and llvm-readobj 23.1.0:

clang --target=aarch64-pc-windows-msvc -O2 -ffunction-sections \
  -c functions.c -o smoke/repro_windows_arm64.syso
llvm-readobj --symbols --relocations --unwind smoke/repro_windows_arm64.syso
cd smoke
GOENV=off GOTOOLCHAIN=local GOWORK=off \
  GOOS=windows GOARCH=arm64 CGO_ENABLED=0 GO111MODULE=off \
  go build -ldflags=-linkmode=internal -o repro.exe .

What did you see happen?

The stock linker exits with status 1:

internal error: unsupported COMDAT selection strategy found in path=<archive>(repro_windows_ar) sec=4 strategy=1 idx=6, please file a bug

The input contains NODUPLICATES (1) .text sections for the two functions.
The non-leaf function also has ASSOCIATIVE (5) .xdata and .pdata sections,
both referring to its .text section. Its .pdata record is eight bytes,
with packed unwind information and an ARM64_ADDR32NB relocation.

A separate diagnostic linker with the feedstock's NODUPLICATES support patch
(including duplicate-definition checking) reaches the next error:

internal error: unsupported COMDAT selection strategy found in path=<archive>(repro_windows_ar) sec=5 strategy=5 idx=12, please file a bug

That second result is from the modified diagnostic linker, not stock Go.
The stock reproduction above stops at strategy 1.

At inspected master commit
714d9afb66994e987aa715e088279e75efcec315,
the loader still accepts only ANY and SAME_SIZE. I have not built and run tip.

What did you expect to see?

Support for internally linking these MSVC-target Clang COFF sections, or
guidance on whether this object form is intentionally outside the supported
internal-linker subset. This is a missing-capability report, not a claim of a
regression from an earlier release.

Related work: Windows ARM64 internal linking landed in
#75485, MSVC-target Clang support in
https://go.dev/cl/703055, and the existing COMDAT selection support in
https://go.dev/cl/383835.

Related ARM64 SEH work is discussed in
#57302. Preserving existing C-host unwind
data is another limitation, so simply accepting strategy 5 would not establish
correct unwind handling. This report is about section loading and association,
not generating unwind metadata for Go frames.

Would a scoped change for NODUPLICATES and its associative children be a useful
first step, or is there existing work to coordinate with?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions