Commit b7c600d6 authored by Hiroshi Ioka's avatar Hiroshi Ioka Committed by Ian Lance Taylor

cmd/go, cmd/link: enable buildmode=pie on darwin/amd64

Change some configurations to enable the feature. Also add the test.
This CL doesn't include internal linking support which is tentatively
disabled due to #18968. We could do that another day.

Fixes #21220

Change-Id: I601d2d78446d36332acc70be0d5b9461ac635208
Reviewed-on: https://go-review.googlesource.com/54790Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 9fbc06e6
...@@ -6,6 +6,8 @@ package main_test ...@@ -6,6 +6,8 @@ package main_test
import ( import (
"bytes" "bytes"
"debug/elf"
"debug/macho"
"fmt" "fmt"
"go/format" "go/format"
"internal/race" "internal/race"
...@@ -4331,3 +4333,59 @@ func TestListTests(t *testing.T) { ...@@ -4331,3 +4333,59 @@ func TestListTests(t *testing.T) {
t.Run("Example1", testWith("Example", "ExampleSimple")) t.Run("Example1", testWith("Example", "ExampleSimple"))
t.Run("Example2", testWith("Example", "ExampleWithEmptyOutput")) t.Run("Example2", testWith("Example", "ExampleWithEmptyOutput"))
} }
func TestBuildmodePIE(t *testing.T) {
if runtime.Compiler == "gccgo" {
t.Skipf("skipping test because buildmode=pie is not supported on gccgo")
}
platform := fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)
switch platform {
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x",
"android/amd64", "android/arm", "android/arm64", "android/386":
case "darwin/amd64":
default:
t.Skipf("skipping test because buildmode=pie is not supported on %s", platform)
}
tg := testgo(t)
defer tg.cleanup()
tg.tempFile("main.go", `package main; func main() { print("hello") }`)
src := tg.path("main.go")
obj := tg.path("main")
tg.run("build", "-buildmode=pie", "-o", obj, src)
switch runtime.GOOS {
case "linux", "android":
f, err := elf.Open(obj)
if err != nil {
t.Fatal(err)
}
if f.Type != elf.ET_DYN {
t.Errorf("PIE type must be ET_DYN, but %s", f.Type)
}
case "darwin":
f, err := macho.Open(obj)
if err != nil {
t.Fatal(err)
}
if f.Flags&macho.FlagDyldLink == 0 {
t.Error("PIE must have DyldLink flag, but not")
}
if f.Flags&macho.FlagPIE == 0 {
t.Error("PIE must have PIE flag, but not")
}
default:
panic("unreachable")
}
out, err := exec.Command(obj).CombinedOutput()
if err != nil {
t.Fatal(err)
}
if string(out) != "hello" {
t.Errorf("got %q; want %q", out, "hello")
}
}
...@@ -327,6 +327,8 @@ func BuildModeInit() { ...@@ -327,6 +327,8 @@ func BuildModeInit() {
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x", case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x",
"android/amd64", "android/arm", "android/arm64", "android/386": "android/amd64", "android/arm", "android/arm64", "android/386":
codegenArg = "-shared" codegenArg = "-shared"
case "darwin/amd64":
codegenArg = "-shared"
default: default:
base.Fatalf("-buildmode=pie not supported on %s\n", platform) base.Fatalf("-buildmode=pie not supported on %s\n", platform)
} }
......
...@@ -44,6 +44,12 @@ func (mode *BuildMode) Set(s string) error { ...@@ -44,6 +44,12 @@ func (mode *BuildMode) Set(s string) error {
case "pie": case "pie":
switch objabi.GOOS { switch objabi.GOOS {
case "android", "linux": case "android", "linux":
case "darwin":
switch objabi.GOARCH {
case "amd64":
default:
return badmode()
}
default: default:
return badmode() return badmode()
} }
......
...@@ -1095,7 +1095,7 @@ func (l *Link) hostlink() { ...@@ -1095,7 +1095,7 @@ func (l *Link) hostlink() {
argv = append(argv, "-Wl,-headerpad,1144") argv = append(argv, "-Wl,-headerpad,1144")
if l.DynlinkingGo() { if l.DynlinkingGo() {
argv = append(argv, "-Wl,-flat_namespace") argv = append(argv, "-Wl,-flat_namespace")
} else if !SysArch.InFamily(sys.ARM64) { } else if !SysArch.InFamily(sys.ARM64) && Buildmode != BuildmodePIE {
argv = append(argv, "-Wl,-no_pie") argv = append(argv, "-Wl,-no_pie")
} }
case objabi.Hopenbsd: case objabi.Hopenbsd:
...@@ -1114,10 +1114,13 @@ func (l *Link) hostlink() { ...@@ -1114,10 +1114,13 @@ func (l *Link) hostlink() {
argv = append(argv, "-Wl,-pagezero_size,4000000") argv = append(argv, "-Wl,-pagezero_size,4000000")
} }
case BuildmodePIE: case BuildmodePIE:
// ELF.
if Headtype != objabi.Hdarwin {
if UseRelro() { if UseRelro() {
argv = append(argv, "-Wl,-z,relro") argv = append(argv, "-Wl,-z,relro")
} }
argv = append(argv, "-pie") argv = append(argv, "-pie")
}
case BuildmodeCShared: case BuildmodeCShared:
if Headtype == objabi.Hdarwin { if Headtype == objabi.Hdarwin {
argv = append(argv, "-dynamiclib") argv = append(argv, "-dynamiclib")
......
...@@ -401,8 +401,8 @@ func machoshbits(ctxt *Link, mseg *MachoSeg, sect *Section, segname string) { ...@@ -401,8 +401,8 @@ func machoshbits(ctxt *Link, mseg *MachoSeg, sect *Section, segname string) {
var msect *MachoSect var msect *MachoSect
if sect.Rwx&1 == 0 && segname != "__DWARF" && (SysArch.Family == sys.ARM64 || if sect.Rwx&1 == 0 && segname != "__DWARF" && (SysArch.Family == sys.ARM64 ||
(SysArch.Family == sys.AMD64 && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive || Buildmode == BuildmodePlugin)) || (SysArch.Family == sys.AMD64 && Buildmode != BuildmodeExe) ||
(SysArch.Family == sys.ARM && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive || Buildmode == BuildmodePlugin))) { (SysArch.Family == sys.ARM && Buildmode != BuildmodeExe)) {
// Darwin external linker on arm64 and on amd64 and arm in c-shared/c-archive buildmode // Darwin external linker on arm64 and on amd64 and arm in c-shared/c-archive buildmode
// complains about absolute relocs in __TEXT, so if the section is not // complains about absolute relocs in __TEXT, so if the section is not
// executable, put it in __DATA segment. // executable, put it in __DATA segment.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment