diff options
| author | Dimitri John Ledkov <dimitri.ledkov@surgut.co.uk> | 2026-01-29 05:30:42 +0100 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2026-02-19 12:17:47 -0800 |
| commit | a8032d4c781f14fa0bd561d96e719492aee08c23 (patch) | |
| tree | 811ce09b9dc1f5f8c0f7ca51d4a891d02dfea707 /src/cmd | |
| parent | 87a956bf8cdf9004108942247af8ae0243c5609a (diff) | |
| download | go-a8032d4c781f14fa0bd561d96e719492aee08c23.tar.xz | |
cmd/link: use bfd ld 2.36+ on linux/arm64 instead of gold
The bfd linker has been fixed for a while. In the mean time gold got
deprecated and has stopped receiving new features. Add runtime version
checking and only use gold, if bfd ld 2.35 and lower is detected.
This enables using `-buildmode=shared` on arm64 without installing
binutils-gold (on distributions that split package this), as well as
to use external ldflags that ld.bfd supports, and ld.gold does
not. For example, this enables to specify gcs-report-dynamic=none when
building with GCC-15.
Fixes #22040.
Change-Id: I4eb8b3dabb78844ff662332ad63a4625278271b1
Reviewed-on: https://go-review.googlesource.com/c/go/+/740480
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/cmd')
| -rw-r--r-- | src/cmd/link/internal/ld/lib.go | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 3799aafac7..cac9cc0b98 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -1700,22 +1700,48 @@ func (ctxt *Link) hostlink() { } if ctxt.Arch.InFamily(sys.ARM64) && buildcfg.GOOS == "linux" { - // On ARM64, the GNU linker will fail with - // -znocopyreloc if it thinks a COPY relocation is - // required. Switch to gold. + // On ARM64, the GNU linker had issues with -znocopyreloc + // and COPY relocations. This was fixed in GNU ld 2.36+. // https://sourceware.org/bugzilla/show_bug.cgi?id=19962 // https://go.dev/issue/22040 - altLinker = "gold" + // And newer gold is deprecated, may lack new features/flags, or even missing - // If gold is not installed, gcc will silently switch - // back to ld.bfd. So we parse the version information - // and provide a useful error if gold is missing. + // If the default linker is GNU ld 2.35 or older, use gold + useGold := false name, args := flagExtld[0], flagExtld[1:] - args = append(args, "-fuse-ld=gold", "-Wl,--version") + args = append(args, "-Wl,--version") cmd := exec.Command(name, args...) if out, err := cmd.CombinedOutput(); err == nil { - if !bytes.Contains(out, []byte("GNU gold")) { - log.Fatalf("ARM64 external linker must be gold (issue #15696, 22040), but is not: %s", out) + // Parse version from output like "GNU ld (GNU Binutils for Distro) 2.36.1" + for line := range strings.Lines(string(out)) { + if !strings.HasPrefix(line, "GNU ld ") { + continue + } + fields := strings.Fields(line[len("GNU ld "):]) + var major, minor int + if ret, err := fmt.Sscanf(fields[len(fields)-1], "%d.%d", &major, &minor); ret == 2 && err == nil { + if major == 2 && minor <= 35 { + useGold = true + } + break + } + } + } + + if useGold { + // Use gold for older linkers + altLinker = "gold" + + // If gold is not installed, gcc will silently switch + // back to ld.bfd. So we parse the version information + // and provide a useful error if gold is missing. + args = flagExtld[1:] + args = append(args, "-fuse-ld=gold", "-Wl,--version") + cmd = exec.Command(name, args...) + if out, err := cmd.CombinedOutput(); err == nil { + if !bytes.Contains(out, []byte("GNU gold")) { + log.Fatalf("ARM64 external linker must be ld>=2.36 or gold (issue #15696, 22040), but is not: %s", out) + } } } } |
