aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorCherry Zhang <cherryyz@google.com>2020-05-21 14:08:32 -0400
committerCherry Zhang <cherryyz@google.com>2020-05-21 14:08:32 -0400
commit6097f7cf7a9a9bf877f6f49112ffcc2d0f0e7e75 (patch)
treec42265e0cfb4ac2bbcf4a9ed9432748997d2362a /src/cmd
parent8e4ab9cb4c28649be36f82a02d04eb1cb31d02c9 (diff)
parentc847589ad06a1acfcceaac7b230c0d5a826caab8 (diff)
downloadgo-6097f7cf7a9a9bf877f6f49112ffcc2d0f0e7e75.tar.xz
[dev.link] all: merge branch 'master' into dev.link
Change-Id: I85b653b621ad8cb2ef27886210ea2c4b7409b60d
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/compile/internal/gc/pgen.go25
-rw-r--r--src/cmd/dist/build.go11
-rw-r--r--src/cmd/dist/buildruntime.go2
-rw-r--r--src/cmd/go.mod2
-rw-r--r--src/cmd/go.sum4
-rw-r--r--src/cmd/go/alldocs.go3
-rw-r--r--src/cmd/go/internal/cfg/cfg.go3
-rw-r--r--src/cmd/go/internal/help/helpdoc.go3
-rw-r--r--src/cmd/go/internal/modfetch/proxy.go10
-rw-r--r--src/cmd/go/internal/work/exec.go14
-rw-r--r--src/cmd/go/note_test.go2
-rw-r--r--src/cmd/go/testdata/script/issue36000.txt6
-rw-r--r--src/cmd/go/testdata/script/mod_gonoproxy.txt10
-rw-r--r--src/cmd/internal/obj/objfile.go8
-rw-r--r--src/cmd/internal/objabi/util.go11
-rw-r--r--src/cmd/link/internal/arm/asm.go6
-rw-r--r--src/cmd/link/internal/ld/fallocate_test.go50
-rw-r--r--src/cmd/link/internal/ld/outbuf_darwin.go17
-rw-r--r--src/cmd/link/internal/ld/pcln.go2
-rw-r--r--src/cmd/link/internal/loader/loader.go14
-rw-r--r--src/cmd/link/internal/ppc64/asm.go10
-rw-r--r--src/cmd/link/link_test.go19
-rw-r--r--src/cmd/vendor/modules.txt2
23 files changed, 179 insertions, 55 deletions
diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go
index 6ccd0b8d94..74654c86bc 100644
--- a/src/cmd/compile/internal/gc/pgen.go
+++ b/src/cmd/compile/internal/gc/pgen.go
@@ -271,7 +271,7 @@ func compile(fn *Node) {
}
}
- if compilenow() {
+ if compilenow(fn) {
compileSSA(fn, 0)
} else {
compilequeue = append(compilequeue, fn)
@@ -282,10 +282,31 @@ func compile(fn *Node) {
// If functions are not compiled immediately,
// they are enqueued in compilequeue,
// which is drained by compileFunctions.
-func compilenow() bool {
+func compilenow(fn *Node) bool {
+ // Issue 38068: if this function is a method AND an inline
+ // candidate AND was not inlined (yet), put it onto the compile
+ // queue instead of compiling it immediately. This is in case we
+ // wind up inlining it into a method wrapper that is generated by
+ // compiling a function later on in the xtop list.
+ if fn.IsMethod() && isInlinableButNotInlined(fn) {
+ return false
+ }
return nBackendWorkers == 1 && Debug_compilelater == 0
}
+// isInlinableButNotInlined returns true if 'fn' was marked as an
+// inline candidate but then never inlined (presumably because we
+// found no call sites).
+func isInlinableButNotInlined(fn *Node) bool {
+ if fn.Func.Nname.Func.Inl == nil {
+ return false
+ }
+ if fn.Sym == nil {
+ return true
+ }
+ return !fn.Sym.Linksym().WasInlined()
+}
+
const maxStackSize = 1 << 30
// compileSSA builds an SSA backend function,
diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go
index d22ee1d361..9e2b4f33b8 100644
--- a/src/cmd/dist/build.go
+++ b/src/cmd/dist/build.go
@@ -31,7 +31,6 @@ var (
goos string
goarm string
go386 string
- goamd64 string
gomips string
gomips64 string
goppc64 string
@@ -152,12 +151,6 @@ func xinit() {
}
go386 = b
- b = os.Getenv("GOAMD64")
- if b == "" {
- b = "alignedjumps"
- }
- goamd64 = b
-
b = os.Getenv("GOMIPS")
if b == "" {
b = "hardfloat"
@@ -230,7 +223,6 @@ func xinit() {
// For tools being invoked but also for os.ExpandEnv.
os.Setenv("GO386", go386)
- os.Setenv("GOAMD64", goamd64)
os.Setenv("GOARCH", goarch)
os.Setenv("GOARM", goarm)
os.Setenv("GOHOSTARCH", gohostarch)
@@ -1171,9 +1163,6 @@ func cmdenv() {
if goarch == "386" {
xprintf(format, "GO386", go386)
}
- if goarch == "amd64" {
- xprintf(format, "GOAMD64", goamd64)
- }
if goarch == "mips" || goarch == "mipsle" {
xprintf(format, "GOMIPS", gomips)
}
diff --git a/src/cmd/dist/buildruntime.go b/src/cmd/dist/buildruntime.go
index f11933c925..2744951597 100644
--- a/src/cmd/dist/buildruntime.go
+++ b/src/cmd/dist/buildruntime.go
@@ -42,7 +42,6 @@ func mkzversion(dir, file string) {
//
// const defaultGOROOT = <goroot>
// const defaultGO386 = <go386>
-// const defaultGOAMD64 = <goamd64>
// const defaultGOARM = <goarm>
// const defaultGOMIPS = <gomips>
// const defaultGOMIPS64 = <gomips64>
@@ -72,7 +71,6 @@ func mkzbootstrap(file string) {
fmt.Fprintf(&buf, "import \"runtime\"\n")
fmt.Fprintln(&buf)
fmt.Fprintf(&buf, "const defaultGO386 = `%s`\n", go386)
- fmt.Fprintf(&buf, "const defaultGOAMD64 = `%s`\n", goamd64)
fmt.Fprintf(&buf, "const defaultGOARM = `%s`\n", goarm)
fmt.Fprintf(&buf, "const defaultGOMIPS = `%s`\n", gomips)
fmt.Fprintf(&buf, "const defaultGOMIPS64 = `%s`\n", gomips64)
diff --git a/src/cmd/go.mod b/src/cmd/go.mod
index 9c78cd14e6..d56dde8a2a 100644
--- a/src/cmd/go.mod
+++ b/src/cmd/go.mod
@@ -7,7 +7,7 @@ require (
github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340 // indirect
golang.org/x/arch v0.0.0-20200511175325-f7c78586839d
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79
- golang.org/x/mod v0.2.1-0.20200429172858-859b3ef565e2
+ golang.org/x/mod v0.3.0
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 // indirect
golang.org/x/tools v0.0.0-20200504152539-33427f1b0364
)
diff --git a/src/cmd/go.sum b/src/cmd/go.sum
index f1b3754aad..922df777be 100644
--- a/src/cmd/go.sum
+++ b/src/cmd/go.sum
@@ -14,8 +14,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88=
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.2.1-0.20200429172858-859b3ef565e2 h1:VUsRDZIYpMs3R7PyYeN7BSbDfYjhxaX6HlWvM5iAEqs=
-golang.org/x/mod v0.2.1-0.20200429172858-859b3ef565e2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index 5c1f7254bf..fdeef651c7 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -1754,9 +1754,6 @@
// GO386
// For GOARCH=386, the floating point instruction set.
// Valid values are 387, sse2.
-// GOAMD64
-// For GOARCH=amd64, jumps can be optionally be aligned such that they do not end on
-// or cross 32 byte boundaries. Valid values are alignedjumps (default), normaljumps.
// GOMIPS
// For GOARCH=mips{,le}, whether to use floating point instructions.
// Valid values are hardfloat (default), softfloat.
diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go
index 21f55e852f..7f8f8e92be 100644
--- a/src/cmd/go/internal/cfg/cfg.go
+++ b/src/cmd/go/internal/cfg/cfg.go
@@ -241,7 +241,6 @@ var (
// Used in envcmd.MkEnv and build ID computations.
GOARM = envOr("GOARM", fmt.Sprint(objabi.GOARM))
GO386 = envOr("GO386", objabi.GO386)
- GOAMD64 = envOr("GOAMD64", objabi.GOAMD64)
GOMIPS = envOr("GOMIPS", objabi.GOMIPS)
GOMIPS64 = envOr("GOMIPS64", objabi.GOMIPS64)
GOPPC64 = envOr("GOPPC64", fmt.Sprintf("%s%d", "power", objabi.GOPPC64))
@@ -267,8 +266,6 @@ func GetArchEnv() (key, val string) {
return "GOARM", GOARM
case "386":
return "GO386", GO386
- case "amd64":
- return "GOAMD64", GOAMD64
case "mips", "mipsle":
return "GOMIPS", GOMIPS
case "mips64", "mips64le":
diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go
index 9583b3f327..693de8ff49 100644
--- a/src/cmd/go/internal/help/helpdoc.go
+++ b/src/cmd/go/internal/help/helpdoc.go
@@ -582,9 +582,6 @@ Architecture-specific environment variables:
GO386
For GOARCH=386, the floating point instruction set.
Valid values are 387, sse2.
- GOAMD64
- For GOARCH=amd64, jumps can be optionally be aligned such that they do not end on
- or cross 32 byte boundaries. Valid values are alignedjumps (default), normaljumps.
GOMIPS
For GOARCH=mips{,le}, whether to use floating point instructions.
Valid values are hardfloat (default), softfloat.
diff --git a/src/cmd/go/internal/modfetch/proxy.go b/src/cmd/go/internal/modfetch/proxy.go
index 0ca43d4c4a..3971598733 100644
--- a/src/cmd/go/internal/modfetch/proxy.go
+++ b/src/cmd/go/internal/modfetch/proxy.go
@@ -196,8 +196,12 @@ func TryProxies(f func(proxy string) error) error {
// We try to report the most helpful error to the user. "direct" and "noproxy"
// errors are best, followed by proxy errors other than ErrNotExist, followed
- // by ErrNotExist. Note that errProxyOff, errNoproxy, and errUseProxy are
- // equivalent to ErrNotExist.
+ // by ErrNotExist.
+ //
+ // Note that errProxyOff, errNoproxy, and errUseProxy are equivalent to
+ // ErrNotExist. errUseProxy should only be returned if "noproxy" is the only
+ // proxy. errNoproxy should never be returned, since there should always be a
+ // more useful error from "noproxy" first.
const (
notExistRank = iota
proxyRank
@@ -212,7 +216,7 @@ func TryProxies(f func(proxy string) error) error {
}
isNotExistErr := errors.Is(err, os.ErrNotExist)
- if proxy.url == "direct" || proxy.url == "noproxy" {
+ if proxy.url == "direct" || (proxy.url == "noproxy" && err != errUseProxy) {
bestErr = err
bestErrRank = directRank
} else if bestErrRank <= proxyRank && !isNotExistErr {
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index 6ab3498c3e..071c9d2db9 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -2434,13 +2434,25 @@ func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool {
if b.flagCache == nil {
b.flagCache = make(map[[2]string]bool)
}
+
+ tmp := os.DevNull
+ if runtime.GOOS == "windows" {
+ f, err := ioutil.TempFile(b.WorkDir, "")
+ if err != nil {
+ return false
+ }
+ f.Close()
+ tmp = f.Name()
+ defer os.Remove(tmp)
+ }
+
// We used to write an empty C file, but that gets complicated with
// go build -n. We tried using a file that does not exist, but that
// fails on systems with GCC version 4.2.1; that is the last GPLv2
// version of GCC, so some systems have frozen on it.
// Now we pass an empty file on stdin, which should work at least for
// GCC and clang.
- cmdArgs := str.StringList(compiler, flag, "-c", "-x", "c", "-", "-o", os.DevNull)
+ cmdArgs := str.StringList(compiler, flag, "-c", "-x", "c", "-", "-o", tmp)
if cfg.BuildN || cfg.BuildX {
b.Showcmd(b.WorkDir, "%s || true", joinUnambiguously(cmdArgs))
if cfg.BuildN {
diff --git a/src/cmd/go/note_test.go b/src/cmd/go/note_test.go
index 089e2f3376..659366dcf9 100644
--- a/src/cmd/go/note_test.go
+++ b/src/cmd/go/note_test.go
@@ -53,7 +53,7 @@ func TestNoteReading(t *testing.T) {
// we've had trouble reading the notes generated by gold.
err := tg.doRun([]string{"build", "-ldflags", "-buildid=" + buildID + " -linkmode=external -extldflags=-fuse-ld=gold", "-o", tg.path("hello3.exe"), tg.path("hello.go")})
if err != nil {
- if tg.grepCountBoth("(invalid linker|gold|cannot find 'ld')") > 0 {
+ if tg.grepCountBoth("(invalid linker|gold|cannot find [‘']ld[’'])") > 0 {
// It's not an error if gold isn't there. gcc claims it "cannot find 'ld'" if
// ld.gold is missing, see issue #22340.
t.Log("skipping gold test")
diff --git a/src/cmd/go/testdata/script/issue36000.txt b/src/cmd/go/testdata/script/issue36000.txt
new file mode 100644
index 0000000000..41732751ac
--- /dev/null
+++ b/src/cmd/go/testdata/script/issue36000.txt
@@ -0,0 +1,6 @@
+# Tests golang.org/issue/36000
+
+[!cgo] skip
+
+# go env with CGO flags should not make NUL file
+go env CGO_CFLAGS
diff --git a/src/cmd/go/testdata/script/mod_gonoproxy.txt b/src/cmd/go/testdata/script/mod_gonoproxy.txt
index 2bd94cdee0..d7848c7d26 100644
--- a/src/cmd/go/testdata/script/mod_gonoproxy.txt
+++ b/src/cmd/go/testdata/script/mod_gonoproxy.txt
@@ -10,7 +10,7 @@ env GOSUMDB=$sumdb' '$proxy/sumdb-wrong
! go get rsc.io/quote
stderr 'SECURITY ERROR'
-# but GONOSUMDB bypasses sumdb, for rsc.io/quote, rsc.io/sampler, golang.org/x/text
+# GONOSUMDB bypasses sumdb, for rsc.io/quote, rsc.io/sampler, golang.org/x/text
env GONOSUMDB='*/quote,*/*mple*,golang.org/x'
go get rsc.io/quote
rm go.sum
@@ -18,7 +18,13 @@ env GOPRIVATE='*/quote,*/*mple*,golang.org/x'
env GONOPROXY=none # that is, proxy all despite GOPRIVATE
go get rsc.io/quote
-# and GONOPROXY bypasses proxy
+# When GOPROXY=off, fetching modules not matched by GONOPROXY fails.
+env GONOPROXY=*/fortune
+env GOPROXY=off
+! go get golang.org/x/text
+stderr '^go get golang.org/x/text: module lookup disabled by GOPROXY=off$'
+
+# GONOPROXY bypasses proxy
[!net] skip
[!exec:git] skip
env GOPRIVATE=none
diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go
index 6701b9bfba..5e7018eb6e 100644
--- a/src/cmd/internal/obj/objfile.go
+++ b/src/cmd/internal/obj/objfile.go
@@ -425,6 +425,14 @@ func (ft *DwarfFixupTable) SetPrecursorFunc(s *LSym, fn interface{}) {
absfn.Type = objabi.SDWARFINFO
ft.ctxt.Data = append(ft.ctxt.Data, absfn)
+ // In the case of "late" inlining (inlines that happen during
+ // wrapper generation as opposed to the main inlining phase) it's
+ // possible that we didn't cache the abstract function sym for the
+ // text symbol -- do so now if needed. See issue 38068.
+ if s.Func != nil && s.Func.dwarfAbsFnSym == nil {
+ s.Func.dwarfAbsFnSym = absfn
+ }
+
ft.precursor[s] = fnState{precursor: fn, absfn: absfn}
}
diff --git a/src/cmd/internal/objabi/util.go b/src/cmd/internal/objabi/util.go
index 72dd5856f8..2f94ec6a67 100644
--- a/src/cmd/internal/objabi/util.go
+++ b/src/cmd/internal/objabi/util.go
@@ -37,16 +37,13 @@ var (
const (
ElfRelocOffset = 256
- MachoRelocOffset = 2048 // reserve enough space for ELF relocations
+ MachoRelocOffset = 2048 // reserve enough space for ELF relocations
+ Go115AMD64 = "alignedjumps" // Should be "alignedjumps" or "normaljumps"; this replaces environment variable introduced in CL 219357.
)
+// TODO(1.16): assuming no issues in 1.15 release, remove this and related constant.
func goamd64() string {
- switch v := envOr("GOAMD64", defaultGOAMD64); v {
- case "normaljumps", "alignedjumps":
- return v
- }
- log.Fatalf("Invalid GOAMD64 value. Must be normaljumps or alignedjumps.")
- panic("unreachable")
+ return Go115AMD64
}
func goarm() int {
diff --git a/src/cmd/link/internal/arm/asm.go b/src/cmd/link/internal/arm/asm.go
index 08f6c765c6..357a22b879 100644
--- a/src/cmd/link/internal/arm/asm.go
+++ b/src/cmd/link/internal/arm/asm.go
@@ -385,12 +385,16 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
offset := (signext24(r.Add()&0xffffff) + 2) * 4
var tramp loader.Sym
for i := 0; ; i++ {
- name := ldr.SymName(rs) + fmt.Sprintf("%+d-tramp%d", offset, i)
+ oName := ldr.SymName(rs)
+ name := oName + fmt.Sprintf("%+d-tramp%d", offset, i)
tramp = ldr.LookupOrCreateSym(name, int(ldr.SymVersion(rs)))
if ldr.SymType(tramp) == sym.SDYNIMPORT {
// don't reuse trampoline defined in other module
continue
}
+ if oName == "runtime.deferreturn" {
+ ldr.SetIsDeferReturnTramp(tramp, true)
+ }
if ldr.SymValue(tramp) == 0 {
// either the trampoline does not exist -- we need to create one,
// or found one the address which is not assigned -- this will be
diff --git a/src/cmd/link/internal/ld/fallocate_test.go b/src/cmd/link/internal/ld/fallocate_test.go
new file mode 100644
index 0000000000..a064bea23d
--- /dev/null
+++ b/src/cmd/link/internal/ld/fallocate_test.go
@@ -0,0 +1,50 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin linux
+
+package ld
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "syscall"
+ "testing"
+)
+
+func TestFallocate(t *testing.T) {
+ dir, err := ioutil.TempDir("", "TestFallocate")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(dir)
+ filename := filepath.Join(dir, "a.out")
+ out := NewOutBuf(nil)
+ err = out.Open(filename)
+ if err != nil {
+ t.Fatalf("Open file failed: %v", err)
+ }
+ defer out.Close()
+
+ // Mmap 1 MiB initially, and grow to 2 and 3 MiB.
+ // Check if the file size and disk usage is expected.
+ for _, sz := range []int64{1 << 20, 2 << 20, 3 << 20} {
+ err = out.Mmap(uint64(sz))
+ if err != nil {
+ t.Fatalf("Mmap failed: %v", err)
+ }
+ stat, err := os.Stat(filename)
+ if err != nil {
+ t.Fatalf("Stat failed: %v", err)
+ }
+ if got := stat.Size(); got != sz {
+ t.Errorf("unexpected file size: got %d, want %d", got, sz)
+ }
+ if got, want := stat.Sys().(*syscall.Stat_t).Blocks, (sz+511)/512; got != want {
+ t.Errorf("unexpected disk usage: got %d blocks, want %d", got, want)
+ }
+ out.munmap()
+ }
+}
diff --git a/src/cmd/link/internal/ld/outbuf_darwin.go b/src/cmd/link/internal/ld/outbuf_darwin.go
index 299902ec62..9a74ba875e 100644
--- a/src/cmd/link/internal/ld/outbuf_darwin.go
+++ b/src/cmd/link/internal/ld/outbuf_darwin.go
@@ -10,16 +10,25 @@ import (
)
func (out *OutBuf) fallocate(size uint64) error {
+ stat, err := out.f.Stat()
+ if err != nil {
+ return err
+ }
+ cursize := uint64(stat.Size())
+ if size <= cursize {
+ return nil
+ }
+
store := &syscall.Fstore_t{
Flags: syscall.F_ALLOCATEALL,
Posmode: syscall.F_PEOFPOSMODE,
Offset: 0,
- Length: int64(size),
+ Length: int64(size - cursize), // F_PEOFPOSMODE allocates from the end of the file, so we want the size difference here
}
- _, _, err := syscall.Syscall(syscall.SYS_FCNTL, uintptr(out.f.Fd()), syscall.F_PREALLOCATE, uintptr(unsafe.Pointer(store)))
- if err != 0 {
- return err
+ _, _, errno := syscall.Syscall(syscall.SYS_FCNTL, uintptr(out.f.Fd()), syscall.F_PREALLOCATE, uintptr(unsafe.Pointer(store)))
+ if errno != 0 {
+ return errno
}
return nil
diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go
index dc2fb70175..a5f776ebff 100644
--- a/src/cmd/link/internal/ld/pcln.go
+++ b/src/cmd/link/internal/ld/pcln.go
@@ -161,7 +161,7 @@ func (state *pclnState) computeDeferReturn(target *Target, s loader.Sym) uint32
// set the resumption point to PC_B.
lastWasmAddr = uint32(r.Add())
}
- if r.Type().IsDirectCall() && r.Sym() == state.deferReturnSym {
+ if r.Type().IsDirectCall() && (r.Sym() == state.deferReturnSym || state.ldr.IsDeferReturnTramp(r.Sym())) {
if target.IsWasm() {
deferreturn = lastWasmAddr - 1
} else {
diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go
index b9e063288a..e340506978 100644
--- a/src/cmd/link/internal/loader/loader.go
+++ b/src/cmd/link/internal/loader/loader.go
@@ -229,7 +229,8 @@ type Loader struct {
outdata [][]byte // symbol's data in the output buffer
extRelocs [][]ExtReloc // symbol's external relocations
- itablink map[Sym]struct{} // itablink[j] defined if j is go.itablink.*
+ itablink map[Sym]struct{} // itablink[j] defined if j is go.itablink.*
+ deferReturnTramp map[Sym]bool // whether the symbol is a trampoline of a deferreturn call
objByPkg map[string]*oReader // map package path to its Go object reader
@@ -354,6 +355,7 @@ func NewLoader(flags uint32, elfsetstring elfsetstringFunc, reporter *ErrorRepor
attrCgoExportDynamic: make(map[Sym]struct{}),
attrCgoExportStatic: make(map[Sym]struct{}),
itablink: make(map[Sym]struct{}),
+ deferReturnTramp: make(map[Sym]bool),
extStaticSyms: make(map[nameVer]Sym),
builtinSyms: make([]Sym, nbuiltin),
flags: flags,
@@ -1050,6 +1052,16 @@ func (l *Loader) IsItabLink(i Sym) bool {
return false
}
+// Return whether this is a trampoline of a deferreturn call.
+func (l *Loader) IsDeferReturnTramp(i Sym) bool {
+ return l.deferReturnTramp[i]
+}
+
+// Set that i is a trampoline of a deferreturn call.
+func (l *Loader) SetIsDeferReturnTramp(i Sym, v bool) {
+ l.deferReturnTramp[i] = v
+}
+
// growValues grows the slice used to store symbol values.
func (l *Loader) growValues(reqLen int) {
curLen := len(l.values)
diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go
index ee14601caa..aae42c0bbc 100644
--- a/src/cmd/link/internal/ppc64/asm.go
+++ b/src/cmd/link/internal/ppc64/asm.go
@@ -686,16 +686,20 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
// target is at some offset within the function. Calls to duff+8 and duff+256 must appear as
// distinct trampolines.
- name := ldr.SymName(rs)
+ oName := ldr.SymName(rs)
+ name := oName
if r.Add() == 0 {
- name = name + fmt.Sprintf("-tramp%d", i)
+ name += fmt.Sprintf("-tramp%d", i)
} else {
- name = name + fmt.Sprintf("%+x-tramp%d", r.Add(), i)
+ name += fmt.Sprintf("%+x-tramp%d", r.Add(), i)
}
// Look up the trampoline in case it already exists
tramp = ldr.LookupOrCreateSym(name, int(ldr.SymVersion(rs)))
+ if oName == "runtime.deferreturn" {
+ ldr.SetIsDeferReturnTramp(tramp, true)
+ }
if ldr.SymValue(tramp) == 0 {
break
}
diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go
index 145eb3c4ae..635c55dce6 100644
--- a/src/cmd/link/link_test.go
+++ b/src/cmd/link/link_test.go
@@ -605,10 +605,23 @@ func TestFuncAlign(t *testing.T) {
}
}
-const helloSrc = `
+const testTrampSrc = `
package main
import "fmt"
-func main() { fmt.Println("hello") }
+func main() {
+ fmt.Println("hello")
+
+ defer func(){
+ if e := recover(); e == nil {
+ panic("did not panic")
+ }
+ }()
+ f1()
+}
+
+// Test deferreturn trampolines. See issue #39049.
+func f1() { defer f2() }
+func f2() { panic("XXX") }
`
func TestTrampoline(t *testing.T) {
@@ -631,7 +644,7 @@ func TestTrampoline(t *testing.T) {
defer os.RemoveAll(tmpdir)
src := filepath.Join(tmpdir, "hello.go")
- err = ioutil.WriteFile(src, []byte(helloSrc), 0666)
+ err = ioutil.WriteFile(src, []byte(testTrampSrc), 0666)
if err != nil {
t.Fatal(err)
}
diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt
index 0a3ea66ffd..8a7976a4bf 100644
--- a/src/cmd/vendor/modules.txt
+++ b/src/cmd/vendor/modules.txt
@@ -29,7 +29,7 @@ golang.org/x/arch/x86/x86asm
golang.org/x/crypto/ed25519
golang.org/x/crypto/ed25519/internal/edwards25519
golang.org/x/crypto/ssh/terminal
-# golang.org/x/mod v0.2.1-0.20200429172858-859b3ef565e2
+# golang.org/x/mod v0.3.0
## explicit
golang.org/x/mod/internal/lazyregexp
golang.org/x/mod/modfile