cmd/link: detect glibc vs musl ldso at link time

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 #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>
This commit is contained in:
Russ Cox 2022-08-02 10:12:52 -04:00 committed by Gopher Robot
parent 52dfdc5e1e
commit 3315066f46
12 changed files with 37 additions and 18 deletions

View file

@ -65,6 +65,7 @@ func Init() (*sys.Arch, ld.Arch) {
TLSIEtoLE: tlsIEtoLE,
Linuxdynld: "/lib64/ld-linux-x86-64.so.2",
LinuxdynldMusl: "/lib/ld-musl-x84_64.so.1",
Freebsddynld: "/libexec/ld-elf.so.1",
Openbsddynld: "/usr/libexec/ld.so",
Netbsddynld: "/libexec/ld.elf_so",

View file

@ -63,6 +63,7 @@ func Init() (*sys.Arch, ld.Arch) {
PEreloc1: pereloc1,
Linuxdynld: "/lib/ld-linux.so.3", // 2 for OABI, 3 for EABI
LinuxdynldMusl: "/lib/ld-musl-arm.so.1",
Freebsddynld: "/usr/libexec/ld-elf.so.1",
Openbsddynld: "/usr/libexec/ld.so",
Netbsddynld: "/libexec/ld.elf_so",

View file

@ -62,8 +62,9 @@ func Init() (*sys.Arch, ld.Arch) {
PEreloc1: pereloc1,
Trampoline: trampoline,
Androiddynld: "/system/bin/linker64",
Linuxdynld: "/lib/ld-linux-aarch64.so.1",
Androiddynld: "/system/bin/linker64",
Linuxdynld: "/lib/ld-linux-aarch64.so.1",
LinuxdynldMusl: "/lib/ld-musl-aarch64.so.1",
Freebsddynld: "/usr/libexec/ld-elf.so.1",
Openbsddynld: "/usr/libexec/ld.so",

View file

@ -15,6 +15,7 @@ import (
"encoding/hex"
"fmt"
"internal/buildcfg"
"os"
"path/filepath"
"runtime"
"sort"
@ -1782,6 +1783,16 @@ func asmbElf(ctxt *Link) {
}
} else {
interpreter = thearch.Linuxdynld
// If interpreter does not exist, try musl instead.
// This lets the same cmd/link binary work on
// both glibc-based and musl-based systems.
if _, err := os.Stat(interpreter); err != nil {
if musl := thearch.LinuxdynldMusl; musl != "" {
if _, err := os.Stat(musl); err == nil {
interpreter = musl
}
}
}
}
case objabi.Hfreebsd:

View file

@ -183,6 +183,7 @@ type Arch struct {
Androiddynld string
Linuxdynld string
LinuxdynldMusl string
Freebsddynld string
Netbsddynld string
Openbsddynld string

View file

@ -31,6 +31,7 @@ func Init() (*sys.Arch, ld.Arch) {
Gentext: gentext,
Linuxdynld: "/lib64/ld.so.1",
LinuxdynldMusl: "/lib64/ld-musl-loongarch.so.1",
Freebsddynld: "XXX",
Openbsddynld: "XXX",
Netbsddynld: "XXX",

View file

@ -39,8 +39,10 @@ import (
func Init() (*sys.Arch, ld.Arch) {
arch := sys.ArchMIPS
musl := "/lib/ld-musl-mips.so.1"
if buildcfg.GOARCH == "mipsle" {
arch = sys.ArchMIPSLE
musl = "/lib/ld-musl-mipsel.so.1"
}
theArch := ld.Arch{
@ -60,7 +62,8 @@ func Init() (*sys.Arch, ld.Arch) {
Gentext: gentext,
Machoreloc1: machoreloc1,
Linuxdynld: "/lib/ld.so.1",
Linuxdynld: "/lib/ld.so.1",
LinuxdynldMusl: musl,
Freebsddynld: "XXX",
Openbsddynld: "XXX",

View file

@ -39,8 +39,10 @@ import (
func Init() (*sys.Arch, ld.Arch) {
arch := sys.ArchMIPS64
musl := "/lib/ld-musl-mips64.so.1"
if buildcfg.GOARCH == "mips64le" {
arch = sys.ArchMIPS64LE
musl = "/lib/ld-musl-mips64el.so.1"
}
theArch := ld.Arch{
@ -60,6 +62,7 @@ func Init() (*sys.Arch, ld.Arch) {
Machoreloc1: machoreloc1,
Linuxdynld: "/lib64/ld64.so.1",
LinuxdynldMusl: musl,
Freebsddynld: "XXX",
Openbsddynld: "/usr/libexec/ld.so",
Netbsddynld: "XXX",

View file

@ -40,10 +40,12 @@ import (
func Init() (*sys.Arch, ld.Arch) {
arch := sys.ArchPPC64LE
dynld := "/lib64/ld64.so.2"
musl := "/lib/ld-musl-powerpc64le.so.1"
if buildcfg.GOARCH == "ppc64" {
arch = sys.ArchPPC64
dynld = "/lib64/ld64.so.1"
musl = "/lib/ld-musl-powerpc64.so.1"
}
theArch := ld.Arch{
@ -68,6 +70,8 @@ func Init() (*sys.Arch, ld.Arch) {
Xcoffreloc1: xcoffreloc1,
Linuxdynld: dynld,
LinuxdynldMusl: musl,
Freebsddynld: "XXX",
Openbsddynld: "XXX",
Netbsddynld: "XXX",

View file

@ -56,7 +56,8 @@ func Init() (*sys.Arch, ld.Arch) {
Gentext: gentext,
Machoreloc1: machoreloc1,
Linuxdynld: "/lib64/ld64.so.1",
Linuxdynld: "/lib64/ld64.so.1",
LinuxdynldMusl: "/lib/ld-musl-s390x.so.1",
// not relevant for s390x
Freebsddynld: "XXX",

View file

@ -61,11 +61,12 @@ func Init() (*sys.Arch, ld.Arch) {
Machoreloc1: machoreloc1,
PEreloc1: pereloc1,
Linuxdynld: "/lib/ld-linux.so.2",
Freebsddynld: "/usr/libexec/ld-elf.so.1",
Openbsddynld: "/usr/libexec/ld.so",
Netbsddynld: "/usr/libexec/ld.elf_so",
Solarisdynld: "/lib/ld.so.1",
Linuxdynld: "/lib/ld-linux.so.2",
LinuxdynldMusl: "/lib/ld-musl-i386.so.1",
Freebsddynld: "/usr/libexec/ld-elf.so.1",
Openbsddynld: "/usr/libexec/ld.so",
Netbsddynld: "/usr/libexec/ld.elf_so",
Solarisdynld: "/lib/ld.so.1",
}
return arch, theArch

View file

@ -133,15 +133,6 @@ if [ "$(uname -s)" = "GNU/kFreeBSD" ]; then
export CGO_ENABLED=0
fi
# Test which linker/loader our system is using, if GO_LDSO is not set.
if [ -z "$GO_LDSO" ] && type readelf >/dev/null 2>&1; then
if echo "int main() { return 0; }" | ${CC:-cc} -o ./test-musl-ldso -x c - >/dev/null 2>&1; then
LDSO=$(readelf -l ./test-musl-ldso | grep 'interpreter:' | sed -e 's/^.*interpreter: \(.*\)[]]/\1/') >/dev/null 2>&1
[ -z "$LDSO" ] || export GO_LDSO="$LDSO"
rm -f ./test-musl-ldso
fi
fi
# Clean old generated file that will cause problems in the build.
rm -f ./runtime/runtime_defs.go