From 3315066f46d5dce3e4474bdcde0997d688c79436 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 2 Aug 2022 10:12:52 -0400 Subject: [PATCH] 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 Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot Run-TryBot: Russ Cox --- src/cmd/link/internal/amd64/obj.go | 1 + src/cmd/link/internal/arm/obj.go | 1 + src/cmd/link/internal/arm64/obj.go | 5 +++-- src/cmd/link/internal/ld/elf.go | 11 +++++++++++ src/cmd/link/internal/ld/lib.go | 1 + src/cmd/link/internal/loong64/obj.go | 1 + src/cmd/link/internal/mips/obj.go | 5 ++++- src/cmd/link/internal/mips64/obj.go | 3 +++ src/cmd/link/internal/ppc64/obj.go | 4 ++++ src/cmd/link/internal/s390x/obj.go | 3 ++- src/cmd/link/internal/x86/obj.go | 11 ++++++----- src/make.bash | 9 --------- 12 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/cmd/link/internal/amd64/obj.go b/src/cmd/link/internal/amd64/obj.go index d09c90ea280..f46045bc9dd 100644 --- a/src/cmd/link/internal/amd64/obj.go +++ b/src/cmd/link/internal/amd64/obj.go @@ -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", diff --git a/src/cmd/link/internal/arm/obj.go b/src/cmd/link/internal/arm/obj.go index b7d149851c4..6da0c774832 100644 --- a/src/cmd/link/internal/arm/obj.go +++ b/src/cmd/link/internal/arm/obj.go @@ -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", diff --git a/src/cmd/link/internal/arm64/obj.go b/src/cmd/link/internal/arm64/obj.go index 9c7459855c1..a47be0b282b 100644 --- a/src/cmd/link/internal/arm64/obj.go +++ b/src/cmd/link/internal/arm64/obj.go @@ -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", diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go index 2566ded58db..040978e6fcc 100644 --- a/src/cmd/link/internal/ld/elf.go +++ b/src/cmd/link/internal/ld/elf.go @@ -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: diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 18910ddb850..c265d73893b 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -183,6 +183,7 @@ type Arch struct { Androiddynld string Linuxdynld string + LinuxdynldMusl string Freebsddynld string Netbsddynld string Openbsddynld string diff --git a/src/cmd/link/internal/loong64/obj.go b/src/cmd/link/internal/loong64/obj.go index b564dfd05f9..0a5bb0ac6d6 100644 --- a/src/cmd/link/internal/loong64/obj.go +++ b/src/cmd/link/internal/loong64/obj.go @@ -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", diff --git a/src/cmd/link/internal/mips/obj.go b/src/cmd/link/internal/mips/obj.go index 5ca75825293..f03c9abfe97 100644 --- a/src/cmd/link/internal/mips/obj.go +++ b/src/cmd/link/internal/mips/obj.go @@ -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", diff --git a/src/cmd/link/internal/mips64/obj.go b/src/cmd/link/internal/mips64/obj.go index 544e1ef7bed..557d7993cdf 100644 --- a/src/cmd/link/internal/mips64/obj.go +++ b/src/cmd/link/internal/mips64/obj.go @@ -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", diff --git a/src/cmd/link/internal/ppc64/obj.go b/src/cmd/link/internal/ppc64/obj.go index bca8fa92120..f580c55456b 100644 --- a/src/cmd/link/internal/ppc64/obj.go +++ b/src/cmd/link/internal/ppc64/obj.go @@ -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", diff --git a/src/cmd/link/internal/s390x/obj.go b/src/cmd/link/internal/s390x/obj.go index 8acc1d49176..3aa89481517 100644 --- a/src/cmd/link/internal/s390x/obj.go +++ b/src/cmd/link/internal/s390x/obj.go @@ -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", diff --git a/src/cmd/link/internal/x86/obj.go b/src/cmd/link/internal/x86/obj.go index a19437d8e61..b0a129eb0ad 100644 --- a/src/cmd/link/internal/x86/obj.go +++ b/src/cmd/link/internal/x86/obj.go @@ -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 diff --git a/src/make.bash b/src/make.bash index ab2ce19f4ee..54bb0705139 100755 --- a/src/make.bash +++ b/src/make.bash @@ -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