Go version

go version go1.25.0 windows/amd64

Output of go env in your module/workspace:

set AR=ar
set CC=gcc
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_ENABLED=1
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set CXX=g++
set GCCGO=gccgo
set GO111MODULE=on
set GOAMD64=v1
set GOARCH=amd64
set GOAUTH=netrc
set GOBIN=
set GOCACHE=C:\Users\cj\AppData\Local\go-build
set GOCACHEPROG=
set GODEBUG=
set GOENV=C:\Users\cj\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFIPS140=off
set GOFLAGS=
set GOGCCFLAGS=-m64 -mthreads -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=C:\Users\cj\AppData\Local\Temp\go-build3808498674=/tmp/go-build -gno-record-gcc-switches
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=C:\Users\cj\go\pkg\mod
set GOOS=windows
set GOPATH=C:\Users\cj\go
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:/Program Files/Go
set GOSUMDB=sum.golang.org
set GOTELEMETRY=local
set GOTELEMETRYDIR=C:\Users\cj\AppData\Roaming\go\telemetry
set GOTMPDIR=
set GOTOOLCHAIN=auto
set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.25.0
set GOWORK=
set PKG_CONFIG=pkg-config

What did you do?

As of Go 1.25, a simple app which uses CGO will fail to run on Windows with the error failed to run: The specified executable is not a valid application for this OS

Example code: https://go.dev/play/p/YKuBXwCGWAd

This same code will run successfully when built with GOEXPERIMENT=nodwarf5 OR stripping debug info -ldflags="-s -w"

dumpbin.exe output shows sections being placed at virtual addresses outside of the normal Windows PE address space.

With DWARF5 enabled:

SECTION HEADER #1
      /4 name (.debug_rnglists)
   1B7D1 virtual size
C0000000 virtual address (0000000200000000 to 000000020001B7D0)
   1B800 size of raw data
     548 file pointer to raw data (00000548 to 0001BD47)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
42100040 flags
         Initialized Data
         RESERVED - UNKNOWN
         Discardable
         Read Only

With GOEXPERIMENT=nodwarf5:

SECTION HEADER #1
   .text name
   B0720 virtual size
    1000 virtual address (0000000140001000 to 00000001400B171F)
   B0800 size of raw data
     600 file pointer to raw data (00000600 to 000B0DFF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
60600060 flags
         Code
         Initialized Data
         RESERVED - UNKNOWN
         RESERVED - UNKNOWN
         Execute Read

What did you see happen?

Program 'main.exe' failed to run: The specified executable is not a valid application for this OS platform.At line:1 char:1

What did you expect to see?

Message: Hello from C!

Comment From: qmuntal

Thanks for reporting this isssue. This issue has not been triggered in CI, nor I can reproduce it locally. Thid makes me think that is dependant on a specific C toolchain. Which Mingw-w64 are you using? From where did you download it?

Comment From: seejdev

Thanks for your help. It was downloaded from https://jmeubank.github.io/tdm-gcc/download/

The installer says the mingw64-runtime version is v8-git2021050601-gcc10-tdm64-1

gcc -v
Using built-in specs.
COLLECT_GCC=C:\TDM-GCC-64\bin\gcc.exe
COLLECT_LTO_WRAPPER=C:/TDM-GCC-64/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../../../src/gcc-git-10.3.0/configure --build=x86_64-w64-mingw32 --enable-targets=all --enable-languages=ada,c,c++,fortran,jit,lto,objc,obj-c++ --enable-libgomp --enable-lto --enable-graphite --enable-cxx-flags=-DWINPTHREAD_STATIC --disable-build-with-cxx --disable-build-poststage1-with-cxx --enable-libstdcxx-debug --enable-threads=posix --enable-versio
n-specific-runtime-libs --enable-fully-dynamic-string --enable-libstdcxx-filesystem-ts=yes --disable-libstdcxx-pch --enable-libstdcxx-threads --enable-libstdcxx-time=yes --enable-mingw-wildcard --with-gnu-ld --disable-werror --enable-nls --disable-win32-registry --enable-large-address-aware --disable-rpath --disable-symvers --prefix=/mingw64tdm --with-local-prefix=/mingw64tdm --with-pkgversion=tdm64-1 --with-bugurl=https://github.com/jmeubank/tdm-gcc/issues
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 10.3.0 (tdm64-1)

Comment From: prattmic

It seems strange that the binary appears to have a dwarf section first, rather than the .text section.

Have you tried any other C toolchain versions?

Comment From: dev-abir

I can reproduce this issue on Go 1.25.0 (windows/amd64) and it does not occur on Go 1.24.6.

It doesn't appear to be a C toolchain issue. I am using an older version of MinGW:

gcc -v
Using built-in specs.
COLLECT_GCC=C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin\gcc.exe
COLLECT_LTO_WRAPPER=C:/Program\ Files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/8.1.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../../../src/gcc-8.1.0/configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw64 --with-sysroot=/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64 --enable-shared --enable-static --disable-multilib --enable-languages=c,c++,fortran,lto --enable-libstdcxx-time=yes --enable-threads=posix --enable-libgomp --enable-libatomic --enable-lto --enable-graphite --enable-checking=release --enable-fully-dynamic-string --enable-version-specific-runtime-libs --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-bootstrap --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with-arch=nocona --with-tune=core2 --with-libiconv --with-system-zlib --with-gmp=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-mpfr=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-mpc=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-isl=/c/mingw810/prerequisites/x86_64-w64-mingw32-static --with-pkgversion='x86_64-posix-seh-rev0, Built by MinGW-W64 project' --with-bugurl=https://sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' CXXFLAGS='-O2 -pipe -fno-ident -I/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' CPPFLAGS=' -I/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/include -I/c/mingw810/prerequisites/x86_64-zlib-static/include -I/c/mingw810/prerequisites/x86_64-w64-mingw32-static/include' LDFLAGS='-pipe -fno-ident -L/c/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/lib -L/c/mingw810/prerequisites/x86_64-zlib-static/lib -L/c/mingw810/prerequisites/x86_64-w64-mingw32-static/lib '
Thread model: posix
gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)

Comment From: michaelquigley

I have also been able to reproduce this using Go 1.25.0, and it does not occur on Go 1.24.6. I am also using TDM-GCC (which is a very tidy Windows-based installation that typically works very well for CGO builds).

Setting GOEXPERIMENT=nodwarf5 does result in a working build.

Comment From: prattmic

cc @golang/compiler @golang/windows @thanm

Comment From: thanm

Thanks for the report.

@seejdev it would be helpful to understand whether this problem happens only with external linking or also with internal linking (in some other reports it sounds like the problems is with internal linking).

Would you kindly try your example with "go build -ldflags=-linkmode=internal" to see whether the resulting executable still works? Thanks.

Comment From: syllith

I can confirm I’m hitting this same problem on Windows with Go 1.25.0. It does not happen on 1.24.6.

In my case the binaries built with the internal linker fail immediately with the “This app can’t run on your PC” dialog. Inspection shows that SizeOfHeaders is not rounded to a multiple of FileAlignment (1352 vs 512), and the first sections have PointerToRawData values misaligned to 512. There are also section names like /4, /20, /36 at RVA 0xC0000000 that look like COFF long-name placeholders, which should never appear in a final PE. With headers/sections in this state the Windows loader refuses to start the program.

Workarounds:

Using the internal linker with stripped debug info works: go build -ldflags="-H=windowsgui -w -s" .

External linking (-linkmode external) does not produce a runnable binary in my setup.

So for me it seems to be the internal linker + DWARF5 debug emission that triggers malformed PE output. Removing debug info avoids it, which matches what others here have seen.

Comment From: thanm

OK, for the folks who are running into this bug, I am assuming that the C linker you're using (from the C compiler toolchain) is built from binutils -- would you kindly check to see which version of binutils is being used for your particular toolchain? I assume this can be done with "ld --version" or equivalent.

I looked at the binutils sources and it appears that support for DWARF 5 was added in this commit: ba6eb62ff0ea9843a018cfd7cd06777bd66ae0a0, which was first released in binutils version 2.37. Binutils 2.37 was put out in July of 2021 so about four years ago.

If you are using a linker built off an older version of binutils, then most likely what's happening is that the linker sees a ".debug_rnglists" section (DWARF-5 specific) and assumes that it is a loadable data section (incorrect) as opposed to a non-loadable data section.

Thanks.

Comment From: syllith

GNU ld (GNU Binutils) 2.36.1

I'm also using TDM GCC, which looks like the latest release was in 2021. Their page says:

TDM-GCC 10.3.0 is now available, along with GDB 10.2, binutils 2.36.1, and new versions of the MinGW.org and MinGW-w64 runtime distributions. Thanks for your patience!

Comment From: thanm

OK, then that confirms it. The linker in your C compiler doesn't understand DWARF 5 -- hence the confusion with the sections winding up loadable as opposed to non-loadable. Thanks.

Comment From: dev-abir

Upgraded my toolchain and this is fixed:

Using built-in specs.
COLLECT_GCC=C:\mingw64\bin\gcc.exe
COLLECT_LTO_WRAPPER=C:/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/15.2.0/lto-wrapper.exe
OFFLOAD_TARGET_NAMES=nvptx-none
Target: x86_64-w64-mingw32
Configured with: ../configure --prefix=/R/winlibs_staging_msvcrt64/inst_gcc-15.2.0/share/gcc --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --enable-offload-targets=nvptx-none --with-pkgversion='MinGW-W64 x86_64-msvcrt-posix-seh, built by Brecht Sanders, r1' --with-tune=generic --enable-checking=release --enable-threads=posix --disable-sjlj-exceptions --disable-libunwind-exceptions --disable-serial-configure --disable-bootstrap --enable-host-shared --enable-plugin --disable-default-ssp --disable-rpath --disable-libstdcxx-debug --disable-version-specific-runtime-libs --disable-symvers --enable-languages=c,c++,fortran,lto,objc,obj-c++ --disable-gold --disable-nls --disable-stage1-checking --disable-win32-registry --disable-multilib --enable-ld --enable-libquadmath --enable-libada --enable-libssp --enable-libstdcxx --enable-lto --enable-fully-dynamic-string --enable-libgomp --enable-graphite --enable-mingw-wildcard --enable-libstdcxx-time --enable-libstdcxx-pch --with-mpc=/c/Prog/winlibs_staging_msvcrt/custombuilt64 --with-mpfr=/c/Prog/winlibs_staging_msvcrt/custombuilt64 --with-gmp=/c/Prog/winlibs_staging_msvcrt/custombuilt64 --with-isl=/c/Prog/winlibs_staging_msvcrt/custombuilt64 --disable-libstdcxx-backtrace --enable-install-libiberty --enable-__cxa_atexit --without-included-gettext --with-diagnostics-color=auto --enable-clocale=generic --enable-libgdiagnostics --with-libiconv --with-system-zlib --with-build-sysroot=/R/winlibs_staging_msvcrt64/gcc-15.2.0/build_mingw/mingw-w64 CFLAGS='-I/c/Prog/winlibs_staging_msvcrt/custombuilt64/include/libdl-win32   -march=nocona -msahf -mtune=generic -O2 -Wno-error=format' CXXFLAGS='-Wno-int-conversion  -march=nocona -msahf -mtune=generic -O2' LDFLAGS='-pthread -Wl,--no-insert-timestamp -Wl,--dynamicbase -Wl,--high-entropy-va -Wl,--nxcompat -Wl,--tsaware' LD=/c/Prog/winlibs_staging_msvcrt/custombuilt64/share/binutils/bin/ld.exe
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 15.2.0 (MinGW-W64 x86_64-msvcrt-posix-seh, built by Brecht Sanders, r1) 

Also, the sections now seem to be aligned to FileAlignment.

Comment From: thrasher-

Can also confirm that after experiencing this issue, updating the gcc toolchain resolved this issue