static linking a no-op binary with `net` and cgo turned off fails

Viewed 536

I tried to file a bug report (https://github.com/golang/go/issues/48081) but was sent here instead.

I am trying to statically link a binary, and am running into trap issues even with a no op binary.

$ go version
go version go1.17 linux/amd64

Note I was using the docker golang:1.17-buster image, but this repros with 1.16 too.

$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.17"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build838287027=/tmp/go-build -gno-record-gcc-switches"

I tried to statically compile a simple main file:

$ cat go.mod
module naphatkrit/go-bug-repro

go 1.17
$ cat main.go
package main

func main() {
}

I then ran go build with the flags needed to statically link my binary, this results in a warning about not being able to find cgo.

$ go build -a -v -o /tmp/my-binary -ldflags "-linkmode external -extldflags -static" -trimpath .
runtime/internal/sys
internal/goexperiment
internal/cpu
internal/abi
runtime/internal/atomic
runtime/internal/math
internal/bytealg
runtime
naphatkrit/go-bug-repro
# naphatkrit/go-bug-repro
loadinternal: cannot find runtime/cgo

Executing the binary results in a trap error

$ /tmp/my-binary
Trace/breakpoint trap

Additionally, here is what strace shows:

root@3f441e3ed41c:/code# strace /tmp/my-binary
execve("/tmp/my-binary", ["/tmp/my-binary"], 0x7fff5db80d00 /* 10 vars */) = 0
brk(NULL)                               = 0xf03000
brk(0xf041c0)                           = 0xf041c0
arch_prctl(ARCH_SET_FS, 0xf03880)       = 0
uname({sysname="Linux", nodename="3f441e3ed41c", ...}) = 0
readlink("/proc/self/exe", "/tmp/my-binary", 4096) = 14
brk(0xf251c0)                           = 0xf251c0
brk(0xf26000)                           = 0xf26000
arch_prctl(ARCH_SET_FS, 0x55fd90)       = 0
--- SIGTRAP {si_signo=SIGTRAP, si_code=SI_KERNEL} ---
+++ killed by SIGTRAP +++
Trace/breakpoint trap

If I forcibly include runtime/cgo, the build warning goes away and the compiled binary runs fine.

$ cat main.go
package main

import _ "runtime/cgo"

func main() {
}
$ go build -a -v -o /tmp/my-binary -ldflags "-linkmode external -extldflags -static" -trimpath .
internal/race
runtime/internal/sys
internal/abi
internal/cpu
internal/goexperiment
runtime/internal/atomic
sync/atomic
runtime/internal/math
internal/bytealg
runtime
sync
runtime/cgo
naphatkrit/go-bug-repro
$ /tmp/my-binary
$

Am I doing static linking wrong?

I have put up my repro at https://github.com/naphatkrit/go-bug-repro for convenience


Edit: I realized that I simplified my repro too far and it detracted from the issue I was facing. What I am trying to do is statically link a binary that uses net and turn off its cgo usage.

In particular, consider this instead and see how it has the same issue as above:

package main

import _ "net"

func main() {
}
$ go build -a -v -o /tmp/gobuild -ldflags "-linkmode external -extldflags -static" -trimpath -tags 'netgo' .
...
loadinternal: cannot find runtime/cgo
$ /tmp/gobuild
Trace/breakpoint trap
1 Answers

Go builds static binaries by default (unless you are actually using cgo to import C code). There are two exceptions with the std library. The net and os/user packages do use native code by default.

EDIT:

To use the net package without native code, you can do

CGO_ENABLED=0 go build ...

or

go build -tags netgo ...

But what you have should also work as well, although I'd omit the -a flag.

Related