cmd/link: don't pass all linker args when testing flag

Some linker flags can actually be input files, which can cause
misleading errors when doing the trial link, which can cause the
linker to incorrectly decide that the flag is not supported, which can
cause the link to fail.

Fixes #27510
Updates #27110
Updates #27293

Change-Id: I70c1e913cee3c813e7b267bf779bcff26d4d194a
Reviewed-on: https://go-review.googlesource.com/134057
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com>
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 60124e3..7029ba1 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -1379,9 +1379,58 @@
 		}
 	})
 
+	flagsWithNextArgSkip := []string{
+		"-F",
+		"-l",
+		"-L",
+		"-framework",
+		"-Wl,-framework",
+		"-Wl,-rpath",
+		"-Wl,-undefined",
+	}
+	flagsWithNextArgKeep := []string{
+		"-arch",
+		"-isysroot",
+		"--sysroot",
+		"-target",
+	}
+	prefixesToKeep := []string{
+		"-f",
+		"-m",
+		"-p",
+		"-Wl,",
+		"-arch",
+		"-isysroot",
+		"--sysroot",
+		"-target",
+	}
+
 	var flags []string
-	flags = append(flags, ldflag...)
-	flags = append(flags, strings.Fields(*flagExtldflags)...)
+	keep := false
+	skip := false
+	extldflags := strings.Fields(*flagExtldflags)
+	for _, f := range append(extldflags, ldflag...) {
+		if keep {
+			flags = append(flags, f)
+			keep = false
+		} else if skip {
+			skip = false
+		} else if f == "" || f[0] != '-' {
+		} else if contains(flagsWithNextArgSkip, f) {
+			skip = true
+		} else if contains(flagsWithNextArgKeep, f) {
+			flags = append(flags, f)
+			keep = true
+		} else {
+			for _, p := range prefixesToKeep {
+				if strings.HasPrefix(f, p) {
+					flags = append(flags, f)
+					break
+				}
+			}
+		}
+	}
+
 	flags = append(flags, flag, "trivial.c")
 
 	cmd := exec.Command(linker, flags...)
diff --git a/src/cmd/link/internal/ld/util.go b/src/cmd/link/internal/ld/util.go
index b80e610..b5b0229 100644
--- a/src/cmd/link/internal/ld/util.go
+++ b/src/cmd/link/internal/ld/util.go
@@ -89,3 +89,13 @@
 func elapsed() float64 {
 	return time.Since(start).Seconds()
 }
+
+// contains reports whether v is in s.
+func contains(s []string, v string) bool {
+	for _, x := range s {
+		if x == v {
+			return true
+		}
+	}
+	return false
+}