Open mikedanese opened 3 months ago
@ianlancetaylor, was the ordering of extldflags before the LDFLAGS from cgo directives in linkerFlagSupported
picked intentionally? I can't tell if it's a terrible solution, but swapping the order would give the go link extdflags precedence over cgo directives for mutually exclusive linker options.
func linkerFlagSupported(arch *sys.Arch, linker, altLinker, flag string) bool {
...
moreFlags := trimLinkerArgv(append(flagExtldflags, ldflag...))
I can't answer that question, but ideally we wouldn't include any absolute paths into the outputs of compilation. Maybe we could use a symlink instead of converting the sysroot to an absolute path?
That said, if flipping the order of flags is a simple way to fix this and no tests break, I'm happy to accept that change.
I don't understand what is creating the absolute path. The code you mention in cmd/cgo only applies to Go file names, not to options like --sysroot=dir
.
Ah ya, misread that. Thanks.
So this is actually happening in rules_go. The flags are getting absolute here:
So we have a --sysroot from a custom cc toolchain. When building the stdlib with go install
, we make all CGO_LDFLAGS absolute, presumably because go install
changes directories. If we don't, then we get an error like:
_cgo_export.c:3:10: fatal error: 'stdlib.h' file not found
I encountered the same issue. We use a custom cc toolchain, the binaries built success but cannot run.
runtime: pcHeader: magic= 0xfffffff1 pad1= 0 pad2= 0 minLC= 1 ptrSize= 8 pcHeader.textStart= 0x1be100 text= 0x557164240100 pluginpath=
fatal error: invalid function symbol table
runtime: panic before malloc heap initialized
According @mikedanese , I try to remove the codes of absEnv as mentioned above , but not works, the issue persists. https://github.com/bazelbuild/rules_go/blob/aeb83e878033ef357642c87122e193df44da03fe/go/tools/builders/stdlib.go#L161-L165
I found that when rule_go link the binary, it doesn't fetch clink flags through clinkopts; instead, it reads gc_linkopts and puts the flags after -extldflags into _extract_extldflags. https://github.com/bazelbuild/rules_go/blob/c0ef535977f9fd2d9a67243552cd04da285ab629/go/private/actions/link.bzl#L64-L106
So, after adding the following flags to my go_binary, it started running correctly.
gc_linkopts = [
"-extldflags",
"-nopie",
],
What version of rules_go are you using?
master sync'd to latest
What version of Bazel are you using?
Does this issue reproduce with the latest releases of all the above?
What operating system and processor architecture are you using?
Linux
What did you see instead?
I have a custom cc toolchain based on LLVM. This toolchain sets a sysroot link option, e.g.
--sysroot=external/sysroot-linux-x86_64-gnu7-llvm-1
.When a cgo library is generated, the cgo tool converts this LD_FLAG value into an absolute path here: https://cs.opensource.google/go/go/+/master:src/cmd/cgo/main.go;l=353-357;drc=bdccd923e914ab61d77a8f23a3329cf1d5aaa7c1. For example, my sysroot ldflag might be converted to
/home/mike.danese/.cache/bazel/_bazel_mike.danese/71e455921cc87b7db5489570176e2cff/sandbox/linux-sandbox/400/execroot/universe/external/sysroot-linux-x86_64-gnu7-llvm-16
. These LD_FLAGs get backed into the object.Now when it's time to link,
go tool link
probes the linker (inlinkerFlagSupported
) to determine if e.g.-no-pie
should be configured: https://cs.opensource.google/go/go/+/master:src/cmd/link/internal/ld/lib.go;l=1833-1834;drc=2ab9218c86ed625362df5060f64fcd59398a76f3. It does this by compiling a trivial program. To construct the compile command, the ldflags from the cgo object are appended to the extdld flags: https://cs.opensource.google/go/go/+/master:src/cmd/link/internal/ld/lib.go;l=2079-2080;drc=2ab9218c86ed625362df5060f64fcd59398a76f3. This results in a command like this:sysroot
arg is passed twice, once from --extld flags and once from the go_ldflags attribute in the cgo object so the second--sysroot
wins. This is a problem because the second sysroot references a path in the no longer existant execution sandbox where the cgo object was compiled. Thus, the probe fails with a nonsensical error:This error is swallowed silently, and
go link
assumes that the linker flag is unsupported. In the case of-no-pie
, this causes rules_go to attempt to link PIE cgo objects into go binaries without relro (e.g. in normal exe buildmode on linux). This causes hard to debug runtime errors such as:There are ~10 other calls to
linkerFlagSupported
and none of them are correctly detecting flag support.