Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/go: static linking only sometimes works on Alpine Linux #38789

Closed
aykevl opened this issue May 1, 2020 · 5 comments
Closed

cmd/go: static linking only sometimes works on Alpine Linux #38789

aykevl opened this issue May 1, 2020 · 5 comments
Labels
FrozenDueToAge GoCommand cmd/go NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Milestone

Comments

@aykevl
Copy link

aykevl commented May 1, 2020

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

$ go version
go version devel +666c9aedd4 Thu Apr 30 17:30:54 2020 +0000 linux/amd64

For completeness, also the GCC version:

$ gcc --version
gcc (Alpine 9.2.0) 9.2.0

Does this issue reproduce with the latest release?

Yes, it also reproduces with go version go1.14.2 linux/amd64, but with the more confusing error message "relocation target ... not defined for ABI0 (but is defined for ABI0)". Possibly related: #33492, #33028.

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

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/root/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/root/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/root/src/go.master"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/root/src/go.master/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
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-build487931648=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Run this program:

package main

import "os/user"

func main() {
	user, _ := user.Current()
	println(user.Username)
}

With the command CGO_LDFLAGS="-static" go run main.go, on Alpine Linux.

For completeness: Alpine Linux 3.11, with Go built from source (tested both the latest release 1.14.2 and the master branch, see above). I removed Go while testing to make sure I didn't accidentally pick the wrong one.

What did you expect to see?

Run a fully statically linked binary. I know that this can work on Alpine Linux, as I've build a big application this way.

What did you see instead?

# _/root/repro
.dynsym: missing Go type information for global symbol: size 72
os/user(.text): relocation target malloc not defined
os/user(.text): relocation target free not defined
os/user(.text): relocation target getgrgid_r not defined
os/user(.text): relocation target getgrnam_r not defined
os/user(.text): relocation target getpwnam_r not defined
os/user(.text): relocation target getpwuid_r not defined
os/user(.text): relocation target realloc not defined
os/user(.text): relocation target sysconf not defined
runtime/cgo(.text): relocation target stderr not defined
runtime/cgo(.text): relocation target fwrite not defined
runtime/cgo(.text): relocation target vfprintf not defined
runtime/cgo(.text): relocation target fputc not defined
runtime/cgo(.text): relocation target abort not defined
runtime/cgo(.text): relocation target pthread_mutex_lock not defined
runtime/cgo(.text): relocation target pthread_cond_wait not defined
runtime/cgo(.text): relocation target pthread_mutex_unlock not defined
runtime/cgo(.text): relocation target __stack_chk_fail not defined
runtime/cgo(.text): relocation target pthread_cond_broadcast not defined
runtime/cgo(.text): relocation target pthread_create not defined
runtime/cgo(.text): relocation target nanosleep not defined
/root/src/go.master/pkg/tool/linux_amd64/link: too many errors
unexpected fault address 0x7fbc8ab82000
fatal error: fault

I found an interesting workaround, which is to use CGo directly in the main package. Somehow this works with CGO_LDFLAGS="-static":

package main

import "os/user"

// #include <stdlib.h>
import "C"

func main() {
	user, _ := user.Current()
	println(user.Username)
	println(C.malloc(1))
}

If you wonder why I pass this CGo linker flag to a program that doesn't use CGo, it's because I run many tests in a single command (go test ./foo ./bar ./baz). Most use CGo, but some don't - at least not directly.

@bcmills bcmills changed the title Static linking only sometimes works on Alpine Linux cmd/go: static linking only sometimes works on Alpine Linux May 1, 2020
@bcmills bcmills added GoCommand cmd/go NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels May 1, 2020
@bcmills bcmills added this to the Backlog milestone May 1, 2020
@bcmills
Copy link
Contributor

bcmills commented May 1, 2020

This may be a duplicate of #26492, in that CGO_LDFLAGS=-static does not imply “always static” and we don't yet have a flag that does imply that.

CC @jayconrod @matloob

@bcmills
Copy link
Contributor

bcmills commented May 1, 2020

@aykevl, can you confirm whether the flags in #26492 (comment) work for your programs?

@bcmills bcmills added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label May 1, 2020
@aykevl
Copy link
Author

aykevl commented May 1, 2020

Right after posting this issue I discovered that there is a osusergo build tag, and indeed CGO_LDFLAGS="-static" go run -tags=osusergo main.go works.

I tested with -tags netgo -ldflags '-extldflags "-static"' but it doesn't fix the issue. However, -tags 'netgo osusergo' -ldflags '-extldflags "-static"' works.

@bcmills
Copy link
Contributor

bcmills commented May 1, 2020

Thanks for confirming. This does seem like the same issue, then.

@bcmills
Copy link
Contributor

bcmills commented May 1, 2020

Duplicate of #26492

@bcmills bcmills marked this as a duplicate of #26492 May 1, 2020
@bcmills bcmills closed this as completed May 1, 2020
atc0005 added a commit to atc0005/check-mail that referenced this issue Oct 3, 2020
The previous build command produces dynamic executables
instead of the intended (but not well noted in the Makefile)
static executables. This commit includes changes noted in
upstream `golang/go` issues which appear to work as intended
for others.

- refs GH-94
- refs golang/go#38789
- refs golang/go#26492
atc0005 added a commit to atc0005/check-mail that referenced this issue Oct 3, 2020
The previous build command produces dynamic executables
instead of the intended (but not well noted in the Makefile)
static executables. This commit includes changes noted in
upstream `golang/go` issues which appear to work as intended
for others.

- refs GH-94
- refs golang/go#38789
- refs golang/go#26492
@golang golang locked and limited conversation to collaborators May 1, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge GoCommand cmd/go NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

3 participants