[PATCH] cmd/link: check CGO_CFLAGS for non -g/-I/-O options before internal linking
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Tue, 5 Jan 2021 23:18:24 +0000 (12:18 +1300)
committerMichael Hudson-Doyle <mwhudson@debian.org>
Tue, 9 Feb 2021 23:58:55 +0000 (23:58 +0000)
On Debian and Ubuntu we are investigating enabling link-time
optimization by default, which means the default CFLAGS will contain
arguments that cause gcc to generate object files
cmd/link/internal/loadelf cannot process. Rather than failing in this
situation, scan CGO_CFLAGS in mustLinkExternal and do not link
internally if there is a flag that does not start with -g, -I, or -O.

CFLAGS can also be injected via #cgo CFLAGS: directives but as use of
any non-standard library cgo modules disables internal linking anyway,
we don't have to worry about that here.

Fixes #43505

Change-Id: Ib083f6daf22617e2e5df67e95d3bc178942328cd

Gbp-Pq: Name 0007-cmd-link-check-CGO_CFLAGS-for-non-g-I-O-options-befo.patch

src/cmd/link/internal/ld/config.go

index 2373b500e3aae1b879470e66cf8ececc16ec793f..18fc5d2cd7f4f7ba1459edd70c58c3edf95ff44a 100644 (file)
@@ -9,6 +9,8 @@ import (
        "cmd/internal/sys"
        "fmt"
        "log"
+       "os"
+       "strings"
 )
 
 // A BuildMode indicates the sort of object we are building.
@@ -164,6 +166,15 @@ func (mode *LinkMode) String() string {
        return fmt.Sprintf("LinkMode(%d)", uint8(*mode))
 }
 
+// Some arguments in CGO_CFLAGS can cause the host compiler to
+// generate object files that loadelf cannot handle but arguments
+// starting with any of these values are OK.
+var internalOKCflagPrefixes = []string{
+       "-O",
+       "-g",
+       "-I",
+}
+
 // mustLinkExternal reports whether the program being linked requires
 // the external linker be used to complete the link.
 func mustLinkExternal(ctxt *Link) (res bool, reason string) {
@@ -223,6 +234,16 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) {
                return true, "dynamically linking with a shared library"
        }
 
+outer:
+       for _, flag := range strings.Fields(os.Getenv("CGO_CFLAGS")) {
+               for _, okPrefix := range internalOKCflagPrefixes {
+                       if strings.HasPrefix(flag, okPrefix) {
+                               continue outer
+                       }
+               }
+               return true, "CGO_CFLAGS contains flag that may inhibit internal linking: " + flag
+       }
+
        return false, ""
 }