aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippo Valsorda <filippo@golang.org>2019-10-24 06:36:26 -0400
committerFilippo Valsorda <filippo@golang.org>2019-10-24 06:36:26 -0400
commitcba6efa89376c6a6660e1c24d5dadcd3fd0735b1 (patch)
treef815811b16e046ed6662bb2c195b276a4691d4b8
parent6a1c22797f9cf16e0098be1d618b6c49a3b9ec34 (diff)
parente64356a4484deb5da57396a4cd80e26667b86b79 (diff)
downloadgo-cba6efa89376c6a6660e1c24d5dadcd3fd0735b1.tar.gz
go-cba6efa89376c6a6660e1c24d5dadcd3fd0735b1.zip
[dev.boringcrypto.go1.13] all: merge go1.13.3 into dev.boringcrypto.go1.13
Change-Id: I6153fcf6c7b933ae651228e8ce3593e861c80e49
-rw-r--r--doc/devel/release.html15
-rw-r--r--doc/go1.13.html4
-rw-r--r--src/cmd/compile/internal/gc/noder.go8
-rw-r--r--src/cmd/compile/internal/gc/subr.go5
-rw-r--r--src/cmd/compile/internal/gc/typecheck.go2
-rw-r--r--src/cmd/cover/func.go4
-rw-r--r--src/cmd/go/alldocs.go1
-rw-r--r--src/cmd/go/internal/get/vcs.go4
-rw-r--r--src/cmd/go/internal/load/pkg.go11
-rw-r--r--src/cmd/go/internal/load/test.go11
-rw-r--r--src/cmd/go/internal/modcmd/download.go30
-rw-r--r--src/cmd/go/internal/modfetch/codehost/git.go68
-rw-r--r--src/cmd/go/internal/modfetch/coderepo_test.go8
-rw-r--r--src/cmd/go/internal/modload/import_test.go2
-rw-r--r--src/cmd/go/internal/modload/load.go5
-rw-r--r--src/cmd/go/internal/modload/query.go42
-rw-r--r--src/cmd/go/internal/search/search.go26
-rw-r--r--src/cmd/go/internal/test/test.go3
-rw-r--r--src/cmd/go/internal/work/exec.go10
-rw-r--r--src/cmd/go/script_test.go20
-rw-r--r--src/cmd/go/testdata/mod/example.com_dotgo.go_v1.0.0.txt16
-rw-r--r--src/cmd/go/testdata/script/build_trimpath.txt29
-rw-r--r--src/cmd/go/testdata/script/cover_mod_empty.txt9
-rw-r--r--src/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt21
-rw-r--r--src/cmd/go/testdata/script/get_insecure_redirect.txt5
-rw-r--r--src/cmd/go/testdata/script/list_ambiguous_path.txt37
-rw-r--r--src/cmd/go/testdata/script/list_split_main.txt25
-rw-r--r--src/cmd/go/testdata/script/mod_download.txt4
-rw-r--r--src/cmd/go/testdata/script/mod_download_latest.txt20
-rw-r--r--src/cmd/go/testdata/script/mod_get_direct.txt20
-rw-r--r--src/cmd/go/testdata/script/mod_get_insecure_redirect.txt13
-rw-r--r--src/cmd/go/testdata/script/mod_get_major.txt23
-rw-r--r--src/cmd/go/testdata/script/mod_get_patterns.txt4
-rw-r--r--src/cmd/go/testdata/script/mod_get_trailing_slash.txt30
-rw-r--r--src/cmd/go/testdata/script/mod_list_upgrade.txt20
-rw-r--r--src/cmd/go/testdata/script/mod_replace.txt7
-rw-r--r--src/cmd/go/testdata/script/test_timeout.txt11
-rw-r--r--src/crypto/ecdsa/ecdsa.go16
-rw-r--r--src/crypto/ecdsa/ecdsa_noasm.go22
-rw-r--r--src/crypto/ecdsa/ecdsa_s390x.go153
-rw-r--r--src/crypto/ecdsa/ecdsa_s390x.s31
-rw-r--r--src/crypto/ecdsa/ecdsa_s390x_test.go33
-rw-r--r--src/errors/errors.go8
-rw-r--r--src/internal/syscall/windows/mksyscall.go2
-rw-r--r--src/internal/syscall/windows/registry/mksyscall.go2
-rw-r--r--src/log/syslog/syslog_test.go6
-rw-r--r--src/net/dnsclient_unix.go8
-rw-r--r--src/net/dnsclient_unix_test.go47
-rw-r--r--src/net/http/client.go4
-rw-r--r--src/net/http/clone.go10
-rw-r--r--src/net/http/export_test.go24
-rw-r--r--src/net/http/h2_bundle.go9
-rw-r--r--src/net/http/header_test.go32
-rw-r--r--src/net/http/request_test.go28
-rw-r--r--src/net/http/server.go9
-rw-r--r--src/net/http/transport.go5
-rw-r--r--src/net/http/transport_test.go70
-rw-r--r--src/net/interface_test.go12
-rw-r--r--src/os/os_test.go5
-rw-r--r--src/runtime/export_test.go3
-rw-r--r--src/runtime/mgc.go9
-rw-r--r--src/runtime/mgcscavenge.go108
-rw-r--r--src/runtime/mheap.go96
-rw-r--r--src/runtime/mstats.go2
-rw-r--r--src/runtime/os_windows.go81
-rw-r--r--src/runtime/sys_darwin.go8
-rw-r--r--src/runtime/syscall_windows.go12
-rw-r--r--src/syscall/mksyscall_windows.go890
-rw-r--r--src/syscall/syscall.go2
-rw-r--r--src/syscall/syscall_darwin.go1
-rw-r--r--src/syscall/syscall_darwin_386.go1
-rw-r--r--src/syscall/syscall_darwin_amd64.go1
-rw-r--r--src/syscall/syscall_darwin_arm.go4
-rw-r--r--src/syscall/syscall_darwin_arm64.go4
-rw-r--r--src/syscall/zsyscall_darwin_386.go42
-rw-r--r--src/syscall/zsyscall_darwin_386.s4
-rw-r--r--src/syscall/zsyscall_darwin_amd64.go42
-rw-r--r--src/syscall/zsyscall_darwin_amd64.s4
-rw-r--r--src/syscall/zsyscall_darwin_arm.go21
-rw-r--r--src/syscall/zsyscall_darwin_arm.s2
-rw-r--r--src/syscall/zsyscall_darwin_arm64.go21
-rw-r--r--src/syscall/zsyscall_darwin_arm64.s2
-rw-r--r--test/fixedbugs/issue31747.go10
83 files changed, 952 insertions, 1527 deletions
diff --git a/doc/devel/release.html b/doc/devel/release.html
index fc858d418b..0ac3b86334 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -46,6 +46,14 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.13.2">Go
1.13.2 milestone</a> on our issue tracker for details.
</p>
+<p>
+go1.13.3 (released 2019/10/17) includes fixes to the go command,
+the toolchain, the runtime, <code>syscall</code>, <code>net</code>,
+<code>net/http</code>, and <code>crypto/ecdsa</code> packages.
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.13.3">Go
+1.13.3 milestone</a> on our issue tracker for details.
+</p>
+
<h2 id="go1.12">go1.12 (released 2019/02/25)</h2>
<p>
@@ -135,6 +143,13 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.11">Go
1.12.11 milestone</a> on our issue tracker for details.
</p>
+<p>
+go1.12.12 (released 2019/10/17) includes fixes to the go command,
+runtime, <code>syscall</code> and <code>net</code> packages.
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.12">Go
+1.12.12 milestone</a> on our issue tracker for details.
+</p>
+
<h2 id="go1.11">go1.11 (released 2018/08/24)</h2>
<p>
diff --git a/doc/go1.13.html b/doc/go1.13.html
index d5809d6ad1..d4a762721f 100644
--- a/doc/go1.13.html
+++ b/doc/go1.13.html
@@ -102,7 +102,7 @@ Do not send CLs removing the interior tags from such phrases.
<h2 id="ports">Ports</h2>
-<p>
+<p id="nacl">
Go 1.13 is the last release that will run on Native Client (NaCl).
</p>
@@ -821,7 +821,7 @@ godoc
<p><!-- CL 154383 -->
<a href="/pkg/net/http/#TimeoutHandler"><code>TimeoutHandler</code></a>'s
<a href="/pkg/net/http/#ResponseWriter"><code>ResponseWriter</code></a> now implements the
- <a href="/pkg/net/http/#Pusher"><code>Pusher</code></a> and <a href="/pkg/net/http/#Flusher"><code>Flusher</code></a> interfaces.
+ <a href="/pkg/net/http/#Pusher"><code>Pusher</code></a> interface.
</p>
<p><!-- CL 157339 -->
diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go
index 93d355278e..6aca89cad9 100644
--- a/src/cmd/compile/internal/gc/noder.go
+++ b/src/cmd/compile/internal/gc/noder.go
@@ -1330,7 +1330,7 @@ func checkLangCompat(lit *syntax.BasicLit) {
}
// len(s) > 2
if strings.Contains(s, "_") {
- yyerror("underscores in numeric literals only supported as of -lang=go1.13")
+ yyerrorv("go1.13", "underscores in numeric literals")
return
}
if s[0] != '0' {
@@ -1338,15 +1338,15 @@ func checkLangCompat(lit *syntax.BasicLit) {
}
base := s[1]
if base == 'b' || base == 'B' {
- yyerror("binary literals only supported as of -lang=go1.13")
+ yyerrorv("go1.13", "binary literals")
return
}
if base == 'o' || base == 'O' {
- yyerror("0o/0O-style octal literals only supported as of -lang=go1.13")
+ yyerrorv("go1.13", "0o/0O-style octal literals")
return
}
if lit.Kind != syntax.IntLit && (base == 'x' || base == 'X') {
- yyerror("hexadecimal floating-point literals only supported as of -lang=go1.13")
+ yyerrorv("go1.13", "hexadecimal floating-point literals")
}
}
diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go
index f3ec21c7cb..d33fd4eb6c 100644
--- a/src/cmd/compile/internal/gc/subr.go
+++ b/src/cmd/compile/internal/gc/subr.go
@@ -154,6 +154,11 @@ func yyerrorl(pos src.XPos, format string, args ...interface{}) {
}
}
+func yyerrorv(lang string, format string, args ...interface{}) {
+ what := fmt.Sprintf(format, args...)
+ yyerrorl(lineno, "%s requires %s or later (-lang was set to %s; check go.mod)", what, lang, flag_lang)
+}
+
func yyerror(format string, args ...interface{}) {
yyerrorl(lineno, format, args...)
}
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index 4cb28d6100..223e5add36 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -632,7 +632,7 @@ func typecheck1(n *Node, top int) (res *Node) {
return n
}
if t.IsSigned() && !langSupported(1, 13) {
- yyerror("invalid operation: %v (signed shift count type %v, only supported as of -lang=go1.13)", n, r.Type)
+ yyerrorv("go1.13", "invalid operation: %v (signed shift count type %v)", n, r.Type)
n.Type = nil
return n
}
diff --git a/src/cmd/cover/func.go b/src/cmd/cover/func.go
index fe64374189..988c4caebf 100644
--- a/src/cmd/cover/func.go
+++ b/src/cmd/cover/func.go
@@ -191,6 +191,10 @@ func findPkgs(profiles []*Profile) (map[string]*Pkg, error) {
}
}
+ if len(list) == 0 {
+ return pkgs, nil
+ }
+
// Note: usually run as "go tool cover" in which case $GOROOT is set,
// in which case runtime.GOROOT() does exactly what we want.
goTool := filepath.Join(runtime.GOROOT(), "bin/go")
diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index ebbead5d31..0a8935b6bc 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -1018,7 +1018,6 @@
// Dir string // absolute path to cached source root directory
// Sum string // checksum for path, version (as in go.sum)
// GoModSum string // checksum for go.mod (as in go.sum)
-// Latest bool // would @latest resolve to this version?
// }
//
// See 'go help modules' for more about module queries.
diff --git a/src/cmd/go/internal/get/vcs.go b/src/cmd/go/internal/get/vcs.go
index 705bb66dbe..6ae3cffd93 100644
--- a/src/cmd/go/internal/get/vcs.go
+++ b/src/cmd/go/internal/get/vcs.go
@@ -904,7 +904,7 @@ func metaImportsForPrefix(importPrefix string, mod ModuleMode, security web.Secu
}
resp, err := web.Get(security, url)
if err != nil {
- return setCache(fetchResult{url: url, err: fmt.Errorf("fetch %s: %v", resp.URL, err)})
+ return setCache(fetchResult{url: url, err: fmt.Errorf("fetching %s: %v", importPrefix, err)})
}
body := resp.Body
defer body.Close()
@@ -913,7 +913,7 @@ func metaImportsForPrefix(importPrefix string, mod ModuleMode, security web.Secu
return setCache(fetchResult{url: url, err: fmt.Errorf("parsing %s: %v", resp.URL, err)})
}
if len(imports) == 0 {
- err = fmt.Errorf("fetch %s: no go-import meta tag", url)
+ err = fmt.Errorf("fetching %s: no go-import meta tag found in %s", importPrefix, resp.URL)
}
return setCache(fetchResult{url: url, imports: imports, err: err})
})
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index 64267a4a46..07f7115e33 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -1956,9 +1956,14 @@ func Packages(args []string) []*Package {
// cannot be loaded at all.
// The packages that fail to load will have p.Error != nil.
func PackagesAndErrors(patterns []string) []*Package {
- if len(patterns) > 0 {
- for _, p := range patterns {
- if strings.HasSuffix(p, ".go") {
+ for _, p := range patterns {
+ // Listing is only supported with all patterns referring to either:
+ // - Files that are part of the same directory.
+ // - Explicit package paths or patterns.
+ if strings.HasSuffix(p, ".go") {
+ // We need to test whether the path is an actual Go file and not a
+ // package path or pattern ending in '.go' (see golang.org/issue/34653).
+ if fi, err := os.Stat(p); err == nil && !fi.IsDir() {
return []*Package{GoFilesPackage(patterns)}
}
}
diff --git a/src/cmd/go/internal/load/test.go b/src/cmd/go/internal/load/test.go
index afff5deaaa..aac7d7d481 100644
--- a/src/cmd/go/internal/load/test.go
+++ b/src/cmd/go/internal/load/test.go
@@ -399,10 +399,13 @@ func recompileForTest(pmain, preal, ptest, pxtest *Package) {
}
}
- // Don't compile build info from a main package. This can happen
- // if -coverpkg patterns include main packages, since those packages
- // are imported by pmain. See golang.org/issue/30907.
- if p.Internal.BuildInfo != "" && p != pmain {
+ // Force main packages the test imports to be built as libraries.
+ // Normal imports of main packages are forbidden by the package loader,
+ // but this can still happen if -coverpkg patterns include main packages:
+ // covered packages are imported by pmain. Linking multiple packages
+ // compiled with '-p main' causes duplicate symbol errors.
+ // See golang.org/issue/30907, golang.org/issue/34114.
+ if p.Name == "main" && p != pmain && p != ptest {
split()
}
}
diff --git a/src/cmd/go/internal/modcmd/download.go b/src/cmd/go/internal/modcmd/download.go
index 60d0d5b6e2..0d432e9549 100644
--- a/src/cmd/go/internal/modcmd/download.go
+++ b/src/cmd/go/internal/modcmd/download.go
@@ -43,7 +43,6 @@ corresponding to this Go struct:
Dir string // absolute path to cached source root directory
Sum string // checksum for path, version (as in go.sum)
GoModSum string // checksum for go.mod (as in go.sum)
- Latest bool // would @latest resolve to this version?
}
See 'go help modules' for more about module queries.
@@ -66,7 +65,6 @@ type moduleJSON struct {
Dir string `json:",omitempty"`
Sum string `json:",omitempty"`
GoModSum string `json:",omitempty"`
- Latest bool `json:",omitempty"`
}
func runDownload(cmd *base.Command, args []string) {
@@ -105,31 +103,6 @@ func runDownload(cmd *base.Command, args []string) {
work.Add(m)
}
- latest := map[string]string{} // path → version
- if *downloadJSON {
- // We need to populate the Latest field, but if the main module depends on a
- // version newer than latest — or if the version requested on the command
- // line is itself newer than latest — that's not trivial to determine from
- // the info returned by ListModules. Instead, we issue a separate
- // ListModules request for "latest", which should be inexpensive relative to
- // downloading the modules.
- var latestArgs []string
- for _, m := range mods {
- if m.Error != "" {
- continue
- }
- latestArgs = append(latestArgs, m.Path+"@latest")
- }
-
- if len(latestArgs) > 0 {
- for _, info := range modload.ListModules(latestArgs, listU, listVersions) {
- if info.Version != "" {
- latest[info.Path] = info.Version
- }
- }
- }
- }
-
work.Do(10, func(item interface{}) {
m := item.(*moduleJSON)
var err error
@@ -160,9 +133,6 @@ func runDownload(cmd *base.Command, args []string) {
m.Error = err.Error()
return
}
- if latest[m.Path] == m.Version {
- m.Latest = true
- }
})
if *downloadJSON {
diff --git a/src/cmd/go/internal/modfetch/codehost/git.go b/src/cmd/go/internal/modfetch/codehost/git.go
index d382e8ac9a..dc5add906b 100644
--- a/src/cmd/go/internal/modfetch/codehost/git.go
+++ b/src/cmd/go/internal/modfetch/codehost/git.go
@@ -241,13 +241,6 @@ func (r *gitRepo) findRef(hash string) (ref string, ok bool) {
return "", false
}
-func unshallow(gitDir string) []string {
- if _, err := os.Stat(filepath.Join(gitDir, "shallow")); err == nil {
- return []string{"--unshallow"}
- }
- return []string{}
-}
-
// minHashDigits is the minimum number of digits to require
// before accepting a hex digit sequence as potentially identifying
// a specific commit in a git repo. (Of course, users can always
@@ -397,29 +390,27 @@ func (r *gitRepo) stat(rev string) (*RevInfo, error) {
// fetchRefsLocked requires that r.mu remain locked for the duration of the call.
func (r *gitRepo) fetchRefsLocked() error {
if r.fetchLevel < fetchAll {
- if err := r.fetchUnshallow("refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"); err != nil {
+ // NOTE: To work around a bug affecting Git clients up to at least 2.23.0
+ // (2019-08-16), we must first expand the set of local refs, and only then
+ // unshallow the repository as a separate fetch operation. (See
+ // golang.org/issue/34266 and
+ // https://github.com/git/git/blob/4c86140027f4a0d2caaa3ab4bd8bfc5ce3c11c8a/transport.c#L1303-L1309.)
+
+ if _, err := Run(r.dir, "git", "fetch", "-f", r.remote, "refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"); err != nil {
return err
}
+
+ if _, err := os.Stat(filepath.Join(r.dir, "shallow")); err == nil {
+ if _, err := Run(r.dir, "git", "fetch", "--unshallow", "-f", r.remote); err != nil {
+ return err
+ }
+ }
+
r.fetchLevel = fetchAll
}
return nil
}
-func (r *gitRepo) fetchUnshallow(refSpecs ...string) error {
- // To work around a protocol version 2 bug that breaks --unshallow,
- // add -c protocol.version=0.
- // TODO(rsc): The bug is believed to be server-side, meaning only
- // on Google's Git servers. Once the servers are fixed, drop the
- // protocol.version=0. See Google-internal bug b/110495752.
- var protoFlag []string
- unshallowFlag := unshallow(r.dir)
- if len(unshallowFlag) > 0 {
- protoFlag = []string{"-c", "protocol.version=0"}
- }
- _, err := Run(r.dir, "git", protoFlag, "fetch", unshallowFlag, "-f", r.remote, refSpecs)
- return err
-}
-
// statLocal returns a RevInfo describing rev in the local git repository.
// It uses version as info.Version.
func (r *gitRepo) statLocal(version, rev string) (*RevInfo, error) {
@@ -539,39 +530,10 @@ func (r *gitRepo) ReadFileRevs(revs []string, file string, maxSize int64) (map[s
}
defer unlock()
- var refs []string
- var protoFlag []string
- var unshallowFlag []string
- for _, tag := range redo {
- refs = append(refs, "refs/tags/"+tag+":refs/tags/"+tag)
- }
- if len(refs) > 1 {
- unshallowFlag = unshallow(r.dir)
- if len(unshallowFlag) > 0 {
- // To work around a protocol version 2 bug that breaks --unshallow,
- // add -c protocol.version=0.
- // TODO(rsc): The bug is believed to be server-side, meaning only
- // on Google's Git servers. Once the servers are fixed, drop the
- // protocol.version=0. See Google-internal bug b/110495752.
- protoFlag = []string{"-c", "protocol.version=0"}
- }
- }
- if _, err := Run(r.dir, "git", protoFlag, "fetch", unshallowFlag, "-f", r.remote, refs); err != nil {
+ if err := r.fetchRefsLocked(); err != nil {
return nil, err
}
- // TODO(bcmills): after the 1.11 freeze, replace the block above with:
- // if r.fetchLevel <= fetchSome {
- // r.fetchLevel = fetchSome
- // var refs []string
- // for _, tag := range redo {
- // refs = append(refs, "refs/tags/"+tag+":refs/tags/"+tag)
- // }
- // if _, err := Run(r.dir, "git", "fetch", "--update-shallow", "-f", r.remote, refs); err != nil {
- // return nil, err
- // }
- // }
-
if _, err := r.readFileRevs(redo, file, files); err != nil {
return nil, err
}
diff --git a/src/cmd/go/internal/modfetch/coderepo_test.go b/src/cmd/go/internal/modfetch/coderepo_test.go
index 1f2b95bd23..663324b3dd 100644
--- a/src/cmd/go/internal/modfetch/coderepo_test.go
+++ b/src/cmd/go/internal/modfetch/coderepo_test.go
@@ -338,10 +338,10 @@ var codeRepoTests = []codeRepoTest{
vcs: "git",
path: "gopkg.in/yaml.v2",
rev: "v2",
- version: "v2.2.3-0.20190319135612-7b8349ac747c",
- name: "7b8349ac747c6a24702b762d2c4fd9266cf4f1d6",
- short: "7b8349ac747c",
- time: time.Date(2019, 03, 19, 13, 56, 12, 0, time.UTC),
+ version: "v2.2.5-0.20191002202810-970885f01c8b",
+ name: "970885f01c8bc1fecb7ab1c8ce8e7609bda45530",
+ short: "970885f01c8b",
+ time: time.Date(2019, 10, 2, 20, 28, 10, 0, time.UTC),
gomod: "module \"gopkg.in/yaml.v2\"\n\nrequire (\n\t\"gopkg.in/check.v1\" v0.0.0-20161208181325-20d25e280405\n)\n",
},
{
diff --git a/src/cmd/go/internal/modload/import_test.go b/src/cmd/go/internal/modload/import_test.go
index c6ade5d17f..c58892e2ab 100644
--- a/src/cmd/go/internal/modload/import_test.go
+++ b/src/cmd/go/internal/modload/import_test.go
@@ -21,7 +21,7 @@ var importTests = []struct {
},
{
path: "golang.org/x/net",
- err: "module golang.org/x/net@.* found, but does not contain package golang.org/x/net",
+ err: `module golang.org/x/net@.* found \(v0.0.0-.*\), but does not contain package golang.org/x/net`,
},
{
path: "golang.org/x/text",
diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go
index b50a084166..92e76a9246 100644
--- a/src/cmd/go/internal/modload/load.go
+++ b/src/cmd/go/internal/modload/load.go
@@ -1205,6 +1205,11 @@ func (*mvsReqs) next(m module.Version) (module.Version, error) {
return module.Version{Path: m.Path, Version: "none"}, nil
}
+// fetch downloads the given module (or its replacement)
+// and returns its location.
+//
+// The isLocal return value reports whether the replacement,
+// if any, is local to the filesystem.
func fetch(mod module.Version) (dir string, isLocal bool, err error) {
if mod == Target {
return ModRoot(), true, nil
diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go
index 602bf47275..75c18f25cc 100644
--- a/src/cmd/go/internal/modload/query.go
+++ b/src/cmd/go/internal/modload/query.go
@@ -381,9 +381,10 @@ func QueryPattern(pattern, query string, allowed func(module.Version) bool) ([]Q
r.Packages = match(r.Mod, root, isLocal)
if len(r.Packages) == 0 {
return r, &PackageNotInModuleError{
- Mod: r.Mod,
- Query: query,
- Pattern: pattern,
+ Mod: r.Mod,
+ Replacement: Replacement(r.Mod),
+ Query: query,
+ Pattern: pattern,
}
}
return r, nil
@@ -471,7 +472,17 @@ func queryPrefixModules(candidateModules []string, queryModule func(path string)
notExistErr = rErr
}
} else if err == nil {
- err = r.err
+ if len(found) > 0 || noPackage != nil {
+ // golang.org/issue/34094: If we have already found a module that
+ // could potentially contain the target package, ignore unclassified
+ // errors for modules with shorter paths.
+
+ // golang.org/issue/34383 is a special case of this: if we have
+ // already found example.com/foo/v2@v2.0.0 with a matching go.mod
+ // file, ignore the error from example.com/foo@v2.0.0.
+ } else {
+ err = r.err
+ }
}
}
}
@@ -526,21 +537,32 @@ func (e *NoMatchingVersionError) Error() string {
// code for the versions it knows about, and thus did not have the opportunity
// to return a non-400 status code to suppress fallback.
type PackageNotInModuleError struct {
- Mod module.Version
- Query string
- Pattern string
+ Mod module.Version
+ Replacement module.Version
+ Query string
+ Pattern string
}
func (e *PackageNotInModuleError) Error() string {
found := ""
- if e.Query != e.Mod.Version {
+ if r := e.Replacement; r.Path != "" {
+ replacement := r.Path
+ if r.Version != "" {
+ replacement = fmt.Sprintf("%s@%s", r.Path, r.Version)
+ }
+ if e.Query == e.Mod.Version {
+ found = fmt.Sprintf(" (replaced by %s)", replacement)
+ } else {
+ found = fmt.Sprintf(" (%s, replaced by %s)", e.Mod.Version, replacement)
+ }
+ } else if e.Query != e.Mod.Version {
found = fmt.Sprintf(" (%s)", e.Mod.Version)
}
if strings.Contains(e.Pattern, "...") {
- return fmt.Sprintf("module %s@%s%s found, but does not contain packages matching %s", e.Mod.Path, e.Query, found, e.Pattern)
+ return fmt.Sprintf("module %s@%s found%s, but does not contain packages matching %s", e.Mod.Path, e.Query, found, e.Pattern)
}
- return fmt.Sprintf("module %s@%s%s found, but does not contain package %s", e.Mod.Path, e.Query, found, e.Pattern)
+ return fmt.Sprintf("module %s@%s found%s, but does not contain package %s", e.Mod.Path, e.Query, found, e.Pattern)
}
// ModuleHasRootPackage returns whether module m contains a package m.Path.
diff --git a/src/cmd/go/internal/search/search.go b/src/cmd/go/internal/search/search.go
index 0167c8d755..d794287583 100644
--- a/src/cmd/go/internal/search/search.go
+++ b/src/cmd/go/internal/search/search.go
@@ -363,30 +363,40 @@ func ImportPathsQuiet(patterns []string) []*Match {
// CleanPatterns returns the patterns to use for the given
// command line. It canonicalizes the patterns but does not
-// evaluate any matches.
+// evaluate any matches. It preserves text after '@' for commands
+// that accept versions.
func CleanPatterns(patterns []string) []string {
if len(patterns) == 0 {
return []string{"."}
}
var out []string
for _, a := range patterns {
+ var p, v string
+ if i := strings.IndexByte(a, '@'); i < 0 {
+ p = a
+ } else {
+ p = a[:i]
+ v = a[i:]
+ }
+
// Arguments are supposed to be import paths, but
// as a courtesy to Windows developers, rewrite \ to /
// in command-line arguments. Handles .\... and so on.
if filepath.Separator == '\\' {
- a = strings.ReplaceAll(a, `\`, `/`)
+ p = strings.ReplaceAll(p, `\`, `/`)
}
// Put argument in canonical form, but preserve leading ./.
- if strings.HasPrefix(a, "./") {
- a = "./" + path.Clean(a)
- if a == "./." {
- a = "."
+ if strings.HasPrefix(p, "./") {
+ p = "./" + path.Clean(p)
+ if p == "./." {
+ p = "."
}
} else {
- a = path.Clean(a)
+ p = path.Clean(p)
}
- out = append(out, a)
+
+ out = append(out, p+v)
}
return out
}
diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go
index 95000011d8..8141e31c99 100644
--- a/src/cmd/go/internal/test/test.go
+++ b/src/cmd/go/internal/test/test.go
@@ -572,8 +572,9 @@ func runTest(cmd *base.Command, args []string) {
}
// Pass timeout to tests if it exists.
+ // Prepend rather than appending so that it appears before positional arguments.
if testActualTimeout > 0 {
- testArgs = append(testArgs, "-test.timeout="+testActualTimeout.String())
+ testArgs = append([]string{"-test.timeout=" + testActualTimeout.String()}, testArgs...)
}
// show passing test output (after buffering) with -v flag.
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index b68f902853..7dd9a90c18 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -200,12 +200,12 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
// same compiler settings and can reuse each other's results.
// If not, the reason is already recorded in buildGcflags.
fmt.Fprintf(h, "compile\n")
+ // Only include the package directory if it may affect the output.
+ // We trim workspace paths for all packages when -trimpath is set.
// The compiler hides the exact value of $GOROOT
- // when building things in GOROOT,
- // but it does not hide the exact value of $GOPATH.
- // Include the full dir in that case.
+ // when building things in GOROOT.
// Assume b.WorkDir is being trimmed properly.
- if !p.Goroot && !strings.HasPrefix(p.Dir, b.WorkDir) {
+ if !p.Goroot && !cfg.BuildTrimpath && !strings.HasPrefix(p.Dir, b.WorkDir) {
fmt.Fprintf(h, "dir %s\n", p.Dir)
}
fmt.Fprintf(h, "goos %s goarch %s\n", cfg.Goos, cfg.Goarch)
@@ -1030,7 +1030,7 @@ func (b *Builder) vet(a *Action) error {
// dependency tree turn on *more* analysis, as here.
// (The unsafeptr check does not write any facts for use by
// later vet runs.)
- if a.Package.Goroot && !VetExplicit {
+ if a.Package.Goroot && !VetExplicit && VetTool == "" {
// Note that $GOROOT/src/buildall.bash
// does the same for the misc-compile trybots
// and should be updated if these flags are
diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go
index 4dcb4b4e0d..5e50dd14c7 100644
--- a/src/cmd/go/script_test.go
+++ b/src/cmd/go/script_test.go
@@ -441,10 +441,15 @@ func (ts *testScript) cmdCmp(neg bool, args []string) {
// It would be strange to say "this file can have any content except this precise byte sequence".
ts.fatalf("unsupported: ! cmp")
}
+ quiet := false
+ if len(args) > 0 && args[0] == "-q" {
+ quiet = true
+ args = args[1:]
+ }
if len(args) != 2 {
ts.fatalf("usage: cmp file1 file2")
}
- ts.doCmdCmp(args, false)
+ ts.doCmdCmp(args, false, quiet)
}
// cmpenv compares two files with environment variable substitution.
@@ -452,13 +457,18 @@ func (ts *testScript) cmdCmpenv(neg bool, args []string) {
if neg {
ts.fatalf("unsupported: ! cmpenv")
}
+ quiet := false
+ if len(args) > 0 && args[0] == "-q" {
+ quiet = true
+ args = args[1:]
+ }
if len(args) != 2 {
ts.fatalf("usage: cmpenv file1 file2")
}
- ts.doCmdCmp(args, true)
+ ts.doCmdCmp(args, true, quiet)
}
-func (ts *testScript) doCmdCmp(args []string, env bool) {
+func (ts *testScript) doCmdCmp(args []string, env, quiet bool) {
name1, name2 := args[0], args[1]
var text1, text2 string
if name1 == "stdout" {
@@ -484,7 +494,9 @@ func (ts *testScript) doCmdCmp(args []string, env bool) {
return
}
- fmt.Fprintf(&ts.log, "[diff -%s +%s]\n%s\n", name1, name2, diff(text1, text2))
+ if !quiet {
+ fmt.Fprintf(&ts.log, "[diff -%s +%s]\n%s\n", name1, name2, diff(text1, text2))
+ }
ts.fatalf("%s and %s differ", name1, name2)
}
diff --git a/src/cmd/go/testdata/mod/example.com_dotgo.go_v1.0.0.txt b/src/cmd/go/testdata/mod/example.com_dotgo.go_v1.0.0.txt
new file mode 100644
index 0000000000..4f7f4d7dd2
--- /dev/null
+++ b/src/cmd/go/testdata/mod/example.com_dotgo.go_v1.0.0.txt
@@ -0,0 +1,16 @@
+This module's path ends with ".go".
+Based on github.com/nats-io/nats.go.
+Used in regression tests for golang.org/issue/32483.
+
+-- .mod --
+module example.com/dotgo.go
+
+go 1.13
+-- .info --
+{"Version":"v1.0.0"}
+-- go.mod --
+module example.com/dotgo.go
+
+go 1.13
+-- dotgo.go --
+package dotgo
diff --git a/src/cmd/go/testdata/script/build_trimpath.txt b/src/cmd/go/testdata/script/build_trimpath.txt
index f785b0cb9e..668f75599e 100644
--- a/src/cmd/go/testdata/script/build_trimpath.txt
+++ b/src/cmd/go/testdata/script/build_trimpath.txt
@@ -1,21 +1,44 @@
[short] skip
env -r GOROOT_REGEXP=$GOROOT
-env -r WORK_REGEXP=$WORK
+env -r WORK_REGEXP='$WORK' # don't expand $WORK; grep replaces $WORK in text before matching.
env GOROOT GOROOT_REGEXP WORK WORK_REGEXP
+# A binary built without -trimpath should contain the current workspace
+# and GOROOT for debugging and stack traces.
+cd a
+go build -o hello.exe hello.go
+grep -q $WORK_REGEXP hello.exe
+grep -q $GOROOT_REGEXP hello.exe
+
+# A binary built with -trimpath should not contain the current workspace
+# or GOROOT.
go build -trimpath -o hello.exe hello.go
! grep -q $GOROOT_REGEXP hello.exe
! grep -q $WORK_REGEXP hello.exe
+cd ..
+# A binary from an external module built with -trimpath should not contain
+# the current workspace or GOROOT.
env GO111MODULE=on
go build -trimpath -o fortune.exe rsc.io/fortune
! grep -q $GOROOT_REGEXP fortune.exe
! grep -q $WORK_REGEXP fortune.exe
--- hello.go --
+# Two binaries built from identical packages in different directories
+# should be identical.
+mkdir b
+cp a/go.mod a/hello.go b
+cd a
+go build -trimpath -o ../a.exe .
+cd ../b
+go build -trimpath -o ../b.exe .
+cd ..
+cmp -q a.exe b.exe
+
+-- a/hello.go --
package main
func main() { println("hello") }
--- go.mod --
+-- a/go.mod --
module m
diff --git a/src/cmd/go/testdata/script/cover_mod_empty.txt b/src/cmd/go/testdata/script/cover_mod_empty.txt
new file mode 100644
index 0000000000..3c45243edb
--- /dev/null
+++ b/src/cmd/go/testdata/script/cover_mod_empty.txt
@@ -0,0 +1,9 @@
+go tool cover -func=cover.out
+stdout total.*statements.*0.0%
+
+go mod init golang.org/issue/33855
+
+go tool cover -func=cover.out
+stdout total.*statements.*0.0%
+
+-- cover.out --
diff --git a/src/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt b/src/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt
index ab7cd66949..f21cd8b3a8 100644
--- a/src/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt
+++ b/src/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt
@@ -1,29 +1,32 @@
# This test checks that multiple main packages can be tested
# with -coverpkg=all without duplicate symbol errors.
-# Verifies golang.org/issue/30374.
-
-env GO111MODULE=on
+# Verifies golang.org/issue/30374, golang.org/issue/34114.
[short] skip
+cd $GOPATH/src/example.com/cov
+
+env GO111MODULE=on
+go test -coverpkg=all ./...
+env GO111MODULE=off
go test -coverpkg=all ./...
--- go.mod --
+-- $GOPATH/src/example.com/cov/go.mod --
module example.com/cov
--- mainonly/mainonly.go --
+-- $GOPATH/src/example.com/cov/mainonly/mainonly.go --
package main
func main() {}
--- mainwithtest/mainwithtest.go --
+-- $GOPATH/src/example.com/cov/mainwithtest/mainwithtest.go --
package main
func main() {}
func Foo() {}
--- mainwithtest/mainwithtest_test.go --
+-- $GOPATH/src/example.com/cov/mainwithtest/mainwithtest_test.go --
package main
import "testing"
@@ -32,10 +35,10 @@ func TestFoo(t *testing.T) {
Foo()
}
--- xtest/x.go --
+-- $GOPATH/src/example.com/cov/xtest/x.go --
package x
--- xtest/x_test.go --
+-- $GOPATH/src/example.com/cov/xtest/x_test.go --
package x_test
import "testing"
diff --git a/src/cmd/go/testdata/script/get_insecure_redirect.txt b/src/cmd/go/testdata/script/get_insecure_redirect.txt
index a83b17672d..0478d1f75d 100644
--- a/src/cmd/go/testdata/script/get_insecure_redirect.txt
+++ b/src/cmd/go/testdata/script/get_insecure_redirect.txt
@@ -1,11 +1,10 @@
# golang.org/issue/29591: 'go get' was following plain-HTTP redirects even without -insecure.
+# golang.org/issue/34049: 'go get' would panic in case of an insecure redirect in GOPATH mode
[!net] skip
[!exec:git] skip
-env GO111MODULE=on
-env GOPROXY=direct
-env GOSUMDB=off
+env GO111MODULE=off
! go get -d vcs-test.golang.org/insecure/go/insecure
stderr 'redirected .* to insecure URL'
diff --git a/src/cmd/go/testdata/script/list_ambiguous_path.txt b/src/cmd/go/testdata/script/list_ambiguous_path.txt
new file mode 100644
index 0000000000..9f1aa37be8
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_ambiguous_path.txt
@@ -0,0 +1,37 @@
+# Ensures that we can correctly list package patterns ending in '.go'.
+# See golang.org/issue/34653.
+
+# A single pattern for a package ending in '.go'.
+go list ./foo.go
+stdout '^test/foo.go$'
+
+# Multiple patterns for packages including one ending in '.go'.
+go list ./bar ./foo.go
+stdout '^test/bar$'
+stdout '^test/foo.go$'
+
+# A single pattern for a Go file.
+go list ./a.go
+stdout '^command-line-arguments$'
+
+# A single typo-ed pattern for a Go file. This should
+# treat the wrong pattern as if it were a package.
+! go list ./foo.go/b.go
+stderr 'package ./foo.go/b.go: cannot find package "."'
+
+# Multiple patterns for Go files with a typo. This should
+# treat the wrong pattern as if it were a non-existint file.
+! go list ./foo.go/a.go ./foo.go/b.go
+[windows] stderr './foo.go/b.go: The system cannot find the file specified'
+[!windows] stderr './foo.go/b.go: no such file or directory'
+
+-- a.go --
+package main
+-- bar/a.go --
+package bar
+-- foo.go/a.go --
+package foo.go
+-- go.mod --
+module "test"
+
+go 1.13
diff --git a/src/cmd/go/testdata/script/list_split_main.txt b/src/cmd/go/testdata/script/list_split_main.txt
new file mode 100644
index 0000000000..74e7d5d74c
--- /dev/null
+++ b/src/cmd/go/testdata/script/list_split_main.txt
@@ -0,0 +1,25 @@
+# This test checks that a "main" package with an external test package
+# is recompiled only once.
+# Verifies golang.org/issue/34321.
+
+env GO111MODULE=off
+
+go list -e -test -deps -f '{{if not .Standard}}{{.ImportPath}}{{end}}' pkg
+cmp stdout want
+
+-- $GOPATH/src/pkg/pkg.go --
+package main
+
+func main() {}
+
+-- $GOPATH/src/pkg/pkg_test.go --
+package main
+
+import "testing"
+
+func Test(t *testing.T) {}
+
+-- want --
+pkg
+pkg [pkg.test]
+pkg.test
diff --git a/src/cmd/go/testdata/script/mod_download.txt b/src/cmd/go/testdata/script/mod_download.txt
index 9eb3140c33..0777913786 100644
--- a/src/cmd/go/testdata/script/mod_download.txt
+++ b/src/cmd/go/testdata/script/mod_download.txt
@@ -17,7 +17,6 @@ stderr 'this.domain.is.invalid'
stdout '"Error": ".*this.domain.is.invalid.*"'
# download -json with version should print JSON
-# and download the .info file for the 'latest' version.
go mod download -json 'rsc.io/quote@<=v1.5.0'
stdout '^\t"Path": "rsc.io/quote"'
stdout '^\t"Version": "v1.5.0"'
@@ -28,14 +27,13 @@ stdout '^\t"Sum": "h1:6fJa6E\+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE="' # hash of
stdout '^\t"GoModSum": "h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe\+TKr0="'
! stdout '"Error"'
-exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.info
-
# download queries above should not have added to go.mod.
go list -m all
! stdout rsc.io
# add to go.mod so we can test non-query downloads
go mod edit -require rsc.io/quote@v1.5.2
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.info
! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
diff --git a/src/cmd/go/testdata/script/mod_download_latest.txt b/src/cmd/go/testdata/script/mod_download_latest.txt
deleted file mode 100644
index 60d860e4da..0000000000
--- a/src/cmd/go/testdata/script/mod_download_latest.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-env GO111MODULE=on
-
-# If the module is the latest version of itself,
-# the Latest field should be set.
-go mod download -json rsc.io/quote@v1.5.2
-stdout '"Latest":\s*true'
-
-# If the module is older than latest, the field should be unset.
-go mod download -json rsc.io/quote@v1.5.1
-! stdout '"Latest":'
-
-# If the module is newer than "latest", the field should be unset...
-go mod download -json rsc.io/quote@v1.5.3-pre1
-! stdout '"Latest":'
-
-# ...even if that version is also what is required by the main module.
-go mod init example.com
-go mod edit -require rsc.io/quote@v1.5.3-pre1
-go mod download -json rsc.io/quote@v1.5.3-pre1
-! stdout '"Latest":'
diff --git a/src/cmd/go/testdata/script/mod_get_direct.txt b/src/cmd/go/testdata/script/mod_get_direct.txt
new file mode 100644
index 0000000000..42ccbcd38a
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_direct.txt
@@ -0,0 +1,20 @@
+# Regression test for golang.org/issue/34092: with an empty module cache,
+# 'GOPROXY=direct go get golang.org/x/tools/gopls@master' did not correctly
+# resolve the pseudo-version for its dependency on golang.org/x/tools.
+
+[short] skip
+[!net] skip
+[!exec:git] skip
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+go list -m cloud.google.com/go@master
+! stdout 'v0.0.0-'
+
+-- go.mod --
+module example.com
+
+go 1.14
+-- go.sum --
diff --git a/src/cmd/go/testdata/script/mod_get_insecure_redirect.txt b/src/cmd/go/testdata/script/mod_get_insecure_redirect.txt
new file mode 100644
index 0000000000..a83b17672d
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_insecure_redirect.txt
@@ -0,0 +1,13 @@
+# golang.org/issue/29591: 'go get' was following plain-HTTP redirects even without -insecure.
+
+[!net] skip
+[!exec:git] skip
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+! go get -d vcs-test.golang.org/insecure/go/insecure
+stderr 'redirected .* to insecure URL'
+
+go get -d -insecure vcs-test.golang.org/insecure/go/insecure
diff --git a/src/cmd/go/testdata/script/mod_get_major.txt b/src/cmd/go/testdata/script/mod_get_major.txt
new file mode 100644
index 0000000000..367ede9ded
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_major.txt
@@ -0,0 +1,23 @@
+[!net] skip
+[!exec:git] skip
+
+env GO111MODULE=on
+env GOPROXY=direct
+env GOSUMDB=off
+
+# golang.org/issue/34383: if a module path ends in a major-version suffix,
+# ensure that 'direct' mode can resolve the package to a module.
+
+go get -d vcs-test.golang.org/git/v3pkg.git/v3@v3.0.0
+
+go list -m vcs-test.golang.org/git/v3pkg.git/v3
+stdout '^vcs-test.golang.org/git/v3pkg.git/v3 v3.0.0$'
+
+go get -d vcs-test.golang.org/git/empty-v2-without-v1.git/v2@v2.0.0
+
+go list -m vcs-test.golang.org/git/empty-v2-without-v1.git/v2
+stdout '^vcs-test.golang.org/git/empty-v2-without-v1.git/v2 v2.0.0$'
+
+-- go.mod --
+module example.com
+go 1.13
diff --git a/src/cmd/go/testdata/script/mod_get_patterns.txt b/src/cmd/go/testdata/script/mod_get_patterns.txt
index bfab70090c..8adc4b0c06 100644
--- a/src/cmd/go/testdata/script/mod_get_patterns.txt
+++ b/src/cmd/go/testdata/script/mod_get_patterns.txt
@@ -10,11 +10,11 @@ grep 'require rsc.io/quote' go.mod
cp go.mod.orig go.mod
! go get -d rsc.io/quote/x...
-stderr 'go get rsc.io/quote/x...: module rsc.io/quote@upgrade \(v1.5.2\) found, but does not contain packages matching rsc.io/quote/x...'
+stderr 'go get rsc.io/quote/x...: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching rsc.io/quote/x...'
! grep 'require rsc.io/quote' go.mod
! go get -d rsc.io/quote/x/...
-stderr 'go get rsc.io/quote/x/...: module rsc.io/quote@upgrade \(v1.5.2\) found, but does not contain packages matching rsc.io/quote/x/...'
+stderr 'go get rsc.io/quote/x/...: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching rsc.io/quote/x/...'
! grep 'require rsc.io/quote' go.mod
# If a pattern matches no packages within a module, the module should not
diff --git a/src/cmd/go/testdata/script/mod_get_trailing_slash.txt b/src/cmd/go/testdata/script/mod_get_trailing_slash.txt
new file mode 100644
index 0000000000..7b5d90c50b
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_trailing_slash.txt
@@ -0,0 +1,30 @@
+# go list should succeed to load a package ending with ".go" if the path does
+# not correspond to an existing local file. Listing a pattern ending with
+# ".go/" should try to list a package regardless of whether a file exists at the
+# path without the suffixed "/" or not.
+go list example.com/dotgo.go
+stdout ^example.com/dotgo.go$
+go list example.com/dotgo.go/
+stdout ^example.com/dotgo.go$
+
+# go get -d should succeed in either case, with or without a version.
+# Arguments are interpreted as packages or package patterns with versions,
+# not source files.
+go get -d example.com/dotgo.go
+go get -d example.com/dotgo.go/
+go get -d example.com/dotgo.go@v1.0.0
+go get -d example.com/dotgo.go/@v1.0.0
+
+# go get (without -d) should also succeed in either case.
+[short] skip
+go get example.com/dotgo.go
+go get example.com/dotgo.go/
+go get example.com/dotgo.go@v1.0.0
+go get example.com/dotgo.go/@v1.0.0
+
+-- go.mod --
+module m
+
+go 1.13
+
+require example.com/dotgo.go v1.0.0
diff --git a/src/cmd/go/testdata/script/mod_list_upgrade.txt b/src/cmd/go/testdata/script/mod_list_upgrade.txt
index f2d0649092..474df0dc26 100644
--- a/src/cmd/go/testdata/script/mod_list_upgrade.txt
+++ b/src/cmd/go/testdata/script/mod_list_upgrade.txt
@@ -1,28 +1,8 @@
env GO111MODULE=on
-# If the current version is not latest, 'go list -u' should include its upgrade.
go list -m -u all
stdout 'rsc.io/quote v1.2.0 \[v1\.5\.2\]'
-# If the current version is latest, 'go list -u' should omit the upgrade.
-go get -d rsc.io/quote@v1.5.2
-go list -m -u all
-stdout 'rsc.io/quote v1.5.2$'
-
-# If the current version is newer than latest, 'go list -u' should
-# omit the upgrade.
-go get -d rsc.io/quote@v1.5.3-pre1
-go list -m -u all
-stdout 'rsc.io/quote v1.5.3-pre1$'
-
-# If the current build list has a higher version and the user asks about
-# a lower one, -u should report the upgrade for the lower one
-# but leave the build list unchanged.
-go list -m -u rsc.io/quote@v1.5.1
-stdout 'rsc.io/quote v1.5.1 \[v1.5.2\]$'
-go list -m -u rsc.io/quote
-stdout 'rsc.io/quote v1.5.3-pre1$'
-
-- go.mod --
module x
require rsc.io/quote v1.2.0
diff --git a/src/cmd/go/testdata/script/mod_replace.txt b/src/cmd/go/testdata/script/mod_replace.txt
index 35824b3a8a..e4301b50d0 100644
--- a/src/cmd/go/testdata/script/mod_replace.txt
+++ b/src/cmd/go/testdata/script/mod_replace.txt
@@ -38,6 +38,13 @@ grep 'not-rsc.io/quote/v3 v3.1.0' go.mod
exec ./a5.exe
stdout 'Concurrency is not parallelism.'
+# Error messages for modules not found in replacements should
+# indicate the replacement module.
+cp go.mod.orig go.mod
+go mod edit -replace=rsc.io/quote/v3=./local/rsc.io/quote/v3
+! go get -d rsc.io/quote/v3/missing-package
+stderr 'module rsc.io/quote/v3@upgrade found \(v3.0.0, replaced by ./local/rsc.io/quote/v3\), but does not contain package'
+
-- go.mod --
module quoter
diff --git a/src/cmd/go/testdata/script/test_timeout.txt b/src/cmd/go/testdata/script/test_timeout.txt
index 8dead0a439..4de4df4508 100644
--- a/src/cmd/go/testdata/script/test_timeout.txt
+++ b/src/cmd/go/testdata/script/test_timeout.txt
@@ -2,12 +2,13 @@
env GO111MODULE=off
cd a
-# No timeout is passed via 'go test' command.
-go test -v
+# If no timeout is set explicitly, 'go test' should set
+# -test.timeout to its internal deadline.
+go test -v . --
stdout '10m0s'
-# Timeout is passed via 'go test' command.
-go test -v -timeout 30m
+# An explicit -timeout argument should be propagated to -test.timeout.
+go test -v -timeout 30m . --
stdout '30m0s'
-- a/timeout_test.go --
@@ -19,4 +20,4 @@ import (
)
func TestTimeout(t *testing.T) {
fmt.Println(flag.Lookup("test.timeout").Value.String())
-} \ No newline at end of file
+}
diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go
index be01a29606..22de2a5661 100644
--- a/src/crypto/ecdsa/ecdsa.go
+++ b/src/crypto/ecdsa/ecdsa.go
@@ -225,21 +225,14 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
// See [NSA] 3.4.1
c := priv.PublicKey.Curve
- e := hashToInt(hash, c)
- r, s, err = sign(priv, &csprng, c, e)
- return
-}
-
-func signGeneric(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, e *big.Int) (r, s *big.Int, err error) {
N := c.Params().N
if N.Sign() == 0 {
return nil, nil, errZeroParam
}
-
var k, kInv *big.Int
for {
for {
- k, err = randFieldElement(c, *csprng)
+ k, err = randFieldElement(c, csprng)
if err != nil {
r = nil
return
@@ -257,6 +250,8 @@ func signGeneric(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve
break
}
}
+
+ e := hashToInt(hash, c)
s = new(big.Int).Mul(priv.D, r)
s.Add(s, e)
s.Mul(s, kInv)
@@ -265,6 +260,7 @@ func signGeneric(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve
break
}
}
+
return
}
@@ -291,12 +287,8 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
return false
}
e := hashToInt(hash, c)
- return verify(pub, c, e, r, s)
-}
-func verifyGeneric(pub *PublicKey, c elliptic.Curve, e, r, s *big.Int) bool {
var w *big.Int
- N := c.Params().N
if in, ok := c.(invertible); ok {
w = in.Inverse(s)
} else {
diff --git a/src/crypto/ecdsa/ecdsa_noasm.go b/src/crypto/ecdsa/ecdsa_noasm.go
deleted file mode 100644
index 2dfdb866d6..0000000000
--- a/src/crypto/ecdsa/ecdsa_noasm.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2019 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 !s390x
-
-package ecdsa
-
-import (
- "crypto/cipher"
- "crypto/elliptic"
- "math/big"
-)
-
-func sign(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, e *big.Int) (r, s *big.Int, err error) {
- r, s, err = signGeneric(priv, csprng, c, e)
- return
-}
-
-func verify(pub *PublicKey, c elliptic.Curve, e, r, s *big.Int) bool {
- return verifyGeneric(pub, c, e, r, s)
-}
diff --git a/src/crypto/ecdsa/ecdsa_s390x.go b/src/crypto/ecdsa/ecdsa_s390x.go
deleted file mode 100644
index f07c3bf50c..0000000000
--- a/src/crypto/ecdsa/ecdsa_s390x.go
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright 2019 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 s390x,!gccgo
-
-package ecdsa
-
-import (
- "crypto/cipher"
- "crypto/elliptic"
- "internal/cpu"
- "math/big"
-)
-
-// s390x accelerated signatures
-//go:noescape
-func kdsaSig(fc uint64, block *[1720]byte) (errn uint64)
-
-type signverify int
-
-const (
- signing signverify = iota
- verifying
-)
-
-// bufferOffsets represents the offset of a particular parameter in
-// the buffer passed to the KDSA instruction.
-type bufferOffsets struct {
- baseSize int
- hashSize int
- offsetHash int
- offsetKey1 int
- offsetRNorKey2 int
- offsetR int
- offsetS int
- functionCode uint64
-}
-
-func canUseKDSA(sv signverify, c elliptic.Curve, bo *bufferOffsets) bool {
- if !cpu.S390X.HasECDSA {
- return false
- }
-
- switch c.Params().Name {
- case "P-256":
- bo.baseSize = 32
- bo.hashSize = 32
- bo.offsetHash = 64
- bo.offsetKey1 = 96
- bo.offsetRNorKey2 = 128
- bo.offsetR = 0
- bo.offsetS = 32
- if sv == signing {
- bo.functionCode = 137
- } else {
- bo.functionCode = 1
- }
- return true
- case "P-384":
- bo.baseSize = 48
- bo.hashSize = 48
- bo.offsetHash = 96
- bo.offsetKey1 = 144
- bo.offsetRNorKey2 = 192
- bo.offsetR = 0
- bo.offsetS = 48
- if sv == signing {
- bo.functionCode = 138
- } else {
- bo.functionCode = 2
- }
- return true
- case "P-521":
- bo.baseSize = 66
- bo.hashSize = 80
- bo.offsetHash = 160
- bo.offsetKey1 = 254
- bo.offsetRNorKey2 = 334
- bo.offsetR = 14
- bo.offsetS = 94
- if sv == signing {
- bo.functionCode = 139
- } else {
- bo.functionCode = 3
- }
- return true
- }
- return false
-}
-
-// zeroExtendAndCopy pads src with leading zeros until it has the size given.
-// It then copies the padded src into the dst. Bytes beyond size in dst are
-// not modified.
-func zeroExtendAndCopy(dst, src []byte, size int) {
- nz := size - len(src)
- if nz < 0 {
- panic("src is too long")
- }
- // the compiler should replace this loop with a memclr call
- z := dst[:nz]
- for i := range z {
- z[i] = 0
- }
- copy(dst[nz:size], src[:size-nz])
- return
-}
-
-func sign(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, e *big.Int) (r, s *big.Int, err error) {
- var bo bufferOffsets
- if canUseKDSA(signing, c, &bo) && e.Sign() != 0 {
- var buffer [1720]byte
- for {
- var k *big.Int
- k, err = randFieldElement(c, csprng)
- if err != nil {
- return nil, nil, err
- }
- zeroExtendAndCopy(buffer[bo.offsetHash:], e.Bytes(), bo.hashSize)
- zeroExtendAndCopy(buffer[bo.offsetKey1:], priv.D.Bytes(), bo.baseSize)
- zeroExtendAndCopy(buffer[bo.offsetRNorKey2:], k.Bytes(), bo.baseSize)
- errn := kdsaSig(bo.functionCode, &buffer)
- if errn == 2 {
- return nil, nil, errZeroParam
- }
- if errn == 0 { // success == 0 means successful signing
- r = new(big.Int)
- r.SetBytes(buffer[bo.offsetR : bo.offsetR+bo.baseSize])
- s = new(big.Int)
- s.SetBytes(buffer[bo.offsetS : bo.offsetS+bo.baseSize])
- return
- }
- //at this point, it must be that errn == 1: retry
- }
- }
- r, s, err = signGeneric(priv, csprng, c, e)
- return
-}
-
-func verify(pub *PublicKey, c elliptic.Curve, e, r, s *big.Int) bool {
- var bo bufferOffsets
- if canUseKDSA(verifying, c, &bo) && e.Sign() != 0 {
- var buffer [1720]byte
- zeroExtendAndCopy(buffer[bo.offsetR:], r.Bytes(), bo.baseSize)
- zeroExtendAndCopy(buffer[bo.offsetS:], s.Bytes(), bo.baseSize)
- zeroExtendAndCopy(buffer[bo.offsetHash:], e.Bytes(), bo.hashSize)
- zeroExtendAndCopy(buffer[bo.offsetKey1:], pub.X.Bytes(), bo.baseSize)
- zeroExtendAndCopy(buffer[bo.offsetRNorKey2:], pub.Y.Bytes(), bo.baseSize)
- errn := kdsaSig(bo.functionCode, &buffer)
- return errn == 0
- }
- return verifyGeneric(pub, c, e, r, s)
-}
diff --git a/src/crypto/ecdsa/ecdsa_s390x.s b/src/crypto/ecdsa/ecdsa_s390x.s
deleted file mode 100644
index 6ee00ce79c..0000000000
--- a/src/crypto/ecdsa/ecdsa_s390x.s
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2019 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.
-
-#include "textflag.h"
-
-// func kdsaSig(fc uint64, block *[1720]byte) (errn uint64)
-TEXT ·kdsaSig(SB), NOSPLIT|NOFRAME, $0-24
- MOVD fc+0(FP), R0 // function code
- MOVD block+8(FP), R1 // address parameter block
-
-loop:
- WORD $0xB93A0008 // compute digital signature authentication
- BVS loop // branch back if interrupted
- BEQ success // signature creation successful
- BGT retry // signing unsuccessful, but retry with new CSPRN
-
-error:
- MOVD $2, R2 // fallthrough indicates fatal error
- MOVD R2, errn+16(FP) // return 2 - sign/verify abort
- RET
-
-retry:
- MOVD $1, R2
- MOVD R2, errn+16(FP) // return 1 - sign/verify was unsuccessful -- if sign, retry with new RN
- RET
-
-success:
- MOVD $0, R2
- MOVD R2, errn+16(FP) // return 0 - sign/verify was successful
- RET
diff --git a/src/crypto/ecdsa/ecdsa_s390x_test.go b/src/crypto/ecdsa/ecdsa_s390x_test.go
deleted file mode 100644
index 80babc9cb4..0000000000
--- a/src/crypto/ecdsa/ecdsa_s390x_test.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2019 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 s390x,!gccgo
-
-package ecdsa
-
-import (
- "crypto/elliptic"
- "testing"
-)
-
-func TestNoAsm(t *testing.T) {
- curves := [...]elliptic.Curve{
- elliptic.P256(),
- elliptic.P384(),
- elliptic.P521(),
- }
-
- for _, curve := range curves {
- // override the name of the curve to stop the assembly path being taken
- params := *curve.Params()
- name := params.Name
- params.Name = name + "_GENERIC_OVERRIDE"
-
- testKeyGeneration(t, &params, name)
- testSignAndVerify(t, &params, name)
- testNonceSafety(t, &params, name)
- testINDCCA(t, &params, name)
- testNegativeInputs(t, &params, name)
- }
-}
diff --git a/src/errors/errors.go b/src/errors/errors.go
index 85d4260762..d923ad4b70 100644
--- a/src/errors/errors.go
+++ b/src/errors/errors.go
@@ -13,16 +13,16 @@
//
// If e.Unwrap() returns a non-nil error w, then we say that e wraps w.
//
+// Unwrap unpacks wrapped errors. If its argument's type has an
+// Unwrap method, it calls the method once. Otherwise, it returns nil.
+//
// A simple way to create wrapped errors is to call fmt.Errorf and apply the %w verb
// to the error argument:
//
-// fmt.Errorf("... %w ...", ..., err, ...).Unwrap()
+// errors.Unwrap(fmt.Errorf("... %w ...", ..., err, ...))
//
// returns err.
//
-// Unwrap unpacks wrapped errors. If its argument's type has an
-// Unwrap method, it calls the method once. Otherwise, it returns nil.
-//
// Is unwraps its first argument sequentially looking for an error that matches the
// second. It reports whether it finds a match. It should be used in preference to
// simple equality checks:
diff --git a/src/internal/syscall/windows/mksyscall.go b/src/internal/syscall/windows/mksyscall.go
index 0bf87dc95c..95e36f7aa3 100644
--- a/src/internal/syscall/windows/mksyscall.go
+++ b/src/internal/syscall/windows/mksyscall.go
@@ -6,4 +6,4 @@
package windows
-//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go security_windows.go psapi_windows.go symlink_windows.go
+//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall_windows.go security_windows.go psapi_windows.go symlink_windows.go
diff --git a/src/internal/syscall/windows/registry/mksyscall.go b/src/internal/syscall/windows/registry/mksyscall.go
index fa8e27e8ff..cb4906a7b2 100644
--- a/src/internal/syscall/windows/registry/mksyscall.go
+++ b/src/internal/syscall/windows/registry/mksyscall.go
@@ -6,4 +6,4 @@
package registry
-//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall.go
+//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall.go
diff --git a/src/log/syslog/syslog_test.go b/src/log/syslog/syslog_test.go
index 447654a874..8a28d67c98 100644
--- a/src/log/syslog/syslog_test.go
+++ b/src/log/syslog/syslog_test.go
@@ -134,6 +134,9 @@ func startServer(n, la string, done chan<- string) (addr string, sock io.Closer,
}
func TestWithSimulated(t *testing.T) {
+ if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
+ t.Skipf("sysctl is not supported on iOS")
+ }
t.Parallel()
msg := "Test 123"
var transport []string
@@ -272,6 +275,9 @@ func check(t *testing.T, in, out string) {
}
func TestWrite(t *testing.T) {
+ if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
+ t.Skipf("sysctl is not supported on iOS")
+ }
t.Parallel()
tests := []struct {
pri Priority
diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go
index e0a7ef8552..c90892b833 100644
--- a/src/net/dnsclient_unix.go
+++ b/src/net/dnsclient_unix.go
@@ -765,6 +765,14 @@ func (r *Resolver) goLookupPTR(ctx context.Context, addr string) ([]string, erro
}
}
if h.Type != dnsmessage.TypePTR {
+ err := p.SkipAnswer()
+ if err != nil {
+ return nil, &DNSError{
+ Err: "cannot marshal DNS message",
+ Name: addr,
+ Server: server,
+ }
+ }
continue
}
ptr, err := p.PTRResource()
diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go
index 98304d36ea..31cb6f721a 100644
--- a/src/net/dnsclient_unix_test.go
+++ b/src/net/dnsclient_unix_test.go
@@ -1753,3 +1753,50 @@ func TestDNSUseTCP(t *testing.T) {
t.Fatal("exchange failed:", err)
}
}
+
+// Issue 34660: PTR response with non-PTR answers should ignore non-PTR
+func TestPTRandNonPTR(t *testing.T) {
+ fake := fakeDNSServer{
+ rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
+ r := dnsmessage.Message{
+ Header: dnsmessage.Header{
+ ID: q.Header.ID,
+ Response: true,
+ RCode: dnsmessage.RCodeSuccess,
+ },
+ Questions: q.Questions,
+ Answers: []dnsmessage.Resource{
+ {
+ Header: dnsmessage.ResourceHeader{
+ Name: q.Questions[0].Name,
+ Type: dnsmessage.TypePTR,
+ Class: dnsmessage.ClassINET,
+ },
+ Body: &dnsmessage.PTRResource{
+ PTR: dnsmessage.MustNewName("golang.org."),
+ },
+ },
+ {
+ Header: dnsmessage.ResourceHeader{
+ Name: q.Questions[0].Name,
+ Type: dnsmessage.TypeTXT,
+ Class: dnsmessage.ClassINET,
+ },
+ Body: &dnsmessage.TXTResource{
+ TXT: []string{"PTR 8 6 60 ..."}, // fake RRSIG
+ },
+ },
+ },
+ }
+ return r, nil
+ },
+ }
+ r := Resolver{PreferGo: true, Dial: fake.DialContext}
+ names, err := r.lookupAddr(context.Background(), "192.0.2.123")
+ if err != nil {
+ t.Fatalf("LookupAddr: %v", err)
+ }
+ if want := []string{"golang.org."}; !reflect.DeepEqual(names, want) {
+ t.Errorf("names = %q; want %q", names, want)
+ }
+}
diff --git a/src/net/http/client.go b/src/net/http/client.go
index 65a9d51cc6..20496d2f0e 100644
--- a/src/net/http/client.go
+++ b/src/net/http/client.go
@@ -238,7 +238,7 @@ func send(ireq *Request, rt RoundTripper, deadline time.Time) (resp *Response, d
username := u.Username()
password, _ := u.Password()
forkReq()
- req.Header = ireq.Header.Clone()
+ req.Header = cloneOrMakeHeader(ireq.Header)
req.Header.Set("Authorization", "Basic "+basicAuth(username, password))
}
@@ -668,7 +668,7 @@ func (c *Client) makeHeadersCopier(ireq *Request) func(*Request) {
// The headers to copy are from the very initial request.
// We use a closured callback to keep a reference to these original headers.
var (
- ireqhdr = ireq.Header.Clone()
+ ireqhdr = cloneOrMakeHeader(ireq.Header)
icookies map[string][]*Cookie
)
if c.Jar != nil && ireq.Header.Get("Cookie") != "" {
diff --git a/src/net/http/clone.go b/src/net/http/clone.go
index 5f2784d280..3a3375bff7 100644
--- a/src/net/http/clone.go
+++ b/src/net/http/clone.go
@@ -62,3 +62,13 @@ func cloneMultipartFileHeader(fh *multipart.FileHeader) *multipart.FileHeader {
fh2.Header = textproto.MIMEHeader(Header(fh.Header).Clone())
return fh2
}
+
+// cloneOrMakeHeader invokes Header.Clone but if the
+// result is nil, it'll instead make and return a non-nil Header.
+func cloneOrMakeHeader(hdr Header) Header {
+ clone := hdr.Clone()
+ if clone == nil {
+ clone = make(Header)
+ }
+ return clone
+}
diff --git a/src/net/http/export_test.go b/src/net/http/export_test.go
index d265cd3f72..e5c06a8903 100644
--- a/src/net/http/export_test.go
+++ b/src/net/http/export_test.go
@@ -208,6 +208,30 @@ func (t *Transport) PutIdleTestConn(scheme, addr string) bool {
}) == nil
}
+// PutIdleTestConnH2 reports whether it was able to insert a fresh
+// HTTP/2 persistConn for scheme, addr into the idle connection pool.
+func (t *Transport) PutIdleTestConnH2(scheme, addr string, alt RoundTripper) bool {
+ key := connectMethodKey{"", scheme, addr, false}
+
+ if t.MaxConnsPerHost > 0 {
+ // Transport is tracking conns-per-host.
+ // Increment connection count to account
+ // for new persistConn created below.
+ t.connsPerHostMu.Lock()
+ if t.connsPerHost == nil {
+ t.connsPerHost = make(map[connectMethodKey]int)
+ }
+ t.connsPerHost[key]++
+ t.connsPerHostMu.Unlock()
+ }
+
+ return t.tryPutIdleConn(&persistConn{
+ t: t,
+ alt: alt,
+ cacheKey: key,
+ }) == nil
+}
+
// All test hooks must be non-nil so they can be called directly,
// but the tests use nil to mean hook disabled.
func unnilTestHook(f *func()) {
diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
index 53cc5bd1b8..e9a55f388a 100644
--- a/src/net/http/h2_bundle.go
+++ b/src/net/http/h2_bundle.go
@@ -10148,7 +10148,8 @@ type http2randomWriteScheduler struct {
zero http2writeQueue
// sq contains the stream-specific queues, keyed by stream ID.
- // When a stream is idle or closed, it's deleted from the map.
+ // When a stream is idle, closed, or emptied, it's deleted
+ // from the map.
sq map[uint32]*http2writeQueue
// pool of empty queues for reuse.
@@ -10192,8 +10193,12 @@ func (ws *http2randomWriteScheduler) Pop() (http2FrameWriteRequest, bool) {
return ws.zero.shift(), true
}
// Iterate over all non-idle streams until finding one that can be consumed.
- for _, q := range ws.sq {
+ for streamID, q := range ws.sq {
if wr, ok := q.consume(math.MaxInt32); ok {
+ if q.empty() {
+ delete(ws.sq, streamID)
+ ws.queuePool.put(q)
+ }
return wr, true
}
}
diff --git a/src/net/http/header_test.go b/src/net/http/header_test.go
index 51fcab103b..4789362919 100644
--- a/src/net/http/header_test.go
+++ b/src/net/http/header_test.go
@@ -7,6 +7,7 @@ package http
import (
"bytes"
"internal/race"
+ "reflect"
"runtime"
"testing"
"time"
@@ -219,3 +220,34 @@ func TestHeaderWriteSubsetAllocs(t *testing.T) {
t.Errorf("allocs = %g; want 0", n)
}
}
+
+// Issue 34878: test that every call to
+// cloneOrMakeHeader never returns a nil Header.
+func TestCloneOrMakeHeader(t *testing.T) {
+ tests := []struct {
+ name string
+ in, want Header
+ }{
+ {"nil", nil, Header{}},
+ {"empty", Header{}, Header{}},
+ {
+ name: "non-empty",
+ in: Header{"foo": {"bar"}},
+ want: Header{"foo": {"bar"}},
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := cloneOrMakeHeader(tt.in)
+ if got == nil {
+ t.Fatal("unexpected nil Header")
+ }
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Fatalf("Got: %#v\nWant: %#v", got, tt.want)
+ }
+ got.Add("A", "B")
+ got.Get("A")
+ })
+ }
+}
diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
index b072f95802..bb06d922f0 100644
--- a/src/net/http/request_test.go
+++ b/src/net/http/request_test.go
@@ -826,6 +826,34 @@ func TestWithContextDeepCopiesURL(t *testing.T) {
}
}
+func TestNoPanicOnRoundTripWithBasicAuth_h1(t *testing.T) {
+ testNoPanicWithBasicAuth(t, h1Mode)
+}
+
+func TestNoPanicOnRoundTripWithBasicAuth_h2(t *testing.T) {
+ testNoPanicWithBasicAuth(t, h2Mode)
+}
+
+// Issue 34878: verify we don't panic when including basic auth (Go 1.13 regression)
+func testNoPanicWithBasicAuth(t *testing.T, h2 bool) {
+ defer afterTest(t)
+ cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {}))
+ defer cst.close()
+
+ u, err := url.Parse(cst.ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ u.User = url.UserPassword("foo", "bar")
+ req := &Request{
+ URL: u,
+ Method: "GET",
+ }
+ if _, err := cst.c.Do(req); err != nil {
+ t.Fatalf("Unexpected error: %v", err)
+ }
+}
+
// verify that NewRequest sets Request.GetBody and that it works
func TestNewRequestGetBody(t *testing.T) {
tests := []struct {
diff --git a/src/net/http/server.go b/src/net/http/server.go
index f554c81300..95a5eabaa2 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -3267,7 +3267,6 @@ type timeoutWriter struct {
}
var _ Pusher = (*timeoutWriter)(nil)
-var _ Flusher = (*timeoutWriter)(nil)
// Push implements the Pusher interface.
func (tw *timeoutWriter) Push(target string, opts *PushOptions) error {
@@ -3277,14 +3276,6 @@ func (tw *timeoutWriter) Push(target string, opts *PushOptions) error {
return ErrNotSupported
}
-// Flush implements the Flusher interface.
-func (tw *timeoutWriter) Flush() {
- f, ok := tw.w.(Flusher)
- if ok {
- f.Flush()
- }
-}
-
func (tw *timeoutWriter) Header() Header { return tw.h }
func (tw *timeoutWriter) Write(p []byte) (int, error) {
diff --git a/src/net/http/transport.go b/src/net/http/transport.go
index ee279877e0..caa4bdc36f 100644
--- a/src/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -539,6 +539,7 @@ func (t *Transport) roundTrip(req *Request) (*Response, error) {
}
if http2isNoCachedConnError(err) {
t.removeIdleConn(pconn)
+ t.decConnsPerHost(pconn.cacheKey)
} else if !pconn.shouldRetryRequest(req, err) {
// Issue 16465: return underlying net.Conn.Read error from peek,
// as we've historically done.
@@ -1206,7 +1207,9 @@ func (t *Transport) getConn(treq *transportRequest, cm connectMethod) (pc *persi
// Queue for idle connection.
if delivered := t.queueForIdleConn(w); delivered {
pc := w.pc
- if trace != nil && trace.GotConn != nil {
+ // Trace only for HTTP/1.
+ // HTTP/2 calls trace.GotConn itself.
+ if pc.alt == nil && trace != nil && trace.GotConn != nil {
trace.GotConn(pc.gotIdleConnTrace(pc.idleAt))
}
// set request canceler to some non-nil function so we
diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
index 181d944d85..e43c8956ee 100644
--- a/src/net/http/transport_test.go
+++ b/src/net/http/transport_test.go
@@ -3562,6 +3562,76 @@ func TestTransportCloseIdleConnsThenReturn(t *testing.T) {
wantIdle("after final put", 1)
}
+// Test for issue 34282
+// Ensure that getConn doesn't call the GotConn trace hook on a HTTP/2 idle conn
+func TestTransportTraceGotConnH2IdleConns(t *testing.T) {
+ tr := &Transport{}
+ wantIdle := func(when string, n int) bool {
+ got := tr.IdleConnCountForTesting("https", "example.com:443") // key used by PutIdleTestConnH2
+ if got == n {
+ return true
+ }
+ t.Errorf("%s: idle conns = %d; want %d", when, got, n)
+ return false
+ }
+ wantIdle("start", 0)
+ alt := funcRoundTripper(func() {})
+ if !tr.PutIdleTestConnH2("https", "example.com:443", alt) {
+ t.Fatal("put failed")
+ }
+ wantIdle("after put", 1)
+ ctx := httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{
+ GotConn: func(httptrace.GotConnInfo) {
+ // tr.getConn should leave it for the HTTP/2 alt to call GotConn.
+ t.Error("GotConn called")
+ },
+ })
+ req, _ := NewRequestWithContext(ctx, MethodGet, "https://example.com", nil)
+ _, err := tr.RoundTrip(req)
+ if err != errFakeRoundTrip {
+ t.Errorf("got error: %v; want %q", err, errFakeRoundTrip)
+ }
+ wantIdle("after round trip", 1)
+}
+
+func TestTransportRemovesH2ConnsAfterIdle(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping in short mode")
+ }
+
+ trFunc := func(tr *Transport) {
+ tr.MaxConnsPerHost = 1
+ tr.MaxIdleConnsPerHost = 1
+ tr.IdleConnTimeout = 10 * time.Millisecond
+ }
+ cst := newClientServerTest(t, h2Mode, HandlerFunc(func(w ResponseWriter, r *Request) {}), trFunc)
+ defer cst.close()
+
+ if _, err := cst.c.Get(cst.ts.URL); err != nil {
+ t.Fatalf("got error: %s", err)
+ }
+
+ time.Sleep(100 * time.Millisecond)
+ got := make(chan error)
+ go func() {
+ if _, err := cst.c.Get(cst.ts.URL); err != nil {
+ got <- err
+ }
+ close(got)
+ }()
+
+ timeout := time.NewTimer(5 * time.Second)
+ defer timeout.Stop()
+ select {
+ case err := <-got:
+ if err != nil {
+ t.Fatalf("got error: %s", err)
+ }
+ case <-timeout.C:
+ t.Fatal("request never completed")
+ }
+}
+
// This tests that an client requesting a content range won't also
// implicitly ask for gzip support. If they want that, they need to do it
// on their own.
diff --git a/src/net/interface_test.go b/src/net/interface_test.go
index fb6032fbc0..6cdfb6265f 100644
--- a/src/net/interface_test.go
+++ b/src/net/interface_test.go
@@ -51,6 +51,9 @@ func ipv6LinkLocalUnicastAddr(ifi *Interface) string {
}
func TestInterfaces(t *testing.T) {
+ if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
+ t.Skipf("sysctl is not supported on iOS")
+ }
ift, err := Interfaces()
if err != nil {
t.Fatal(err)
@@ -82,6 +85,9 @@ func TestInterfaces(t *testing.T) {
}
func TestInterfaceAddrs(t *testing.T) {
+ if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
+ t.Skipf("sysctl is not supported on iOS")
+ }
ift, err := Interfaces()
if err != nil {
t.Fatal(err)
@@ -101,6 +107,9 @@ func TestInterfaceAddrs(t *testing.T) {
}
func TestInterfaceUnicastAddrs(t *testing.T) {
+ if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
+ t.Skipf("sysctl is not supported on iOS")
+ }
ift, err := Interfaces()
if err != nil {
t.Fatal(err)
@@ -128,6 +137,9 @@ func TestInterfaceUnicastAddrs(t *testing.T) {
}
func TestInterfaceMulticastAddrs(t *testing.T) {
+ if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
+ t.Skipf("sysctl is not supported on iOS")
+ }
ift, err := Interfaces()
if err != nil {
t.Fatal(err)
diff --git a/src/os/os_test.go b/src/os/os_test.go
index 6c88d7e8b8..b94ab0d232 100644
--- a/src/os/os_test.go
+++ b/src/os/os_test.go
@@ -1521,6 +1521,9 @@ func testWindowsHostname(t *testing.T, hostname string) {
}
func TestHostname(t *testing.T) {
+ if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
+ t.Skipf("sysctl is not supported on iOS")
+ }
hostname, err := Hostname()
if err != nil {
t.Fatal(err)
@@ -2251,8 +2254,6 @@ func TestPipeThreads(t *testing.T) {
t.Skip("skipping on Plan 9; does not support runtime poller")
case "js":
t.Skip("skipping on js; no support for os.Pipe")
- case "darwin":
- t.Skip("skipping on Darwin; issue 33953")
}
threads := 100
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go
index 6009932056..e4a7faf965 100644
--- a/src/runtime/export_test.go
+++ b/src/runtime/export_test.go
@@ -345,6 +345,9 @@ func ReadMemStatsSlow() (base, slow MemStats) {
slow.HeapReleased += uint64(i.span().released())
}
+ // Unused space in the current arena also counts as released space.
+ slow.HeapReleased += uint64(mheap_.curArena.end - mheap_.curArena.base)
+
getg().m.mallocing--
})
diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go
index 823b556e53..8a6b860c96 100644
--- a/src/runtime/mgc.go
+++ b/src/runtime/mgc.go
@@ -229,6 +229,8 @@ func setGCPercent(in int32) (out int32) {
gcSetTriggerRatio(memstats.triggerRatio)
unlock(&mheap_.lock)
})
+ // Pacing changed, so the scavenger should be awoken.
+ wakeScavenger()
// If we just disabled GC, wait for any concurrent GC mark to
// finish so we always return with no GC running.
@@ -1649,9 +1651,16 @@ func gcMarkTermination(nextTriggerRatio float64) {
throw("gc done but gcphase != _GCoff")
}
+ // Record next_gc and heap_inuse for scavenger.
+ memstats.last_next_gc = memstats.next_gc
+ memstats.last_heap_inuse = memstats.heap_inuse
+
// Update GC trigger and pacing for the next cycle.
gcSetTriggerRatio(nextTriggerRatio)
+ // Pacing changed, so the scavenger should be awoken.
+ wakeScavenger()
+
// Update timing memstats
now := nanotime()
sec, nsec, _ := time_now()
diff --git a/src/runtime/mgcscavenge.go b/src/runtime/mgcscavenge.go
index 45a9eb2b2a..c4394a3d60 100644
--- a/src/runtime/mgcscavenge.go
+++ b/src/runtime/mgcscavenge.go
@@ -17,7 +17,29 @@
// scavenger's primary goal is to bring the estimated heap RSS of the
// application down to a goal.
//
-// That goal is defined as (retainExtraPercent+100) / 100 * next_gc.
+// That goal is defined as:
+// (retainExtraPercent+100) / 100 * (next_gc / last_next_gc) * last_heap_inuse
+//
+// Essentially, we wish to have the application's RSS track the heap goal, but
+// the heap goal is defined in terms of bytes of objects, rather than pages like
+// RSS. As a result, we need to take into account for fragmentation internal to
+// spans. next_gc / last_next_gc defines the ratio between the current heap goal
+// and the last heap goal, which tells us by how much the heap is growing and
+// shrinking. We estimate what the heap will grow to in terms of pages by taking
+// this ratio and multiplying it by heap_inuse at the end of the last GC, which
+// allows us to account for this additional fragmentation. Note that this
+// procedure makes the assumption that the degree of fragmentation won't change
+// dramatically over the next GC cycle. Overestimating the amount of
+// fragmentation simply results in higher memory use, which will be accounted
+// for by the next pacing up date. Underestimating the fragmentation however
+// could lead to performance degradation. Handling this case is not within the
+// scope of the scavenger. Situations where the amount of fragmentation balloons
+// over the course of a single GC cycle should be considered pathologies,
+// flagged as bugs, and fixed appropriately.
+//
+// An additional factor of retainExtraPercent is added as a buffer to help ensure
+// that there's more unscavenged memory to allocate out of, since each allocation
+// out of scavenged memory incurs a potentially expensive page fault.
//
// The goal is updated after each GC and the scavenger's pacing parameters
// (which live in mheap_) are updated to match. The pacing parameters work much
@@ -81,14 +103,24 @@ func heapRetained() uint64 {
//
// mheap_.lock must be held or the world must be stopped.
func gcPaceScavenger() {
- // Compute our scavenging goal and align it to a physical page boundary
- // to make the following calculations more exact.
- retainedGoal := memstats.next_gc
+ // If we're called before the first GC completed, disable scavenging.
+ // We never scavenge before the 2nd GC cycle anyway (we don't have enough
+ // information about the heap yet) so this is fine, and avoids a fault
+ // or garbage data later.
+ if memstats.last_next_gc == 0 {
+ mheap_.scavengeBytesPerNS = 0
+ return
+ }
+ // Compute our scavenging goal.
+ goalRatio := float64(memstats.next_gc) / float64(memstats.last_next_gc)
+ retainedGoal := uint64(float64(memstats.last_heap_inuse) * goalRatio)
// Add retainExtraPercent overhead to retainedGoal. This calculation
// looks strange but the purpose is to arrive at an integer division
// (e.g. if retainExtraPercent = 12.5, then we get a divisor of 8)
// that also avoids the overflow from a multiplication.
retainedGoal += retainedGoal / (1.0 / (retainExtraPercent / 100.0))
+ // Align it to a physical page boundary to make the following calculations
+ // a bit more exact.
retainedGoal = (retainedGoal + uint64(physPageSize) - 1) &^ (uint64(physPageSize) - 1)
// Represents where we are now in the heap's contribution to RSS in bytes.
@@ -154,36 +186,41 @@ func gcPaceScavenger() {
now := nanotime()
- lock(&scavenge.lock)
-
// Update all the pacing parameters in mheap with scavenge.lock held,
// so that scavenge.gen is kept in sync with the updated values.
mheap_.scavengeRetainedGoal = retainedGoal
mheap_.scavengeRetainedBasis = retainedNow
mheap_.scavengeTimeBasis = now
mheap_.scavengeBytesPerNS = float64(totalWork) / float64(totalTime)
- scavenge.gen++ // increase scavenge generation
-
- // Wake up background scavenger if needed, since the pacing was just updated.
- wakeScavengerLocked()
-
- unlock(&scavenge.lock)
+ mheap_.scavengeGen++ // increase scavenge generation
}
-// State of the background scavenger.
+// Sleep/wait state of the background scavenger.
var scavenge struct {
lock mutex
g *g
parked bool
timer *timer
- gen uint32 // read with either lock or mheap_.lock, write with both
+
+ // Generation counter.
+ //
+ // It represents the last generation count (as defined by
+ // mheap_.scavengeGen) checked by the scavenger and is updated
+ // each time the scavenger checks whether it is on-pace.
+ //
+ // Skew between this field and mheap_.scavengeGen is used to
+ // determine whether a new update is available.
+ //
+ // Protected by mheap_.lock.
+ gen uint64
}
-// wakeScavengerLocked unparks the scavenger if necessary. It must be called
+// wakeScavenger unparks the scavenger if necessary. It must be called
// after any pacing update.
//
-// scavenge.lock must be held.
-func wakeScavengerLocked() {
+// mheap_.lock and scavenge.lock must not be held.
+func wakeScavenger() {
+ lock(&scavenge.lock)
if scavenge.parked {
// Try to stop the timer but we don't really care if we succeed.
// It's possible that either a timer was never started, or that
@@ -198,11 +235,10 @@ func wakeScavengerLocked() {
scavenge.parked = false
ready(scavenge.g, 0, true)
}
+ unlock(&scavenge.lock)
}
// scavengeSleep attempts to put the scavenger to sleep for ns.
-// It also checks to see if gen != scavenge.gen before going to sleep,
-// and aborts if true (meaning an update had occurred).
//
// Note that this function should only be called by the scavenger.
//
@@ -210,24 +246,32 @@ func wakeScavengerLocked() {
// to sleep at all if there's a pending pacing change.
//
// Returns false if awoken early (i.e. true means a complete sleep).
-func scavengeSleep(gen uint32, ns int64) bool {
+func scavengeSleep(ns int64) bool {
lock(&scavenge.lock)
- // If there was an update, just abort the sleep.
- if scavenge.gen != gen {
+ // First check if there's a pending update.
+ // If there is one, don't bother sleeping.
+ var hasUpdate bool
+ systemstack(func() {
+ lock(&mheap_.lock)
+ hasUpdate = mheap_.scavengeGen != scavenge.gen
+ unlock(&mheap_.lock)
+ })
+ if hasUpdate {
unlock(&scavenge.lock)
return false
}
// Set the timer.
+ //
+ // This must happen here instead of inside gopark
+ // because we can't close over any variables without
+ // failing escape analysis.
now := nanotime()
scavenge.timer.when = now + ns
startTimer(scavenge.timer)
- // Park the goroutine. It's fine that we don't publish the
- // fact that the timer was set; even if the timer wakes up
- // and fire scavengeReady before we park, it'll block on
- // scavenge.lock.
+ // Mark ourself as asleep and go to sleep.
scavenge.parked = true
goparkunlock(&scavenge.lock, waitReasonSleep, traceEvGoSleep, 2)
@@ -248,9 +292,7 @@ func bgscavenge(c chan int) {
scavenge.timer = new(timer)
scavenge.timer.f = func(_ interface{}, _ uintptr) {
- lock(&scavenge.lock)
- wakeScavengerLocked()
- unlock(&scavenge.lock)
+ wakeScavenger()
}
c <- 1
@@ -279,14 +321,14 @@ func bgscavenge(c chan int) {
released := uintptr(0)
park := false
ttnext := int64(0)
- gen := uint32(0)
// Run on the system stack since we grab the heap lock,
// and a stack growth with the heap lock means a deadlock.
systemstack(func() {
lock(&mheap_.lock)
- gen = scavenge.gen
+ // Update the last generation count that the scavenger has handled.
+ scavenge.gen = mheap_.scavengeGen
// If background scavenging is disabled or if there's no work to do just park.
retained := heapRetained()
@@ -343,7 +385,7 @@ func bgscavenge(c chan int) {
if released == 0 {
// If we were unable to release anything this may be because there's
// no free memory available to scavenge. Go to sleep and try again.
- if scavengeSleep(gen, retryDelayNS) {
+ if scavengeSleep(retryDelayNS) {
// If we successfully slept through the delay, back off exponentially.
retryDelayNS *= 2
}
@@ -355,7 +397,7 @@ func bgscavenge(c chan int) {
// If there's an appreciable amount of time until the next scavenging
// goal, just sleep. We'll get woken up if anything changes and this
// way we avoid spinning.
- scavengeSleep(gen, ttnext)
+ scavengeSleep(ttnext)
continue
}
diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go
index 706603aba4..3807050cbe 100644
--- a/src/runtime/mheap.go
+++ b/src/runtime/mheap.go
@@ -107,6 +107,7 @@ type mheap struct {
scavengeRetainedBasis uint64
scavengeBytesPerNS float64
scavengeRetainedGoal uint64
+ scavengeGen uint64 // incremented on each pacing update
// Page reclaimer state
@@ -185,6 +186,12 @@ type mheap struct {
// simply blocking GC (by disabling preemption).
sweepArenas []arenaIdx
+ // curArena is the arena that the heap is currently growing
+ // into. This should always be physPageSize-aligned.
+ curArena struct {
+ base, end uintptr
+ }
+
_ uint32 // ensure 64-bit alignment of central
// central free lists for small size classes.
@@ -1220,16 +1227,6 @@ HaveSpan:
// heap_released since we already did so earlier.
sysUsed(unsafe.Pointer(s.base()), s.npages<<_PageShift)
s.scavenged = false
-
- // Since we allocated out of a scavenged span, we just
- // grew the RSS. Mitigate this by scavenging enough free
- // space to make up for it but only if we need to.
- //
- // scavengeLocked may cause coalescing, so prevent
- // coalescing with s by temporarily changing its state.
- s.state = mSpanManual
- h.scavengeIfNeededLocked(s.npages * pageSize)
- s.state = mSpanFree
}
h.setSpans(s.base(), npage, s)
@@ -1249,29 +1246,78 @@ HaveSpan:
// h must be locked.
func (h *mheap) grow(npage uintptr) bool {
ask := npage << _PageShift
- v, size := h.sysAlloc(ask)
- if v == nil {
- print("runtime: out of memory: cannot allocate ", ask, "-byte block (", memstats.heap_sys, " in use)\n")
- return false
- }
- // Create a fake "in use" span and free it, so that the
- // right accounting and coalescing happens.
+ nBase := round(h.curArena.base+ask, physPageSize)
+ if nBase > h.curArena.end {
+ // Not enough room in the current arena. Allocate more
+ // arena space. This may not be contiguous with the
+ // current arena, so we have to request the full ask.
+ av, asize := h.sysAlloc(ask)
+ if av == nil {
+ print("runtime: out of memory: cannot allocate ", ask, "-byte block (", memstats.heap_sys, " in use)\n")
+ return false
+ }
+
+ if uintptr(av) == h.curArena.end {
+ // The new space is contiguous with the old
+ // space, so just extend the current space.
+ h.curArena.end = uintptr(av) + asize
+ } else {
+ // The new space is discontiguous. Track what
+ // remains of the current space and switch to
+ // the new space. This should be rare.
+ if size := h.curArena.end - h.curArena.base; size != 0 {
+ h.growAddSpan(unsafe.Pointer(h.curArena.base), size)
+ }
+ // Switch to the new space.
+ h.curArena.base = uintptr(av)
+ h.curArena.end = uintptr(av) + asize
+ }
+
+ // The memory just allocated counts as both released
+ // and idle, even though it's not yet backed by spans.
+ //
+ // The allocation is always aligned to the heap arena
+ // size which is always > physPageSize, so its safe to
+ // just add directly to heap_released. Coalescing, if
+ // possible, will also always be correct in terms of
+ // accounting, because s.base() must be a physical
+ // page boundary.
+ memstats.heap_released += uint64(asize)
+ memstats.heap_idle += uint64(asize)
+
+ // Recalculate nBase
+ nBase = round(h.curArena.base+ask, physPageSize)
+ }
+
+ // Grow into the current arena.
+ v := h.curArena.base
+ h.curArena.base = nBase
+ h.growAddSpan(unsafe.Pointer(v), nBase-v)
+ return true
+}
+
+// growAddSpan adds a free span when the heap grows into [v, v+size).
+// This memory must be in the Prepared state (not Ready).
+//
+// h must be locked.
+func (h *mheap) growAddSpan(v unsafe.Pointer, size uintptr) {
+ // Scavenge some pages to make up for the virtual memory space
+ // we just allocated, but only if we need to.
+ h.scavengeIfNeededLocked(size)
+
s := (*mspan)(h.spanalloc.alloc())
s.init(uintptr(v), size/pageSize)
h.setSpans(s.base(), s.npages, s)
s.state = mSpanFree
- memstats.heap_idle += uint64(size)
- // (*mheap).sysAlloc returns untouched/uncommitted memory.
+ // [v, v+size) is always in the Prepared state. The new span
+ // must be marked scavenged so the allocator transitions it to
+ // Ready when allocating from it.
s.scavenged = true
- // s is always aligned to the heap arena size which is always > physPageSize,
- // so its totally safe to just add directly to heap_released. Coalescing,
- // if possible, will also always be correct in terms of accounting, because
- // s.base() must be a physical page boundary.
- memstats.heap_released += uint64(size)
+ // This span is both released and idle, but grow already
+ // updated both memstats.
h.coalesce(s)
h.free.insert(s)
- return true
}
// Free the span back into the heap.
diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go
index 421580eec3..09dbb26735 100644
--- a/src/runtime/mstats.go
+++ b/src/runtime/mstats.go
@@ -79,6 +79,8 @@ type mstats struct {
last_gc_nanotime uint64 // last gc (monotonic time)
tinyallocs uint64 // number of tiny allocations that didn't cause actual allocation; not exported to go directly
+ last_next_gc uint64 // next_gc for the previous GC
+ last_heap_inuse uint64 // heap_inuse at mark termination of the previous GC
// triggerRatio is the heap growth ratio that triggers marking.
//
diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
index 074ae0f40d..1cd0932eae 100644
--- a/src/runtime/os_windows.go
+++ b/src/runtime/os_windows.go
@@ -49,6 +49,7 @@ const (
//go:cgo_import_dynamic runtime._VirtualFree VirtualFree%3 "kernel32.dll"
//go:cgo_import_dynamic runtime._VirtualQuery VirtualQuery%3 "kernel32.dll"
//go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject%2 "kernel32.dll"
+//go:cgo_import_dynamic runtime._WaitForMultipleObjects WaitForMultipleObjects%4 "kernel32.dll"
//go:cgo_import_dynamic runtime._WriteConsoleW WriteConsoleW%5 "kernel32.dll"
//go:cgo_import_dynamic runtime._WriteFile WriteFile%5 "kernel32.dll"
@@ -96,6 +97,7 @@ var (
_VirtualFree,
_VirtualQuery,
_WaitForSingleObject,
+ _WaitForMultipleObjects,
_WriteConsoleW,
_WriteFile,
_ stdFunction
@@ -139,7 +141,8 @@ func tstart_stdcall(newm *m)
func ctrlhandler()
type mOS struct {
- waitsema uintptr // semaphore for parking on locks
+ waitsema uintptr // semaphore for parking on locks
+ resumesema uintptr // semaphore to indicate suspend/resume
}
//go:linkname os_sigpipe os.sigpipe
@@ -258,6 +261,40 @@ func loadOptionalSyscalls() {
}
}
+func monitorSuspendResume() {
+ const _DEVICE_NOTIFY_CALLBACK = 2
+ type _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS struct {
+ callback uintptr
+ context uintptr
+ }
+
+ powrprof := windowsLoadSystemLib([]byte("powrprof.dll\000"))
+ if powrprof == 0 {
+ return // Running on Windows 7, where we don't need it anyway.
+ }
+ powerRegisterSuspendResumeNotification := windowsFindfunc(powrprof, []byte("PowerRegisterSuspendResumeNotification\000"))
+ if powerRegisterSuspendResumeNotification == nil {
+ return // Running on Windows 7, where we don't need it anyway.
+ }
+ var fn interface{} = func(context uintptr, changeType uint32, setting uintptr) uintptr {
+ for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
+ if mp.resumesema != 0 {
+ stdcall1(_SetEvent, mp.resumesema)
+ }
+ }
+ return 0
+ }
+ params := _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS{
+ callback: compileCallback(*efaceOf(&fn), true),
+ }
+ handle := uintptr(0)
+ if stdcall3(powerRegisterSuspendResumeNotification, _DEVICE_NOTIFY_CALLBACK,
+ uintptr(unsafe.Pointer(&params)),
+ uintptr(unsafe.Pointer(&handle))) != 0 {
+ throw("PowerRegisterSuspendResumeNotification failure")
+ }
+}
+
//go:nosplit
func getLoadLibrary() uintptr {
return uintptr(unsafe.Pointer(_LoadLibraryW))
@@ -488,6 +525,10 @@ func goenvs() {
}
stdcall1(_FreeEnvironmentStringsW, uintptr(strings))
+
+ // We call this all the way here, late in init, so that malloc works
+ // for the callback function this generates.
+ monitorSuspendResume()
}
// exiting is set to non-zero when the process is exiting.
@@ -606,19 +647,32 @@ func semasleep(ns int64) int32 {
_WAIT_FAILED = 0xFFFFFFFF
)
- // store ms in ns to save stack space
+ var result uintptr
if ns < 0 {
- ns = _INFINITE
+ result = stdcall2(_WaitForSingleObject, getg().m.waitsema, uintptr(_INFINITE))
} else {
- ns = int64(timediv(ns, 1000000, nil))
- if ns == 0 {
- ns = 1
+ start := nanotime()
+ elapsed := int64(0)
+ for {
+ ms := int64(timediv(ns-elapsed, 1000000, nil))
+ if ms == 0 {
+ ms = 1
+ }
+ result = stdcall4(_WaitForMultipleObjects, 2,
+ uintptr(unsafe.Pointer(&[2]uintptr{getg().m.waitsema, getg().m.resumesema})),
+ 0, uintptr(ms))
+ if result != _WAIT_OBJECT_0+1 {
+ // Not a suspend/resume event
+ break
+ }
+ elapsed = nanotime() - start
+ if elapsed >= ns {
+ return -1
+ }
}
}
-
- result := stdcall2(_WaitForSingleObject, getg().m.waitsema, uintptr(ns))
switch result {
- case _WAIT_OBJECT_0: //signaled
+ case _WAIT_OBJECT_0: // Signaled
return 0
case _WAIT_TIMEOUT:
@@ -667,6 +721,15 @@ func semacreate(mp *m) {
throw("runtime.semacreate")
})
}
+ mp.resumesema = stdcall4(_CreateEventA, 0, 0, 0, 0)
+ if mp.resumesema == 0 {
+ systemstack(func() {
+ print("runtime: createevent failed; errno=", getlasterror(), "\n")
+ throw("runtime.semacreate")
+ })
+ stdcall1(_CloseHandle, mp.waitsema)
+ mp.waitsema = 0
+ }
}
// May run with m.p==nil, so write barriers are not allowed. This
diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go
index 376f76dbc5..a630d53a6e 100644
--- a/src/runtime/sys_darwin.go
+++ b/src/runtime/sys_darwin.go
@@ -60,7 +60,7 @@ func libcCall(fn, arg unsafe.Pointer) int32 {
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
- entersyscallblock()
+ entersyscall()
libcCall(unsafe.Pointer(funcPC(syscall)), unsafe.Pointer(&fn))
exitsyscall()
return
@@ -71,7 +71,7 @@ func syscall()
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
- entersyscallblock()
+ entersyscall()
libcCall(unsafe.Pointer(funcPC(syscall6)), unsafe.Pointer(&fn))
exitsyscall()
return
@@ -82,7 +82,7 @@ func syscall6()
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
- entersyscallblock()
+ entersyscall()
libcCall(unsafe.Pointer(funcPC(syscall6X)), unsafe.Pointer(&fn))
exitsyscall()
return
@@ -93,7 +93,7 @@ func syscall6X()
//go:nosplit
//go:cgo_unsafe_args
func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
- entersyscallblock()
+ entersyscall()
libcCall(unsafe.Pointer(funcPC(syscallPtr)), unsafe.Pointer(&fn))
exitsyscall()
return
diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go
index 722a73d108..0e2fcfb02d 100644
--- a/src/runtime/syscall_windows.go
+++ b/src/runtime/syscall_windows.go
@@ -74,16 +74,18 @@ func compileCallback(fn eface, cleanstack bool) (code uintptr) {
argsize += uintptrSize
}
- lock(&cbs.lock)
- defer unlock(&cbs.lock)
+ lock(&cbs.lock) // We don't unlock this in a defer because this is used from the system stack.
n := cbs.n
for i := 0; i < n; i++ {
if cbs.ctxt[i].gobody == fn.data && cbs.ctxt[i].isCleanstack() == cleanstack {
- return callbackasmAddr(i)
+ r := callbackasmAddr(i)
+ unlock(&cbs.lock)
+ return r
}
}
if n >= cb_max {
+ unlock(&cbs.lock)
throw("too many callback functions")
}
@@ -99,7 +101,9 @@ func compileCallback(fn eface, cleanstack bool) (code uintptr) {
cbs.ctxt[n] = c
cbs.n++
- return callbackasmAddr(n)
+ r := callbackasmAddr(n)
+ unlock(&cbs.lock)
+ return r
}
const _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
diff --git a/src/syscall/mksyscall_windows.go b/src/syscall/mksyscall_windows.go
index ee2123f939..d66bf7865f 100644
--- a/src/syscall/mksyscall_windows.go
+++ b/src/syscall/mksyscall_windows.go
@@ -4,897 +4,23 @@
// +build ignore
-/*
-mksyscall_windows generates windows system call bodies
-
-It parses all files specified on command line containing function
-prototypes (like syscall_windows.go) and prints system call bodies
-to standard output.
-
-The prototypes are marked by lines beginning with "//sys" and read
-like func declarations if //sys is replaced by func, but:
-
-* The parameter lists must give a name for each argument. This
- includes return parameters.
-
-* The parameter lists must give a type for each argument:
- the (x, y, z int) shorthand is not allowed.
-
-* If the return parameter is an error number, it must be named err.
-
-* If go func name needs to be different from its winapi dll name,
- the winapi name could be specified at the end, after "=" sign, like
- //sys LoadLibrary(libname string) (handle uint32, err error) = LoadLibraryA
-
-* Each function that returns err needs to supply a condition, that
- return value of winapi will be tested against to detect failure.
- This would set err to windows "last-error", otherwise it will be nil.
- The value can be provided at end of //sys declaration, like
- //sys LoadLibrary(libname string) (handle uint32, err error) [failretval==-1] = LoadLibraryA
- and is [failretval==0] by default.
-
-Usage:
- mksyscall_windows [flags] [path ...]
-
-The flags are:
- -output
- Specify output file name (outputs to console if blank).
- -trace
- Generate print statement after every syscall.
-*/
package main
import (
- "bufio"
- "bytes"
- "errors"
- "flag"
- "fmt"
- "go/format"
- "go/parser"
- "go/token"
- "io"
- "io/ioutil"
- "log"
"os"
+ "os/exec"
"path/filepath"
"runtime"
- "sort"
- "strconv"
- "strings"
- "text/template"
-)
-
-var (
- filename = flag.String("output", "", "output file name (standard output if omitted)")
- printTraceFlag = flag.Bool("trace", false, "generate print statement after every syscall")
- systemDLL = flag.Bool("systemdll", true, "whether all DLLs should be loaded from the Windows system directory")
)
-func trim(s string) string {
- return strings.Trim(s, " \t")
-}
-
-var packageName string
-
-func packagename() string {
- return packageName
-}
-
-func syscalldot() string {
- if packageName == "syscall" {
- return ""
- }
- return "syscall."
-}
-
-// Param is function parameter
-type Param struct {
- Name string
- Type string
- fn *Fn
- tmpVarIdx int
-}
-
-// tmpVar returns temp variable name that will be used to represent p during syscall.
-func (p *Param) tmpVar() string {
- if p.tmpVarIdx < 0 {
- p.tmpVarIdx = p.fn.curTmpVarIdx
- p.fn.curTmpVarIdx++
- }
- return fmt.Sprintf("_p%d", p.tmpVarIdx)
-}
-
-// BoolTmpVarCode returns source code for bool temp variable.
-func (p *Param) BoolTmpVarCode() string {
- const code = `var %s uint32
- if %s {
- %s = 1
- } else {
- %s = 0
- }`
- tmp := p.tmpVar()
- return fmt.Sprintf(code, tmp, p.Name, tmp, tmp)
-}
-
-// SliceTmpVarCode returns source code for slice temp variable.
-func (p *Param) SliceTmpVarCode() string {
- const code = `var %s *%s
- if len(%s) > 0 {
- %s = &%s[0]
- }`
- tmp := p.tmpVar()
- return fmt.Sprintf(code, tmp, p.Type[2:], p.Name, tmp, p.Name)
-}
-
-// StringTmpVarCode returns source code for string temp variable.
-func (p *Param) StringTmpVarCode() string {
- errvar := p.fn.Rets.ErrorVarName()
- if errvar == "" {
- errvar = "_"
- }
- tmp := p.tmpVar()
- const code = `var %s %s
- %s, %s = %s(%s)`
- s := fmt.Sprintf(code, tmp, p.fn.StrconvType(), tmp, errvar, p.fn.StrconvFunc(), p.Name)
- if errvar == "-" {
- return s
- }
- const morecode = `
- if %s != nil {
- return
- }`
- return s + fmt.Sprintf(morecode, errvar)
-}
-
-// TmpVarCode returns source code for temp variable.
-func (p *Param) TmpVarCode() string {
- switch {
- case p.Type == "bool":
- return p.BoolTmpVarCode()
- case strings.HasPrefix(p.Type, "[]"):
- return p.SliceTmpVarCode()
- default:
- return ""
- }
-}
-
-// TmpVarHelperCode returns source code for helper's temp variable.
-func (p *Param) TmpVarHelperCode() string {
- if p.Type != "string" {
- return ""
- }
- return p.StringTmpVarCode()
-}
-
-// SyscallArgList returns source code fragments representing p parameter
-// in syscall. Slices are translated into 2 syscall parameters: pointer to
-// the first element and length.
-func (p *Param) SyscallArgList() []string {
- t := p.HelperType()
- var s string
- switch {
- case t[0] == '*':
- s = fmt.Sprintf("unsafe.Pointer(%s)", p.Name)
- case t == "bool":
- s = p.tmpVar()
- case strings.HasPrefix(t, "[]"):
- return []string{
- fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.tmpVar()),
- fmt.Sprintf("uintptr(len(%s))", p.Name),
- }
- default:
- s = p.Name
- }
- return []string{fmt.Sprintf("uintptr(%s)", s)}
-}
-
-// IsError determines if p parameter is used to return error.
-func (p *Param) IsError() bool {
- return p.Name == "err" && p.Type == "error"
-}
-
-// HelperType returns type of parameter p used in helper function.
-func (p *Param) HelperType() string {
- if p.Type == "string" {
- return p.fn.StrconvType()
- }
- return p.Type
-}
-
-// join concatenates parameters ps into a string with sep separator.
-// Each parameter is converted into string by applying fn to it
-// before conversion.
-func join(ps []*Param, fn func(*Param) string, sep string) string {
- if len(ps) == 0 {
- return ""
- }
- a := make([]string, 0)
- for _, p := range ps {
- a = append(a, fn(p))
- }
- return strings.Join(a, sep)
-}
-
-// Rets describes function return parameters.
-type Rets struct {
- Name string
- Type string
- ReturnsError bool
- FailCond string
-}
-
-// ErrorVarName returns error variable name for r.
-func (r *Rets) ErrorVarName() string {
- if r.ReturnsError {
- return "err"
- }
- if r.Type == "error" {
- return r.Name
- }
- return ""
-}
-
-// ToParams converts r into slice of *Param.
-func (r *Rets) ToParams() []*Param {
- ps := make([]*Param, 0)
- if len(r.Name) > 0 {
- ps = append(ps, &Param{Name: r.Name, Type: r.Type})
- }
- if r.ReturnsError {
- ps = append(ps, &Param{Name: "err", Type: "error"})
- }
- return ps
-}
-
-// List returns source code of syscall return parameters.
-func (r *Rets) List() string {
- s := join(r.ToParams(), func(p *Param) string { return p.Name + " " + p.Type }, ", ")
- if len(s) > 0 {
- s = "(" + s + ")"
- }
- return s
-}
-
-// PrintList returns source code of trace printing part correspondent
-// to syscall return values.
-func (r *Rets) PrintList() string {
- return join(r.ToParams(), func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `)
-}
-
-// SetReturnValuesCode returns source code that accepts syscall return values.
-func (r *Rets) SetReturnValuesCode() string {
- if r.Name == "" && !r.ReturnsError {
- return ""
- }
- retvar := "r0"
- if r.Name == "" {
- retvar = "r1"
- }
- errvar := "_"
- if r.ReturnsError {
- errvar = "e1"
- }
- return fmt.Sprintf("%s, _, %s := ", retvar, errvar)
-}
-
-func (r *Rets) useLongHandleErrorCode(retvar string) string {
- const code = `if %s {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = %sEINVAL
- }
- }`
- cond := retvar + " == 0"
- if r.FailCond != "" {
- cond = strings.Replace(r.FailCond, "failretval", retvar, 1)
- }
- return fmt.Sprintf(code, cond, syscalldot())
-}
-
-// SetErrorCode returns source code that sets return parameters.
-func (r *Rets) SetErrorCode() string {
- const code = `if r0 != 0 {
- %s = %sErrno(r0)
- }`
- if r.Name == "" && !r.ReturnsError {
- return ""
- }
- if r.Name == "" {
- return r.useLongHandleErrorCode("r1")
- }
- if r.Type == "error" {
- return fmt.Sprintf(code, r.Name, syscalldot())
- }
- s := ""
- switch {
- case r.Type[0] == '*':
- s = fmt.Sprintf("%s = (%s)(unsafe.Pointer(r0))", r.Name, r.Type)
- case r.Type == "bool":
- s = fmt.Sprintf("%s = r0 != 0", r.Name)
- default:
- s = fmt.Sprintf("%s = %s(r0)", r.Name, r.Type)
- }
- if !r.ReturnsError {
- return s
- }
- return s + "\n\t" + r.useLongHandleErrorCode(r.Name)
-}
-
-// Fn describes syscall function.
-type Fn struct {
- Name string
- Params []*Param
- Rets *Rets
- PrintTrace bool
- dllname string
- dllfuncname string
- src string
- // TODO: get rid of this field and just use parameter index instead
- curTmpVarIdx int // insure tmp variables have uniq names
-}
-
-// extractParams parses s to extract function parameters.
-func extractParams(s string, f *Fn) ([]*Param, error) {
- s = trim(s)
- if s == "" {
- return nil, nil
- }
- a := strings.Split(s, ",")
- ps := make([]*Param, len(a))
- for i := range ps {
- s2 := trim(a[i])
- b := strings.Split(s2, " ")
- if len(b) != 2 {
- b = strings.Split(s2, "\t")
- if len(b) != 2 {
- return nil, errors.New("Could not extract function parameter from \"" + s2 + "\"")
- }
- }
- ps[i] = &Param{
- Name: trim(b[0]),
- Type: trim(b[1]),
- fn: f,
- tmpVarIdx: -1,
- }
- }
- return ps, nil
-}
-
-// extractSection extracts text out of string s starting after start
-// and ending just before end. found return value will indicate success,
-// and prefix, body and suffix will contain correspondent parts of string s.
-func extractSection(s string, start, end rune) (prefix, body, suffix string, found bool) {
- s = trim(s)
- if strings.HasPrefix(s, string(start)) {
- // no prefix
- body = s[1:]
- } else {
- a := strings.SplitN(s, string(start), 2)
- if len(a) != 2 {
- return "", "", s, false
- }
- prefix = a[0]
- body = a[1]
- }
- a := strings.SplitN(body, string(end), 2)
- if len(a) != 2 {
- return "", "", "", false
- }
- return prefix, a[0], a[1], true
-}
-
-// newFn parses string s and return created function Fn.
-func newFn(s string) (*Fn, error) {
- s = trim(s)
- f := &Fn{
- Rets: &Rets{},
- src: s,
- PrintTrace: *printTraceFlag,
- }
- // function name and args
- prefix, body, s, found := extractSection(s, '(', ')')
- if !found || prefix == "" {
- return nil, errors.New("Could not extract function name and parameters from \"" + f.src + "\"")
- }
- f.Name = prefix
- var err error
- f.Params, err = extractParams(body, f)
- if err != nil {
- return nil, err
- }
- // return values
- _, body, s, found = extractSection(s, '(', ')')
- if found {
- r, err := extractParams(body, f)
- if err != nil {
- return nil, err
- }
- switch len(r) {
- case 0:
- case 1:
- if r[0].IsError() {
- f.Rets.ReturnsError = true
- } else {
- f.Rets.Name = r[0].Name
- f.Rets.Type = r[0].Type
- }
- case 2:
- if !r[1].IsError() {
- return nil, errors.New("Only last windows error is allowed as second return value in \"" + f.src + "\"")
- }
- f.Rets.ReturnsError = true
- f.Rets.Name = r[0].Name
- f.Rets.Type = r[0].Type
- default:
- return nil, errors.New("Too many return values in \"" + f.src + "\"")
- }
- }
- // fail condition
- _, body, s, found = extractSection(s, '[', ']')
- if found {
- f.Rets.FailCond = body
- }
- // dll and dll function names
- s = trim(s)
- if s == "" {
- return f, nil
- }
- if !strings.HasPrefix(s, "=") {
- return nil, errors.New("Could not extract dll name from \"" + f.src + "\"")
- }
- s = trim(s[1:])
- a := strings.Split(s, ".")
- switch len(a) {
- case 1:
- f.dllfuncname = a[0]
- case 2:
- f.dllname = a[0]
- f.dllfuncname = a[1]
- default:
- return nil, errors.New("Could not extract dll name from \"" + f.src + "\"")
- }
- return f, nil
-}
-
-// DLLName returns DLL name for function f.
-func (f *Fn) DLLName() string {
- if f.dllname == "" {
- return "kernel32"
- }
- return f.dllname
-}
-
-// DLLName returns DLL function name for function f.
-func (f *Fn) DLLFuncName() string {
- if f.dllfuncname == "" {
- return f.Name
- }
- return f.dllfuncname
-}
-
-// ParamList returns source code for function f parameters.
-func (f *Fn) ParamList() string {
- return join(f.Params, func(p *Param) string { return p.Name + " " + p.Type }, ", ")
-}
-
-// HelperParamList returns source code for helper function f parameters.
-func (f *Fn) HelperParamList() string {
- return join(f.Params, func(p *Param) string { return p.Name + " " + p.HelperType() }, ", ")
-}
-
-// ParamPrintList returns source code of trace printing part correspondent
-// to syscall input parameters.
-func (f *Fn) ParamPrintList() string {
- return join(f.Params, func(p *Param) string { return fmt.Sprintf(`"%s=", %s, `, p.Name, p.Name) }, `", ", `)
-}
-
-// ParamCount return number of syscall parameters for function f.
-func (f *Fn) ParamCount() int {
- n := 0
- for _, p := range f.Params {
- n += len(p.SyscallArgList())
- }
- return n
-}
-
-// SyscallParamCount determines which version of Syscall/Syscall6/Syscall9/...
-// to use. It returns parameter count for correspondent SyscallX function.
-func (f *Fn) SyscallParamCount() int {
- n := f.ParamCount()
- switch {
- case n <= 3:
- return 3
- case n <= 6:
- return 6
- case n <= 9:
- return 9
- case n <= 12:
- return 12
- case n <= 15:
- return 15
- default:
- panic("too many arguments to system call")
- }
-}
-
-// Syscall determines which SyscallX function to use for function f.
-func (f *Fn) Syscall() string {
- c := f.SyscallParamCount()
- if c == 3 {
- return syscalldot() + "Syscall"
- }
- return syscalldot() + "Syscall" + strconv.Itoa(c)
-}
-
-// SyscallParamList returns source code for SyscallX parameters for function f.
-func (f *Fn) SyscallParamList() string {
- a := make([]string, 0)
- for _, p := range f.Params {
- a = append(a, p.SyscallArgList()...)
- }
- for len(a) < f.SyscallParamCount() {
- a = append(a, "0")
- }
- return strings.Join(a, ", ")
-}
-
-// HelperCallParamList returns source code of call into function f helper.
-func (f *Fn) HelperCallParamList() string {
- a := make([]string, 0, len(f.Params))
- for _, p := range f.Params {
- s := p.Name
- if p.Type == "string" {
- s = p.tmpVar()
- }
- a = append(a, s)
- }
- return strings.Join(a, ", ")
-}
-
-// IsUTF16 is true, if f is W (utf16) function. It is false
-// for all A (ascii) functions.
-func (f *Fn) IsUTF16() bool {
- s := f.DLLFuncName()
- return s[len(s)-1] == 'W'
-}
-
-// StrconvFunc returns name of Go string to OS string function for f.
-func (f *Fn) StrconvFunc() string {
- if f.IsUTF16() {
- return syscalldot() + "UTF16PtrFromString"
- }
- return syscalldot() + "BytePtrFromString"
-}
-
-// StrconvType returns Go type name used for OS string for f.
-func (f *Fn) StrconvType() string {
- if f.IsUTF16() {
- return "*uint16"
- }
- return "*byte"
-}
-
-// HasStringParam is true, if f has at least one string parameter.
-// Otherwise it is false.
-func (f *Fn) HasStringParam() bool {
- for _, p := range f.Params {
- if p.Type == "string" {
- return true
- }
- }
- return false
-}
-
-// HelperName returns name of function f helper.
-func (f *Fn) HelperName() string {
- if !f.HasStringParam() {
- return f.Name
- }
- return "_" + f.Name
-}
-
-// Source files and functions.
-type Source struct {
- Funcs []*Fn
- Files []string
- StdLibImports []string
- ExternalImports []string
-}
-
-func (src *Source) Import(pkg string) {
- src.StdLibImports = append(src.StdLibImports, pkg)
- sort.Strings(src.StdLibImports)
-}
-
-func (src *Source) ExternalImport(pkg string) {
- src.ExternalImports = append(src.ExternalImports, pkg)
- sort.Strings(src.ExternalImports)
-}
-
-// ParseFiles parses files listed in fs and extracts all syscall
-// functions listed in sys comments. It returns source files
-// and functions collection *Source if successful.
-func ParseFiles(fs []string) (*Source, error) {
- src := &Source{
- Funcs: make([]*Fn, 0),
- Files: make([]string, 0),
- StdLibImports: []string{
- "unsafe",
- },
- ExternalImports: make([]string, 0),
- }
- for _, file := range fs {
- if err := src.ParseFile(file); err != nil {
- return nil, err
- }
- }
- return src, nil
-}
-
-// DLLs return dll names for a source set src.
-func (src *Source) DLLs() []string {
- uniq := make(map[string]bool)
- r := make([]string, 0)
- for _, f := range src.Funcs {
- name := f.DLLName()
- if _, found := uniq[name]; !found {
- uniq[name] = true
- r = append(r, name)
- }
- }
- return r
-}
-
-// ParseFile adds additional file path to a source set src.
-func (src *Source) ParseFile(path string) error {
- file, err := os.Open(path)
- if err != nil {
- return err
- }
- defer file.Close()
-
- s := bufio.NewScanner(file)
- for s.Scan() {
- t := trim(s.Text())
- if len(t) < 7 {
- continue
- }
- if !strings.HasPrefix(t, "//sys") {
- continue
- }
- t = t[5:]
- if !(t[0] == ' ' || t[0] == '\t') {
- continue
- }
- f, err := newFn(t[1:])
- if err != nil {
- return err
- }
- src.Funcs = append(src.Funcs, f)
- }
- if err := s.Err(); err != nil {
- return err
- }
- src.Files = append(src.Files, path)
-
- // get package name
- fset := token.NewFileSet()
- _, err = file.Seek(0, 0)
- if err != nil {
- return err
- }
- pkg, err := parser.ParseFile(fset, "", file, parser.PackageClauseOnly)
- if err != nil {
- return err
- }
- packageName = pkg.Name.Name
-
- return nil
-}
-
-// IsStdRepo reports whether src is part of standard library.
-func (src *Source) IsStdRepo() (bool, error) {
- if len(src.Files) == 0 {
- return false, errors.New("no input files provided")
- }
- abspath, err := filepath.Abs(src.Files[0])
- if err != nil {
- return false, err
- }
- goroot := runtime.GOROOT()
- if runtime.GOOS == "windows" {
- abspath = strings.ToLower(abspath)
- goroot = strings.ToLower(goroot)
- }
- sep := string(os.PathSeparator)
- if !strings.HasSuffix(goroot, sep) {
- goroot += sep
- }
- return strings.HasPrefix(abspath, goroot), nil
-}
-
-// Generate output source file from a source set src.
-func (src *Source) Generate(w io.Writer) error {
- const (
- pkgStd = iota // any package in std library
- pkgXSysWindows // x/sys/windows package
- pkgOther
- )
- isStdRepo, err := src.IsStdRepo()
- if err != nil {
- return err
- }
- var pkgtype int
- switch {
- case isStdRepo:
- pkgtype = pkgStd
- case packageName == "windows":
- // TODO: this needs better logic than just using package name
- pkgtype = pkgXSysWindows
- default:
- pkgtype = pkgOther
- }
- if *systemDLL {
- switch pkgtype {
- case pkgStd:
- src.Import("internal/syscall/windows/sysdll")
- case pkgXSysWindows:
- default:
- src.ExternalImport("golang.org/x/sys/windows")
- }
- }
- if packageName != "syscall" {
- src.Import("syscall")
- }
- funcMap := template.FuncMap{
- "packagename": packagename,
- "syscalldot": syscalldot,
- "newlazydll": func(dll string) string {
- arg := "\"" + dll + ".dll\""
- if !*systemDLL {
- return syscalldot() + "NewLazyDLL(" + arg + ")"
- }
- switch pkgtype {
- case pkgStd:
- return syscalldot() + "NewLazyDLL(sysdll.Add(" + arg + "))"
- case pkgXSysWindows:
- return "NewLazySystemDLL(" + arg + ")"
- default:
- return "windows.NewLazySystemDLL(" + arg + ")"
- }
- },
- }
- t := template.Must(template.New("main").Funcs(funcMap).Parse(srcTemplate))
- err = t.Execute(w, src)
- if err != nil {
- return errors.New("Failed to execute template: " + err.Error())
- }
- return nil
-}
-
-func usage() {
- fmt.Fprintf(os.Stderr, "usage: mksyscall_windows [flags] [path ...]\n")
- flag.PrintDefaults()
- os.Exit(1)
-}
-
func main() {
- flag.Usage = usage
- flag.Parse()
- if len(flag.Args()) <= 0 {
- fmt.Fprintf(os.Stderr, "no files to parse provided\n")
- usage()
- }
-
- src, err := ParseFiles(flag.Args())
- if err != nil {
- log.Fatal(err)
- }
-
- var buf bytes.Buffer
- if err := src.Generate(&buf); err != nil {
- log.Fatal(err)
- }
-
- data, err := format.Source(buf.Bytes())
+ os.Stderr.WriteString("WARNING: Please switch from using:\n go run $GOROOT/src/syscall/mksyscall_windows.go\nto using:\n go run golang.org/x/sys/windows/mkwinsyscall\n")
+ args := append([]string{"run", "golang.org/x/sys/windows/mkwinsyscall"}, os.Args[1:]...)
+ cmd := exec.Command(filepath.Join(runtime.GOROOT(), "bin", "go"), args...)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ err := cmd.Run()
if err != nil {
- log.Fatal(err)
- }
- if *filename == "" {
- _, err = os.Stdout.Write(data)
- } else {
- err = ioutil.WriteFile(*filename, data, 0644)
- }
- if err != nil {
- log.Fatal(err)
+ os.Exit(1)
}
}
-
-// TODO: use println instead to print in the following template
-const srcTemplate = `
-
-{{define "main"}}// Code generated by 'go generate'; DO NOT EDIT.
-
-package {{packagename}}
-
-import (
-{{range .StdLibImports}}"{{.}}"
-{{end}}
-
-{{range .ExternalImports}}"{{.}}"
-{{end}}
-)
-
-var _ unsafe.Pointer
-
-// Do the interface allocations only once for common
-// Errno values.
-const (
- errnoERROR_IO_PENDING = 997
-)
-
-var (
- errERROR_IO_PENDING error = {{syscalldot}}Errno(errnoERROR_IO_PENDING)
-)
-
-// errnoErr returns common boxed Errno values, to prevent
-// allocations at runtime.
-func errnoErr(e {{syscalldot}}Errno) error {
- switch e {
- case 0:
- return nil
- case errnoERROR_IO_PENDING:
- return errERROR_IO_PENDING
- }
- // TODO: add more here, after collecting data on the common
- // error values see on Windows. (perhaps when running
- // all.bat?)
- return e
-}
-
-var (
-{{template "dlls" .}}
-{{template "funcnames" .}})
-{{range .Funcs}}{{if .HasStringParam}}{{template "helperbody" .}}{{end}}{{template "funcbody" .}}{{end}}
-{{end}}
-
-{{/* help functions */}}
-
-{{define "dlls"}}{{range .DLLs}} mod{{.}} = {{newlazydll .}}
-{{end}}{{end}}
-
-{{define "funcnames"}}{{range .Funcs}} proc{{.DLLFuncName}} = mod{{.DLLName}}.NewProc("{{.DLLFuncName}}")
-{{end}}{{end}}
-
-{{define "helperbody"}}
-func {{.Name}}({{.ParamList}}) {{template "results" .}}{
-{{template "helpertmpvars" .}} return {{.HelperName}}({{.HelperCallParamList}})
-}
-{{end}}
-
-{{define "funcbody"}}
-func {{.HelperName}}({{.HelperParamList}}) {{template "results" .}}{
-{{template "tmpvars" .}} {{template "syscall" .}}
-{{template "seterror" .}}{{template "printtrace" .}} return
-}
-{{end}}
-
-{{define "helpertmpvars"}}{{range .Params}}{{if .TmpVarHelperCode}} {{.TmpVarHelperCode}}
-{{end}}{{end}}{{end}}
-
-{{define "tmpvars"}}{{range .Params}}{{if .TmpVarCode}} {{.TmpVarCode}}
-{{end}}{{end}}{{end}}
-
-{{define "results"}}{{if .Rets.List}}{{.Rets.List}} {{end}}{{end}}
-
-{{define "syscall"}}{{.Rets.SetReturnValuesCode}}{{.Syscall}}(proc{{.DLLFuncName}}.Addr(), {{.ParamCount}}, {{.SyscallParamList}}){{end}}
-
-{{define "seterror"}}{{if .Rets.SetErrorCode}} {{.Rets.SetErrorCode}}
-{{end}}{{end}}
-
-{{define "printtrace"}}{{if .PrintTrace}} print("SYSCALL: {{.Name}}(", {{.ParamPrintList}}") (", {{.Rets.PrintList}}")\n")
-{{end}}{{end}}
-
-`
diff --git a/src/syscall/syscall.go b/src/syscall/syscall.go
index e02fc502c7..980ef9d27f 100644
--- a/src/syscall/syscall.go
+++ b/src/syscall/syscall.go
@@ -26,7 +26,7 @@
//
package syscall
-//go:generate go run mksyscall_windows.go -systemdll -output zsyscall_windows.go syscall_windows.go security_windows.go
+//go:generate go run golang.org/x/sys/windows/mkwinsyscall -systemdll -output zsyscall_windows.go syscall_windows.go security_windows.go
// StringByteSlice converts a string to a NUL-terminated []byte,
// If s contains a NUL byte this function panics instead of
diff --git a/src/syscall/syscall_darwin.go b/src/syscall/syscall_darwin.go
index 7d795ee4d3..2efcf3bea9 100644
--- a/src/syscall/syscall_darwin.go
+++ b/src/syscall/syscall_darwin.go
@@ -337,7 +337,6 @@ func Kill(pid int, signum Signal) (err error) { return kill(pid, int(signum), 1)
//sysnb ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_ioctl
//sysnb execve(path *byte, argv **byte, envp **byte) (err error)
//sysnb exit(res int) (err error)
-//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error)
//sys fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (val int, err error) = SYS_fcntl
//sys unlinkat(fd int, path string, flags int) (err error)
//sys openat(fd int, path string, flags int, perm uint32) (fdret int, err error)
diff --git a/src/syscall/syscall_darwin_386.go b/src/syscall/syscall_darwin_386.go
index 8c5b82da55..46714bab57 100644
--- a/src/syscall/syscall_darwin_386.go
+++ b/src/syscall/syscall_darwin_386.go
@@ -22,6 +22,7 @@ func setTimeval(sec, usec int64) Timeval {
//sys Statfs(path string, stat *Statfs_t) (err error) = SYS_statfs64
//sys fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_fstatat64
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
+//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error)
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint32(fd)
diff --git a/src/syscall/syscall_darwin_amd64.go b/src/syscall/syscall_darwin_amd64.go
index 23a4e5f996..43506e4531 100644
--- a/src/syscall/syscall_darwin_amd64.go
+++ b/src/syscall/syscall_darwin_amd64.go
@@ -22,6 +22,7 @@ func setTimeval(sec, usec int64) Timeval {
//sys Statfs(path string, stat *Statfs_t) (err error) = SYS_statfs64
//sys fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_fstatat64
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
+//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error)
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint64(fd)
diff --git a/src/syscall/syscall_darwin_arm.go b/src/syscall/syscall_darwin_arm.go
index 7f39cf4003..4ca2e300e4 100644
--- a/src/syscall/syscall_darwin_arm.go
+++ b/src/syscall/syscall_darwin_arm.go
@@ -29,6 +29,10 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) error {
return ENOTSUP
}
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error {
+ return ENOTSUP
+}
+
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint32(fd)
k.Filter = int16(mode)
diff --git a/src/syscall/syscall_darwin_arm64.go b/src/syscall/syscall_darwin_arm64.go
index bd110f2e7f..fde48f3596 100644
--- a/src/syscall/syscall_darwin_arm64.go
+++ b/src/syscall/syscall_darwin_arm64.go
@@ -29,6 +29,10 @@ func ptrace(request int, pid int, addr uintptr, data uintptr) error {
return ENOTSUP
}
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error {
+ return ENOTSUP
+}
+
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint64(fd)
k.Filter = int16(mode)
diff --git a/src/syscall/zsyscall_darwin_386.go b/src/syscall/zsyscall_darwin_386.go
index 2c3b15f5f9..0ffc692116 100644
--- a/src/syscall/zsyscall_darwin_386.go
+++ b/src/syscall/zsyscall_darwin_386.go
@@ -1870,27 +1870,6 @@ func libc_exit_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
- var _p0 unsafe.Pointer
- if len(mib) > 0 {
- _p0 = unsafe.Pointer(&mib[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- _, _, e1 := syscall6(funcPC(libc_sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func libc_sysctl_trampoline()
-
-//go:linkname libc_sysctl libc_sysctl
-//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (val int, err error) {
r0, _, e1 := syscall(funcPC(libc_fcntl_trampoline), uintptr(fd), uintptr(cmd), uintptr(arg))
val = int(r0)
@@ -2081,3 +2060,24 @@ func libc_ptrace_trampoline()
//go:linkname libc_ptrace libc_ptrace
//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
+ var _p0 unsafe.Pointer
+ if len(mib) > 0 {
+ _p0 = unsafe.Pointer(&mib[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := syscall6(funcPC(libc_sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+func libc_sysctl_trampoline()
+
+//go:linkname libc_sysctl libc_sysctl
+//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
diff --git a/src/syscall/zsyscall_darwin_386.s b/src/syscall/zsyscall_darwin_386.s
index d84b46229e..0dec5baa22 100644
--- a/src/syscall/zsyscall_darwin_386.s
+++ b/src/syscall/zsyscall_darwin_386.s
@@ -229,8 +229,6 @@ TEXT ·libc_execve_trampoline(SB),NOSPLIT,$0-0
JMP libc_execve(SB)
TEXT ·libc_exit_trampoline(SB),NOSPLIT,$0-0
JMP libc_exit(SB)
-TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0
- JMP libc_sysctl(SB)
TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0
JMP libc_unlinkat(SB)
TEXT ·libc_openat_trampoline(SB),NOSPLIT,$0-0
@@ -251,3 +249,5 @@ TEXT ·libc_fstatat64_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstatat64(SB)
TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0
JMP libc_ptrace(SB)
+TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0
+ JMP libc_sysctl(SB)
diff --git a/src/syscall/zsyscall_darwin_amd64.go b/src/syscall/zsyscall_darwin_amd64.go
index 83214de2fb..942152ae39 100644
--- a/src/syscall/zsyscall_darwin_amd64.go
+++ b/src/syscall/zsyscall_darwin_amd64.go
@@ -1870,27 +1870,6 @@ func libc_exit_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
- var _p0 unsafe.Pointer
- if len(mib) > 0 {
- _p0 = unsafe.Pointer(&mib[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- _, _, e1 := syscall6(funcPC(libc_sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func libc_sysctl_trampoline()
-
-//go:linkname libc_sysctl libc_sysctl
-//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (val int, err error) {
r0, _, e1 := syscall(funcPC(libc_fcntl_trampoline), uintptr(fd), uintptr(cmd), uintptr(arg))
val = int(r0)
@@ -2081,3 +2060,24 @@ func libc_ptrace_trampoline()
//go:linkname libc_ptrace libc_ptrace
//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
+ var _p0 unsafe.Pointer
+ if len(mib) > 0 {
+ _p0 = unsafe.Pointer(&mib[0])
+ } else {
+ _p0 = unsafe.Pointer(&_zero)
+ }
+ _, _, e1 := syscall6(funcPC(libc_sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+func libc_sysctl_trampoline()
+
+//go:linkname libc_sysctl libc_sysctl
+//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
diff --git a/src/syscall/zsyscall_darwin_amd64.s b/src/syscall/zsyscall_darwin_amd64.s
index 23ddbe06c0..fcb7f9c291 100644
--- a/src/syscall/zsyscall_darwin_amd64.s
+++ b/src/syscall/zsyscall_darwin_amd64.s
@@ -229,8 +229,6 @@ TEXT ·libc_execve_trampoline(SB),NOSPLIT,$0-0
JMP libc_execve(SB)
TEXT ·libc_exit_trampoline(SB),NOSPLIT,$0-0
JMP libc_exit(SB)
-TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0
- JMP libc_sysctl(SB)
TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0
JMP libc_unlinkat(SB)
TEXT ·libc_openat_trampoline(SB),NOSPLIT,$0-0
@@ -251,3 +249,5 @@ TEXT ·libc_fstatat64_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstatat64(SB)
TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0
JMP libc_ptrace(SB)
+TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0
+ JMP libc_sysctl(SB)
diff --git a/src/syscall/zsyscall_darwin_arm.go b/src/syscall/zsyscall_darwin_arm.go
index 2a643f209f..73ee205d33 100644
--- a/src/syscall/zsyscall_darwin_arm.go
+++ b/src/syscall/zsyscall_darwin_arm.go
@@ -1870,27 +1870,6 @@ func libc_exit_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
- var _p0 unsafe.Pointer
- if len(mib) > 0 {
- _p0 = unsafe.Pointer(&mib[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- _, _, e1 := syscall6(funcPC(libc_sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func libc_sysctl_trampoline()
-
-//go:linkname libc_sysctl libc_sysctl
-//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (val int, err error) {
r0, _, e1 := syscall(funcPC(libc_fcntl_trampoline), uintptr(fd), uintptr(cmd), uintptr(arg))
val = int(r0)
diff --git a/src/syscall/zsyscall_darwin_arm.s b/src/syscall/zsyscall_darwin_arm.s
index c7cd83d83e..6462a198b0 100644
--- a/src/syscall/zsyscall_darwin_arm.s
+++ b/src/syscall/zsyscall_darwin_arm.s
@@ -229,8 +229,6 @@ TEXT ·libc_execve_trampoline(SB),NOSPLIT,$0-0
JMP libc_execve(SB)
TEXT ·libc_exit_trampoline(SB),NOSPLIT,$0-0
JMP libc_exit(SB)
-TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0
- JMP libc_sysctl(SB)
TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0
JMP libc_unlinkat(SB)
TEXT ·libc_openat_trampoline(SB),NOSPLIT,$0-0
diff --git a/src/syscall/zsyscall_darwin_arm64.go b/src/syscall/zsyscall_darwin_arm64.go
index 0b77839869..bbe092cd07 100644
--- a/src/syscall/zsyscall_darwin_arm64.go
+++ b/src/syscall/zsyscall_darwin_arm64.go
@@ -1870,27 +1870,6 @@ func libc_exit_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
- var _p0 unsafe.Pointer
- if len(mib) > 0 {
- _p0 = unsafe.Pointer(&mib[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- _, _, e1 := syscall6(funcPC(libc_sysctl_trampoline), uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func libc_sysctl_trampoline()
-
-//go:linkname libc_sysctl libc_sysctl
-//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (val int, err error) {
r0, _, e1 := syscall(funcPC(libc_fcntl_trampoline), uintptr(fd), uintptr(cmd), uintptr(arg))
val = int(r0)
diff --git a/src/syscall/zsyscall_darwin_arm64.s b/src/syscall/zsyscall_darwin_arm64.s
index 7b8b3764a8..ec2210f1df 100644
--- a/src/syscall/zsyscall_darwin_arm64.s
+++ b/src/syscall/zsyscall_darwin_arm64.s
@@ -229,8 +229,6 @@ TEXT ·libc_execve_trampoline(SB),NOSPLIT,$0-0
JMP libc_execve(SB)
TEXT ·libc_exit_trampoline(SB),NOSPLIT,$0-0
JMP libc_exit(SB)
-TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0
- JMP libc_sysctl(SB)
TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0
JMP libc_unlinkat(SB)
TEXT ·libc_openat_trampoline(SB),NOSPLIT,$0-0
diff --git a/test/fixedbugs/issue31747.go b/test/fixedbugs/issue31747.go
index dfb585c613..420fe30735 100644
--- a/test/fixedbugs/issue31747.go
+++ b/test/fixedbugs/issue31747.go
@@ -8,11 +8,11 @@ package p
// numeric literals
const (
- _ = 1_000 // ERROR "underscores in numeric literals only supported as of -lang=go1.13"
- _ = 0b111 // ERROR "binary literals only supported as of -lang=go1.13"
- _ = 0o567 // ERROR "0o/0O-style octal literals only supported as of -lang=go1.13"
+ _ = 1_000 // ERROR "underscores in numeric literals requires go1.13 or later \(-lang was set to go1.12; check go.mod\)"
+ _ = 0b111 // ERROR "binary literals requires go1.13 or later"
+ _ = 0o567 // ERROR "0o/0O-style octal literals requires go1.13 or later"
_ = 0xabc // ok
- _ = 0x0p1 // ERROR "hexadecimal floating-point literals only supported as of -lang=go1.13"
+ _ = 0x0p1 // ERROR "hexadecimal floating-point literals requires go1.13 or later"
_ = 0B111 // ERROR "binary"
_ = 0O567 // ERROR "octal"
@@ -29,6 +29,6 @@ const (
// signed shift counts
var (
s int
- _ = 1 << s // ERROR "signed shift count type int, only supported as of -lang=go1.13"
+ _ = 1 << s // ERROR "invalid operation: 1 << s \(signed shift count type int\) requires go1.13 or later"
_ = 1 >> s // ERROR "signed shift count"
)