From a3310f9981ac6916a1c03ec9ac84ee023cb7d8ed Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 18 Jul 2017 13:22:39 -0700 Subject: [release-branch.go1.4] cmd/go: if -no-pie doesn't work, try -nopie This is a backport of https://golang.org/cl/49710 to the Go 1.4 branch. Original CL description: GCC says -no-pie, clang says -nopie. Updates #21042 Change-Id: I67b755ccb0149324098b79e07ee4bbc49429c44c Reviewed-on: https://go-review.googlesource.com/49711 Reviewed-by: Brad Fitzpatrick --- src/cmd/go/build.go | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index 93bc2200f1..1367658953 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -2121,34 +2121,40 @@ func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string { return a } -// On systems with PIE (position independent executables) enabled by default, -// -no-pie must be passed when doing a partial link with -Wl,-r. But -no-pie is -// not supported by all compilers. -func (b *builder) gccSupportsNoPie() bool { +// gccNoPie returns the flag to use to request non-PIE. On systems +// with PIE (position independent executables) enabled by default, +// -no-pie must be passed when doing a partial link with -Wl,-r. +// But -no-pie is not supported by all compilers, and clang spells it -nopie. +func (b *builder) gccNoPie() string { if goos != "linux" { // On some BSD platforms, error messages from the // compiler make it to the console despite cmd.Std* // all being nil. As -no-pie is only required on linux // systems so far, we only test there. - return false + return "" } src := filepath.Join(b.work, "trivial.c") if err := ioutil.WriteFile(src, []byte{}, 0666); err != nil { - return false + return "" } - cmdArgs := b.gccCmd(b.work) - cmdArgs = append(cmdArgs, "-no-pie", "-c", "trivial.c") - if buildN || buildX { - b.showcmd(b.work, "%s", joinUnambiguously(cmdArgs)) - if buildN { - return false + for _, nopie := range []string{"-no-pie", "-nopie"} { + cmdArgs := b.gccCmd(b.work) + cmdArgs = append(cmdArgs, nopie, "-c", "trivial.c") + if buildN || buildX { + b.showcmd(b.work, "%s", joinUnambiguously(cmdArgs)) + if buildN { + return "" + } + } + cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) + cmd.Dir = b.work + cmd.Env = envForDir(cmd.Dir) + err := cmd.Run() + if err == nil { + return nopie } } - cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) - cmd.Dir = b.work - cmd.Env = envForDir(cmd.Dir) - err := cmd.Run() - return err == nil + return "" } // gccArchArgs returns arguments to pass to gcc based on the architecture. @@ -2399,8 +2405,8 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfi } ldflags := stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs) - if b.gccSupportsNoPie() { - ldflags = append(ldflags, "-no-pie") + if flag := b.gccNoPie(); flag != "" { + ldflags = append(ldflags, flag) } // Some systems, such as Ubuntu, always add --build-id to -- cgit v1.2.3-54-g00ecf