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/link: determine GO_LDSO on Linux at link time instead of baking in make.bash #54197

Closed
rsc opened this issue Aug 2, 2022 · 2 comments
Closed
Assignees
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@rsc
Copy link
Contributor

rsc commented Aug 2, 2022

#54196 identifies a general problem with our baked-in variables and a general fix of making them per-GOOS/GOARCH. But GO_LDSO is not really even per-GOOS/GOARCH: there are different settings needed on different linux/amd64 systems.

The computation during make.bash of a default GO_LDSO added in CL 301989 is particularly problematic for cross-compilation, since the GO_LDSO is only right for the current machine. CL 343010 fixed the problem for cross-compiling from one machine to another, but it does not fix the problem when the cross-compilation is used to build a bootstrap toolchain that is copied to a new machine. Then the GOOS and GOARCH tests flip back to true and the bootstrap toolchain uses the GO_LDSO setting from the original machine. This makes it impossible today to use bootstrap.bash to build an OpenBSD toolchain from Linux: when the toolchain is run on OpenBSD, it uses a GO_LDSO setting that is only appropriate on Linux. We should at the least make GO_LDSO per-GOOS/GOARCH and probably only bake in GO_LDSO_${GOOS}_${GOARCH} implicitly in make.bash. But I also wonder about baking it in at all. The default baking makes non-cross-compilation subtly different from cross compilation, which will keep coming back to bite us. And essentially all systems have a hard-coded ldso path.

CL 301989 was done to deal with the confusion of having two different ld.so on Linux systems, but then we end up with toolchains that still only work on one system or the other. Any bake-in is going to have that property. It seems like a better fix would be to not bake anything in by default and instead have the linker stat the two possible ld.so paths and use the one it finds. Then the same linker binary will produce working binaries on glibc- and musl-based systems.

/cc @ianlancetaylor and @cherrymui for thoughts. I am happy to write the CL adding the stat call in cmd/link and removing the GO_LDSO baking in make.bash.

@gopherbot
Copy link

Change https://go.dev/cl/420774 mentions this issue: cmd/link: detect glibc vs musl ldso at link time

@ianlancetaylor
Copy link
Contributor

As far as I know this confusion about dynamic linkers is specific to Linux.

For GCC you pick a target when you build GCC. That sets the default dynamic linker. Then you can override that default with the options -mglibc, -muclibc, -mmusl, -mbionic. The -mbionic option corresponds to our GOOS == "android". uclibc always uses /lib/ld-uClibc.so.0 or /lib/ld64-uClibc.so.0. musl unfortunately varies by GOARCH.

Trying to detect the default at run time is reasonable though we will sometimes get it wrong. And we will need a table of values for musl.

This is what I pulled out of the GCC sources for the musl dynamic linker:

arm64 /lib/ld-musl-aarch64[_be][_ilp32].so.1
arm /lib/ld-musl-arm[eb][hf][-fdpic].so.1
386 /lib/ld-musl-i386.so.1
amd64 /lib/ld-musl-x86_64.so.1
loongarch64 /lib64/ld-musl-loongarch-{,lp64d,lp64f,lp64s}.so.1
mips /lib/ld-musl-mips[el][-sf].so.1
mips64 /lib/ld-musl-mips64[el][-sf].so.1
risv64 /lib/ld-musl.so.1
powerp64 /lib/ld-musl-powerpc[le][sf].so.1
s390x /lib/ld-musl-s390x.so.1

@dmitshur dmitshur added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Aug 3, 2022
@dmitshur dmitshur added this to the Backlog milestone Aug 3, 2022
jproberts pushed a commit to jproberts/go that referenced this issue Aug 10, 2022
Doing the test at link time lets us distribute one Linux toolchain
that works on both glibc-based and musl-based Linux systems.
The old way built a toolchain that only ran on one or the other.

Fixes golang#54197.

Change-Id: Iaae8c274c78e1091eee828a720b49646be9bfffe
Reviewed-on: https://go-review.googlesource.com/c/go/+/420774
Auto-Submit: Russ Cox <rsc@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
@dmitshur dmitshur added 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 Nov 8, 2022
@dmitshur dmitshur modified the milestones: Backlog, Go1.20 Nov 8, 2022
@golang golang locked and limited conversation to collaborators Nov 8, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

4 participants