Skip to content

Commit b7c600d

Browse files
hirochachachaianlancetaylor
authored andcommitted
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/54790 Reviewed-by: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
1 parent 9fbc06e commit b7c600d

File tree

5 files changed

+75
-6
lines changed

5 files changed

+75
-6
lines changed

src/cmd/go/go_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package main_test
66

77
import (
88
"bytes"
9+
"debug/elf"
10+
"debug/macho"
911
"fmt"
1012
"go/format"
1113
"internal/race"
@@ -4331,3 +4333,59 @@ func TestListTests(t *testing.T) {
43314333
t.Run("Example1", testWith("Example", "ExampleSimple"))
43324334
t.Run("Example2", testWith("Example", "ExampleWithEmptyOutput"))
43334335
}
4336+
4337+
func TestBuildmodePIE(t *testing.T) {
4338+
if runtime.Compiler == "gccgo" {
4339+
t.Skipf("skipping test because buildmode=pie is not supported on gccgo")
4340+
}
4341+
4342+
platform := fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)
4343+
switch platform {
4344+
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x",
4345+
"android/amd64", "android/arm", "android/arm64", "android/386":
4346+
case "darwin/amd64":
4347+
default:
4348+
t.Skipf("skipping test because buildmode=pie is not supported on %s", platform)
4349+
}
4350+
4351+
tg := testgo(t)
4352+
defer tg.cleanup()
4353+
4354+
tg.tempFile("main.go", `package main; func main() { print("hello") }`)
4355+
src := tg.path("main.go")
4356+
obj := tg.path("main")
4357+
tg.run("build", "-buildmode=pie", "-o", obj, src)
4358+
4359+
switch runtime.GOOS {
4360+
case "linux", "android":
4361+
f, err := elf.Open(obj)
4362+
if err != nil {
4363+
t.Fatal(err)
4364+
}
4365+
if f.Type != elf.ET_DYN {
4366+
t.Errorf("PIE type must be ET_DYN, but %s", f.Type)
4367+
}
4368+
case "darwin":
4369+
f, err := macho.Open(obj)
4370+
if err != nil {
4371+
t.Fatal(err)
4372+
}
4373+
if f.Flags&macho.FlagDyldLink == 0 {
4374+
t.Error("PIE must have DyldLink flag, but not")
4375+
}
4376+
if f.Flags&macho.FlagPIE == 0 {
4377+
t.Error("PIE must have PIE flag, but not")
4378+
}
4379+
default:
4380+
panic("unreachable")
4381+
}
4382+
4383+
out, err := exec.Command(obj).CombinedOutput()
4384+
if err != nil {
4385+
t.Fatal(err)
4386+
}
4387+
4388+
if string(out) != "hello" {
4389+
t.Errorf("got %q; want %q", out, "hello")
4390+
}
4391+
}

src/cmd/go/internal/work/build.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,8 @@ func BuildModeInit() {
327327
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x",
328328
"android/amd64", "android/arm", "android/arm64", "android/386":
329329
codegenArg = "-shared"
330+
case "darwin/amd64":
331+
codegenArg = "-shared"
330332
default:
331333
base.Fatalf("-buildmode=pie not supported on %s\n", platform)
332334
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ func (mode *BuildMode) Set(s string) error {
4444
case "pie":
4545
switch objabi.GOOS {
4646
case "android", "linux":
47+
case "darwin":
48+
switch objabi.GOARCH {
49+
case "amd64":
50+
default:
51+
return badmode()
52+
}
4753
default:
4854
return badmode()
4955
}

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,7 +1095,7 @@ func (l *Link) hostlink() {
10951095
argv = append(argv, "-Wl,-headerpad,1144")
10961096
if l.DynlinkingGo() {
10971097
argv = append(argv, "-Wl,-flat_namespace")
1098-
} else if !SysArch.InFamily(sys.ARM64) {
1098+
} else if !SysArch.InFamily(sys.ARM64) && Buildmode != BuildmodePIE {
10991099
argv = append(argv, "-Wl,-no_pie")
11001100
}
11011101
case objabi.Hopenbsd:
@@ -1114,10 +1114,13 @@ func (l *Link) hostlink() {
11141114
argv = append(argv, "-Wl,-pagezero_size,4000000")
11151115
}
11161116
case BuildmodePIE:
1117-
if UseRelro() {
1118-
argv = append(argv, "-Wl,-z,relro")
1117+
// ELF.
1118+
if Headtype != objabi.Hdarwin {
1119+
if UseRelro() {
1120+
argv = append(argv, "-Wl,-z,relro")
1121+
}
1122+
argv = append(argv, "-pie")
11191123
}
1120-
argv = append(argv, "-pie")
11211124
case BuildmodeCShared:
11221125
if Headtype == objabi.Hdarwin {
11231126
argv = append(argv, "-dynamiclib")

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,8 @@ func machoshbits(ctxt *Link, mseg *MachoSeg, sect *Section, segname string) {
401401

402402
var msect *MachoSect
403403
if sect.Rwx&1 == 0 && segname != "__DWARF" && (SysArch.Family == sys.ARM64 ||
404-
(SysArch.Family == sys.AMD64 && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive || Buildmode == BuildmodePlugin)) ||
405-
(SysArch.Family == sys.ARM && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive || Buildmode == BuildmodePlugin))) {
404+
(SysArch.Family == sys.AMD64 && Buildmode != BuildmodeExe) ||
405+
(SysArch.Family == sys.ARM && Buildmode != BuildmodeExe)) {
406406
// Darwin external linker on arm64 and on amd64 and arm in c-shared/c-archive buildmode
407407
// complains about absolute relocs in __TEXT, so if the section is not
408408
// executable, put it in __DATA segment.

0 commit comments

Comments
 (0)