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/cgo, cmd/link: with zig as CC/CXX, Go linker does not put libc onto the linker line, causing undefined symbol errors #52690

Closed
andrewrk opened this issue May 3, 2022 · 31 comments
Labels
FrozenDueToAge help wanted NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@andrewrk
Copy link

andrewrk commented May 3, 2022

Corresponding Zig issue: ziglang/zig#11398

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

$ go version
go version go1.18.1 linux/amd64

Does this issue reproduce with the latest release?

I only tested with go1.18.1.

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

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/andy/.cache/go-build"
GOENV="/home/andy/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/andy/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/andy/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/nix/store/qyc0w8vsikzmbdy97gb68l2ri1jzqp9v-go-1.18.1/share/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/nix/store/qyc0w8vsikzmbdy97gb68l2ri1jzqp9v-go-1.18.1/share/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.18.1"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
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=/run/user/1000/go-build3829224601=/tmp/go-build -gno-record-gcc-switches"

What did you do?

go.mod:

module test

go 1.18

foo.go:

package test

func foo() {}

foo_test.go:

package test

import (
	"testing"
)

func TestFoo(t *testing.T) {
	foo()
}

Then use zig cc as the C toolchain for go test with race detection:

CGO_ENABLED=1 CC="zig cc" go test -race test

Zig Version 0.10.0-dev.2052+3cfde183f

What did you expect to see?

This should work, as it does without -race.

What did you see instead?

We get errors from the Go linker:

# test.test
runtime/race(.text): relocation target getuid not defined
runtime/race(.text): relocation target pthread_self not defined
runtime/race(.text): relocation target sleep not defined
runtime/race(.text): relocation target usleep not defined
runtime/race(.text): relocation target abort not defined
runtime/race(.text): relocation target isatty not defined
runtime/race(.text): relocation target pthread_attr_getstack not defined
runtime/race(.text): relocation target sigaction not defined
runtime/race(.text): relocation target getrusage not defined
runtime/race(.text): relocation target syslog not defined
runtime/race(.text): relocation target confstr not defined
runtime/race(.text): relocation target getrlimit not defined
runtime/race(.text): relocation target pipe not defined
runtime/race(.text): relocation target sched_getaffinity not defined
runtime/race(.text): relocation target __sched_cpucount not defined
runtime/race(.text): relocation target pthread_attr_init not defined
runtime/race(.text): relocation target pthread_getattr_np not defined
runtime/race(.text): relocation target pthread_attr_destroy not defined
runtime/race(.text): relocation target exit not defined
runtime/race(.text): relocation target sysconf not defined
runtime/race(.text): relocation target setrlimit not defined
/home/kmicklas/go/pkg/tool/linux_amd64/link: too many errors
FAIL	test [build failed]
FAIL

Notes

Related issue: #44695

It appears that cgo has asked the C compiler to compile C source files which contain dependencies on libc symbols, however the Go linker is not actually putting libc onto the linker line, causing these undefined symbol errors.

It does compile and run successfully using -linkmode external, however, I don't see why it shouldn't work with the Go linker as well, given that zig cc produces standard ELF object files (same as Clang and GCC).

It looks to me like the fix is simple: the Go linker needs to put libc onto the linker line when it is linking objects that contain libc dependencies.

@ianlancetaylor
Copy link
Contributor

With compilers like GCC and clang, the compiler links against the C library by default. Does zig cc not work that way? What happens if I write zig cc -o hello hello.o?

@andrewrk
Copy link
Author

andrewrk commented May 3, 2022

zig cc does work this way. In your example code, zig cc is being used as the linker, and in fact as noted above, with -linkmode external this issue is not present because zig cc is being used as the linker. However, the issue occurs because Go is using Go as the linker and not putting libc on the linker line.

@ianlancetaylor
Copy link
Contributor

Thanks. The Go linker never links directly against the C library. This normally works because the Go build decides that getuid and friends come from the libc.so shared C library. Does zig cc link statically by default?

@andrewrk
Copy link
Author

andrewrk commented May 3, 2022

zig cc follows the same static/dynamic linking rules as clang and gcc; it shares the exact same command line API. On glibc-based systems, GCC, Clang, and zig cc all link dynamically against libc.so by default:

andy@ark ~/tmp> gcc -o hello hello.c
andy@ark ~/tmp> ldd hello
	linux-vdso.so.1 (0x00007ffc9f3df000)
	libc.so.6 => /nix/store/g02b1lpbddhymmcjb923kf0l7s9nww58-glibc-2.33-123/lib/libc.so.6 (0x00007f13b9dec000)
	/nix/store/g02b1lpbddhymmcjb923kf0l7s9nww58-glibc-2.33-123/lib/ld-linux-x86-64.so.2 => /nix/store/g02b1lpbddhymmcjb923kf0l7s9nww58-glibc-2.33-123/lib64/ld-linux-x86-64.so.2 (0x00007f13b9fc3000)
andy@ark ~/tmp> clang -o hello hello.c
andy@ark ~/tmp> ldd hello
	linux-vdso.so.1 (0x00007ffd177ab000)
	libc.so.6 => /nix/store/g02b1lpbddhymmcjb923kf0l7s9nww58-glibc-2.33-123/lib/libc.so.6 (0x00007fc1ef774000)
	/nix/store/g02b1lpbddhymmcjb923kf0l7s9nww58-glibc-2.33-123/lib/ld-linux-x86-64.so.2 => /nix/store/g02b1lpbddhymmcjb923kf0l7s9nww58-glibc-2.33-123/lib64/ld-linux-x86-64.so.2 (0x00007fc1ef94b000)
andy@ark ~/tmp> zig cc -o hello hello.c
andy@ark ~/tmp> ldd hello
	linux-vdso.so.1 (0x00007fff1d5f7000)
	libc.so.6 => /nix/store/g02b1lpbddhymmcjb923kf0l7s9nww58-glibc-2.33-123/lib/libc.so.6 (0x00007ff3ec3ae000)
	/nix/store/g02b1lpbddhymmcjb923kf0l7s9nww58-glibc-2.33-123/lib/ld-linux-x86-64.so.2 => /nix/store/g02b1lpbddhymmcjb923kf0l7s9nww58-glibc-2.33-123/lib64/ld-linux-x86-64.so.2 (0x00007ff3ec585000)

A typical linker line for any C compiler will look something like this:

ld -m elf_x86_64 -o hello Scrt1.o crti.o hello.o libcompiler_rt.a libm.so.6 libpthread.so.0 libc.so.6 libdl.so.2 librt.so.1 libld.so.2 libutil.so.1 libc_nonshared.a crtn.o

In this example, hello.o contains libc dependencies, but it is the linker which satisfies them by putting libc on the linker line, as you can see.

I'm not sure what you mean when you say the Go linker never links directly against the C library. Indeed, getuid and friends come from the libc.so shared C library, as you can see above, but in this issue, the Go linker is omitting libc.so from the list of objects to link, causing the undefined symbol errors.

We can simulate this same problem with any C compiler by passing -nostdlib, causing the linker driver to omit libc.so from the linker line, as Go is doing:

andy@ark ~/tmp> clang -o hello hello.c -nostdlib
/nix/store/b987cpz6k72fkp05ycbhvk635y46m3cc-binutils-2.35.2/bin/ld: /tmp/hello-d74816.o: in function `main':
hello.c:(.text+0x15): undefined reference to `printf'
clang-7: error: linker command failed with exit code 1 (use -v to see invocation)

Ultimately, the Go toolchain is compiling C source files into object files which contain libc dependencies. If any C compiler is used to then link these together, everything works fine, because C compilers put libc onto the linker line. However, when the Go linker is used, which is the default, it does not satisfy its own dependencies.

I think one thing that would shed some light on this issue would be seeing, side by side, the Go linker line when CC=clang is used vs CC="zig cc". I spent a couple hours trying to obtain this information but did not figure out how to do it.

@zikaeroh
Copy link
Contributor

zikaeroh commented May 3, 2022

I think what you're looking for is -ldflags="-linkmode=external -v", which prints a "host link" log line with arguments for me. If you also pass -x to go build, you'll also get all of the commands that go ran to build (including the flags passed to cmd/link), if you want to see even more of the process.

(I'm pretty sure this is the same as #44695, but whichever gets the most traction works for me 😄)

@zikaeroh
Copy link
Contributor

zikaeroh commented May 3, 2022

With gcc as the linker:

# some.tld/go44695
HEADER = -H5 -T0x401000 -R0x1000
host link: "gcc" "-m64" "-o" "/tmp/go-build298697425/b001/exe/a.out" "-rdynamic" "-Wl,--compress-debug-sections=zlib-gnu" "/tmp/go-link-1343527236/go.o" "/tmp/go-link-1343527236/000000.o" "/tmp/go-link-1343527236/000001.o" "/tmp/go-link-1343527236/000002.o" "/tmp/go-link-1343527236/000003.o" "/tmp/go-link-1343527236/000004.o" "/tmp/go-link-1343527236/000005.o" "/tmp/go-link-1343527236/000006.o" "/tmp/go-link-1343527236/000007.o" "/tmp/go-link-1343527236/000008.o" "/tmp/go-link-1343527236/000009.o" "/tmp/go-link-1343527236/000010.o" "/tmp/go-link-1343527236/000011.o" "/tmp/go-link-1343527236/000012.o" "/tmp/go-link-1343527236/000013.o" "/tmp/go-link-1343527236/000014.o" "/tmp/go-link-1343527236/000015.o" "/tmp/go-link-1343527236/000016.o" "/tmp/go-link-1343527236/000017.o" "-g" "-O2" "-g" "-O2" "-lpthread" "-no-pie"
174990 symbols, 42726 reachable
	67777 package symbols, 70621 hashed symbols, 29608 non-package symbols, 6984 external symbols
139482 liveness data

clang as the linker:

# some.tld/go44695
HEADER = -H5 -T0x401000 -R0x1000
host link: "clang" "-m64" "-o" "/tmp/go-build328077678/b001/exe/a.out" "-rdynamic" "-Qunused-arguments" "-Wl,--compress-debug-sections=zlib-gnu" "/tmp/go-link-2078635705/go.o" "/tmp/go-link-2078635705/000000.o" "/tmp/go-link-2078635705/000001.o" "/tmp/go-link-2078635705/000002.o" "/tmp/go-link-2078635705/000003.o" "/tmp/go-link-2078635705/000004.o" "/tmp/go-link-2078635705/000005.o" "/tmp/go-link-2078635705/000006.o" "/tmp/go-link-2078635705/000007.o" "/tmp/go-link-2078635705/000008.o" "/tmp/go-link-2078635705/000009.o" "/tmp/go-link-2078635705/000010.o" "/tmp/go-link-2078635705/000011.o" "/tmp/go-link-2078635705/000012.o" "/tmp/go-link-2078635705/000013.o" "/tmp/go-link-2078635705/000014.o" "/tmp/go-link-2078635705/000015.o" "/tmp/go-link-2078635705/000016.o" "/tmp/go-link-2078635705/000017.o" "-g" "-O2" "-g" "-O2" "-lpthread" "-no-pie"
174990 symbols, 42726 reachable
	67777 package symbols, 70621 hashed symbols, 29608 non-package symbols, 6984 external symbols
139482 liveness data

zig cc as the linker:

# some.tld/go44695
HEADER = -H5 -T0x401000 -R0x1000
host link: "zig" "cc" "-m64" "-o" "/tmp/go-build1740275156/b001/exe/a.out" "-rdynamic" "/tmp/go-link-2842320631/go.o" "/tmp/go-link-2842320631/000000.o" "/tmp/go-link-2842320631/000001.o" "/tmp/go-link-2842320631/000002.o" "/tmp/go-link-2842320631/000003.o" "/tmp/go-link-2842320631/000004.o" "/tmp/go-link-2842320631/000005.o" "/tmp/go-link-2842320631/000006.o" "/tmp/go-link-2842320631/000007.o" "/tmp/go-link-2842320631/000008.o" "/tmp/go-link-2842320631/000009.o" "/tmp/go-link-2842320631/000010.o" "/tmp/go-link-2842320631/000011.o" "/tmp/go-link-2842320631/000012.o" "/tmp/go-link-2842320631/000013.o" "/tmp/go-link-2842320631/000014.o" "/tmp/go-link-2842320631/000015.o" "/tmp/go-link-2842320631/000016.o" "/tmp/go-link-2842320631/000017.o" "-g" "-O2" "-g" "-O2" "-lpthread"
174943 symbols, 42726 reachable
	67777 package symbols, 70621 hashed symbols, 29608 non-package symbols, 6937 external symbols
139482 liveness data

The flags are nearly identical, and none mention libc in any way.

@ianlancetaylor
Copy link
Contributor

ianlancetaylor commented May 3, 2022

I'm not sure what you mean when you say the Go linker never links directly against the C library.

I mean literally that. The Go linker never opens the C library.

Indeed, getuid and friends come from the libc.so shared C library, as you can see above, but in this issue, the Go linker is omitting libc.so from the list of objects to link, causing the undefined symbol errors.

In the GCC case, the cgo tool is run against runtime/cgo and runtime/race. This happens when building those packages, not at link time. Among other things, cgo runs a C link to produce a temporary executable. It examines that executable for references to symbols defined in shared libraries. It passes a list of those symbols and the corresponding shared libraries to the Go linker. The Go linker uses that to build a dynamic symbol table that tells the dynamic linker (ld.so) how to satisfy those symbol references.

Somehow that is failing when using zig cc but I don't know how.

@motiejus
Copy link
Contributor

motiejus commented May 4, 2022

Data point: the _cgo_.o intermediate object files are very different across clang-13 and zig cc.

I am comparing workdirs of CC="zig cc" vs CC="clang-13" with this script:

#!/bin/bash
set -xeuo pipefail

_collect() {
    local slug="${CC/ /-}"
    local workdir="work-${slug}"
    local logfile="${slug}.log"
    rm -fr ~/.cache/go-build "$workdir"
    env CGO_ENABLED=1 CC="$CC" \
        GOMAXPROCS=1 \
        go test -ldflags="-v" -work -x -race test >& "$logfile" || :

    # contains line WORK=...
    . <(head -1 "$logfile")
    mv "$WORK" "$workdir"
}

CC="zig cc" _collect
CC="clang-13" _collect

This is how go builds the object for runtime/cgo, to $WORK/b079/_cgo_.o

TERM='dumb' zig cc -I /usr/local/go/src/runtime/race -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=$WORK/b079=/tmp/go-build -gno-record-gcc-switches -o $WORK/b079/_cgo_.o $WORK/b079/_cgo_main.o $WORK/b079/_x001.o $WORK/b079/_x002.o /usr/local/go/src/runtime/race/race_linux_amd64.syso -g -O2

(ditto for clang-13)

TERM='dumb' clang-13 -I /usr/local/go/src/runtime/race -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=$WORK/b079=/tmp/go-build -gno-record-gcc-switches -o $WORK/b079/_cgo_.o $WORK/b079/_cgo_main.o $WORK/b079/_x001.o $WORK/b079/_x002.o /usr/local/go/src/runtime/race/race_linux_amd64.syso -g -O2

Result: the zig-cc one is very small, and contains just a couple of symbols, and no references to libc ones:

motiejus ~/x/race $ nm work-zig-cc/b079/_cgo_.o
00000000002014d0 T _cgo_allocate
00000000002014e0 T _cgo_panic
00000000002014f0 T _cgo_reginit
00000000002014b0 T _cgo_release_context
00000000002014c0 T _cgo_topofstack
00000000002014a0 T _cgo_wait_runtime_init_done
0000000000201490 T crosscall2
00000000002025a8 d _DYNAMIC
000000000020159c t _fini
00000000002036c8 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000201584 t _init
0000000000201450 t __init_array_end
0000000000201450 t __init_array_start
0000000000201580 T __libc_csu_fini
0000000000201500 T __libc_csu_init
                 U __libc_start_main
0000000000201480 T main
0000000000201450 T _start

The clang-13 is much bigger, and contains references to libc:

motiejus ~/x/race $ nm work-clang-13/b079/_cgo_.o | wc -l
910
motiejus ~/x/race $ nm work-clang-13/b079/_cgo_.o | grep GLIBC
                 U abort@GLIBC_2.2.5
                 U confstr@GLIBC_2.2.5
                 U dl_iterate_phdr@GLIBC_2.2.5
                 U __errno_location@GLIBC_2.2.5
                 U exit@GLIBC_2.2.5
                 U getrlimit@GLIBC_2.2.5
                 U getrusage@GLIBC_2.2.5
                 U getuid@GLIBC_2.2.5
                 U isatty@GLIBC_2.2.5
                 U __libc_start_main@GLIBC_2.2.5
                 U pipe@GLIBC_2.2.5
                 U pthread_attr_destroy@GLIBC_2.2.5
                 U pthread_attr_getstack@GLIBC_2.2.5
                 U pthread_attr_init@GLIBC_2.2.5
                 U pthread_getattr_np@GLIBC_2.2.5
                 U pthread_self@GLIBC_2.2.5
                 U __sched_cpucount@GLIBC_2.6
                 U sched_getaffinity@GLIBC_2.3.4
                 U sched_yield@GLIBC_2.2.5
                 U setrlimit@GLIBC_2.2.5
                 U sigaction@GLIBC_2.2.5
                 U sleep@GLIBC_2.2.5
                 U sysconf@GLIBC_2.2.5
                 U syslog@GLIBC_2.2.5
                 U usleep@GLIBC_2.2.5

Digging ...

@andrewrk
Copy link
Author

andrewrk commented May 4, 2022

Thanks for the clues everyone.

cgo runs a C link to produce a temporary executable. It examines that executable for references to symbols defined in shared libraries. It passes a list of those symbols and the corresponding shared libraries to the Go linker. The Go linker uses that to build a dynamic symbol table that tells the dynamic linker (ld.so) how to satisfy those symbol references.

Aha, I think we have almost gotten to the bottom of this. This strategy means that the temporary executable needs to be exemplary in terms of linking to libc. If, for instance, the temporary executable happened to have advanced linker optimizations enabled, garbage collecting unused libc dependencies, then Go's strategy of using it as an example of how to link to libc would not work.

In order to avoid this situation, Go would need to make sure this temporary executable had libc function calls to all the needed symbols.

One way to test this hypothesis would be with the following patch to Zig:

--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -1691,9 +1691,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
                 argv.appendAssumeCapacity(arg);
             }
 
-            if (!as_needed) {
-                argv.appendAssumeCapacity("--as-needed");
-                as_needed = true;
+            if (as_needed) {
+                argv.appendAssumeCapacity("--no-as-needed");
+                as_needed = false;
             }
 
             // libc++ dep

However, I want to stress that using --as-needed for libc symbols is a perfectly legal optimization for Zig to make, and a proper solution would mean Go including actual symbol dependencies on the libc functions that are needed when creating the temporary executable. In other words the C source code for the temporary executable needs to have dummy calls to getuid, pthread_self, sleep, and every other libc function that cgo/race code wants to call.

@motiejus
Copy link
Contributor

motiejus commented May 4, 2022

The patch doesn't help: the linker flag gets added, but the resulting intermediate _cgo_.o still lacks the glibc symbols.

I've extracted the zig cc command, added -v, purged zig cache. Here is the resulting zig cc -v output of combining that file:

motiejus ~/x/race $ TERM='dumb' /home/motiejus/code/zig/build/zig cc -v -I /usr/local/go/src/runtime/race -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=$WORK/b079=/tmp/go-build -gno-record-gcc-switches -o $WORK/b079/_cgo_.o $WORK/b079/_cgo_main.o $WORK/b079/_x001.o
 $WORK/b079/_x002.o /usr/local/go/src/runtime/race/race_linux_amd64.syso -g -O2
ld.lld -r -error-limit=0 -O3 -s -m elf_x86_64 -static -o /home/motiejus/.cache/zig/o/91b96c8f38a568cc8b1b3e8332fe1b2a/crti.o /home/motiejus/.cache/zig/o/58045fff5ef1b611af2c16ef4e58f359/crti.o
ld.lld -r -error-limit=0 -O3 -s -m elf_x86_64 -static -o /home/motiejus/.cache/zig/o/2b6be64219df30475dcacb8367694020/crtn.o /home/motiejus/.cache/zig/o/870e26b625ee1c9772895a1fddf09d67/crtn.o
ld.lld -r -error-limit=0 -O3 -s -m elf_x86_64 -static -o /home/motiejus/.cache/zig/o/fd5a6c8e022865ea653050e7d424be3c/Scrt1.o /home/motiejus/.cache/zig/o/57fe1256d14eae680970384f17905956/start-2.33.o /home/motiejus/.cache/zig/o/8c85e058308f477ec91b8985d8f4c424/abi-note.o
ar rcs /home/motiejus/.cache/zig/o/80c22cbf6b3eaf4d8a98165e54c56362/libc_nonshared.a /home/motiejus/.cache/zig/o/6da1183bf34802781be50f033c0dc8fb/atexit.o /home/motiejus/.cache/zig/o/14366b018930963137551512b6ff7f9b/at_quick_exit.o /home/motiejus/.cache/zig/o/0435e34094e802b6b9094600fb40a8d4/pthread_atfork.o /home/motiejus/.cache/zig/o/a938a0cc359416b5242ccf11dbf4e8b7/stack_chk_fail_local.o /home/motiejus/.cache/zig/o/05e0c9400de4e9b9a2fd9cad643eaf46/errno.o /home/motiejus/.cache/zig/o/3f3b2fa88360c6f2709304ed414a1e64/elf-init-2.33.o /home/motiejus/.cache/zig/o/9073bc2189d97a928cec22d11aa1c2ec/stat.o /home/motiejus/.cache/zig/o/243b9ef98c561938c663e48cb9fe37e6/fstat.o /home/motiejus/.cache/zig/o/c62b463acc22fc8f3f9a6aebedc1a4cf/lstat.o /home/motiejus/.cache/zig/o/9ed7e253d0c0850dfc125b598ae93543/stat64.o /home/motiejus/.cache/zig/o/b1a9086ecf04276c9d0ed9b4164e89f3/fstat64.o /home/motiejus/.cache/zig/o/3ce5f80df2ed924c693130bf03643317/lstat64.o /home/motiejus/.cache/zig/o/c2b6fbcf844186e09efce31992786903/fstatat.o /home/motiejus/.cache/zig/o/17bcf947c9f2a5fabd7aebbceab88732/fstatat64.o /home/motiejus/.cache/zig/o/97412572c8facabb00517c70006680fb/mknodat.o /home/motiejus/.cache/zig/o/5eead55743586901ad12776a208ab1c2/mknod.o /home/motiejus/.cache/zig/o/ed013cfd3317240de811014a8bfaee60/stat_t64_cp.o
ld.lld -error-limit=0 -O3 --gc-sections -s -m elf_x86_64 -shared -o /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/libm.so.6 -soname libm.so.6 -version-script /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/all.map /home/motiejus/.cache/zig/o/314cdab16cda146564952d0189798c1f/m.o --as-needed --no-as-needed --allow-shlib-undefined
ld.lld -error-limit=0 -O3 --gc-sections -s -m elf_x86_64 -shared -o /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/libpthread.so.0 -soname libpthread.so.0 -version-script /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/all.map /home/motiejus/.cache/zig/o/f2c227c87fe510e09281643a20d61673/pthread.o --as-needed --no-as-needed --allow-shlib-undefined
ld.lld -error-limit=0 -O3 --gc-sections -s -m elf_x86_64 -shared -o /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/libc.so.6 -soname libc.so.6 -version-script /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/all.map /home/motiejus/.cache/zig/o/0d9f96c191fd716d028af63e0afbafa8/c.o --as-needed --no-as-needed --allow-shlib-undefined
ld.lld -error-limit=0 -O3 --gc-sections -s -m elf_x86_64 -shared -o /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/libdl.so.2 -soname libdl.so.2 -version-script /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/all.map /home/motiejus/.cache/zig/o/a0a3c156409f43b4977c043cf49b555d/dl.o --as-needed --no-as-needed --allow-shlib-undefined
ld.lld -error-limit=0 -O3 --gc-sections -s -m elf_x86_64 -shared -o /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/librt.so.1 -soname librt.so.1 -version-script /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/all.map /home/motiejus/.cache/zig/o/6248fb0c9383e8ffeb5e393255e6990d/rt.o --as-needed --no-as-needed --allow-shlib-undefined
ld.lld -error-limit=0 -O3 --gc-sections -s -m elf_x86_64 -shared -o /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/libld.so.2 -soname ld-linux-x86-64.so.2 -version-script /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/all.map /home/motiejus/.cache/zig/o/7e0596190876301e19191e76f01ae3a3/ld.o --as-needed --no-as-needed --allow-shlib-undefined
ld.lld -error-limit=0 -O3 --gc-sections -s -m elf_x86_64 -shared -o /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/libutil.so.1 -soname libutil.so.1 -version-script /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/all.map /home/motiejus/.cache/zig/o/77380b63a792d807811009994ee4fadf/util.o --as-needed --no-as-needed --allow-shlib-undefined
ar rcs /home/motiejus/.cache/zig/o/cff27c0f8922543f0abbb2040c54353e/libcompiler_rt.a /home/motiejus/.cache/zig/o/cff27c0f8922543f0abbb2040c54353e/compiler_rt.o
ld.lld -error-limit=0 -O3 -z stack-size=16777216 --gc-sections --eh-frame-hdr -m elf_x86_64 -o /home/motiejus/.cache/zig/o/b4138bfd013b47c91024e05b06a68ea5/_cgo_.o /home/motiejus/.cache/zig/o/fd5a6c8e022865ea653050e7d424be3c/Scrt1.o /home/motiejus/.cache/zig/o/91b96c8f38a568cc8b1b3e8332fe1b2a/crti.o -L /usr/local/lib64 -L /usr/local/lib -L /usr/lib/x86_64-linux-gnu -L /lib64 -L /lib -L /usr/lib64 -L /usr/lib -L /lib/x86_64-linux-gnu -dynamic-linker /lib64/ld-linux-x86-64.so.2 /tmp/go-build2893123627/b079/_cgo_main.o /tmp/go-build2893123627/b079/_x001.o /tmp/go-build2893123627/b079/_x002.o /usr/local/go/src/runtime/race/race_linux_amd64.syso /home/motiejus/.cache/zig/o/cff27c0f8922543f0abbb2040c54353e/libcompiler_rt.a --as-needed --no-as-needed /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/libm.so.6 /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/libpthread.so.0 /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/libc.so.6 /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/libdl.so.2 /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/librt.so.1 /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/libld.so.2 /home/motiejus/.cache/zig/o/3a1193ad8830067188265e81a8a1b846/libutil.so.1 /home/motiejus/.cache/zig/o/80c22cbf6b3eaf4d8a98165e54c56362/libc_nonshared.a /home/motiejus/.cache/zig/o/2b6be64219df30475dcacb8367694020/crtn.o

Verbose clang-13 linker:

motiejus ~/x/race $ TERM='dumb' clang-13 -v -I /usr/local/go/src/runtime/race -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=$WORK/b079=/tmp/go-build -gno-record-gcc-switches -o $WORK/b079/_cgo_.o $WORK/b079/_cgo_main.o $WORK/b079/_x001.o $WORK/b079/_x002.o /usr/local/go/src/runtime/race/race_linux_amd64.syso -g -O2
Debian clang version 13.0.1-++20220126092033+75e33f71c2da-1~exp1~20220126212112.63
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/10
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/10
Candidate multilib: .;@m64
Selected multilib: .;@m64
 "/usr/bin/ld" --hash-style=both --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o /tmp/go-build3943283512/b079/_cgo_.o /lib/x86_64-linux-gnu/crt1.o /lib/x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/10/crtbegin.o -L/usr/bin/../lib/gcc/x86_64-linux-gnu/10 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../lib64 -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib64 -L/usr/lib/llvm-13/bin/../lib -L/lib -L/usr/lib /tmp/go-build3943283512/b079/_cgo_main.o /tmp/go-build3943283512/b079/_x001.o /tmp/go-build3943283512/b079/_x002.o /usr/local/go/src/runtime/race/race_linux_amd64.syso -lgcc --as-needed -lgcc_s --no-as-needed -lpthread -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/bin/../lib/gcc/x86_64-linux-gnu/10/crtend.o /lib/x86_64-linux-gnu/crtn.o

However, I want to stress that using --as-needed for libc symbols is a perfectly legal optimization for Zig to make,

I think it will be fair to talk more about this when we get to the bottom of the problem (and a workaround). :)

@motiejus
Copy link
Contributor

motiejus commented May 4, 2022

It's --gc-sections:

$ CGO_ENABLED=1 CC="zig cc -Wl,--no-gc-sections" go test  -race
testing
PASS
ok      test    0.018s

@motiejus
Copy link
Contributor

motiejus commented May 4, 2022

Adding --print-unused-sections to the linker line prints:

removing unused section /home/motiejus/.cache/zig/o/466e75650350030c221ee851caa5092f/Scrt1.o:(.data)                                                                                                                                                                                                                                                                                                                                                                                                                           
removing unused section /home/motiejus/.cache/zig/o/94127ccfce64f0a53722b58cfee94ed6/crti.o:(.text)                                                                                                                                                                                                                                                                                                                                                                                                                            
removing unused section /tmp/go-build565131511/b079/_x001.o:(.text)                                                                                                                                                                                                                                                            
removing unused section /tmp/go-build565131511/b079/_x002.o:(.text)                                                                                                                                                                                                                                                                                                          
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text)                                                                                                                                                                                                                                                                                                                                                      
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data)                                                                                                                                                                                                                                                                                         
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.bss)                                                                                                                                                                                                                                            
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer10DDCallback6UnwindEv)                                                                                                                                                                                            
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer10DDCallback6UnwindEv)                                                                                                                                                                                                                                                                                                                                                                                                     
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer10DDCallback9UniqueTidEv)                                                                                                                                                                                                                                                                                                                                                                                         
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer10DDCallback9UniqueTidEv)                                                                                                                                                                                                                                                                                                                                                                                                  
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer9DDetector20CreatePhysicalThreadEv)                                                                                                                                                                                                                             
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer9DDetector20CreatePhysicalThreadEv)                                                                                                                                                                                                                                      
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer9DDetector21DestroyPhysicalThreadEPNS_16DDPhysicalThreadE)                                                                                                                                                                                                      
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer9DDetector21DestroyPhysicalThreadEPNS_16DDPhysicalThreadE)                                                                                                                                                                                                               
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer9DDetector19CreateLogicalThreadEy)                                                                                                                                                                                                                              
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer9DDetector19CreateLogicalThreadEy)                                                                                                                                                                                                                                       
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer9DDetector20DestroyLogicalThreadEPNS_15DDLogicalThreadE)                                                                                                                                                                                                        
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer9DDetector20DestroyLogicalThreadEPNS_15DDLogicalThreadE)                                                                                                                                                                                                                                                                              
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer9DDetector9MutexInitEPNS_10DDCallbackEPNS_7DDMutexE)                                                                                                                                                              
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer9DDetector9MutexInitEPNS_10DDCallbackEPNS_7DDMutexE)                                                                                                                                                                                                                     
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer9DDetector15MutexBeforeLockEPNS_10DDCallbackEPNS_7DDMutexEb)                                                                                                                                                                                                    
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer9DDetector15MutexBeforeLockEPNS_10DDCallbackEPNS_7DDMutexEb)                                                                                                                                                                                                             
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer9DDetector14MutexAfterLockEPNS_10DDCallbackEPNS_7DDMutexEbb)                                                                                                                                                                                                    
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer9DDetector14MutexAfterLockEPNS_10DDCallbackEPNS_7DDMutexEbb)                                                                                                                                                                                                             
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer9DDetector17MutexBeforeUnlockEPNS_10DDCallbackEPNS_7DDMutexEb)                                                                                                                                                                                                  
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer9DDetector17MutexBeforeUnlockEPNS_10DDCallbackEPNS_7DDMutexEb)                                                                                                                                                                                                           
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer9DDetector12MutexDestroyEPNS_10DDCallbackEPNS_7DDMutexE)                                                                                                                                                                                                        
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer9DDetector12MutexDestroyEPNS_10DDCallbackEPNS_7DDMutexE)                                                                                                                                                                                                                 
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer9DDetector9GetReportEPNS_10DDCallbackE)                                                                                                                                                                                                                                                                                      
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer9DDetector9GetReportEPNS_10DDCallbackE)                                                                                                                                                                                                                                  
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer17ThreadContextBase6OnDeadEv)                                                                                                                                                                                                                                   
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer17ThreadContextBase6OnDeadEv)                                                                                                                                                                                                                                                                                                         
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer17ThreadContextBase8OnJoinedEPv)                                                                                                                                                                                                                                                                                             
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer17ThreadContextBase8OnJoinedEPv)                                                                                                                                                                                                                                                                                                      
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer17ThreadContextBase10OnFinishedEv)                                                                                                                                                                                
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer17ThreadContextBase10OnFinishedEv)                                                                                                                                                                                                                                                                                                    
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer17ThreadContextBase9OnStartedEPv)                                                                                                                                                                                                                                                                                            
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer17ThreadContextBase9OnStartedEPv)                                                                                                                                                                                                                                                                                                     
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer17ThreadContextBase9OnCreatedEPv)                                                                                                                                                                                                                                                                                            
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer17ThreadContextBase9OnCreatedEPv)                                                                                                                                                                                                                                                                                                     
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer17ThreadContextBase7OnResetEv)                                                                                                                                                                                                                                                                                               
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer17ThreadContextBase7OnResetEv)                                                                                                                                                                                                                                                                                                        
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer17ThreadContextBase10OnDetachedEPv)                                                                                                                                                                               
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer17ThreadContextBase10OnDetachedEPv)                                                                                                                                                                                                                                                                                                   
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer15FlagHandlerBase5ParseEPKc)                                                                                                                                                                                                                                                                                                                                                                                      
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer15FlagHandlerBase5ParseEPKc)                                                                                                                                                                                                                                                                                                          
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer15FlagHandlerBase6FormatEPcm)                                                                                                                                                                                     
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer15FlagHandlerBase6FormatEPcm)                                                                                                                                                                                              
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer11FlagHandlerIPKcE5ParseES2_)                                                                                                                                                                                                                                                                                                                                                                                     
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer11FlagHandlerIPKcE5ParseES2_)                                                                                                                                                                                              
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely)                                                                                                                                                                                                                                                                                
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN6__tsan8Callback9UniqueTidEv)                                                                                                                                                                                                                                                                                                             
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN6__tsan8Callback9UniqueTidEv)                                                                                                                                                                                                                                                         
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer14SymbolizerTool14LateInitializeEv)                                                                                                                                                                                                                                                                                          
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer14SymbolizerTool14LateInitializeEv)                                                                                                                                                                                                                                                                                                   
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.rodata.str1.1)                                                                                                                                                                                                                                                                                                                                             
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.rodata.str1.8)                                                                                                                                                                                                                                                                                
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN6__tsan12MemoryAccessEPNS_11ThreadStateEmmibb)                                                                                                                                                                                                                                                                                                                                                                                 
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN6__tsan12MemoryAccessEPNS_11ThreadStateEmmibb)                                                                                                                                                                                                                                                                                                                                                                                          
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN6__tsan16MemoryAccessImplEPNS_11ThreadStateEmibbPyNS_6ShadowE)                                                                                                                                                                                                                                                                                                                                                                 
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN6__tsan16MemoryAccessImplEPNS_11ThreadStateEmibbPyNS_6ShadowE)                                                                                                                                                                                                                        
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN6__tsan9FuncEntryEPNS_11ThreadStateEm)                                                                                                                                                                                                                                                                                                                                                                                         
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN6__tsan9FuncEntryEPNS_11ThreadStateEm)                                                                                                                                                                                                                                                                                                                                                                                                  
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN6__tsan8FuncExitEPNS_11ThreadStateE)                                                                                                                                                                                                                                                                                                                                                                                           
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN6__tsan8FuncExitEPNS_11ThreadStateE)                                                                                                                                                                                                                                                                                                                                                                                                    
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.rodata)                                                                                                                                                                                                                                                                                                                                                                                                                                         
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer15StaticSpinMutex8LockSlowEv)                                                                                                                                                                                                                                                                                                                                                                                     
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer15StaticSpinMutex8LockSlowEv)                                                                                                                                                                                                                                                                                                                                                                                              
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer11FlagHandlerIbE5ParseEPKc)                                                                                                                                                                                                                                                                                                                                                                                       
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer11FlagHandlerIbE5ParseEPKc)                                                                                                                                                                                                                                                                                                                                                                                                
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer11FlagHandlerINS_16HandleSignalModeEE5ParseEPKc)                                                                                                                                                                                                                                                                                                                                                                  
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer11FlagHandlerINS_16HandleSignalModeEE5ParseEPKc)                                                                                                                                                                                                                                                                                                                                                                           
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer11FlagHandlerIiE5ParseEPKc)                                                                                                                                                                                                                                                                                                                                                                                       
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer11FlagHandlerIiE5ParseEPKc)                                                                                                                                                                                                                                                                                                                                                                                                
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer11FlagHandlerImE5ParseEPKc)                                                                                                                                                                                                                                                                                                  
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer11FlagHandlerImE5ParseEPKc)                                                                                                                                                                                                                                                                                                                                                                                                
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer11FlagHandlerIiE6FormatEPcm)                                                                                                                                                                                                                                                                                                 
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer11FlagHandlerIiE6FormatEPcm)                                                                                                                                                                                                                                                                                                                                                                                               
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer11FlagHandlerIPKcE6FormatEPcm)                                                                                                                                                                                                                                                                                                                                                                                    
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer11FlagHandlerIPKcE6FormatEPcm)                                                                                                                                                                                                                                                                                                                                                                                             
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer11FlagHandlerIbE6FormatEPcm)                                                                                                                                                                                                                                                                                                 
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer11FlagHandlerIbE6FormatEPcm)                                                                                                                                                                                                                                                                                                          
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer18FlagHandlerInclude6FormatEPcm)                                                                                                                                                                                                                                                                                             
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer18FlagHandlerInclude6FormatEPcm)                                                                                                                                                                                                                                                                                                      
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer11FlagHandlerImE6FormatEPcm)                                                                                                                                                                                                                                                                                                 
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer11FlagHandlerImE6FormatEPcm)                                                                                     
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer11FlagHandlerINS_16HandleSignalModeEE6FormatEPcm)                                                       
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer11FlagHandlerINS_16HandleSignalModeEE6FormatEPcm)                                                                
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZNK11__sanitizer20SuspendedThreadsList11GetThreadIDEm)                                                                 
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZNK11__sanitizer20SuspendedThreadsList11GetThreadIDEm)                                                                          
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZNK11__sanitizer20SuspendedThreadsList11ThreadCountEv)                                                                 
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZNK11__sanitizer20SuspendedThreadsList11ThreadCountEv)                                                                          
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZNK11__sanitizer20SuspendedThreadsList17GetRegistersAndSPEmPNS_18InternalMmapVectorImEEPm)                                                                                                                                                                                                                                                                                                                                       
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZNK11__sanitizer20SuspendedThreadsList17GetRegistersAndSPEmPNS_18InternalMmapVectorImEEPm)                                                                                                                                                                                                                                                                                                                                                
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer18FlagHandlerInclude5ParseEPKc)                                                                         
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer18FlagHandlerInclude5ParseEPKc)                                                                                  
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer14StackDepotBaseINS_14StackDepotNodeELi1ELi20EE3PutENS_10StackTraceEPb)                                                                                                                                                                                                                                                                                                                                           
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer14StackDepotBaseINS_14StackDepotNodeELi1ELi20EE3PutENS_10StackTraceEPb)                                                                                                                                                                                                                                                                                                                                                    
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer20SizeClassAllocator32INS_4AP32EE16PopulateFreeListEPNS_14AllocatorStatsEPNS_30SizeClassAllocator32LocalCacheIS2_EEPNS2_13SizeClassInfoEm)                                                                                                                                                                                                                                                                        
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer20SizeClassAllocator32INS_4AP32EE16PopulateFreeListEPNS_14AllocatorStatsEPNS_30SizeClassAllocator32LocalCacheIS2_EEPNS2_13SizeClassInfoEm)                                                                                                                                                                                                                                                                                 
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer20SizeClassAllocator32INS_4AP32EE13AllocateBatchEPNS_14AllocatorStatsEPNS_30SizeClassAllocator32LocalCacheIS2_EEm)                                                                                                                                                                                                                                                                                                
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer20SizeClassAllocator32INS_4AP32EE13AllocateBatchEPNS_14AllocatorStatsEPNS_30SizeClassAllocator32LocalCacheIS2_EEm)                                                                                                                                                                                                                                                                                                         
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer30SizeClassAllocator32LocalCacheINS_20SizeClassAllocator32INS_4AP32EEEE6RefillEPNS4_8PerClassEPS3_m)                                                                                                                                                                                                                                                                                                              
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer30SizeClassAllocator32LocalCacheINS_20SizeClassAllocator32INS_4AP32EEEE6RefillEPNS4_8PerClassEPS3_m)                                                                                                                                                                                                                                                                                                                       
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer30SizeClassAllocator32LocalCacheINS_20SizeClassAllocator32INS_4AP32EEEE5DrainEPNS4_8PerClassEPS3_m)                                                                                                                                                                                                                                                                                                               
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer30SizeClassAllocator32LocalCacheINS_20SizeClassAllocator32INS_4AP32EEEE5DrainEPNS4_8PerClassEPS3_m)                                                                                                                                                                                                                                                                                                                        
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer17CombinedAllocatorINS_20SizeClassAllocator32INS_4AP32EEENS_32LargeMmapAllocatorPtrArrayStaticEE10ReallocateEPNS_30SizeClassAllocator32LocalCacheIS3_EEPvmm)                                                                                                                                                                                                                                                      
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer17CombinedAllocatorINS_20SizeClassAllocator32INS_4AP32EEENS_32LargeMmapAllocatorPtrArrayStaticEE10ReallocateEPNS_30SizeClassAllocator32LocalCacheIS3_EEPvmm)                                                                                                                                                                                                                                                               
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN6__tsan8Callback6UnwindEv)                                                                                                                                                                                                                                                                                                                                                                                                     
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN6__tsan8Callback6UnwindEv)                                                                                                                                                                                                                                                                                                                                                                                                              
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text.unlikely._ZN11__sanitizer6VectorIN6__tsan10RacyStacksEE8PushBackERKS2_)                                                                                                                                                                                                                                                                                                                                                                    
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.text._ZN11__sanitizer6VectorIN6__tsan10RacyStacksEE8PushBackERKS2_)                                                                                                                                                                                                                                                                                                                                                                             
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.ro._ZTVN11__sanitizer10DDCallbackE)                                                                                                                                                                                                                                                                                                                                                                                                    
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.ro._ZTVN11__sanitizer9DDetectorE)                                                                                                                                                                                                                                                                                                                                                                                                      
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.ro._ZTVN11__sanitizer17ThreadContextBaseE)                                                                                                                                                                                                                                                                                                                                                                                             
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.ro._ZTVN11__sanitizer15FlagHandlerBaseE)                                                                                                                                                                                                                                                                                                                                                                                               
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.ro._ZTVN11__sanitizer11FlagHandlerIbEE)                                                                                                                                                                                                                                                                                                                                                                                                
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.ro._ZTVN11__sanitizer11FlagHandlerINS_16HandleSignalModeEEE)                                                                                                                                                                                                                                                                                                                                                                           
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.ro._ZTVN11__sanitizer11FlagHandlerIPKcEE)                                                                                                                                                                                                                                                                                                                                                                                              
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.ro._ZTVN11__sanitizer11FlagHandlerIiEE)                                                                                                                                
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.ro._ZTVN11__sanitizer11FlagHandlerImEE)                                                                                                                                
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.ro._ZTVN6__tsan8CallbackE)                                                                                                                                             
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.ro._ZTVN6__tsan13ThreadContextE)                                                                                                                                       
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.ro._ZTVN11__sanitizer2DDE)                                                                                                                                             
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.ro._ZTVN11__sanitizer18FlagHandlerIncludeE)                                                                                                                            
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.ro._ZTVN11__sanitizer20SuspendedThreadsListE)                                                                                                                          
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.ro._ZTVN11__sanitizer25SuspendedThreadsListLinuxE)                                                                                                                     
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel)                                                                                                                                                                       
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.data.rel.local)                                                                                                                                                                 
removing unused section /usr/local/go/src/runtime/race/race_linux_amd64.syso:(.rodata.cst16)                                                                                                                                                                   
removing unused section /home/motiejus/.cache/zig/o/09f3f90c2c8cb45a9ea08e615d2440aa/crtn.o:(.text)                                                                                                                                                            

motiejus added a commit to motiejus/zig that referenced this issue May 4, 2022
When building object files, `zig cc` will instruct lld to remove unused
sections via `--gc-sections`. This is problematic for cgo. Briefly, go
builds cgo executables as follows*:

1. build `_cgo_.o`, which links (on linux_amd64 systems) to
   `/usr/local/go/src/runtime/race/race_linux_amd64.syso`.
2. That `.syso` contains references to symbols from libc.

If the actual Go program uses at least one libc symbol, it will link
correctly. However, if Go is building a cgo executable, but without any
C code, the sections from `.syso` file will be garbage-collected,
leaving a `_cgo_.o` without any references to libc.

I assume the `gc_sections` is an optimization. If yes, then it makes
sense for the final executable, but not for the intermediate object. If
not, please correct me.

Quoting @andrewrk in [1]:

> The C source code for the temporary executable needs to have dummy
> calls to getuid, pthread_self, sleep, and every other libc function
> that cgo/race code wants to call.

I agree in this case. However, while we could potentially fix it for go,
I don't know how many other systems do that, which compilcates use of
`zig cc` for other projects. If we consider `zig cc` a drop-in clang
replacement (except for `-fsanitize=undefined`, which I tend to agree
with), then it should not be optimizing the intermediate object files.

I assume this was added as an optimization. If that's correct, let's
optimize the final executable, but not the intermediate objects.

Fixes ziglang#11398
Fixes golang/go#44695
Fixes golang/go#52690

[*]: Empirically observed with `CGO_ENABLED=1 go test -race -x -v`

[1]: golang/go#52690 (comment)
motiejus added a commit to motiejus/zig that referenced this issue May 4, 2022
When building object files, `zig cc` will instruct lld to remove unused
sections via `--gc-sections`. This is problematic cgo builds that don't
explicitly use C code. Briefly, go builds cgo executables as follows*:

1. build `_cgo_.o`, which links (on linux_amd64 systems) to
   `/usr/local/go/src/runtime/race/race_linux_amd64.syso`.
2. That `.syso` contains references to symbols from libc.

If the user program uses at least one libc symbol, it will link
correctly. However, if Go is building a cgo executable, but without C
code, the sections from `.syso` file will be garbage-collected, leaving
a `_cgo_.o` without any references to libc, causing the final linking
step to not link libc.

Until now, this could be worked around by `-linkmode external` flag to
`go build`. This causes Go to link the final executable using the
external linker (which implicitly links libc). However, that flag brings
in a whole different world of worms.

I assume the `gc_sections` is an optimization; I tried to re-add
`--gc-sections` to the final executable, but that didn't go well. I know
removing such an optimization may be contentious, so let's start the
discussion here. Quoting @andrewrk in [1] (it was about `--as-needed`,
but the point remains the same):

> The C source code for the temporary executable needs to have dummy
> calls to getuid, pthread_self, sleep, and every other libc function
> that cgo/race code wants to call.

I agree this is how it *should* work. However, while we could fix it for
go, I don't know how many other systems rely on that, and we'll never
know we've fixed the last one. The point is, GCC/Clang does not optimize
sections by default, and downstream tools rely on that. If we want to
consider `zig cc` a drop-in clang replacement (except for
`-fsanitize=undefined`, which I tend to agree with), then it should not
be optimizing the intermediate object files. Or at least have a very
prominent fine-print that this is happening, with ways to work around
it.

Fixes ziglang#11398
Fixes golang/go#44695
Fixes golang/go#52690

[*]: Empirically observed with `CGO_ENABLED=1 go test -race -x -v`

[1]: golang/go#52690 (comment)
@dr2chase dr2chase added this to the Backlog milestone May 4, 2022
@dr2chase dr2chase added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label May 4, 2022
motiejus added a commit to motiejus/zig that referenced this issue May 5, 2022
When building object files, `zig cc` will instruct lld to remove unused
sections via `--gc-sections`. This is problematic cgo builds that don't
explicitly use C code. Briefly, go builds cgo executables as follows*:

1. build `_cgo_.o`, which links (on linux_amd64 systems) to
   `/usr/local/go/src/runtime/race/race_linux_amd64.syso`.
2. That `.syso` contains references to symbols from libc.

If the user program uses at least one libc symbol, it will link
correctly. However, if Go is building a cgo executable, but without C
code, the sections from `.syso` file will be garbage-collected, leaving
a `_cgo_.o` without any references to libc, causing the final linking
step to not link libc.

Until now, this could be worked around by `-linkmode external` flag to
`go build`. This causes Go to link the final executable using the
external linker (which implicitly links libc). However, that flag brings
in a whole different world of worms.

I assume the `gc_sections` is an optimization; I tried to re-add
`--gc-sections` to the final executable, but that didn't go well. I know
removing such an optimization may be contentious, so let's start the
discussion here. Quoting @andrewrk in [1] (it was about `--as-needed`,
but the point remains the same):

> The C source code for the temporary executable needs to have dummy
> calls to getuid, pthread_self, sleep, and every other libc function
> that cgo/race code wants to call.

I agree this is how it *should* work. However, while we could fix it for
go, I don't know how many other systems rely on that, and we'll never
know we've fixed the last one. The point is, GCC/Clang does not optimize
sections by default, and downstream tools rely on that. If we want to
consider `zig cc` a drop-in clang replacement (except for
`-fsanitize=undefined`, which I tend to agree with), then it should not
be optimizing the intermediate object files. Or at least have a very
prominent fine-print that this is happening, with ways to work around
it.

Fixes ziglang#11398
Fixes golang/go#44695
Fixes golang/go#52690

[*]: Empirically observed with `CGO_ENABLED=1 go test -race -x -v`

[1]: golang/go#52690 (comment)
uhthomas pushed a commit to gmirror/bazel-zig-cc that referenced this issue May 5, 2022
`zig cc` emits `--gc-sections` for the linker, which is incompatbile
with what CGo thinks about linking.

This commit adds a workaround: it will add `--no-gc-sections` to the
linking step if the command is not specified (falling back to the
default behavior of gcc/clang).

Related: golang/go#52690
@ianlancetaylor
Copy link
Contributor

It would be fine with me if somebody wants to send a cgo patch that passes -Wl,--no-gc-sections, with a fallback if that option is not supported.

@ianlancetaylor ianlancetaylor added help wanted NeedsFix The path to resolution is known, but the work has not been done. and removed NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels May 6, 2022
@andrewrk
Copy link
Author

andrewrk commented May 7, 2022

I think that would work fine but, any reason not to take my suggestion of having the C source code for the temporary executable make a call to any libc function? Seems like that would be more technically robust and avoid introducing logic for detecting available linker options.

@ianlancetaylor
Copy link
Contributor

In general we would need to call the function with the correct argument types, as compilers know about an increasing number of functions and will complain if they are misused. That might be kind of painful. But if someone can make that work, then, sure, that is fine with me.

@motiejus
Copy link
Contributor

motiejus commented May 7, 2022

How about assigning the function addresses to a void * and making sure assignments are not optimized out? That does not necessitate knowing their argument types.

@ianlancetaylor
Copy link
Contributor

Worth a try.

@kristoff-it
Copy link

kristoff-it commented May 8, 2022

All you have to do is use one symbol referenced by the dynamic symbol table, adding print("hi go") in main will be enough to prevent the table from being potentially removed by optimizing compilers.

@gopherbot
Copy link

Change https://go.dev/cl/407216 mentions this issue: cmd/dist: support spaces and quotes in CC

motiejus added a commit to motiejus/go that referenced this issue May 20, 2022
zig cc passes `--gc-sections` to the underlying linker, which then
causes undefined symbol errors when compiling with cgo but without C
code. Add `-Wl,--no-gc-sections` to make it work with zig cc. Minimal
example:

**main.go**

    package main
    import _ "runtime/cgo"
    func main() {}

Run (works after the patch, doesn't work before):

    CC="zig cc" go build main.go

Among the existing code, `src/runtime/testdata/testprognet` fails to
build:

    src/runtime/testdata/testprognet$ CC="zig cc" go build .
    net(.text): relocation target __errno_location not defined
    net(.text): relocation target getaddrinfo not defined
    net(.text): relocation target freeaddrinfo not defined
    net(.text): relocation target gai_strerror 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_create not defined
    runtime/cgo(.text): relocation target nanosleep not defined
    runtime/cgo(.text): relocation target pthread_detach not defined
    runtime/cgo(.text): relocation target stderr not defined
    runtime/cgo(.text): relocation target strerror not defined
    runtime/cgo(.text): relocation target fprintf 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 pthread_cond_broadcast not defined
    runtime/cgo(.text): relocation target malloc not defined

With the patch both examples build as expected.

@ianlancetaylor suggested:

> It would be fine with me if somebody wants to send a cgo patch that
passes -Wl,--no-gc-sections, with a fallback if that option is not
supported.

... and this is what we are doing. Tested with zig
0.10.0-dev.2252+a4369918b

Fixes golang#52690
motiejus added a commit to motiejus/go that referenced this issue May 20, 2022
zig cc passes `--gc-sections` to the underlying linker, which then
causes undefined symbol errors when compiling with cgo but without C
code. Add `-Wl,--no-gc-sections` to make it work with zig cc. Minimal
example:

**main.go**

    package main
    import _ "runtime/cgo"
    func main() {}

Run (works after the patch, doesn't work before):

    CC="zig cc" go build main.go

Among the existing code, `src/runtime/testdata/testprognet` fails to
build:

    src/runtime/testdata/testprognet$ CC="zig cc" go build .
    net(.text): relocation target __errno_location not defined
    net(.text): relocation target getaddrinfo not defined
    net(.text): relocation target freeaddrinfo not defined
    net(.text): relocation target gai_strerror 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_create not defined
    runtime/cgo(.text): relocation target nanosleep not defined
    runtime/cgo(.text): relocation target pthread_detach not defined
    runtime/cgo(.text): relocation target stderr not defined
    runtime/cgo(.text): relocation target strerror not defined
    runtime/cgo(.text): relocation target fprintf 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 pthread_cond_broadcast not defined
    runtime/cgo(.text): relocation target malloc not defined

With the patch both examples build as expected.

@ianlancetaylor suggested:

> It would be fine with me if somebody wants to send a cgo patch that
passes -Wl,--no-gc-sections, with a fallback if that option is not
supported.

... and this is what we are doing. Tested with zig
0.10.0-dev.2252+a4369918b

Fixes golang#52690
motiejus added a commit to motiejus/go that referenced this issue May 20, 2022
As of CL 334732 `go build` can accept `$CC` with spaces and quotes,
which lets us easily use `zig cc` as the C compiler, or easily pass
extra compiler parameters:

```
CC="zig cc" go build <...>
CC="clang-13 -v" go build <...>
CC="zig cc -Wl,--print-gc-sections" go build <...>
```

However, the same does not apply for building go itself:

```
$ CC="zig cc" ./make.bash
Building Go cmd/dist using /usr/local/go. (go1.18.2 linux/amd64)
go tool dist: cannot invoke C compiler "zig cc": exec: "zig cc": executable file not found in $PATH

Go needs a system C compiler for use with cgo.
To set a C compiler, set CC=the-compiler.
To disable cgo, set CGO_ENABLED=0.
```

With this change Go can be built directly with `zig cc` (the linker arg
will disappear with golang#52815 and/or golang#52690):

```
$ CC="zig cc -Wl,--no-gc-sections" ./make.bash
Building Go cmd/dist using /usr/local/go. (go1.18.2 linux/amd64)
Building Go toolchain1 using /usr/local/go.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for linux/amd64.
---
Installed Go for linux/amd64 in /home/motiejus/code/go
Installed commands in /home/motiejus/code/go/bin
$ ../bin/go version
go version devel go1.19-811f1913a8 Thu May 19 09:44:49 2022 +0300 linux/amd64
```

Fixes golang#52990
@dmitshur dmitshur reopened this May 21, 2022
motiejus added a commit to motiejus/go that referenced this issue May 23, 2022
zig cc passes `--gc-sections` to the underlying linker, which then
causes undefined symbol errors when compiling with cgo but without C
code. Add `-Wl,--no-gc-sections` to make it work with zig cc. Minimal
example:

**main.go**

    package main
    import _ "runtime/cgo"
    func main() {}

Run (works after the patch, doesn't work before):

    CC="zig cc" go build main.go

Among the existing code, `src/runtime/testdata/testprognet` fails to
build:

    src/runtime/testdata/testprognet$ CC="zig cc" go build .
    net(.text): relocation target __errno_location not defined
    net(.text): relocation target getaddrinfo not defined
    net(.text): relocation target freeaddrinfo not defined
    net(.text): relocation target gai_strerror 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_create not defined
    runtime/cgo(.text): relocation target nanosleep not defined
    runtime/cgo(.text): relocation target pthread_detach not defined
    runtime/cgo(.text): relocation target stderr not defined
    runtime/cgo(.text): relocation target strerror not defined
    runtime/cgo(.text): relocation target fprintf 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 pthread_cond_broadcast not defined
    runtime/cgo(.text): relocation target malloc not defined

With the patch both examples build as expected.

@ianlancetaylor suggested:

> It would be fine with me if somebody wants to send a cgo patch that
passes -Wl,--no-gc-sections, with a fallback if that option is not
supported.

... and this is what we are doing. Tested with zig
0.10.0-dev.2252+a4369918b

This is a continuation of CL 405414: the original one broke AIX and iOS
builds. To fix that, added `unknown option` to the list of strings
under lookup.

Fixes golang#52690
motiejus added a commit to motiejus/go that referenced this issue May 23, 2022
zig cc passes `--gc-sections` to the underlying linker, which then
causes undefined symbol errors when compiling with cgo but without C
code. Add `-Wl,--no-gc-sections` to make it work with zig cc. Minimal
example:

**main.go**

    package main
    import _ "runtime/cgo"
    func main() {}

Run (works after the patch, doesn't work before):

    CC="zig cc" go build main.go

Among the existing code, `src/runtime/testdata/testprognet` fails to
build:

    src/runtime/testdata/testprognet$ CC="zig cc" go build .
    net(.text): relocation target __errno_location not defined
    net(.text): relocation target getaddrinfo not defined
    net(.text): relocation target freeaddrinfo not defined
    net(.text): relocation target gai_strerror 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_create not defined
    runtime/cgo(.text): relocation target nanosleep not defined
    runtime/cgo(.text): relocation target pthread_detach not defined
    runtime/cgo(.text): relocation target stderr not defined
    runtime/cgo(.text): relocation target strerror not defined
    runtime/cgo(.text): relocation target fprintf 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 pthread_cond_broadcast not defined
    runtime/cgo(.text): relocation target malloc not defined

With the patch both examples build as expected.

@ianlancetaylor suggested:

> It would be fine with me if somebody wants to send a cgo patch that
passes -Wl,--no-gc-sections, with a fallback if that option is not
supported.

... and this is what we are doing. Tested with zig
0.10.0-dev.2252+a4369918b

This is a continuation of CL 405414: the original one broke AIX and iOS
builds. To fix that, added `unknown option` to the list of strings
under lookup.

Fixes golang#52690
@gopherbot
Copy link

Change https://go.dev/cl/407814 mentions this issue: cmd/cgo: use --no-gc-sections if available

motiejus added a commit to motiejus/go that referenced this issue May 24, 2022
zig cc passes `--gc-sections` to the underlying linker, which then
causes undefined symbol errors when compiling with cgo but without C
code. Add `-Wl,--no-gc-sections` to make it work with zig cc. Minimal
example:

**main.go**

    package main
    import _ "runtime/cgo"
    func main() {}

Run (works after the patch, doesn't work before):

    CC="zig cc" go build main.go

Among the existing code, `src/runtime/testdata/testprognet` fails to
build:

    src/runtime/testdata/testprognet$ CC="zig cc" go build .
    net(.text): relocation target __errno_location not defined
    net(.text): relocation target getaddrinfo not defined
    net(.text): relocation target freeaddrinfo not defined
    net(.text): relocation target gai_strerror 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_create not defined
    runtime/cgo(.text): relocation target nanosleep not defined
    runtime/cgo(.text): relocation target pthread_detach not defined
    runtime/cgo(.text): relocation target stderr not defined
    runtime/cgo(.text): relocation target strerror not defined
    runtime/cgo(.text): relocation target fprintf 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 pthread_cond_broadcast not defined
    runtime/cgo(.text): relocation target malloc not defined

With the patch both examples build as expected.

@ianlancetaylor suggested:

> It would be fine with me if somebody wants to send a cgo patch that
passes -Wl,--no-gc-sections, with a fallback if that option is not
supported.

... and this is what we are doing. Tested with zig
0.10.0-dev.2252+a4369918b

This is a continuation of CL 405414: the original one broke AIX and iOS
builds. To fix that, added `unknown option` to the list of strings
under lookup.

Fixes golang#52690
motiejus added a commit to motiejus/go that referenced this issue May 25, 2022
zig cc passes `--gc-sections` to the underlying linker, which then
causes undefined symbol errors when compiling with cgo but without C
code. Add `-Wl,--no-gc-sections` to make it work with zig cc. Minimal
example:

**main.go**

    package main
    import _ "runtime/cgo"
    func main() {}

Run (works after the patch, doesn't work before):

    CC="zig cc" go build main.go

Among the existing code, `src/runtime/testdata/testprognet` fails to
build:

    src/runtime/testdata/testprognet$ CC="zig cc" go build .
    net(.text): relocation target __errno_location not defined
    net(.text): relocation target getaddrinfo not defined
    net(.text): relocation target freeaddrinfo not defined
    net(.text): relocation target gai_strerror 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_create not defined
    runtime/cgo(.text): relocation target nanosleep not defined
    runtime/cgo(.text): relocation target pthread_detach not defined
    runtime/cgo(.text): relocation target stderr not defined
    runtime/cgo(.text): relocation target strerror not defined
    runtime/cgo(.text): relocation target fprintf 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 pthread_cond_broadcast not defined
    runtime/cgo(.text): relocation target malloc not defined

With the patch both examples build as expected.

@ianlancetaylor suggested:

> It would be fine with me if somebody wants to send a cgo patch that
passes -Wl,--no-gc-sections, with a fallback if that option is not
supported.

... and this is what we are doing. Tested with zig
0.10.0-dev.2252+a4369918b

This is a continuation of CL 405414: the original one broke AIX and iOS
builds. To fix that, added `unknown option` to the list of strings
under lookup.

Fixes golang#52690
@dmitshur dmitshur modified the milestones: Backlog, Go1.19 May 26, 2022
@uhthomas
Copy link

uhthomas commented Feb 1, 2023

I still see this issue with Go 1.20 and zig 0.11.0-dev.811+8ff9284c4.

(20:10:30) ERROR: /private/var/tmp/_bazel_thomas/d95eb470615df18f91feffc144a9a015/external/com_github_sourcegraph_sourcegraph/cmd/migrator/BUILD.bazel:16:10: GoLink external/com_github_sourcegraph_sourcegraph/cmd/migrator/migrator_/migrator failed: (Exit 1): sandbox-exec failed: error executing command 
  (cd /private/var/tmp/_bazel_thomas/d95eb470615df18f91feffc144a9a015/sandbox/darwin-sandbox/21777/execroot/sourcegraph_oss && \
  exec env - \
    CGO_ENABLED=1 \
    GOARCH=amd64 \
    GOOS=linux \
    GOPATH='' \
    GOROOT=bazel-out/darwin_arm64-fastbuild-ST-0b20c6396c42/bin/external/io_bazel_rules_go/stdlib_ \
    GOROOT_FINAL=GOROOT \
    PATH=external/zig_sdk/tools/x86_64-linux-gnu.2.28:/bin:/usr/bin \
    TMPDIR=/var/folders/ws/lyfqx2sn72v223fhz5kb77m40000gp/T/ \
  /usr/bin/sandbox-exec -f /private/var/tmp/_bazel_thomas/d95eb470615df18f91feffc144a9a015/sandbox/darwin-sandbox/21777/sandbox.sb /var/tmp/_bazel_thomas/install/730b09b9d9f2bfd30b4c0a074ba23835/process-wrapper '--timeout=0' '--kill_delay=15' '--stats=/private/var/tmp/_bazel_thomas/d95eb470615df18f91feffc144a9a015/sandbox/darwin-sandbox/21777/stats.out' bazel-out/darwin_arm64-opt-exec-2B5CBBC6-ST-625e526ca8a8/bin/external/go_sdk/builder_reset/builder '-param=bazel-out/darwin_arm64-fastbuild-ST-4a519fd6d3e4/bin/external/com_github_sourcegraph_sourcegraph/cmd/migrator/migrator_/migrator-0.params' -- -extld external/zig_sdk/tools/x86_64-linux-gnu.2.28/c++ '-buildid=redacted' -extldflags '-fno-lto -Wl,-S')
net(.text): relocation target __res_search@GLIBC_2.2.5 not defined
os/user(.text): relocation target memset not defined
os/user(.text): relocation target memcpy not defined
runtime/cgo(.text): relocation target memset not defined
link: error running subcommand external/go_sdk/pkg/tool/darwin_arm64/link: exit status 2

@ianlancetaylor
Copy link
Contributor

@uhthomas Those are different error messages (the details matter). We believe that this issue is fixed. Please open a new issue for the new problem. Thanks.

@uhthomas
Copy link

uhthomas commented Feb 1, 2023

Original examples:

runtime/cgo(.text): relocation target malloc not defined
runtime/race(.text): relocation target getuid not defined

What I am observing:

net(.text): relocation target __res_search@GLIBC_2.2.5 not defined
os/user(.text): relocation target memset not defined
os/user(.text): relocation target memcpy not defined
runtime/cgo(.text): relocation target memset not defined

Would you be able to help me understand how this is not the same issue? It looks like it's just different packages and symbols?

It may be helpful to know that this does not happen with Zig 0.10.0-dev.2977+7d2e14267... So, maybe I should open an issue with Zig instead? @andrewrk

@ianlancetaylor
Copy link
Contributor

@uhthomas That's exactly right: it's different packages and symbols. In particular it's not about runtime/race any more.
The new packages and symbols make the problem appear to be related to some changes that were made in 1.20 in the net and os/user packages.

I am surprised that this changes based on the version of Zig, though. I have no explanation for that.

@motiejus
Copy link
Contributor

motiejus commented Feb 1, 2023

I fixed the memset/memcpy in zig upstream.

A fix for res_search and a few more symbols is now developed for upstream zig by my colleague.

@uhthomas
Copy link

uhthomas commented Feb 2, 2023

Would you be able to link the memset/memcpy fix here? Was this recent? @motiejus

@motiejus
Copy link
Contributor

motiejus commented Feb 2, 2023

Would you be able to link the memset/memcpy fix here? Was this recent? @motiejus

Sure, here it is: ziglang/zig@b3f4e0d

I attempted to workaround res_search issue it in bazel-zig-cc (https://git.sr.ht/~motiejus/bazel-zig-cc/commit/7b0de33070bef14265d7ec560fca43f5e132eea4 and https://git.sr.ht/~motiejus/bazel-zig-cc/commit/8d1e1c9fa66712c8f7da3634990ab4ccd2aa47c9), but that doesn't always work, as you can see.

We agreed with @andrewrk that we will change the offending headers in upsteam zig (add ifdefs on glibc version). To my latest knowledge, @sywhang is working on that.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge help wanted NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
9 participants