Skip to content

go build: produces broken static pie files when build with go build instead of go build -o outfile source.go #62173

Not planned
@bluec0re

Description

@bluec0re

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

$ go version
go version go1.20.7 linux/amd64

Does this issue reproduce with the latest release?

No. While filing this bug, I noticed that it works with go 1.21 (build pipelines are still using 1.20) and I figured would be still worth reporting

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd[6](https://github.com/bluec0re/go-static-pie-bug/actions/runs/5923174296/job/16058323972#step:4:7)4"
GOBIN=""
GOCACHE="/home/runner/.cache/go-build"
GOENV="/home/runner/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/runner/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/runner/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/opt/hostedtoolcache/go/1.20.[7](https://github.com/bluec0re/go-static-pie-bug/actions/runs/5923174296/job/16058323972#step:4:8)/x64"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/opt/hostedtoolcache/go/1.20.7/x64/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.20.7"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="0"
GOMOD="/dev/null"
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 -m64 -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build57144[9](https://github.com/bluec0re/go-static-pie-bug/actions/runs/5923174296/job/16058323972#step:4:10)650=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Compiling a static PIE binary with forced external linking. (-tags netgo,osusergo,static_build -buildmode=pie -trimpath -ldflags '-extldflags -static-pie -extld gcc -linkmode external').

Note: The bug only manifests if the binary was build with go build $FLAGS, not when build with go build $FLAGS -o outfile main.go

What did you expect to see?

Compiles successfully and runs.

What did you see instead?

Sometimes an error/warning loadinternal: cannot find runtime/cgo but build ends successfully. The binary then crashes on startup

build output
go version go1.20.7 linux/amd64
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/runner/.cache/go-build"
GOENV="/home/runner/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/runner/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/runner/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/opt/hostedtoolcache/go/1.20.7/x64"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/opt/hostedtoolcache/go/1.20.7/x64/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.20.7"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="0"
GOMOD="/dev/null"
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 -m64 -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build[5](https://github.com/bluec0re/go-static-pie-bug/actions/runs/5923174296/job/16058323972#step:4:6)71449[6](https://github.com/bluec0re/go-static-pie-bug/actions/runs/5923174296/job/16058323972#step:4:7)50=/tmp/go-build -gno-record-gcc-switches"
# mod
 # build
# github.com/bluec0re/go-static-pie-bug
loadinternal: cannot find runtime/cgo
 # build -o foo.go main.go
# path
 # build
# github.com/bluec0re/go-static-pie-bug
loadinternal: cannot find runtime/cgo
 # build -o foo.go main.go
# file
mod/go-static-pie-bug:  ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), static-pie linked, BuildID[sha1]=cf3f6d[7](https://github.com/bluec0re/go-static-pie-bug/actions/runs/5923174296/job/16058323972#step:4:8)9942b40e6eb0467ba[8](https://github.com/bluec0re/go-static-pie-bug/actions/runs/5923174296/job/16058323972#step:4:9)[9](https://github.com/bluec0re/go-static-pie-bug/actions/runs/5923174296/job/16058323972#step:4:10)d34a19b646c033, for GNU/Linux 3.2.0, with debug_info, not stripped
path/go-static-pie-bug: ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), static-pie linked, BuildID[sha1]=cf5db9dc6c43af4e3f243d5fc4486f637281514e, for GNU/Linux 3.2.0, with debug_info, not stripped
mod/foo:                ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), static-pie linked, BuildID[sha1]=f57a846177a64196a35318f6865cf0eda8615a7c, for GNU/Linux 3.2.0, with debug_info, not stripped
path/foo:               ELF 64-bit LSB pie executable, x86-64, version 1 (GNU/Linux), static-pie linked, BuildID[sha1]=5d1c[11](https://github.com/bluec0re/go-static-pie-bug/actions/runs/5923174296/job/16058323972#step:4:12)d6dc66b7b56bb81f279b99f2bb1ccab33d, for GNU/Linux 3.2.0, with debug_info, not stripped
# ldd
mod/go-static-pie-bug:
	statically linked
path/go-static-pie-bug:
	statically linked
mod/foo:
	statically linked
path/foo:
	statically linked
# deadcode
mod/main.go:	fmt.Println("This is not used")
# exec
./mod/go-static-pie-bug
./test.sh: line 45:  30[17](https://github.com/bluec0re/go-static-pie-bug/actions/runs/5923174296/job/16058323972#step:4:18) Trace/breakpoint trap   (core dumped) $b
./path/go-static-pie-bug
./test.sh: line 45:  30[19](https://github.com/bluec0re/go-static-pie-bug/actions/runs/5923174296/job/16058323972#step:4:20) Trace/breakpoint trap   (core dumped) $b
./mod/foo
Hello world
./path/foo
Hello world

Activity

bcmills

bcmills commented on Aug 21, 2023

@bcmills
Contributor

You are overriding cmd/go's choice of linker flags to request something incompatible: your go env reports CGO_ENABLED="0" but setting -linkmode external in your -ldflags requests that the build use a C linker.

You cannot safely link a Go program using a C linker without Go runtime support for the things that the C linker may incorporate into the binary.

bcmills

bcmills commented on Aug 21, 2023

@bcmills
Contributor

Duplicate of #46330

bluec0re

bluec0re commented on Aug 25, 2023

@bluec0re
Author

Yes, that is intended. The goal is to have a fully static pie binary, ideally build with pure go.

Without forcing gcc as linker, the binary will not be PIE, just static.

Please note that

CGO_ENABLED=0 go build -tags=netgo,osusergo,static_build -buildmode=pie -trimpath -ldflags -extldflags -static-pie -extld gcc -linkmode external -o some_binary main.go

doesn't seem to require cgo, while

CGO_ENABLED=0 go build -tags=netgo,osusergo,static_build -buildmode=pie -trimpath -ldflags -extldflags -static-pie -extld gcc -linkmode external

does.

A binary compiled with the first version works fine (I'm using this variant since go 1.13 now without a single crash or bug outside of my very own). I just recently changed something in the build pipeline , using the variant without explicit -o and source files, and that is what caused cgo dependencies and crashes.

locked and limited conversation to collaborators on Aug 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @bluec0re@bcmills@gopherbot

        Issue actions

          go build: produces broken static pie files when build with `go build` instead of `go build -o outfile source.go` · Issue #62173 · golang/go