aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDimitri John Ledkov <dimitri.ledkov@surgut.co.uk>2026-01-29 05:30:42 +0100
committerGopher Robot <gobot@golang.org>2026-02-19 12:17:47 -0800
commita8032d4c781f14fa0bd561d96e719492aee08c23 (patch)
tree811ce09b9dc1f5f8c0f7ca51d4a891d02dfea707 /src
parent87a956bf8cdf9004108942247af8ae0243c5609a (diff)
downloadgo-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')
-rw-r--r--src/cmd/link/internal/ld/lib.go46
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)
+ }
}
}
}