Skip to content

Commit

Permalink
cmd/go, cmd/link: enable buildmode=pie on darwin/amd64
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
hirochachacha authored and ianlancetaylor committed Aug 14, 2017
1 parent 9fbc06e commit b7c600d
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 6 deletions.
58 changes: 58 additions & 0 deletions src/cmd/go/go_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ package main_test

import (
"bytes"
"debug/elf"
"debug/macho"
"fmt"
"go/format"
"internal/race"
Expand Down Expand Up @@ -4331,3 +4333,59 @@ func TestListTests(t *testing.T) {
t.Run("Example1", testWith("Example", "ExampleSimple"))
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")
}
}
2 changes: 2 additions & 0 deletions src/cmd/go/internal/work/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ func BuildModeInit() {
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x",
"android/amd64", "android/arm", "android/arm64", "android/386":
codegenArg = "-shared"
case "darwin/amd64":
codegenArg = "-shared"
default:
base.Fatalf("-buildmode=pie not supported on %s\n", platform)
}
Expand Down
6 changes: 6 additions & 0 deletions src/cmd/link/internal/ld/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ func (mode *BuildMode) Set(s string) error {
case "pie":
switch objabi.GOOS {
case "android", "linux":
case "darwin":
switch objabi.GOARCH {
case "amd64":
default:
return badmode()
}
default:
return badmode()
}
Expand Down
11 changes: 7 additions & 4 deletions src/cmd/link/internal/ld/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -1095,7 +1095,7 @@ func (l *Link) hostlink() {
argv = append(argv, "-Wl,-headerpad,1144")
if l.DynlinkingGo() {
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")
}
case objabi.Hopenbsd:
Expand All @@ -1114,10 +1114,13 @@ func (l *Link) hostlink() {
argv = append(argv, "-Wl,-pagezero_size,4000000")
}
case BuildmodePIE:
if UseRelro() {
argv = append(argv, "-Wl,-z,relro")
// ELF.
if Headtype != objabi.Hdarwin {
if UseRelro() {
argv = append(argv, "-Wl,-z,relro")
}
argv = append(argv, "-pie")
}
argv = append(argv, "-pie")
case BuildmodeCShared:
if Headtype == objabi.Hdarwin {
argv = append(argv, "-dynamiclib")
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/link/internal/ld/macho.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,8 +401,8 @@ func machoshbits(ctxt *Link, mseg *MachoSeg, sect *Section, segname string) {

var msect *MachoSect
if sect.Rwx&1 == 0 && segname != "__DWARF" && (SysArch.Family == sys.ARM64 ||
(SysArch.Family == sys.AMD64 && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive || Buildmode == BuildmodePlugin)) ||
(SysArch.Family == sys.ARM && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive || Buildmode == BuildmodePlugin))) {
(SysArch.Family == sys.AMD64 && Buildmode != BuildmodeExe) ||
(SysArch.Family == sys.ARM && Buildmode != BuildmodeExe)) {
// 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
// executable, put it in __DATA segment.
Expand Down

0 comments on commit b7c600d

Please sign in to comment.