diff options
-rw-r--r-- | src/cmd/go/build.go | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index 1dd4314da6..93bc2200f1 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -2121,6 +2121,36 @@ 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 { + 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 + } + src := filepath.Join(b.work, "trivial.c") + if err := ioutil.WriteFile(src, []byte{}, 0666); err != nil { + return false + } + 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 + } + } + cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) + cmd.Dir = b.work + cmd.Env = envForDir(cmd.Dir) + err := cmd.Run() + return err == nil +} + // gccArchArgs returns arguments to pass to gcc based on the architecture. func (b *builder) gccArchArgs() []string { switch archChar { @@ -2369,6 +2399,10 @@ 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") + } + // Some systems, such as Ubuntu, always add --build-id to // every link, but we don't want a build ID since we are // producing an object file. On some of those system a plain |