diff --git a/VERSION b/VERSION index 06b29847687a85ab8f5e113c03ae7935a5c1211c..a246dd81516f21faad3bc341a6bd45e27ca1b714 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -go1.18.3 \ No newline at end of file +go1.18.10 \ No newline at end of file diff --git a/debian/changelog b/debian/changelog index be0c44fa5401a3d0f8e4a4ab0fdd754e227ed75b..178bf33ce7e815046ec2ea390fe39a34b58ebead 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,125 @@ +golang-1.18 (1.18.10-1~bpo11+1) bullseye-backports; urgency=medium + + * Rebuild for bullseye-backports. + + -- Anthony Fok <foka@debian.org> Tue, 17 Jan 2023 08:51:18 -0700 + +golang-1.18 (1.18.10-1) unstable; urgency=medium + + * Team upload. + * New upstream version 1.18.10 + * Add NO_PNG_PKG_MANGLE to prevent mangling testdata. + This is Ubuntu specific behaviour so they can sync the package without + vendor patch. + + -- Shengjing Zhu <zhsj@debian.org> Wed, 11 Jan 2023 16:33:29 +0800 + +golang-1.18 (1.18.9-1) unstable; urgency=medium + + * New upstream version 1.18.9 + + CVE-2022-41720: os, net/http: avoid escapes from os.DirFS and http.Dir + on Windows + + CVE-2022-41717: net/http: limit canonical header cache by bytes, not + entries + + -- William 'jawn-smith' Wilson <jawn-smith@ubuntu.com> Tue, 06 Dec 2022 13:39:48 -0600 + +golang-1.18 (1.18.8-1~bpo11+1) bullseye-backports; urgency=medium + + * Rebuild for bullseye-backports. + + -- Anthony Fok <foka@debian.org> Mon, 21 Nov 2022 21:59:26 -0700 + +golang-1.18 (1.18.8-1) unstable; urgency=medium + + * New upstream version 1.18.8 + + CVE-2022-41716: syscall, os/exec: unsanitized NUL in environment variables + On Windows, syscall.StartProcess and os/exec.Cmd did not properly check + for invalid environment variable values. A malicious environment variable + value could exploit this behavior to set a value for a different + environment variable. + + -- William 'jawn-smith' Wilson <jawn-smith@ubuntu.com> Thu, 03 Nov 2022 08:20:54 -0500 + +golang-1.18 (1.18.7-1) unstable; urgency=medium + + * New upstream version 1.18.7 + + CVE-2022-2879: archive/tar: unbounded memory consumption when reading + headers + + CVE-2022-2880: net/http/httputil: ReverseProxy should not forward + unparseable query parameters + + CVE-2022-41715: regexp/syntax: limit memory used by parsing regexps + + -- William 'jawn-smith' Wilson <jawn-smith@ubuntu.com> Tue, 04 Oct 2022 15:34:34 -0500 + +golang-1.18 (1.18.6-1~bpo11+1) bullseye-backports; urgency=medium + + * Rebuild for bullseye-backports. + + -- Anthony Fok <foka@debian.org> Wed, 21 Sep 2022 10:38:52 -0600 + +golang-1.18 (1.18.6-1) unstable; urgency=medium + + * New upstream version 1.18.6 + + CVE-2022-27664: net/http: handle server errors after sending GOAWAY + + CVE-2022-32190: net/url: JoinPath does not strip relative path + components in all circumstances + + -- William 'jawn-smith' Wilson <jawn-smith@ubuntu.com> Tue, 06 Sep 2022 15:05:10 -0500 + +golang-1.18 (1.18.5-1~bpo11+1) bullseye-backports; urgency=medium + + * Rebuild for bullseye-backports. + + -- Anthony Fok <foka@debian.org> Sat, 06 Aug 2022 06:30:50 -0600 + +golang-1.18 (1.18.5-1) unstable; urgency=medium + + * New upstream version 1.18.5 + + CVE-2022-32189: math/big: index out of range in Float.GobDecode + + cmd/go: Build information embedded by Go 1.18 impairs build + reproducibility with cgo flags (Closes: #1008114) + * Remove 0005-cmd-compile-revert-fix-missing-dict-pass-for-type-as.patch + which has been applied upstream in v1.18.5 + * Bump Standards-Version to 4.6.1 (no change) + + -- Anthony Fok <foka@debian.org> Sat, 06 Aug 2022 04:56:18 -0600 + +golang-1.18 (1.18.4-2) unstable; urgency=medium + + * Team upload. + * cmd/compile: revert "fix missing dict pass for type assertions" + Backport patch from https://go.dev/cl/417615 (Closes: #1015088) + + -- Shengjing Zhu <zhsj@debian.org> Tue, 26 Jul 2022 10:58:55 +0800 + +golang-1.18 (1.18.4-1~bpo11+1) bullseye-backports; urgency=medium + + * Rebuild for bullseye-backports. + + -- Anthony Fok <foka@debian.org> Thu, 14 Jul 2022 11:01:43 -0600 + +golang-1.18 (1.18.4-1) unstable; urgency=medium + + * New upstream version 1.18.4 + + CVE-2022-1705: net/http: improper sanitization of Transfer-Encoding + header + + CVE-2022-32148: When httputil.ReverseProxy.ServeHTTP was called with a + Request.Header map containing a nil value for the X-Forwarded-For header, + ReverseProxy would set the client IP as the value of the X-Forwarded-For + header, contrary to its documentation. In the more usual case where a + Director function set the X-Forwarded-For header value to nil, + ReverseProxy would leave the header unmodified as expected. + + CVE-2022-30631: compress/gzip: stack exhaustion in Reader.Read + + CVE-2022-30633: encoding/xml: stack exhaustion in Unmarshal + + CVE-2022-28131: encoding/xml: stack exhaustion in Decoder.Skip + + CVE-2022-30635: encoding/gob: stack exhaustion in Decoder.Decode + + CVE-2022-30632: path/filepath: stack exhaustion in Glob + + CVE-2022-30630: io/fs: stack exhaustion in Glob + + CVE-2022-1962: go/parser: stack exhaustion in all Parse* functions + + -- William 'jawn-smith' Wilson <jawn-smith@ubuntu.com> Tue, 12 Jul 2022 19:08:18 -0500 + golang-1.18 (1.18.3-1~bpo11+1) bullseye-backports; urgency=medium * Rebuild for bullseye-backports. diff --git a/debian/control b/debian/control index c9620a516463e73de125fa8b93260edb9d2bf27c..7ba5224b430b5530a9786a274d14f5a9da20f901 100644 --- a/debian/control +++ b/debian/control @@ -15,7 +15,7 @@ Priority: optional Build-Depends: debhelper-compat (= 13), golang-any (>= 2:1.4~) | golang-go (>= 2:1.4~) | gccgo (>= 4:5~), netbase -Standards-Version: 4.6.0 +Standards-Version: 4.6.1 Vcs-Browser: https://salsa.debian.org/go-team/compiler/golang/tree/golang-1.18 Vcs-Git: https://salsa.debian.org/go-team/compiler/golang.git -b golang-1.18 Homepage: https://go.dev/ diff --git a/debian/control.in b/debian/control.in index 3cc1561162dc667eb6864ec95de881347f59d467..a0f378c0a6380fae6cd019c595f033d4c36b6a32 100644 --- a/debian/control.in +++ b/debian/control.in @@ -11,7 +11,7 @@ Priority: optional Build-Depends: debhelper-compat (= 13), golang-any (>= 2:1.4~) | golang-go (>= 2:1.4~) | gccgo (>= 4:5~), netbase -Standards-Version: 4.6.0 +Standards-Version: 4.6.1 Vcs-Browser: https://salsa.debian.org/go-team/compiler/golang/tree/golang-X.Y Vcs-Git: https://salsa.debian.org/go-team/compiler/golang.git -b golang-X.Y Homepage: https://go.dev/ diff --git a/debian/patches/0001-Disable-test-for-UserHomeDir.patch b/debian/patches/0001-Disable-test-for-UserHomeDir.patch index 3cf9813c5af1b0f3cbc346eb2ff9e8f0938d19bf..29a38b1e5727100a07cf9553c1830135b4c6cf91 100644 --- a/debian/patches/0001-Disable-test-for-UserHomeDir.patch +++ b/debian/patches/0001-Disable-test-for-UserHomeDir.patch @@ -7,9 +7,11 @@ On Debian buildds, the user home dir does not exist, so this test fails. src/os/os_test.go | 2 ++ 1 file changed, 2 insertions(+) +diff --git a/src/os/os_test.go b/src/os/os_test.go +index 63427de..1695375 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go -@@ -2540,6 +2540,8 @@ +@@ -2534,6 +2534,8 @@ func TestUserHomeDir(t *testing.T) { if err != nil { t.Skipf("UserHomeDir failed: %v", err) } diff --git a/debian/patches/0002-Fix-Lintian-warnings-about-wrong-interpreter-path.patch b/debian/patches/0002-Fix-Lintian-warnings-about-wrong-interpreter-path.patch index f83aa0587ff86f906b0d3bd0162eae28c1c90e78..3068cc34e18f3b772d34e44aa8da310047601d97 100644 --- a/debian/patches/0002-Fix-Lintian-warnings-about-wrong-interpreter-path.patch +++ b/debian/patches/0002-Fix-Lintian-warnings-about-wrong-interpreter-path.patch @@ -9,14 +9,15 @@ grep -rH "/usr/bin/env perl" * | cut -d: -f1 | xargs -n1 sed -i -e "s,/usr/bin/e src/syscall/mksyscall.pl | 2 +- src/syscall/mksyscall_libc.pl | 2 +- src/syscall/mksysctl_openbsd.pl | 2 +- - src/syscall/mksysnum_darwin.pl | 2 +- src/syscall/mksysnum_dragonfly.pl | 2 +- src/syscall/mksysnum_freebsd.pl | 2 +- src/syscall/mksysnum_linux.pl | 2 +- src/syscall/mksysnum_netbsd.pl | 2 +- src/syscall/mksysnum_openbsd.pl | 2 +- - 9 files changed, 9 insertions(+), 9 deletions(-) + 8 files changed, 8 insertions(+), 8 deletions(-) +diff --git a/src/syscall/mksyscall.pl b/src/syscall/mksyscall.pl +index 25ab911..98de8e8 100755 --- a/src/syscall/mksyscall.pl +++ b/src/syscall/mksyscall.pl @@ -1,4 +1,4 @@ @@ -25,6 +26,8 @@ grep -rH "/usr/bin/env perl" * | cut -d: -f1 | xargs -n1 sed -i -e "s,/usr/bin/e # Copyright 2009 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. +diff --git a/src/syscall/mksyscall_libc.pl b/src/syscall/mksyscall_libc.pl +index 3731476..47457a1 100755 --- a/src/syscall/mksyscall_libc.pl +++ b/src/syscall/mksyscall_libc.pl @@ -1,4 +1,4 @@ @@ -33,6 +36,8 @@ grep -rH "/usr/bin/env perl" * | cut -d: -f1 | xargs -n1 sed -i -e "s,/usr/bin/e # Copyright 2009 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. +diff --git a/src/syscall/mksysctl_openbsd.pl b/src/syscall/mksysctl_openbsd.pl +index ea462a7..7e8a3e2 100755 --- a/src/syscall/mksysctl_openbsd.pl +++ b/src/syscall/mksysctl_openbsd.pl @@ -1,4 +1,4 @@ @@ -41,6 +46,8 @@ grep -rH "/usr/bin/env perl" * | cut -d: -f1 | xargs -n1 sed -i -e "s,/usr/bin/e # Copyright 2011 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style +diff --git a/src/syscall/mksysnum_dragonfly.pl b/src/syscall/mksysnum_dragonfly.pl +index e9a634b..a8df18d 100755 --- a/src/syscall/mksysnum_dragonfly.pl +++ b/src/syscall/mksysnum_dragonfly.pl @@ -1,4 +1,4 @@ @@ -49,6 +56,8 @@ grep -rH "/usr/bin/env perl" * | cut -d: -f1 | xargs -n1 sed -i -e "s,/usr/bin/e # Copyright 2009 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. +diff --git a/src/syscall/mksysnum_freebsd.pl b/src/syscall/mksysnum_freebsd.pl +index c04ada9..f9b7b91 100755 --- a/src/syscall/mksysnum_freebsd.pl +++ b/src/syscall/mksysnum_freebsd.pl @@ -1,4 +1,4 @@ @@ -57,6 +66,8 @@ grep -rH "/usr/bin/env perl" * | cut -d: -f1 | xargs -n1 sed -i -e "s,/usr/bin/e # Copyright 2009 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. +diff --git a/src/syscall/mksysnum_linux.pl b/src/syscall/mksysnum_linux.pl +index 5fb1d0e..ebeb9a8 100755 --- a/src/syscall/mksysnum_linux.pl +++ b/src/syscall/mksysnum_linux.pl @@ -1,4 +1,4 @@ @@ -65,6 +76,8 @@ grep -rH "/usr/bin/env perl" * | cut -d: -f1 | xargs -n1 sed -i -e "s,/usr/bin/e # Copyright 2009 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. +diff --git a/src/syscall/mksysnum_netbsd.pl b/src/syscall/mksysnum_netbsd.pl +index 4f5150a..53783ff 100755 --- a/src/syscall/mksysnum_netbsd.pl +++ b/src/syscall/mksysnum_netbsd.pl @@ -1,4 +1,4 @@ @@ -73,6 +86,8 @@ grep -rH "/usr/bin/env perl" * | cut -d: -f1 | xargs -n1 sed -i -e "s,/usr/bin/e # Copyright 2009 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. +diff --git a/src/syscall/mksysnum_openbsd.pl b/src/syscall/mksysnum_openbsd.pl +index f8f484b..312486d 100755 --- a/src/syscall/mksysnum_openbsd.pl +++ b/src/syscall/mksysnum_openbsd.pl @@ -1,4 +1,4 @@ diff --git a/debian/patches/0005-cmd-dist-increase-default-timeout-scale-for-arm.patch b/debian/patches/0003-cmd-dist-increase-default-timeout-scale-for-arm.patch similarity index 86% rename from debian/patches/0005-cmd-dist-increase-default-timeout-scale-for-arm.patch rename to debian/patches/0003-cmd-dist-increase-default-timeout-scale-for-arm.patch index 9f146a89721dbdcb4fb4ab5744287ca55cc271a8..7dc8a004cb91c3e1d28a478c69a823534b777913 100644 --- a/debian/patches/0005-cmd-dist-increase-default-timeout-scale-for-arm.patch +++ b/debian/patches/0003-cmd-dist-increase-default-timeout-scale-for-arm.patch @@ -14,9 +14,11 @@ scale on arm to avoid tests timing out. src/cmd/dist/test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) +diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go +index d9eb9c3..c82d746 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go -@@ -165,7 +165,7 @@ +@@ -173,7 +173,7 @@ func (t *tester) run() { t.timeoutScale = 1 switch goarch { case "arm": diff --git a/debian/patches/0006-skip-userns-test-in-schroot-as-well.patch b/debian/patches/0004-skip-userns-test-in-schroot-as-well.patch similarity index 80% rename from debian/patches/0006-skip-userns-test-in-schroot-as-well.patch rename to debian/patches/0004-skip-userns-test-in-schroot-as-well.patch index 2d874c8bf7ddfb39ea21a0ca9cabc01d844648e9..1b135d3f1fa338a0e5ec8ad6723c16194ab36718 100644 --- a/debian/patches/0006-skip-userns-test-in-schroot-as-well.patch +++ b/debian/patches/0004-skip-userns-test-in-schroot-as-well.patch @@ -3,14 +3,15 @@ Date: Fri, 5 Feb 2021 21:21:45 +0800 Subject: skip userns test in schroot as well When schroot is using overlayfs, it fails to detect it as chroot. - --- src/syscall/exec_linux_test.go | 7 +++++++ 1 file changed, 7 insertions(+) +diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go +index 0ec9c4d..cabaaf9 100644 --- a/src/syscall/exec_linux_test.go +++ b/src/syscall/exec_linux_test.go -@@ -33,6 +33,10 @@ +@@ -32,6 +32,10 @@ func isLXC() bool { return os.Getenv("container") == "lxc" } @@ -21,7 +22,7 @@ When schroot is using overlayfs, it fails to detect it as chroot. func skipInContainer(t *testing.T) { // TODO: the callers of this func are using this func to skip // tests when running as some sort of "fake root" that's uid 0 -@@ -48,6 +52,9 @@ +@@ -47,6 +51,9 @@ func skipInContainer(t *testing.T) { if isLXC() { t.Skip("skip this test in LXC container") } diff --git a/debian/patches/series b/debian/patches/series index ca8b1d3cc1b7923e50dec041d6896069305a76d0..63e10a0e1534978b747f41e18bd6b02fca06f16e 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,4 +1,4 @@ 0001-Disable-test-for-UserHomeDir.patch 0002-Fix-Lintian-warnings-about-wrong-interpreter-path.patch -0005-cmd-dist-increase-default-timeout-scale-for-arm.patch -0006-skip-userns-test-in-schroot-as-well.patch +0003-cmd-dist-increase-default-timeout-scale-for-arm.patch +0004-skip-userns-test-in-schroot-as-well.patch diff --git a/debian/rules b/debian/rules index 6e88151b19271fc424ea7642a71cf6aef95033b0..7c091610ad97c7b60ff5fb7dab8da2ecc02f2292 100755 --- a/debian/rules +++ b/debian/rules @@ -7,6 +7,9 @@ include /usr/share/dpkg/architecture.mk # for DEB_VERSION_UPSTREAM include /usr/share/dpkg/pkg-info.mk +# Ubuntu mangles png files by default, which can break the testdata. +export NO_PNG_PKG_MANGLE := 1 + export GOVER := $(shell echo $(DEB_VERSION_UPSTREAM) | grep -oP '^([0-9]+\.[0-9]+)') export GOROOT := $(CURDIR) diff --git a/debian/upstream/signing-key.asc b/debian/upstream/signing-key.asc index 39d3905252c974465ad69b2c8079eed381ef1808..60e82b8d7e93f8ea03a3b619a1a737c9cdf785b6 100644 --- a/debian/upstream/signing-key.asc +++ b/debian/upstream/signing-key.asc @@ -160,6 +160,39 @@ yICWUW/wXuhhHkkwNTiwfciJfVA8ckOiRubik8geEH5boOxgeAaBu6yusQVHnRRy G4wjQ+qsWo+wDI9WMdtpNG1toJrSUL4OYa4oX3YogSv5hGrbYIaP4HwO6O2oTMnS 0lRIGJOqbEQcmKUa/nWT/3NipTnYzyMjMlEQe89YKjd+32tjMfOSdIOvwCGaTizd WnKPF77qB9D0v8C/7AdHmEFqf2ZX8vK31aaY+ZpPWG5IHlf6f/buIMBalJOxIBev -eBqxcHwQ -=4zaS +eBqxcHwQuQINBGF4DJ8BEACk2Gwau+s/pKmOTnGLMnB3ybQsiVGLRhsw2SqSTvSy +BthAyW1UAqdRqNA8/FdMlvVuppG8+vCLXPmpP63C+9M2tyQeOR2aVQp+u1EIwN4l +Pu4wrh6vdtgSRim8uxBdLIHG16z0xxVhE2rM/Ot/gucfkpoEw289VaR7sPmIxfVT +m1QcqCGiFQl3rZnma6Bz8UOXJoE8wO+LK5WkcdmFz6+Z3BLSb5IL9lhsArFToNq5 +dN2SSTbCTdHRzrRuoCdefYHdxoLCM4kJfggRRgWhKoEJro+ZipESq1T5yHV/iAJy ++3DuC8LbYLvsjt9VZYARw8xIGb90Vj3ThWuMoVr/IVmKT7foC5Whe0PTI/b2frNa +WCxxC4cRVxMusiBX66mclQ4Mvzwj50G1WKygULYcvPQ81Tg0pvgTKqgxwL9luN9M +iDVtkn9CZx7NFlszVr+ic7nVJjANnJebFHCEZfJbQo4uIwKfYbhopUkCa41iXpes +bVzAKqNwePgyNTAMFyYnjAUE8FVUmx7ZJVb15iEbMs38gJKJ/Wb8wtJRflAfkhrE +zh1M/43WUAU3RfPmXTrGeyDCYKTHiXTnj748uH6U40sB9q+qeEhZdTj0KufjgtWa +FWsZTkVrtGOaI6xfX6py/k3hjU3es+7ddElxhPBcqNE3pkPRqb9wz+exSdM7hiUz +NwARAQABiQREBBgBCAAPBQJheAyfAhsCBQkFo5qAAikJEHch9jvTi0eWwV0gBBkB +CAAGBQJheAyfAAoJEE6yfbKjuIuLggkP/1INRyRToLmY1ms9DTWMQ0lwbBL8J3xu +/neKIOKVGOdw9zcWlGugUoOthSbT8bjvuybH1Vjx4wFM+cnuMVfjD58Xu6ZpgCHN +1wXYMuzYweBFKaMg4oSwTKuAJBJ2IhfEm/cAryVvKY2zY+uyzgizx3vAg3sjkAPD +crSCJP2nkuHcJ3nzUbKNAjmdMsnWDrqqZVwP99nuyMk8bAtueZ0SKvIpCv2wIeYO +7zkj61vuQOFOGhl98OBui5wUhtgQw//esTWYiGNKSmD3derd2JHVA01tBmCWV4KM +LDbg3CcMMQ1x3V1me6EG3giwBL1I9xTsBUbEa6eEN9U0zdKvoMbSogON5wCuxAzO +/CXGMreJtBUupHEc69oTuwe426Ihi3AbRrPAg3tnGGFCt11HoQFNnRPWb3unF8Ul +A2rSytvwFyQi3pzBYt5VsTIA7NEHGuJs+/Oor6AOInzht1cp7AfmDGfGy2N5ow+4 +GI6FPe2UqIg2+nFiGr9hRZOvXRgLQL8dlDnFChymldxm/J/UFdJGSWRldEDsPrzH +QESKvsV9EjnJQR5p5zkQK6jx0zqSlDgiNG2GT3/CSvwIdCih6Cl9HThHtYNm3ZYN +0bU9W2jeoLh3AINNTcrp0tAHZuQLFxukbj56O5eB+nfk67/X2iNii46ZdJQNwbT9 +YN6CstQz+Cnqg7YP/3G6Y6NHIQggXnlYIi3iwN72hEgEqz6vIRK87lBGW2r3eQ0c +DZuE3+5Q4FYciw+B2RKeDhjdmPHypA5o+RiAyI7JOZwJalqHO3nwJG5sr0rRzcJs +bGvpbzso2JuTyTURv4tBNq45b9y0Qdzt5PpNrPJbQADJWn+HWsbVJB5gWBTdoQYg +pyTr84nQyscWAUFTRbmHvtjCCfLdvU8wM7ubAQ5Dwi1pABRttRAMuPA94HzaBF5y +XkghxHpnW0IcXGiwgch9LQyaO9VSRhiPH6r5Zuk7KvGhHph7SC5JgUn9vJmmp1zc +d0mXQ2Zh8M81J3Ri3iGPHM2CqplAxXNbIrnztbEJhN2I+77m73Z4d+K1ivg6xQht +eSZhwhx7/Z3Tl+U2jYOEFIn/UFmV3UxRSJa/jQRcjvMKprSp4tAZ2yJI3babjRbi +xgUEtlK105/JepxcAdw9vosxO/rR7VqCzu0copdxC0GAH8og+A9/3LPhlRGy3Qhf +zjy9JHWHj4EIsol02BS8+dWvAoYerkve9O9+h6/B5wM/Yng9BjT+OrNvkfmqK2cs +pBXwYedOrC4uWcUmueEVrv5P4FF36wJ+ejvPS6vdTxVTdLXjouUHwTQQZVlNjWY3 +cIyj03nZ19c+b30+2FzG/uSnb/ePWsRLY7Iyz4ygr8etweBPnEIvjwpAZxOu +=ilBW -----END PGP PUBLIC KEY BLOCK----- diff --git a/misc/cgo/testcarchive/carchive_test.go b/misc/cgo/testcarchive/carchive_test.go index d36b97b70ecc35d74be60afbc084ac7faa3e6e61..3d325a5e34b5249c23da9eb8b62cf2e849a4d23c 100644 --- a/misc/cgo/testcarchive/carchive_test.go +++ b/misc/cgo/testcarchive/carchive_test.go @@ -19,6 +19,7 @@ import ( "runtime" "strconv" "strings" + "sync" "syscall" "testing" "time" @@ -518,38 +519,13 @@ func TestEarlySignalHandler(t *testing.T) { func TestSignalForwarding(t *testing.T) { checkSignalForwardingTest(t) + buildSignalForwardingTest(t) - if !testWork { - defer func() { - os.Remove("libgo2.a") - os.Remove("libgo2.h") - os.Remove("testp" + exeSuffix) - os.RemoveAll(filepath.Join(GOPATH, "pkg")) - }() - } - - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2") - if out, err := cmd.CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - checkLineComments(t, "libgo2.h") - checkArchive(t, "libgo2.a") - - ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a") - if runtime.Compiler == "gccgo" { - ccArgs = append(ccArgs, "-lgo") - } - if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - - cmd = exec.Command(bin[0], append(bin[1:], "1")...) + cmd := exec.Command(bin[0], append(bin[1:], "1")...) out, err := cmd.CombinedOutput() t.Logf("%v\n%s", cmd.Args, out) - expectSignal(t, err, syscall.SIGSEGV) + expectSignal(t, err, syscall.SIGSEGV, 0) // SIGPIPE is never forwarded on darwin. See golang.org/issue/33384. if runtime.GOOS != "darwin" && runtime.GOOS != "ios" { @@ -560,7 +536,7 @@ func TestSignalForwarding(t *testing.T) { if len(out) > 0 { t.Logf("%s", out) } - expectSignal(t, err, syscall.SIGPIPE) + expectSignal(t, err, syscall.SIGPIPE, 0) } } @@ -571,21 +547,100 @@ func TestSignalForwardingExternal(t *testing.T) { t.Skipf("skipping on %s/%s: runtime does not permit SI_USER SIGSEGV", GOOS, GOARCH) } checkSignalForwardingTest(t) + buildSignalForwardingTest(t) + // We want to send the process a signal and see if it dies. + // Normally the signal goes to the C thread, the Go signal + // handler picks it up, sees that it is running in a C thread, + // and the program dies. Unfortunately, occasionally the + // signal is delivered to a Go thread, which winds up + // discarding it because it was sent by another program and + // there is no Go handler for it. To avoid this, run the + // program several times in the hopes that it will eventually + // fail. + const tries = 20 + for i := 0; i < tries; i++ { + err := runSignalForwardingTest(t, "2") + if err == nil { + continue + } + + // If the signal is delivered to a C thread, as expected, + // the Go signal handler will disable itself and re-raise + // the signal, causing the program to die with SIGSEGV. + // + // It is also possible that the signal will be + // delivered to a Go thread, such as a GC thread. + // Currently when the Go runtime sees that a SIGSEGV was + // sent from a different program, it first tries to send + // the signal to the os/signal API. If nothing is looking + // for (or explicitly ignoring) SIGSEGV, then it crashes. + // Because the Go runtime is invoked via a c-archive, + // it treats this as GOTRACEBACK=crash, meaning that it + // dumps a stack trace for all goroutines, which it does + // by raising SIGQUIT. The effect is that we will see the + // program die with SIGQUIT in that case, not SIGSEGV. + if expectSignal(t, err, syscall.SIGSEGV, syscall.SIGQUIT) { + return + } + } + + t.Errorf("program succeeded unexpectedly %d times", tries) +} + +func TestSignalForwardingGo(t *testing.T) { + // This test fails on darwin-amd64 because of the special + // handling of user-generated SIGSEGV signals in fixsigcode in + // runtime/signal_darwin_amd64.go. + if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" { + t.Skip("not supported on darwin-amd64") + } + + checkSignalForwardingTest(t) + buildSignalForwardingTest(t) + err := runSignalForwardingTest(t, "4") + + // Occasionally the signal will be delivered to a C thread, + // and the program will crash with SIGSEGV. + expectSignal(t, err, syscall.SIGQUIT, syscall.SIGSEGV) +} + +// checkSignalForwardingTest calls t.Skip if the SignalForwarding test +// doesn't work on this platform. +func checkSignalForwardingTest(t *testing.T) { + switch GOOS { + case "darwin", "ios": + switch GOARCH { + case "arm64": + t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH) + } + case "windows": + t.Skip("skipping signal test on Windows") + } +} + +// buildSignalForwardingTest builds the executable used by the various +// signal forwarding tests. +func buildSignalForwardingTest(t *testing.T) { if !testWork { - defer func() { + t.Cleanup(func() { os.Remove("libgo2.a") os.Remove("libgo2.h") os.Remove("testp" + exeSuffix) os.RemoveAll(filepath.Join(GOPATH, "pkg")) - }() + }) } + t.Log("go build -buildmode=c-archive -o libgo2.a ./libgo2") cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2") - if out, err := cmd.CombinedOutput(); err != nil { + out, err := cmd.CombinedOutput() + if len(out) > 0 { t.Logf("%s", out) + } + if err != nil { t.Fatal(err) } + checkLineComments(t, "libgo2.h") checkArchive(t, "libgo2.a") @@ -593,91 +648,92 @@ func TestSignalForwardingExternal(t *testing.T) { if runtime.Compiler == "gccgo" { ccArgs = append(ccArgs, "-lgo") } - if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { + t.Log(ccArgs) + out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput() + if len(out) > 0 { t.Logf("%s", out) + } + if err != nil { t.Fatal(err) } +} - // We want to send the process a signal and see if it dies. - // Normally the signal goes to the C thread, the Go signal - // handler picks it up, sees that it is running in a C thread, - // and the program dies. Unfortunately, occasionally the - // signal is delivered to a Go thread, which winds up - // discarding it because it was sent by another program and - // there is no Go handler for it. To avoid this, run the - // program several times in the hopes that it will eventually - // fail. - const tries = 20 - for i := 0; i < tries; i++ { - cmd = exec.Command(bin[0], append(bin[1:], "2")...) +func runSignalForwardingTest(t *testing.T, arg string) error { + t.Logf("%v %s", bin, arg) + cmd := exec.Command(bin[0], append(bin[1:], arg)...) - stderr, err := cmd.StderrPipe() - if err != nil { - t.Fatal(err) - } - defer stderr.Close() + var out strings.Builder + cmd.Stdout = &out - r := bufio.NewReader(stderr) + stderr, err := cmd.StderrPipe() + if err != nil { + t.Fatal(err) + } + defer stderr.Close() - err = cmd.Start() + r := bufio.NewReader(stderr) - if err != nil { - t.Fatal(err) - } + err = cmd.Start() + if err != nil { + t.Fatal(err) + } - // Wait for trigger to ensure that the process is started. - ok, err := r.ReadString('\n') + // Wait for trigger to ensure that process is started. + ok, err := r.ReadString('\n') - // Verify trigger. - if err != nil || ok != "OK\n" { - t.Fatalf("Did not receive OK signal") - } + // Verify trigger. + if err != nil || ok != "OK\n" { + t.Fatal("Did not receive OK signal") + } - // Give the program a chance to enter the sleep function. - time.Sleep(time.Millisecond) + var wg sync.WaitGroup + wg.Add(1) + var errsb strings.Builder + go func() { + defer wg.Done() + io.Copy(&errsb, r) + }() - cmd.Process.Signal(syscall.SIGSEGV) + // Give the program a chance to enter the function. + // If the program doesn't get there the test will still + // pass, although it doesn't quite test what we intended. + // This is fine as long as the program normally makes it. + time.Sleep(time.Millisecond) - err = cmd.Wait() + cmd.Process.Signal(syscall.SIGSEGV) - if err == nil { - continue - } + err = cmd.Wait() - if expectSignal(t, err, syscall.SIGSEGV) { - return - } + s := out.String() + if len(s) > 0 { + t.Log(s) } - - t.Errorf("program succeeded unexpectedly %d times", tries) -} - -// checkSignalForwardingTest calls t.Skip if the SignalForwarding test -// doesn't work on this platform. -func checkSignalForwardingTest(t *testing.T) { - switch GOOS { - case "darwin", "ios": - switch GOARCH { - case "arm64": - t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH) - } - case "windows": - t.Skip("skipping signal test on Windows") + wg.Wait() + s = errsb.String() + if len(s) > 0 { + t.Log(s) } + + return err } // expectSignal checks that err, the exit status of a test program, -// shows a failure due to a specific signal. Returns whether we found -// the expected signal. -func expectSignal(t *testing.T, err error, sig syscall.Signal) bool { +// shows a failure due to a specific signal or two. Returns whether we +// found an expected signal. +func expectSignal(t *testing.T, err error, sig1, sig2 syscall.Signal) bool { + t.Helper() if err == nil { t.Error("test program succeeded unexpectedly") } else if ee, ok := err.(*exec.ExitError); !ok { t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err) } else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok { t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys()) - } else if !ws.Signaled() || ws.Signal() != sig { - t.Errorf("got %v; expected signal %v", ee, sig) + } else if !ws.Signaled() || (ws.Signal() != sig1 && ws.Signal() != sig2) { + if sig2 == 0 { + t.Errorf("got %q; expected signal %q", ee, sig1) + } else { + t.Errorf("got %q; expected signal %q or %q", ee, sig1, sig2) + } } else { return true } @@ -1013,14 +1069,14 @@ func TestCompileWithoutShared(t *testing.T) { binArgs := append(cmdToRun(exe), "1") out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput() t.Logf("%v\n%s", binArgs, out) - expectSignal(t, err, syscall.SIGSEGV) + expectSignal(t, err, syscall.SIGSEGV, 0) // SIGPIPE is never forwarded on darwin. See golang.org/issue/33384. if runtime.GOOS != "darwin" && runtime.GOOS != "ios" { binArgs := append(cmdToRun(exe), "3") out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput() t.Logf("%v\n%s", binArgs, out) - expectSignal(t, err, syscall.SIGPIPE) + expectSignal(t, err, syscall.SIGPIPE, 0) } } diff --git a/misc/cgo/testcarchive/testdata/libgo2/libgo2.go b/misc/cgo/testcarchive/testdata/libgo2/libgo2.go index 19c8e1a6dcb8e8dd8c13d24f778a8685f3c113e8..35c89ae92bbff744bc1be569d75f2639bcb279dd 100644 --- a/misc/cgo/testcarchive/testdata/libgo2/libgo2.go +++ b/misc/cgo/testcarchive/testdata/libgo2/libgo2.go @@ -49,6 +49,12 @@ func RunGoroutines() { } } +// Block blocks the current thread while running Go code. +//export Block +func Block() { + select {} +} + var P *byte // TestSEGV makes sure that an invalid address turns into a run-time Go panic. diff --git a/misc/cgo/testcarchive/testdata/main5.c b/misc/cgo/testcarchive/testdata/main5.c index d431ce01ce52513822c5e85bed7227eab474fb37..c64c246fdea8e5dfe058d39563d65b85c04f65c5 100644 --- a/misc/cgo/testcarchive/testdata/main5.c +++ b/misc/cgo/testcarchive/testdata/main5.c @@ -29,10 +29,6 @@ int main(int argc, char** argv) { verbose = (argc > 2); - if (verbose) { - printf("calling RunGoroutines\n"); - } - Noop(); switch (test) { @@ -90,6 +86,15 @@ int main(int argc, char** argv) { printf("did not receive SIGPIPE\n"); return 0; } + case 4: { + fprintf(stderr, "OK\n"); + fflush(stderr); + + if (verbose) { + printf("calling Block\n"); + } + Block(); + } default: printf("Unknown test: %d\n", test); return 0; diff --git a/misc/cgo/testcshared/cshared_test.go b/misc/cgo/testcshared/cshared_test.go index c9e9e5fe63e4a53222b442c3db6f846a853d3b0d..1cd8c2ab4ad3ee2fe7f20d0956ff3ce63ba39885 100644 --- a/misc/cgo/testcshared/cshared_test.go +++ b/misc/cgo/testcshared/cshared_test.go @@ -317,30 +317,46 @@ func createHeaders() error { if err != nil { return fmt.Errorf("unable to find dlltool path: %v\n%s\n", err, out) } - args := []string{strings.TrimSpace(string(out)), "-D", args[6], "-l", libgoname, "-d", "libgo.def"} - - // This is an unfortunate workaround for https://github.com/mstorsjo/llvm-mingw/issues/205 in which - // we basically reimplement the contents of the dlltool.sh wrapper: https://git.io/JZFlU - dlltoolContents, err := os.ReadFile(args[0]) - if err != nil { - return fmt.Errorf("unable to read dlltool: %v\n", err) + dlltoolpath := strings.TrimSpace(string(out)) + if filepath.Ext(dlltoolpath) == "" { + // Some compilers report slash-separated paths without extensions + // instead of ordinary Windows paths. + // Try to find the canonical name for the path. + if lp, err := exec.LookPath(dlltoolpath); err == nil { + dlltoolpath = lp + } } - if bytes.HasPrefix(dlltoolContents, []byte("#!/bin/sh")) && bytes.Contains(dlltoolContents, []byte("llvm-dlltool")) { - base, name := filepath.Split(args[0]) - args[0] = filepath.Join(base, "llvm-dlltool") - var machine string - switch prefix, _, _ := strings.Cut(name, "-"); prefix { - case "i686": - machine = "i386" - case "x86_64": - machine = "i386:x86-64" - case "armv7": - machine = "arm" - case "aarch64": - machine = "arm64" + + args := []string{dlltoolpath, "-D", args[6], "-l", libgoname, "-d", "libgo.def"} + + if filepath.Ext(dlltoolpath) == "" { + // This is an unfortunate workaround for + // https://github.com/mstorsjo/llvm-mingw/issues/205 in which + // we basically reimplement the contents of the dlltool.sh + // wrapper: https://git.io/JZFlU. + // TODO(thanm): remove this workaround once we can upgrade + // the compilers on the windows-arm64 builder. + dlltoolContents, err := os.ReadFile(args[0]) + if err != nil { + return fmt.Errorf("unable to read dlltool: %v\n", err) } - if len(machine) > 0 { - args = append(args, "-m", machine) + if bytes.HasPrefix(dlltoolContents, []byte("#!/bin/sh")) && bytes.Contains(dlltoolContents, []byte("llvm-dlltool")) { + base, name := filepath.Split(args[0]) + args[0] = filepath.Join(base, "llvm-dlltool") + var machine string + switch prefix, _, _ := strings.Cut(name, "-"); prefix { + case "i686": + machine = "i386" + case "x86_64": + machine = "i386:x86-64" + case "armv7": + machine = "arm" + case "aarch64": + machine = "arm64" + } + if len(machine) > 0 { + args = append(args, "-m", machine) + } } } diff --git a/src/archive/tar/format.go b/src/archive/tar/format.go index 21b9d9d4dbc628f7f18a370d7bb10f597b0efc70..8898c438b513e0ebfd628348f21ee77b0a129b53 100644 --- a/src/archive/tar/format.go +++ b/src/archive/tar/format.go @@ -143,6 +143,10 @@ const ( blockSize = 512 // Size of each block in a tar stream nameSize = 100 // Max length of the name field in USTAR format prefixSize = 155 // Max length of the prefix field in USTAR format + + // Max length of a special file (PAX header, GNU long name or link). + // This matches the limit used by libarchive. + maxSpecialFileSize = 1 << 20 ) // blockPadding computes the number of bytes needed to pad offset up to the diff --git a/src/archive/tar/reader.go b/src/archive/tar/reader.go index 4b11909bc9527d37af905cba8c33f495b83893ca..e609c15f27af73b0f41d1ed75f9945205db20d8d 100644 --- a/src/archive/tar/reader.go +++ b/src/archive/tar/reader.go @@ -103,7 +103,7 @@ func (tr *Reader) next() (*Header, error) { continue // This is a meta header affecting the next header case TypeGNULongName, TypeGNULongLink: format.mayOnlyBe(FormatGNU) - realname, err := io.ReadAll(tr) + realname, err := readSpecialFile(tr) if err != nil { return nil, err } @@ -293,7 +293,7 @@ func mergePAX(hdr *Header, paxHdrs map[string]string) (err error) { // parsePAX parses PAX headers. // If an extended header (type 'x') is invalid, ErrHeader is returned func parsePAX(r io.Reader) (map[string]string, error) { - buf, err := io.ReadAll(r) + buf, err := readSpecialFile(r) if err != nil { return nil, err } @@ -828,6 +828,16 @@ func tryReadFull(r io.Reader, b []byte) (n int, err error) { return n, err } +// readSpecialFile is like io.ReadAll except it returns +// ErrFieldTooLong if more than maxSpecialFileSize is read. +func readSpecialFile(r io.Reader) ([]byte, error) { + buf, err := io.ReadAll(io.LimitReader(r, maxSpecialFileSize+1)) + if len(buf) > maxSpecialFileSize { + return nil, ErrFieldTooLong + } + return buf, err +} + // discard skips n bytes in r, reporting an error if unable to do so. func discard(r io.Reader, n int64) error { // If possible, Seek to the last byte before the end of the data section. diff --git a/src/archive/tar/reader_test.go b/src/archive/tar/reader_test.go index f21a6065b485706f3e2c2825f1fd8c04472fa275..140c736429120cdfc0648ff9c6b92552ba43a70b 100644 --- a/src/archive/tar/reader_test.go +++ b/src/archive/tar/reader_test.go @@ -6,6 +6,7 @@ package tar import ( "bytes" + "compress/bzip2" "crypto/md5" "errors" "fmt" @@ -243,6 +244,9 @@ func TestReader(t *testing.T) { }, { file: "testdata/pax-bad-hdr-file.tar", err: ErrHeader, + }, { + file: "testdata/pax-bad-hdr-large.tar.bz2", + err: ErrFieldTooLong, }, { file: "testdata/pax-bad-mtime-file.tar", err: ErrHeader, @@ -625,9 +629,14 @@ func TestReader(t *testing.T) { } defer f.Close() + var fr io.Reader = f + if strings.HasSuffix(v.file, ".bz2") { + fr = bzip2.NewReader(fr) + } + // Capture all headers and checksums. var ( - tr = NewReader(f) + tr = NewReader(fr) hdrs []*Header chksums []string rdbuf = make([]byte, 8) diff --git a/src/archive/tar/testdata/pax-bad-hdr-large.tar.bz2 b/src/archive/tar/testdata/pax-bad-hdr-large.tar.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..06bf710d3ae4e96a27487124f08e30c9e318699d Binary files /dev/null and b/src/archive/tar/testdata/pax-bad-hdr-large.tar.bz2 differ diff --git a/src/archive/tar/writer.go b/src/archive/tar/writer.go index 3729f7e82c192f685e43398a88d2777bde5c17e0..9b2e3e25d4ceb10920da917a0c711d679d7c7b4e 100644 --- a/src/archive/tar/writer.go +++ b/src/archive/tar/writer.go @@ -199,6 +199,9 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHdrs map[string]string) error { flag = TypeXHeader } data := buf.String() + if len(data) > maxSpecialFileSize { + return ErrFieldTooLong + } if err := tw.writeRawFile(name, data, flag, FormatPAX); err != nil || isGlobal { return err // Global headers return here } diff --git a/src/archive/tar/writer_test.go b/src/archive/tar/writer_test.go index da3fb89e65e51ecd17627d444af95b68e54f4596..640264984a96e5530591af4b4d0ebcb1e17b1cf1 100644 --- a/src/archive/tar/writer_test.go +++ b/src/archive/tar/writer_test.go @@ -1004,6 +1004,33 @@ func TestIssue12594(t *testing.T) { } } +func TestWriteLongHeader(t *testing.T) { + for _, test := range []struct { + name string + h *Header + }{{ + name: "name too long", + h: &Header{Name: strings.Repeat("a", maxSpecialFileSize)}, + }, { + name: "linkname too long", + h: &Header{Linkname: strings.Repeat("a", maxSpecialFileSize)}, + }, { + name: "uname too long", + h: &Header{Uname: strings.Repeat("a", maxSpecialFileSize)}, + }, { + name: "gname too long", + h: &Header{Gname: strings.Repeat("a", maxSpecialFileSize)}, + }, { + name: "PAX header too long", + h: &Header{PAXRecords: map[string]string{"GOLANG.x": strings.Repeat("a", maxSpecialFileSize)}}, + }} { + w := NewWriter(io.Discard) + if err := w.WriteHeader(test.h); err != ErrFieldTooLong { + t.Errorf("%v: w.WriteHeader() = %v, want ErrFieldTooLong", test.name, err) + } + } +} + // testNonEmptyWriter wraps an io.Writer and ensures that // Write is never called with an empty buffer. type testNonEmptyWriter struct{ io.Writer } diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 997a830994f09bdd6118299e31e20125cadff3ff..79d27c3e374d107e0ae40556236641537f8298b3 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -577,8 +577,23 @@ func (p *Package) loadDWARF(f *File, conv *typeConv, names []*Name) { switch e.Tag { case dwarf.TagVariable: name, _ := e.Val(dwarf.AttrName).(string) + // As of https://reviews.llvm.org/D123534, clang + // now emits DW_TAG_variable DIEs that have + // no name (so as to be able to describe the + // type and source locations of constant strings + // like the second arg in the call below: + // + // myfunction(42, "foo") + // + // If a var has no name we won't see attempts to + // refer to it via "C.<name>", so skip these vars + // + // See issue 53000 for more context. + if name == "" { + break + } typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset) - if name == "" || typOff == 0 { + if typOff == 0 { if e.Val(dwarf.AttrSpecification) != nil { // Since we are reading all the DWARF, // assume we will see the variable elsewhere. @@ -2215,6 +2230,8 @@ var dwarfToName = map[string]string{ "long long unsigned int": "ulonglong", "signed char": "schar", "unsigned char": "uchar", + "unsigned long": "ulong", // Used by Clang 14; issue 53013. + "unsigned long long": "ulonglong", // Used by Clang 14; issue 53013. } const signedDelta = 64 diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index b0e5c34030f32b9d6b62159a7fef03e4dc3a5e80..b5db283e8702800295a5e3a51f1d9d6f91273359 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -78,6 +78,8 @@ func storeByType(t *types.Type) obj.As { return x86.AMOVL case 8: return x86.AMOVQ + case 16: + return x86.AMOVUPS } } panic(fmt.Sprintf("bad store type %v", t)) diff --git a/src/cmd/compile/internal/dwarfgen/dwarf.go b/src/cmd/compile/internal/dwarfgen/dwarf.go index e249a52e57a9839b7c32c444be97c864f6929acc..8ae03d70e62acc3424a4f95ef7026faaea7980da 100644 --- a/src/cmd/compile/internal/dwarfgen/dwarf.go +++ b/src/cmd/compile/internal/dwarfgen/dwarf.go @@ -91,6 +91,11 @@ func Info(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.Scope, continue } apdecls = append(apdecls, n) + if n.Type().Kind() == types.TSSA { + // Can happen for TypeInt128 types. This only happens for + // spill locations, so not a huge deal. + continue + } fnsym.Func().RecordAutoType(reflectdata.TypeLinksym(n.Type())) } } diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 716a7fbcd93a25900e204efa575a3a532aabd6fd..bc7ec5cf204f2318b47d75841102ea132815c107 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -771,18 +771,18 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b // CalleeEffects appends any side effects from evaluating callee to init. func CalleeEffects(init *ir.Nodes, callee ir.Node) { for { + init.Append(ir.TakeInit(callee)...) + switch callee.Op() { case ir.ONAME, ir.OCLOSURE, ir.OMETHEXPR: return // done case ir.OCONVNOP: conv := callee.(*ir.ConvExpr) - init.Append(ir.TakeInit(conv)...) callee = conv.X case ir.OINLCALL: ic := callee.(*ir.InlinedCallExpr) - init.Append(ir.TakeInit(ic)...) init.Append(ic.Body.Take()...) callee = ic.SingleResult() diff --git a/src/cmd/compile/internal/ir/symtab.go b/src/cmd/compile/internal/ir/symtab.go index b204a1d544e7b4e2ba9835d1b7c27f529082adf6..148edb2c885e4250409b6f1236715fe250966f0f 100644 --- a/src/cmd/compile/internal/ir/symtab.go +++ b/src/cmd/compile/internal/ir/symtab.go @@ -26,6 +26,7 @@ var Syms struct { GCWriteBarrier *obj.LSym Goschedguarded *obj.LSym Growslice *obj.LSym + Memmove *obj.LSym Msanread *obj.LSym Msanwrite *obj.LSym Msanmove *obj.LSym diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index b36db67a507a87f8cd6bd0a56791b4f34399cedc..17ec87788a61dcb4f8b9b7a9709e472bbdb14dc0 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -323,7 +323,9 @@ func (p *noder) processPragmas() { } n := ir.AsNode(typecheck.Lookup(l.local).Def) if n == nil || n.Op() != ir.ONAME { - p.errorAt(l.pos, "//go:linkname must refer to declared function or variable") + if types.AllowsGoVersion(types.LocalPkg, 1, 18) { + p.errorAt(l.pos, "//go:linkname must refer to declared function or variable") + } continue } if n.Sym().Linkname != "" { diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 58b7b9e8ddfaccce5d5dd05c45a934c26cf2d277..a41b35a0dd170daba127ef5a0abfc611459e1bd9 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1186,7 +1186,7 @@ func (subst *subster) node(n ir.Node) ir.Node { if m.Tag != nil && m.Tag.Op() == ir.OTYPESW { break // Nothing to do here for type switches. } - if m.Tag != nil && !m.Tag.Type().IsInterface() && m.Tag.Type().HasShape() { + if m.Tag != nil && !m.Tag.Type().IsEmptyInterface() && m.Tag.Type().HasShape() { // To implement a switch on a value that is or has a type parameter, we first convert // that thing we're switching on to an interface{}. m.Tag = assignconvfn(m.Tag, types.Types[types.TINTER]) @@ -1195,7 +1195,7 @@ func (subst *subster) node(n ir.Node) ir.Node { for i, x := range c.List { // If we have a case that is or has a type parameter, convert that case // to an interface{}. - if !x.Type().IsInterface() && x.Type().HasShape() { + if !x.Type().IsEmptyInterface() && x.Type().HasShape() { c.List[i] = assignconvfn(x, types.Types[types.TINTER]) } } @@ -1599,12 +1599,14 @@ func (g *genInst) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool se := call.X.(*ir.SelectorExpr) if se.X.Type().IsShape() { // This is a method call enabled by a type bound. - - // We need this extra check for method expressions, - // which don't add in the implicit XDOTs. - tmpse := ir.NewSelectorExpr(src.NoXPos, ir.OXDOT, se.X, se.Sel) - tmpse = typecheck.AddImplicitDots(tmpse) - tparam := tmpse.X.Type() + tparam := se.X.Type() + if call.X.Op() == ir.ODOTMETH { + // We need this extra check for method expressions, + // which don't add in the implicit XDOTs. + tmpse := ir.NewSelectorExpr(src.NoXPos, ir.OXDOT, se.X, se.Sel) + tmpse = typecheck.AddImplicitDots(tmpse) + tparam = tmpse.X.Type() + } if !tparam.IsShape() { // The method expression is not // really on a typeparam. diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index aec7358c32263b37a0845c06bc599833156b5b78..4ee9830db38317ec6f3c8bc807ace8c24ed6a60b 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1878,14 +1878,14 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy // the TOC to the appropriate value for that module. But if it returns // directly to the wrapper's caller, nothing will reset it to the correct // value for that function. + var call *ir.CallExpr if !base.Flag.Cfg.Instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) && !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) && !generic { - call := ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil) + call = ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil) call.Args = ir.ParamNames(tfn.Type()) call.IsDDD = tfn.Type().IsVariadic() fn.Body.Append(ir.NewTailCallStmt(base.Pos, call)) } else { fn.SetWrapper(true) // ignore frame for panic+recover matching - var call *ir.CallExpr if generic && dot.X != nthis { // If there is embedding involved, then we should do the @@ -1970,7 +1970,22 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy typecheck.Stmts(fn.Body) if AfterGlobalEscapeAnalysis { - inline.InlineCalls(fn) + // Inlining the method may reveal closures, which require walking all function bodies + // to decide whether to capture free variables by value or by ref. So we only do inline + // if the method do not contain any closures, otherwise, the escape analysis may make + // dead variables resurrected, and causing liveness analysis confused, see issue #53702. + var canInline bool + switch x := call.X.(type) { + case *ir.Name: + canInline = len(x.Func.Closures) == 0 + case *ir.SelectorExpr: + if x.Op() == ir.OMETHEXPR { + canInline = x.FuncName().Func != nil && len(x.FuncName().Func.Closures) == 0 + } + } + if canInline { + inline.InlineCalls(fn) + } escape.Batch([]*ir.Func{fn}, false) } diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index be8be4ebe3215dddbf266b4536c0e235e4a18c09..ad999600789cfd717c25d9c2c7309f23fd9acd9d 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -316,9 +316,9 @@ (FCMPD x (FMOVDconst [0])) => (FCMPD0 x) (FCMPD (FMOVDconst [0]) x) => (InvertFlags (FCMPD0 x)) -// CSEL needs a flag-generating argument. Synthesize a CMPW if necessary. +// CSEL needs a flag-generating argument. Synthesize a TSTW if necessary. (CondSelect x y boolval) && flagArg(boolval) != nil => (CSEL [boolval.Op] x y flagArg(boolval)) -(CondSelect x y boolval) && flagArg(boolval) == nil => (CSEL [OpARM64NotEqual] x y (CMPWconst [0] boolval)) +(CondSelect x y boolval) && flagArg(boolval) == nil => (CSEL [OpARM64NotEqual] x y (TSTWconst [1] boolval)) (OffPtr [off] ptr:(SP)) && is32Bit(off) => (MOVDaddr [int32(off)] ptr) (OffPtr [off] ptr) => (ADDconst [off] ptr) @@ -532,7 +532,7 @@ (If (GreaterThanF cc) yes no) => (FGT cc yes no) (If (GreaterEqualF cc) yes no) => (FGE cc yes no) -(If cond yes no) => (NZ cond yes no) +(If cond yes no) => (TBNZ [0] cond yes no) // atomic intrinsics // Note: these ops do not accept offset. @@ -593,6 +593,21 @@ (NZ (GreaterThanF cc) yes no) => (FGT cc yes no) (NZ (GreaterEqualF cc) yes no) => (FGE cc yes no) +(TBNZ [0] (Equal cc) yes no) => (EQ cc yes no) +(TBNZ [0] (NotEqual cc) yes no) => (NE cc yes no) +(TBNZ [0] (LessThan cc) yes no) => (LT cc yes no) +(TBNZ [0] (LessThanU cc) yes no) => (ULT cc yes no) +(TBNZ [0] (LessEqual cc) yes no) => (LE cc yes no) +(TBNZ [0] (LessEqualU cc) yes no) => (ULE cc yes no) +(TBNZ [0] (GreaterThan cc) yes no) => (GT cc yes no) +(TBNZ [0] (GreaterThanU cc) yes no) => (UGT cc yes no) +(TBNZ [0] (GreaterEqual cc) yes no) => (GE cc yes no) +(TBNZ [0] (GreaterEqualU cc) yes no) => (UGE cc yes no) +(TBNZ [0] (LessThanF cc) yes no) => (FLT cc yes no) +(TBNZ [0] (LessEqualF cc) yes no) => (FLE cc yes no) +(TBNZ [0] (GreaterThanF cc) yes no) => (FGT cc yes no) +(TBNZ [0] (GreaterEqualF cc) yes no) => (FGE cc yes no) + (EQ (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (EQ (TSTWconst [int32(c)] y) yes no) (NE (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (NE (TSTWconst [int32(c)] y) yes no) (LT (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 => (LT (TSTWconst [int32(c)] y) yes no) @@ -1563,9 +1578,9 @@ (GreaterThanF (InvertFlags x)) => (LessThanF x) (GreaterEqualF (InvertFlags x)) => (LessEqualF x) -// Boolean-generating instructions always +// Boolean-generating instructions (NOTE: NOT all boolean Values) always // zero upper bit of the register; no need to zero-extend -(MOVBUreg x) && x.Type.IsBoolean() => (MOVDreg x) +(MOVBUreg x:((Equal|NotEqual|LessThan|LessThanU|LessThanF|LessEqual|LessEqualU|LessEqualF|GreaterThan|GreaterThanU|GreaterThanF|GreaterEqual|GreaterEqualU|GreaterEqualF) _)) => (MOVDreg x) // absorb flag constants into conditional instructions (CSEL [cc] x _ flag) && ccARM64Eval(cc, flag) > 0 => x diff --git a/src/cmd/compile/internal/ssa/gen/MIPS64.rules b/src/cmd/compile/internal/ssa/gen/MIPS64.rules index 292ff2fc7966092fac267f78a39a1d939e221c12..0d6d30fa4c93c9eeeaffca21574a12a1b6fcb335 100644 --- a/src/cmd/compile/internal/ssa/gen/MIPS64.rules +++ b/src/cmd/compile/internal/ssa/gen/MIPS64.rules @@ -392,7 +392,8 @@ (AtomicAdd(32|64) ...) => (LoweredAtomicAdd(32|64) ...) -(AtomicCompareAndSwap(32|64) ...) => (LoweredAtomicCas(32|64) ...) +(AtomicCompareAndSwap32 ptr old new mem) => (LoweredAtomicCas32 ptr (SignExt32to64 old) new mem) +(AtomicCompareAndSwap64 ...) => (LoweredAtomicCas64 ...) // checks (NilCheck ...) => (LoweredNilCheck ...) diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules index c3f07a4e22cf3929a4af63e5a7482d70d7aafa60..f83ed78bab3a210c6f7769f09e5e2578ab7a98ce 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64.rules +++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules @@ -445,19 +445,19 @@ (If (FGreaterThan cc) yes no) => (FGT cc yes no) (If (FGreaterEqual cc) yes no) => (FGE cc yes no) -(If cond yes no) => (NE (CMPWconst [0] cond) yes no) +(If cond yes no) => (NE (CMPWconst [0] (ANDconst <typ.UInt32> [1] cond)) yes no) // Absorb boolean tests into block -(NE (CMPWconst [0] (Equal cc)) yes no) => (EQ cc yes no) -(NE (CMPWconst [0] (NotEqual cc)) yes no) => (NE cc yes no) -(NE (CMPWconst [0] (LessThan cc)) yes no) => (LT cc yes no) -(NE (CMPWconst [0] (LessEqual cc)) yes no) => (LE cc yes no) -(NE (CMPWconst [0] (GreaterThan cc)) yes no) => (GT cc yes no) -(NE (CMPWconst [0] (GreaterEqual cc)) yes no) => (GE cc yes no) -(NE (CMPWconst [0] (FLessThan cc)) yes no) => (FLT cc yes no) -(NE (CMPWconst [0] (FLessEqual cc)) yes no) => (FLE cc yes no) -(NE (CMPWconst [0] (FGreaterThan cc)) yes no) => (FGT cc yes no) -(NE (CMPWconst [0] (FGreaterEqual cc)) yes no) => (FGE cc yes no) +(NE (CMPWconst [0] (ANDconst [1] (Equal cc))) yes no) => (EQ cc yes no) +(NE (CMPWconst [0] (ANDconst [1] (NotEqual cc))) yes no) => (NE cc yes no) +(NE (CMPWconst [0] (ANDconst [1] (LessThan cc))) yes no) => (LT cc yes no) +(NE (CMPWconst [0] (ANDconst [1] (LessEqual cc))) yes no) => (LE cc yes no) +(NE (CMPWconst [0] (ANDconst [1] (GreaterThan cc))) yes no) => (GT cc yes no) +(NE (CMPWconst [0] (ANDconst [1] (GreaterEqual cc))) yes no) => (GE cc yes no) +(NE (CMPWconst [0] (ANDconst [1] (FLessThan cc))) yes no) => (FLT cc yes no) +(NE (CMPWconst [0] (ANDconst [1] (FLessEqual cc))) yes no) => (FLE cc yes no) +(NE (CMPWconst [0] (ANDconst [1] (FGreaterThan cc))) yes no) => (FGT cc yes no) +(NE (CMPWconst [0] (ANDconst [1] (FGreaterEqual cc))) yes no) => (FGE cc yes no) // Elide compares of bit tests // TODO need to make both CC and result of ANDCC available. (EQ (CMPconst [0] (ANDconst [c] x)) yes no) => (EQ (ANDCCconst [c] x) yes no) @@ -562,9 +562,9 @@ ((EQ|NE|LT|LE|GT|GE) (CMPconst [0] z:(XOR x y)) yes no) && z.Uses == 1 => ((EQ|NE|LT|LE|GT|GE) (XORCC x y) yes no) // Only lower after bool is lowered. It should always lower. This helps ensure the folding below happens reliably. -(CondSelect x y bool) && flagArg(bool) == nil => (ISEL [6] x y (CMPWconst [0] bool)) +(CondSelect x y bool) && flagArg(bool) == nil => (ISEL [6] x y (Select1 <types.TypeFlags> (ANDCCconst [1] bool))) // Fold any CR -> GPR -> CR transfers when applying the above rule. -(ISEL [6] x y (CMPWconst [0] (ISELB [c] one cmp))) => (ISEL [c] x y cmp) +(ISEL [6] x y (Select1 (ANDCCconst [1] (ISELB [c] one cmp)))) => (ISEL [c] x y cmp) // Lowering loads (Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) => (MOVDload ptr mem) diff --git a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go index 59d8af1a9d3952fb1bfeee88af01200fc618cf6a..d18cbcc787140fdb9c7940da8e684e720e263239 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/PPC64Ops.go @@ -11,8 +11,8 @@ import "strings" // Notes: // - Less-than-64-bit integer types live in the low portion of registers. -// For now, the upper portion is junk; sign/zero-extension might be optimized in the future, but not yet. -// - Boolean types are zero or 1; stored in a byte, but loaded with AMOVBZ so the upper bytes of a register are zero. +// The upper portion is junk. +// - Boolean types are zero or 1; stored in a byte, with upper bytes of the register containing junk. // - *const instructions may use a constant larger than the instruction can encode. // In this case the assembler expands to multiple instructions and uses tmp // register (R31). diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules index 96b24a63808c668c583a012501e1b5fd47e58cc0..acef3df3893b9a48eb9ff5bb5819217ed272f41b 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/gen/RISCV64.rules @@ -568,7 +568,7 @@ (AtomicAnd32 ...) => (LoweredAtomicAnd32 ...) -(AtomicCompareAndSwap32 ...) => (LoweredAtomicCas32 ...) +(AtomicCompareAndSwap32 ptr old new mem) => (LoweredAtomicCas32 ptr (SignExt32to64 old) new mem) (AtomicCompareAndSwap64 ...) => (LoweredAtomicCas64 ...) (AtomicExchange32 ...) => (LoweredAtomicExchange32 ...) @@ -583,7 +583,7 @@ (AtomicOr32 ...) => (LoweredAtomicOr32 ...) // Conditional branches -(If cond yes no) => (BNEZ cond yes no) +(If cond yes no) => (BNEZ (MOVBUreg <typ.UInt64> cond) yes no) // Optimizations @@ -621,6 +621,10 @@ (MOVWstore [off] {sym} ptr (MOVDconst [0]) mem) => (MOVWstorezero [off] {sym} ptr mem) (MOVDstore [off] {sym} ptr (MOVDconst [0]) mem) => (MOVDstorezero [off] {sym} ptr mem) +// Boolean ops are already extended. +(MOVBUreg x:((SEQZ|SNEZ) _)) => x +(MOVBUreg x:((SLT|SLTU) _ _)) => x + // Avoid sign/zero extension for consts. (MOVBreg (MOVDconst [c])) => (MOVDconst [int64(int8(c))]) (MOVHreg (MOVDconst [c])) => (MOVDconst [int64(int16(c))]) diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 6dbe9b47d011fabd3c83e493b126a981efa45191..b78d2aac3c037ca4f795b7909f47f0b76c8127e8 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -2082,7 +2082,13 @@ // Inline small or disjoint runtime.memmove calls with constant length. // See the comment in op Move in genericOps.go for discussion of the type. - +// +// Note that we've lost any knowledge of the type and alignment requirements +// of the source and destination. We only know the size, and that the type +// contains no pointers. +// The type of the move is not necessarily v.Args[0].Type().Elem()! +// See issue 55122 for details. +// // Because expand calls runs after prove, constants useful to this pattern may not appear. // Both versions need to exist; the memory and register variants. // @@ -2090,31 +2096,28 @@ (SelectN [0] call:(StaticCall {sym} s1:(Store _ (Const(64|32) [sz]) s2:(Store _ src s3:(Store {t} _ dst mem))))) && sz >= 0 && isSameCall(sym, "runtime.memmove") - && t.IsPtr() // avoids TUNSAFEPTR, see issue 30061 && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call) - => (Move {t.Elem()} [int64(sz)] dst src mem) + => (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem) // Match post-expansion calls, register version. (SelectN [0] call:(StaticCall {sym} dst src (Const(64|32) [sz]) mem)) && sz >= 0 && call.Uses == 1 // this will exclude all calls with results && isSameCall(sym, "runtime.memmove") - && dst.Type.IsPtr() // avoids TUNSAFEPTR, see issue 30061 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call) - => (Move {dst.Type.Elem()} [int64(sz)] dst src mem) + => (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem) // Match pre-expansion calls. (SelectN [0] call:(StaticLECall {sym} dst src (Const(64|32) [sz]) mem)) && sz >= 0 && call.Uses == 1 // this will exclude all calls with results && isSameCall(sym, "runtime.memmove") - && dst.Type.IsPtr() // avoids TUNSAFEPTR, see issue 30061 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call) - => (Move {dst.Type.Elem()} [int64(sz)] dst src mem) + => (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem) // De-virtualize late-expanded interface calls into late-expanded static calls. // Note that (ITab (IMake)) doesn't get rewritten until after the first opt pass, diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 4f133b1ff6a1b85de79dec35a4360d9cb2d2a231..69cd828c09dd52eb28c2b5c799f162c8d1aec22d 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -355,7 +355,9 @@ var genericOps = []opData{ {name: "Load", argLength: 2}, // Load from arg0. arg1=memory {name: "Dereference", argLength: 2}, // Load from arg0. arg1=memory. Helper op for arg/result passing, result is an otherwise not-SSA-able "value". {name: "Store", argLength: 3, typ: "Mem", aux: "Typ"}, // Store arg1 to arg0. arg2=memory, aux=type. Returns memory. - // The source and destination of Move may overlap in some cases. See e.g. + // Normally we require that the source and destination of Move do not overlap. + // There is an exception when we know all the loads will happen before all + // the stores. In that case, overlap is ok. See // memmove inlining in generic.rules. When inlineablememmovesize (in ../rewrite.go) // returns true, we must do all loads before all stores, when lowering Move. // The type of Move is used for the write barrier pass to insert write barriers diff --git a/src/cmd/compile/internal/ssa/loopbce.go b/src/cmd/compile/internal/ssa/loopbce.go index 5a4bc1d60aa5e573ff27f510fe951d4f7468ef6d..fd03efb417db73d916657e1a2f58902e6e3c63c3 100644 --- a/src/cmd/compile/internal/ssa/loopbce.go +++ b/src/cmd/compile/internal/ssa/loopbce.go @@ -159,6 +159,13 @@ func findIndVar(f *Func) []indVar { step = -step } + if flags&indVarMaxInc != 0 && max.Op == OpConst64 && max.AuxInt+step < max.AuxInt { + // For a <= comparison, we need to make sure that a value equal to + // max can be incremented without overflowing. + // (For a < comparison, the %step check below ensures no overflow.) + continue + } + // Up to now we extracted the induction variable (ind), // the increment delta (inc), the temporary sum (nxt), // the mininum value (min) and the maximum value (max). diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index eb8fa0c02abe44f56be68f352d7ffe32a7f1e70f..70cd4c54cb67460c551afa1c3034d79eb85ae048 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -1358,7 +1358,8 @@ func zeroUpper56Bits(x *Value, depth int) bool { // isInlinableMemmove reports whether the given arch performs a Move of the given size // faster than memmove. It will only return true if replacing the memmove with a Move is -// safe, either because Move is small or because the arguments are disjoint. +// safe, either because Move will do all of its loads before any of its stores, or +// because the arguments are known to be disjoint. // This is used as a check for replacing memmove with Move ops. func isInlinableMemmove(dst, src *Value, sz int64, c *Config) bool { // It is always safe to convert memmove into Move when its arguments are disjoint. @@ -1377,6 +1378,9 @@ func isInlinableMemmove(dst, src *Value, sz int64, c *Config) bool { } return false } +func IsInlinableMemmove(dst, src *Value, sz int64, c *Config) bool { + return isInlinableMemmove(dst, src, sz, c) +} // logLargeCopy logs the occurrence of a large copy. // The best place to do this is in the rewrite rules where the size of the move is easy to find. @@ -1390,6 +1394,14 @@ func logLargeCopy(v *Value, s int64) bool { } return true } +func LogLargeCopy(funcName string, pos src.XPos, s int64) { + if s < 128 { + return + } + if logopt.Enabled() { + logopt.LogOpt(pos, "copy", "lower", funcName, fmt.Sprintf("%d bytes", s)) + } +} // hasSmallRotate reports whether the architecture has rotate instructions // for sizes < 32-bit. This is used to decide whether to promote some rotations. diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index c5f53e55072efd3df5d33a865c2c39275d798390..ad1052f88d7f65726dc69c12dbb56af061395072 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -7321,12 +7321,154 @@ func rewriteValueARM64_OpARM64MOVBUreg(v *Value) bool { v.AuxInt = int64ToAuxInt(int64(uint8(c))) return true } - // match: (MOVBUreg x) - // cond: x.Type.IsBoolean() + // match: (MOVBUreg x:(Equal _)) // result: (MOVDreg x) for { x := v_0 - if !(x.Type.IsBoolean()) { + if x.Op != OpARM64Equal { + break + } + v.reset(OpARM64MOVDreg) + v.AddArg(x) + return true + } + // match: (MOVBUreg x:(NotEqual _)) + // result: (MOVDreg x) + for { + x := v_0 + if x.Op != OpARM64NotEqual { + break + } + v.reset(OpARM64MOVDreg) + v.AddArg(x) + return true + } + // match: (MOVBUreg x:(LessThan _)) + // result: (MOVDreg x) + for { + x := v_0 + if x.Op != OpARM64LessThan { + break + } + v.reset(OpARM64MOVDreg) + v.AddArg(x) + return true + } + // match: (MOVBUreg x:(LessThanU _)) + // result: (MOVDreg x) + for { + x := v_0 + if x.Op != OpARM64LessThanU { + break + } + v.reset(OpARM64MOVDreg) + v.AddArg(x) + return true + } + // match: (MOVBUreg x:(LessThanF _)) + // result: (MOVDreg x) + for { + x := v_0 + if x.Op != OpARM64LessThanF { + break + } + v.reset(OpARM64MOVDreg) + v.AddArg(x) + return true + } + // match: (MOVBUreg x:(LessEqual _)) + // result: (MOVDreg x) + for { + x := v_0 + if x.Op != OpARM64LessEqual { + break + } + v.reset(OpARM64MOVDreg) + v.AddArg(x) + return true + } + // match: (MOVBUreg x:(LessEqualU _)) + // result: (MOVDreg x) + for { + x := v_0 + if x.Op != OpARM64LessEqualU { + break + } + v.reset(OpARM64MOVDreg) + v.AddArg(x) + return true + } + // match: (MOVBUreg x:(LessEqualF _)) + // result: (MOVDreg x) + for { + x := v_0 + if x.Op != OpARM64LessEqualF { + break + } + v.reset(OpARM64MOVDreg) + v.AddArg(x) + return true + } + // match: (MOVBUreg x:(GreaterThan _)) + // result: (MOVDreg x) + for { + x := v_0 + if x.Op != OpARM64GreaterThan { + break + } + v.reset(OpARM64MOVDreg) + v.AddArg(x) + return true + } + // match: (MOVBUreg x:(GreaterThanU _)) + // result: (MOVDreg x) + for { + x := v_0 + if x.Op != OpARM64GreaterThanU { + break + } + v.reset(OpARM64MOVDreg) + v.AddArg(x) + return true + } + // match: (MOVBUreg x:(GreaterThanF _)) + // result: (MOVDreg x) + for { + x := v_0 + if x.Op != OpARM64GreaterThanF { + break + } + v.reset(OpARM64MOVDreg) + v.AddArg(x) + return true + } + // match: (MOVBUreg x:(GreaterEqual _)) + // result: (MOVDreg x) + for { + x := v_0 + if x.Op != OpARM64GreaterEqual { + break + } + v.reset(OpARM64MOVDreg) + v.AddArg(x) + return true + } + // match: (MOVBUreg x:(GreaterEqualU _)) + // result: (MOVDreg x) + for { + x := v_0 + if x.Op != OpARM64GreaterEqualU { + break + } + v.reset(OpARM64MOVDreg) + v.AddArg(x) + return true + } + // match: (MOVBUreg x:(GreaterEqualF _)) + // result: (MOVDreg x) + for { + x := v_0 + if x.Op != OpARM64GreaterEqualF { break } v.reset(OpARM64MOVDreg) @@ -23267,7 +23409,7 @@ func rewriteValueARM64_OpCondSelect(v *Value) bool { } // match: (CondSelect x y boolval) // cond: flagArg(boolval) == nil - // result: (CSEL [OpARM64NotEqual] x y (CMPWconst [0] boolval)) + // result: (CSEL [OpARM64NotEqual] x y (TSTWconst [1] boolval)) for { x := v_0 y := v_1 @@ -23277,8 +23419,8 @@ func rewriteValueARM64_OpCondSelect(v *Value) bool { } v.reset(OpARM64CSEL) v.AuxInt = opToAuxInt(OpARM64NotEqual) - v0 := b.NewValue0(v.Pos, OpARM64CMPWconst, types.TypeFlags) - v0.AuxInt = int32ToAuxInt(0) + v0 := b.NewValue0(v.Pos, OpARM64TSTWconst, types.TypeFlags) + v0.AuxInt = int32ToAuxInt(1) v0.AddArg(boolval) v.AddArg3(x, y, v0) return true @@ -28660,10 +28802,11 @@ func rewriteBlockARM64(b *Block) bool { return true } // match: (If cond yes no) - // result: (NZ cond yes no) + // result: (TBNZ [0] cond yes no) for { cond := b.Controls[0] - b.resetWithControl(BlockARM64NZ, cond) + b.resetWithControl(BlockARM64TBNZ, cond) + b.AuxInt = int64ToAuxInt(0) return true } case BlockARM64LE: @@ -30052,6 +30195,161 @@ func rewriteBlockARM64(b *Block) bool { b.Reset(BlockFirst) return true } + case BlockARM64TBNZ: + // match: (TBNZ [0] (Equal cc) yes no) + // result: (EQ cc yes no) + for b.Controls[0].Op == OpARM64Equal { + v_0 := b.Controls[0] + cc := v_0.Args[0] + if auxIntToInt64(b.AuxInt) != 0 { + break + } + b.resetWithControl(BlockARM64EQ, cc) + return true + } + // match: (TBNZ [0] (NotEqual cc) yes no) + // result: (NE cc yes no) + for b.Controls[0].Op == OpARM64NotEqual { + v_0 := b.Controls[0] + cc := v_0.Args[0] + if auxIntToInt64(b.AuxInt) != 0 { + break + } + b.resetWithControl(BlockARM64NE, cc) + return true + } + // match: (TBNZ [0] (LessThan cc) yes no) + // result: (LT cc yes no) + for b.Controls[0].Op == OpARM64LessThan { + v_0 := b.Controls[0] + cc := v_0.Args[0] + if auxIntToInt64(b.AuxInt) != 0 { + break + } + b.resetWithControl(BlockARM64LT, cc) + return true + } + // match: (TBNZ [0] (LessThanU cc) yes no) + // result: (ULT cc yes no) + for b.Controls[0].Op == OpARM64LessThanU { + v_0 := b.Controls[0] + cc := v_0.Args[0] + if auxIntToInt64(b.AuxInt) != 0 { + break + } + b.resetWithControl(BlockARM64ULT, cc) + return true + } + // match: (TBNZ [0] (LessEqual cc) yes no) + // result: (LE cc yes no) + for b.Controls[0].Op == OpARM64LessEqual { + v_0 := b.Controls[0] + cc := v_0.Args[0] + if auxIntToInt64(b.AuxInt) != 0 { + break + } + b.resetWithControl(BlockARM64LE, cc) + return true + } + // match: (TBNZ [0] (LessEqualU cc) yes no) + // result: (ULE cc yes no) + for b.Controls[0].Op == OpARM64LessEqualU { + v_0 := b.Controls[0] + cc := v_0.Args[0] + if auxIntToInt64(b.AuxInt) != 0 { + break + } + b.resetWithControl(BlockARM64ULE, cc) + return true + } + // match: (TBNZ [0] (GreaterThan cc) yes no) + // result: (GT cc yes no) + for b.Controls[0].Op == OpARM64GreaterThan { + v_0 := b.Controls[0] + cc := v_0.Args[0] + if auxIntToInt64(b.AuxInt) != 0 { + break + } + b.resetWithControl(BlockARM64GT, cc) + return true + } + // match: (TBNZ [0] (GreaterThanU cc) yes no) + // result: (UGT cc yes no) + for b.Controls[0].Op == OpARM64GreaterThanU { + v_0 := b.Controls[0] + cc := v_0.Args[0] + if auxIntToInt64(b.AuxInt) != 0 { + break + } + b.resetWithControl(BlockARM64UGT, cc) + return true + } + // match: (TBNZ [0] (GreaterEqual cc) yes no) + // result: (GE cc yes no) + for b.Controls[0].Op == OpARM64GreaterEqual { + v_0 := b.Controls[0] + cc := v_0.Args[0] + if auxIntToInt64(b.AuxInt) != 0 { + break + } + b.resetWithControl(BlockARM64GE, cc) + return true + } + // match: (TBNZ [0] (GreaterEqualU cc) yes no) + // result: (UGE cc yes no) + for b.Controls[0].Op == OpARM64GreaterEqualU { + v_0 := b.Controls[0] + cc := v_0.Args[0] + if auxIntToInt64(b.AuxInt) != 0 { + break + } + b.resetWithControl(BlockARM64UGE, cc) + return true + } + // match: (TBNZ [0] (LessThanF cc) yes no) + // result: (FLT cc yes no) + for b.Controls[0].Op == OpARM64LessThanF { + v_0 := b.Controls[0] + cc := v_0.Args[0] + if auxIntToInt64(b.AuxInt) != 0 { + break + } + b.resetWithControl(BlockARM64FLT, cc) + return true + } + // match: (TBNZ [0] (LessEqualF cc) yes no) + // result: (FLE cc yes no) + for b.Controls[0].Op == OpARM64LessEqualF { + v_0 := b.Controls[0] + cc := v_0.Args[0] + if auxIntToInt64(b.AuxInt) != 0 { + break + } + b.resetWithControl(BlockARM64FLE, cc) + return true + } + // match: (TBNZ [0] (GreaterThanF cc) yes no) + // result: (FGT cc yes no) + for b.Controls[0].Op == OpARM64GreaterThanF { + v_0 := b.Controls[0] + cc := v_0.Args[0] + if auxIntToInt64(b.AuxInt) != 0 { + break + } + b.resetWithControl(BlockARM64FGT, cc) + return true + } + // match: (TBNZ [0] (GreaterEqualF cc) yes no) + // result: (FGE cc yes no) + for b.Controls[0].Op == OpARM64GreaterEqualF { + v_0 := b.Controls[0] + cc := v_0.Args[0] + if auxIntToInt64(b.AuxInt) != 0 { + break + } + b.resetWithControl(BlockARM64FGE, cc) + return true + } case BlockARM64UGE: // match: (UGE (FlagConstant [fc]) yes no) // cond: fc.uge() diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS64.go b/src/cmd/compile/internal/ssa/rewriteMIPS64.go index 1fbd556b5cbcd7d32cb9ad6424d5c5d2a14580e7..6a0fd3ad6ee20352bb2eb4b72fc125de7cc8646c 100644 --- a/src/cmd/compile/internal/ssa/rewriteMIPS64.go +++ b/src/cmd/compile/internal/ssa/rewriteMIPS64.go @@ -52,8 +52,7 @@ func rewriteValueMIPS64(v *Value) bool { v.Op = OpMIPS64LoweredAtomicAdd64 return true case OpAtomicCompareAndSwap32: - v.Op = OpMIPS64LoweredAtomicCas32 - return true + return rewriteValueMIPS64_OpAtomicCompareAndSwap32(v) case OpAtomicCompareAndSwap64: v.Op = OpMIPS64LoweredAtomicCas64 return true @@ -697,6 +696,27 @@ func rewriteValueMIPS64_OpAddr(v *Value) bool { return true } } +func rewriteValueMIPS64_OpAtomicCompareAndSwap32(v *Value) bool { + v_3 := v.Args[3] + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + typ := &b.Func.Config.Types + // match: (AtomicCompareAndSwap32 ptr old new mem) + // result: (LoweredAtomicCas32 ptr (SignExt32to64 old) new mem) + for { + ptr := v_0 + old := v_1 + new := v_2 + mem := v_3 + v.reset(OpMIPS64LoweredAtomicCas32) + v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64) + v0.AddArg(old) + v.AddArg4(ptr, v0, new, mem) + return true + } +} func rewriteValueMIPS64_OpAvg64u(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go index 7592b4f50582405812ba82999ed599e8e3a43cce..c7bcc248fc3984fd91d85ff489b7cffeddec2a96 100644 --- a/src/cmd/compile/internal/ssa/rewritePPC64.go +++ b/src/cmd/compile/internal/ssa/rewritePPC64.go @@ -1167,9 +1167,10 @@ func rewriteValuePPC64_OpCondSelect(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] b := v.Block + typ := &b.Func.Config.Types // match: (CondSelect x y bool) // cond: flagArg(bool) == nil - // result: (ISEL [6] x y (CMPWconst [0] bool)) + // result: (ISEL [6] x y (Select1 <types.TypeFlags> (ANDCCconst [1] bool))) for { x := v_0 y := v_1 @@ -1179,9 +1180,11 @@ func rewriteValuePPC64_OpCondSelect(v *Value) bool { } v.reset(OpPPC64ISEL) v.AuxInt = int32ToAuxInt(6) - v0 := b.NewValue0(v.Pos, OpPPC64CMPWconst, types.TypeFlags) - v0.AuxInt = int32ToAuxInt(0) - v0.AddArg(bool) + v0 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags) + v1 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.NewTuple(typ.Int, types.TypeFlags)) + v1.AuxInt = int64ToAuxInt(1) + v1.AddArg(bool) + v0.AddArg(v1) v.AddArg3(x, y, v0) return true } @@ -5895,7 +5898,7 @@ func rewriteValuePPC64_OpPPC64ISEL(v *Value) bool { v.AddArg(y) return true } - // match: (ISEL [6] x y (CMPWconst [0] (ISELB [c] one cmp))) + // match: (ISEL [6] x y (Select1 (ANDCCconst [1] (ISELB [c] one cmp)))) // result: (ISEL [c] x y cmp) for { if auxIntToInt32(v.AuxInt) != 6 { @@ -5903,15 +5906,19 @@ func rewriteValuePPC64_OpPPC64ISEL(v *Value) bool { } x := v_0 y := v_1 - if v_2.Op != OpPPC64CMPWconst || auxIntToInt32(v_2.AuxInt) != 0 { + if v_2.Op != OpSelect1 { break } v_2_0 := v_2.Args[0] - if v_2_0.Op != OpPPC64ISELB { + if v_2_0.Op != OpPPC64ANDCCconst || auxIntToInt64(v_2_0.AuxInt) != 1 { break } - c := auxIntToInt32(v_2_0.AuxInt) - cmp := v_2_0.Args[1] + v_2_0_0 := v_2_0.Args[0] + if v_2_0_0.Op != OpPPC64ISELB { + break + } + c := auxIntToInt32(v_2_0_0.AuxInt) + cmp := v_2_0_0.Args[1] v.reset(OpPPC64ISEL) v.AuxInt = int32ToAuxInt(c) v.AddArg3(x, y, cmp) @@ -17194,6 +17201,7 @@ func rewriteValuePPC64_OpZero(v *Value) bool { return false } func rewriteBlockPPC64(b *Block) bool { + typ := &b.Func.Config.Types switch b.Kind { case BlockPPC64EQ: // match: (EQ (CMPconst [0] (ANDconst [c] x)) yes no) @@ -17767,12 +17775,15 @@ func rewriteBlockPPC64(b *Block) bool { return true } // match: (If cond yes no) - // result: (NE (CMPWconst [0] cond) yes no) + // result: (NE (CMPWconst [0] (ANDconst <typ.UInt32> [1] cond)) yes no) for { cond := b.Controls[0] v0 := b.NewValue0(cond.Pos, OpPPC64CMPWconst, types.TypeFlags) v0.AuxInt = int32ToAuxInt(0) - v0.AddArg(cond) + v1 := b.NewValue0(cond.Pos, OpPPC64ANDconst, typ.UInt32) + v1.AuxInt = int64ToAuxInt(1) + v1.AddArg(cond) + v0.AddArg(v1) b.resetWithControl(BlockPPC64NE, v0) return true } @@ -18078,7 +18089,7 @@ func rewriteBlockPPC64(b *Block) bool { break } case BlockPPC64NE: - // match: (NE (CMPWconst [0] (Equal cc)) yes no) + // match: (NE (CMPWconst [0] (ANDconst [1] (Equal cc))) yes no) // result: (EQ cc yes no) for b.Controls[0].Op == OpPPC64CMPWconst { v_0 := b.Controls[0] @@ -18086,14 +18097,18 @@ func rewriteBlockPPC64(b *Block) bool { break } v_0_0 := v_0.Args[0] - if v_0_0.Op != OpPPC64Equal { + if v_0_0.Op != OpPPC64ANDconst || auxIntToInt64(v_0_0.AuxInt) != 1 { + break + } + v_0_0_0 := v_0_0.Args[0] + if v_0_0_0.Op != OpPPC64Equal { break } - cc := v_0_0.Args[0] + cc := v_0_0_0.Args[0] b.resetWithControl(BlockPPC64EQ, cc) return true } - // match: (NE (CMPWconst [0] (NotEqual cc)) yes no) + // match: (NE (CMPWconst [0] (ANDconst [1] (NotEqual cc))) yes no) // result: (NE cc yes no) for b.Controls[0].Op == OpPPC64CMPWconst { v_0 := b.Controls[0] @@ -18101,14 +18116,18 @@ func rewriteBlockPPC64(b *Block) bool { break } v_0_0 := v_0.Args[0] - if v_0_0.Op != OpPPC64NotEqual { + if v_0_0.Op != OpPPC64ANDconst || auxIntToInt64(v_0_0.AuxInt) != 1 { break } - cc := v_0_0.Args[0] + v_0_0_0 := v_0_0.Args[0] + if v_0_0_0.Op != OpPPC64NotEqual { + break + } + cc := v_0_0_0.Args[0] b.resetWithControl(BlockPPC64NE, cc) return true } - // match: (NE (CMPWconst [0] (LessThan cc)) yes no) + // match: (NE (CMPWconst [0] (ANDconst [1] (LessThan cc))) yes no) // result: (LT cc yes no) for b.Controls[0].Op == OpPPC64CMPWconst { v_0 := b.Controls[0] @@ -18116,14 +18135,18 @@ func rewriteBlockPPC64(b *Block) bool { break } v_0_0 := v_0.Args[0] - if v_0_0.Op != OpPPC64LessThan { + if v_0_0.Op != OpPPC64ANDconst || auxIntToInt64(v_0_0.AuxInt) != 1 { + break + } + v_0_0_0 := v_0_0.Args[0] + if v_0_0_0.Op != OpPPC64LessThan { break } - cc := v_0_0.Args[0] + cc := v_0_0_0.Args[0] b.resetWithControl(BlockPPC64LT, cc) return true } - // match: (NE (CMPWconst [0] (LessEqual cc)) yes no) + // match: (NE (CMPWconst [0] (ANDconst [1] (LessEqual cc))) yes no) // result: (LE cc yes no) for b.Controls[0].Op == OpPPC64CMPWconst { v_0 := b.Controls[0] @@ -18131,14 +18154,18 @@ func rewriteBlockPPC64(b *Block) bool { break } v_0_0 := v_0.Args[0] - if v_0_0.Op != OpPPC64LessEqual { + if v_0_0.Op != OpPPC64ANDconst || auxIntToInt64(v_0_0.AuxInt) != 1 { break } - cc := v_0_0.Args[0] + v_0_0_0 := v_0_0.Args[0] + if v_0_0_0.Op != OpPPC64LessEqual { + break + } + cc := v_0_0_0.Args[0] b.resetWithControl(BlockPPC64LE, cc) return true } - // match: (NE (CMPWconst [0] (GreaterThan cc)) yes no) + // match: (NE (CMPWconst [0] (ANDconst [1] (GreaterThan cc))) yes no) // result: (GT cc yes no) for b.Controls[0].Op == OpPPC64CMPWconst { v_0 := b.Controls[0] @@ -18146,14 +18173,18 @@ func rewriteBlockPPC64(b *Block) bool { break } v_0_0 := v_0.Args[0] - if v_0_0.Op != OpPPC64GreaterThan { + if v_0_0.Op != OpPPC64ANDconst || auxIntToInt64(v_0_0.AuxInt) != 1 { + break + } + v_0_0_0 := v_0_0.Args[0] + if v_0_0_0.Op != OpPPC64GreaterThan { break } - cc := v_0_0.Args[0] + cc := v_0_0_0.Args[0] b.resetWithControl(BlockPPC64GT, cc) return true } - // match: (NE (CMPWconst [0] (GreaterEqual cc)) yes no) + // match: (NE (CMPWconst [0] (ANDconst [1] (GreaterEqual cc))) yes no) // result: (GE cc yes no) for b.Controls[0].Op == OpPPC64CMPWconst { v_0 := b.Controls[0] @@ -18161,14 +18192,18 @@ func rewriteBlockPPC64(b *Block) bool { break } v_0_0 := v_0.Args[0] - if v_0_0.Op != OpPPC64GreaterEqual { + if v_0_0.Op != OpPPC64ANDconst || auxIntToInt64(v_0_0.AuxInt) != 1 { break } - cc := v_0_0.Args[0] + v_0_0_0 := v_0_0.Args[0] + if v_0_0_0.Op != OpPPC64GreaterEqual { + break + } + cc := v_0_0_0.Args[0] b.resetWithControl(BlockPPC64GE, cc) return true } - // match: (NE (CMPWconst [0] (FLessThan cc)) yes no) + // match: (NE (CMPWconst [0] (ANDconst [1] (FLessThan cc))) yes no) // result: (FLT cc yes no) for b.Controls[0].Op == OpPPC64CMPWconst { v_0 := b.Controls[0] @@ -18176,14 +18211,18 @@ func rewriteBlockPPC64(b *Block) bool { break } v_0_0 := v_0.Args[0] - if v_0_0.Op != OpPPC64FLessThan { + if v_0_0.Op != OpPPC64ANDconst || auxIntToInt64(v_0_0.AuxInt) != 1 { + break + } + v_0_0_0 := v_0_0.Args[0] + if v_0_0_0.Op != OpPPC64FLessThan { break } - cc := v_0_0.Args[0] + cc := v_0_0_0.Args[0] b.resetWithControl(BlockPPC64FLT, cc) return true } - // match: (NE (CMPWconst [0] (FLessEqual cc)) yes no) + // match: (NE (CMPWconst [0] (ANDconst [1] (FLessEqual cc))) yes no) // result: (FLE cc yes no) for b.Controls[0].Op == OpPPC64CMPWconst { v_0 := b.Controls[0] @@ -18191,14 +18230,18 @@ func rewriteBlockPPC64(b *Block) bool { break } v_0_0 := v_0.Args[0] - if v_0_0.Op != OpPPC64FLessEqual { + if v_0_0.Op != OpPPC64ANDconst || auxIntToInt64(v_0_0.AuxInt) != 1 { + break + } + v_0_0_0 := v_0_0.Args[0] + if v_0_0_0.Op != OpPPC64FLessEqual { break } - cc := v_0_0.Args[0] + cc := v_0_0_0.Args[0] b.resetWithControl(BlockPPC64FLE, cc) return true } - // match: (NE (CMPWconst [0] (FGreaterThan cc)) yes no) + // match: (NE (CMPWconst [0] (ANDconst [1] (FGreaterThan cc))) yes no) // result: (FGT cc yes no) for b.Controls[0].Op == OpPPC64CMPWconst { v_0 := b.Controls[0] @@ -18206,14 +18249,18 @@ func rewriteBlockPPC64(b *Block) bool { break } v_0_0 := v_0.Args[0] - if v_0_0.Op != OpPPC64FGreaterThan { + if v_0_0.Op != OpPPC64ANDconst || auxIntToInt64(v_0_0.AuxInt) != 1 { break } - cc := v_0_0.Args[0] + v_0_0_0 := v_0_0.Args[0] + if v_0_0_0.Op != OpPPC64FGreaterThan { + break + } + cc := v_0_0_0.Args[0] b.resetWithControl(BlockPPC64FGT, cc) return true } - // match: (NE (CMPWconst [0] (FGreaterEqual cc)) yes no) + // match: (NE (CMPWconst [0] (ANDconst [1] (FGreaterEqual cc))) yes no) // result: (FGE cc yes no) for b.Controls[0].Op == OpPPC64CMPWconst { v_0 := b.Controls[0] @@ -18221,10 +18268,14 @@ func rewriteBlockPPC64(b *Block) bool { break } v_0_0 := v_0.Args[0] - if v_0_0.Op != OpPPC64FGreaterEqual { + if v_0_0.Op != OpPPC64ANDconst || auxIntToInt64(v_0_0.AuxInt) != 1 { + break + } + v_0_0_0 := v_0_0.Args[0] + if v_0_0_0.Op != OpPPC64FGreaterEqual { break } - cc := v_0_0.Args[0] + cc := v_0_0_0.Args[0] b.resetWithControl(BlockPPC64FGE, cc) return true } diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index a67d13e0da9236fe66dfea98aac714fead304e41..b277979061ecc8620b32de15b78e68b8dc6dfaf4 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -61,8 +61,7 @@ func rewriteValueRISCV64(v *Value) bool { case OpAtomicAnd8: return rewriteValueRISCV64_OpAtomicAnd8(v) case OpAtomicCompareAndSwap32: - v.Op = OpRISCV64LoweredAtomicCas32 - return true + return rewriteValueRISCV64_OpAtomicCompareAndSwap32(v) case OpAtomicCompareAndSwap64: v.Op = OpRISCV64LoweredAtomicCas64 return true @@ -765,6 +764,27 @@ func rewriteValueRISCV64_OpAtomicAnd8(v *Value) bool { return true } } +func rewriteValueRISCV64_OpAtomicCompareAndSwap32(v *Value) bool { + v_3 := v.Args[3] + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + typ := &b.Func.Config.Types + // match: (AtomicCompareAndSwap32 ptr old new mem) + // result: (LoweredAtomicCas32 ptr (SignExt32to64 old) new mem) + for { + ptr := v_0 + old := v_1 + new := v_2 + mem := v_3 + v.reset(OpRISCV64LoweredAtomicCas32) + v0 := b.NewValue0(v.Pos, OpSignExt32to64, typ.Int64) + v0.AddArg(old) + v.AddArg4(ptr, v0, new, mem) + return true + } +} func rewriteValueRISCV64_OpAtomicOr8(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -3152,6 +3172,46 @@ func rewriteValueRISCV64_OpRISCV64MOVBUload(v *Value) bool { func rewriteValueRISCV64_OpRISCV64MOVBUreg(v *Value) bool { v_0 := v.Args[0] b := v.Block + // match: (MOVBUreg x:(SEQZ _)) + // result: x + for { + x := v_0 + if x.Op != OpRISCV64SEQZ { + break + } + v.copyOf(x) + return true + } + // match: (MOVBUreg x:(SNEZ _)) + // result: x + for { + x := v_0 + if x.Op != OpRISCV64SNEZ { + break + } + v.copyOf(x) + return true + } + // match: (MOVBUreg x:(SLT _ _)) + // result: x + for { + x := v_0 + if x.Op != OpRISCV64SLT { + break + } + v.copyOf(x) + return true + } + // match: (MOVBUreg x:(SLTU _ _)) + // result: x + for { + x := v_0 + if x.Op != OpRISCV64SLTU { + break + } + v.copyOf(x) + return true + } // match: (MOVBUreg (MOVDconst [c])) // result: (MOVDconst [int64(uint8(c))]) for { @@ -6483,6 +6543,7 @@ func rewriteValueRISCV64_OpZero(v *Value) bool { } } func rewriteBlockRISCV64(b *Block) bool { + typ := &b.Func.Config.Types switch b.Kind { case BlockRISCV64BEQ: // match: (BEQ (MOVDconst [0]) cond yes no) @@ -6690,10 +6751,12 @@ func rewriteBlockRISCV64(b *Block) bool { } case BlockIf: // match: (If cond yes no) - // result: (BNEZ cond yes no) + // result: (BNEZ (MOVBUreg <typ.UInt64> cond) yes no) for { cond := b.Controls[0] - b.resetWithControl(BlockRISCV64BNEZ, cond) + v0 := b.NewValue0(cond.Pos, OpRISCV64MOVBUreg, typ.UInt64) + v0.AddArg(cond) + b.resetWithControl(BlockRISCV64BNEZ, v0) return true } } diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index fbf227562a92fc4e708aaa94746c6800d9a07918..434402b55ddf2f1d92ec459d829d159ca656fee6 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -21053,8 +21053,8 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool { return true } // match: (SelectN [0] call:(StaticCall {sym} s1:(Store _ (Const64 [sz]) s2:(Store _ src s3:(Store {t} _ dst mem))))) - // cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call) - // result: (Move {t.Elem()} [int64(sz)] dst src mem) + // cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call) + // result: (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem) for { if auxIntToInt64(v.AuxInt) != 0 { break @@ -21084,21 +21084,20 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool { if s3.Op != OpStore { break } - t := auxToType(s3.Aux) mem := s3.Args[2] dst := s3.Args[1] - if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call)) { + if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call)) { break } v.reset(OpMove) v.AuxInt = int64ToAuxInt(int64(sz)) - v.Aux = typeToAux(t.Elem()) + v.Aux = typeToAux(types.Types[types.TUINT8]) v.AddArg3(dst, src, mem) return true } // match: (SelectN [0] call:(StaticCall {sym} s1:(Store _ (Const32 [sz]) s2:(Store _ src s3:(Store {t} _ dst mem))))) - // cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call) - // result: (Move {t.Elem()} [int64(sz)] dst src mem) + // cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call) + // result: (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem) for { if auxIntToInt64(v.AuxInt) != 0 { break @@ -21128,21 +21127,20 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool { if s3.Op != OpStore { break } - t := auxToType(s3.Aux) mem := s3.Args[2] dst := s3.Args[1] - if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && t.IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call)) { + if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, int64(sz), config) && clobber(s1, s2, s3, call)) { break } v.reset(OpMove) v.AuxInt = int64ToAuxInt(int64(sz)) - v.Aux = typeToAux(t.Elem()) + v.Aux = typeToAux(types.Types[types.TUINT8]) v.AddArg3(dst, src, mem) return true } // match: (SelectN [0] call:(StaticCall {sym} dst src (Const64 [sz]) mem)) - // cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call) - // result: (Move {dst.Type.Elem()} [int64(sz)] dst src mem) + // cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call) + // result: (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem) for { if auxIntToInt64(v.AuxInt) != 0 { break @@ -21160,18 +21158,18 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool { break } sz := auxIntToInt64(call_2.AuxInt) - if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) { + if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) { break } v.reset(OpMove) v.AuxInt = int64ToAuxInt(int64(sz)) - v.Aux = typeToAux(dst.Type.Elem()) + v.Aux = typeToAux(types.Types[types.TUINT8]) v.AddArg3(dst, src, mem) return true } // match: (SelectN [0] call:(StaticCall {sym} dst src (Const32 [sz]) mem)) - // cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call) - // result: (Move {dst.Type.Elem()} [int64(sz)] dst src mem) + // cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call) + // result: (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem) for { if auxIntToInt64(v.AuxInt) != 0 { break @@ -21189,18 +21187,18 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool { break } sz := auxIntToInt32(call_2.AuxInt) - if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) { + if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) { break } v.reset(OpMove) v.AuxInt = int64ToAuxInt(int64(sz)) - v.Aux = typeToAux(dst.Type.Elem()) + v.Aux = typeToAux(types.Types[types.TUINT8]) v.AddArg3(dst, src, mem) return true } // match: (SelectN [0] call:(StaticLECall {sym} dst src (Const64 [sz]) mem)) - // cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call) - // result: (Move {dst.Type.Elem()} [int64(sz)] dst src mem) + // cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call) + // result: (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem) for { if auxIntToInt64(v.AuxInt) != 0 { break @@ -21218,18 +21216,18 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool { break } sz := auxIntToInt64(call_2.AuxInt) - if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) { + if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) { break } v.reset(OpMove) v.AuxInt = int64ToAuxInt(int64(sz)) - v.Aux = typeToAux(dst.Type.Elem()) + v.Aux = typeToAux(types.Types[types.TUINT8]) v.AddArg3(dst, src, mem) return true } // match: (SelectN [0] call:(StaticLECall {sym} dst src (Const32 [sz]) mem)) - // cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call) - // result: (Move {dst.Type.Elem()} [int64(sz)] dst src mem) + // cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call) + // result: (Move {types.Types[types.TUINT8]} [int64(sz)] dst src mem) for { if auxIntToInt64(v.AuxInt) != 0 { break @@ -21247,12 +21245,12 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool { break } sz := auxIntToInt32(call_2.AuxInt) - if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) { + if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) { break } v.reset(OpMove) v.AuxInt = int64ToAuxInt(int64(sz)) - v.Aux = typeToAux(dst.Type.Elem()) + v.Aux = typeToAux(types.Types[types.TUINT8]) v.AddArg3(dst, src, mem) return true } diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 364e0c8197ebf6859b51cc865667959986ccf71a..b19f3c812bedbd0e0e2332cf4776820f012747d7 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -105,6 +105,7 @@ func InitConfig() { ir.Syms.GCWriteBarrier = typecheck.LookupRuntimeFunc("gcWriteBarrier") ir.Syms.Goschedguarded = typecheck.LookupRuntimeFunc("goschedguarded") ir.Syms.Growslice = typecheck.LookupRuntimeFunc("growslice") + ir.Syms.Memmove = typecheck.LookupRuntimeFunc("memmove") ir.Syms.Msanread = typecheck.LookupRuntimeFunc("msanread") ir.Syms.Msanwrite = typecheck.LookupRuntimeFunc("msanwrite") ir.Syms.Msanmove = typecheck.LookupRuntimeFunc("msanmove") @@ -1387,7 +1388,47 @@ func (s *state) zero(t *types.Type, dst *ssa.Value) { } func (s *state) move(t *types.Type, dst, src *ssa.Value) { + s.moveWhichMayOverlap(t, dst, src, false) +} +func (s *state) moveWhichMayOverlap(t *types.Type, dst, src *ssa.Value, mayOverlap bool) { s.instrumentMove(t, dst, src) + if mayOverlap && t.IsArray() && t.NumElem() > 1 && !ssa.IsInlinableMemmove(dst, src, t.Size(), s.f.Config) { + // Normally, when moving Go values of type T from one location to another, + // we don't need to worry about partial overlaps. The two Ts must either be + // in disjoint (nonoverlapping) memory or in exactly the same location. + // There are 2 cases where this isn't true: + // 1) Using unsafe you can arrange partial overlaps. + // 2) Since Go 1.17, you can use a cast from a slice to a ptr-to-array. + // https://go.dev/ref/spec#Conversions_from_slice_to_array_pointer + // This feature can be used to construct partial overlaps of array types. + // var a [3]int + // p := (*[2]int)(a[:]) + // q := (*[2]int)(a[1:]) + // *p = *q + // We don't care about solving 1. Or at least, we haven't historically + // and no one has complained. + // For 2, we need to ensure that if there might be partial overlap, + // then we can't use OpMove; we must use memmove instead. + // (memmove handles partial overlap by copying in the correct + // direction. OpMove does not.) + // + // Note that we have to be careful here not to introduce a call when + // we're marshaling arguments to a call or unmarshaling results from a call. + // Cases where this is happening must pass mayOverlap to false. + // (Currently this only happens when unmarshaling results of a call.) + if t.HasPointers() { + s.rtcall(ir.Syms.Typedmemmove, true, nil, s.reflectType(t), dst, src) + // We would have otherwise implemented this move with straightline code, + // including a write barrier. Pretend we issue a write barrier here, + // so that the write barrier tests work. (Otherwise they'd need to know + // the details of IsInlineableMemmove.) + s.curfn.SetWBPos(s.peekPos()) + } else { + s.rtcall(ir.Syms.Memmove, true, nil, dst, src, s.constInt(types.Types[types.TUINTPTR], t.Size())) + } + ssa.LogLargeCopy(s.f.Name, s.peekPos(), t.Size()) + return + } store := s.newValue3I(ssa.OpMove, types.TypeMem, t.Size(), dst, src, s.mem()) store.Aux = t s.vars[memVar] = store @@ -1565,6 +1606,36 @@ func (s *state) stmt(n ir.Node) { return } + // mayOverlap keeps track of whether the LHS and RHS might + // refer to overlapping memory. + mayOverlap := true + if n.Y == nil { + // Not a move at all, mayOverlap is not relevant. + } else if n.Def { + // A variable being defined cannot overlap anything else. + mayOverlap = false + } else if n.X.Op() == ir.ONAME && n.Y.Op() == ir.ONAME { + // Two named things never overlap. + // (Or they are identical, which we treat as nonoverlapping.) + mayOverlap = false + } else if n.Y.Op() == ir.ODEREF { + p := n.Y.(*ir.StarExpr).X + for p.Op() == ir.OCONVNOP { + p = p.(*ir.ConvExpr).X + } + if p.Op() == ir.OSPTR && p.(*ir.UnaryExpr).X.Type().IsString() { + // Pointer fields of strings point to unmodifiable memory. + // That memory can't overlap with the memory being written. + mayOverlap = false + } + } else if n.Y.Op() == ir.ORESULT || n.Y.Op() == ir.OCALLFUNC || n.Y.Op() == ir.OCALLINTER { + // When copying values out of the return area of a call, we know + // the source and destination don't overlap. Importantly, we must + // set mayOverlap so we don't introduce a call to memmove while + // we still have live data in the argument area. + mayOverlap = false + } + // Evaluate RHS. rhs := n.Y if rhs != nil { @@ -1665,7 +1736,7 @@ func (s *state) stmt(n ir.Node) { } } - s.assign(n.X, r, deref, skip) + s.assignWhichMayOverlap(n.X, r, deref, skip, mayOverlap) case ir.OIF: n := n.(*ir.IfStmt) @@ -3503,7 +3574,11 @@ const ( // If deref is true, then we do left = *right instead (and right has already been nil-checked). // If deref is true and right == nil, just do left = 0. // skip indicates assignments (at the top level) that can be avoided. +// mayOverlap indicates whether left&right might partially overlap in memory. Default is false. func (s *state) assign(left ir.Node, right *ssa.Value, deref bool, skip skipMask) { + s.assignWhichMayOverlap(left, right, deref, skip, false) +} +func (s *state) assignWhichMayOverlap(left ir.Node, right *ssa.Value, deref bool, skip skipMask, mayOverlap bool) { if left.Op() == ir.ONAME && ir.IsBlank(left) { return } @@ -3604,7 +3679,7 @@ func (s *state) assign(left ir.Node, right *ssa.Value, deref bool, skip skipMask if right == nil { s.zero(t, addr) } else { - s.move(t, addr, right) + s.moveWhichMayOverlap(t, addr, right, mayOverlap) } return } diff --git a/src/cmd/compile/internal/test/race.go b/src/cmd/compile/internal/test/race.go new file mode 100644 index 0000000000000000000000000000000000000000..4cc4d536095c91f84d1d58cdf6429181028e9539 --- /dev/null +++ b/src/cmd/compile/internal/test/race.go @@ -0,0 +1,65 @@ +// Copyright 2022 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. + +//go:build !compiler_bootstrap +// +build !compiler_bootstrap + +package test + +// The racecompile builder only builds packages, but does not build +// or run tests. This is a non-test file to hold cases that (used +// to) trigger compiler data races, so they will be exercised on +// the racecompile builder. +// +// This package is not imported so functions here are not included +// in the actual compiler. + +// Issue 55357: data race when building multiple instantiations of +// generic closures with _ parameters. +func Issue55357() { + type U struct { + A int + B string + C string + } + var q T55357[U] + q.Count() + q.List() + + type M struct { + A int64 + B uint32 + C uint32 + } + var q2 T55357[M] + q2.Count() + q2.List() +} + +type T55357[T any] struct{} + +//go:noinline +func (q *T55357[T]) do(w, v bool, fn func(bk []byte, v T) error) error { + return nil +} + +func (q *T55357[T]) Count() (n int, rerr error) { + err := q.do(false, false, func(kb []byte, _ T) error { + n++ + return nil + }) + return n, err +} + +func (q *T55357[T]) List() (list []T, rerr error) { + var l []T + err := q.do(false, true, func(_ []byte, v T) error { + l = append(l, v) + return nil + }) + if err != nil { + return nil, err + } + return l, nil +} diff --git a/src/cmd/compile/internal/typecheck/const.go b/src/cmd/compile/internal/typecheck/const.go index fbe7c02c49821eb587ea97bf5e27b9f507e3bff6..24058fae584d203a13486f2d90d7a39fe3d230fb 100644 --- a/src/cmd/compile/internal/typecheck/const.go +++ b/src/cmd/compile/internal/typecheck/const.go @@ -895,6 +895,18 @@ func evalunsafe(n ir.Node) int64 { sel.X = Expr(sel.X) sbase := sel.X + // Implicit dot may already be resolved for instantiating generic function. So we + // need to remove any implicit dot until we reach the first non-implicit one, it's + // the right base selector. See issue #53137. + var clobberBase func(n ir.Node) ir.Node + clobberBase = func(n ir.Node) ir.Node { + if sel, ok := n.(*ir.SelectorExpr); ok && sel.Implicit() { + return clobberBase(sel.X) + } + return n + } + sbase = clobberBase(sbase) + tsel := Expr(sel) n.X = tsel if tsel.Type() == nil { diff --git a/src/cmd/compile/internal/typecheck/stmt.go b/src/cmd/compile/internal/typecheck/stmt.go index 7ab9a1df96e3ea5d211414f7c17f92f815af2030..9a02c1752caf13f6c89e26866e01ba553a767e62 100644 --- a/src/cmd/compile/internal/typecheck/stmt.go +++ b/src/cmd/compile/internal/typecheck/stmt.go @@ -127,23 +127,13 @@ func assign(stmt ir.Node, lhs, rhs []ir.Node) { checkLHS := func(i int, typ *types.Type) { lhs[i] = Resolve(lhs[i]) - if base.Flag.G != 0 || base.Debug.Unified != 0 { - // New logic added in CL 403837 for Go 1.19, which only has -G=3 and unified IR. - if n := lhs[i]; typ != nil && ir.DeclaredBy(n, stmt) && n.Type() == nil { - base.Assertf(typ.Kind() == types.TNIL, "unexpected untyped nil") + if n := lhs[i]; typ != nil && ir.DeclaredBy(n, stmt) && n.Name().Ntype == nil { + if typ.Kind() != types.TNIL { n.SetType(defaultType(typ)) - } - } else { - // Original logic from Go 1.18, which is still needed for -G=0. - if n := lhs[i]; typ != nil && ir.DeclaredBy(n, stmt) && n.Name().Ntype == nil { - if typ.Kind() != types.TNIL { - n.SetType(defaultType(typ)) - } else { - base.Errorf("use of untyped nil") - } + } else { + base.Errorf("use of untyped nil") } } - if lhs[i].Typecheck() == 0 { lhs[i] = AssignExpr(lhs[i]) } diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index a41a3d62fbf696571407bdceb992bcf165851e8c..7c48fb577dfd2bbcf02dd7c97259e779c8e9bbf5 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1356,7 +1356,8 @@ func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type { newfields[i].SetNointerface(true) } if f.Nname != nil && ts.Vars != nil { - v := ts.Vars[f.Nname.(*ir.Name)] + n := f.Nname.(*ir.Name) + v := ts.Vars[n] if v != nil { // This is the case where we are // translating the type of the function we @@ -1364,6 +1365,13 @@ func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type { // the subst.ts.vars table, and we want to // change to reference the new dcl. newfields[i].Nname = v + } else if ir.IsBlank(n) { + // Blank variable is not dcl list. Make a + // new one to not share. + m := ir.NewNameAt(n.Pos(), ir.BlankNode.Sym()) + m.SetType(n.Type()) + m.SetTypecheck(1) + newfields[i].Nname = m } else { // This is the case where we are // translating the type of a function diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index fb6accdc642f74acf21f57ea663729db2b536428..0c3fa922f86174aaffc48ceab35c0b39de26d13c 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -696,6 +696,12 @@ func PtrDataSize(t *Type) int64 { } return 0 + case TSSA: + if t != TypeInt128 { + base.Fatalf("PtrDataSize: unexpected ssa type %v", t) + } + return 0 + default: base.Fatalf("PtrDataSize: unexpected type, %v", t) return 0 diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index bfcb8d215e34a3e1bd84f288e59440109fb234cf..1021bd94a0db03799873445a77c73b3c3c3239e6 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1721,6 +1721,11 @@ var ( TypeResultMem = newResults([]*Type{TypeMem}) ) +func init() { + TypeInt128.width = 16 + TypeInt128.align = 8 +} + // NewNamed returns a new named type for the given type name. obj should be an // ir.Name. The new type is incomplete (marked as TFORW kind), and the underlying // type should be set later via SetUnderlying(). References to the type are diff --git a/src/cmd/compile/internal/types2/issues_test.go b/src/cmd/compile/internal/types2/issues_test.go index 697a73525cd4a88e069c90ed83320f13c93ae338..fc4aeb163456b002308e905142b58de47e1a254b 100644 --- a/src/cmd/compile/internal/types2/issues_test.go +++ b/src/cmd/compile/internal/types2/issues_test.go @@ -637,3 +637,40 @@ func TestIssue50646(t *testing.T) { t.Errorf("comparable not assignable to any") } } + +func TestIssue55030(t *testing.T) { + // makeSig makes the signature func(typ...) + makeSig := func(typ Type) { + par := NewVar(nopos, nil, "", typ) + params := NewTuple(par) + NewSignatureType(nil, nil, nil, params, nil, true) + } + + // makeSig must not panic for the following (example) types: + // []int + makeSig(NewSlice(Typ[Int])) + + // string + makeSig(Typ[String]) + + // P where P's core type is string + { + P := NewTypeName(nopos, nil, "P", nil) // [P string] + makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]}))) + } + + // P where P's core type is an (unnamed) slice + { + P := NewTypeName(nopos, nil, "P", nil) // [P []int] + makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])}))) + } + + // P where P's core type is bytestring (i.e., string or []byte) + { + t1 := NewTerm(true, Typ[String]) // ~string + t2 := NewTerm(false, NewSlice(Typ[Byte])) // []byte + u := NewUnion([]*Term{t1, t2}) // ~string | []byte + P := NewTypeName(nopos, nil, "P", nil) // [P ~string | []byte] + makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u}))) + } +} diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index c98024f92482e0e46891298bbce1b1b6e27d1bab..f52f3e25b23c114060728bb9e3cf3d736b87b432 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -4,7 +4,10 @@ package types2 -import "cmd/compile/internal/syntax" +import ( + "cmd/compile/internal/syntax" + "fmt" +) // ---------------------------------------------------------------------------- // API @@ -28,16 +31,18 @@ type Signature struct { // NewSignatureType creates a new function type for the given receiver, // receiver type parameters, type parameters, parameters, and results. If // variadic is set, params must hold at least one parameter and the last -// parameter must be of unnamed slice type. If recv is non-nil, typeParams must -// be empty. If recvTypeParams is non-empty, recv must be non-nil. +// parameter's core type must be of unnamed slice or bytestring type. +// If recv is non-nil, typeParams must be empty. If recvTypeParams is +// non-empty, recv must be non-nil. func NewSignatureType(recv *Var, recvTypeParams, typeParams []*TypeParam, params, results *Tuple, variadic bool) *Signature { if variadic { n := params.Len() if n == 0 { panic("variadic function must have at least one parameter") } - if _, ok := params.At(n - 1).typ.(*Slice); !ok { - panic("variadic parameter must be of unnamed slice type") + core := coreString(params.At(n - 1).typ) + if _, ok := core.(*Slice); !ok && !isString(core) { + panic(fmt.Sprintf("got %s, want variadic parameter with unnamed slice type or string as core type", core.String())) } } sig := &Signature{recv: recv, params: params, results: results, variadic: variadic} diff --git a/src/cmd/compile/internal/walk/complit.go b/src/cmd/compile/internal/walk/complit.go index b985b4caeb8597ec7387cb7ca24eb4cde01e5c0d..e9575800710234b158f8bc1b0c101fa98232237a 100644 --- a/src/cmd/compile/internal/walk/complit.go +++ b/src/cmd/compile/internal/walk/complit.go @@ -621,6 +621,12 @@ func oaslit(n *ir.AssignStmt, init *ir.Nodes) bool { // not a special composite literal assignment return false } + if x.Addrtaken() { + // If x is address-taken, the RHS may (implicitly) uses LHS. + // Not safe to do a special composite literal assignment + // (which may expand to multiple assignments). + return false + } switch n.Y.Op() { default: @@ -629,7 +635,7 @@ func oaslit(n *ir.AssignStmt, init *ir.Nodes) bool { case ir.OSTRUCTLIT, ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT: if ir.Any(n.Y, func(y ir.Node) bool { return ir.Uses(y, x) }) { - // not a special composite literal assignment + // not safe to do a special composite literal assignment if RHS uses LHS. return false } anylit(n.Y, n.X, init) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 5bd7bf9b8b62b277a4eda057b52664f4055fc7e7..44aa3230db48a2f41271b66841c3649b53c8718e 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -3,7 +3,7 @@ module cmd go 1.18 require ( - github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31 + github.com/google/pprof v0.0.0-20220729232143-a41b82acbcb1 golang.org/x/arch v0.0.0-20210923205945-b76863e36670 golang.org/x/mod v0.6.0-dev.0.20211102181907-3a5865c02020 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c @@ -12,8 +12,8 @@ require ( ) require ( - github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d // indirect + github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2 // indirect golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect - golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index a8a85503a89b04582a813b0bb5f0411702e3babc..baad8bb5074c6746e6085adae95a53a22980fe9a 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -1,10 +1,7 @@ -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31 h1:YvpxjnjGhf/vDEeYOysNbsrtB///PKS8lqkFNSDm1p8= -github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= -github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d h1:uGg2frlt3IcT7kbV6LEp5ONv4vmoO2FW4qSO+my/aoM= -github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/google/pprof v0.0.0-20220729232143-a41b82acbcb1 h1:8pyqKJvrJqUYaKS851Ule26pwWvey6IDMiczaBLDKLQ= +github.com/google/pprof v0.0.0-20220729232143-a41b82acbcb1/go.mod h1:gSuNB+gJaOiQKLEZ+q+PK9Mq3SOzhRcw2GsGS/FhYDk= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2 h1:rcanfLhLDA8nozr/K289V1zcntHr3V+SHlXwzz1ZI2g= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M= @@ -13,9 +10,8 @@ golang.org/x/mod v0.6.0-dev.0.20211102181907-3a5865c02020 h1:HjtpZuJcnSa+yHlL4Y5 golang.org/x/mod v0.6.0-dev.0.20211102181907-3a5865c02020/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E= -golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/tools v0.1.9-0.20220329150752-294080fd2f5a h1:IlVBSvpiWIkpqADzaiismkf1xcqsZjBDIXzO+7kZEpY= diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index c1adf8cef4ca1b386042ff17c0da3d9245c9cfb8..2a283fc4f80ba1f53f24826a95aedd50f3ebd128 100644 --- a/src/cmd/go/internal/envcmd/env.go +++ b/src/cmd/go/internal/envcmd/env.go @@ -167,8 +167,8 @@ func ExtraEnvVars() []cfg.EnvVar { // ExtraEnvVarsCostly returns environment variables that should not leak into child processes // but are costly to evaluate. func ExtraEnvVarsCostly() []cfg.EnvVar { - var b work.Builder - b.Init() + b := work.NewBuilder("") + cppflags, cflags, cxxflags, fflags, ldflags, err := b.CFlags(&load.Package{}) if err != nil { // Should not happen - b.CFlags was given an empty package. diff --git a/src/cmd/go/internal/imports/tags.go b/src/cmd/go/internal/imports/tags.go index 01b448b9142e57729bd19fdb380be7822cb08feb..d1467b81b0b66083a3542ca0b27f9829500eb682 100644 --- a/src/cmd/go/internal/imports/tags.go +++ b/src/cmd/go/internal/imports/tags.go @@ -36,6 +36,9 @@ func loadTags() map[string]bool { for _, tag := range cfg.BuildContext.BuildTags { tags[tag] = true } + for _, tag := range cfg.BuildContext.ToolTags { + tags[tag] = true + } for _, tag := range cfg.BuildContext.ReleaseTags { tags[tag] = true } diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index 62c18866c4c65287939d5e08ac65116e382a8b98..c15749ebf198920f486f6bc23ad5d259098ee769 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -592,8 +592,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) { // Do we need to run a build to gather information? needStale := *listJson || strings.Contains(*listFmt, ".Stale") if needStale || *listExport || *listCompiled { - var b work.Builder - b.Init() + b := work.NewBuilder("") b.IsCmdList = true b.NeedExport = *listExport b.NeedCompiledGoFiles = *listCompiled diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 438cc350859feed8201b6a902c3f28a6241a231e..5b5b5efbba476b7b78a48df2cb48dfcb4c9f7f97 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -2329,7 +2329,17 @@ func (p *Package) setBuildInfo(includeVCS bool) { appendSetting("-gcflags", BuildGcflags.String()) } if BuildLdflags.present { - appendSetting("-ldflags", BuildLdflags.String()) + // https://go.dev/issue/52372: only include ldflags if -trimpath is not set, + // since it can include system paths through various linker flags (notably + // -extar, -extld, and -extldflags). + // + // TODO: since we control cmd/link, in theory we can parse ldflags to + // determine whether they may refer to system paths. If we do that, we can + // redact only those paths from the recorded -ldflags setting and still + // record the system-independent parts of the flags. + if !cfg.BuildTrimpath { + appendSetting("-ldflags", BuildLdflags.String()) + } } if cfg.BuildMSan { appendSetting("-msan", "true") @@ -2345,7 +2355,14 @@ func (p *Package) setBuildInfo(includeVCS bool) { cgo = "1" } appendSetting("CGO_ENABLED", cgo) - if cfg.BuildContext.CgoEnabled { + // https://go.dev/issue/52372: only include CGO flags if -trimpath is not set. + // (If -trimpath is set, it is possible that these flags include system paths.) + // If cgo is involved, reproducibility is already pretty well ruined anyway, + // given that we aren't stamping header or library versions. + // + // TODO(bcmills): perhaps we could at least parse the flags and stamp the + // subset of flags that are known not to be paths? + if cfg.BuildContext.CgoEnabled && !cfg.BuildTrimpath { for _, name := range []string{"CGO_CFLAGS", "CGO_CPPFLAGS", "CGO_CXXFLAGS", "CGO_LDFLAGS"} { appendSetting(name, cfg.Getenv(name)) } diff --git a/src/cmd/go/internal/modfetch/codehost/git.go b/src/cmd/go/internal/modfetch/codehost/git.go index 34f453c855ef8d6b3dd7f6edbab34f30430b7c08..afd71c1671b54bdf094823c2ebf7c6ebe77943a4 100644 --- a/src/cmd/go/internal/modfetch/codehost/git.go +++ b/src/cmd/go/internal/modfetch/codehost/git.go @@ -447,7 +447,7 @@ func (r *gitRepo) fetchRefsLocked() error { // 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) { - out, err := Run(r.dir, "git", "-c", "log.showsignature=false", "log", "-n1", "--format=format:%H %ct %D", rev, "--") + out, err := Run(r.dir, "git", "-c", "log.showsignature=false", "log", "--no-decorate", "-n1", "--format=format:%H %ct %D", rev, "--") if err != nil { return nil, &UnknownRevisionError{Rev: rev} } diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 6f9072c8c48c395a6a1c44f2fd87f0e77390bbcb..0664dd43ebc960a6ef129c8879d5b7016c73a447 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -397,7 +397,6 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio seen := map[module.Version]bool{} for _, m := range roots { hasDepsInAll[m.Path] = true - seen[m] = true } // This loop will terminate because it will call enqueue on each version of // each dependency of the modules in hasDepsInAll at most once (and only @@ -406,11 +405,11 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio needsEnqueueing := map[module.Version]bool{} for p := range hasDepsInAll { m := module.Version{Path: p, Version: mg.g.Selected(p)} - reqs, ok := mg.g.RequiredBy(m) - if !ok { + if !seen[m] { needsEnqueueing[m] = true continue } + reqs, _ := mg.g.RequiredBy(m) for _, r := range reqs { s := module.Version{Path: r.Path, Version: mg.g.Selected(r.Path)} if cmpVersion(s.Version, r.Version) > 0 && !seen[s] { diff --git a/src/cmd/go/internal/modload/import_test.go b/src/cmd/go/internal/modload/import_test.go index 65a889ec52f11c8355085050833b82ccfee56ddd..eb4f5d64d3a3c7dca78c66d9dfa901530c5dfaa9 100644 --- a/src/cmd/go/internal/modload/import_test.go +++ b/src/cmd/go/internal/modload/import_test.go @@ -27,7 +27,7 @@ var importTests = []struct { }, { path: "golang.org/x/net", - err: `module golang.org/x/net@.* found \(v0.0.0-.*\), but does not contain package golang.org/x/net`, + err: `module golang.org/x/net@.* found \(v[01]\.\d+\.\d+\), but does not contain package golang.org/x/net`, }, { path: "golang.org/x/text", diff --git a/src/cmd/go/internal/run/run.go b/src/cmd/go/internal/run/run.go index 312b49ef5dfa33828cf65c9ac373dfad88d86e8f..a0aca316fcf546b670bba229f981a1b5230670d7 100644 --- a/src/cmd/go/internal/run/run.go +++ b/src/cmd/go/internal/run/run.go @@ -87,8 +87,7 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) { } work.BuildInit() - var b work.Builder - b.Init() + b := work.NewBuilder("") b.Print = printStderr i := 0 diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 50e6d5201b0d6e04cc59a3289d30fa8b4e1cb2b0..3f31a8a80d594da3a46010d551ed521e7ace2e2c 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -744,8 +744,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { } } - var b work.Builder - b.Init() + b := work.NewBuilder("") if cfg.BuildI { fmt.Fprint(os.Stderr, "go: -i flag is deprecated\n") @@ -800,7 +799,16 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { if !testC || a.Failed { return } - b.Init() + + // TODO(bcmills): I have no idea why the Builder must be reset here, but + // without this reset dance, TestGoTestDashIDashOWritesBinary fails with + // lots of "vet config not found" errors. This was added in CL 5699088, + // which had almost no public discussion, a very short commit description, + // and left no comment in the code to explain what is going on here. 🤯 + // + // Maybe this has the effect of removing actions that were registered by the + // call to CompileAction above? + b = work.NewBuilder("") } var builds, runs, prints []*work.Action @@ -916,7 +924,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { ensureImport(p, "sync/atomic") } - buildTest, runTest, printTest, err := builderTest(&b, ctx, pkgOpts, p, allImports[p]) + buildTest, runTest, printTest, err := builderTest(b, ctx, pkgOpts, p, allImports[p]) if err != nil { str := err.Error() str = strings.TrimPrefix(str, "\n") diff --git a/src/cmd/go/internal/vet/vet.go b/src/cmd/go/internal/vet/vet.go index d3e0dd8116f481ef4d8e72e5c467a75110cde9bc..9b8698295af111f13cf4e91cfd51289fd75734bc 100644 --- a/src/cmd/go/internal/vet/vet.go +++ b/src/cmd/go/internal/vet/vet.go @@ -94,8 +94,7 @@ func runVet(ctx context.Context, cmd *base.Command, args []string) { base.Fatalf("no packages to vet") } - var b work.Builder - b.Init() + b := work.NewBuilder("") root := &work.Action{Mode: "go vet"} for _, p := range pkgs { diff --git a/src/cmd/go/internal/work/action.go b/src/cmd/go/internal/work/action.go index c0862c5efe503af8cf6384aebd1468b9d89e024f..4bbd23ab8e43212b10a1303cfec594a16afff59e 100644 --- a/src/cmd/go/internal/work/action.go +++ b/src/cmd/go/internal/work/action.go @@ -240,7 +240,13 @@ const ( ModeVetOnly = 1 << 8 ) -func (b *Builder) Init() { +// NewBuilder returns a new Builder ready for use. +// +// If workDir is the empty string, NewBuilder creates a WorkDir if needed +// and arranges for it to be removed in case of an unclean exit. +func NewBuilder(workDir string) *Builder { + b := new(Builder) + b.Print = func(a ...any) (int, error) { return fmt.Fprint(os.Stderr, a...) } @@ -249,7 +255,9 @@ func (b *Builder) Init() { b.toolIDCache = make(map[string]string) b.buildIDCache = make(map[string]string) - if cfg.BuildN { + if workDir != "" { + b.WorkDir = workDir + } else if cfg.BuildN { b.WorkDir = "$WORK" } else { tmp, err := os.MkdirTemp(cfg.Getenv("GOTMPDIR"), "go-build") @@ -306,6 +314,8 @@ func (b *Builder) Init() { base.Exit() } } + + return b } func CheckGOOSARCHPair(goos, goarch string) error { diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index 394fe9105003c7b149439b19b0f5188b1bfddfc1..e66dad6898157f20143ebb9ddba54aa6b1841521 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -402,8 +402,7 @@ var runtimeVersion = runtime.Version() func runBuild(ctx context.Context, cmd *base.Command, args []string) { modload.InitWorkfile() BuildInit() - var b Builder - b.Init() + b := NewBuilder("") pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{LoadVCS: true}, args) load.CheckPackageErrors(pkgs) @@ -721,8 +720,8 @@ func InstallPackages(ctx context.Context, patterns []string, pkgs []*load.Packag } base.ExitIfErrors() - var b Builder - b.Init() + b := NewBuilder("") + depMode := ModeBuild if cfg.BuildI { depMode = ModeInstall diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index 55a88e0e0b03e23ac34dc7e6e6b5db2d46abe0b3..aac0b4792da0de818da05aa59ba2ceaf69a21602 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -532,10 +532,8 @@ func (ts *testScript) cmdCc(want simpleStatus, args []string) { ts.fatalf("usage: cc args... [&]") } - var b work.Builder - b.Init() + b := work.NewBuilder(ts.workdir) ts.cmdExec(want, append(b.GccCmd(".", ""), args...)) - robustio.RemoveAll(b.WorkDir) } // cd changes to a different directory. diff --git a/src/cmd/go/testdata/script/mod_download_git_decorate_full.txt b/src/cmd/go/testdata/script/mod_download_git_decorate_full.txt new file mode 100644 index 0000000000000000000000000000000000000000..3b19acc1b152a0e560b7eec3acaca34c0b910a06 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_download_git_decorate_full.txt @@ -0,0 +1,28 @@ +env GO111MODULE=on + +[!net] skip +[!exec:git] skip + +env GOPROXY=direct +env HOME=$WORK/home/gopher + + +go env GOPROXY +stdout 'direct' + +exec git config --get log.decorate +stdout 'full' + +# Test that Git log with user's global config '~/gitconfig' has log.decorate=full +# go mod download has an error 'v1.x.y is not a tag' +# with go1.16.14: +# `go1.16.14 list -m vcs-test.golang.org/git/gitrepo1.git@v1.2.3` +# will output with error: +# go list -m: vcs-test.golang.org/git/gitrepo1.git@v1.2.3: invalid version: unknown revision v1.2.3 +# See golang/go#51312. +go list -m vcs-test.golang.org/git/gitrepo1.git@v1.2.3 +stdout 'vcs-test.golang.org/git/gitrepo1.git v1.2.3' + +-- $WORK/home/gopher/.gitconfig -- +[log] + decorate = full \ No newline at end of file diff --git a/src/cmd/go/testdata/script/mod_replace_gopkgin.txt b/src/cmd/go/testdata/script/mod_replace_gopkgin.txt index df752d9716e538b4bb89c73679d45df8e1b395ca..8cb034c36c823175652933ef5ed18f116ff8390a 100644 --- a/src/cmd/go/testdata/script/mod_replace_gopkgin.txt +++ b/src/cmd/go/testdata/script/mod_replace_gopkgin.txt @@ -4,6 +4,9 @@ # even if there is an explicit go.mod file containing the # gopkg.in path. +skip 'skipping test that depends on an unreliable third-party server; see https://go.dev/issue/54503' + # TODO(#54043): Make this test hermetic and re-enable it. + [short] skip [!net] skip [!exec:git] skip diff --git a/src/cmd/go/testdata/script/test_race_tag.txt b/src/cmd/go/testdata/script/test_race_tag.txt new file mode 100644 index 0000000000000000000000000000000000000000..4b18ebc45496f89add3ccc2e25aaf8690f2e5b64 --- /dev/null +++ b/src/cmd/go/testdata/script/test_race_tag.txt @@ -0,0 +1,29 @@ +# Tests Issue #54468 + +[short] skip 'links a test binary' +[!race] skip + +go mod tidy +go test -c -o=$devnull -race . + +! stderr 'cannot find package' + +-- go.mod -- +module testrace + +go 1.18 + +require rsc.io/sampler v1.0.0 +-- race_test.go -- +//go:build race + +package testrace + +import ( + "testing" + + _ "rsc.io/sampler" +) + +func TestRaceTag(t *testing.T) { +} diff --git a/src/cmd/go/testdata/script/trampoline_reuse_test.txt b/src/cmd/go/testdata/script/trampoline_reuse_test.txt new file mode 100644 index 0000000000000000000000000000000000000000..bca897c16d0544ab6d8d369c732ca5dc10c569c9 --- /dev/null +++ b/src/cmd/go/testdata/script/trampoline_reuse_test.txt @@ -0,0 +1,100 @@ +# Verify PPC64 does not reuse a trampoline which is too far away. +# This tests an edge case where the direct call relocation addend should +# be ignored when computing the distance from the direct call to the +# already placed trampoline +[short] skip +[!ppc64] [!ppc64le] skip +[aix] skip + +# Note, this program does not run. Presumably, 'DWORD $0' is simpler to +# assembly 2^26 or so times. +# +# We build something which should be laid out as such: +# +# bar.Bar +# main.Func1 +# bar.Bar+400-tramp0 +# main.BigAsm +# main.Func2 +# bar.Bar+400-tramp1 +# +# bar.Bar needs to be placed far enough away to generate relocations +# from main package calls. and main.Func1 and main.Func2 are placed +# a bit more than the direct call limit apart, but not more than 0x400 +# bytes beyond it (to verify the reloc calc). + +go build + +-- go.mod -- + +module foo + +go 1.19 + +-- main.go -- + +package main + +import "foo/bar" + +func Func1() + +func main() { + Func1() + bar.Bar2() +} + +-- foo.s -- + +TEXT main·Func1(SB),0,$0-0 + CALL bar·Bar+0x400(SB) + CALL main·BigAsm(SB) +// A trampoline will be placed here to bar.Bar + +// This creates a gap sufficiently large to prevent trampoline reuse +#define NOP64 DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; +#define NOP256 NOP64 NOP64 NOP64 NOP64 +#define NOP2S10 NOP256 NOP256 NOP256 NOP256 +#define NOP2S12 NOP2S10 NOP2S10 NOP2S10 NOP2S10 +#define NOP2S14 NOP2S12 NOP2S12 NOP2S12 NOP2S12 +#define NOP2S16 NOP2S14 NOP2S14 NOP2S14 NOP2S14 +#define NOP2S18 NOP2S16 NOP2S16 NOP2S16 NOP2S16 +#define NOP2S20 NOP2S18 NOP2S18 NOP2S18 NOP2S18 +#define NOP2S22 NOP2S20 NOP2S20 NOP2S20 NOP2S20 +#define NOP2S24 NOP2S22 NOP2S22 NOP2S22 NOP2S22 +#define BIGNOP NOP2S24 NOP2S24 +TEXT main·BigAsm(SB),0,$0-0 + // Fill to the direct call limit so Func2 must generate a new trampoline. + // As the implicit trampoline above is just barely unreachable. + BIGNOP + MOVD $main·Func2(SB), R3 + +TEXT main·Func2(SB),0,$0-0 + CALL bar·Bar+0x400(SB) +// Another trampoline should be placed here. + +-- bar/bar.s -- + +#define NOP64 DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; DWORD $0; +#define NOP256 NOP64 NOP64 NOP64 NOP64 +#define NOP2S10 NOP256 NOP256 NOP256 NOP256 +#define NOP2S12 NOP2S10 NOP2S10 NOP2S10 NOP2S10 +#define NOP2S14 NOP2S12 NOP2S12 NOP2S12 NOP2S12 +#define NOP2S16 NOP2S14 NOP2S14 NOP2S14 NOP2S14 +#define NOP2S18 NOP2S16 NOP2S16 NOP2S16 NOP2S16 +#define NOP2S20 NOP2S18 NOP2S18 NOP2S18 NOP2S18 +#define NOP2S22 NOP2S20 NOP2S20 NOP2S20 NOP2S20 +#define NOP2S24 NOP2S22 NOP2S22 NOP2S22 NOP2S22 +#define BIGNOP NOP2S24 NOP2S24 NOP2S10 +// A very big not very interesting function. +TEXT bar·Bar(SB),0,$0-0 + BIGNOP + +-- bar/bar.go -- + +package bar + +func Bar() + +func Bar2() { +} diff --git a/src/cmd/go/testdata/script/version_build_settings.txt b/src/cmd/go/testdata/script/version_build_settings.txt index dc9e67681ea998049e2da46a0584b1d6d514174a..08df7e611db8fd2a6fd3236a45216bca4cc06518 100644 --- a/src/cmd/go/testdata/script/version_build_settings.txt +++ b/src/cmd/go/testdata/script/version_build_settings.txt @@ -47,19 +47,34 @@ go build go version -m m$GOEXE stdout '^\tbuild\tCGO_ENABLED=0$' ! stdout CGO_CPPFLAGS|CGO_CFLAGS|CGO_CXXFLAGS|CGO_LDFLAGS + [cgo] env CGO_ENABLED=1 [cgo] env CGO_CPPFLAGS=-DFROM_CPPFLAGS=1 [cgo] env CGO_CFLAGS=-DFROM_CFLAGS=1 [cgo] env CGO_CXXFLAGS=-DFROM_CXXFLAGS=1 [cgo] env CGO_LDFLAGS=-L/extra/dir/does/not/exist -[cgo] go build +[cgo] go build '-ldflags=all=-linkmode=external -extldflags=-L/bonus/dir/does/not/exist' [cgo] go version -m m$GOEXE +[cgo] stdout '^\tbuild\t-ldflags="all=-linkmode=external -extldflags=-L/bonus/dir/does/not/exist"$' [cgo] stdout '^\tbuild\tCGO_ENABLED=1$' [cgo] stdout '^\tbuild\tCGO_CPPFLAGS=-DFROM_CPPFLAGS=1$' [cgo] stdout '^\tbuild\tCGO_CFLAGS=-DFROM_CFLAGS=1$' [cgo] stdout '^\tbuild\tCGO_CXXFLAGS=-DFROM_CXXFLAGS=1$' [cgo] stdout '^\tbuild\tCGO_LDFLAGS=-L/extra/dir/does/not/exist$' +# https://go.dev/issue/52372: a cgo-enabled binary should not be stamped with +# CGO_ flags that contain paths. +[cgo] env CGO_ENABLED=1 +[cgo] env CGO_CPPFLAGS=-DFROM_CPPFLAGS=1 +[cgo] env CGO_CFLAGS=-DFROM_CFLAGS=1 +[cgo] env CGO_CXXFLAGS=-DFROM_CXXFLAGS=1 +[cgo] env CGO_LDFLAGS=-L/extra/dir/does/not/exist +[cgo] go build -trimpath '-ldflags=all=-linkmode=external -extldflags=-L/bonus/dir/does/not/exist' +[cgo] go version -m m$GOEXE +[cgo] ! stdout '/extra/dir/does/not/exist' +[cgo] ! stdout '/bonus/dir/does/not/exist' +[cgo] stdout '^\tbuild\tCGO_ENABLED=1$' + -- go.mod -- module example.com/m diff --git a/src/cmd/go/testdata/script/version_buildvcs_git_gpg.txt b/src/cmd/go/testdata/script/version_buildvcs_git_gpg.txt deleted file mode 100644 index dcf97d7c447f5b5d67c9321ff3ed15333122f1fb..0000000000000000000000000000000000000000 --- a/src/cmd/go/testdata/script/version_buildvcs_git_gpg.txt +++ /dev/null @@ -1,105 +0,0 @@ -# This test checks that VCS information is stamped into Go binaries even when -# the current commit is signed and the use has configured git to display commit -# signatures. - -[!exec:git] skip -[!exec:gpg] skip -[short] skip -env GOBIN=$GOPATH/bin -env GNUPGHOME=$WORK/.gpupg -mkdir $GNUPGHOME -chmod 0700 $GNUPGHOME - -# Create GPG key -exec gpg --batch --passphrase '' --quick-generate-key gopher@golang.org -exec gpg --list-secret-keys --with-colons gopher@golang.org -cp stdout keyinfo.txt -go run extract_key_id.go keyinfo.txt -cp stdout keyid.txt - -# Initialize repo -cd repo/ -exec git init -exec git config user.email gopher@golang.org -exec git config user.name 'J.R. Gopher' -exec git config --add log.showSignature true -go run ../configure_signing_key.go ../keyid.txt - -# Create signed commit -cd a -exec git add -A -exec git commit -m 'initial commit' --gpg-sign -exec git log - -# Verify commit signature does not interfere with versioning -go install -go version -m $GOBIN/a -stdout '^\tbuild\tvcs\.revision=' -stdout '^\tbuild\tvcs\.time=' -stdout '^\tbuild\tvcs\.modified=false$' - --- repo/README -- -Far out in the uncharted backwaters of the unfashionable end of the western -spiral arm of the Galaxy lies a small, unregarded yellow sun. --- repo/a/go.mod -- -module example.com/a - -go 1.18 --- repo/a/a.go -- -package main - -func main() {} - --- extract_key_id.go -- -package main - -import "fmt" -import "io/ioutil" -import "os" -import "strings" - -func main() { - err := run(os.Args[1]) - if err != nil { - panic(err) - } -} - -func run(keyInfoFilePath string) error { - contents, err := ioutil.ReadFile(keyInfoFilePath) - if err != nil { - return err - } - lines := strings.Split(string(contents), "\n") - for _, line := range lines { - fields := strings.Split(line, ":") - if fields[0] == "sec" { - fmt.Print(fields[4]) - return nil - } - } - return fmt.Errorf("key ID not found in: %s", keyInfoFilePath) -} - --- configure_signing_key.go -- -package main - -import "io/ioutil" -import "os" -import "os/exec" - -func main() { - err := run(os.Args[1]) - if err != nil { - panic(err) - } -} - -func run(keyIdFilePath string) error { - keyId, err := ioutil.ReadFile(keyIdFilePath) - if err != nil { - return err - } - gitCmd := exec.Command("git", "config", "user.signingKey", string(keyId)) - return gitCmd.Run() -} diff --git a/src/cmd/go/testdata/script/work_goproxy_off.txt b/src/cmd/go/testdata/script/work_goproxy_off.txt new file mode 100644 index 0000000000000000000000000000000000000000..767040d09a3742c2408119905efd7d45f8a76a67 --- /dev/null +++ b/src/cmd/go/testdata/script/work_goproxy_off.txt @@ -0,0 +1,59 @@ +go work init +go work use . ./sub + +# Verify that the go.mod files for both modules in the workspace are tidy, +# and add missing go.sum entries as needed. + +cp go.mod go.mod.orig +go mod tidy +cmp go.mod go.mod.orig + +cd sub +cp go.mod go.mod.orig +go mod tidy +cmp go.mod go.mod.orig +cd .. + +go list -m all +stdout '^rsc\.io/quote v1\.5\.1$' +stdout '^rsc\.io/sampler v1\.3\.1$' + +# Now remove the module dependencies from the module cache. +# Because one module upgrades a transitive dependency needed by another, +# listing the modules in the workspace should error out. + +go clean -modcache +env GOPROXY=off +! go list -m all +stderr '^go: rsc.io/sampler@v1.3.0: module lookup disabled by GOPROXY=off$' + +-- example.go -- +package example + +import _ "rsc.io/sampler" +-- go.mod -- +module example + +go 1.18 + +require rsc.io/sampler v1.3.0 + +require ( + golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect + rsc.io/testonly v1.0.0 // indirect +) +-- sub/go.mod -- +module example/sub + +go 1.18 + +require rsc.io/quote v1.5.1 + +require ( + golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect + rsc.io/sampler v1.3.1 // indirect +) +-- sub/sub.go -- +package example + +import _ "rsc.io/quote" diff --git a/src/cmd/internal/moddeps/moddeps_test.go b/src/cmd/internal/moddeps/moddeps_test.go index 56c3b2585c7fdc211a0c4e17827bf182eb938661..cd4d523e464219b8b515b124ef3dbdf6d4b95c90 100644 --- a/src/cmd/internal/moddeps/moddeps_test.go +++ b/src/cmd/internal/moddeps/moddeps_test.go @@ -34,6 +34,8 @@ import ( // See issues 36852, 41409, and 43687. // (Also see golang.org/issue/27348.) func TestAllDependencies(t *testing.T) { + t.Skip("TODO(#57008): 1.18.9 contains unreleased changes from vendored modules") + goBin := testenv.GoToolPath(t) // Ensure that all packages imported within GOROOT diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go index 2f9bf25d101c1fcb1f0f4d63bb885745e4f6b441..c1f60f0289ecd51b420a69363db838b04a349c9b 100644 --- a/src/cmd/link/internal/ld/dwarf_test.go +++ b/src/cmd/link/internal/ld/dwarf_test.go @@ -1843,3 +1843,82 @@ func main() { } } } +func TestIssue54320(t *testing.T) { + // Check that when trampolines are used, the DWARF LPT is correctly + // emitted in the final binary + testenv.MustHaveGoBuild(t) + + if runtime.GOOS == "plan9" { + t.Skip("skipping on plan9; no DWARF symbol table in executables") + } + + t.Parallel() + + const prog = ` +package main + +import "fmt" + +func main() { + fmt.Printf("Hello world\n"); +} +` + + dir := t.TempDir() + f := gobuild(t, dir, prog, "-ldflags=-debugtramp=2") + defer f.Close() + + d, err := f.DWARF() + if err != nil { + t.Fatalf("error reading DWARF: %v", err) + } + + rdr := d.Reader() + found := false + var entry *dwarf.Entry + for entry, err = rdr.Next(); entry != nil; entry, err = rdr.Next() { + if err != nil { + t.Fatalf("error reading DWARF: %v", err) + } + if entry.Tag != dwarf.TagCompileUnit { + continue + } + name, _ := entry.Val(dwarf.AttrName).(string) + if name == "main" { + found = true + break + } + rdr.SkipChildren() + } + + if !found { + t.Fatalf("could not find main compile unit") + } + lr, err := d.LineReader(entry) + if err != nil { + t.Fatalf("error obtaining linereader: %v", err) + } + + var le dwarf.LineEntry + found = false + for { + if err := lr.Next(&le); err != nil { + if err == io.EOF { + break + } + t.Fatalf("error reading linentry: %v", err) + } + // check LE contains an entry to test.go + if le.File == nil { + continue + } + file := filepath.Base(le.File.Name) + if file == "test.go" { + found = true + break + } + } + if !found { + t.Errorf("no LPT entries for test.go") + } +} diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index f1a37e955e93706e2324d1d476041616fd939c29..239e2dd4efc5740638d6c2c1db1d24591977931c 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -1324,7 +1324,6 @@ func (ctxt *Link) hostlink() { if ctxt.HeadType == objabi.Hdarwin { if machoPlatform == PLATFORM_MACOS && ctxt.IsAMD64() { argv = append(argv, "-Wl,-no_pie") - argv = append(argv, "-Wl,-pagezero_size,4000000") } } case BuildModePIE: @@ -1660,6 +1659,13 @@ func (ctxt *Link) hostlink() { if len(out) > 0 { // always print external output even if the command is successful, so that we don't // swallow linker warnings (see https://golang.org/issue/17935). + if ctxt.IsDarwin() && ctxt.IsAMD64() { + const noPieWarning = "ld: warning: -no_pie is deprecated when targeting new OS versions\n" + if i := bytes.Index(out, []byte(noPieWarning)); i >= 0 { + // swallow -no_pie deprecation warning, issue 54482 + out = append(out[:i], out[i+len(noPieWarning):]...) + } + } ctxt.Logf("%s", out) } diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 34c1c6a4c86c52a95e3f6aefcc1192e8ba4280ff..2a9435b96db20c8a5561e6bf337c2097bbb648c0 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -1630,13 +1630,8 @@ func (l *Loader) GetFuncDwarfAuxSyms(fnSymIdx Sym) (auxDwarfInfo, auxDwarfLoc, a if l.SymType(fnSymIdx) != sym.STEXT { log.Fatalf("error: non-function sym %d/%s t=%s passed to GetFuncDwarfAuxSyms", fnSymIdx, l.SymName(fnSymIdx), l.SymType(fnSymIdx).String()) } - if l.IsExternal(fnSymIdx) { - // Current expectation is that any external function will - // not have auxsyms. - return - } - r, li := l.toLocal(fnSymIdx) - auxs := r.Auxs(li) + r, auxs := l.auxs(fnSymIdx) + for i := range auxs { a := &auxs[i] switch a.Type() { @@ -2351,6 +2346,10 @@ func (l *Loader) cloneToExternal(symIdx Sym) { // need to access the old symbol content.) l.objSyms[symIdx] = objSym{l.extReader.objidx, uint32(pi)} l.extReader.syms = append(l.extReader.syms, symIdx) + + // Some attributes were encoded in the object file. Copy them over. + l.SetAttrDuplicateOK(symIdx, r.Sym(li).Dupok()) + l.SetAttrShared(symIdx, r.Shared()) } // Copy the payload of symbol src to dst. Both src and dst must be external @@ -2371,31 +2370,6 @@ func (l *Loader) CopySym(src, dst Sym) { // TODO: other attributes? } -// CopyAttributes copies over all of the attributes of symbol 'src' to -// symbol 'dst'. -func (l *Loader) CopyAttributes(src Sym, dst Sym) { - l.SetAttrReachable(dst, l.AttrReachable(src)) - l.SetAttrOnList(dst, l.AttrOnList(src)) - l.SetAttrLocal(dst, l.AttrLocal(src)) - l.SetAttrNotInSymbolTable(dst, l.AttrNotInSymbolTable(src)) - if l.IsExternal(dst) { - l.SetAttrVisibilityHidden(dst, l.AttrVisibilityHidden(src)) - l.SetAttrDuplicateOK(dst, l.AttrDuplicateOK(src)) - l.SetAttrShared(dst, l.AttrShared(src)) - l.SetAttrExternal(dst, l.AttrExternal(src)) - } else { - // Some attributes are modifiable only for external symbols. - // In such cases, don't try to transfer over the attribute - // from the source even if there is a clash. This comes up - // when copying attributes from a dupOK ABI wrapper symbol to - // the real target symbol (which may not be marked dupOK). - } - l.SetAttrSpecial(dst, l.AttrSpecial(src)) - l.SetAttrCgoExportDynamic(dst, l.AttrCgoExportDynamic(src)) - l.SetAttrCgoExportStatic(dst, l.AttrCgoExportStatic(src)) - l.SetAttrReadOnly(dst, l.AttrReadOnly(src)) -} - // CreateExtSym creates a new external symbol with the specified name // without adding it to any lookup tables, returning a Sym index for it. func (l *Loader) CreateExtSym(name string, ver int) Sym { diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go index d2b140b45dee9a30c68479608038d99605e9f91a..879adaa96505076b1ef4bb039d60eb19258df19f 100644 --- a/src/cmd/link/internal/ppc64/asm.go +++ b/src/cmd/link/internal/ppc64/asm.go @@ -766,7 +766,7 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) { // For external linking, the linker can insert a call stub to handle a long call, but depends on having the TOC address in // r2. For those build modes with external linking where the TOC address is not maintained in r2, trampolines must be created. if ctxt.IsExternal() && r2Valid(ctxt) { - // No trampolines needed since r2 contains the TOC + // The TOC pointer is valid. The external linker will insert trampolines. return } @@ -809,8 +809,9 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) { if ldr.SymValue(tramp) == 0 { break } - - t = ldr.SymValue(tramp) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) + // Note, the trampoline is always called directly. The addend of the original relocation is accounted for in the + // trampoline itself. + t = ldr.SymValue(tramp) - (ldr.SymValue(s) + int64(r.Off())) // With internal linking, the trampoline can be used if it is not too far. // With external linking, the trampoline must be in this section for it to be reused. @@ -819,14 +820,9 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) { } } if ldr.SymType(tramp) == 0 { - if r2Valid(ctxt) { - // Should have returned for above cases - ctxt.Errorf(s, "unexpected trampoline for shared or dynamic linking") - } else { - trampb := ldr.MakeSymbolUpdater(tramp) - ctxt.AddTramp(trampb) - gentramp(ctxt, ldr, trampb, rs, r.Add()) - } + trampb := ldr.MakeSymbolUpdater(tramp) + ctxt.AddTramp(trampb) + gentramp(ctxt, ldr, trampb, rs, r.Add()) } sb := ldr.MakeSymbolUpdater(s) relocs := sb.Relocs() @@ -842,7 +838,6 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) { func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) { tramp.SetSize(16) // 4 instructions P := make([]byte, tramp.Size()) - t := ldr.SymValue(target) + offset var o1, o2 uint32 if ctxt.IsAIX() { @@ -851,8 +846,8 @@ func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, ta // However, all text symbols are accessed with a TOC symbol as // text relocations aren't supposed to be possible. // So, keep using the external linking way to be more AIX friendly. - o1 = uint32(0x3fe20000) // lis r2, toctargetaddr hi - o2 = uint32(0xebff0000) // ld r31, toctargetaddr lo + o1 = uint32(0x3c000000) | 12<<21 | 2<<16 // addis r12, r2, toctargetaddr hi + o2 = uint32(0xe8000000) | 12<<21 | 12<<16 // ld r12, r12, toctargetaddr lo toctramp := ldr.CreateSymForUpdate("TOC."+ldr.SymName(tramp.Sym()), 0) toctramp.SetType(sym.SXCOFFTOC) @@ -866,31 +861,32 @@ func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, ta // Used for default build mode for an executable // Address of the call target is generated using // relocation and doesn't depend on r2 (TOC). - o1 = uint32(0x3fe00000) // lis r31,targetaddr hi - o2 = uint32(0x3bff0000) // addi r31,targetaddr lo + o1 = uint32(0x3c000000) | 12<<21 // lis r12,targetaddr hi + o2 = uint32(0x38000000) | 12<<21 | 12<<16 // addi r12,r12,targetaddr lo - // With external linking, the target address must be - // relocated using LO and HA - if ctxt.IsExternal() || ldr.SymValue(target) == 0 { + t := ldr.SymValue(target) + if t == 0 || r2Valid(ctxt) || ctxt.IsExternal() { + // Target address is unknown, generate relocations r, _ := tramp.AddRel(objabi.R_ADDRPOWER) + if r2Valid(ctxt) { + // Use a TOC relative address if R2 holds the TOC pointer + o1 |= uint32(2 << 16) // Transform lis r31,ha into addis r31,r2,ha + r.SetType(objabi.R_ADDRPOWER_TOCREL) + } r.SetOff(0) r.SetSiz(8) // generates 2 relocations: HA + LO r.SetSym(target) r.SetAdd(offset) } else { - // adjustment needed if lo has sign bit set - // when using addi to compute address - val := uint32((t & 0xffff0000) >> 16) - if t&0x8000 != 0 { - val += 1 - } - o1 |= val // hi part of addr - o2 |= uint32(t & 0xffff) // lo part of addr + // The target address is known, resolve it + t += offset + o1 |= (uint32(t) + 0x8000) >> 16 // HA + o2 |= uint32(t) & 0xFFFF // LO } } - o3 := uint32(0x7fe903a6) // mtctr r31 - o4 := uint32(0x4e800420) // bctr + o3 := uint32(0x7c0903a6) | 12<<21 // mtctr r12 + o4 := uint32(0x4e800420) // bctr ctxt.Arch.ByteOrder.PutUint32(P, o1) ctxt.Arch.ByteOrder.PutUint32(P[4:], o2) ctxt.Arch.ByteOrder.PutUint32(P[8:], o3) @@ -962,7 +958,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade // If we are linking PIE or shared code, all golang generated object files have an extra 2 instruction prologue // to regenerate the TOC pointer from R12. The exception are two special case functions tested below. Note, // local call offsets for externally generated objects are accounted for when converting into golang relocs. - if !ldr.IsExternal(rs) && ldr.AttrShared(rs) && tgtName != "runtime.duffzero" && tgtName != "runtime.duffcopy" { + if !ldr.AttrExternal(rs) && ldr.AttrShared(rs) && tgtName != "runtime.duffzero" && tgtName != "runtime.duffcopy" { // Furthermore, only apply the offset if the target looks like the start of a function call. if r.Add() == 0 && ldr.SymType(rs) == sym.STEXT { t += 8 diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go index ad7658bb2577f0fb163b8854d63c47c26c470a7a..d58ee8669bdc80e929e44827b5bd285737415aad 100644 --- a/src/cmd/link/link_test.go +++ b/src/cmd/link/link_test.go @@ -642,8 +642,12 @@ func TestTrampoline(t *testing.T) { // For stress test, we set -debugtramp=2 flag, which sets a very low // threshold for trampoline generation, and essentially all cross-package // calls will use trampolines. + buildmodes := []string{"default"} switch runtime.GOARCH { - case "arm", "arm64", "ppc64", "ppc64le": + case "arm", "arm64", "ppc64": + case "ppc64le": + // Trampolines are generated differently when internal linking PIE, test them too. + buildmodes = append(buildmodes, "pie") default: t.Skipf("trampoline insertion is not implemented on %s", runtime.GOARCH) } @@ -661,18 +665,20 @@ func TestTrampoline(t *testing.T) { } exe := filepath.Join(tmpdir, "hello.exe") - cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-debugtramp=2", "-o", exe, src) - out, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf("build failed: %v\n%s", err, out) - } - cmd = exec.Command(exe) - out, err = cmd.CombinedOutput() - if err != nil { - t.Errorf("executable failed to run: %v\n%s", err, out) - } - if string(out) != "hello\n" { - t.Errorf("unexpected output:\n%s", out) + for _, mode := range buildmodes { + cmd := exec.Command(testenv.GoToolPath(t), "build", "-buildmode="+mode, "-ldflags=-debugtramp=2", "-o", exe, src) + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("build (%s) failed: %v\n%s", mode, err, out) + } + cmd = exec.Command(exe) + out, err = cmd.CombinedOutput() + if err != nil { + t.Errorf("executable failed to run (%s): %v\n%s", mode, err, out) + } + if string(out) != "hello\n" { + t.Errorf("unexpected output (%s):\n%s", mode, out) + } } } @@ -693,8 +699,12 @@ func TestTrampolineCgo(t *testing.T) { // For stress test, we set -debugtramp=2 flag, which sets a very low // threshold for trampoline generation, and essentially all cross-package // calls will use trampolines. + buildmodes := []string{"default"} switch runtime.GOARCH { - case "arm", "arm64", "ppc64", "ppc64le": + case "arm", "arm64", "ppc64": + case "ppc64le": + // Trampolines are generated differently when internal linking PIE, test them too. + buildmodes = append(buildmodes, "pie") default: t.Skipf("trampoline insertion is not implemented on %s", runtime.GOARCH) } @@ -713,37 +723,39 @@ func TestTrampolineCgo(t *testing.T) { } exe := filepath.Join(tmpdir, "hello.exe") - cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-debugtramp=2", "-o", exe, src) - out, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf("build failed: %v\n%s", err, out) - } - cmd = exec.Command(exe) - out, err = cmd.CombinedOutput() - if err != nil { - t.Errorf("executable failed to run: %v\n%s", err, out) - } - if string(out) != "hello\n" && string(out) != "hello\r\n" { - t.Errorf("unexpected output:\n%s", out) - } + for _, mode := range buildmodes { + cmd := exec.Command(testenv.GoToolPath(t), "build", "-buildmode="+mode, "-ldflags=-debugtramp=2", "-o", exe, src) + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("build (%s) failed: %v\n%s", mode, err, out) + } + cmd = exec.Command(exe) + out, err = cmd.CombinedOutput() + if err != nil { + t.Errorf("executable failed to run (%s): %v\n%s", mode, err, out) + } + if string(out) != "hello\n" && string(out) != "hello\r\n" { + t.Errorf("unexpected output (%s):\n%s", mode, out) + } - // Test internal linking mode. + // Test internal linking mode. - if runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || (runtime.GOARCH == "arm64" && runtime.GOOS == "windows") || !testenv.CanInternalLink() { - return // internal linking cgo is not supported - } - cmd = exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-debugtramp=2 -linkmode=internal", "-o", exe, src) - out, err = cmd.CombinedOutput() - if err != nil { - t.Fatalf("build failed: %v\n%s", err, out) - } - cmd = exec.Command(exe) - out, err = cmd.CombinedOutput() - if err != nil { - t.Errorf("executable failed to run: %v\n%s", err, out) - } - if string(out) != "hello\n" && string(out) != "hello\r\n" { - t.Errorf("unexpected output:\n%s", out) + if runtime.GOARCH == "ppc64" || (runtime.GOARCH == "arm64" && runtime.GOOS == "windows") || !testenv.CanInternalLink() { + return // internal linking cgo is not supported + } + cmd = exec.Command(testenv.GoToolPath(t), "build", "-buildmode="+mode, "-ldflags=-debugtramp=2 -linkmode=internal", "-o", exe, src) + out, err = cmd.CombinedOutput() + if err != nil { + t.Fatalf("build (%s) failed: %v\n%s", mode, err, out) + } + cmd = exec.Command(exe) + out, err = cmd.CombinedOutput() + if err != nil { + t.Errorf("executable failed to run (%s): %v\n%s", mode, err, out) + } + if string(out) != "hello\n" && string(out) != "hello\r\n" { + t.Errorf("unexpected output (%s):\n%s", mode, out) + } } } diff --git a/src/cmd/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go index ff4316103083ac6d35f3d47b13c46f43863b849b..f5743970be41ca419511ea1fb4ed0d26aae7ffe5 100644 --- a/src/cmd/objdump/objdump_test.go +++ b/src/cmd/objdump/objdump_test.go @@ -102,7 +102,7 @@ var ppcNeed = []string{ var ppcGnuNeed = []string{ "mflr", "lbz", - "cmpw", + "beq", } func mustHaveDisasm(t *testing.T) { diff --git a/src/cmd/pprof/pprof.go b/src/cmd/pprof/pprof.go index e72c765adc30515d06e44eb5d81765f964a012e7..c073c964b42af0b5060e92ee74cc7204182dab9e 100644 --- a/src/cmd/pprof/pprof.go +++ b/src/cmd/pprof/pprof.go @@ -149,7 +149,7 @@ type objTool struct { disasmCache map[string]*objfile.Disasm } -func (*objTool) Open(name string, start, limit, offset uint64) (driver.ObjFile, error) { +func (*objTool) Open(name string, start, limit, offset uint64, relocationSymbol string) (driver.ObjFile, error) { of, err := objfile.Open(name) if err != nil { return nil, err diff --git a/src/cmd/vendor/github.com/google/pprof/driver/driver.go b/src/cmd/vendor/github.com/google/pprof/driver/driver.go index fc05f919baf7ae940be7b8c36a094b8810ee8be1..5a8222f70ac69fde701e4810a91f65e58a5ec201 100644 --- a/src/cmd/vendor/github.com/google/pprof/driver/driver.go +++ b/src/cmd/vendor/github.com/google/pprof/driver/driver.go @@ -137,8 +137,10 @@ type MappingSources map[string][]struct { type ObjTool interface { // Open opens the named object file. If the object is a shared // library, start/limit/offset are the addresses where it is mapped - // into memory in the address space being inspected. - Open(file string, start, limit, offset uint64) (ObjFile, error) + // into memory in the address space being inspected. If the object + // is a linux kernel, relocationSymbol is the name of the symbol + // corresponding to the start address. + Open(file string, start, limit, offset uint64, relocationSymbol string) (ObjFile, error) // Disasm disassembles the named object file, starting at // the start address and stopping at (before) the end address. @@ -232,8 +234,8 @@ type internalObjTool struct { ObjTool } -func (o *internalObjTool) Open(file string, start, limit, offset uint64) (plugin.ObjFile, error) { - f, err := o.ObjTool.Open(file, start, limit, offset) +func (o *internalObjTool) Open(file string, start, limit, offset uint64, relocationSymbol string) (plugin.ObjFile, error) { + f, err := o.ObjTool.Open(file, start, limit, offset, relocationSymbol) if err != nil { return nil, err } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils.go b/src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils.go index e920eeb2fa204331ec562b24e943e84a54a31df2..efa9167af7d643fb26ae6c6a1a16e6dbaa448ded 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils.go @@ -284,7 +284,7 @@ func (bu *Binutils) Disasm(file string, start, end uint64, intelSyntax bool) ([] } // Open satisfies the plugin.ObjTool interface. -func (bu *Binutils) Open(name string, start, limit, offset uint64) (plugin.ObjFile, error) { +func (bu *Binutils) Open(name string, start, limit, offset uint64, relocationSymbol string) (plugin.ObjFile, error) { b := bu.get() // Make sure file is a supported executable. @@ -316,7 +316,7 @@ func (bu *Binutils) Open(name string, start, limit, offset uint64) (plugin.ObjFi // Match against supported file types. if elfMagic == elf.ELFMAG { - f, err := b.openELF(name, start, limit, offset) + f, err := b.openELF(name, start, limit, offset, relocationSymbol) if err != nil { return nil, fmt.Errorf("error reading ELF file %s: %v", name, err) } @@ -425,7 +425,7 @@ func (b *binrep) openMachO(name string, start, limit, offset uint64) (plugin.Obj return b.openMachOCommon(name, of, start, limit, offset) } -func (b *binrep) openELF(name string, start, limit, offset uint64) (plugin.ObjFile, error) { +func (b *binrep) openELF(name string, start, limit, offset uint64, relocationSymbol string) (plugin.ObjFile, error) { ef, err := elfOpen(name) if err != nil { return nil, fmt.Errorf("error parsing %s: %v", name, err) @@ -440,8 +440,8 @@ func (b *binrep) openELF(name string, start, limit, offset uint64) (plugin.ObjFi } var ( - stextOffset *uint64 - pageAligned = func(addr uint64) bool { return addr%4096 == 0 } + kernelOffset *uint64 + pageAligned = func(addr uint64) bool { return addr%4096 == 0 } ) if strings.Contains(name, "vmlinux") || !pageAligned(start) || !pageAligned(limit) || !pageAligned(offset) { // Reading all Symbols is expensive, and we only rarely need it so @@ -455,10 +455,18 @@ func (b *binrep) openELF(name string, start, limit, offset uint64) (plugin.ObjFi if err != nil && err != elf.ErrNoSymbols { return nil, err } + + // The kernel relocation symbol (the mapping start address) can be either + // _text or _stext. When profiles are generated by `perf`, which one was used is + // distinguished by the mapping name for the kernel image: + // '[kernel.kallsyms]_text' or '[kernel.kallsyms]_stext', respectively. If we haven't + // been able to parse it from the mapping, we default to _stext. + if relocationSymbol == "" { + relocationSymbol = "_stext" + } for _, s := range symbols { - if s.Name == "_stext" { - // The kernel may use _stext as the mapping start address. - stextOffset = &s.Value + if s.Name == relocationSymbol { + kernelOffset = &s.Value break } } @@ -469,7 +477,7 @@ func (b *binrep) openELF(name string, start, limit, offset uint64) (plugin.ObjFi // value until we have a sample address for this mapping, so that we can // correctly identify the associated program segment that is needed to compute // the base. - if _, err := elfexec.GetBase(&ef.FileHeader, elfexec.FindTextProgHeader(ef), stextOffset, start, limit, offset); err != nil { + if _, err := elfexec.GetBase(&ef.FileHeader, elfexec.FindTextProgHeader(ef), kernelOffset, start, limit, offset); err != nil { return nil, fmt.Errorf("could not identify base for %s: %v", name, err) } @@ -478,14 +486,14 @@ func (b *binrep) openELF(name string, start, limit, offset uint64) (plugin.ObjFi b: b, name: name, buildID: buildID, - m: &elfMapping{start: start, limit: limit, offset: offset, stextOffset: stextOffset}, + m: &elfMapping{start: start, limit: limit, offset: offset, kernelOffset: kernelOffset}, }}, nil } return &fileAddr2Line{file: file{ b: b, name: name, buildID: buildID, - m: &elfMapping{start: start, limit: limit, offset: offset, stextOffset: stextOffset}, + m: &elfMapping{start: start, limit: limit, offset: offset, kernelOffset: kernelOffset}, }}, nil } @@ -521,8 +529,8 @@ func (b *binrep) openPE(name string, start, limit, offset uint64) (plugin.ObjFil type elfMapping struct { // Runtime mapping parameters. start, limit, offset uint64 - // Offset of _stext symbol. Only defined for kernel images, nil otherwise. - stextOffset *uint64 + // Offset of kernel relocation symbol. Only defined for kernel images, nil otherwise. + kernelOffset *uint64 } // findProgramHeader returns the program segment that matches the current @@ -535,7 +543,7 @@ func (m *elfMapping) findProgramHeader(ef *elf.File, addr uint64) (*elf.ProgHead // it's a kernel / .ko module mapping, because with quipper address remapping // enabled, the address would be in the lower half of the address space. - if m.stextOffset != nil || m.start >= m.limit || m.limit >= (uint64(1)<<63) { + if m.kernelOffset != nil || m.start >= m.limit || m.limit >= (uint64(1)<<63) { // For the kernel, find the program segment that includes the .text section. return elfexec.FindTextProgHeader(ef), nil } @@ -601,7 +609,7 @@ func (f *file) computeBase(addr uint64) error { return fmt.Errorf("failed to find program header for file %q, ELF mapping %#v, address %x: %v", f.name, *f.m, addr, err) } - base, err := elfexec.GetBase(&ef.FileHeader, ph, f.m.stextOffset, f.m.start, f.m.limit, f.m.offset) + base, err := elfexec.GetBase(&ef.FileHeader, ph, f.m.kernelOffset, f.m.start, f.m.limit, f.m.offset) if err != nil { return err } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go index 492400c5f3733dce70edf803df196910df508089..237cc332338fa91968b80226480aac4626550165 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go @@ -98,7 +98,7 @@ func parseFlags(o *plugin.Options) (*source, []string, error) { // Recognize first argument as an executable or buildid override. if len(args) > 1 { arg0 := args[0] - if file, err := o.Obj.Open(arg0, 0, ^uint64(0), 0); err == nil { + if file, err := o.Obj.Open(arg0, 0, ^uint64(0), 0, ""); err == nil { file.Close() execName = arg0 args = args[1:] diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch.go index b8a69e87fce753c0e8fa30214ee2e62ab409c4d5..0b361651bce400bc76d6ea0924ddda1abb744996 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch.go @@ -420,12 +420,14 @@ mapping: fileNames = append(fileNames, filepath.Join(path, m.File)) } for _, name := range fileNames { - if f, err := obj.Open(name, m.Start, m.Limit, m.Offset); err == nil { + if f, err := obj.Open(name, m.Start, m.Limit, m.Offset, m.KernelRelocationSymbol); err == nil { defer f.Close() fileBuildID := f.BuildID() if m.BuildID != "" && m.BuildID != fileBuildID { ui.PrintErr("Ignoring local file " + name + ": build-id mismatch (" + m.BuildID + " != " + fileBuildID + ")") } else { + // Explicitly do not update KernelRelocationSymbol -- + // the new local file name is most likely missing it. m.File = name continue mapping } @@ -449,6 +451,8 @@ mapping: if execName, buildID := s.ExecName, s.BuildID; execName != "" || buildID != "" { m := p.Mapping[0] if execName != "" { + // Explicitly do not update KernelRelocationSymbol -- + // the source override is most likely missing it. m.File = execName } if buildID != "" { diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/html/common.css b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/common.css new file mode 100644 index 0000000000000000000000000000000000000000..03755abc0e093f2fa7d0e53e18de7f1ee4271f8f --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/common.css @@ -0,0 +1,272 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} +html, body { + height: 100%; +} +body { + font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; + font-size: 13px; + line-height: 1.4; + display: flex; + flex-direction: column; +} +a { + color: #2a66d9; +} +.header { + display: flex; + align-items: center; + height: 44px; + min-height: 44px; + background-color: #eee; + color: #212121; + padding: 0 1rem; +} +.header > div { + margin: 0 0.125em; +} +.header .title h1 { + font-size: 1.75em; + margin-right: 1rem; + margin-bottom: 4px; +} +.header .title a { + color: #212121; + text-decoration: none; +} +.header .title a:hover { + text-decoration: underline; +} +.header .description { + width: 100%; + text-align: right; + white-space: nowrap; +} +@media screen and (max-width: 799px) { + .header input { + display: none; + } +} +#detailsbox { + display: none; + z-index: 1; + position: fixed; + top: 40px; + right: 20px; + background-color: #ffffff; + box-shadow: 0 1px 5px rgba(0,0,0,.3); + line-height: 24px; + padding: 1em; + text-align: left; +} +.header input { + background: white url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' style='pointer-events:none;display:block;width:100%25;height:100%25;fill:%23757575'%3E%3Cpath d='M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61.0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z'/%3E%3C/svg%3E") no-repeat 4px center/20px 20px; + border: 1px solid #d1d2d3; + border-radius: 2px 0 0 2px; + padding: 0.25em; + padding-left: 28px; + margin-left: 1em; + font-family: 'Roboto', 'Noto', sans-serif; + font-size: 1em; + line-height: 24px; + color: #212121; +} +.downArrow { + border-top: .36em solid #ccc; + border-left: .36em solid transparent; + border-right: .36em solid transparent; + margin-bottom: .05em; + margin-left: .5em; + transition: border-top-color 200ms; +} +.menu-item { + height: 100%; + text-transform: uppercase; + font-family: 'Roboto Medium', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; + position: relative; +} +.menu-item .menu-name:hover { + opacity: 0.75; +} +.menu-item .menu-name:hover .downArrow { + border-top-color: #666; +} +.menu-name { + height: 100%; + padding: 0 0.5em; + display: flex; + align-items: center; + justify-content: center; +} +.menu-name a { + text-decoration: none; + color: #212121; +} +.submenu { + display: none; + z-index: 1; + margin-top: -4px; + min-width: 10em; + position: absolute; + left: 0px; + background-color: white; + box-shadow: 0 1px 5px rgba(0,0,0,.3); + font-size: 100%; + text-transform: none; +} +.menu-item, .submenu { + user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -webkit-user-select: none; +} +.submenu hr { + border: 0; + border-top: 2px solid #eee; +} +.submenu a { + display: block; + padding: .5em 1em; + text-decoration: none; +} +.submenu a:hover, .submenu a.active { + color: white; + background-color: #6b82d6; +} +.submenu a.disabled { + color: gray; + pointer-events: none; +} +.menu-check-mark { + position: absolute; + left: 2px; +} +.menu-delete-btn { + position: absolute; + right: 2px; +} + +{{/* Used to disable events when a modal dialog is displayed */}} +#dialog-overlay { + display: none; + position: fixed; + left: 0px; + top: 0px; + width: 100%; + height: 100%; + background-color: rgba(1,1,1,0.1); +} + +.dialog { + {{/* Displayed centered horizontally near the top */}} + display: none; + position: fixed; + margin: 0px; + top: 60px; + left: 50%; + transform: translateX(-50%); + + z-index: 3; + font-size: 125%; + background-color: #ffffff; + box-shadow: 0 1px 5px rgba(0,0,0,.3); +} +.dialog-header { + font-size: 120%; + border-bottom: 1px solid #CCCCCC; + width: 100%; + text-align: center; + background: #EEEEEE; + user-select: none; +} +.dialog-footer { + border-top: 1px solid #CCCCCC; + width: 100%; + text-align: right; + padding: 10px; +} +.dialog-error { + margin: 10px; + color: red; +} +.dialog input { + margin: 10px; + font-size: inherit; +} +.dialog button { + margin-left: 10px; + font-size: inherit; +} +#save-dialog, #delete-dialog { + width: 50%; + max-width: 20em; +} +#delete-prompt { + padding: 10px; +} + +#content { + overflow-y: scroll; + padding: 1em; +} +#top { + overflow-y: scroll; +} +#graph { + overflow: hidden; +} +#graph svg { + width: 100%; + height: auto; + padding: 10px; +} +#content.source .filename { + margin-top: 0; + margin-bottom: 1em; + font-size: 120%; +} +#content.source pre { + margin-bottom: 3em; +} +table { + border-spacing: 0px; + width: 100%; + padding-bottom: 1em; + white-space: nowrap; +} +table thead { + font-family: 'Roboto Medium', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; +} +table tr th { + position: sticky; + top: 0; + background-color: #ddd; + text-align: right; + padding: .3em .5em; +} +table tr td { + padding: .3em .5em; + text-align: right; +} +#top table tr th:nth-child(6), +#top table tr th:nth-child(7), +#top table tr td:nth-child(6), +#top table tr td:nth-child(7) { + text-align: left; +} +#top table tr td:nth-child(6) { + width: 100%; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} +#flathdr1, #flathdr2, #cumhdr1, #cumhdr2, #namehdr { + cursor: ns-resize; +} +.hilite { + background-color: #ebf5fb; + font-weight: bold; +} diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/html/common.js b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/common.js new file mode 100644 index 0000000000000000000000000000000000000000..4fe3caa442a93289ffddc65a300ec4f8551955bd --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/common.js @@ -0,0 +1,693 @@ +// Make svg pannable and zoomable. +// Call clickHandler(t) if a click event is caught by the pan event handlers. +function initPanAndZoom(svg, clickHandler) { + 'use strict'; + + // Current mouse/touch handling mode + const IDLE = 0; + const MOUSEPAN = 1; + const TOUCHPAN = 2; + const TOUCHZOOM = 3; + let mode = IDLE; + + // State needed to implement zooming. + let currentScale = 1.0; + const initWidth = svg.viewBox.baseVal.width; + const initHeight = svg.viewBox.baseVal.height; + + // State needed to implement panning. + let panLastX = 0; // Last event X coordinate + let panLastY = 0; // Last event Y coordinate + let moved = false; // Have we seen significant movement + let touchid = null; // Current touch identifier + + // State needed for pinch zooming + let touchid2 = null; // Second id for pinch zooming + let initGap = 1.0; // Starting gap between two touches + let initScale = 1.0; // currentScale when pinch zoom started + let centerPoint = null; // Center point for scaling + + // Convert event coordinates to svg coordinates. + function toSvg(x, y) { + const p = svg.createSVGPoint(); + p.x = x; + p.y = y; + let m = svg.getCTM(); + if (m == null) m = svg.getScreenCTM(); // Firefox workaround. + return p.matrixTransform(m.inverse()); + } + + // Change the scaling for the svg to s, keeping the point denoted + // by u (in svg coordinates]) fixed at the same screen location. + function rescale(s, u) { + // Limit to a good range. + if (s < 0.2) s = 0.2; + if (s > 10.0) s = 10.0; + + currentScale = s; + + // svg.viewBox defines the visible portion of the user coordinate + // system. So to magnify by s, divide the visible portion by s, + // which will then be stretched to fit the viewport. + const vb = svg.viewBox; + const w1 = vb.baseVal.width; + const w2 = initWidth / s; + const h1 = vb.baseVal.height; + const h2 = initHeight / s; + vb.baseVal.width = w2; + vb.baseVal.height = h2; + + // We also want to adjust vb.baseVal.x so that u.x remains at same + // screen X coordinate. In other words, want to change it from x1 to x2 + // so that: + // (u.x - x1) / w1 = (u.x - x2) / w2 + // Simplifying that, we get + // (u.x - x1) * (w2 / w1) = u.x - x2 + // x2 = u.x - (u.x - x1) * (w2 / w1) + vb.baseVal.x = u.x - (u.x - vb.baseVal.x) * (w2 / w1); + vb.baseVal.y = u.y - (u.y - vb.baseVal.y) * (h2 / h1); + } + + function handleWheel(e) { + if (e.deltaY == 0) return; + // Change scale factor by 1.1 or 1/1.1 + rescale(currentScale * (e.deltaY < 0 ? 1.1 : (1/1.1)), + toSvg(e.offsetX, e.offsetY)); + } + + function setMode(m) { + mode = m; + touchid = null; + touchid2 = null; + } + + function panStart(x, y) { + moved = false; + panLastX = x; + panLastY = y; + } + + function panMove(x, y) { + let dx = x - panLastX; + let dy = y - panLastY; + if (Math.abs(dx) <= 2 && Math.abs(dy) <= 2) return; // Ignore tiny moves + + moved = true; + panLastX = x; + panLastY = y; + + // Firefox workaround: get dimensions from parentNode. + const swidth = svg.clientWidth || svg.parentNode.clientWidth; + const sheight = svg.clientHeight || svg.parentNode.clientHeight; + + // Convert deltas from screen space to svg space. + dx *= (svg.viewBox.baseVal.width / swidth); + dy *= (svg.viewBox.baseVal.height / sheight); + + svg.viewBox.baseVal.x -= dx; + svg.viewBox.baseVal.y -= dy; + } + + function handleScanStart(e) { + if (e.button != 0) return; // Do not catch right-clicks etc. + setMode(MOUSEPAN); + panStart(e.clientX, e.clientY); + e.preventDefault(); + svg.addEventListener('mousemove', handleScanMove); + } + + function handleScanMove(e) { + if (e.buttons == 0) { + // Missed an end event, perhaps because mouse moved outside window. + setMode(IDLE); + svg.removeEventListener('mousemove', handleScanMove); + return; + } + if (mode == MOUSEPAN) panMove(e.clientX, e.clientY); + } + + function handleScanEnd(e) { + if (mode == MOUSEPAN) panMove(e.clientX, e.clientY); + setMode(IDLE); + svg.removeEventListener('mousemove', handleScanMove); + if (!moved) clickHandler(e.target); + } + + // Find touch object with specified identifier. + function findTouch(tlist, id) { + for (const t of tlist) { + if (t.identifier == id) return t; + } + return null; + } + + // Return distance between two touch points + function touchGap(t1, t2) { + const dx = t1.clientX - t2.clientX; + const dy = t1.clientY - t2.clientY; + return Math.hypot(dx, dy); + } + + function handleTouchStart(e) { + if (mode == IDLE && e.changedTouches.length == 1) { + // Start touch based panning + const t = e.changedTouches[0]; + setMode(TOUCHPAN); + touchid = t.identifier; + panStart(t.clientX, t.clientY); + e.preventDefault(); + } else if (mode == TOUCHPAN && e.touches.length == 2) { + // Start pinch zooming + setMode(TOUCHZOOM); + const t1 = e.touches[0]; + const t2 = e.touches[1]; + touchid = t1.identifier; + touchid2 = t2.identifier; + initScale = currentScale; + initGap = touchGap(t1, t2); + centerPoint = toSvg((t1.clientX + t2.clientX) / 2, + (t1.clientY + t2.clientY) / 2); + e.preventDefault(); + } + } + + function handleTouchMove(e) { + if (mode == TOUCHPAN) { + const t = findTouch(e.changedTouches, touchid); + if (t == null) return; + if (e.touches.length != 1) { + setMode(IDLE); + return; + } + panMove(t.clientX, t.clientY); + e.preventDefault(); + } else if (mode == TOUCHZOOM) { + // Get two touches; new gap; rescale to ratio. + const t1 = findTouch(e.touches, touchid); + const t2 = findTouch(e.touches, touchid2); + if (t1 == null || t2 == null) return; + const gap = touchGap(t1, t2); + rescale(initScale * gap / initGap, centerPoint); + e.preventDefault(); + } + } + + function handleTouchEnd(e) { + if (mode == TOUCHPAN) { + const t = findTouch(e.changedTouches, touchid); + if (t == null) return; + panMove(t.clientX, t.clientY); + setMode(IDLE); + e.preventDefault(); + if (!moved) clickHandler(t.target); + } else if (mode == TOUCHZOOM) { + setMode(IDLE); + e.preventDefault(); + } + } + + svg.addEventListener('mousedown', handleScanStart); + svg.addEventListener('mouseup', handleScanEnd); + svg.addEventListener('touchstart', handleTouchStart); + svg.addEventListener('touchmove', handleTouchMove); + svg.addEventListener('touchend', handleTouchEnd); + svg.addEventListener('wheel', handleWheel, true); +} + +function initMenus() { + 'use strict'; + + let activeMenu = null; + let activeMenuHdr = null; + + function cancelActiveMenu() { + if (activeMenu == null) return; + activeMenu.style.display = 'none'; + activeMenu = null; + activeMenuHdr = null; + } + + // Set click handlers on every menu header. + for (const menu of document.getElementsByClassName('submenu')) { + const hdr = menu.parentElement; + if (hdr == null) return; + if (hdr.classList.contains('disabled')) return; + function showMenu(e) { + // menu is a child of hdr, so this event can fire for clicks + // inside menu. Ignore such clicks. + if (e.target.parentElement != hdr) return; + activeMenu = menu; + activeMenuHdr = hdr; + menu.style.display = 'block'; + } + hdr.addEventListener('mousedown', showMenu); + hdr.addEventListener('touchstart', showMenu); + } + + // If there is an active menu and a down event outside, retract the menu. + for (const t of ['mousedown', 'touchstart']) { + document.addEventListener(t, (e) => { + // Note: to avoid unnecessary flicker, if the down event is inside + // the active menu header, do not retract the menu. + if (activeMenuHdr != e.target.closest('.menu-item')) { + cancelActiveMenu(); + } + }, { passive: true, capture: true }); + } + + // If there is an active menu and an up event inside, retract the menu. + document.addEventListener('mouseup', (e) => { + if (activeMenu == e.target.closest('.submenu')) { + cancelActiveMenu(); + } + }, { passive: true, capture: true }); +} + +function sendURL(method, url, done) { + fetch(url.toString(), {method: method}) + .then((response) => { done(response.ok); }) + .catch((error) => { done(false); }); +} + +// Initialize handlers for saving/loading configurations. +function initConfigManager() { + 'use strict'; + + // Initialize various elements. + function elem(id) { + const result = document.getElementById(id); + if (!result) console.warn('element ' + id + ' not found'); + return result; + } + const overlay = elem('dialog-overlay'); + const saveDialog = elem('save-dialog'); + const saveInput = elem('save-name'); + const saveError = elem('save-error'); + const delDialog = elem('delete-dialog'); + const delPrompt = elem('delete-prompt'); + const delError = elem('delete-error'); + + let currentDialog = null; + let currentDeleteTarget = null; + + function showDialog(dialog) { + if (currentDialog != null) { + overlay.style.display = 'none'; + currentDialog.style.display = 'none'; + } + currentDialog = dialog; + if (dialog != null) { + overlay.style.display = 'block'; + dialog.style.display = 'block'; + } + } + + function cancelDialog(e) { + showDialog(null); + } + + // Show dialog for saving the current config. + function showSaveDialog(e) { + saveError.innerText = ''; + showDialog(saveDialog); + saveInput.focus(); + } + + // Commit save config. + function commitSave(e) { + const name = saveInput.value; + const url = new URL(document.URL); + // Set path relative to existing path. + url.pathname = new URL('./saveconfig', document.URL).pathname; + url.searchParams.set('config', name); + saveError.innerText = ''; + sendURL('POST', url, (ok) => { + if (!ok) { + saveError.innerText = 'Save failed'; + } else { + showDialog(null); + location.reload(); // Reload to show updated config menu + } + }); + } + + function handleSaveInputKey(e) { + if (e.key === 'Enter') commitSave(e); + } + + function deleteConfig(e, elem) { + e.preventDefault(); + const config = elem.dataset.config; + delPrompt.innerText = 'Delete ' + config + '?'; + currentDeleteTarget = elem; + showDialog(delDialog); + } + + function commitDelete(e, elem) { + if (!currentDeleteTarget) return; + const config = currentDeleteTarget.dataset.config; + const url = new URL('./deleteconfig', document.URL); + url.searchParams.set('config', config); + delError.innerText = ''; + sendURL('DELETE', url, (ok) => { + if (!ok) { + delError.innerText = 'Delete failed'; + return; + } + showDialog(null); + // Remove menu entry for this config. + if (currentDeleteTarget && currentDeleteTarget.parentElement) { + currentDeleteTarget.parentElement.remove(); + } + }); + } + + // Bind event on elem to fn. + function bind(event, elem, fn) { + if (elem == null) return; + elem.addEventListener(event, fn); + if (event == 'click') { + // Also enable via touch. + elem.addEventListener('touchstart', fn); + } + } + + bind('click', elem('save-config'), showSaveDialog); + bind('click', elem('save-cancel'), cancelDialog); + bind('click', elem('save-confirm'), commitSave); + bind('keydown', saveInput, handleSaveInputKey); + + bind('click', elem('delete-cancel'), cancelDialog); + bind('click', elem('delete-confirm'), commitDelete); + + // Activate deletion button for all config entries in menu. + for (const del of Array.from(document.getElementsByClassName('menu-delete-btn'))) { + bind('click', del, (e) => { + deleteConfig(e, del); + }); + } +} + +function viewer(baseUrl, nodes) { + 'use strict'; + + // Elements + const search = document.getElementById('search'); + const graph0 = document.getElementById('graph0'); + const svg = (graph0 == null ? null : graph0.parentElement); + const toptable = document.getElementById('toptable'); + + let regexpActive = false; + let selected = new Map(); + let origFill = new Map(); + let searchAlarm = null; + let buttonsEnabled = true; + + function handleDetails(e) { + e.preventDefault(); + const detailsText = document.getElementById('detailsbox'); + if (detailsText != null) { + if (detailsText.style.display === 'block') { + detailsText.style.display = 'none'; + } else { + detailsText.style.display = 'block'; + } + } + } + + function handleKey(e) { + if (e.keyCode != 13) return; + setHrefParams(window.location, function (params) { + params.set('f', search.value); + }); + e.preventDefault(); + } + + function handleSearch() { + // Delay expensive processing so a flurry of key strokes is handled once. + if (searchAlarm != null) { + clearTimeout(searchAlarm); + } + searchAlarm = setTimeout(selectMatching, 300); + + regexpActive = true; + updateButtons(); + } + + function selectMatching() { + searchAlarm = null; + let re = null; + if (search.value != '') { + try { + re = new RegExp(search.value); + } catch (e) { + // TODO: Display error state in search box + return; + } + } + + function match(text) { + return re != null && re.test(text); + } + + // drop currently selected items that do not match re. + selected.forEach(function(v, n) { + if (!match(nodes[n])) { + unselect(n, document.getElementById('node' + n)); + } + }) + + // add matching items that are not currently selected. + if (nodes) { + for (let n = 0; n < nodes.length; n++) { + if (!selected.has(n) && match(nodes[n])) { + select(n, document.getElementById('node' + n)); + } + } + } + + updateButtons(); + } + + function toggleSvgSelect(elem) { + // Walk up to immediate child of graph0 + while (elem != null && elem.parentElement != graph0) { + elem = elem.parentElement; + } + if (!elem) return; + + // Disable regexp mode. + regexpActive = false; + + const n = nodeId(elem); + if (n < 0) return; + if (selected.has(n)) { + unselect(n, elem); + } else { + select(n, elem); + } + updateButtons(); + } + + function unselect(n, elem) { + if (elem == null) return; + selected.delete(n); + setBackground(elem, false); + } + + function select(n, elem) { + if (elem == null) return; + selected.set(n, true); + setBackground(elem, true); + } + + function nodeId(elem) { + const id = elem.id; + if (!id) return -1; + if (!id.startsWith('node')) return -1; + const n = parseInt(id.slice(4), 10); + if (isNaN(n)) return -1; + if (n < 0 || n >= nodes.length) return -1; + return n; + } + + function setBackground(elem, set) { + // Handle table row highlighting. + if (elem.nodeName == 'TR') { + elem.classList.toggle('hilite', set); + return; + } + + // Handle svg element highlighting. + const p = findPolygon(elem); + if (p != null) { + if (set) { + origFill.set(p, p.style.fill); + p.style.fill = '#ccccff'; + } else if (origFill.has(p)) { + p.style.fill = origFill.get(p); + } + } + } + + function findPolygon(elem) { + if (elem.localName == 'polygon') return elem; + for (const c of elem.children) { + const p = findPolygon(c); + if (p != null) return p; + } + return null; + } + + // convert a string to a regexp that matches that string. + function quotemeta(str) { + return str.replace(/([\\\.?+*\[\](){}|^$])/g, '\\$1'); + } + + function setSampleIndexLink(id) { + const elem = document.getElementById(id); + if (elem != null) { + setHrefParams(elem, function (params) { + params.set("si", id); + }); + } + } + + // Update id's href to reflect current selection whenever it is + // liable to be followed. + function makeSearchLinkDynamic(id) { + const elem = document.getElementById(id); + if (elem == null) return; + + // Most links copy current selection into the 'f' parameter, + // but Refine menu links are different. + let param = 'f'; + if (id == 'ignore') param = 'i'; + if (id == 'hide') param = 'h'; + if (id == 'show') param = 's'; + if (id == 'show-from') param = 'sf'; + + // We update on mouseenter so middle-click/right-click work properly. + elem.addEventListener('mouseenter', updater); + elem.addEventListener('touchstart', updater); + + function updater() { + // The selection can be in one of two modes: regexp-based or + // list-based. Construct regular expression depending on mode. + let re = regexpActive + ? search.value + : Array.from(selected.keys()).map(key => quotemeta(nodes[key])).join('|'); + + setHrefParams(elem, function (params) { + if (re != '') { + // For focus/show/show-from, forget old parameter. For others, add to re. + if (param != 'f' && param != 's' && param != 'sf' && params.has(param)) { + const old = params.get(param); + if (old != '') { + re += '|' + old; + } + } + params.set(param, re); + } else { + params.delete(param); + } + }); + } + } + + function setHrefParams(elem, paramSetter) { + let url = new URL(elem.href); + url.hash = ''; + + // Copy params from this page's URL. + const params = url.searchParams; + for (const p of new URLSearchParams(window.location.search)) { + params.set(p[0], p[1]); + } + + // Give the params to the setter to modify. + paramSetter(params); + + elem.href = url.toString(); + } + + function handleTopClick(e) { + // Walk back until we find TR and then get the Name column (index 5) + let elem = e.target; + while (elem != null && elem.nodeName != 'TR') { + elem = elem.parentElement; + } + if (elem == null || elem.children.length < 6) return; + + e.preventDefault(); + const tr = elem; + const td = elem.children[5]; + if (td.nodeName != 'TD') return; + const name = td.innerText; + const index = nodes.indexOf(name); + if (index < 0) return; + + // Disable regexp mode. + regexpActive = false; + + if (selected.has(index)) { + unselect(index, elem); + } else { + select(index, elem); + } + updateButtons(); + } + + function updateButtons() { + const enable = (search.value != '' || selected.size != 0); + if (buttonsEnabled == enable) return; + buttonsEnabled = enable; + for (const id of ['focus', 'ignore', 'hide', 'show', 'show-from']) { + const link = document.getElementById(id); + if (link != null) { + link.classList.toggle('disabled', !enable); + } + } + } + + // Initialize button states + updateButtons(); + + // Setup event handlers + initMenus(); + if (svg != null) { + initPanAndZoom(svg, toggleSvgSelect); + } + if (toptable != null) { + toptable.addEventListener('mousedown', handleTopClick); + toptable.addEventListener('touchstart', handleTopClick); + } + + const ids = ['topbtn', 'graphbtn', 'flamegraph', 'peek', 'list', 'disasm', + 'focus', 'ignore', 'hide', 'show', 'show-from']; + ids.forEach(makeSearchLinkDynamic); + + const sampleIDs = [{{range .SampleTypes}}'{{.}}', {{end}}]; + sampleIDs.forEach(setSampleIndexLink); + + // Bind action to button with specified id. + function addAction(id, action) { + const btn = document.getElementById(id); + if (btn != null) { + btn.addEventListener('click', action); + btn.addEventListener('touchstart', action); + } + } + + addAction('details', handleDetails); + initConfigManager(); + + search.addEventListener('input', handleSearch); + search.addEventListener('keydown', handleKey); + + // Give initial focus to main container so it can be scrolled using keys. + const main = document.getElementById('bodycontainer'); + if (main) { + main.focus(); + } +} diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/html/flamegraph.html b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/flamegraph.html new file mode 100644 index 0000000000000000000000000000000000000000..9866755bcd7e9ac3ecd4078fb4363163af810c03 --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/flamegraph.html @@ -0,0 +1,103 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>{{.Title}}</title> + {{template "css" .}} + <style type="text/css">{{template "d3flamegraphcss" .}}</style> + <style type="text/css"> + .flamegraph-content { + width: 90%; + min-width: 80%; + margin-left: 5%; + } + .flamegraph-details { + height: 1.2em; + width: 90%; + min-width: 90%; + margin-left: 5%; + padding: 15px 0 35px; + } + </style> +</head> +<body> + {{template "header" .}} + <div id="bodycontainer"> + <div id="flamegraphdetails" class="flamegraph-details"></div> + <div class="flamegraph-content"> + <div id="chart"></div> + </div> + </div> + {{template "script" .}} + <script>viewer(new URL(window.location.href), {{.Nodes}});</script> + <script>{{template "d3flamegraphscript" .}}</script> + <script> + {{- /* Deserialize as JSON instead of a JS object literal because the browser's + JSON parser can handle larger payloads than its JS parser. */ -}} + var data = JSON.parse("{{.FlameGraph}}"); + + var width = document.getElementById('chart').clientWidth; + + var flameGraph = flamegraph() + .width(width) + .cellHeight(18) + .minFrameSize(1) + .transitionDuration(750) + .inverted(true) + .sort(true) + .title('') + .tooltip(false) + .setDetailsElement(document.getElementById('flamegraphdetails')); + + // <full name> (percentage, value) + flameGraph.label((d) => d.data.f + ' (' + d.data.p + ', ' + d.data.l + ')'); + + flameGraph.setColorHue('warm'); + + select('#chart') + .datum(data) + .call(flameGraph); + + function clear() { + flameGraph.clear(); + } + + function resetZoom() { + flameGraph.resetZoom(); + } + + window.addEventListener('resize', function() { + var width = document.getElementById('chart').clientWidth; + var graphs = document.getElementsByClassName('d3-flame-graph'); + if (graphs.length > 0) { + graphs[0].setAttribute('width', width); + } + flameGraph.width(width); + flameGraph.resetZoom(); + }, true); + + var search = document.getElementById('search'); + var searchAlarm = null; + + function selectMatching() { + searchAlarm = null; + + if (search.value != '') { + flameGraph.search(search.value); + } else { + flameGraph.clear(); + } + } + + function handleSearch() { + // Delay expensive processing so a flurry of key strokes is handled once. + if (searchAlarm != null) { + clearTimeout(searchAlarm); + } + searchAlarm = setTimeout(selectMatching, 300); + } + + search.addEventListener('input', handleSearch); + </script> +</body> +</html> diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/html/graph.html b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/graph.html new file mode 100644 index 0000000000000000000000000000000000000000..a113549fc4c7a82ca073ef9083f45856016f4cdc --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/graph.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>{{.Title}}</title> + {{template "css" .}} +</head> +<body> + {{template "header" .}} + <div id="graph"> + {{.HTMLBody}} + </div> + {{template "script" .}} + <script>viewer(new URL(window.location.href), {{.Nodes}});</script> +</body> +</html> diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/html/header.html b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/header.html new file mode 100644 index 0000000000000000000000000000000000000000..66cabbbaa4be08f024dc30c7940744ae46303d19 --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/header.html @@ -0,0 +1,113 @@ +<div class="header"> + <div class="title"> + <h1><a href="./">pprof</a></h1> + </div> + + <div id="view" class="menu-item"> + <div class="menu-name"> + View + <i class="downArrow"></i> + </div> + <div class="submenu"> + <a title="{{.Help.top}}" href="./top" id="topbtn">Top</a> + <a title="{{.Help.graph}}" href="./" id="graphbtn">Graph</a> + <a title="{{.Help.flamegraph}}" href="./flamegraph" id="flamegraph">Flame Graph</a> + <a title="{{.Help.peek}}" href="./peek" id="peek">Peek</a> + <a title="{{.Help.list}}" href="./source" id="list">Source</a> + <a title="{{.Help.disasm}}" href="./disasm" id="disasm">Disassemble</a> + </div> + </div> + + {{$sampleLen := len .SampleTypes}} + {{if gt $sampleLen 1}} + <div id="sample" class="menu-item"> + <div class="menu-name"> + Sample + <i class="downArrow"></i> + </div> + <div class="submenu"> + {{range .SampleTypes}} + <a href="?si={{.}}" id="{{.}}">{{.}}</a> + {{end}} + </div> + </div> + {{end}} + + <div id="refine" class="menu-item"> + <div class="menu-name"> + Refine + <i class="downArrow"></i> + </div> + <div class="submenu"> + <a title="{{.Help.focus}}" href="?" id="focus">Focus</a> + <a title="{{.Help.ignore}}" href="?" id="ignore">Ignore</a> + <a title="{{.Help.hide}}" href="?" id="hide">Hide</a> + <a title="{{.Help.show}}" href="?" id="show">Show</a> + <a title="{{.Help.show_from}}" href="?" id="show-from">Show from</a> + <hr> + <a title="{{.Help.reset}}" href="?">Reset</a> + </div> + </div> + + <div id="config" class="menu-item"> + <div class="menu-name"> + Config + <i class="downArrow"></i> + </div> + <div class="submenu"> + <a title="{{.Help.save_config}}" id="save-config">Save as ...</a> + <hr> + {{range .Configs}} + <a href="{{.URL}}"> + {{if .Current}}<span class="menu-check-mark">✓</span>{{end}} + {{.Name}} + {{if .UserConfig}}<span class="menu-delete-btn" data-config={{.Name}}>🗙</span>{{end}} + </a> + {{end}} + </div> + </div> + + <div id="download" class="menu-item"> + <div class="menu-name"> + <a href="./download">Download</a> + </div> + </div> + + <div> + <input id="search" type="text" placeholder="Search regexp" autocomplete="off" autocapitalize="none" size=40> + </div> + + <div class="description"> + <a title="{{.Help.details}}" href="#" id="details">{{.Title}}</a> + <div id="detailsbox"> + {{range .Legend}}<div>{{.}}</div>{{end}} + </div> + </div> +</div> + +<div id="dialog-overlay"></div> + +<div class="dialog" id="save-dialog"> + <div class="dialog-header">Save options as</div> + <datalist id="config-list"> + {{range .Configs}}{{if .UserConfig}}<option value="{{.Name}}" />{{end}}{{end}} + </datalist> + <input id="save-name" type="text" list="config-list" placeholder="New config" /> + <div class="dialog-footer"> + <span class="dialog-error" id="save-error"></span> + <button id="save-cancel">Cancel</button> + <button id="save-confirm">Save</button> + </div> +</div> + +<div class="dialog" id="delete-dialog"> + <div class="dialog-header" id="delete-dialog-title">Delete config</div> + <div id="delete-prompt"></div> + <div class="dialog-footer"> + <span class="dialog-error" id="delete-error"></span> + <button id="delete-cancel">Cancel</button> + <button id="delete-confirm">Delete</button> + </div> +</div> + +<div id="errors">{{range .Errors}}<div>{{.}}</div>{{end}}</div> diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/html/plaintext.html b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/plaintext.html new file mode 100644 index 0000000000000000000000000000000000000000..9791cc7718981c238224b2fb3459e5df813611f0 --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/plaintext.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>{{.Title}}</title> + {{template "css" .}} +</head> +<body> + {{template "header" .}} + <div id="content"> + <pre> + {{.TextBody}} + </pre> + </div> + {{template "script" .}} + <script>viewer(new URL(window.location.href), null);</script> +</body> +</html> diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/html/source.html b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/source.html new file mode 100644 index 0000000000000000000000000000000000000000..3212bee4a084d4a2d402719dc888c87e0b4cea99 --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/source.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>{{.Title}}</title> + {{template "css" .}} + {{template "weblistcss" .}} + {{template "weblistjs" .}} +</head> +<body> + {{template "header" .}} + <div id="content" class="source"> + {{.HTMLBody}} + </div> + {{template "script" .}} + <script>viewer(new URL(window.location.href), null);</script> +</body> +</html> diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/html/top.html b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/top.html new file mode 100644 index 0000000000000000000000000000000000000000..86d9fcbdb0d62f2cb97d280d26e7f65fde10dc02 --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/html/top.html @@ -0,0 +1,114 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>{{.Title}}</title> + {{template "css" .}} + <style type="text/css"> + </style> +</head> +<body> + {{template "header" .}} + <div id="top"> + <table id="toptable"> + <thead> + <tr> + <th id="flathdr1">Flat</th> + <th id="flathdr2">Flat%</th> + <th>Sum%</th> + <th id="cumhdr1">Cum</th> + <th id="cumhdr2">Cum%</th> + <th id="namehdr">Name</th> + <th>Inlined?</th> + </tr> + </thead> + <tbody id="rows"></tbody> + </table> + </div> + {{template "script" .}} + <script> + function makeTopTable(total, entries) { + const rows = document.getElementById('rows'); + if (rows == null) return; + + // Store initial index in each entry so we have stable node ids for selection. + for (let i = 0; i < entries.length; i++) { + entries[i].Id = 'node' + i; + } + + // Which column are we currently sorted by and in what order? + let currentColumn = ''; + let descending = false; + sortBy('Flat'); + + function sortBy(column) { + // Update sort criteria + if (column == currentColumn) { + descending = !descending; // Reverse order + } else { + currentColumn = column; + descending = (column != 'Name'); + } + + // Sort according to current criteria. + function cmp(a, b) { + const av = a[currentColumn]; + const bv = b[currentColumn]; + if (av < bv) return -1; + if (av > bv) return +1; + return 0; + } + entries.sort(cmp); + if (descending) entries.reverse(); + + function addCell(tr, val) { + const td = document.createElement('td'); + td.textContent = val; + tr.appendChild(td); + } + + function percent(v) { + return (v * 100.0 / total).toFixed(2) + '%'; + } + + // Generate rows + const fragment = document.createDocumentFragment(); + let sum = 0; + for (const row of entries) { + const tr = document.createElement('tr'); + tr.id = row.Id; + sum += row.Flat; + addCell(tr, row.FlatFormat); + addCell(tr, percent(row.Flat)); + addCell(tr, percent(sum)); + addCell(tr, row.CumFormat); + addCell(tr, percent(row.Cum)); + addCell(tr, row.Name); + addCell(tr, row.InlineLabel); + fragment.appendChild(tr); + } + + rows.textContent = ''; // Remove old rows + rows.appendChild(fragment); + } + + // Make different column headers trigger sorting. + function bindSort(id, column) { + const hdr = document.getElementById(id); + if (hdr == null) return; + const fn = function() { sortBy(column) }; + hdr.addEventListener('click', fn); + hdr.addEventListener('touch', fn); + } + bindSort('flathdr1', 'Flat'); + bindSort('flathdr2', 'Flat'); + bindSort('cumhdr1', 'Cum'); + bindSort('cumhdr2', 'Cum'); + bindSort('namehdr', 'Name'); + } + + viewer(new URL(window.location.href), {{.Nodes}}); + makeTopTable({{.Total}}, {{.Top}}); + </script> +</body> +</html> diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/settings.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/settings.go index f72314b1857ddbcb09dd8e81675288f3a575e3e3..1e9154c5f533690a90727f76c13cc14fea0f3d38 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/settings.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/settings.go @@ -79,7 +79,7 @@ type configMenuEntry struct { } // configMenu returns a list of items to add to a menu in the web UI. -func configMenu(fname string, url url.URL) []configMenuEntry { +func configMenu(fname string, u url.URL) []configMenuEntry { // Start with system configs. configs := []namedConfig{{Name: "Default", config: defaultConfig()}} if settings, err := readSettings(fname); err == nil { @@ -91,13 +91,15 @@ func configMenu(fname string, url url.URL) []configMenuEntry { result := make([]configMenuEntry, len(configs)) lastMatch := -1 for i, cfg := range configs { - dst, changed := cfg.config.makeURL(url) + dst, changed := cfg.config.makeURL(u) if !changed { lastMatch = i } + // Use a relative URL to work in presence of stripping/redirects in webui.go. + rel := &url.URL{RawQuery: dst.RawQuery, ForceQuery: true} result[i] = configMenuEntry{ Name: cfg.Name, - URL: dst.String(), + URL: rel.String(), UserConfig: (i != 0), } } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/tagroot.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/tagroot.go index c2cdfa455eeaf54e8063d7cfb1a0c5272ecdd727..c43d5999821f3aee234355994636d215117f2968 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/tagroot.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/tagroot.go @@ -113,12 +113,17 @@ func formatLabelValues(s *profile.Sample, k string, outputUnit string) []string values = append(values, s.Label[k]...) numLabels := s.NumLabel[k] numUnits := s.NumUnit[k] - if len(numLabels) != len(numUnits) { + if len(numLabels) != len(numUnits) && len(numUnits) != 0 { return values } for i, numLabel := range numLabels { - unit := numUnits[i] - values = append(values, measurement.ScaledLabel(numLabel, unit, outputUnit)) + var value string + if len(numUnits) != 0 { + value = measurement.ScaledLabel(numLabel, numUnits[i], outputUnit) + } else { + value = measurement.ScaledLabel(numLabel, "", "") + } + values = append(values, value) } return values } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/webhtml.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/webhtml.go index b9c73271b8c928783469546844e1b66b71144fd6..94f32e3755fc9bdcf400cc41f530d7a769315520 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/webhtml.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/webhtml.go @@ -15,1400 +15,54 @@ package driver import ( + "embed" + "fmt" "html/template" + "os" - "github.com/google/pprof/third_party/d3" "github.com/google/pprof/third_party/d3flamegraph" ) +//go:embed html +var embeddedFiles embed.FS + // addTemplates adds a set of template definitions to templates. func addTemplates(templates *template.Template) { - template.Must(templates.Parse(`{{define "d3script"}}` + d3.JSSource + `{{end}}`)) - template.Must(templates.Parse(`{{define "d3flamegraphscript"}}` + d3flamegraph.JSSource + `{{end}}`)) - template.Must(templates.Parse(`{{define "d3flamegraphcss"}}` + d3flamegraph.CSSSource + `{{end}}`)) - template.Must(templates.Parse(` -{{define "css"}} -<style type="text/css"> -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} -html, body { - height: 100%; -} -body { - font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; - font-size: 13px; - line-height: 1.4; - display: flex; - flex-direction: column; -} -a { - color: #2a66d9; -} -.header { - display: flex; - align-items: center; - height: 44px; - min-height: 44px; - background-color: #eee; - color: #212121; - padding: 0 1rem; -} -.header > div { - margin: 0 0.125em; -} -.header .title h1 { - font-size: 1.75em; - margin-right: 1rem; - margin-bottom: 4px; -} -.header .title a { - color: #212121; - text-decoration: none; -} -.header .title a:hover { - text-decoration: underline; -} -.header .description { - width: 100%; - text-align: right; - white-space: nowrap; -} -@media screen and (max-width: 799px) { - .header input { - display: none; - } -} -#detailsbox { - display: none; - z-index: 1; - position: fixed; - top: 40px; - right: 20px; - background-color: #ffffff; - box-shadow: 0 1px 5px rgba(0,0,0,.3); - line-height: 24px; - padding: 1em; - text-align: left; -} -.header input { - background: white url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' style='pointer-events:none;display:block;width:100%25;height:100%25;fill:%23757575'%3E%3Cpath d='M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61.0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z'/%3E%3C/svg%3E") no-repeat 4px center/20px 20px; - border: 1px solid #d1d2d3; - border-radius: 2px 0 0 2px; - padding: 0.25em; - padding-left: 28px; - margin-left: 1em; - font-family: 'Roboto', 'Noto', sans-serif; - font-size: 1em; - line-height: 24px; - color: #212121; -} -.downArrow { - border-top: .36em solid #ccc; - border-left: .36em solid transparent; - border-right: .36em solid transparent; - margin-bottom: .05em; - margin-left: .5em; - transition: border-top-color 200ms; -} -.menu-item { - height: 100%; - text-transform: uppercase; - font-family: 'Roboto Medium', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; - position: relative; -} -.menu-item .menu-name:hover { - opacity: 0.75; -} -.menu-item .menu-name:hover .downArrow { - border-top-color: #666; -} -.menu-name { - height: 100%; - padding: 0 0.5em; - display: flex; - align-items: center; - justify-content: center; -} -.menu-name a { - text-decoration: none; - color: #212121; -} -.submenu { - display: none; - z-index: 1; - margin-top: -4px; - min-width: 10em; - position: absolute; - left: 0px; - background-color: white; - box-shadow: 0 1px 5px rgba(0,0,0,.3); - font-size: 100%; - text-transform: none; -} -.menu-item, .submenu { - user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -webkit-user-select: none; -} -.submenu hr { - border: 0; - border-top: 2px solid #eee; -} -.submenu a { - display: block; - padding: .5em 1em; - text-decoration: none; -} -.submenu a:hover, .submenu a.active { - color: white; - background-color: #6b82d6; -} -.submenu a.disabled { - color: gray; - pointer-events: none; -} -.menu-check-mark { - position: absolute; - left: 2px; -} -.menu-delete-btn { - position: absolute; - right: 2px; -} - -{{/* Used to disable events when a modal dialog is displayed */}} -#dialog-overlay { - display: none; - position: fixed; - left: 0px; - top: 0px; - width: 100%; - height: 100%; - background-color: rgba(1,1,1,0.1); -} - -.dialog { - {{/* Displayed centered horizontally near the top */}} - display: none; - position: fixed; - margin: 0px; - top: 60px; - left: 50%; - transform: translateX(-50%); - - z-index: 3; - font-size: 125%; - background-color: #ffffff; - box-shadow: 0 1px 5px rgba(0,0,0,.3); -} -.dialog-header { - font-size: 120%; - border-bottom: 1px solid #CCCCCC; - width: 100%; - text-align: center; - background: #EEEEEE; - user-select: none; -} -.dialog-footer { - border-top: 1px solid #CCCCCC; - width: 100%; - text-align: right; - padding: 10px; -} -.dialog-error { - margin: 10px; - color: red; -} -.dialog input { - margin: 10px; - font-size: inherit; -} -.dialog button { - margin-left: 10px; - font-size: inherit; -} -#save-dialog, #delete-dialog { - width: 50%; - max-width: 20em; -} -#delete-prompt { - padding: 10px; -} - -#content { - overflow-y: scroll; - padding: 1em; -} -#top { - overflow-y: scroll; -} -#graph { - overflow: hidden; -} -#graph svg { - width: 100%; - height: auto; - padding: 10px; -} -#content.source .filename { - margin-top: 0; - margin-bottom: 1em; - font-size: 120%; -} -#content.source pre { - margin-bottom: 3em; -} -table { - border-spacing: 0px; - width: 100%; - padding-bottom: 1em; - white-space: nowrap; -} -table thead { - font-family: 'Roboto Medium', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -} -table tr th { - position: sticky; - top: 0; - background-color: #ddd; - text-align: right; - padding: .3em .5em; -} -table tr td { - padding: .3em .5em; - text-align: right; -} -#top table tr th:nth-child(6), -#top table tr th:nth-child(7), -#top table tr td:nth-child(6), -#top table tr td:nth-child(7) { - text-align: left; -} -#top table tr td:nth-child(6) { - width: 100%; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; -} -#flathdr1, #flathdr2, #cumhdr1, #cumhdr2, #namehdr { - cursor: ns-resize; -} -.hilite { - background-color: #ebf5fb; - font-weight: bold; -} -</style> -{{end}} - -{{define "header"}} -<div class="header"> - <div class="title"> - <h1><a href="./">pprof</a></h1> - </div> - - <div id="view" class="menu-item"> - <div class="menu-name"> - View - <i class="downArrow"></i> - </div> - <div class="submenu"> - <a title="{{.Help.top}}" href="./top" id="topbtn">Top</a> - <a title="{{.Help.graph}}" href="./" id="graphbtn">Graph</a> - <a title="{{.Help.flamegraph}}" href="./flamegraph" id="flamegraph">Flame Graph</a> - <a title="{{.Help.peek}}" href="./peek" id="peek">Peek</a> - <a title="{{.Help.list}}" href="./source" id="list">Source</a> - <a title="{{.Help.disasm}}" href="./disasm" id="disasm">Disassemble</a> - </div> - </div> - - {{$sampleLen := len .SampleTypes}} - {{if gt $sampleLen 1}} - <div id="sample" class="menu-item"> - <div class="menu-name"> - Sample - <i class="downArrow"></i> - </div> - <div class="submenu"> - {{range .SampleTypes}} - <a href="?si={{.}}" id="{{.}}">{{.}}</a> - {{end}} - </div> - </div> - {{end}} - - <div id="refine" class="menu-item"> - <div class="menu-name"> - Refine - <i class="downArrow"></i> - </div> - <div class="submenu"> - <a title="{{.Help.focus}}" href="?" id="focus">Focus</a> - <a title="{{.Help.ignore}}" href="?" id="ignore">Ignore</a> - <a title="{{.Help.hide}}" href="?" id="hide">Hide</a> - <a title="{{.Help.show}}" href="?" id="show">Show</a> - <a title="{{.Help.show_from}}" href="?" id="show-from">Show from</a> - <hr> - <a title="{{.Help.reset}}" href="?">Reset</a> - </div> - </div> - - <div id="config" class="menu-item"> - <div class="menu-name"> - Config - <i class="downArrow"></i> - </div> - <div class="submenu"> - <a title="{{.Help.save_config}}" id="save-config">Save as ...</a> - <hr> - {{range .Configs}} - <a href="{{.URL}}"> - {{if .Current}}<span class="menu-check-mark">✓</span>{{end}} - {{.Name}} - {{if .UserConfig}}<span class="menu-delete-btn" data-config={{.Name}}>🗙</span>{{end}} - </a> - {{end}} - </div> - </div> - - <div id="download" class="menu-item"> - <div class="menu-name"> - <a href="./download">Download</a> - </div> - </div> - - <div> - <input id="search" type="text" placeholder="Search regexp" autocomplete="off" autocapitalize="none" size=40> - </div> - - <div class="description"> - <a title="{{.Help.details}}" href="#" id="details">{{.Title}}</a> - <div id="detailsbox"> - {{range .Legend}}<div>{{.}}</div>{{end}} - </div> - </div> -</div> - -<div id="dialog-overlay"></div> - -<div class="dialog" id="save-dialog"> - <div class="dialog-header">Save options as</div> - <datalist id="config-list"> - {{range .Configs}}{{if .UserConfig}}<option value="{{.Name}}" />{{end}}{{end}} - </datalist> - <input id="save-name" type="text" list="config-list" placeholder="New config" /> - <div class="dialog-footer"> - <span class="dialog-error" id="save-error"></span> - <button id="save-cancel">Cancel</button> - <button id="save-confirm">Save</button> - </div> -</div> - -<div class="dialog" id="delete-dialog"> - <div class="dialog-header" id="delete-dialog-title">Delete config</div> - <div id="delete-prompt"></div> - <div class="dialog-footer"> - <span class="dialog-error" id="delete-error"></span> - <button id="delete-cancel">Cancel</button> - <button id="delete-confirm">Delete</button> - </div> -</div> - -<div id="errors">{{range .Errors}}<div>{{.}}</div>{{end}}</div> -{{end}} - -{{define "graph" -}} -<!DOCTYPE html> -<html> -<head> - <meta charset="utf-8"> - <title>{{.Title}}</title> - {{template "css" .}} -</head> -<body> - {{template "header" .}} - <div id="graph"> - {{.HTMLBody}} - </div> - {{template "script" .}} - <script>viewer(new URL(window.location.href), {{.Nodes}});</script> -</body> -</html> -{{end}} - -{{define "script"}} -<script> -// Make svg pannable and zoomable. -// Call clickHandler(t) if a click event is caught by the pan event handlers. -function initPanAndZoom(svg, clickHandler) { - 'use strict'; - - // Current mouse/touch handling mode - const IDLE = 0; - const MOUSEPAN = 1; - const TOUCHPAN = 2; - const TOUCHZOOM = 3; - let mode = IDLE; - - // State needed to implement zooming. - let currentScale = 1.0; - const initWidth = svg.viewBox.baseVal.width; - const initHeight = svg.viewBox.baseVal.height; - - // State needed to implement panning. - let panLastX = 0; // Last event X coordinate - let panLastY = 0; // Last event Y coordinate - let moved = false; // Have we seen significant movement - let touchid = null; // Current touch identifier - - // State needed for pinch zooming - let touchid2 = null; // Second id for pinch zooming - let initGap = 1.0; // Starting gap between two touches - let initScale = 1.0; // currentScale when pinch zoom started - let centerPoint = null; // Center point for scaling - - // Convert event coordinates to svg coordinates. - function toSvg(x, y) { - const p = svg.createSVGPoint(); - p.x = x; - p.y = y; - let m = svg.getCTM(); - if (m == null) m = svg.getScreenCTM(); // Firefox workaround. - return p.matrixTransform(m.inverse()); - } - - // Change the scaling for the svg to s, keeping the point denoted - // by u (in svg coordinates]) fixed at the same screen location. - function rescale(s, u) { - // Limit to a good range. - if (s < 0.2) s = 0.2; - if (s > 10.0) s = 10.0; - - currentScale = s; - - // svg.viewBox defines the visible portion of the user coordinate - // system. So to magnify by s, divide the visible portion by s, - // which will then be stretched to fit the viewport. - const vb = svg.viewBox; - const w1 = vb.baseVal.width; - const w2 = initWidth / s; - const h1 = vb.baseVal.height; - const h2 = initHeight / s; - vb.baseVal.width = w2; - vb.baseVal.height = h2; - - // We also want to adjust vb.baseVal.x so that u.x remains at same - // screen X coordinate. In other words, want to change it from x1 to x2 - // so that: - // (u.x - x1) / w1 = (u.x - x2) / w2 - // Simplifying that, we get - // (u.x - x1) * (w2 / w1) = u.x - x2 - // x2 = u.x - (u.x - x1) * (w2 / w1) - vb.baseVal.x = u.x - (u.x - vb.baseVal.x) * (w2 / w1); - vb.baseVal.y = u.y - (u.y - vb.baseVal.y) * (h2 / h1); - } - - function handleWheel(e) { - if (e.deltaY == 0) return; - // Change scale factor by 1.1 or 1/1.1 - rescale(currentScale * (e.deltaY < 0 ? 1.1 : (1/1.1)), - toSvg(e.offsetX, e.offsetY)); - } - - function setMode(m) { - mode = m; - touchid = null; - touchid2 = null; - } - - function panStart(x, y) { - moved = false; - panLastX = x; - panLastY = y; - } - - function panMove(x, y) { - let dx = x - panLastX; - let dy = y - panLastY; - if (Math.abs(dx) <= 2 && Math.abs(dy) <= 2) return; // Ignore tiny moves - - moved = true; - panLastX = x; - panLastY = y; - - // Firefox workaround: get dimensions from parentNode. - const swidth = svg.clientWidth || svg.parentNode.clientWidth; - const sheight = svg.clientHeight || svg.parentNode.clientHeight; - - // Convert deltas from screen space to svg space. - dx *= (svg.viewBox.baseVal.width / swidth); - dy *= (svg.viewBox.baseVal.height / sheight); - - svg.viewBox.baseVal.x -= dx; - svg.viewBox.baseVal.y -= dy; - } - - function handleScanStart(e) { - if (e.button != 0) return; // Do not catch right-clicks etc. - setMode(MOUSEPAN); - panStart(e.clientX, e.clientY); - e.preventDefault(); - svg.addEventListener('mousemove', handleScanMove); - } - - function handleScanMove(e) { - if (e.buttons == 0) { - // Missed an end event, perhaps because mouse moved outside window. - setMode(IDLE); - svg.removeEventListener('mousemove', handleScanMove); - return; - } - if (mode == MOUSEPAN) panMove(e.clientX, e.clientY); - } - - function handleScanEnd(e) { - if (mode == MOUSEPAN) panMove(e.clientX, e.clientY); - setMode(IDLE); - svg.removeEventListener('mousemove', handleScanMove); - if (!moved) clickHandler(e.target); - } - - // Find touch object with specified identifier. - function findTouch(tlist, id) { - for (const t of tlist) { - if (t.identifier == id) return t; - } - return null; - } - - // Return distance between two touch points - function touchGap(t1, t2) { - const dx = t1.clientX - t2.clientX; - const dy = t1.clientY - t2.clientY; - return Math.hypot(dx, dy); - } - - function handleTouchStart(e) { - if (mode == IDLE && e.changedTouches.length == 1) { - // Start touch based panning - const t = e.changedTouches[0]; - setMode(TOUCHPAN); - touchid = t.identifier; - panStart(t.clientX, t.clientY); - e.preventDefault(); - } else if (mode == TOUCHPAN && e.touches.length == 2) { - // Start pinch zooming - setMode(TOUCHZOOM); - const t1 = e.touches[0]; - const t2 = e.touches[1]; - touchid = t1.identifier; - touchid2 = t2.identifier; - initScale = currentScale; - initGap = touchGap(t1, t2); - centerPoint = toSvg((t1.clientX + t2.clientX) / 2, - (t1.clientY + t2.clientY) / 2); - e.preventDefault(); - } - } - - function handleTouchMove(e) { - if (mode == TOUCHPAN) { - const t = findTouch(e.changedTouches, touchid); - if (t == null) return; - if (e.touches.length != 1) { - setMode(IDLE); - return; - } - panMove(t.clientX, t.clientY); - e.preventDefault(); - } else if (mode == TOUCHZOOM) { - // Get two touches; new gap; rescale to ratio. - const t1 = findTouch(e.touches, touchid); - const t2 = findTouch(e.touches, touchid2); - if (t1 == null || t2 == null) return; - const gap = touchGap(t1, t2); - rescale(initScale * gap / initGap, centerPoint); - e.preventDefault(); - } - } - - function handleTouchEnd(e) { - if (mode == TOUCHPAN) { - const t = findTouch(e.changedTouches, touchid); - if (t == null) return; - panMove(t.clientX, t.clientY); - setMode(IDLE); - e.preventDefault(); - if (!moved) clickHandler(t.target); - } else if (mode == TOUCHZOOM) { - setMode(IDLE); - e.preventDefault(); - } - } - - svg.addEventListener('mousedown', handleScanStart); - svg.addEventListener('mouseup', handleScanEnd); - svg.addEventListener('touchstart', handleTouchStart); - svg.addEventListener('touchmove', handleTouchMove); - svg.addEventListener('touchend', handleTouchEnd); - svg.addEventListener('wheel', handleWheel, true); -} - -function initMenus() { - 'use strict'; - - let activeMenu = null; - let activeMenuHdr = null; - - function cancelActiveMenu() { - if (activeMenu == null) return; - activeMenu.style.display = 'none'; - activeMenu = null; - activeMenuHdr = null; - } - - // Set click handlers on every menu header. - for (const menu of document.getElementsByClassName('submenu')) { - const hdr = menu.parentElement; - if (hdr == null) return; - if (hdr.classList.contains('disabled')) return; - function showMenu(e) { - // menu is a child of hdr, so this event can fire for clicks - // inside menu. Ignore such clicks. - if (e.target.parentElement != hdr) return; - activeMenu = menu; - activeMenuHdr = hdr; - menu.style.display = 'block'; - } - hdr.addEventListener('mousedown', showMenu); - hdr.addEventListener('touchstart', showMenu); - } - - // If there is an active menu and a down event outside, retract the menu. - for (const t of ['mousedown', 'touchstart']) { - document.addEventListener(t, (e) => { - // Note: to avoid unnecessary flicker, if the down event is inside - // the active menu header, do not retract the menu. - if (activeMenuHdr != e.target.closest('.menu-item')) { - cancelActiveMenu(); - } - }, { passive: true, capture: true }); - } - - // If there is an active menu and an up event inside, retract the menu. - document.addEventListener('mouseup', (e) => { - if (activeMenu == e.target.closest('.submenu')) { - cancelActiveMenu(); - } - }, { passive: true, capture: true }); -} - -function sendURL(method, url, done) { - fetch(url.toString(), {method: method}) - .then((response) => { done(response.ok); }) - .catch((error) => { done(false); }); -} - -// Initialize handlers for saving/loading configurations. -function initConfigManager() { - 'use strict'; - - // Initialize various elements. - function elem(id) { - const result = document.getElementById(id); - if (!result) console.warn('element ' + id + ' not found'); - return result; - } - const overlay = elem('dialog-overlay'); - const saveDialog = elem('save-dialog'); - const saveInput = elem('save-name'); - const saveError = elem('save-error'); - const delDialog = elem('delete-dialog'); - const delPrompt = elem('delete-prompt'); - const delError = elem('delete-error'); - - let currentDialog = null; - let currentDeleteTarget = null; - - function showDialog(dialog) { - if (currentDialog != null) { - overlay.style.display = 'none'; - currentDialog.style.display = 'none'; - } - currentDialog = dialog; - if (dialog != null) { - overlay.style.display = 'block'; - dialog.style.display = 'block'; - } - } - - function cancelDialog(e) { - showDialog(null); - } - - // Show dialog for saving the current config. - function showSaveDialog(e) { - saveError.innerText = ''; - showDialog(saveDialog); - saveInput.focus(); - } - - // Commit save config. - function commitSave(e) { - const name = saveInput.value; - const url = new URL(document.URL); - // Set path relative to existing path. - url.pathname = new URL('./saveconfig', document.URL).pathname; - url.searchParams.set('config', name); - saveError.innerText = ''; - sendURL('POST', url, (ok) => { - if (!ok) { - saveError.innerText = 'Save failed'; - } else { - showDialog(null); - location.reload(); // Reload to show updated config menu - } - }); - } - - function handleSaveInputKey(e) { - if (e.key === 'Enter') commitSave(e); - } - - function deleteConfig(e, elem) { - e.preventDefault(); - const config = elem.dataset.config; - delPrompt.innerText = 'Delete ' + config + '?'; - currentDeleteTarget = elem; - showDialog(delDialog); - } - - function commitDelete(e, elem) { - if (!currentDeleteTarget) return; - const config = currentDeleteTarget.dataset.config; - const url = new URL('./deleteconfig', document.URL); - url.searchParams.set('config', config); - delError.innerText = ''; - sendURL('DELETE', url, (ok) => { - if (!ok) { - delError.innerText = 'Delete failed'; - return; - } - showDialog(null); - // Remove menu entry for this config. - if (currentDeleteTarget && currentDeleteTarget.parentElement) { - currentDeleteTarget.parentElement.remove(); - } - }); - } - - // Bind event on elem to fn. - function bind(event, elem, fn) { - if (elem == null) return; - elem.addEventListener(event, fn); - if (event == 'click') { - // Also enable via touch. - elem.addEventListener('touchstart', fn); - } - } - - bind('click', elem('save-config'), showSaveDialog); - bind('click', elem('save-cancel'), cancelDialog); - bind('click', elem('save-confirm'), commitSave); - bind('keydown', saveInput, handleSaveInputKey); - - bind('click', elem('delete-cancel'), cancelDialog); - bind('click', elem('delete-confirm'), commitDelete); - - // Activate deletion button for all config entries in menu. - for (const del of Array.from(document.getElementsByClassName('menu-delete-btn'))) { - bind('click', del, (e) => { - deleteConfig(e, del); - }); - } -} - -function viewer(baseUrl, nodes) { - 'use strict'; - - // Elements - const search = document.getElementById('search'); - const graph0 = document.getElementById('graph0'); - const svg = (graph0 == null ? null : graph0.parentElement); - const toptable = document.getElementById('toptable'); - - let regexpActive = false; - let selected = new Map(); - let origFill = new Map(); - let searchAlarm = null; - let buttonsEnabled = true; - - function handleDetails(e) { - e.preventDefault(); - const detailsText = document.getElementById('detailsbox'); - if (detailsText != null) { - if (detailsText.style.display === 'block') { - detailsText.style.display = 'none'; - } else { - detailsText.style.display = 'block'; - } - } - } - - function handleKey(e) { - if (e.keyCode != 13) return; - setHrefParams(window.location, function (params) { - params.set('f', search.value); - }); - e.preventDefault(); - } - - function handleSearch() { - // Delay expensive processing so a flurry of key strokes is handled once. - if (searchAlarm != null) { - clearTimeout(searchAlarm); - } - searchAlarm = setTimeout(selectMatching, 300); - - regexpActive = true; - updateButtons(); - } - - function selectMatching() { - searchAlarm = null; - let re = null; - if (search.value != '') { - try { - re = new RegExp(search.value); - } catch (e) { - // TODO: Display error state in search box - return; - } - } - - function match(text) { - return re != null && re.test(text); - } - - // drop currently selected items that do not match re. - selected.forEach(function(v, n) { - if (!match(nodes[n])) { - unselect(n, document.getElementById('node' + n)); - } - }) - - // add matching items that are not currently selected. - if (nodes) { - for (let n = 0; n < nodes.length; n++) { - if (!selected.has(n) && match(nodes[n])) { - select(n, document.getElementById('node' + n)); - } - } - } - - updateButtons(); - } - - function toggleSvgSelect(elem) { - // Walk up to immediate child of graph0 - while (elem != null && elem.parentElement != graph0) { - elem = elem.parentElement; - } - if (!elem) return; - - // Disable regexp mode. - regexpActive = false; - - const n = nodeId(elem); - if (n < 0) return; - if (selected.has(n)) { - unselect(n, elem); - } else { - select(n, elem); - } - updateButtons(); - } - - function unselect(n, elem) { - if (elem == null) return; - selected.delete(n); - setBackground(elem, false); - } - - function select(n, elem) { - if (elem == null) return; - selected.set(n, true); - setBackground(elem, true); - } - - function nodeId(elem) { - const id = elem.id; - if (!id) return -1; - if (!id.startsWith('node')) return -1; - const n = parseInt(id.slice(4), 10); - if (isNaN(n)) return -1; - if (n < 0 || n >= nodes.length) return -1; - return n; - } - - function setBackground(elem, set) { - // Handle table row highlighting. - if (elem.nodeName == 'TR') { - elem.classList.toggle('hilite', set); - return; - } - - // Handle svg element highlighting. - const p = findPolygon(elem); - if (p != null) { - if (set) { - origFill.set(p, p.style.fill); - p.style.fill = '#ccccff'; - } else if (origFill.has(p)) { - p.style.fill = origFill.get(p); - } - } - } - - function findPolygon(elem) { - if (elem.localName == 'polygon') return elem; - for (const c of elem.children) { - const p = findPolygon(c); - if (p != null) return p; - } - return null; - } - - // convert a string to a regexp that matches that string. - function quotemeta(str) { - return str.replace(/([\\\.?+*\[\](){}|^$])/g, '\\$1'); - } - - function setSampleIndexLink(id) { - const elem = document.getElementById(id); - if (elem != null) { - setHrefParams(elem, function (params) { - params.set("si", id); - }); - } - } - - // Update id's href to reflect current selection whenever it is - // liable to be followed. - function makeSearchLinkDynamic(id) { - const elem = document.getElementById(id); - if (elem == null) return; - - // Most links copy current selection into the 'f' parameter, - // but Refine menu links are different. - let param = 'f'; - if (id == 'ignore') param = 'i'; - if (id == 'hide') param = 'h'; - if (id == 'show') param = 's'; - if (id == 'show-from') param = 'sf'; - - // We update on mouseenter so middle-click/right-click work properly. - elem.addEventListener('mouseenter', updater); - elem.addEventListener('touchstart', updater); - - function updater() { - // The selection can be in one of two modes: regexp-based or - // list-based. Construct regular expression depending on mode. - let re = regexpActive - ? search.value - : Array.from(selected.keys()).map(key => quotemeta(nodes[key])).join('|'); - - setHrefParams(elem, function (params) { - if (re != '') { - // For focus/show/show-from, forget old parameter. For others, add to re. - if (param != 'f' && param != 's' && param != 'sf' && params.has(param)) { - const old = params.get(param); - if (old != '') { - re += '|' + old; - } - } - params.set(param, re); - } else { - params.delete(param); - } - }); - } - } - - function setHrefParams(elem, paramSetter) { - let url = new URL(elem.href); - url.hash = ''; - - // Copy params from this page's URL. - const params = url.searchParams; - for (const p of new URLSearchParams(window.location.search)) { - params.set(p[0], p[1]); - } - - // Give the params to the setter to modify. - paramSetter(params); - - elem.href = url.toString(); - } - - function handleTopClick(e) { - // Walk back until we find TR and then get the Name column (index 5) - let elem = e.target; - while (elem != null && elem.nodeName != 'TR') { - elem = elem.parentElement; - } - if (elem == null || elem.children.length < 6) return; - - e.preventDefault(); - const tr = elem; - const td = elem.children[5]; - if (td.nodeName != 'TD') return; - const name = td.innerText; - const index = nodes.indexOf(name); - if (index < 0) return; - - // Disable regexp mode. - regexpActive = false; - - if (selected.has(index)) { - unselect(index, elem); - } else { - select(index, elem); - } - updateButtons(); - } - - function updateButtons() { - const enable = (search.value != '' || selected.size != 0); - if (buttonsEnabled == enable) return; - buttonsEnabled = enable; - for (const id of ['focus', 'ignore', 'hide', 'show', 'show-from']) { - const link = document.getElementById(id); - if (link != null) { - link.classList.toggle('disabled', !enable); - } - } - } - - // Initialize button states - updateButtons(); - - // Setup event handlers - initMenus(); - if (svg != null) { - initPanAndZoom(svg, toggleSvgSelect); - } - if (toptable != null) { - toptable.addEventListener('mousedown', handleTopClick); - toptable.addEventListener('touchstart', handleTopClick); - } - - const ids = ['topbtn', 'graphbtn', 'flamegraph', 'peek', 'list', 'disasm', - 'focus', 'ignore', 'hide', 'show', 'show-from']; - ids.forEach(makeSearchLinkDynamic); - - const sampleIDs = [{{range .SampleTypes}}'{{.}}', {{end}}]; - sampleIDs.forEach(setSampleIndexLink); - - // Bind action to button with specified id. - function addAction(id, action) { - const btn = document.getElementById(id); - if (btn != null) { - btn.addEventListener('click', action); - btn.addEventListener('touchstart', action); - } - } - - addAction('details', handleDetails); - initConfigManager(); - - search.addEventListener('input', handleSearch); - search.addEventListener('keydown', handleKey); - - // Give initial focus to main container so it can be scrolled using keys. - const main = document.getElementById('bodycontainer'); - if (main) { - main.focus(); - } -} -</script> -{{end}} - -{{define "top" -}} -<!DOCTYPE html> -<html> -<head> - <meta charset="utf-8"> - <title>{{.Title}}</title> - {{template "css" .}} - <style type="text/css"> - </style> -</head> -<body> - {{template "header" .}} - <div id="top"> - <table id="toptable"> - <thead> - <tr> - <th id="flathdr1">Flat</th> - <th id="flathdr2">Flat%</th> - <th>Sum%</th> - <th id="cumhdr1">Cum</th> - <th id="cumhdr2">Cum%</th> - <th id="namehdr">Name</th> - <th>Inlined?</th> - </tr> - </thead> - <tbody id="rows"></tbody> - </table> - </div> - {{template "script" .}} - <script> - function makeTopTable(total, entries) { - const rows = document.getElementById('rows'); - if (rows == null) return; - - // Store initial index in each entry so we have stable node ids for selection. - for (let i = 0; i < entries.length; i++) { - entries[i].Id = 'node' + i; - } - - // Which column are we currently sorted by and in what order? - let currentColumn = ''; - let descending = false; - sortBy('Flat'); - - function sortBy(column) { - // Update sort criteria - if (column == currentColumn) { - descending = !descending; // Reverse order - } else { - currentColumn = column; - descending = (column != 'Name'); - } - - // Sort according to current criteria. - function cmp(a, b) { - const av = a[currentColumn]; - const bv = b[currentColumn]; - if (av < bv) return -1; - if (av > bv) return +1; - return 0; - } - entries.sort(cmp); - if (descending) entries.reverse(); - - function addCell(tr, val) { - const td = document.createElement('td'); - td.textContent = val; - tr.appendChild(td); - } - - function percent(v) { - return (v * 100.0 / total).toFixed(2) + '%'; - } - - // Generate rows - const fragment = document.createDocumentFragment(); - let sum = 0; - for (const row of entries) { - const tr = document.createElement('tr'); - tr.id = row.Id; - sum += row.Flat; - addCell(tr, row.FlatFormat); - addCell(tr, percent(row.Flat)); - addCell(tr, percent(sum)); - addCell(tr, row.CumFormat); - addCell(tr, percent(row.Cum)); - addCell(tr, row.Name); - addCell(tr, row.InlineLabel); - fragment.appendChild(tr); - } - - rows.textContent = ''; // Remove old rows - rows.appendChild(fragment); - } - - // Make different column headers trigger sorting. - function bindSort(id, column) { - const hdr = document.getElementById(id); - if (hdr == null) return; - const fn = function() { sortBy(column) }; - hdr.addEventListener('click', fn); - hdr.addEventListener('touch', fn); - } - bindSort('flathdr1', 'Flat'); - bindSort('flathdr2', 'Flat'); - bindSort('cumhdr1', 'Cum'); - bindSort('cumhdr2', 'Cum'); - bindSort('namehdr', 'Name'); - } - - viewer(new URL(window.location.href), {{.Nodes}}); - makeTopTable({{.Total}}, {{.Top}}); - </script> -</body> -</html> -{{end}} - -{{define "sourcelisting" -}} -<!DOCTYPE html> -<html> -<head> - <meta charset="utf-8"> - <title>{{.Title}}</title> - {{template "css" .}} - {{template "weblistcss" .}} - {{template "weblistjs" .}} -</head> -<body> - {{template "header" .}} - <div id="content" class="source"> - {{.HTMLBody}} - </div> - {{template "script" .}} - <script>viewer(new URL(window.location.href), null);</script> -</body> -</html> -{{end}} - -{{define "plaintext" -}} -<!DOCTYPE html> -<html> -<head> - <meta charset="utf-8"> - <title>{{.Title}}</title> - {{template "css" .}} -</head> -<body> - {{template "header" .}} - <div id="content"> - <pre> - {{.TextBody}} - </pre> - </div> - {{template "script" .}} - <script>viewer(new URL(window.location.href), null);</script> -</body> -</html> -{{end}} - -{{define "flamegraph" -}} -<!DOCTYPE html> -<html> -<head> - <meta charset="utf-8"> - <title>{{.Title}}</title> - {{template "css" .}} - <style type="text/css">{{template "d3flamegraphcss" .}}</style> - <style type="text/css"> - .flamegraph-content { - width: 90%; - min-width: 80%; - margin-left: 5%; - } - .flamegraph-details { - height: 1.2em; - width: 90%; - min-width: 90%; - margin-left: 5%; - padding: 15px 0 35px; - } - </style> -</head> -<body> - {{template "header" .}} - <div id="bodycontainer"> - <div id="flamegraphdetails" class="flamegraph-details"></div> - <div class="flamegraph-content"> - <div id="chart"></div> - </div> - </div> - {{template "script" .}} - <script>viewer(new URL(window.location.href), {{.Nodes}});</script> - <script>{{template "d3script" .}}</script> - <script>{{template "d3flamegraphscript" .}}</script> - <script> - var data = {{.FlameGraph}}; - - var width = document.getElementById('chart').clientWidth; - - var flameGraph = d3.flamegraph() - .width(width) - .cellHeight(18) - .minFrameSize(1) - .transitionDuration(750) - .transitionEase(d3.easeCubic) - .inverted(true) - .sort(true) - .title('') - .tooltip(false) - .details(document.getElementById('flamegraphdetails')); - - // <full name> (percentage, value) - flameGraph.label((d) => d.data.f + ' (' + d.data.p + ', ' + d.data.l + ')'); - - (function(flameGraph) { - var oldColorMapper = flameGraph.color(); - function colorMapper(d) { - // Hack to force default color mapper to use 'warm' color scheme by not passing libtype - const { data, highlight } = d; - return oldColorMapper({ data: { n: data.n }, highlight }); - } - - flameGraph.color(colorMapper); - }(flameGraph)); - - d3.select('#chart') - .datum(data) - .call(flameGraph); - - function clear() { - flameGraph.clear(); - } - - function resetZoom() { - flameGraph.resetZoom(); - } - - window.addEventListener('resize', function() { - var width = document.getElementById('chart').clientWidth; - var graphs = document.getElementsByClassName('d3-flame-graph'); - if (graphs.length > 0) { - graphs[0].setAttribute('width', width); - } - flameGraph.width(width); - flameGraph.resetZoom(); - }, true); - - var search = document.getElementById('search'); - var searchAlarm = null; - - function selectMatching() { - searchAlarm = null; - - if (search.value != '') { - flameGraph.search(search.value); - } else { - flameGraph.clear(); - } - } - - function handleSearch() { - // Delay expensive processing so a flurry of key strokes is handled once. - if (searchAlarm != null) { - clearTimeout(searchAlarm); - } - searchAlarm = setTimeout(selectMatching, 300); - } - - search.addEventListener('input', handleSearch); - </script> -</body> -</html> -{{end}} -`)) + // Load specified file. + loadFile := func(fname string) string { + data, err := embeddedFiles.ReadFile(fname) + if err != nil { + fmt.Fprintf(os.Stderr, "internal/driver: embedded file %q not found\n", + fname) + os.Exit(1) + } + return string(data) + } + loadCSS := func(fname string) string { + return `<style type="text/css">` + "\n" + loadFile(fname) + `</style>` + "\n" + } + loadJS := func(fname string) string { + return `<script>` + "\n" + loadFile(fname) + `</script>` + "\n" + } + + // Define a named template with specified contents. + def := func(name, contents string) { + sub := template.New(name) + template.Must(sub.Parse(contents)) + template.Must(templates.AddParseTree(name, sub.Tree)) + } + + // Pre-packaged third-party files. + def("d3flamegraphscript", d3flamegraph.JSSource) + def("d3flamegraphcss", d3flamegraph.CSSSource) + + // Embeded files. + def("css", loadCSS("html/common.css")) + def("header", loadFile("html/header.html")) + def("graph", loadFile("html/graph.html")) + def("script", loadJS("html/common.js")) + def("top", loadFile("html/top.html")) + def("sourcelisting", loadFile("html/source.html")) + def("plaintext", loadFile("html/plaintext.html")) + def("flamegraph", loadFile("html/flamegraph.html")) } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go b/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go index 6447092d3d9978baeea75405fc441c0546d5c87e..718481b078856f9fd373091876343548437439dd 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go @@ -165,9 +165,9 @@ func GetBuildID(binary io.ReaderAt) ([]byte, error) { return nil, nil } -// kernelBase caluclates the base for kernel mappings, which usually require +// kernelBase calculates the base for kernel mappings, which usually require // special handling. For kernel mappings, tools (like perf) use the address of -// the kernel relocation symbol (_text or _stext) as the mmap start. Additionaly, +// the kernel relocation symbol (_text or _stext) as the mmap start. Additionally, // for obfuscation, ChromeOS profiles have the kernel image remapped to the 0-th page. func kernelBase(loadSegment *elf.ProgHeader, stextOffset *uint64, start, limit, offset uint64) (uint64, bool) { const ( @@ -217,7 +217,7 @@ func kernelBase(loadSegment *elf.ProgHeader, stextOffset *uint64, start, limit, // GetBase determines the base address to subtract from virtual // address to get symbol table address. For an executable, the base // is 0. Otherwise, it's a shared library, and the base is the -// address where the mapping starts. The kernel needs special hanldling. +// address where the mapping starts. The kernel needs special handling. func GetBase(fh *elf.FileHeader, loadSegment *elf.ProgHeader, stextOffset *uint64, start, limit, offset uint64) (uint64, error) { if start == 0 && offset == 0 && (limit == ^uint64(0) || limit == 0) { diff --git a/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go b/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go index 800867524848d41e6adf7c902402a30b2fc71c30..09d40fd2c9901773ece5de9201a4c7ab9236eb4b 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go @@ -126,7 +126,7 @@ func (b *builder) addLegend() { return } title := labels[0] - fmt.Fprintf(b, `subgraph cluster_L { "%s" [shape=box fontsize=16`, title) + fmt.Fprintf(b, `subgraph cluster_L { "%s" [shape=box fontsize=16`, escapeForDot(title)) fmt.Fprintf(b, ` label="%s\l"`, strings.Join(escapeAllForDot(labels), `\l`)) if b.config.LegendURL != "" { fmt.Fprintf(b, ` URL="%s" target="_blank"`, b.config.LegendURL) @@ -385,6 +385,9 @@ func multilinePrintableName(info *NodeInfo) string { infoCopy := *info infoCopy.Name = escapeForDot(ShortenFunctionName(infoCopy.Name)) infoCopy.Name = strings.Replace(infoCopy.Name, "::", `\n`, -1) + // Go type parameters are reported as "[...]" by Go pprof profiles. + // Keep this ellipsis rather than replacing with newlines below. + infoCopy.Name = strings.Replace(infoCopy.Name, "[...]", "[…]", -1) infoCopy.Name = strings.Replace(infoCopy.Name, ".", `\n`, -1) if infoCopy.File != "" { infoCopy.File = filepath.Base(infoCopy.File) @@ -485,7 +488,7 @@ func escapeAllForDot(in []string) []string { // escapeForDot escapes double quotes and backslashes, and replaces Graphviz's // "center" character (\n) with a left-justified character. -// See https://graphviz.org/doc/info/attrs.html#k:escString for more info. +// See https://graphviz.org/docs/attr-types/escString/ for more info. func escapeForDot(str string) string { return strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(str, `\`, `\\`), `"`, `\"`), "\n", `\l`) } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/measurement/measurement.go b/src/cmd/vendor/github.com/google/pprof/internal/measurement/measurement.go index 53325740a3ed8438fa5eb5d29681ab997e34da69..b5fcfbc3e463f98b1e33f1e7232b4ea9ccb539f3 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/measurement/measurement.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/measurement/measurement.go @@ -110,10 +110,15 @@ func compatibleValueTypes(v1, v2 *profile.ValueType) bool { return false } - return v1.Unit == v2.Unit || - (timeUnits.sniffUnit(v1.Unit) != nil && timeUnits.sniffUnit(v2.Unit) != nil) || - (memoryUnits.sniffUnit(v1.Unit) != nil && memoryUnits.sniffUnit(v2.Unit) != nil) || - (gcuUnits.sniffUnit(v1.Unit) != nil && gcuUnits.sniffUnit(v2.Unit) != nil) + if v1.Unit == v2.Unit { + return true + } + for _, ut := range unitTypes { + if ut.sniffUnit(v1.Unit) != nil && ut.sniffUnit(v2.Unit) != nil { + return true + } + } + return false } // Scale a measurement from an unit to a different unit and returns @@ -125,14 +130,10 @@ func Scale(value int64, fromUnit, toUnit string) (float64, string) { v, u := Scale(-value, fromUnit, toUnit) return -v, u } - if m, u, ok := memoryUnits.convertUnit(value, fromUnit, toUnit); ok { - return m, u - } - if t, u, ok := timeUnits.convertUnit(value, fromUnit, toUnit); ok { - return t, u - } - if g, u, ok := gcuUnits.convertUnit(value, fromUnit, toUnit); ok { - return g, u + for _, ut := range unitTypes { + if v, u, ok := ut.convertUnit(value, fromUnit, toUnit); ok { + return v, u + } } // Skip non-interesting units. switch toUnit { @@ -257,7 +258,7 @@ func (ut unitType) convertUnit(value int64, fromUnitStr, toUnitStr string) (floa return v / toUnit.factor, toUnit.canonicalName, true } -var memoryUnits = unitType{ +var unitTypes = []unitType{{ units: []unit{ {"B", []string{"b", "byte"}, 1}, {"kB", []string{"kb", "kbyte", "kilobyte"}, float64(1 << 10)}, @@ -267,9 +268,7 @@ var memoryUnits = unitType{ {"PB", []string{"pb", "pbyte", "petabyte"}, float64(1 << 50)}, }, defaultUnit: unit{"B", []string{"b", "byte"}, 1}, -} - -var timeUnits = unitType{ +}, { units: []unit{ {"ns", []string{"ns", "nanosecond"}, float64(time.Nanosecond)}, {"us", []string{"μs", "us", "microsecond"}, float64(time.Microsecond)}, @@ -278,9 +277,7 @@ var timeUnits = unitType{ {"hrs", []string{"hour", "hr"}, float64(time.Hour)}, }, defaultUnit: unit{"s", []string{}, float64(time.Second)}, -} - -var gcuUnits = unitType{ +}, { units: []unit{ {"n*GCU", []string{"nanogcu"}, 1e-9}, {"u*GCU", []string{"microgcu"}, 1e-6}, @@ -293,4 +290,4 @@ var gcuUnits = unitType{ {"P*GCU", []string{"petagcu"}, 1e15}, }, defaultUnit: unit{"GCU", []string{}, 1.0}, -} +}} diff --git a/src/cmd/vendor/github.com/google/pprof/internal/plugin/plugin.go b/src/cmd/vendor/github.com/google/pprof/internal/plugin/plugin.go index a57a0b20a96256f6d887105f76dc7e55a7c51f0e..98eb1dd8179bb01bc87658e647f83aec0a9417ed 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/plugin/plugin.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/plugin/plugin.go @@ -109,8 +109,10 @@ type MappingSources map[string][]struct { type ObjTool interface { // Open opens the named object file. If the object is a shared // library, start/limit/offset are the addresses where it is mapped - // into memory in the address space being inspected. - Open(file string, start, limit, offset uint64) (ObjFile, error) + // into memory in the address space being inspected. If the object + // is a linux kernel, relocationSymbol is the name of the symbol + // corresponding to the start address. + Open(file string, start, limit, offset uint64, relocationSymbol string) (ObjFile, error) // Disasm disassembles the named object file, starting at // the start address and stopping at (before) the end address. diff --git a/src/cmd/vendor/github.com/google/pprof/internal/report/report.go b/src/cmd/vendor/github.com/google/pprof/internal/report/report.go index e2fb00314ca0ab437b6362891093bb0929c112c1..36ddf2e934efd622d632289c97bb413fec186fdf 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/report/report.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/report/report.go @@ -526,7 +526,7 @@ func symbolsFromBinaries(prof *profile.Profile, g *graph.Graph, rx *regexp.Regex } } - f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset) + f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset, m.KernelRelocationSymbol) if err != nil { fmt.Printf("%v\n", err) continue diff --git a/src/cmd/vendor/github.com/google/pprof/internal/report/source.go b/src/cmd/vendor/github.com/google/pprof/internal/report/source.go index 33d04c591d9beba025eb1911f0cbb25be7fd4e67..d8b4395265634525d919cf7a000e5b1d74e7908f 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/report/source.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/report/source.go @@ -744,7 +744,7 @@ func (sp *sourcePrinter) objectFile(m *profile.Mapping) plugin.ObjFile { if object, ok := sp.objects[m.File]; ok { return object // May be nil if we detected an error earlier. } - object, err := sp.objectTool.Open(m.File, m.Start, m.Limit, m.Offset) + object, err := sp.objectTool.Open(m.File, m.Start, m.Limit, m.Offset, m.KernelRelocationSymbol) if err != nil { object = nil } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/symbolizer/symbolizer.go b/src/cmd/vendor/github.com/google/pprof/internal/symbolizer/symbolizer.go index d741e7ad7fa7b62b1d82baf2e3069a80d94fcd85..d243b800a92fc8f5dc627c6f3fd699af24678d9e 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/symbolizer/symbolizer.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/symbolizer/symbolizer.go @@ -205,49 +205,64 @@ func Demangle(prof *profile.Profile, force bool, demanglerMode string) { } } - var options []demangle.Option + options := demanglerModeToOptions(demanglerMode) + for _, fn := range prof.Function { + demangleSingleFunction(fn, options) + } +} + +func demanglerModeToOptions(demanglerMode string) []demangle.Option { switch demanglerMode { case "": // demangled, simplified: no parameters, no templates, no return type - options = []demangle.Option{demangle.NoParams, demangle.NoTemplateParams} + return []demangle.Option{demangle.NoParams, demangle.NoTemplateParams} case "templates": // demangled, simplified: no parameters, no return type - options = []demangle.Option{demangle.NoParams} + return []demangle.Option{demangle.NoParams} case "full": - options = []demangle.Option{demangle.NoClones} + return []demangle.Option{demangle.NoClones} case "none": // no demangling - return + return []demangle.Option{} } + panic(fmt.Sprintf("unknown demanglerMode %s", demanglerMode)) +} + +func demangleSingleFunction(fn *profile.Function, options []demangle.Option) { + if fn.Name != "" && fn.SystemName != fn.Name { + return // Already demangled. + } // Copy the options because they may be updated by the call. o := make([]demangle.Option, len(options)) - for _, fn := range prof.Function { - if fn.Name != "" && fn.SystemName != fn.Name { - continue // Already demangled. - } - copy(o, options) - if demangled := demangle.Filter(fn.SystemName, o...); demangled != fn.SystemName { - fn.Name = demangled - continue - } - // Could not demangle. Apply heuristics in case the name is - // already demangled. - name := fn.SystemName - if looksLikeDemangledCPlusPlus(name) { - if demanglerMode == "" || demanglerMode == "templates" { + copy(o, options) + if demangled := demangle.Filter(fn.SystemName, o...); demangled != fn.SystemName { + fn.Name = demangled + return + } + // Could not demangle. Apply heuristics in case the name is + // already demangled. + name := fn.SystemName + if looksLikeDemangledCPlusPlus(name) { + for _, o := range options { + switch o { + case demangle.NoParams: name = removeMatching(name, '(', ')') - } - if demanglerMode == "" { + case demangle.NoTemplateParams: name = removeMatching(name, '<', '>') } } - fn.Name = name } + fn.Name = name } // looksLikeDemangledCPlusPlus is a heuristic to decide if a name is // the result of demangling C++. If so, further heuristics will be // applied to simplify the name. func looksLikeDemangledCPlusPlus(demangled string) bool { - if strings.Contains(demangled, ".<") { // Skip java names of the form "class.<init>" + // Skip java names of the form "class.<init>". + if strings.Contains(demangled, ".<") { + return false + } + // Skip Go names of the form "foo.(*Bar[...]).Method". + if strings.Contains(demangled, "]).") { return false } return strings.ContainsAny(demangled, "<>[]") || strings.Contains(demangled, "::") @@ -325,7 +340,10 @@ func newMapping(prof *profile.Profile, obj plugin.ObjTool, ui plugin.UI, force b } name := filepath.Base(m.File) - f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset) + if m.BuildID != "" { + name += fmt.Sprintf(" (build ID %s)", m.BuildID) + } + f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset, m.KernelRelocationSymbol) if err != nil { ui.PrintErr("Local symbolization failed for ", name, ": ", err) missingBinaries = true diff --git a/src/cmd/vendor/github.com/google/pprof/profile/encode.go b/src/cmd/vendor/github.com/google/pprof/profile/encode.go index ab7f03ae2677b4a5673def3d47e349821629f606..96aa271e54fb75fd9161755ddd7070a435d9e5a3 100644 --- a/src/cmd/vendor/github.com/google/pprof/profile/encode.go +++ b/src/cmd/vendor/github.com/google/pprof/profile/encode.go @@ -17,6 +17,7 @@ package profile import ( "errors" "sort" + "strings" ) func (p *Profile) decoder() []decoder { @@ -252,6 +253,14 @@ func (p *Profile) postDecode() error { } else { mappings[m.ID] = m } + + // If this a main linux kernel mapping with a relocation symbol suffix + // ("[kernel.kallsyms]_text"), extract said suffix. + // It is fairly hacky to handle at this level, but the alternatives appear even worse. + if strings.HasPrefix(m.File, "[kernel.kallsyms]") { + m.KernelRelocationSymbol = strings.ReplaceAll(m.File, "[kernel.kallsyms]", "") + } + } functions := make(map[uint64]*Function, len(p.Function)) diff --git a/src/cmd/vendor/github.com/google/pprof/profile/legacy_profile.go b/src/cmd/vendor/github.com/google/pprof/profile/legacy_profile.go index 0c8f3bb5b71f45f6c9edc402c4a9fada3690b9f8..9ba9a77c924f82ce8799b866f996041a4728fa06 100644 --- a/src/cmd/vendor/github.com/google/pprof/profile/legacy_profile.go +++ b/src/cmd/vendor/github.com/google/pprof/profile/legacy_profile.go @@ -295,11 +295,12 @@ func get64b(b []byte) (uint64, []byte) { // // The general format for profilez samples is a sequence of words in // binary format. The first words are a header with the following data: -// 1st word -- 0 -// 2nd word -- 3 -// 3rd word -- 0 if a c++ application, 1 if a java application. -// 4th word -- Sampling period (in microseconds). -// 5th word -- Padding. +// +// 1st word -- 0 +// 2nd word -- 3 +// 3rd word -- 0 if a c++ application, 1 if a java application. +// 4th word -- Sampling period (in microseconds). +// 5th word -- Padding. func parseCPU(b []byte) (*Profile, error) { var parse func([]byte) (uint64, []byte) var n1, n2, n3, n4, n5 uint64 @@ -403,15 +404,18 @@ func cleanupDuplicateLocations(p *Profile) { // // profilez samples are a repeated sequence of stack frames of the // form: -// 1st word -- The number of times this stack was encountered. -// 2nd word -- The size of the stack (StackSize). -// 3rd word -- The first address on the stack. -// ... -// StackSize + 2 -- The last address on the stack +// +// 1st word -- The number of times this stack was encountered. +// 2nd word -- The size of the stack (StackSize). +// 3rd word -- The first address on the stack. +// ... +// StackSize + 2 -- The last address on the stack +// // The last stack trace is of the form: -// 1st word -- 0 -// 2nd word -- 1 -// 3rd word -- 0 +// +// 1st word -- 0 +// 2nd word -- 1 +// 3rd word -- 0 // // Addresses from stack traces may point to the next instruction after // each call. Optionally adjust by -1 to land somewhere on the actual diff --git a/src/cmd/vendor/github.com/google/pprof/profile/merge.go b/src/cmd/vendor/github.com/google/pprof/profile/merge.go index 9978e7330e6e6fe670b78561c2eb45d166b217bb..6fcd11de19a539ce42e72e341613288a4ccaec91 100644 --- a/src/cmd/vendor/github.com/google/pprof/profile/merge.go +++ b/src/cmd/vendor/github.com/google/pprof/profile/merge.go @@ -303,16 +303,17 @@ func (pm *profileMerger) mapMapping(src *Mapping) mapInfo { return mi } m := &Mapping{ - ID: uint64(len(pm.p.Mapping) + 1), - Start: src.Start, - Limit: src.Limit, - Offset: src.Offset, - File: src.File, - BuildID: src.BuildID, - HasFunctions: src.HasFunctions, - HasFilenames: src.HasFilenames, - HasLineNumbers: src.HasLineNumbers, - HasInlineFrames: src.HasInlineFrames, + ID: uint64(len(pm.p.Mapping) + 1), + Start: src.Start, + Limit: src.Limit, + Offset: src.Offset, + File: src.File, + KernelRelocationSymbol: src.KernelRelocationSymbol, + BuildID: src.BuildID, + HasFunctions: src.HasFunctions, + HasFilenames: src.HasFilenames, + HasLineNumbers: src.HasLineNumbers, + HasInlineFrames: src.HasInlineFrames, } pm.p.Mapping = append(pm.p.Mapping, m) diff --git a/src/cmd/vendor/github.com/google/pprof/profile/profile.go b/src/cmd/vendor/github.com/google/pprof/profile/profile.go index 2590c8ddb42e25ede9dd54e54a80f0286cc7105e..5a3807f978eb6c5f2364892fbb194eedc0ca7638 100644 --- a/src/cmd/vendor/github.com/google/pprof/profile/profile.go +++ b/src/cmd/vendor/github.com/google/pprof/profile/profile.go @@ -106,6 +106,15 @@ type Mapping struct { fileX int64 buildIDX int64 + + // Name of the kernel relocation symbol ("_text" or "_stext"), extracted from File. + // For linux kernel mappings generated by some tools, correct symbolization depends + // on knowing which of the two possible relocation symbols was used for `Start`. + // This is given to us as a suffix in `File` (e.g. "[kernel.kallsyms]_stext"). + // + // Note, this public field is not persisted in the proto. For the purposes of + // copying / merging / hashing profiles, it is considered subsumed by `File`. + KernelRelocationSymbol string } // Location corresponds to Profile.Location diff --git a/src/cmd/vendor/github.com/google/pprof/third_party/d3/LICENSE b/src/cmd/vendor/github.com/google/pprof/third_party/d3/LICENSE deleted file mode 100644 index 1d9d875edb469786a9c6dbae5aaeef9a3bcb2c33..0000000000000000000000000000000000000000 --- a/src/cmd/vendor/github.com/google/pprof/third_party/d3/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright 2010-2017 Mike Bostock -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the author nor the names of contributors may be used to - endorse or promote products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/cmd/vendor/github.com/google/pprof/third_party/d3/README.md b/src/cmd/vendor/github.com/google/pprof/third_party/d3/README.md deleted file mode 100644 index 53e6eb61eba7d24098284accd8fddbe46b39a5e0..0000000000000000000000000000000000000000 --- a/src/cmd/vendor/github.com/google/pprof/third_party/d3/README.md +++ /dev/null @@ -1,119 +0,0 @@ -# Building a customized D3.js bundle - -The D3.js version distributed with pprof is customized to only include the modules required by pprof. - -## Dependencies - -First, it's necessary to pull all bundle dependencies. We will use a JavaScript package manager, [npm](https://www.npmjs.com/), to accomplish that. npm dependencies are declared in a `package.json` file, so create one with the following configuration: - -```js -{ - "name": "d3-pprof", - "version": "1.0.0", - "description": "A d3.js bundle for pprof.", - "scripts": { - "prepare": "rollup -c && uglifyjs d3.js -c -m -o d3.min.js" - }, - "license": "Apache-2.0", - "devDependencies": { - "d3-selection": "1.1.0", - "d3-hierarchy": "1.1.5", - "d3-scale": "1.0.6", - "d3-format": "1.2.0", - "d3-ease": "1.0.3", - "d3-array": "1.2.1", - "d3-collection": "1.0.4", - "d3-transition": "1.1.0", - "rollup": "0.51.8", - "rollup-plugin-node-resolve": "3", - "uglify-js": "3.1.10" - } -} -``` - -Besides the bundle dependencies, the `package.json` file also specifies a script called `prepare`, which will be executed to create the bundle after `Rollup` is installed. - -## Bundler - -The simplest way of creating a custom bundle is to use a bundler, such as [Rollup](https://rollupjs.org/) or [Webpack](https://webpack.js.org/). Rollup will be used in this example. - -First, create a `rollup.config.js` file, containing the configuration Rollup should use to build the bundle. - -```js -import node from "rollup-plugin-node-resolve"; - -export default { - input: "index.js", - output: { - format: "umd", - file: "d3.js" - }, - name: "d3", - plugins: [node()], - sourcemap: false -}; -``` - -Then create an `index.js` file containing all the functions that need to be exported in the bundle. - -```js -export { - select, - selection, - event, -} from "d3-selection"; - -export { - hierarchy, - partition, -} from "d3-hierarchy"; - -export { - scaleLinear, -} from "d3-scale"; - -export { - format, -} from "d3-format"; - -export { - easeCubic, -} from "d3-ease"; - -export { - ascending, -} from "d3-array"; - -export { - map, -} from "d3-collection"; - -export { - transition, -} from "d3-transition"; -``` - -## Building - -Once all files were created, execute the following commands to pull all dependencies and build the bundle. - -``` -% npm install -% npm run prepare -``` - -This will create two files, `d3.js` and `d3.min.js`, the custom D3.js bundle and its minified version respectively. - -# References - -## D3 Custom Bundle - -A demonstration of building a custom D3 4.0 bundle using ES2015 modules and Rollup. - -[bl.ocks.org/mbostock/bb09af4c39c79cffcde4](https://bl.ocks.org/mbostock/bb09af4c39c79cffcde4) - -## d3-pprof - -A repository containing all previously mentioned configuration files and the generated custom bundle. - -[github.com/spiermar/d3-pprof](https://github.com/spiermar/d3-pprof) \ No newline at end of file diff --git a/src/cmd/vendor/github.com/google/pprof/third_party/d3/d3.go b/src/cmd/vendor/github.com/google/pprof/third_party/d3/d3.go deleted file mode 100644 index 7d217c71bf380384acfd45f3695f3eb0786f6805..0000000000000000000000000000000000000000 --- a/src/cmd/vendor/github.com/google/pprof/third_party/d3/d3.go +++ /dev/null @@ -1,4675 +0,0 @@ -// D3.js is a JavaScript library for manipulating documents based on data. -// https://github.com/d3/d3 -// See LICENSE file for license details -// Custom build for pprof (https://github.com/spiermar/d3-pprof) - -package d3 - -// JSSource returns the d3.js file -const JSSource = ` -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (factory((global.d3 = {}))); -}(this, (function (exports) { 'use strict'; - -var xhtml = "http://www.w3.org/1999/xhtml"; - -var namespaces = { - svg: "http://www.w3.org/2000/svg", - xhtml: xhtml, - xlink: "http://www.w3.org/1999/xlink", - xml: "http://www.w3.org/XML/1998/namespace", - xmlns: "http://www.w3.org/2000/xmlns/" -}; - -var namespace = function(name) { - var prefix = name += "", i = prefix.indexOf(":"); - if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); - return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name; -}; - -function creatorInherit(name) { - return function() { - var document = this.ownerDocument, - uri = this.namespaceURI; - return uri === xhtml && document.documentElement.namespaceURI === xhtml - ? document.createElement(name) - : document.createElementNS(uri, name); - }; -} - -function creatorFixed(fullname) { - return function() { - return this.ownerDocument.createElementNS(fullname.space, fullname.local); - }; -} - -var creator = function(name) { - var fullname = namespace(name); - return (fullname.local - ? creatorFixed - : creatorInherit)(fullname); -}; - -var matcher = function(selector) { - return function() { - return this.matches(selector); - }; -}; - -if (typeof document !== "undefined") { - var element = document.documentElement; - if (!element.matches) { - var vendorMatches = element.webkitMatchesSelector - || element.msMatchesSelector - || element.mozMatchesSelector - || element.oMatchesSelector; - matcher = function(selector) { - return function() { - return vendorMatches.call(this, selector); - }; - }; - } -} - -var matcher$1 = matcher; - -var filterEvents = {}; - -exports.event = null; - -if (typeof document !== "undefined") { - var element$1 = document.documentElement; - if (!("onmouseenter" in element$1)) { - filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"}; - } -} - -function filterContextListener(listener, index, group) { - listener = contextListener(listener, index, group); - return function(event) { - var related = event.relatedTarget; - if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) { - listener.call(this, event); - } - }; -} - -function contextListener(listener, index, group) { - return function(event1) { - var event0 = exports.event; // Events can be reentrant (e.g., focus). - exports.event = event1; - try { - listener.call(this, this.__data__, index, group); - } finally { - exports.event = event0; - } - }; -} - -function parseTypenames(typenames) { - return typenames.trim().split(/^|\s+/).map(function(t) { - var name = "", i = t.indexOf("."); - if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); - return {type: t, name: name}; - }); -} - -function onRemove(typename) { - return function() { - var on = this.__on; - if (!on) return; - for (var j = 0, i = -1, m = on.length, o; j < m; ++j) { - if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) { - this.removeEventListener(o.type, o.listener, o.capture); - } else { - on[++i] = o; - } - } - if (++i) on.length = i; - else delete this.__on; - }; -} - -function onAdd(typename, value, capture) { - var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener; - return function(d, i, group) { - var on = this.__on, o, listener = wrap(value, i, group); - if (on) for (var j = 0, m = on.length; j < m; ++j) { - if ((o = on[j]).type === typename.type && o.name === typename.name) { - this.removeEventListener(o.type, o.listener, o.capture); - this.addEventListener(o.type, o.listener = listener, o.capture = capture); - o.value = value; - return; - } - } - this.addEventListener(typename.type, listener, capture); - o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture}; - if (!on) this.__on = [o]; - else on.push(o); - }; -} - -var selection_on = function(typename, value, capture) { - var typenames = parseTypenames(typename + ""), i, n = typenames.length, t; - - if (arguments.length < 2) { - var on = this.node().__on; - if (on) for (var j = 0, m = on.length, o; j < m; ++j) { - for (i = 0, o = on[j]; i < n; ++i) { - if ((t = typenames[i]).type === o.type && t.name === o.name) { - return o.value; - } - } - } - return; - } - - on = value ? onAdd : onRemove; - if (capture == null) capture = false; - for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture)); - return this; -}; - -function none() {} - -var selector = function(selector) { - return selector == null ? none : function() { - return this.querySelector(selector); - }; -}; - -var selection_select = function(select) { - if (typeof select !== "function") select = selector(select); - - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { - if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { - if ("__data__" in node) subnode.__data__ = node.__data__; - subgroup[i] = subnode; - } - } - } - - return new Selection(subgroups, this._parents); -}; - -function empty() { - return []; -} - -var selectorAll = function(selector) { - return selector == null ? empty : function() { - return this.querySelectorAll(selector); - }; -}; - -var selection_selectAll = function(select) { - if (typeof select !== "function") select = selectorAll(select); - - for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - subgroups.push(select.call(node, node.__data__, i, group)); - parents.push(node); - } - } - } - - return new Selection(subgroups, parents); -}; - -var selection_filter = function(match) { - if (typeof match !== "function") match = matcher$1(match); - - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { - if ((node = group[i]) && match.call(node, node.__data__, i, group)) { - subgroup.push(node); - } - } - } - - return new Selection(subgroups, this._parents); -}; - -var sparse = function(update) { - return new Array(update.length); -}; - -var selection_enter = function() { - return new Selection(this._enter || this._groups.map(sparse), this._parents); -}; - -function EnterNode(parent, datum) { - this.ownerDocument = parent.ownerDocument; - this.namespaceURI = parent.namespaceURI; - this._next = null; - this._parent = parent; - this.__data__ = datum; -} - -EnterNode.prototype = { - constructor: EnterNode, - appendChild: function(child) { return this._parent.insertBefore(child, this._next); }, - insertBefore: function(child, next) { return this._parent.insertBefore(child, next); }, - querySelector: function(selector) { return this._parent.querySelector(selector); }, - querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); } -}; - -var constant = function(x) { - return function() { - return x; - }; -}; - -var keyPrefix = "$"; // Protect against keys like “__proto__â€. - -function bindIndex(parent, group, enter, update, exit, data) { - var i = 0, - node, - groupLength = group.length, - dataLength = data.length; - - // Put any non-null nodes that fit into update. - // Put any null nodes into enter. - // Put any remaining data into enter. - for (; i < dataLength; ++i) { - if (node = group[i]) { - node.__data__ = data[i]; - update[i] = node; - } else { - enter[i] = new EnterNode(parent, data[i]); - } - } - - // Put any non-null nodes that don’t fit into exit. - for (; i < groupLength; ++i) { - if (node = group[i]) { - exit[i] = node; - } - } -} - -function bindKey(parent, group, enter, update, exit, data, key) { - var i, - node, - nodeByKeyValue = {}, - groupLength = group.length, - dataLength = data.length, - keyValues = new Array(groupLength), - keyValue; - - // Compute the key for each node. - // If multiple nodes have the same key, the duplicates are added to exit. - for (i = 0; i < groupLength; ++i) { - if (node = group[i]) { - keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group); - if (keyValue in nodeByKeyValue) { - exit[i] = node; - } else { - nodeByKeyValue[keyValue] = node; - } - } - } - - // Compute the key for each datum. - // If there a node associated with this key, join and add it to update. - // If there is not (or the key is a duplicate), add it to enter. - for (i = 0; i < dataLength; ++i) { - keyValue = keyPrefix + key.call(parent, data[i], i, data); - if (node = nodeByKeyValue[keyValue]) { - update[i] = node; - node.__data__ = data[i]; - nodeByKeyValue[keyValue] = null; - } else { - enter[i] = new EnterNode(parent, data[i]); - } - } - - // Add any remaining nodes that were not bound to data to exit. - for (i = 0; i < groupLength; ++i) { - if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) { - exit[i] = node; - } - } -} - -var selection_data = function(value, key) { - if (!value) { - data = new Array(this.size()), j = -1; - this.each(function(d) { data[++j] = d; }); - return data; - } - - var bind = key ? bindKey : bindIndex, - parents = this._parents, - groups = this._groups; - - if (typeof value !== "function") value = constant(value); - - for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) { - var parent = parents[j], - group = groups[j], - groupLength = group.length, - data = value.call(parent, parent && parent.__data__, j, parents), - dataLength = data.length, - enterGroup = enter[j] = new Array(dataLength), - updateGroup = update[j] = new Array(dataLength), - exitGroup = exit[j] = new Array(groupLength); - - bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); - - // Now connect the enter nodes to their following update node, such that - // appendChild can insert the materialized enter node before this node, - // rather than at the end of the parent node. - for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) { - if (previous = enterGroup[i0]) { - if (i0 >= i1) i1 = i0 + 1; - while (!(next = updateGroup[i1]) && ++i1 < dataLength); - previous._next = next || null; - } - } - } - - update = new Selection(update, parents); - update._enter = enter; - update._exit = exit; - return update; -}; - -var selection_exit = function() { - return new Selection(this._exit || this._groups.map(sparse), this._parents); -}; - -var selection_merge = function(selection$$1) { - - for (var groups0 = this._groups, groups1 = selection$$1._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { - for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { - if (node = group0[i] || group1[i]) { - merge[i] = node; - } - } - } - - for (; j < m0; ++j) { - merges[j] = groups0[j]; - } - - return new Selection(merges, this._parents); -}; - -var selection_order = function() { - - for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) { - for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) { - if (node = group[i]) { - if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); - next = node; - } - } - } - - return this; -}; - -var selection_sort = function(compare) { - if (!compare) compare = ascending; - - function compareNode(a, b) { - return a && b ? compare(a.__data__, b.__data__) : !a - !b; - } - - for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) { - if (node = group[i]) { - sortgroup[i] = node; - } - } - sortgroup.sort(compareNode); - } - - return new Selection(sortgroups, this._parents).order(); -}; - -function ascending(a, b) { - return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; -} - -var selection_call = function() { - var callback = arguments[0]; - arguments[0] = this; - callback.apply(null, arguments); - return this; -}; - -var selection_nodes = function() { - var nodes = new Array(this.size()), i = -1; - this.each(function() { nodes[++i] = this; }); - return nodes; -}; - -var selection_node = function() { - - for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { - for (var group = groups[j], i = 0, n = group.length; i < n; ++i) { - var node = group[i]; - if (node) return node; - } - } - - return null; -}; - -var selection_size = function() { - var size = 0; - this.each(function() { ++size; }); - return size; -}; - -var selection_empty = function() { - return !this.node(); -}; - -var selection_each = function(callback) { - - for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { - for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) { - if (node = group[i]) callback.call(node, node.__data__, i, group); - } - } - - return this; -}; - -function attrRemove(name) { - return function() { - this.removeAttribute(name); - }; -} - -function attrRemoveNS(fullname) { - return function() { - this.removeAttributeNS(fullname.space, fullname.local); - }; -} - -function attrConstant(name, value) { - return function() { - this.setAttribute(name, value); - }; -} - -function attrConstantNS(fullname, value) { - return function() { - this.setAttributeNS(fullname.space, fullname.local, value); - }; -} - -function attrFunction(name, value) { - return function() { - var v = value.apply(this, arguments); - if (v == null) this.removeAttribute(name); - else this.setAttribute(name, v); - }; -} - -function attrFunctionNS(fullname, value) { - return function() { - var v = value.apply(this, arguments); - if (v == null) this.removeAttributeNS(fullname.space, fullname.local); - else this.setAttributeNS(fullname.space, fullname.local, v); - }; -} - -var selection_attr = function(name, value) { - var fullname = namespace(name); - - if (arguments.length < 2) { - var node = this.node(); - return fullname.local - ? node.getAttributeNS(fullname.space, fullname.local) - : node.getAttribute(fullname); - } - - return this.each((value == null - ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function" - ? (fullname.local ? attrFunctionNS : attrFunction) - : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value)); -}; - -var defaultView = function(node) { - return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node - || (node.document && node) // node is a Window - || node.defaultView; // node is a Document -}; - -function styleRemove(name) { - return function() { - this.style.removeProperty(name); - }; -} - -function styleConstant(name, value, priority) { - return function() { - this.style.setProperty(name, value, priority); - }; -} - -function styleFunction(name, value, priority) { - return function() { - var v = value.apply(this, arguments); - if (v == null) this.style.removeProperty(name); - else this.style.setProperty(name, v, priority); - }; -} - -var selection_style = function(name, value, priority) { - return arguments.length > 1 - ? this.each((value == null - ? styleRemove : typeof value === "function" - ? styleFunction - : styleConstant)(name, value, priority == null ? "" : priority)) - : styleValue(this.node(), name); -}; - -function styleValue(node, name) { - return node.style.getPropertyValue(name) - || defaultView(node).getComputedStyle(node, null).getPropertyValue(name); -} - -function propertyRemove(name) { - return function() { - delete this[name]; - }; -} - -function propertyConstant(name, value) { - return function() { - this[name] = value; - }; -} - -function propertyFunction(name, value) { - return function() { - var v = value.apply(this, arguments); - if (v == null) delete this[name]; - else this[name] = v; - }; -} - -var selection_property = function(name, value) { - return arguments.length > 1 - ? this.each((value == null - ? propertyRemove : typeof value === "function" - ? propertyFunction - : propertyConstant)(name, value)) - : this.node()[name]; -}; - -function classArray(string) { - return string.trim().split(/^|\s+/); -} - -function classList(node) { - return node.classList || new ClassList(node); -} - -function ClassList(node) { - this._node = node; - this._names = classArray(node.getAttribute("class") || ""); -} - -ClassList.prototype = { - add: function(name) { - var i = this._names.indexOf(name); - if (i < 0) { - this._names.push(name); - this._node.setAttribute("class", this._names.join(" ")); - } - }, - remove: function(name) { - var i = this._names.indexOf(name); - if (i >= 0) { - this._names.splice(i, 1); - this._node.setAttribute("class", this._names.join(" ")); - } - }, - contains: function(name) { - return this._names.indexOf(name) >= 0; - } -}; - -function classedAdd(node, names) { - var list = classList(node), i = -1, n = names.length; - while (++i < n) list.add(names[i]); -} - -function classedRemove(node, names) { - var list = classList(node), i = -1, n = names.length; - while (++i < n) list.remove(names[i]); -} - -function classedTrue(names) { - return function() { - classedAdd(this, names); - }; -} - -function classedFalse(names) { - return function() { - classedRemove(this, names); - }; -} - -function classedFunction(names, value) { - return function() { - (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names); - }; -} - -var selection_classed = function(name, value) { - var names = classArray(name + ""); - - if (arguments.length < 2) { - var list = classList(this.node()), i = -1, n = names.length; - while (++i < n) if (!list.contains(names[i])) return false; - return true; - } - - return this.each((typeof value === "function" - ? classedFunction : value - ? classedTrue - : classedFalse)(names, value)); -}; - -function textRemove() { - this.textContent = ""; -} - -function textConstant(value) { - return function() { - this.textContent = value; - }; -} - -function textFunction(value) { - return function() { - var v = value.apply(this, arguments); - this.textContent = v == null ? "" : v; - }; -} - -var selection_text = function(value) { - return arguments.length - ? this.each(value == null - ? textRemove : (typeof value === "function" - ? textFunction - : textConstant)(value)) - : this.node().textContent; -}; - -function htmlRemove() { - this.innerHTML = ""; -} - -function htmlConstant(value) { - return function() { - this.innerHTML = value; - }; -} - -function htmlFunction(value) { - return function() { - var v = value.apply(this, arguments); - this.innerHTML = v == null ? "" : v; - }; -} - -var selection_html = function(value) { - return arguments.length - ? this.each(value == null - ? htmlRemove : (typeof value === "function" - ? htmlFunction - : htmlConstant)(value)) - : this.node().innerHTML; -}; - -function raise() { - if (this.nextSibling) this.parentNode.appendChild(this); -} - -var selection_raise = function() { - return this.each(raise); -}; - -function lower() { - if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild); -} - -var selection_lower = function() { - return this.each(lower); -}; - -var selection_append = function(name) { - var create = typeof name === "function" ? name : creator(name); - return this.select(function() { - return this.appendChild(create.apply(this, arguments)); - }); -}; - -function constantNull() { - return null; -} - -var selection_insert = function(name, before) { - var create = typeof name === "function" ? name : creator(name), - select = before == null ? constantNull : typeof before === "function" ? before : selector(before); - return this.select(function() { - return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null); - }); -}; - -function remove() { - var parent = this.parentNode; - if (parent) parent.removeChild(this); -} - -var selection_remove = function() { - return this.each(remove); -}; - -var selection_datum = function(value) { - return arguments.length - ? this.property("__data__", value) - : this.node().__data__; -}; - -function dispatchEvent(node, type, params) { - var window = defaultView(node), - event = window.CustomEvent; - - if (typeof event === "function") { - event = new event(type, params); - } else { - event = window.document.createEvent("Event"); - if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail; - else event.initEvent(type, false, false); - } - - node.dispatchEvent(event); -} - -function dispatchConstant(type, params) { - return function() { - return dispatchEvent(this, type, params); - }; -} - -function dispatchFunction(type, params) { - return function() { - return dispatchEvent(this, type, params.apply(this, arguments)); - }; -} - -var selection_dispatch = function(type, params) { - return this.each((typeof params === "function" - ? dispatchFunction - : dispatchConstant)(type, params)); -}; - -var root = [null]; - -function Selection(groups, parents) { - this._groups = groups; - this._parents = parents; -} - -function selection() { - return new Selection([[document.documentElement]], root); -} - -Selection.prototype = selection.prototype = { - constructor: Selection, - select: selection_select, - selectAll: selection_selectAll, - filter: selection_filter, - data: selection_data, - enter: selection_enter, - exit: selection_exit, - merge: selection_merge, - order: selection_order, - sort: selection_sort, - call: selection_call, - nodes: selection_nodes, - node: selection_node, - size: selection_size, - empty: selection_empty, - each: selection_each, - attr: selection_attr, - style: selection_style, - property: selection_property, - classed: selection_classed, - text: selection_text, - html: selection_html, - raise: selection_raise, - lower: selection_lower, - append: selection_append, - insert: selection_insert, - remove: selection_remove, - datum: selection_datum, - on: selection_on, - dispatch: selection_dispatch -}; - -var select = function(selector) { - return typeof selector === "string" - ? new Selection([[document.querySelector(selector)]], [document.documentElement]) - : new Selection([[selector]], root); -}; - -function count(node) { - var sum = 0, - children = node.children, - i = children && children.length; - if (!i) sum = 1; - else while (--i >= 0) sum += children[i].value; - node.value = sum; -} - -var node_count = function() { - return this.eachAfter(count); -}; - -var node_each = function(callback) { - var node = this, current, next = [node], children, i, n; - do { - current = next.reverse(), next = []; - while (node = current.pop()) { - callback(node), children = node.children; - if (children) for (i = 0, n = children.length; i < n; ++i) { - next.push(children[i]); - } - } - } while (next.length); - return this; -}; - -var node_eachBefore = function(callback) { - var node = this, nodes = [node], children, i; - while (node = nodes.pop()) { - callback(node), children = node.children; - if (children) for (i = children.length - 1; i >= 0; --i) { - nodes.push(children[i]); - } - } - return this; -}; - -var node_eachAfter = function(callback) { - var node = this, nodes = [node], next = [], children, i, n; - while (node = nodes.pop()) { - next.push(node), children = node.children; - if (children) for (i = 0, n = children.length; i < n; ++i) { - nodes.push(children[i]); - } - } - while (node = next.pop()) { - callback(node); - } - return this; -}; - -var node_sum = function(value) { - return this.eachAfter(function(node) { - var sum = +value(node.data) || 0, - children = node.children, - i = children && children.length; - while (--i >= 0) sum += children[i].value; - node.value = sum; - }); -}; - -var node_sort = function(compare) { - return this.eachBefore(function(node) { - if (node.children) { - node.children.sort(compare); - } - }); -}; - -var node_path = function(end) { - var start = this, - ancestor = leastCommonAncestor(start, end), - nodes = [start]; - while (start !== ancestor) { - start = start.parent; - nodes.push(start); - } - var k = nodes.length; - while (end !== ancestor) { - nodes.splice(k, 0, end); - end = end.parent; - } - return nodes; -}; - -function leastCommonAncestor(a, b) { - if (a === b) return a; - var aNodes = a.ancestors(), - bNodes = b.ancestors(), - c = null; - a = aNodes.pop(); - b = bNodes.pop(); - while (a === b) { - c = a; - a = aNodes.pop(); - b = bNodes.pop(); - } - return c; -} - -var node_ancestors = function() { - var node = this, nodes = [node]; - while (node = node.parent) { - nodes.push(node); - } - return nodes; -}; - -var node_descendants = function() { - var nodes = []; - this.each(function(node) { - nodes.push(node); - }); - return nodes; -}; - -var node_leaves = function() { - var leaves = []; - this.eachBefore(function(node) { - if (!node.children) { - leaves.push(node); - } - }); - return leaves; -}; - -var node_links = function() { - var root = this, links = []; - root.each(function(node) { - if (node !== root) { // Don’t include the root’s parent, if any. - links.push({source: node.parent, target: node}); - } - }); - return links; -}; - -function hierarchy(data, children) { - var root = new Node(data), - valued = +data.value && (root.value = data.value), - node, - nodes = [root], - child, - childs, - i, - n; - - if (children == null) children = defaultChildren; - - while (node = nodes.pop()) { - if (valued) node.value = +node.data.value; - if ((childs = children(node.data)) && (n = childs.length)) { - node.children = new Array(n); - for (i = n - 1; i >= 0; --i) { - nodes.push(child = node.children[i] = new Node(childs[i])); - child.parent = node; - child.depth = node.depth + 1; - } - } - } - - return root.eachBefore(computeHeight); -} - -function node_copy() { - return hierarchy(this).eachBefore(copyData); -} - -function defaultChildren(d) { - return d.children; -} - -function copyData(node) { - node.data = node.data.data; -} - -function computeHeight(node) { - var height = 0; - do node.height = height; - while ((node = node.parent) && (node.height < ++height)); -} - -function Node(data) { - this.data = data; - this.depth = - this.height = 0; - this.parent = null; -} - -Node.prototype = hierarchy.prototype = { - constructor: Node, - count: node_count, - each: node_each, - eachAfter: node_eachAfter, - eachBefore: node_eachBefore, - sum: node_sum, - sort: node_sort, - path: node_path, - ancestors: node_ancestors, - descendants: node_descendants, - leaves: node_leaves, - links: node_links, - copy: node_copy -}; - -var roundNode = function(node) { - node.x0 = Math.round(node.x0); - node.y0 = Math.round(node.y0); - node.x1 = Math.round(node.x1); - node.y1 = Math.round(node.y1); -}; - -var treemapDice = function(parent, x0, y0, x1, y1) { - var nodes = parent.children, - node, - i = -1, - n = nodes.length, - k = parent.value && (x1 - x0) / parent.value; - - while (++i < n) { - node = nodes[i], node.y0 = y0, node.y1 = y1; - node.x0 = x0, node.x1 = x0 += node.value * k; - } -}; - -var partition = function() { - var dx = 1, - dy = 1, - padding = 0, - round = false; - - function partition(root) { - var n = root.height + 1; - root.x0 = - root.y0 = padding; - root.x1 = dx; - root.y1 = dy / n; - root.eachBefore(positionNode(dy, n)); - if (round) root.eachBefore(roundNode); - return root; - } - - function positionNode(dy, n) { - return function(node) { - if (node.children) { - treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n); - } - var x0 = node.x0, - y0 = node.y0, - x1 = node.x1 - padding, - y1 = node.y1 - padding; - if (x1 < x0) x0 = x1 = (x0 + x1) / 2; - if (y1 < y0) y0 = y1 = (y0 + y1) / 2; - node.x0 = x0; - node.y0 = y0; - node.x1 = x1; - node.y1 = y1; - }; - } - - partition.round = function(x) { - return arguments.length ? (round = !!x, partition) : round; - }; - - partition.size = function(x) { - return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy]; - }; - - partition.padding = function(x) { - return arguments.length ? (padding = +x, partition) : padding; - }; - - return partition; -}; - -var ascending$1 = function(a, b) { - return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; -}; - -var bisector = function(compare) { - if (compare.length === 1) compare = ascendingComparator(compare); - return { - left: function(a, x, lo, hi) { - if (lo == null) lo = 0; - if (hi == null) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) < 0) lo = mid + 1; - else hi = mid; - } - return lo; - }, - right: function(a, x, lo, hi) { - if (lo == null) lo = 0; - if (hi == null) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) > 0) hi = mid; - else lo = mid + 1; - } - return lo; - } - }; -}; - -function ascendingComparator(f) { - return function(d, x) { - return ascending$1(f(d), x); - }; -} - -var ascendingBisect = bisector(ascending$1); -var bisectRight = ascendingBisect.right; - -var e10 = Math.sqrt(50); -var e5 = Math.sqrt(10); -var e2 = Math.sqrt(2); - -var ticks = function(start, stop, count) { - var reverse, - i = -1, - n, - ticks, - step; - - stop = +stop, start = +start, count = +count; - if (start === stop && count > 0) return [start]; - if (reverse = stop < start) n = start, start = stop, stop = n; - if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return []; - - if (step > 0) { - start = Math.ceil(start / step); - stop = Math.floor(stop / step); - ticks = new Array(n = Math.ceil(stop - start + 1)); - while (++i < n) ticks[i] = (start + i) * step; - } else { - start = Math.floor(start * step); - stop = Math.ceil(stop * step); - ticks = new Array(n = Math.ceil(start - stop + 1)); - while (++i < n) ticks[i] = (start - i) / step; - } - - if (reverse) ticks.reverse(); - - return ticks; -}; - -function tickIncrement(start, stop, count) { - var step = (stop - start) / Math.max(0, count), - power = Math.floor(Math.log(step) / Math.LN10), - error = step / Math.pow(10, power); - return power >= 0 - ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) - : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1); -} - -function tickStep(start, stop, count) { - var step0 = Math.abs(stop - start) / Math.max(0, count), - step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)), - error = step0 / step1; - if (error >= e10) step1 *= 10; - else if (error >= e5) step1 *= 5; - else if (error >= e2) step1 *= 2; - return stop < start ? -step1 : step1; -} - -var prefix = "$"; - -function Map() {} - -Map.prototype = map$1.prototype = { - constructor: Map, - has: function(key) { - return (prefix + key) in this; - }, - get: function(key) { - return this[prefix + key]; - }, - set: function(key, value) { - this[prefix + key] = value; - return this; - }, - remove: function(key) { - var property = prefix + key; - return property in this && delete this[property]; - }, - clear: function() { - for (var property in this) if (property[0] === prefix) delete this[property]; - }, - keys: function() { - var keys = []; - for (var property in this) if (property[0] === prefix) keys.push(property.slice(1)); - return keys; - }, - values: function() { - var values = []; - for (var property in this) if (property[0] === prefix) values.push(this[property]); - return values; - }, - entries: function() { - var entries = []; - for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]}); - return entries; - }, - size: function() { - var size = 0; - for (var property in this) if (property[0] === prefix) ++size; - return size; - }, - empty: function() { - for (var property in this) if (property[0] === prefix) return false; - return true; - }, - each: function(f) { - for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this); - } -}; - -function map$1(object, f) { - var map = new Map; - - // Copy constructor. - if (object instanceof Map) object.each(function(value, key) { map.set(key, value); }); - - // Index array by numeric index or specified key function. - else if (Array.isArray(object)) { - var i = -1, - n = object.length, - o; - - if (f == null) while (++i < n) map.set(i, object[i]); - else while (++i < n) map.set(f(o = object[i], i, object), o); - } - - // Convert object to map. - else if (object) for (var key in object) map.set(key, object[key]); - - return map; -} - -function Set() {} - -var proto = map$1.prototype; - -Set.prototype = set.prototype = { - constructor: Set, - has: proto.has, - add: function(value) { - value += ""; - this[prefix + value] = value; - return this; - }, - remove: proto.remove, - clear: proto.clear, - values: proto.keys, - size: proto.size, - empty: proto.empty, - each: proto.each -}; - -function set(object, f) { - var set = new Set; - - // Copy constructor. - if (object instanceof Set) object.each(function(value) { set.add(value); }); - - // Otherwise, assume it’s an array. - else if (object) { - var i = -1, n = object.length; - if (f == null) while (++i < n) set.add(object[i]); - else while (++i < n) set.add(f(object[i], i, object)); - } - - return set; -} - -var array$1 = Array.prototype; - -var map$3 = array$1.map; -var slice$2 = array$1.slice; - -var define = function(constructor, factory, prototype) { - constructor.prototype = factory.prototype = prototype; - prototype.constructor = constructor; -}; - -function extend(parent, definition) { - var prototype = Object.create(parent.prototype); - for (var key in definition) prototype[key] = definition[key]; - return prototype; -} - -function Color() {} - -var darker = 0.7; -var brighter = 1 / darker; - -var reI = "\\s*([+-]?\\d+)\\s*"; -var reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*"; -var reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*"; -var reHex3 = /^#([0-9a-f]{3})$/; -var reHex6 = /^#([0-9a-f]{6})$/; -var reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"); -var reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"); -var reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"); -var reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"); -var reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"); -var reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$"); - -var named = { - aliceblue: 0xf0f8ff, - antiquewhite: 0xfaebd7, - aqua: 0x00ffff, - aquamarine: 0x7fffd4, - azure: 0xf0ffff, - beige: 0xf5f5dc, - bisque: 0xffe4c4, - black: 0x000000, - blanchedalmond: 0xffebcd, - blue: 0x0000ff, - blueviolet: 0x8a2be2, - brown: 0xa52a2a, - burlywood: 0xdeb887, - cadetblue: 0x5f9ea0, - chartreuse: 0x7fff00, - chocolate: 0xd2691e, - coral: 0xff7f50, - cornflowerblue: 0x6495ed, - cornsilk: 0xfff8dc, - crimson: 0xdc143c, - cyan: 0x00ffff, - darkblue: 0x00008b, - darkcyan: 0x008b8b, - darkgoldenrod: 0xb8860b, - darkgray: 0xa9a9a9, - darkgreen: 0x006400, - darkgrey: 0xa9a9a9, - darkkhaki: 0xbdb76b, - darkmagenta: 0x8b008b, - darkolivegreen: 0x556b2f, - darkorange: 0xff8c00, - darkorchid: 0x9932cc, - darkred: 0x8b0000, - darksalmon: 0xe9967a, - darkseagreen: 0x8fbc8f, - darkslateblue: 0x483d8b, - darkslategray: 0x2f4f4f, - darkslategrey: 0x2f4f4f, - darkturquoise: 0x00ced1, - darkviolet: 0x9400d3, - deeppink: 0xff1493, - deepskyblue: 0x00bfff, - dimgray: 0x696969, - dimgrey: 0x696969, - dodgerblue: 0x1e90ff, - firebrick: 0xb22222, - floralwhite: 0xfffaf0, - forestgreen: 0x228b22, - fuchsia: 0xff00ff, - gainsboro: 0xdcdcdc, - ghostwhite: 0xf8f8ff, - gold: 0xffd700, - goldenrod: 0xdaa520, - gray: 0x808080, - green: 0x008000, - greenyellow: 0xadff2f, - grey: 0x808080, - honeydew: 0xf0fff0, - hotpink: 0xff69b4, - indianred: 0xcd5c5c, - indigo: 0x4b0082, - ivory: 0xfffff0, - khaki: 0xf0e68c, - lavender: 0xe6e6fa, - lavenderblush: 0xfff0f5, - lawngreen: 0x7cfc00, - lemonchiffon: 0xfffacd, - lightblue: 0xadd8e6, - lightcoral: 0xf08080, - lightcyan: 0xe0ffff, - lightgoldenrodyellow: 0xfafad2, - lightgray: 0xd3d3d3, - lightgreen: 0x90ee90, - lightgrey: 0xd3d3d3, - lightpink: 0xffb6c1, - lightsalmon: 0xffa07a, - lightseagreen: 0x20b2aa, - lightskyblue: 0x87cefa, - lightslategray: 0x778899, - lightslategrey: 0x778899, - lightsteelblue: 0xb0c4de, - lightyellow: 0xffffe0, - lime: 0x00ff00, - limegreen: 0x32cd32, - linen: 0xfaf0e6, - magenta: 0xff00ff, - maroon: 0x800000, - mediumaquamarine: 0x66cdaa, - mediumblue: 0x0000cd, - mediumorchid: 0xba55d3, - mediumpurple: 0x9370db, - mediumseagreen: 0x3cb371, - mediumslateblue: 0x7b68ee, - mediumspringgreen: 0x00fa9a, - mediumturquoise: 0x48d1cc, - mediumvioletred: 0xc71585, - midnightblue: 0x191970, - mintcream: 0xf5fffa, - mistyrose: 0xffe4e1, - moccasin: 0xffe4b5, - navajowhite: 0xffdead, - navy: 0x000080, - oldlace: 0xfdf5e6, - olive: 0x808000, - olivedrab: 0x6b8e23, - orange: 0xffa500, - orangered: 0xff4500, - orchid: 0xda70d6, - palegoldenrod: 0xeee8aa, - palegreen: 0x98fb98, - paleturquoise: 0xafeeee, - palevioletred: 0xdb7093, - papayawhip: 0xffefd5, - peachpuff: 0xffdab9, - peru: 0xcd853f, - pink: 0xffc0cb, - plum: 0xdda0dd, - powderblue: 0xb0e0e6, - purple: 0x800080, - rebeccapurple: 0x663399, - red: 0xff0000, - rosybrown: 0xbc8f8f, - royalblue: 0x4169e1, - saddlebrown: 0x8b4513, - salmon: 0xfa8072, - sandybrown: 0xf4a460, - seagreen: 0x2e8b57, - seashell: 0xfff5ee, - sienna: 0xa0522d, - silver: 0xc0c0c0, - skyblue: 0x87ceeb, - slateblue: 0x6a5acd, - slategray: 0x708090, - slategrey: 0x708090, - snow: 0xfffafa, - springgreen: 0x00ff7f, - steelblue: 0x4682b4, - tan: 0xd2b48c, - teal: 0x008080, - thistle: 0xd8bfd8, - tomato: 0xff6347, - turquoise: 0x40e0d0, - violet: 0xee82ee, - wheat: 0xf5deb3, - white: 0xffffff, - whitesmoke: 0xf5f5f5, - yellow: 0xffff00, - yellowgreen: 0x9acd32 -}; - -define(Color, color, { - displayable: function() { - return this.rgb().displayable(); - }, - toString: function() { - return this.rgb() + ""; - } -}); - -function color(format) { - var m; - format = (format + "").trim().toLowerCase(); - return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1)) // #f00 - : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000 - : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0) - : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%) - : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1) - : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1) - : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%) - : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1) - : named.hasOwnProperty(format) ? rgbn(named[format]) - : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) - : null; -} - -function rgbn(n) { - return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1); -} - -function rgba(r, g, b, a) { - if (a <= 0) r = g = b = NaN; - return new Rgb(r, g, b, a); -} - -function rgbConvert(o) { - if (!(o instanceof Color)) o = color(o); - if (!o) return new Rgb; - o = o.rgb(); - return new Rgb(o.r, o.g, o.b, o.opacity); -} - -function rgb(r, g, b, opacity) { - return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); -} - -function Rgb(r, g, b, opacity) { - this.r = +r; - this.g = +g; - this.b = +b; - this.opacity = +opacity; -} - -define(Rgb, rgb, extend(Color, { - brighter: function(k) { - k = k == null ? brighter : Math.pow(brighter, k); - return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); - }, - darker: function(k) { - k = k == null ? darker : Math.pow(darker, k); - return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); - }, - rgb: function() { - return this; - }, - displayable: function() { - return (0 <= this.r && this.r <= 255) - && (0 <= this.g && this.g <= 255) - && (0 <= this.b && this.b <= 255) - && (0 <= this.opacity && this.opacity <= 1); - }, - toString: function() { - var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a)); - return (a === 1 ? "rgb(" : "rgba(") - + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " - + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " - + Math.max(0, Math.min(255, Math.round(this.b) || 0)) - + (a === 1 ? ")" : ", " + a + ")"); - } -})); - -function hsla(h, s, l, a) { - if (a <= 0) h = s = l = NaN; - else if (l <= 0 || l >= 1) h = s = NaN; - else if (s <= 0) h = NaN; - return new Hsl(h, s, l, a); -} - -function hslConvert(o) { - if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity); - if (!(o instanceof Color)) o = color(o); - if (!o) return new Hsl; - if (o instanceof Hsl) return o; - o = o.rgb(); - var r = o.r / 255, - g = o.g / 255, - b = o.b / 255, - min = Math.min(r, g, b), - max = Math.max(r, g, b), - h = NaN, - s = max - min, - l = (max + min) / 2; - if (s) { - if (r === max) h = (g - b) / s + (g < b) * 6; - else if (g === max) h = (b - r) / s + 2; - else h = (r - g) / s + 4; - s /= l < 0.5 ? max + min : 2 - max - min; - h *= 60; - } else { - s = l > 0 && l < 1 ? 0 : h; - } - return new Hsl(h, s, l, o.opacity); -} - -function hsl(h, s, l, opacity) { - return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); -} - -function Hsl(h, s, l, opacity) { - this.h = +h; - this.s = +s; - this.l = +l; - this.opacity = +opacity; -} - -define(Hsl, hsl, extend(Color, { - brighter: function(k) { - k = k == null ? brighter : Math.pow(brighter, k); - return new Hsl(this.h, this.s, this.l * k, this.opacity); - }, - darker: function(k) { - k = k == null ? darker : Math.pow(darker, k); - return new Hsl(this.h, this.s, this.l * k, this.opacity); - }, - rgb: function() { - var h = this.h % 360 + (this.h < 0) * 360, - s = isNaN(h) || isNaN(this.s) ? 0 : this.s, - l = this.l, - m2 = l + (l < 0.5 ? l : 1 - l) * s, - m1 = 2 * l - m2; - return new Rgb( - hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), - hsl2rgb(h, m1, m2), - hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), - this.opacity - ); - }, - displayable: function() { - return (0 <= this.s && this.s <= 1 || isNaN(this.s)) - && (0 <= this.l && this.l <= 1) - && (0 <= this.opacity && this.opacity <= 1); - } -})); - -/* From FvD 13.37, CSS Color Module Level 3 */ -function hsl2rgb(h, m1, m2) { - return (h < 60 ? m1 + (m2 - m1) * h / 60 - : h < 180 ? m2 - : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 - : m1) * 255; -} - -var deg2rad = Math.PI / 180; -var rad2deg = 180 / Math.PI; - -var Kn = 18; -var Xn = 0.950470; -var Yn = 1; -var Zn = 1.088830; -var t0 = 4 / 29; -var t1 = 6 / 29; -var t2 = 3 * t1 * t1; -var t3 = t1 * t1 * t1; - -function labConvert(o) { - if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity); - if (o instanceof Hcl) { - var h = o.h * deg2rad; - return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity); - } - if (!(o instanceof Rgb)) o = rgbConvert(o); - var b = rgb2xyz(o.r), - a = rgb2xyz(o.g), - l = rgb2xyz(o.b), - x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn), - y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn), - z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn); - return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity); -} - -function lab(l, a, b, opacity) { - return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity); -} - -function Lab(l, a, b, opacity) { - this.l = +l; - this.a = +a; - this.b = +b; - this.opacity = +opacity; -} - -define(Lab, lab, extend(Color, { - brighter: function(k) { - return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); - }, - darker: function(k) { - return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); - }, - rgb: function() { - var y = (this.l + 16) / 116, - x = isNaN(this.a) ? y : y + this.a / 500, - z = isNaN(this.b) ? y : y - this.b / 200; - y = Yn * lab2xyz(y); - x = Xn * lab2xyz(x); - z = Zn * lab2xyz(z); - return new Rgb( - xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB - xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z), - xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z), - this.opacity - ); - } -})); - -function xyz2lab(t) { - return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0; -} - -function lab2xyz(t) { - return t > t1 ? t * t * t : t2 * (t - t0); -} - -function xyz2rgb(x) { - return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055); -} - -function rgb2xyz(x) { - return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4); -} - -function hclConvert(o) { - if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity); - if (!(o instanceof Lab)) o = labConvert(o); - var h = Math.atan2(o.b, o.a) * rad2deg; - return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity); -} - -function hcl(h, c, l, opacity) { - return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity); -} - -function Hcl(h, c, l, opacity) { - this.h = +h; - this.c = +c; - this.l = +l; - this.opacity = +opacity; -} - -define(Hcl, hcl, extend(Color, { - brighter: function(k) { - return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity); - }, - darker: function(k) { - return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity); - }, - rgb: function() { - return labConvert(this).rgb(); - } -})); - -var A = -0.14861; -var B = +1.78277; -var C = -0.29227; -var D = -0.90649; -var E = +1.97294; -var ED = E * D; -var EB = E * B; -var BC_DA = B * C - D * A; - -function cubehelixConvert(o) { - if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity); - if (!(o instanceof Rgb)) o = rgbConvert(o); - var r = o.r / 255, - g = o.g / 255, - b = o.b / 255, - l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB), - bl = b - l, - k = (E * (g - l) - C * bl) / D, - s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1 - h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN; - return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity); -} - -function cubehelix(h, s, l, opacity) { - return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity); -} - -function Cubehelix(h, s, l, opacity) { - this.h = +h; - this.s = +s; - this.l = +l; - this.opacity = +opacity; -} - -define(Cubehelix, cubehelix, extend(Color, { - brighter: function(k) { - k = k == null ? brighter : Math.pow(brighter, k); - return new Cubehelix(this.h, this.s, this.l * k, this.opacity); - }, - darker: function(k) { - k = k == null ? darker : Math.pow(darker, k); - return new Cubehelix(this.h, this.s, this.l * k, this.opacity); - }, - rgb: function() { - var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad, - l = +this.l, - a = isNaN(this.s) ? 0 : this.s * l * (1 - l), - cosh = Math.cos(h), - sinh = Math.sin(h); - return new Rgb( - 255 * (l + a * (A * cosh + B * sinh)), - 255 * (l + a * (C * cosh + D * sinh)), - 255 * (l + a * (E * cosh)), - this.opacity - ); - } -})); - -var constant$3 = function(x) { - return function() { - return x; - }; -}; - -function linear$1(a, d) { - return function(t) { - return a + t * d; - }; -} - -function exponential(a, b, y) { - return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) { - return Math.pow(a + t * b, y); - }; -} - -function hue(a, b) { - var d = b - a; - return d ? linear$1(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$3(isNaN(a) ? b : a); -} - -function gamma(y) { - return (y = +y) === 1 ? nogamma : function(a, b) { - return b - a ? exponential(a, b, y) : constant$3(isNaN(a) ? b : a); - }; -} - -function nogamma(a, b) { - var d = b - a; - return d ? linear$1(a, d) : constant$3(isNaN(a) ? b : a); -} - -var interpolateRgb = (function rgbGamma(y) { - var color$$1 = gamma(y); - - function rgb$$1(start, end) { - var r = color$$1((start = rgb(start)).r, (end = rgb(end)).r), - g = color$$1(start.g, end.g), - b = color$$1(start.b, end.b), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.r = r(t); - start.g = g(t); - start.b = b(t); - start.opacity = opacity(t); - return start + ""; - }; - } - - rgb$$1.gamma = rgbGamma; - - return rgb$$1; -})(1); - -var array$2 = function(a, b) { - var nb = b ? b.length : 0, - na = a ? Math.min(nb, a.length) : 0, - x = new Array(nb), - c = new Array(nb), - i; - - for (i = 0; i < na; ++i) x[i] = interpolateValue(a[i], b[i]); - for (; i < nb; ++i) c[i] = b[i]; - - return function(t) { - for (i = 0; i < na; ++i) c[i] = x[i](t); - return c; - }; -}; - -var date = function(a, b) { - var d = new Date; - return a = +a, b -= a, function(t) { - return d.setTime(a + b * t), d; - }; -}; - -var interpolateNumber = function(a, b) { - return a = +a, b -= a, function(t) { - return a + b * t; - }; -}; - -var object = function(a, b) { - var i = {}, - c = {}, - k; - - if (a === null || typeof a !== "object") a = {}; - if (b === null || typeof b !== "object") b = {}; - - for (k in b) { - if (k in a) { - i[k] = interpolateValue(a[k], b[k]); - } else { - c[k] = b[k]; - } - } - - return function(t) { - for (k in i) c[k] = i[k](t); - return c; - }; -}; - -var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; -var reB = new RegExp(reA.source, "g"); - -function zero(b) { - return function() { - return b; - }; -} - -function one(b) { - return function(t) { - return b(t) + ""; - }; -} - -var interpolateString = function(a, b) { - var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b - am, // current match in a - bm, // current match in b - bs, // string preceding current number in b, if any - i = -1, // index in s - s = [], // string constants and placeholders - q = []; // number interpolators - - // Coerce inputs to strings. - a = a + "", b = b + ""; - - // Interpolate pairs of numbers in a & b. - while ((am = reA.exec(a)) - && (bm = reB.exec(b))) { - if ((bs = bm.index) > bi) { // a string precedes the next number in b - bs = b.slice(bi, bs); - if (s[i]) s[i] += bs; // coalesce with previous string - else s[++i] = bs; - } - if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match - if (s[i]) s[i] += bm; // coalesce with previous string - else s[++i] = bm; - } else { // interpolate non-matching numbers - s[++i] = null; - q.push({i: i, x: interpolateNumber(am, bm)}); - } - bi = reB.lastIndex; - } - - // Add remains of b. - if (bi < b.length) { - bs = b.slice(bi); - if (s[i]) s[i] += bs; // coalesce with previous string - else s[++i] = bs; - } - - // Special optimization for only a single match. - // Otherwise, interpolate each of the numbers and rejoin the string. - return s.length < 2 ? (q[0] - ? one(q[0].x) - : zero(b)) - : (b = q.length, function(t) { - for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }); -}; - -var interpolateValue = function(a, b) { - var t = typeof b, c; - return b == null || t === "boolean" ? constant$3(b) - : (t === "number" ? interpolateNumber - : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : interpolateString) - : b instanceof color ? interpolateRgb - : b instanceof Date ? date - : Array.isArray(b) ? array$2 - : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object - : interpolateNumber)(a, b); -}; - -var interpolateRound = function(a, b) { - return a = +a, b -= a, function(t) { - return Math.round(a + b * t); - }; -}; - -var degrees = 180 / Math.PI; - -var identity$2 = { - translateX: 0, - translateY: 0, - rotate: 0, - skewX: 0, - scaleX: 1, - scaleY: 1 -}; - -var decompose = function(a, b, c, d, e, f) { - var scaleX, scaleY, skewX; - if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX; - if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX; - if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY; - if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX; - return { - translateX: e, - translateY: f, - rotate: Math.atan2(b, a) * degrees, - skewX: Math.atan(skewX) * degrees, - scaleX: scaleX, - scaleY: scaleY - }; -}; - -var cssNode; -var cssRoot; -var cssView; -var svgNode; - -function parseCss(value) { - if (value === "none") return identity$2; - if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView; - cssNode.style.transform = value; - value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform"); - cssRoot.removeChild(cssNode); - value = value.slice(7, -1).split(","); - return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]); -} - -function parseSvg(value) { - if (value == null) return identity$2; - if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); - svgNode.setAttribute("transform", value); - if (!(value = svgNode.transform.baseVal.consolidate())) return identity$2; - value = value.matrix; - return decompose(value.a, value.b, value.c, value.d, value.e, value.f); -} - -function interpolateTransform(parse, pxComma, pxParen, degParen) { - - function pop(s) { - return s.length ? s.pop() + " " : ""; - } - - function translate(xa, ya, xb, yb, s, q) { - if (xa !== xb || ya !== yb) { - var i = s.push("translate(", null, pxComma, null, pxParen); - q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)}); - } else if (xb || yb) { - s.push("translate(" + xb + pxComma + yb + pxParen); - } - } - - function rotate(a, b, s, q) { - if (a !== b) { - if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path - q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: interpolateNumber(a, b)}); - } else if (b) { - s.push(pop(s) + "rotate(" + b + degParen); - } - } - - function skewX(a, b, s, q) { - if (a !== b) { - q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: interpolateNumber(a, b)}); - } else if (b) { - s.push(pop(s) + "skewX(" + b + degParen); - } - } - - function scale(xa, ya, xb, yb, s, q) { - if (xa !== xb || ya !== yb) { - var i = s.push(pop(s) + "scale(", null, ",", null, ")"); - q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)}); - } else if (xb !== 1 || yb !== 1) { - s.push(pop(s) + "scale(" + xb + "," + yb + ")"); - } - } - - return function(a, b) { - var s = [], // string constants and placeholders - q = []; // number interpolators - a = parse(a), b = parse(b); - translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q); - rotate(a.rotate, b.rotate, s, q); - skewX(a.skewX, b.skewX, s, q); - scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q); - a = b = null; // gc - return function(t) { - var i = -1, n = q.length, o; - while (++i < n) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }; - }; -} - -var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); -var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); - -var rho = Math.SQRT2; - -function cubehelix$1(hue$$1) { - return (function cubehelixGamma(y) { - y = +y; - - function cubehelix$$1(start, end) { - var h = hue$$1((start = cubehelix(start)).h, (end = cubehelix(end)).h), - s = nogamma(start.s, end.s), - l = nogamma(start.l, end.l), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.h = h(t); - start.s = s(t); - start.l = l(Math.pow(t, y)); - start.opacity = opacity(t); - return start + ""; - }; - } - - cubehelix$$1.gamma = cubehelixGamma; - - return cubehelix$$1; - })(1); -} - -cubehelix$1(hue); -var cubehelixLong = cubehelix$1(nogamma); - -var constant$4 = function(x) { - return function() { - return x; - }; -}; - -var number$1 = function(x) { - return +x; -}; - -var unit = [0, 1]; - -function deinterpolateLinear(a, b) { - return (b -= (a = +a)) - ? function(x) { return (x - a) / b; } - : constant$4(b); -} - -function deinterpolateClamp(deinterpolate) { - return function(a, b) { - var d = deinterpolate(a = +a, b = +b); - return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); }; - }; -} - -function reinterpolateClamp(reinterpolate) { - return function(a, b) { - var r = reinterpolate(a = +a, b = +b); - return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); }; - }; -} - -function bimap(domain, range, deinterpolate, reinterpolate) { - var d0 = domain[0], d1 = domain[1], r0 = range[0], r1 = range[1]; - if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0); - else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1); - return function(x) { return r0(d0(x)); }; -} - -function polymap(domain, range, deinterpolate, reinterpolate) { - var j = Math.min(domain.length, range.length) - 1, - d = new Array(j), - r = new Array(j), - i = -1; - - // Reverse descending domains. - if (domain[j] < domain[0]) { - domain = domain.slice().reverse(); - range = range.slice().reverse(); - } - - while (++i < j) { - d[i] = deinterpolate(domain[i], domain[i + 1]); - r[i] = reinterpolate(range[i], range[i + 1]); - } - - return function(x) { - var i = bisectRight(domain, x, 1, j) - 1; - return r[i](d[i](x)); - }; -} - -function copy(source, target) { - return target - .domain(source.domain()) - .range(source.range()) - .interpolate(source.interpolate()) - .clamp(source.clamp()); -} - -// deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1]. -// reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b]. -function continuous(deinterpolate, reinterpolate) { - var domain = unit, - range = unit, - interpolate$$1 = interpolateValue, - clamp = false, - piecewise, - output, - input; - - function rescale() { - piecewise = Math.min(domain.length, range.length) > 2 ? polymap : bimap; - output = input = null; - return scale; - } - - function scale(x) { - return (output || (output = piecewise(domain, range, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate$$1)))(+x); - } - - scale.invert = function(y) { - return (input || (input = piecewise(range, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y); - }; - - scale.domain = function(_) { - return arguments.length ? (domain = map$3.call(_, number$1), rescale()) : domain.slice(); - }; - - scale.range = function(_) { - return arguments.length ? (range = slice$2.call(_), rescale()) : range.slice(); - }; - - scale.rangeRound = function(_) { - return range = slice$2.call(_), interpolate$$1 = interpolateRound, rescale(); - }; - - scale.clamp = function(_) { - return arguments.length ? (clamp = !!_, rescale()) : clamp; - }; - - scale.interpolate = function(_) { - return arguments.length ? (interpolate$$1 = _, rescale()) : interpolate$$1; - }; - - return rescale(); -} - -// Computes the decimal coefficient and exponent of the specified number x with -// significant digits p, where x is positive and p is in [1, 21] or undefined. -// For example, formatDecimal(1.23) returns ["123", 0]. -var formatDecimal = function(x, p) { - if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity - var i, coefficient = x.slice(0, i); - - // The string returned by toExponential either has the form \d\.\d+e[-+]\d+ - // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3). - return [ - coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, - +x.slice(i + 1) - ]; -}; - -var exponent = function(x) { - return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN; -}; - -var formatGroup = function(grouping, thousands) { - return function(value, width) { - var i = value.length, - t = [], - j = 0, - g = grouping[0], - length = 0; - - while (i > 0 && g > 0) { - if (length + g + 1 > width) g = Math.max(1, width - length); - t.push(value.substring(i -= g, i + g)); - if ((length += g + 1) > width) break; - g = grouping[j = (j + 1) % grouping.length]; - } - - return t.reverse().join(thousands); - }; -}; - -var formatNumerals = function(numerals) { - return function(value) { - return value.replace(/[0-9]/g, function(i) { - return numerals[+i]; - }); - }; -}; - -var formatDefault = function(x, p) { - x = x.toPrecision(p); - - out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) { - switch (x[i]) { - case ".": i0 = i1 = i; break; - case "0": if (i0 === 0) i0 = i; i1 = i; break; - case "e": break out; - default: if (i0 > 0) i0 = 0; break; - } - } - - return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x; -}; - -var prefixExponent; - -var formatPrefixAuto = function(x, p) { - var d = formatDecimal(x, p); - if (!d) return x + ""; - var coefficient = d[0], - exponent = d[1], - i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, - n = coefficient.length; - return i === n ? coefficient - : i > n ? coefficient + new Array(i - n + 1).join("0") - : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) - : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y! -}; - -var formatRounded = function(x, p) { - var d = formatDecimal(x, p); - if (!d) return x + ""; - var coefficient = d[0], - exponent = d[1]; - return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient - : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) - : coefficient + new Array(exponent - coefficient.length + 2).join("0"); -}; - -var formatTypes = { - "": formatDefault, - "%": function(x, p) { return (x * 100).toFixed(p); }, - "b": function(x) { return Math.round(x).toString(2); }, - "c": function(x) { return x + ""; }, - "d": function(x) { return Math.round(x).toString(10); }, - "e": function(x, p) { return x.toExponential(p); }, - "f": function(x, p) { return x.toFixed(p); }, - "g": function(x, p) { return x.toPrecision(p); }, - "o": function(x) { return Math.round(x).toString(8); }, - "p": function(x, p) { return formatRounded(x * 100, p); }, - "r": formatRounded, - "s": formatPrefixAuto, - "X": function(x) { return Math.round(x).toString(16).toUpperCase(); }, - "x": function(x) { return Math.round(x).toString(16); } -}; - -// [[fill]align][sign][symbol][0][width][,][.precision][type] -var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i; - -function formatSpecifier(specifier) { - return new FormatSpecifier(specifier); -} - -formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof - -function FormatSpecifier(specifier) { - if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier); - - var match, - fill = match[1] || " ", - align = match[2] || ">", - sign = match[3] || "-", - symbol = match[4] || "", - zero = !!match[5], - width = match[6] && +match[6], - comma = !!match[7], - precision = match[8] && +match[8].slice(1), - type = match[9] || ""; - - // The "n" type is an alias for ",g". - if (type === "n") comma = true, type = "g"; - - // Map invalid types to the default format. - else if (!formatTypes[type]) type = ""; - - // If zero fill is specified, padding goes after sign and before digits. - if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "="; - - this.fill = fill; - this.align = align; - this.sign = sign; - this.symbol = symbol; - this.zero = zero; - this.width = width; - this.comma = comma; - this.precision = precision; - this.type = type; -} - -FormatSpecifier.prototype.toString = function() { - return this.fill - + this.align - + this.sign - + this.symbol - + (this.zero ? "0" : "") - + (this.width == null ? "" : Math.max(1, this.width | 0)) - + (this.comma ? "," : "") - + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0)) - + this.type; -}; - -var identity$3 = function(x) { - return x; -}; - -var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"]; - -var formatLocale = function(locale) { - var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$3, - currency = locale.currency, - decimal = locale.decimal, - numerals = locale.numerals ? formatNumerals(locale.numerals) : identity$3, - percent = locale.percent || "%"; - - function newFormat(specifier) { - specifier = formatSpecifier(specifier); - - var fill = specifier.fill, - align = specifier.align, - sign = specifier.sign, - symbol = specifier.symbol, - zero = specifier.zero, - width = specifier.width, - comma = specifier.comma, - precision = specifier.precision, - type = specifier.type; - - // Compute the prefix and suffix. - // For SI-prefix, the suffix is lazily computed. - var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "", - suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? percent : ""; - - // What format function should we use? - // Is this an integer type? - // Can this type generate exponential notation? - var formatType = formatTypes[type], - maybeSuffix = !type || /[defgprs%]/.test(type); - - // Set the default precision if not specified, - // or clamp the specified precision to the supported range. - // For significant precision, it must be in [1, 21]. - // For fixed precision, it must be in [0, 20]. - precision = precision == null ? (type ? 6 : 12) - : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) - : Math.max(0, Math.min(20, precision)); - - function format(value) { - var valuePrefix = prefix, - valueSuffix = suffix, - i, n, c; - - if (type === "c") { - valueSuffix = formatType(value) + valueSuffix; - value = ""; - } else { - value = +value; - - // Perform the initial formatting. - var valueNegative = value < 0; - value = formatType(Math.abs(value), precision); - - // If a negative value rounds to zero during formatting, treat as positive. - if (valueNegative && +value === 0) valueNegative = false; - - // Compute the prefix and suffix. - valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; - valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : ""); - - // Break the formatted value into the integer “value†part that can be - // grouped, and fractional or exponential “suffix†part that is not. - if (maybeSuffix) { - i = -1, n = value.length; - while (++i < n) { - if (c = value.charCodeAt(i), 48 > c || c > 57) { - valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix; - value = value.slice(0, i); - break; - } - } - } - } - - // If the fill character is not "0", grouping is applied before padding. - if (comma && !zero) value = group(value, Infinity); - - // Compute the padding. - var length = valuePrefix.length + value.length + valueSuffix.length, - padding = length < width ? new Array(width - length + 1).join(fill) : ""; - - // If the fill character is "0", grouping is applied after padding. - if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; - - // Reconstruct the final output based on the desired alignment. - switch (align) { - case "<": value = valuePrefix + value + valueSuffix + padding; break; - case "=": value = valuePrefix + padding + value + valueSuffix; break; - case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break; - default: value = padding + valuePrefix + value + valueSuffix; break; - } - - return numerals(value); - } - - format.toString = function() { - return specifier + ""; - }; - - return format; - } - - function formatPrefix(specifier, value) { - var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), - e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3, - k = Math.pow(10, -e), - prefix = prefixes[8 + e / 3]; - return function(value) { - return f(k * value) + prefix; - }; - } - - return { - format: newFormat, - formatPrefix: formatPrefix - }; -}; - -var locale; - -var formatPrefix; - -defaultLocale({ - decimal: ".", - thousands: ",", - grouping: [3], - currency: ["$", ""] -}); - -function defaultLocale(definition) { - locale = formatLocale(definition); - exports.format = locale.format; - formatPrefix = locale.formatPrefix; - return locale; -} - -var precisionFixed = function(step) { - return Math.max(0, -exponent(Math.abs(step))); -}; - -var precisionPrefix = function(step, value) { - return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step))); -}; - -var precisionRound = function(step, max) { - step = Math.abs(step), max = Math.abs(max) - step; - return Math.max(0, exponent(max) - exponent(step)) + 1; -}; - -var tickFormat = function(domain, count, specifier) { - var start = domain[0], - stop = domain[domain.length - 1], - step = tickStep(start, stop, count == null ? 10 : count), - precision; - specifier = formatSpecifier(specifier == null ? ",f" : specifier); - switch (specifier.type) { - case "s": { - var value = Math.max(Math.abs(start), Math.abs(stop)); - if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision; - return formatPrefix(specifier, value); - } - case "": - case "e": - case "g": - case "p": - case "r": { - if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e"); - break; - } - case "f": - case "%": { - if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2; - break; - } - } - return exports.format(specifier); -}; - -function linearish(scale) { - var domain = scale.domain; - - scale.ticks = function(count) { - var d = domain(); - return ticks(d[0], d[d.length - 1], count == null ? 10 : count); - }; - - scale.tickFormat = function(count, specifier) { - return tickFormat(domain(), count, specifier); - }; - - scale.nice = function(count) { - if (count == null) count = 10; - - var d = domain(), - i0 = 0, - i1 = d.length - 1, - start = d[i0], - stop = d[i1], - step; - - if (stop < start) { - step = start, start = stop, stop = step; - step = i0, i0 = i1, i1 = step; - } - - step = tickIncrement(start, stop, count); - - if (step > 0) { - start = Math.floor(start / step) * step; - stop = Math.ceil(stop / step) * step; - step = tickIncrement(start, stop, count); - } else if (step < 0) { - start = Math.ceil(start * step) / step; - stop = Math.floor(stop * step) / step; - step = tickIncrement(start, stop, count); - } - - if (step > 0) { - d[i0] = Math.floor(start / step) * step; - d[i1] = Math.ceil(stop / step) * step; - domain(d); - } else if (step < 0) { - d[i0] = Math.ceil(start * step) / step; - d[i1] = Math.floor(stop * step) / step; - domain(d); - } - - return scale; - }; - - return scale; -} - -function linear() { - var scale = continuous(deinterpolateLinear, interpolateNumber); - - scale.copy = function() { - return copy(scale, linear()); - }; - - return linearish(scale); -} - -var t0$1 = new Date; -var t1$1 = new Date; - -function newInterval(floori, offseti, count, field) { - - function interval(date) { - return floori(date = new Date(+date)), date; - } - - interval.floor = interval; - - interval.ceil = function(date) { - return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date; - }; - - interval.round = function(date) { - var d0 = interval(date), - d1 = interval.ceil(date); - return date - d0 < d1 - date ? d0 : d1; - }; - - interval.offset = function(date, step) { - return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; - }; - - interval.range = function(start, stop, step) { - var range = []; - start = interval.ceil(start); - step = step == null ? 1 : Math.floor(step); - if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date - do range.push(new Date(+start)); while (offseti(start, step), floori(start), start < stop) - return range; - }; - - interval.filter = function(test) { - return newInterval(function(date) { - if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1); - }, function(date, step) { - if (date >= date) { - if (step < 0) while (++step <= 0) { - while (offseti(date, -1), !test(date)) {} // eslint-disable-line no-empty - } else while (--step >= 0) { - while (offseti(date, +1), !test(date)) {} // eslint-disable-line no-empty - } - } - }); - }; - - if (count) { - interval.count = function(start, end) { - t0$1.setTime(+start), t1$1.setTime(+end); - floori(t0$1), floori(t1$1); - return Math.floor(count(t0$1, t1$1)); - }; - - interval.every = function(step) { - step = Math.floor(step); - return !isFinite(step) || !(step > 0) ? null - : !(step > 1) ? interval - : interval.filter(field - ? function(d) { return field(d) % step === 0; } - : function(d) { return interval.count(0, d) % step === 0; }); - }; - } - - return interval; -} - -var millisecond = newInterval(function() { - // noop -}, function(date, step) { - date.setTime(+date + step); -}, function(start, end) { - return end - start; -}); - -// An optimized implementation for this simple case. -millisecond.every = function(k) { - k = Math.floor(k); - if (!isFinite(k) || !(k > 0)) return null; - if (!(k > 1)) return millisecond; - return newInterval(function(date) { - date.setTime(Math.floor(date / k) * k); - }, function(date, step) { - date.setTime(+date + step * k); - }, function(start, end) { - return (end - start) / k; - }); -}; - -var durationSecond$1 = 1e3; -var durationMinute$1 = 6e4; -var durationHour$1 = 36e5; -var durationDay$1 = 864e5; -var durationWeek$1 = 6048e5; - -var second = newInterval(function(date) { - date.setTime(Math.floor(date / durationSecond$1) * durationSecond$1); -}, function(date, step) { - date.setTime(+date + step * durationSecond$1); -}, function(start, end) { - return (end - start) / durationSecond$1; -}, function(date) { - return date.getUTCSeconds(); -}); - -var minute = newInterval(function(date) { - date.setTime(Math.floor(date / durationMinute$1) * durationMinute$1); -}, function(date, step) { - date.setTime(+date + step * durationMinute$1); -}, function(start, end) { - return (end - start) / durationMinute$1; -}, function(date) { - return date.getMinutes(); -}); - -var hour = newInterval(function(date) { - var offset = date.getTimezoneOffset() * durationMinute$1 % durationHour$1; - if (offset < 0) offset += durationHour$1; - date.setTime(Math.floor((+date - offset) / durationHour$1) * durationHour$1 + offset); -}, function(date, step) { - date.setTime(+date + step * durationHour$1); -}, function(start, end) { - return (end - start) / durationHour$1; -}, function(date) { - return date.getHours(); -}); - -var day = newInterval(function(date) { - date.setHours(0, 0, 0, 0); -}, function(date, step) { - date.setDate(date.getDate() + step); -}, function(start, end) { - return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationDay$1; -}, function(date) { - return date.getDate() - 1; -}); - -function weekday(i) { - return newInterval(function(date) { - date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7); - date.setHours(0, 0, 0, 0); - }, function(date, step) { - date.setDate(date.getDate() + step * 7); - }, function(start, end) { - return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute$1) / durationWeek$1; - }); -} - -var sunday = weekday(0); -var monday = weekday(1); -var tuesday = weekday(2); -var wednesday = weekday(3); -var thursday = weekday(4); -var friday = weekday(5); -var saturday = weekday(6); - -var month = newInterval(function(date) { - date.setDate(1); - date.setHours(0, 0, 0, 0); -}, function(date, step) { - date.setMonth(date.getMonth() + step); -}, function(start, end) { - return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12; -}, function(date) { - return date.getMonth(); -}); - -var year = newInterval(function(date) { - date.setMonth(0, 1); - date.setHours(0, 0, 0, 0); -}, function(date, step) { - date.setFullYear(date.getFullYear() + step); -}, function(start, end) { - return end.getFullYear() - start.getFullYear(); -}, function(date) { - return date.getFullYear(); -}); - -// An optimized implementation for this simple case. -year.every = function(k) { - return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { - date.setFullYear(Math.floor(date.getFullYear() / k) * k); - date.setMonth(0, 1); - date.setHours(0, 0, 0, 0); - }, function(date, step) { - date.setFullYear(date.getFullYear() + step * k); - }); -}; - -var utcMinute = newInterval(function(date) { - date.setUTCSeconds(0, 0); -}, function(date, step) { - date.setTime(+date + step * durationMinute$1); -}, function(start, end) { - return (end - start) / durationMinute$1; -}, function(date) { - return date.getUTCMinutes(); -}); - -var utcHour = newInterval(function(date) { - date.setUTCMinutes(0, 0, 0); -}, function(date, step) { - date.setTime(+date + step * durationHour$1); -}, function(start, end) { - return (end - start) / durationHour$1; -}, function(date) { - return date.getUTCHours(); -}); - -var utcDay = newInterval(function(date) { - date.setUTCHours(0, 0, 0, 0); -}, function(date, step) { - date.setUTCDate(date.getUTCDate() + step); -}, function(start, end) { - return (end - start) / durationDay$1; -}, function(date) { - return date.getUTCDate() - 1; -}); - -function utcWeekday(i) { - return newInterval(function(date) { - date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7); - date.setUTCHours(0, 0, 0, 0); - }, function(date, step) { - date.setUTCDate(date.getUTCDate() + step * 7); - }, function(start, end) { - return (end - start) / durationWeek$1; - }); -} - -var utcSunday = utcWeekday(0); -var utcMonday = utcWeekday(1); -var utcTuesday = utcWeekday(2); -var utcWednesday = utcWeekday(3); -var utcThursday = utcWeekday(4); -var utcFriday = utcWeekday(5); -var utcSaturday = utcWeekday(6); - -var utcMonth = newInterval(function(date) { - date.setUTCDate(1); - date.setUTCHours(0, 0, 0, 0); -}, function(date, step) { - date.setUTCMonth(date.getUTCMonth() + step); -}, function(start, end) { - return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12; -}, function(date) { - return date.getUTCMonth(); -}); - -var utcYear = newInterval(function(date) { - date.setUTCMonth(0, 1); - date.setUTCHours(0, 0, 0, 0); -}, function(date, step) { - date.setUTCFullYear(date.getUTCFullYear() + step); -}, function(start, end) { - return end.getUTCFullYear() - start.getUTCFullYear(); -}, function(date) { - return date.getUTCFullYear(); -}); - -// An optimized implementation for this simple case. -utcYear.every = function(k) { - return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { - date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k); - date.setUTCMonth(0, 1); - date.setUTCHours(0, 0, 0, 0); - }, function(date, step) { - date.setUTCFullYear(date.getUTCFullYear() + step * k); - }); -}; - -function localDate(d) { - if (0 <= d.y && d.y < 100) { - var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L); - date.setFullYear(d.y); - return date; - } - return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L); -} - -function utcDate(d) { - if (0 <= d.y && d.y < 100) { - var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L)); - date.setUTCFullYear(d.y); - return date; - } - return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L)); -} - -function newYear(y) { - return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0}; -} - -function formatLocale$1(locale) { - var locale_dateTime = locale.dateTime, - locale_date = locale.date, - locale_time = locale.time, - locale_periods = locale.periods, - locale_weekdays = locale.days, - locale_shortWeekdays = locale.shortDays, - locale_months = locale.months, - locale_shortMonths = locale.shortMonths; - - var periodRe = formatRe(locale_periods), - periodLookup = formatLookup(locale_periods), - weekdayRe = formatRe(locale_weekdays), - weekdayLookup = formatLookup(locale_weekdays), - shortWeekdayRe = formatRe(locale_shortWeekdays), - shortWeekdayLookup = formatLookup(locale_shortWeekdays), - monthRe = formatRe(locale_months), - monthLookup = formatLookup(locale_months), - shortMonthRe = formatRe(locale_shortMonths), - shortMonthLookup = formatLookup(locale_shortMonths); - - var formats = { - "a": formatShortWeekday, - "A": formatWeekday, - "b": formatShortMonth, - "B": formatMonth, - "c": null, - "d": formatDayOfMonth, - "e": formatDayOfMonth, - "f": formatMicroseconds, - "H": formatHour24, - "I": formatHour12, - "j": formatDayOfYear, - "L": formatMilliseconds, - "m": formatMonthNumber, - "M": formatMinutes, - "p": formatPeriod, - "Q": formatUnixTimestamp, - "s": formatUnixTimestampSeconds, - "S": formatSeconds, - "u": formatWeekdayNumberMonday, - "U": formatWeekNumberSunday, - "V": formatWeekNumberISO, - "w": formatWeekdayNumberSunday, - "W": formatWeekNumberMonday, - "x": null, - "X": null, - "y": formatYear, - "Y": formatFullYear, - "Z": formatZone, - "%": formatLiteralPercent - }; - - var utcFormats = { - "a": formatUTCShortWeekday, - "A": formatUTCWeekday, - "b": formatUTCShortMonth, - "B": formatUTCMonth, - "c": null, - "d": formatUTCDayOfMonth, - "e": formatUTCDayOfMonth, - "f": formatUTCMicroseconds, - "H": formatUTCHour24, - "I": formatUTCHour12, - "j": formatUTCDayOfYear, - "L": formatUTCMilliseconds, - "m": formatUTCMonthNumber, - "M": formatUTCMinutes, - "p": formatUTCPeriod, - "Q": formatUnixTimestamp, - "s": formatUnixTimestampSeconds, - "S": formatUTCSeconds, - "u": formatUTCWeekdayNumberMonday, - "U": formatUTCWeekNumberSunday, - "V": formatUTCWeekNumberISO, - "w": formatUTCWeekdayNumberSunday, - "W": formatUTCWeekNumberMonday, - "x": null, - "X": null, - "y": formatUTCYear, - "Y": formatUTCFullYear, - "Z": formatUTCZone, - "%": formatLiteralPercent - }; - - var parses = { - "a": parseShortWeekday, - "A": parseWeekday, - "b": parseShortMonth, - "B": parseMonth, - "c": parseLocaleDateTime, - "d": parseDayOfMonth, - "e": parseDayOfMonth, - "f": parseMicroseconds, - "H": parseHour24, - "I": parseHour24, - "j": parseDayOfYear, - "L": parseMilliseconds, - "m": parseMonthNumber, - "M": parseMinutes, - "p": parsePeriod, - "Q": parseUnixTimestamp, - "s": parseUnixTimestampSeconds, - "S": parseSeconds, - "u": parseWeekdayNumberMonday, - "U": parseWeekNumberSunday, - "V": parseWeekNumberISO, - "w": parseWeekdayNumberSunday, - "W": parseWeekNumberMonday, - "x": parseLocaleDate, - "X": parseLocaleTime, - "y": parseYear, - "Y": parseFullYear, - "Z": parseZone, - "%": parseLiteralPercent - }; - - // These recursive directive definitions must be deferred. - formats.x = newFormat(locale_date, formats); - formats.X = newFormat(locale_time, formats); - formats.c = newFormat(locale_dateTime, formats); - utcFormats.x = newFormat(locale_date, utcFormats); - utcFormats.X = newFormat(locale_time, utcFormats); - utcFormats.c = newFormat(locale_dateTime, utcFormats); - - function newFormat(specifier, formats) { - return function(date) { - var string = [], - i = -1, - j = 0, - n = specifier.length, - c, - pad, - format; - - if (!(date instanceof Date)) date = new Date(+date); - - while (++i < n) { - if (specifier.charCodeAt(i) === 37) { - string.push(specifier.slice(j, i)); - if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i); - else pad = c === "e" ? " " : "0"; - if (format = formats[c]) c = format(date, pad); - string.push(c); - j = i + 1; - } - } - - string.push(specifier.slice(j, i)); - return string.join(""); - }; - } - - function newParse(specifier, newDate) { - return function(string) { - var d = newYear(1900), - i = parseSpecifier(d, specifier, string += "", 0), - week, day$$1; - if (i != string.length) return null; - - // If a UNIX timestamp is specified, return it. - if ("Q" in d) return new Date(d.Q); - - // The am-pm flag is 0 for AM, and 1 for PM. - if ("p" in d) d.H = d.H % 12 + d.p * 12; - - // Convert day-of-week and week-of-year to day-of-year. - if ("V" in d) { - if (d.V < 1 || d.V > 53) return null; - if (!("w" in d)) d.w = 1; - if ("Z" in d) { - week = utcDate(newYear(d.y)), day$$1 = week.getUTCDay(); - week = day$$1 > 4 || day$$1 === 0 ? utcMonday.ceil(week) : utcMonday(week); - week = utcDay.offset(week, (d.V - 1) * 7); - d.y = week.getUTCFullYear(); - d.m = week.getUTCMonth(); - d.d = week.getUTCDate() + (d.w + 6) % 7; - } else { - week = newDate(newYear(d.y)), day$$1 = week.getDay(); - week = day$$1 > 4 || day$$1 === 0 ? monday.ceil(week) : monday(week); - week = day.offset(week, (d.V - 1) * 7); - d.y = week.getFullYear(); - d.m = week.getMonth(); - d.d = week.getDate() + (d.w + 6) % 7; - } - } else if ("W" in d || "U" in d) { - if (!("w" in d)) d.w = "u" in d ? d.u % 7 : "W" in d ? 1 : 0; - day$$1 = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay(); - d.m = 0; - d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day$$1 + 5) % 7 : d.w + d.U * 7 - (day$$1 + 6) % 7; - } - - // If a time zone is specified, all fields are interpreted as UTC and then - // offset according to the specified time zone. - if ("Z" in d) { - d.H += d.Z / 100 | 0; - d.M += d.Z % 100; - return utcDate(d); - } - - // Otherwise, all fields are in local time. - return newDate(d); - }; - } - - function parseSpecifier(d, specifier, string, j) { - var i = 0, - n = specifier.length, - m = string.length, - c, - parse; - - while (i < n) { - if (j >= m) return -1; - c = specifier.charCodeAt(i++); - if (c === 37) { - c = specifier.charAt(i++); - parse = parses[c in pads ? specifier.charAt(i++) : c]; - if (!parse || ((j = parse(d, string, j)) < 0)) return -1; - } else if (c != string.charCodeAt(j++)) { - return -1; - } - } - - return j; - } - - function parsePeriod(d, string, i) { - var n = periodRe.exec(string.slice(i)); - return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1; - } - - function parseShortWeekday(d, string, i) { - var n = shortWeekdayRe.exec(string.slice(i)); - return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; - } - - function parseWeekday(d, string, i) { - var n = weekdayRe.exec(string.slice(i)); - return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; - } - - function parseShortMonth(d, string, i) { - var n = shortMonthRe.exec(string.slice(i)); - return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1; - } - - function parseMonth(d, string, i) { - var n = monthRe.exec(string.slice(i)); - return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1; - } - - function parseLocaleDateTime(d, string, i) { - return parseSpecifier(d, locale_dateTime, string, i); - } - - function parseLocaleDate(d, string, i) { - return parseSpecifier(d, locale_date, string, i); - } - - function parseLocaleTime(d, string, i) { - return parseSpecifier(d, locale_time, string, i); - } - - function formatShortWeekday(d) { - return locale_shortWeekdays[d.getDay()]; - } - - function formatWeekday(d) { - return locale_weekdays[d.getDay()]; - } - - function formatShortMonth(d) { - return locale_shortMonths[d.getMonth()]; - } - - function formatMonth(d) { - return locale_months[d.getMonth()]; - } - - function formatPeriod(d) { - return locale_periods[+(d.getHours() >= 12)]; - } - - function formatUTCShortWeekday(d) { - return locale_shortWeekdays[d.getUTCDay()]; - } - - function formatUTCWeekday(d) { - return locale_weekdays[d.getUTCDay()]; - } - - function formatUTCShortMonth(d) { - return locale_shortMonths[d.getUTCMonth()]; - } - - function formatUTCMonth(d) { - return locale_months[d.getUTCMonth()]; - } - - function formatUTCPeriod(d) { - return locale_periods[+(d.getUTCHours() >= 12)]; - } - - return { - format: function(specifier) { - var f = newFormat(specifier += "", formats); - f.toString = function() { return specifier; }; - return f; - }, - parse: function(specifier) { - var p = newParse(specifier += "", localDate); - p.toString = function() { return specifier; }; - return p; - }, - utcFormat: function(specifier) { - var f = newFormat(specifier += "", utcFormats); - f.toString = function() { return specifier; }; - return f; - }, - utcParse: function(specifier) { - var p = newParse(specifier, utcDate); - p.toString = function() { return specifier; }; - return p; - } - }; -} - -var pads = {"-": "", "_": " ", "0": "0"}; -var numberRe = /^\s*\d+/; -var percentRe = /^%/; -var requoteRe = /[\\^$*+?|[\]().{}]/g; - -function pad(value, fill, width) { - var sign = value < 0 ? "-" : "", - string = (sign ? -value : value) + "", - length = string.length; - return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); -} - -function requote(s) { - return s.replace(requoteRe, "\\$&"); -} - -function formatRe(names) { - return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i"); -} - -function formatLookup(names) { - var map = {}, i = -1, n = names.length; - while (++i < n) map[names[i].toLowerCase()] = i; - return map; -} - -function parseWeekdayNumberSunday(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 1)); - return n ? (d.w = +n[0], i + n[0].length) : -1; -} - -function parseWeekdayNumberMonday(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 1)); - return n ? (d.u = +n[0], i + n[0].length) : -1; -} - -function parseWeekNumberSunday(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.U = +n[0], i + n[0].length) : -1; -} - -function parseWeekNumberISO(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.V = +n[0], i + n[0].length) : -1; -} - -function parseWeekNumberMonday(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.W = +n[0], i + n[0].length) : -1; -} - -function parseFullYear(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 4)); - return n ? (d.y = +n[0], i + n[0].length) : -1; -} - -function parseYear(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1; -} - -function parseZone(d, string, i) { - var n = /^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(string.slice(i, i + 6)); - return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1; -} - -function parseMonthNumber(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.m = n[0] - 1, i + n[0].length) : -1; -} - -function parseDayOfMonth(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.d = +n[0], i + n[0].length) : -1; -} - -function parseDayOfYear(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 3)); - return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1; -} - -function parseHour24(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.H = +n[0], i + n[0].length) : -1; -} - -function parseMinutes(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.M = +n[0], i + n[0].length) : -1; -} - -function parseSeconds(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 2)); - return n ? (d.S = +n[0], i + n[0].length) : -1; -} - -function parseMilliseconds(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 3)); - return n ? (d.L = +n[0], i + n[0].length) : -1; -} - -function parseMicroseconds(d, string, i) { - var n = numberRe.exec(string.slice(i, i + 6)); - return n ? (d.L = Math.floor(n[0] / 1000), i + n[0].length) : -1; -} - -function parseLiteralPercent(d, string, i) { - var n = percentRe.exec(string.slice(i, i + 1)); - return n ? i + n[0].length : -1; -} - -function parseUnixTimestamp(d, string, i) { - var n = numberRe.exec(string.slice(i)); - return n ? (d.Q = +n[0], i + n[0].length) : -1; -} - -function parseUnixTimestampSeconds(d, string, i) { - var n = numberRe.exec(string.slice(i)); - return n ? (d.Q = (+n[0]) * 1000, i + n[0].length) : -1; -} - -function formatDayOfMonth(d, p) { - return pad(d.getDate(), p, 2); -} - -function formatHour24(d, p) { - return pad(d.getHours(), p, 2); -} - -function formatHour12(d, p) { - return pad(d.getHours() % 12 || 12, p, 2); -} - -function formatDayOfYear(d, p) { - return pad(1 + day.count(year(d), d), p, 3); -} - -function formatMilliseconds(d, p) { - return pad(d.getMilliseconds(), p, 3); -} - -function formatMicroseconds(d, p) { - return formatMilliseconds(d, p) + "000"; -} - -function formatMonthNumber(d, p) { - return pad(d.getMonth() + 1, p, 2); -} - -function formatMinutes(d, p) { - return pad(d.getMinutes(), p, 2); -} - -function formatSeconds(d, p) { - return pad(d.getSeconds(), p, 2); -} - -function formatWeekdayNumberMonday(d) { - var day$$1 = d.getDay(); - return day$$1 === 0 ? 7 : day$$1; -} - -function formatWeekNumberSunday(d, p) { - return pad(sunday.count(year(d), d), p, 2); -} - -function formatWeekNumberISO(d, p) { - var day$$1 = d.getDay(); - d = (day$$1 >= 4 || day$$1 === 0) ? thursday(d) : thursday.ceil(d); - return pad(thursday.count(year(d), d) + (year(d).getDay() === 4), p, 2); -} - -function formatWeekdayNumberSunday(d) { - return d.getDay(); -} - -function formatWeekNumberMonday(d, p) { - return pad(monday.count(year(d), d), p, 2); -} - -function formatYear(d, p) { - return pad(d.getFullYear() % 100, p, 2); -} - -function formatFullYear(d, p) { - return pad(d.getFullYear() % 10000, p, 4); -} - -function formatZone(d) { - var z = d.getTimezoneOffset(); - return (z > 0 ? "-" : (z *= -1, "+")) - + pad(z / 60 | 0, "0", 2) - + pad(z % 60, "0", 2); -} - -function formatUTCDayOfMonth(d, p) { - return pad(d.getUTCDate(), p, 2); -} - -function formatUTCHour24(d, p) { - return pad(d.getUTCHours(), p, 2); -} - -function formatUTCHour12(d, p) { - return pad(d.getUTCHours() % 12 || 12, p, 2); -} - -function formatUTCDayOfYear(d, p) { - return pad(1 + utcDay.count(utcYear(d), d), p, 3); -} - -function formatUTCMilliseconds(d, p) { - return pad(d.getUTCMilliseconds(), p, 3); -} - -function formatUTCMicroseconds(d, p) { - return formatUTCMilliseconds(d, p) + "000"; -} - -function formatUTCMonthNumber(d, p) { - return pad(d.getUTCMonth() + 1, p, 2); -} - -function formatUTCMinutes(d, p) { - return pad(d.getUTCMinutes(), p, 2); -} - -function formatUTCSeconds(d, p) { - return pad(d.getUTCSeconds(), p, 2); -} - -function formatUTCWeekdayNumberMonday(d) { - var dow = d.getUTCDay(); - return dow === 0 ? 7 : dow; -} - -function formatUTCWeekNumberSunday(d, p) { - return pad(utcSunday.count(utcYear(d), d), p, 2); -} - -function formatUTCWeekNumberISO(d, p) { - var day$$1 = d.getUTCDay(); - d = (day$$1 >= 4 || day$$1 === 0) ? utcThursday(d) : utcThursday.ceil(d); - return pad(utcThursday.count(utcYear(d), d) + (utcYear(d).getUTCDay() === 4), p, 2); -} - -function formatUTCWeekdayNumberSunday(d) { - return d.getUTCDay(); -} - -function formatUTCWeekNumberMonday(d, p) { - return pad(utcMonday.count(utcYear(d), d), p, 2); -} - -function formatUTCYear(d, p) { - return pad(d.getUTCFullYear() % 100, p, 2); -} - -function formatUTCFullYear(d, p) { - return pad(d.getUTCFullYear() % 10000, p, 4); -} - -function formatUTCZone() { - return "+0000"; -} - -function formatLiteralPercent() { - return "%"; -} - -function formatUnixTimestamp(d) { - return +d; -} - -function formatUnixTimestampSeconds(d) { - return Math.floor(+d / 1000); -} - -var locale$1; -var timeFormat; -var timeParse; -var utcFormat; -var utcParse; - -defaultLocale$1({ - dateTime: "%x, %X", - date: "%-m/%-d/%Y", - time: "%-I:%M:%S %p", - periods: ["AM", "PM"], - days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], - shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], - months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], - shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] -}); - -function defaultLocale$1(definition) { - locale$1 = formatLocale$1(definition); - timeFormat = locale$1.format; - timeParse = locale$1.parse; - utcFormat = locale$1.utcFormat; - utcParse = locale$1.utcParse; - return locale$1; -} - -var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ"; - -function formatIsoNative(date) { - return date.toISOString(); -} - -var formatIso = Date.prototype.toISOString - ? formatIsoNative - : utcFormat(isoSpecifier); - -function parseIsoNative(string) { - var date = new Date(string); - return isNaN(date) ? null : date; -} - -var parseIso = +new Date("2000-01-01T00:00:00.000Z") - ? parseIsoNative - : utcParse(isoSpecifier); - -var colors = function(s) { - return s.match(/.{6}/g).map(function(x) { - return "#" + x; - }); -}; - -colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"); - -colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6"); - -colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9"); - -colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5"); - -cubehelixLong(cubehelix(300, 0.5, 0.0), cubehelix(-240, 0.5, 1.0)); - -var warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.50, 0.8)); - -var cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.50, 0.8)); - -var rainbow = cubehelix(); - -function ramp(range) { - var n = range.length; - return function(t) { - return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))]; - }; -} - -ramp(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")); - -var magma = ramp(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")); - -var inferno = ramp(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")); - -var plasma = ramp(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921")); - -function cubicInOut(t) { - return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2; -} - -var pi = Math.PI; - -var tau = 2 * Math.PI; - -var noop = {value: function() {}}; - -function dispatch() { - for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { - if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t); - _[t] = []; - } - return new Dispatch(_); -} - -function Dispatch(_) { - this._ = _; -} - -function parseTypenames$1(typenames, types) { - return typenames.trim().split(/^|\s+/).map(function(t) { - var name = "", i = t.indexOf("."); - if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); - if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t); - return {type: t, name: name}; - }); -} - -Dispatch.prototype = dispatch.prototype = { - constructor: Dispatch, - on: function(typename, callback) { - var _ = this._, - T = parseTypenames$1(typename + "", _), - t, - i = -1, - n = T.length; - - // If no callback was specified, return the callback of the given type and name. - if (arguments.length < 2) { - while (++i < n) if ((t = (typename = T[i]).type) && (t = get$1(_[t], typename.name))) return t; - return; - } - - // If a type was specified, set the callback for the given type and name. - // Otherwise, if a null callback was specified, remove callbacks of the given name. - if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback); - while (++i < n) { - if (t = (typename = T[i]).type) _[t] = set$3(_[t], typename.name, callback); - else if (callback == null) for (t in _) _[t] = set$3(_[t], typename.name, null); - } - - return this; - }, - copy: function() { - var copy = {}, _ = this._; - for (var t in _) copy[t] = _[t].slice(); - return new Dispatch(copy); - }, - call: function(type, that) { - if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2]; - if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); - for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); - }, - apply: function(type, that, args) { - if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); - for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); - } -}; - -function get$1(type, name) { - for (var i = 0, n = type.length, c; i < n; ++i) { - if ((c = type[i]).name === name) { - return c.value; - } - } -} - -function set$3(type, name, callback) { - for (var i = 0, n = type.length; i < n; ++i) { - if (type[i].name === name) { - type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1)); - break; - } - } - if (callback != null) type.push({name: name, value: callback}); - return type; -} - -var frame = 0; -var timeout = 0; -var interval = 0; -var pokeDelay = 1000; -var taskHead; -var taskTail; -var clockLast = 0; -var clockNow = 0; -var clockSkew = 0; -var clock = typeof performance === "object" && performance.now ? performance : Date; -var setFrame = typeof window === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) { setTimeout(f, 17); }; - -function now() { - return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); -} - -function clearNow() { - clockNow = 0; -} - -function Timer() { - this._call = - this._time = - this._next = null; -} - -Timer.prototype = timer.prototype = { - constructor: Timer, - restart: function(callback, delay, time) { - if (typeof callback !== "function") throw new TypeError("callback is not a function"); - time = (time == null ? now() : +time) + (delay == null ? 0 : +delay); - if (!this._next && taskTail !== this) { - if (taskTail) taskTail._next = this; - else taskHead = this; - taskTail = this; - } - this._call = callback; - this._time = time; - sleep(); - }, - stop: function() { - if (this._call) { - this._call = null; - this._time = Infinity; - sleep(); - } - } -}; - -function timer(callback, delay, time) { - var t = new Timer; - t.restart(callback, delay, time); - return t; -} - -function timerFlush() { - now(); // Get the current time, if not already set. - ++frame; // Pretend we’ve set an alarm, if we haven’t already. - var t = taskHead, e; - while (t) { - if ((e = clockNow - t._time) >= 0) t._call.call(null, e); - t = t._next; - } - --frame; -} - -function wake() { - clockNow = (clockLast = clock.now()) + clockSkew; - frame = timeout = 0; - try { - timerFlush(); - } finally { - frame = 0; - nap(); - clockNow = 0; - } -} - -function poke() { - var now = clock.now(), delay = now - clockLast; - if (delay > pokeDelay) clockSkew -= delay, clockLast = now; -} - -function nap() { - var t0, t1 = taskHead, t2, time = Infinity; - while (t1) { - if (t1._call) { - if (time > t1._time) time = t1._time; - t0 = t1, t1 = t1._next; - } else { - t2 = t1._next, t1._next = null; - t1 = t0 ? t0._next = t2 : taskHead = t2; - } - } - taskTail = t0; - sleep(time); -} - -function sleep(time) { - if (frame) return; // Soonest alarm already set, or will be. - if (timeout) timeout = clearTimeout(timeout); - var delay = time - clockNow; // Strictly less than if we recomputed clockNow. - if (delay > 24) { - if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew); - if (interval) interval = clearInterval(interval); - } else { - if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay); - frame = 1, setFrame(wake); - } -} - -var timeout$1 = function(callback, delay, time) { - var t = new Timer; - delay = delay == null ? 0 : +delay; - t.restart(function(elapsed) { - t.stop(); - callback(elapsed + delay); - }, delay, time); - return t; -}; - -var emptyOn = dispatch("start", "end", "interrupt"); -var emptyTween = []; - -var CREATED = 0; -var SCHEDULED = 1; -var STARTING = 2; -var STARTED = 3; -var RUNNING = 4; -var ENDING = 5; -var ENDED = 6; - -var schedule = function(node, name, id, index, group, timing) { - var schedules = node.__transition; - if (!schedules) node.__transition = {}; - else if (id in schedules) return; - create(node, id, { - name: name, - index: index, // For context during callback. - group: group, // For context during callback. - on: emptyOn, - tween: emptyTween, - time: timing.time, - delay: timing.delay, - duration: timing.duration, - ease: timing.ease, - timer: null, - state: CREATED - }); -}; - -function init(node, id) { - var schedule = node.__transition; - if (!schedule || !(schedule = schedule[id]) || schedule.state > CREATED) throw new Error("too late"); - return schedule; -} - -function set$2(node, id) { - var schedule = node.__transition; - if (!schedule || !(schedule = schedule[id]) || schedule.state > STARTING) throw new Error("too late"); - return schedule; -} - -function get(node, id) { - var schedule = node.__transition; - if (!schedule || !(schedule = schedule[id])) throw new Error("too late"); - return schedule; -} - -function create(node, id, self) { - var schedules = node.__transition, - tween; - - // Initialize the self timer when the transition is created. - // Note the actual delay is not known until the first callback! - schedules[id] = self; - self.timer = timer(schedule, 0, self.time); - - function schedule(elapsed) { - self.state = SCHEDULED; - self.timer.restart(start, self.delay, self.time); - - // If the elapsed delay is less than our first sleep, start immediately. - if (self.delay <= elapsed) start(elapsed - self.delay); - } - - function start(elapsed) { - var i, j, n, o; - - // If the state is not SCHEDULED, then we previously errored on start. - if (self.state !== SCHEDULED) return stop(); - - for (i in schedules) { - o = schedules[i]; - if (o.name !== self.name) continue; - - // While this element already has a starting transition during this frame, - // defer starting an interrupting transition until that transition has a - // chance to tick (and possibly end); see d3/d3-transition#54! - if (o.state === STARTED) return timeout$1(start); - - // Interrupt the active transition, if any. - // Dispatch the interrupt event. - if (o.state === RUNNING) { - o.state = ENDED; - o.timer.stop(); - o.on.call("interrupt", node, node.__data__, o.index, o.group); - delete schedules[i]; - } - - // Cancel any pre-empted transitions. No interrupt event is dispatched - // because the cancelled transitions never started. Note that this also - // removes this transition from the pending list! - else if (+i < id) { - o.state = ENDED; - o.timer.stop(); - delete schedules[i]; - } - } - - // Defer the first tick to end of the current frame; see d3/d3#1576. - // Note the transition may be canceled after start and before the first tick! - // Note this must be scheduled before the start event; see d3/d3-transition#16! - // Assuming this is successful, subsequent callbacks go straight to tick. - timeout$1(function() { - if (self.state === STARTED) { - self.state = RUNNING; - self.timer.restart(tick, self.delay, self.time); - tick(elapsed); - } - }); - - // Dispatch the start event. - // Note this must be done before the tween are initialized. - self.state = STARTING; - self.on.call("start", node, node.__data__, self.index, self.group); - if (self.state !== STARTING) return; // interrupted - self.state = STARTED; - - // Initialize the tween, deleting null tween. - tween = new Array(n = self.tween.length); - for (i = 0, j = -1; i < n; ++i) { - if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) { - tween[++j] = o; - } - } - tween.length = j + 1; - } - - function tick(elapsed) { - var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1), - i = -1, - n = tween.length; - - while (++i < n) { - tween[i].call(null, t); - } - - // Dispatch the end event. - if (self.state === ENDING) { - self.on.call("end", node, node.__data__, self.index, self.group); - stop(); - } - } - - function stop() { - self.state = ENDED; - self.timer.stop(); - delete schedules[id]; - for (var i in schedules) return; // eslint-disable-line no-unused-vars - delete node.__transition; - } -} - -var interrupt = function(node, name) { - var schedules = node.__transition, - schedule$$1, - active, - empty = true, - i; - - if (!schedules) return; - - name = name == null ? null : name + ""; - - for (i in schedules) { - if ((schedule$$1 = schedules[i]).name !== name) { empty = false; continue; } - active = schedule$$1.state > STARTING && schedule$$1.state < ENDING; - schedule$$1.state = ENDED; - schedule$$1.timer.stop(); - if (active) schedule$$1.on.call("interrupt", node, node.__data__, schedule$$1.index, schedule$$1.group); - delete schedules[i]; - } - - if (empty) delete node.__transition; -}; - -var selection_interrupt = function(name) { - return this.each(function() { - interrupt(this, name); - }); -}; - -function tweenRemove(id, name) { - var tween0, tween1; - return function() { - var schedule$$1 = set$2(this, id), - tween = schedule$$1.tween; - - // If this node shared tween with the previous node, - // just assign the updated shared tween and we’re done! - // Otherwise, copy-on-write. - if (tween !== tween0) { - tween1 = tween0 = tween; - for (var i = 0, n = tween1.length; i < n; ++i) { - if (tween1[i].name === name) { - tween1 = tween1.slice(); - tween1.splice(i, 1); - break; - } - } - } - - schedule$$1.tween = tween1; - }; -} - -function tweenFunction(id, name, value) { - var tween0, tween1; - if (typeof value !== "function") throw new Error; - return function() { - var schedule$$1 = set$2(this, id), - tween = schedule$$1.tween; - - // If this node shared tween with the previous node, - // just assign the updated shared tween and we’re done! - // Otherwise, copy-on-write. - if (tween !== tween0) { - tween1 = (tween0 = tween).slice(); - for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) { - if (tween1[i].name === name) { - tween1[i] = t; - break; - } - } - if (i === n) tween1.push(t); - } - - schedule$$1.tween = tween1; - }; -} - -var transition_tween = function(name, value) { - var id = this._id; - - name += ""; - - if (arguments.length < 2) { - var tween = get(this.node(), id).tween; - for (var i = 0, n = tween.length, t; i < n; ++i) { - if ((t = tween[i]).name === name) { - return t.value; - } - } - return null; - } - - return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value)); -}; - -function tweenValue(transition, name, value) { - var id = transition._id; - - transition.each(function() { - var schedule$$1 = set$2(this, id); - (schedule$$1.value || (schedule$$1.value = {}))[name] = value.apply(this, arguments); - }); - - return function(node) { - return get(node, id).value[name]; - }; -} - -var interpolate = function(a, b) { - var c; - return (typeof b === "number" ? interpolateNumber - : b instanceof color ? interpolateRgb - : (c = color(b)) ? (b = c, interpolateRgb) - : interpolateString)(a, b); -}; - -function attrRemove$1(name) { - return function() { - this.removeAttribute(name); - }; -} - -function attrRemoveNS$1(fullname) { - return function() { - this.removeAttributeNS(fullname.space, fullname.local); - }; -} - -function attrConstant$1(name, interpolate$$1, value1) { - var value00, - interpolate0; - return function() { - var value0 = this.getAttribute(name); - return value0 === value1 ? null - : value0 === value00 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value1); - }; -} - -function attrConstantNS$1(fullname, interpolate$$1, value1) { - var value00, - interpolate0; - return function() { - var value0 = this.getAttributeNS(fullname.space, fullname.local); - return value0 === value1 ? null - : value0 === value00 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value1); - }; -} - -function attrFunction$1(name, interpolate$$1, value) { - var value00, - value10, - interpolate0; - return function() { - var value0, value1 = value(this); - if (value1 == null) return void this.removeAttribute(name); - value0 = this.getAttribute(name); - return value0 === value1 ? null - : value0 === value00 && value1 === value10 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); - }; -} - -function attrFunctionNS$1(fullname, interpolate$$1, value) { - var value00, - value10, - interpolate0; - return function() { - var value0, value1 = value(this); - if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local); - value0 = this.getAttributeNS(fullname.space, fullname.local); - return value0 === value1 ? null - : value0 === value00 && value1 === value10 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); - }; -} - -var transition_attr = function(name, value) { - var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate; - return this.attrTween(name, typeof value === "function" - ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)(fullname, i, tweenValue(this, "attr." + name, value)) - : value == null ? (fullname.local ? attrRemoveNS$1 : attrRemove$1)(fullname) - : (fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, i, value + "")); -}; - -function attrTweenNS(fullname, value) { - function tween() { - var node = this, i = value.apply(node, arguments); - return i && function(t) { - node.setAttributeNS(fullname.space, fullname.local, i(t)); - }; - } - tween._value = value; - return tween; -} - -function attrTween(name, value) { - function tween() { - var node = this, i = value.apply(node, arguments); - return i && function(t) { - node.setAttribute(name, i(t)); - }; - } - tween._value = value; - return tween; -} - -var transition_attrTween = function(name, value) { - var key = "attr." + name; - if (arguments.length < 2) return (key = this.tween(key)) && key._value; - if (value == null) return this.tween(key, null); - if (typeof value !== "function") throw new Error; - var fullname = namespace(name); - return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value)); -}; - -function delayFunction(id, value) { - return function() { - init(this, id).delay = +value.apply(this, arguments); - }; -} - -function delayConstant(id, value) { - return value = +value, function() { - init(this, id).delay = value; - }; -} - -var transition_delay = function(value) { - var id = this._id; - - return arguments.length - ? this.each((typeof value === "function" - ? delayFunction - : delayConstant)(id, value)) - : get(this.node(), id).delay; -}; - -function durationFunction(id, value) { - return function() { - set$2(this, id).duration = +value.apply(this, arguments); - }; -} - -function durationConstant(id, value) { - return value = +value, function() { - set$2(this, id).duration = value; - }; -} - -var transition_duration = function(value) { - var id = this._id; - - return arguments.length - ? this.each((typeof value === "function" - ? durationFunction - : durationConstant)(id, value)) - : get(this.node(), id).duration; -}; - -function easeConstant(id, value) { - if (typeof value !== "function") throw new Error; - return function() { - set$2(this, id).ease = value; - }; -} - -var transition_ease = function(value) { - var id = this._id; - - return arguments.length - ? this.each(easeConstant(id, value)) - : get(this.node(), id).ease; -}; - -var transition_filter = function(match) { - if (typeof match !== "function") match = matcher$1(match); - - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { - if ((node = group[i]) && match.call(node, node.__data__, i, group)) { - subgroup.push(node); - } - } - } - - return new Transition(subgroups, this._parents, this._name, this._id); -}; - -var transition_merge = function(transition$$1) { - if (transition$$1._id !== this._id) throw new Error; - - for (var groups0 = this._groups, groups1 = transition$$1._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { - for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { - if (node = group0[i] || group1[i]) { - merge[i] = node; - } - } - } - - for (; j < m0; ++j) { - merges[j] = groups0[j]; - } - - return new Transition(merges, this._parents, this._name, this._id); -}; - -function start(name) { - return (name + "").trim().split(/^|\s+/).every(function(t) { - var i = t.indexOf("."); - if (i >= 0) t = t.slice(0, i); - return !t || t === "start"; - }); -} - -function onFunction(id, name, listener) { - var on0, on1, sit = start(name) ? init : set$2; - return function() { - var schedule$$1 = sit(this, id), - on = schedule$$1.on; - - // If this node shared a dispatch with the previous node, - // just assign the updated shared dispatch and we’re done! - // Otherwise, copy-on-write. - if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener); - - schedule$$1.on = on1; - }; -} - -var transition_on = function(name, listener) { - var id = this._id; - - return arguments.length < 2 - ? get(this.node(), id).on.on(name) - : this.each(onFunction(id, name, listener)); -}; - -function removeFunction(id) { - return function() { - var parent = this.parentNode; - for (var i in this.__transition) if (+i !== id) return; - if (parent) parent.removeChild(this); - }; -} - -var transition_remove = function() { - return this.on("end.remove", removeFunction(this._id)); -}; - -var transition_select = function(select) { - var name = this._name, - id = this._id; - - if (typeof select !== "function") select = selector(select); - - for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { - if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { - if ("__data__" in node) subnode.__data__ = node.__data__; - subgroup[i] = subnode; - schedule(subgroup[i], name, id, i, subgroup, get(node, id)); - } - } - } - - return new Transition(subgroups, this._parents, name, id); -}; - -var transition_selectAll = function(select) { - var name = this._name, - id = this._id; - - if (typeof select !== "function") select = selectorAll(select); - - for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - for (var children = select.call(node, node.__data__, i, group), child, inherit = get(node, id), k = 0, l = children.length; k < l; ++k) { - if (child = children[k]) { - schedule(child, name, id, k, children, inherit); - } - } - subgroups.push(children); - parents.push(node); - } - } - } - - return new Transition(subgroups, parents, name, id); -}; - -var Selection$1 = selection.prototype.constructor; - -var transition_selection = function() { - return new Selection$1(this._groups, this._parents); -}; - -function styleRemove$1(name, interpolate$$1) { - var value00, - value10, - interpolate0; - return function() { - var value0 = styleValue(this, name), - value1 = (this.style.removeProperty(name), styleValue(this, name)); - return value0 === value1 ? null - : value0 === value00 && value1 === value10 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); - }; -} - -function styleRemoveEnd(name) { - return function() { - this.style.removeProperty(name); - }; -} - -function styleConstant$1(name, interpolate$$1, value1) { - var value00, - interpolate0; - return function() { - var value0 = styleValue(this, name); - return value0 === value1 ? null - : value0 === value00 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value1); - }; -} - -function styleFunction$1(name, interpolate$$1, value) { - var value00, - value10, - interpolate0; - return function() { - var value0 = styleValue(this, name), - value1 = value(this); - if (value1 == null) value1 = (this.style.removeProperty(name), styleValue(this, name)); - return value0 === value1 ? null - : value0 === value00 && value1 === value10 ? interpolate0 - : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); - }; -} - -var transition_style = function(name, value, priority) { - var i = (name += "") === "transform" ? interpolateTransformCss : interpolate; - return value == null ? this - .styleTween(name, styleRemove$1(name, i)) - .on("end.style." + name, styleRemoveEnd(name)) - : this.styleTween(name, typeof value === "function" - ? styleFunction$1(name, i, tweenValue(this, "style." + name, value)) - : styleConstant$1(name, i, value + ""), priority); -}; - -function styleTween(name, value, priority) { - function tween() { - var node = this, i = value.apply(node, arguments); - return i && function(t) { - node.style.setProperty(name, i(t), priority); - }; - } - tween._value = value; - return tween; -} - -var transition_styleTween = function(name, value, priority) { - var key = "style." + (name += ""); - if (arguments.length < 2) return (key = this.tween(key)) && key._value; - if (value == null) return this.tween(key, null); - if (typeof value !== "function") throw new Error; - return this.tween(key, styleTween(name, value, priority == null ? "" : priority)); -}; - -function textConstant$1(value) { - return function() { - this.textContent = value; - }; -} - -function textFunction$1(value) { - return function() { - var value1 = value(this); - this.textContent = value1 == null ? "" : value1; - }; -} - -var transition_text = function(value) { - return this.tween("text", typeof value === "function" - ? textFunction$1(tweenValue(this, "text", value)) - : textConstant$1(value == null ? "" : value + "")); -}; - -var transition_transition = function() { - var name = this._name, - id0 = this._id, - id1 = newId(); - - for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - var inherit = get(node, id0); - schedule(node, name, id1, i, group, { - time: inherit.time + inherit.delay + inherit.duration, - delay: 0, - duration: inherit.duration, - ease: inherit.ease - }); - } - } - } - - return new Transition(groups, this._parents, name, id1); -}; - -var id = 0; - -function Transition(groups, parents, name, id) { - this._groups = groups; - this._parents = parents; - this._name = name; - this._id = id; -} - -function transition(name) { - return selection().transition(name); -} - -function newId() { - return ++id; -} - -var selection_prototype = selection.prototype; - -Transition.prototype = transition.prototype = { - constructor: Transition, - select: transition_select, - selectAll: transition_selectAll, - filter: transition_filter, - merge: transition_merge, - selection: transition_selection, - transition: transition_transition, - call: selection_prototype.call, - nodes: selection_prototype.nodes, - node: selection_prototype.node, - size: selection_prototype.size, - empty: selection_prototype.empty, - each: selection_prototype.each, - on: transition_on, - attr: transition_attr, - attrTween: transition_attrTween, - style: transition_style, - styleTween: transition_styleTween, - text: transition_text, - remove: transition_remove, - tween: transition_tween, - delay: transition_delay, - duration: transition_duration, - ease: transition_ease -}; - -var defaultTiming = { - time: null, // Set on use. - delay: 0, - duration: 250, - ease: cubicInOut -}; - -function inherit(node, id) { - var timing; - while (!(timing = node.__transition) || !(timing = timing[id])) { - if (!(node = node.parentNode)) { - return defaultTiming.time = now(), defaultTiming; - } - } - return timing; -} - -var selection_transition = function(name) { - var id, - timing; - - if (name instanceof Transition) { - id = name._id, name = name._name; - } else { - id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + ""; - } - - for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { - for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { - if (node = group[i]) { - schedule(node, name, id, i, group, timing || inherit(node, id)); - } - } - } - - return new Transition(groups, this._parents, name, id); -}; - -selection.prototype.interrupt = selection_interrupt; -selection.prototype.transition = selection_transition; - -exports.select = select; -exports.selection = selection; -exports.hierarchy = hierarchy; -exports.partition = partition; -exports.scaleLinear = linear; -exports.easeCubic = cubicInOut; -exports.ascending = ascending$1; -exports.map = map$1; -exports.transition = transition; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); -` diff --git a/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/LICENSE b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/D3_FLAME_GRAPH_LICENSE similarity index 100% rename from src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/LICENSE rename to src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/D3_FLAME_GRAPH_LICENSE diff --git a/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/D3_LICENSE b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/D3_LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..b0145150fd35f3e325d7ddec6ed3be68c457975e --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/D3_LICENSE @@ -0,0 +1,13 @@ +Copyright 2010-2021 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/README.md b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/README.md new file mode 100644 index 0000000000000000000000000000000000000000..eb84b6800784ed3a9420f0aafdfe65924aff8422 --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/README.md @@ -0,0 +1,33 @@ +# Building a customized D3.js bundle + +The D3.js version distributed with pprof is customized to only include the +modules required by pprof. + +## Dependencies + +- Install [npm](https://www.npmjs.com). + +## Building + +- Run `update.sh` to: + - Download npm package dependencies (declared in `package.json` and `package-lock.json`) + - Create a d3.js bundle containing the JavScript of d3 and d3-flame-graph (by running `webpack`) + +This will `d3_flame_graph.go`, the minified custom D3.js bundle as Go source code. + +# References / Appendix + +## D3 Custom Bundle + +A demonstration of building a custom D3 4.0 bundle using ES2015 modules and Rollup. + +[bl.ocks.org/mbostock/bb09af4c39c79cffcde4](https://bl.ocks.org/mbostock/bb09af4c39c79cffcde4) + +## Old version of d3-pprof + +A previous version of d3-flame-graph bundled for pprof used Rollup instead of +Webpack. This has now been migrated directly into this directory. + +The repository configuring Rollup was here: + +[github.com/spiermar/d3-pprof](https://github.com/spiermar/d3-pprof) diff --git a/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/d3_flame_graph.go b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/d3_flame_graph.go index 58a7fb4c40a8a9a5e3f09cc2f9b644925843fd31..7e2794199510033a422162e534023e8e2e3f337e 100644 --- a/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/d3_flame_graph.go +++ b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/d3_flame_graph.go @@ -1,915 +1,17 @@ -// A D3.js plugin that produces flame graphs from hierarchical data. +// D3.js is a JavaScript library for manipulating documents based on data. +// https://github.com/d3/d3 +// See D3_LICENSE file for license details + +// d3-flame-graph is a D3.js plugin that produces flame graphs from hierarchical data. // https://github.com/spiermar/d3-flame-graph -// Version 2.0.0-alpha4 -// See LICENSE file for license details +// See D3_FLAME_GRAPH_LICENSE file for license details package d3flamegraph -// JSSource returns the d3-flamegraph.js file +// JSSource returns the d3 and d3-flame-graph JavaScript bundle const JSSource = ` -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3')) : - typeof define === 'function' && define.amd ? define(['exports', 'd3'], factory) : - (factory((global.d3 = global.d3 || {}),global.d3)); -}(this, (function (exports,d3) { 'use strict'; - -var d3__default = 'default' in d3 ? d3['default'] : d3; - -var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - - - - - -function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; -} - -var d3Tip = createCommonjsModule(function (module) { -// d3.tip -// Copyright (c) 2013 Justin Palmer -// -// Tooltips for d3.js SVG visualizations - -(function (root, factory) { - if (typeof undefined === 'function' && undefined.amd) { - // AMD. Register as an anonymous module with d3 as a dependency. - undefined(['d3'], factory); - } else if ('object' === 'object' && module.exports) { - // CommonJS - var d3$$1 = d3__default; - module.exports = factory(d3$$1); - } else { - // Browser global. - root.d3.tip = factory(root.d3); - } -}(commonjsGlobal, function (d3$$1) { - - // Public - contructs a new tooltip - // - // Returns a tip - return function() { - var direction = d3_tip_direction, - offset = d3_tip_offset, - html = d3_tip_html, - node = initNode(), - svg = null, - point = null, - target = null; - - function tip(vis) { - svg = getSVGNode(vis); - point = svg.createSVGPoint(); - document.body.appendChild(node); - } - - // Public - show the tooltip on the screen - // - // Returns a tip - tip.show = function() { - var args = Array.prototype.slice.call(arguments); - if(args[args.length - 1] instanceof SVGElement) target = args.pop(); - - var content = html.apply(this, args), - poffset = offset.apply(this, args), - dir = direction.apply(this, args), - nodel = getNodeEl(), - i = directions.length, - coords, - scrollTop = document.documentElement.scrollTop || document.body.scrollTop, - scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; - - nodel.html(content) - .style('opacity', 1).style('pointer-events', 'all'); - - while(i--) nodel.classed(directions[i], false); - coords = direction_callbacks.get(dir).apply(this); - nodel.classed(dir, true) - .style('top', (coords.top + poffset[0]) + scrollTop + 'px') - .style('left', (coords.left + poffset[1]) + scrollLeft + 'px'); - - return tip; - }; - - // Public - hide the tooltip - // - // Returns a tip - tip.hide = function() { - var nodel = getNodeEl(); - nodel.style('opacity', 0).style('pointer-events', 'none'); - return tip - }; - - // Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value. - // - // n - name of the attribute - // v - value of the attribute - // - // Returns tip or attribute value - tip.attr = function(n, v) { - if (arguments.length < 2 && typeof n === 'string') { - return getNodeEl().attr(n) - } else { - var args = Array.prototype.slice.call(arguments); - d3$$1.selection.prototype.attr.apply(getNodeEl(), args); - } - - return tip - }; - - // Public: Proxy style calls to the d3 tip container. Sets or gets a style value. - // - // n - name of the property - // v - value of the property - // - // Returns tip or style property value - tip.style = function(n, v) { - if (arguments.length < 2 && typeof n === 'string') { - return getNodeEl().style(n) - } else { - var args = Array.prototype.slice.call(arguments); - d3$$1.selection.prototype.style.apply(getNodeEl(), args); - } - - return tip - }; - - // Public: Set or get the direction of the tooltip - // - // v - One of n(north), s(south), e(east), or w(west), nw(northwest), - // sw(southwest), ne(northeast) or se(southeast) - // - // Returns tip or direction - tip.direction = function(v) { - if (!arguments.length) return direction - direction = v == null ? v : functor(v); - - return tip - }; - - // Public: Sets or gets the offset of the tip - // - // v - Array of [x, y] offset - // - // Returns offset or - tip.offset = function(v) { - if (!arguments.length) return offset - offset = v == null ? v : functor(v); - - return tip - }; - - // Public: sets or gets the html value of the tooltip - // - // v - String value of the tip - // - // Returns html value or tip - tip.html = function(v) { - if (!arguments.length) return html - html = v == null ? v : functor(v); - - return tip - }; - - // Public: destroys the tooltip and removes it from the DOM - // - // Returns a tip - tip.destroy = function() { - if(node) { - getNodeEl().remove(); - node = null; - } - return tip; - }; - - function d3_tip_direction() { return 'n' } - function d3_tip_offset() { return [0, 0] } - function d3_tip_html() { return ' ' } - - var direction_callbacks = d3$$1.map({ - n: direction_n, - s: direction_s, - e: direction_e, - w: direction_w, - nw: direction_nw, - ne: direction_ne, - sw: direction_sw, - se: direction_se - }), - - directions = direction_callbacks.keys(); - - function direction_n() { - var bbox = getScreenBBox(); - return { - top: bbox.n.y - node.offsetHeight, - left: bbox.n.x - node.offsetWidth / 2 - } - } - - function direction_s() { - var bbox = getScreenBBox(); - return { - top: bbox.s.y, - left: bbox.s.x - node.offsetWidth / 2 - } - } - - function direction_e() { - var bbox = getScreenBBox(); - return { - top: bbox.e.y - node.offsetHeight / 2, - left: bbox.e.x - } - } - - function direction_w() { - var bbox = getScreenBBox(); - return { - top: bbox.w.y - node.offsetHeight / 2, - left: bbox.w.x - node.offsetWidth - } - } - - function direction_nw() { - var bbox = getScreenBBox(); - return { - top: bbox.nw.y - node.offsetHeight, - left: bbox.nw.x - node.offsetWidth - } - } - - function direction_ne() { - var bbox = getScreenBBox(); - return { - top: bbox.ne.y - node.offsetHeight, - left: bbox.ne.x - } - } - - function direction_sw() { - var bbox = getScreenBBox(); - return { - top: bbox.sw.y, - left: bbox.sw.x - node.offsetWidth - } - } - - function direction_se() { - var bbox = getScreenBBox(); - return { - top: bbox.se.y, - left: bbox.e.x - } - } - - function initNode() { - var node = d3$$1.select(document.createElement('div')); - node.style('position', 'absolute').style('top', 0).style('opacity', 0) - .style('pointer-events', 'none').style('box-sizing', 'border-box'); - - return node.node() - } - - function getSVGNode(el) { - el = el.node(); - if(el.tagName.toLowerCase() === 'svg') - return el - - return el.ownerSVGElement - } - - function getNodeEl() { - if(node === null) { - node = initNode(); - // re-add node to DOM - document.body.appendChild(node); - } - return d3$$1.select(node); - } - - // Private - gets the screen coordinates of a shape - // - // Given a shape on the screen, will return an SVGPoint for the directions - // n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest), - // sw(southwest). - // - // +-+-+ - // | | - // + + - // | | - // +-+-+ - // - // Returns an Object {n, s, e, w, nw, sw, ne, se} - function getScreenBBox() { - var targetel = target || d3$$1.event.target; - - while ('undefined' === typeof targetel.getScreenCTM && 'undefined' === targetel.parentNode) { - targetel = targetel.parentNode; - } - - var bbox = {}, - matrix = targetel.getScreenCTM(), - tbbox = targetel.getBBox(), - width = tbbox.width, - height = tbbox.height, - x = tbbox.x, - y = tbbox.y; - - point.x = x; - point.y = y; - bbox.nw = point.matrixTransform(matrix); - point.x += width; - bbox.ne = point.matrixTransform(matrix); - point.y += height; - bbox.se = point.matrixTransform(matrix); - point.x -= width; - bbox.sw = point.matrixTransform(matrix); - point.y -= height / 2; - bbox.w = point.matrixTransform(matrix); - point.x += width; - bbox.e = point.matrixTransform(matrix); - point.x -= width / 2; - point.y -= height / 2; - bbox.n = point.matrixTransform(matrix); - point.y += height; - bbox.s = point.matrixTransform(matrix); - - return bbox - } - - // Private - replace D3JS 3.X d3.functor() function - function functor(v) { - return typeof v === "function" ? v : function() { - return v - } - } - - return tip - }; - -})); -}); - -var flamegraph = function () { - var w = 960; // graph width - var h = null; // graph height - var c = 18; // cell height - var selection = null; // selection - var tooltip = true; // enable tooltip - var title = ''; // graph title - var transitionDuration = 750; - var transitionEase = d3.easeCubic; // tooltip offset - var sort = false; - var inverted = false; // invert the graph direction - var clickHandler = null; - var minFrameSize = 0; - var details = null; - - var tip = d3Tip() - .direction('s') - .offset([8, 0]) - .attr('class', 'd3-flame-graph-tip') - .html(function (d) { return label(d) }); - - var svg; - - function name (d) { - return d.data.n || d.data.name - } - - function libtype (d) { - return d.data.l || d.data.libtype - } - - function children (d) { - return d.c || d.children - } - - function value (d) { - return d.v || d.value - } - - var label = function (d) { - return name(d) + ' (' + d3.format('.3f')(100 * (d.x1 - d.x0), 3) + '%, ' + value(d) + ' samples)' - }; - - function setDetails (t) { - if (details) { details.innerHTML = t; } - } - - var colorMapper = function (d) { - return d.highlight ? '#E600E6' : colorHash(name(d), libtype(d)) - }; - - function generateHash (name) { - // Return a vector (0.0->1.0) that is a hash of the input string. - // The hash is computed to favor early characters over later ones, so - // that strings with similar starts have similar vectors. Only the first - // 6 characters are considered. - const MAX_CHAR = 6; - - var hash = 0; - var maxHash = 0; - var weight = 1; - var mod = 10; - - if (name) { - for (var i = 0; i < name.length; i++) { - if (i > MAX_CHAR) { break } - hash += weight * (name.charCodeAt(i) % mod); - maxHash += weight * (mod - 1); - weight *= 0.70; - } - if (maxHash > 0) { hash = hash / maxHash; } - } - return hash - } - - function colorHash (name, libtype) { - // Return a color for the given name and library type. The library type - // selects the hue, and the name is hashed to a color in that hue. - - var r; - var g; - var b; - - // Select hue. Order is important. - var hue; - if (typeof libtype === 'undefined' || libtype === '') { - // default when libtype is not in use - hue = 'warm'; - } else { - hue = 'red'; - if (name.match(/::/)) { - hue = 'yellow'; - } - if (libtype === 'kernel') { - hue = 'orange'; - } else if (libtype === 'jit') { - hue = 'green'; - } else if (libtype === 'inlined') { - hue = 'aqua'; - } - } - - // calculate hash - var vector = 0; - if (name) { - var nameArr = name.split('` + "`" + `'); - if (nameArr.length > 1) { - name = nameArr[nameArr.length - 1]; // drop module name if present - } - name = name.split('(')[0]; // drop extra info - vector = generateHash(name); - } - - // calculate color - if (hue === 'red') { - r = 200 + Math.round(55 * vector); - g = 50 + Math.round(80 * vector); - b = g; - } else if (hue === 'orange') { - r = 190 + Math.round(65 * vector); - g = 90 + Math.round(65 * vector); - b = 0; - } else if (hue === 'yellow') { - r = 175 + Math.round(55 * vector); - g = r; - b = 50 + Math.round(20 * vector); - } else if (hue === 'green') { - r = 50 + Math.round(60 * vector); - g = 200 + Math.round(55 * vector); - b = r; - } else if (hue === 'aqua') { - r = 50 + Math.round(60 * vector); - g = 165 + Math.round(55 * vector); - b = g; - } else { - // original warm palette - r = 200 + Math.round(55 * vector); - g = 0 + Math.round(230 * (1 - vector)); - b = 0 + Math.round(55 * (1 - vector)); - } - - return 'rgb(' + r + ',' + g + ',' + b + ')' - } - - function hide (d) { - d.data.hide = true; - if (children(d)) { - children(d).forEach(hide); - } - } - - function show (d) { - d.data.fade = false; - d.data.hide = false; - if (children(d)) { - children(d).forEach(show); - } - } - - function getSiblings (d) { - var siblings = []; - if (d.parent) { - var me = d.parent.children.indexOf(d); - siblings = d.parent.children.slice(0); - siblings.splice(me, 1); - } - return siblings - } - - function hideSiblings (d) { - var siblings = getSiblings(d); - siblings.forEach(function (s) { - hide(s); - }); - if (d.parent) { - hideSiblings(d.parent); - } - } - function fadeAncestors (d) { - if (d.parent) { - d.parent.data.fade = true; - fadeAncestors(d.parent); - } - } - - // function getRoot (d) { - // if (d.parent) { - // return getRoot(d.parent) - // } - // return d - // } - - function zoom (d) { - tip.hide(d); - hideSiblings(d); - show(d); - fadeAncestors(d); - update(); - if (typeof clickHandler === 'function') { - clickHandler(d); - } - } - - function searchTree (d, term) { - var re = new RegExp(term); - var searchResults = []; - - function searchInner (d) { - var label = name(d); - - if (children(d)) { - children(d).forEach(function (child) { - searchInner(child); - }); - } - - if (label.match(re)) { - d.highlight = true; - searchResults.push(d); - } else { - d.highlight = false; - } - } - - searchInner(d); - return searchResults - } - - function clear (d) { - d.highlight = false; - if (children(d)) { - children(d).forEach(function (child) { - clear(child); - }); - } - } - - function doSort (a, b) { - if (typeof sort === 'function') { - return sort(a, b) - } else if (sort) { - return d3.ascending(name(a), name(b)) - } - } - - var p = d3.partition(); - - function filterNodes (root) { - var nodeList = root.descendants(); - if (minFrameSize > 0) { - var kx = w / (root.x1 - root.x0); - nodeList = nodeList.filter(function (el) { - return ((el.x1 - el.x0) * kx) > minFrameSize - }); - } - return nodeList - } - - function update () { - selection.each(function (root) { - var x = d3.scaleLinear().range([0, w]); - var y = d3.scaleLinear().range([0, c]); - - if (sort) root.sort(doSort); - root.sum(function (d) { - if (d.fade || d.hide) { - return 0 - } - // The node's self value is its total value minus all children. - var v = value(d); - if (children(d)) { - var c = children(d); - for (var i = 0; i < c.length; i++) { - v -= value(c[i]); - } - } - return v - }); - p(root); - - var kx = w / (root.x1 - root.x0); - function width (d) { return (d.x1 - d.x0) * kx } - - var descendants = filterNodes(root); - var g = d3.select(this).select('svg').selectAll('g').data(descendants, function (d) { return d.id }); - - g.transition() - .duration(transitionDuration) - .ease(transitionEase) - .attr('transform', function (d) { return 'translate(' + x(d.x0) + ',' + (inverted ? y(d.depth) : (h - y(d.depth) - c)) + ')' }); - - g.select('rect') - .attr('width', width); - - var node = g.enter() - .append('svg:g') - .attr('transform', function (d) { return 'translate(' + x(d.x0) + ',' + (inverted ? y(d.depth) : (h - y(d.depth) - c)) + ')' }); - - node.append('svg:rect') - .transition() - .delay(transitionDuration / 2) - .attr('width', width); - - if (!tooltip) { node.append('svg:title'); } - - node.append('foreignObject') - .append('xhtml:div'); - - // Now we have to re-select to see the new elements (why?). - g = d3.select(this).select('svg').selectAll('g').data(descendants, function (d) { return d.id }); - - g.attr('width', width) - .attr('height', function (d) { return c }) - .attr('name', function (d) { return name(d) }) - .attr('class', function (d) { return d.data.fade ? 'frame fade' : 'frame' }); - - g.select('rect') - .attr('height', function (d) { return c }) - .attr('fill', function (d) { return colorMapper(d) }); - - if (!tooltip) { - g.select('title') - .text(label); - } - - g.select('foreignObject') - .attr('width', width) - .attr('height', function (d) { return c }) - .select('div') - .attr('class', 'd3-flame-graph-label') - .style('display', function (d) { return (width(d) < 35) ? 'none' : 'block' }) - .transition() - .delay(transitionDuration) - .text(name); - - g.on('click', zoom); - - g.exit() - .remove(); - - g.on('mouseover', function (d) { - if (tooltip) tip.show(d, this); - setDetails(label(d)); - }).on('mouseout', function (d) { - if (tooltip) tip.hide(d); - setDetails(''); - }); - }); - } - - function merge (data, samples) { - samples.forEach(function (sample) { - var node = data.find(function (element) { - return (element.name === sample.name) - }); - - if (node) { - if (node.original) { - node.original += sample.value; - } else { - node.value += sample.value; - } - if (sample.children) { - if (!node.children) { - node.children = []; - } - merge(node.children, sample.children); - } - } else { - data.push(sample); - } - }); - } - - function s4 () { - return Math.floor((1 + Math.random()) * 0x10000) - .toString(16) - .substring(1) - } - - function injectIds (node) { - node.id = s4() + '-' + s4() + '-' + '-' + s4() + '-' + s4(); - var children = node.c || node.children || []; - for (var i = 0; i < children.length; i++) { - injectIds(children[i]); - } - } - - function chart (s) { - var root = d3.hierarchy( - s.datum(), function (d) { return children(d) } - ); - injectIds(root); - selection = s.datum(root); - - if (!arguments.length) return chart - - if (!h) { - h = (root.height + 2) * c; - } - - selection.each(function (data) { - if (!svg) { - svg = d3.select(this) - .append('svg:svg') - .attr('width', w) - .attr('height', h) - .attr('class', 'partition d3-flame-graph') - .call(tip); - - svg.append('svg:text') - .attr('class', 'title') - .attr('text-anchor', 'middle') - .attr('y', '25') - .attr('x', w / 2) - .attr('fill', '#808080') - .text(title); - } - }); - - // first draw - update(); - } - - chart.height = function (_) { - if (!arguments.length) { return h } - h = _; - return chart - }; - - chart.width = function (_) { - if (!arguments.length) { return w } - w = _; - return chart - }; - - chart.cellHeight = function (_) { - if (!arguments.length) { return c } - c = _; - return chart - }; - - chart.tooltip = function (_) { - if (!arguments.length) { return tooltip } - if (typeof _ === 'function') { - tip = _; - } - tooltip = !!_; - return chart - }; - - chart.title = function (_) { - if (!arguments.length) { return title } - title = _; - return chart - }; - - chart.transitionDuration = function (_) { - if (!arguments.length) { return transitionDuration } - transitionDuration = _; - return chart - }; - - chart.transitionEase = function (_) { - if (!arguments.length) { return transitionEase } - transitionEase = _; - return chart - }; - - chart.sort = function (_) { - if (!arguments.length) { return sort } - sort = _; - return chart - }; - - chart.inverted = function (_) { - if (!arguments.length) { return inverted } - inverted = _; - return chart - }; - - chart.label = function (_) { - if (!arguments.length) { return label } - label = _; - return chart - }; - - chart.search = function (term) { - var searchResults = []; - selection.each(function (data) { - searchResults = searchTree(data, term); - update(); - }); - return searchResults - }; - - chart.clear = function () { - selection.each(function (data) { - clear(data); - update(); - }); - }; - - chart.zoomTo = function (d) { - zoom(d); - }; - - chart.resetZoom = function () { - selection.each(function (data) { - zoom(data); // zoom to root - }); - }; - - chart.onClick = function (_) { - if (!arguments.length) { - return clickHandler - } - clickHandler = _; - return chart - }; - - chart.merge = function (samples) { - var newRoot; // Need to re-create hierarchy after data changes. - selection.each(function (root) { - merge([root.data], [samples]); - newRoot = d3.hierarchy(root.data, function (d) { return children(d) }); - injectIds(newRoot); - }); - selection = selection.datum(newRoot); - update(); - }; - - chart.color = function (_) { - if (!arguments.length) { return colorMapper } - colorMapper = _; - return chart - }; - - chart.minFrameSize = function (_) { - if (!arguments.length) { return minFrameSize } - minFrameSize = _; - return chart - }; - - chart.details = function (_) { - if (!arguments.length) { return details } - details = _; - return chart - }; - - return chart -}; - -exports.flamegraph = flamegraph; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); +!function(t,n){if("object"==typeof exports&&"object"==typeof module)module.exports=n();else if("function"==typeof define&&define.amd)define([],n);else{var e=n();for(var r in e)("object"==typeof exports?exports:t)[r]=e[r]}}(self,(function(){return(()=>{"use strict";var t={d:(n,e)=>{for(var r in e)t.o(e,r)&&!t.o(n,r)&&Object.defineProperty(n,r,{enumerable:!0,get:e[r]})},o:(t,n)=>Object.prototype.hasOwnProperty.call(t,n),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},n={};function e(){}function r(t){return null==t?e:function(){return this.querySelector(t)}}function i(t){return null==t?[]:Array.isArray(t)?t:Array.from(t)}function o(){return[]}function u(t){return function(n){return n.matches(t)}}t.r(n),t.d(n,{flamegraph:()=>ji,select:()=>pt});var a=Array.prototype.find;function l(){return this.firstElementChild}var s=Array.prototype.filter;function c(){return Array.from(this.children)}function f(t){return new Array(t.length)}function h(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=n}function p(t){return function(){return t}}function d(t,n,e,r,i,o){for(var u,a=0,l=n.length,s=o.length;a<s;++a)(u=n[a])?(u.__data__=o[a],r[a]=u):e[a]=new h(t,o[a]);for(;a<l;++a)(u=n[a])&&(i[a]=u)}function g(t,n,e,r,i,o,u){var a,l,s,c=new Map,f=n.length,p=o.length,d=new Array(f);for(a=0;a<f;++a)(l=n[a])&&(d[a]=s=u.call(l,l.__data__,a,n)+"",c.has(s)?i[a]=l:c.set(s,l));for(a=0;a<p;++a)s=u.call(t,o[a],a,o)+"",(l=c.get(s))?(r[a]=l,l.__data__=o[a],c.delete(s)):e[a]=new h(t,o[a]);for(a=0;a<f;++a)(l=n[a])&&c.get(d[a])===l&&(i[a]=l)}function v(t){return t.__data__}function y(t){return"object"==typeof t&&"length"in t?t:Array.from(t)}function m(t,n){return t<n?-1:t>n?1:t>=n?0:NaN}h.prototype={constructor:h,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,n){return this._parent.insertBefore(t,n)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var _="http://www.w3.org/1999/xhtml";const w={svg:"http://www.w3.org/2000/svg",xhtml:_,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};function b(t){var n=t+="",e=n.indexOf(":");return e>=0&&"xmlns"!==(n=t.slice(0,e))&&(t=t.slice(e+1)),w.hasOwnProperty(n)?{space:w[n],local:t}:t}function x(t){return function(){this.removeAttribute(t)}}function M(t){return function(){this.removeAttributeNS(t.space,t.local)}}function A(t,n){return function(){this.setAttribute(t,n)}}function N(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}function E(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}}function k(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}}function S(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function C(t){return function(){this.style.removeProperty(t)}}function P(t,n,e){return function(){this.style.setProperty(t,n,e)}}function j(t,n,e){return function(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}}function q(t,n){return t.style.getPropertyValue(n)||S(t).getComputedStyle(t,null).getPropertyValue(n)}function O(t){return function(){delete this[t]}}function L(t,n){return function(){this[t]=n}}function T(t,n){return function(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}}function B(t){return t.trim().split(/^|\s+/)}function D(t){return t.classList||new H(t)}function H(t){this._node=t,this._names=B(t.getAttribute("class")||"")}function R(t,n){for(var e=D(t),r=-1,i=n.length;++r<i;)e.add(n[r])}function V(t,n){for(var e=D(t),r=-1,i=n.length;++r<i;)e.remove(n[r])}function X(t){return function(){R(this,t)}}function z(t){return function(){V(this,t)}}function I(t,n){return function(){(n.apply(this,arguments)?R:V)(this,t)}}function $(){this.textContent=""}function U(t){return function(){this.textContent=t}}function Y(t){return function(){var n=t.apply(this,arguments);this.textContent=null==n?"":n}}function F(){this.innerHTML=""}function Z(t){return function(){this.innerHTML=t}}function G(t){return function(){var n=t.apply(this,arguments);this.innerHTML=null==n?"":n}}function J(){this.nextSibling&&this.parentNode.appendChild(this)}function K(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function Q(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===_&&n.documentElement.namespaceURI===_?n.createElement(t):n.createElementNS(e,t)}}function W(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function tt(t){var n=b(t);return(n.local?W:Q)(n)}function nt(){return null}function et(){var t=this.parentNode;t&&t.removeChild(this)}function rt(){var t=this.cloneNode(!1),n=this.parentNode;return n?n.insertBefore(t,this.nextSibling):t}function it(){var t=this.cloneNode(!0),n=this.parentNode;return n?n.insertBefore(t,this.nextSibling):t}function ot(t){return t.trim().split(/^|\s+/).map((function(t){var n="",e=t.indexOf(".");return e>=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}}))}function ut(t){return function(){var n=this.__on;if(n){for(var e,r=0,i=-1,o=n.length;r<o;++r)e=n[r],t.type&&e.type!==t.type||e.name!==t.name?n[++i]=e:this.removeEventListener(e.type,e.listener,e.options);++i?n.length=i:delete this.__on}}}function at(t,n,e){return function(){var r,i=this.__on,o=function(t){return function(n){t.call(this,n,this.__data__)}}(n);if(i)for(var u=0,a=i.length;u<a;++u)if((r=i[u]).type===t.type&&r.name===t.name)return this.removeEventListener(r.type,r.listener,r.options),this.addEventListener(r.type,r.listener=o,r.options=e),void(r.value=n);this.addEventListener(t.type,o,e),r={type:t.type,name:t.name,value:n,listener:o,options:e},i?i.push(r):this.__on=[r]}}function lt(t,n,e){var r=S(t),i=r.CustomEvent;"function"==typeof i?i=new i(n,e):(i=r.document.createEvent("Event"),e?(i.initEvent(n,e.bubbles,e.cancelable),i.detail=e.detail):i.initEvent(n,!1,!1)),t.dispatchEvent(i)}function st(t,n){return function(){return lt(this,t,n)}}function ct(t,n){return function(){return lt(this,t,n.apply(this,arguments))}}H.prototype={add:function(t){this._names.indexOf(t)<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var n=this._names.indexOf(t);n>=0&&(this._names.splice(n,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var ft=[null];function ht(t,n){this._groups=t,this._parents=n}function pt(t){return"string"==typeof t?new ht([[document.querySelector(t)]],[document.documentElement]):new ht([[t]],ft)}function dt(){}function gt(t){return null==t?dt:function(){return this.querySelector(t)}}function vt(t){return null==t?[]:Array.isArray(t)?t:Array.from(t)}function yt(){return[]}function mt(t){return null==t?yt:function(){return this.querySelectorAll(t)}}function _t(t){return function(){return this.matches(t)}}function wt(t){return function(n){return n.matches(t)}}ht.prototype=function(){return new ht([[document.documentElement]],ft)}.prototype={constructor:ht,select:function(t){"function"!=typeof t&&(t=r(t));for(var n=this._groups,e=n.length,i=new Array(e),o=0;o<e;++o)for(var u,a,l=n[o],s=l.length,c=i[o]=new Array(s),f=0;f<s;++f)(u=l[f])&&(a=t.call(u,u.__data__,f,l))&&("__data__"in u&&(a.__data__=u.__data__),c[f]=a);return new ht(i,this._parents)},selectAll:function(t){t="function"==typeof t?function(t){return function(){return i(t.apply(this,arguments))}}(t):function(t){return null==t?o:function(){return this.querySelectorAll(t)}}(t);for(var n=this._groups,e=n.length,r=[],u=[],a=0;a<e;++a)for(var l,s=n[a],c=s.length,f=0;f<c;++f)(l=s[f])&&(r.push(t.call(l,l.__data__,f,s)),u.push(l));return new ht(r,u)},selectChild:function(t){return this.select(null==t?l:function(t){return function(){return a.call(this.children,t)}}("function"==typeof t?t:u(t)))},selectChildren:function(t){return this.selectAll(null==t?c:function(t){return function(){return s.call(this.children,t)}}("function"==typeof t?t:u(t)))},filter:function(t){"function"!=typeof t&&(t=function(t){return function(){return this.matches(t)}}(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u=n[i],a=u.length,l=r[i]=[],s=0;s<a;++s)(o=u[s])&&t.call(o,o.__data__,s,u)&&l.push(o);return new ht(r,this._parents)},data:function(t,n){if(!arguments.length)return Array.from(this,v);var e=n?g:d,r=this._parents,i=this._groups;"function"!=typeof t&&(t=p(t));for(var o=i.length,u=new Array(o),a=new Array(o),l=new Array(o),s=0;s<o;++s){var c=r[s],f=i[s],h=f.length,m=y(t.call(c,c&&c.__data__,s,r)),_=m.length,w=a[s]=new Array(_),b=u[s]=new Array(_),x=l[s]=new Array(h);e(c,f,w,b,x,m,n);for(var M,A,N=0,E=0;N<_;++N)if(M=w[N]){for(N>=E&&(E=N+1);!(A=b[E])&&++E<_;);M._next=A||null}}return(u=new ht(u,r))._enter=a,u._exit=l,u},enter:function(){return new ht(this._enter||this._groups.map(f),this._parents)},exit:function(){return new ht(this._exit||this._groups.map(f),this._parents)},join:function(t,n,e){var r=this.enter(),i=this,o=this.exit();return"function"==typeof t?(r=t(r))&&(r=r.selection()):r=r.append(t+""),null!=n&&(i=n(i))&&(i=i.selection()),null==e?o.remove():e(o),r&&i?r.merge(i).order():i},merge:function(t){for(var n=t.selection?t.selection():t,e=this._groups,r=n._groups,i=e.length,o=r.length,u=Math.min(i,o),a=new Array(i),l=0;l<u;++l)for(var s,c=e[l],f=r[l],h=c.length,p=a[l]=new Array(h),d=0;d<h;++d)(s=c[d]||f[d])&&(p[d]=s);for(;l<i;++l)a[l]=e[l];return new ht(a,this._parents)},selection:function(){return this},order:function(){for(var t=this._groups,n=-1,e=t.length;++n<e;)for(var r,i=t[n],o=i.length-1,u=i[o];--o>=0;)(r=i[o])&&(u&&4^r.compareDocumentPosition(u)&&u.parentNode.insertBefore(r,u),u=r);return this},sort:function(t){function n(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e}t||(t=m);for(var e=this._groups,r=e.length,i=new Array(r),o=0;o<r;++o){for(var u,a=e[o],l=a.length,s=i[o]=new Array(l),c=0;c<l;++c)(u=a[c])&&(s[c]=u);s.sort(n)}return new ht(i,this._parents).order()},call:function(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this},nodes:function(){return Array.from(this)},node:function(){for(var t=this._groups,n=0,e=t.length;n<e;++n)for(var r=t[n],i=0,o=r.length;i<o;++i){var u=r[i];if(u)return u}return null},size:function(){let t=0;for(const n of this)++t;return t},empty:function(){return!this.node()},each:function(t){for(var n=this._groups,e=0,r=n.length;e<r;++e)for(var i,o=n[e],u=0,a=o.length;u<a;++u)(i=o[u])&&t.call(i,i.__data__,u,o);return this},attr:function(t,n){var e=b(t);if(arguments.length<2){var r=this.node();return e.local?r.getAttributeNS(e.space,e.local):r.getAttribute(e)}return this.each((null==n?e.local?M:x:"function"==typeof n?e.local?k:E:e.local?N:A)(e,n))},style:function(t,n,e){return arguments.length>1?this.each((null==n?C:"function"==typeof n?j:P)(t,n,null==e?"":e)):q(this.node(),t)},property:function(t,n){return arguments.length>1?this.each((null==n?O:"function"==typeof n?T:L)(t,n)):this.node()[t]},classed:function(t,n){var e=B(t+"");if(arguments.length<2){for(var r=D(this.node()),i=-1,o=e.length;++i<o;)if(!r.contains(e[i]))return!1;return!0}return this.each(("function"==typeof n?I:n?X:z)(e,n))},text:function(t){return arguments.length?this.each(null==t?$:("function"==typeof t?Y:U)(t)):this.node().textContent},html:function(t){return arguments.length?this.each(null==t?F:("function"==typeof t?G:Z)(t)):this.node().innerHTML},raise:function(){return this.each(J)},lower:function(){return this.each(K)},append:function(t){var n="function"==typeof t?t:tt(t);return this.select((function(){return this.appendChild(n.apply(this,arguments))}))},insert:function(t,n){var e="function"==typeof t?t:tt(t),i=null==n?nt:"function"==typeof n?n:r(n);return this.select((function(){return this.insertBefore(e.apply(this,arguments),i.apply(this,arguments)||null)}))},remove:function(){return this.each(et)},clone:function(t){return this.select(t?it:rt)},datum:function(t){return arguments.length?this.property("__data__",t):this.node().__data__},on:function(t,n,e){var r,i,o=ot(t+""),u=o.length;if(!(arguments.length<2)){for(a=n?at:ut,r=0;r<u;++r)this.each(a(o[r],n,e));return this}var a=this.node().__on;if(a)for(var l,s=0,c=a.length;s<c;++s)for(r=0,l=a[s];r<u;++r)if((i=o[r]).type===l.type&&i.name===l.name)return l.value},dispatch:function(t,n){return this.each(("function"==typeof n?ct:st)(t,n))},[Symbol.iterator]:function*(){for(var t=this._groups,n=0,e=t.length;n<e;++n)for(var r,i=t[n],o=0,u=i.length;o<u;++o)(r=i[o])&&(yield r)}};var bt=Array.prototype.find;function xt(){return this.firstElementChild}var Mt=Array.prototype.filter;function At(){return Array.from(this.children)}function Nt(t){return new Array(t.length)}function Et(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=n}function kt(t){return function(){return t}}function St(t,n,e,r,i,o){for(var u,a=0,l=n.length,s=o.length;a<s;++a)(u=n[a])?(u.__data__=o[a],r[a]=u):e[a]=new Et(t,o[a]);for(;a<l;++a)(u=n[a])&&(i[a]=u)}function Ct(t,n,e,r,i,o,u){var a,l,s,c=new Map,f=n.length,h=o.length,p=new Array(f);for(a=0;a<f;++a)(l=n[a])&&(p[a]=s=u.call(l,l.__data__,a,n)+"",c.has(s)?i[a]=l:c.set(s,l));for(a=0;a<h;++a)s=u.call(t,o[a],a,o)+"",(l=c.get(s))?(r[a]=l,l.__data__=o[a],c.delete(s)):e[a]=new Et(t,o[a]);for(a=0;a<f;++a)(l=n[a])&&c.get(p[a])===l&&(i[a]=l)}function Pt(t){return t.__data__}function jt(t){return"object"==typeof t&&"length"in t?t:Array.from(t)}function qt(t,n){return t<n?-1:t>n?1:t>=n?0:NaN}Et.prototype={constructor:Et,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,n){return this._parent.insertBefore(t,n)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var Ot="http://www.w3.org/1999/xhtml";const Lt={svg:"http://www.w3.org/2000/svg",xhtml:Ot,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};function Tt(t){var n=t+="",e=n.indexOf(":");return e>=0&&"xmlns"!==(n=t.slice(0,e))&&(t=t.slice(e+1)),Lt.hasOwnProperty(n)?{space:Lt[n],local:t}:t}function Bt(t){return function(){this.removeAttribute(t)}}function Dt(t){return function(){this.removeAttributeNS(t.space,t.local)}}function Ht(t,n){return function(){this.setAttribute(t,n)}}function Rt(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}function Vt(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}}function Xt(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}}function zt(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function It(t){return function(){this.style.removeProperty(t)}}function $t(t,n,e){return function(){this.style.setProperty(t,n,e)}}function Ut(t,n,e){return function(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}}function Yt(t,n){return t.style.getPropertyValue(n)||zt(t).getComputedStyle(t,null).getPropertyValue(n)}function Ft(t){return function(){delete this[t]}}function Zt(t,n){return function(){this[t]=n}}function Gt(t,n){return function(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}}function Jt(t){return t.trim().split(/^|\s+/)}function Kt(t){return t.classList||new Qt(t)}function Qt(t){this._node=t,this._names=Jt(t.getAttribute("class")||"")}function Wt(t,n){for(var e=Kt(t),r=-1,i=n.length;++r<i;)e.add(n[r])}function tn(t,n){for(var e=Kt(t),r=-1,i=n.length;++r<i;)e.remove(n[r])}function nn(t){return function(){Wt(this,t)}}function en(t){return function(){tn(this,t)}}function rn(t,n){return function(){(n.apply(this,arguments)?Wt:tn)(this,t)}}function on(){this.textContent=""}function un(t){return function(){this.textContent=t}}function an(t){return function(){var n=t.apply(this,arguments);this.textContent=null==n?"":n}}function ln(){this.innerHTML=""}function sn(t){return function(){this.innerHTML=t}}function cn(t){return function(){var n=t.apply(this,arguments);this.innerHTML=null==n?"":n}}function fn(){this.nextSibling&&this.parentNode.appendChild(this)}function hn(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function pn(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===Ot&&n.documentElement.namespaceURI===Ot?n.createElement(t):n.createElementNS(e,t)}}function dn(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function gn(t){var n=Tt(t);return(n.local?dn:pn)(n)}function vn(){return null}function yn(){var t=this.parentNode;t&&t.removeChild(this)}function mn(){var t=this.cloneNode(!1),n=this.parentNode;return n?n.insertBefore(t,this.nextSibling):t}function _n(){var t=this.cloneNode(!0),n=this.parentNode;return n?n.insertBefore(t,this.nextSibling):t}function wn(t){return t.trim().split(/^|\s+/).map((function(t){var n="",e=t.indexOf(".");return e>=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}}))}function bn(t){return function(){var n=this.__on;if(n){for(var e,r=0,i=-1,o=n.length;r<o;++r)e=n[r],t.type&&e.type!==t.type||e.name!==t.name?n[++i]=e:this.removeEventListener(e.type,e.listener,e.options);++i?n.length=i:delete this.__on}}}function xn(t,n,e){return function(){var r,i=this.__on,o=function(t){return function(n){t.call(this,n,this.__data__)}}(n);if(i)for(var u=0,a=i.length;u<a;++u)if((r=i[u]).type===t.type&&r.name===t.name)return this.removeEventListener(r.type,r.listener,r.options),this.addEventListener(r.type,r.listener=o,r.options=e),void(r.value=n);this.addEventListener(t.type,o,e),r={type:t.type,name:t.name,value:n,listener:o,options:e},i?i.push(r):this.__on=[r]}}function Mn(t,n,e){var r=zt(t),i=r.CustomEvent;"function"==typeof i?i=new i(n,e):(i=r.document.createEvent("Event"),e?(i.initEvent(n,e.bubbles,e.cancelable),i.detail=e.detail):i.initEvent(n,!1,!1)),t.dispatchEvent(i)}function An(t,n){return function(){return Mn(this,t,n)}}function Nn(t,n){return function(){return Mn(this,t,n.apply(this,arguments))}}Qt.prototype={add:function(t){this._names.indexOf(t)<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var n=this._names.indexOf(t);n>=0&&(this._names.splice(n,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var En=[null];function kn(t,n){this._groups=t,this._parents=n}function Sn(){return new kn([[document.documentElement]],En)}kn.prototype=Sn.prototype={constructor:kn,select:function(t){"function"!=typeof t&&(t=gt(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u,a=n[i],l=a.length,s=r[i]=new Array(l),c=0;c<l;++c)(o=a[c])&&(u=t.call(o,o.__data__,c,a))&&("__data__"in o&&(u.__data__=o.__data__),s[c]=u);return new kn(r,this._parents)},selectAll:function(t){t="function"==typeof t?function(t){return function(){return vt(t.apply(this,arguments))}}(t):mt(t);for(var n=this._groups,e=n.length,r=[],i=[],o=0;o<e;++o)for(var u,a=n[o],l=a.length,s=0;s<l;++s)(u=a[s])&&(r.push(t.call(u,u.__data__,s,a)),i.push(u));return new kn(r,i)},selectChild:function(t){return this.select(null==t?xt:function(t){return function(){return bt.call(this.children,t)}}("function"==typeof t?t:wt(t)))},selectChildren:function(t){return this.selectAll(null==t?At:function(t){return function(){return Mt.call(this.children,t)}}("function"==typeof t?t:wt(t)))},filter:function(t){"function"!=typeof t&&(t=_t(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u=n[i],a=u.length,l=r[i]=[],s=0;s<a;++s)(o=u[s])&&t.call(o,o.__data__,s,u)&&l.push(o);return new kn(r,this._parents)},data:function(t,n){if(!arguments.length)return Array.from(this,Pt);var e=n?Ct:St,r=this._parents,i=this._groups;"function"!=typeof t&&(t=kt(t));for(var o=i.length,u=new Array(o),a=new Array(o),l=new Array(o),s=0;s<o;++s){var c=r[s],f=i[s],h=f.length,p=jt(t.call(c,c&&c.__data__,s,r)),d=p.length,g=a[s]=new Array(d),v=u[s]=new Array(d),y=l[s]=new Array(h);e(c,f,g,v,y,p,n);for(var m,_,w=0,b=0;w<d;++w)if(m=g[w]){for(w>=b&&(b=w+1);!(_=v[b])&&++b<d;);m._next=_||null}}return(u=new kn(u,r))._enter=a,u._exit=l,u},enter:function(){return new kn(this._enter||this._groups.map(Nt),this._parents)},exit:function(){return new kn(this._exit||this._groups.map(Nt),this._parents)},join:function(t,n,e){var r=this.enter(),i=this,o=this.exit();return"function"==typeof t?(r=t(r))&&(r=r.selection()):r=r.append(t+""),null!=n&&(i=n(i))&&(i=i.selection()),null==e?o.remove():e(o),r&&i?r.merge(i).order():i},merge:function(t){for(var n=t.selection?t.selection():t,e=this._groups,r=n._groups,i=e.length,o=r.length,u=Math.min(i,o),a=new Array(i),l=0;l<u;++l)for(var s,c=e[l],f=r[l],h=c.length,p=a[l]=new Array(h),d=0;d<h;++d)(s=c[d]||f[d])&&(p[d]=s);for(;l<i;++l)a[l]=e[l];return new kn(a,this._parents)},selection:function(){return this},order:function(){for(var t=this._groups,n=-1,e=t.length;++n<e;)for(var r,i=t[n],o=i.length-1,u=i[o];--o>=0;)(r=i[o])&&(u&&4^r.compareDocumentPosition(u)&&u.parentNode.insertBefore(r,u),u=r);return this},sort:function(t){function n(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e}t||(t=qt);for(var e=this._groups,r=e.length,i=new Array(r),o=0;o<r;++o){for(var u,a=e[o],l=a.length,s=i[o]=new Array(l),c=0;c<l;++c)(u=a[c])&&(s[c]=u);s.sort(n)}return new kn(i,this._parents).order()},call:function(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this},nodes:function(){return Array.from(this)},node:function(){for(var t=this._groups,n=0,e=t.length;n<e;++n)for(var r=t[n],i=0,o=r.length;i<o;++i){var u=r[i];if(u)return u}return null},size:function(){let t=0;for(const n of this)++t;return t},empty:function(){return!this.node()},each:function(t){for(var n=this._groups,e=0,r=n.length;e<r;++e)for(var i,o=n[e],u=0,a=o.length;u<a;++u)(i=o[u])&&t.call(i,i.__data__,u,o);return this},attr:function(t,n){var e=Tt(t);if(arguments.length<2){var r=this.node();return e.local?r.getAttributeNS(e.space,e.local):r.getAttribute(e)}return this.each((null==n?e.local?Dt:Bt:"function"==typeof n?e.local?Xt:Vt:e.local?Rt:Ht)(e,n))},style:function(t,n,e){return arguments.length>1?this.each((null==n?It:"function"==typeof n?Ut:$t)(t,n,null==e?"":e)):Yt(this.node(),t)},property:function(t,n){return arguments.length>1?this.each((null==n?Ft:"function"==typeof n?Gt:Zt)(t,n)):this.node()[t]},classed:function(t,n){var e=Jt(t+"");if(arguments.length<2){for(var r=Kt(this.node()),i=-1,o=e.length;++i<o;)if(!r.contains(e[i]))return!1;return!0}return this.each(("function"==typeof n?rn:n?nn:en)(e,n))},text:function(t){return arguments.length?this.each(null==t?on:("function"==typeof t?an:un)(t)):this.node().textContent},html:function(t){return arguments.length?this.each(null==t?ln:("function"==typeof t?cn:sn)(t)):this.node().innerHTML},raise:function(){return this.each(fn)},lower:function(){return this.each(hn)},append:function(t){var n="function"==typeof t?t:gn(t);return this.select((function(){return this.appendChild(n.apply(this,arguments))}))},insert:function(t,n){var e="function"==typeof t?t:gn(t),r=null==n?vn:"function"==typeof n?n:gt(n);return this.select((function(){return this.insertBefore(e.apply(this,arguments),r.apply(this,arguments)||null)}))},remove:function(){return this.each(yn)},clone:function(t){return this.select(t?_n:mn)},datum:function(t){return arguments.length?this.property("__data__",t):this.node().__data__},on:function(t,n,e){var r,i,o=wn(t+""),u=o.length;if(!(arguments.length<2)){for(a=n?xn:bn,r=0;r<u;++r)this.each(a(o[r],n,e));return this}var a=this.node().__on;if(a)for(var l,s=0,c=a.length;s<c;++s)for(r=0,l=a[s];r<u;++r)if((i=o[r]).type===l.type&&i.name===l.name)return l.value},dispatch:function(t,n){return this.each(("function"==typeof n?Nn:An)(t,n))},[Symbol.iterator]:function*(){for(var t=this._groups,n=0,e=t.length;n<e;++n)for(var r,i=t[n],o=0,u=i.length;o<u;++o)(r=i[o])&&(yield r)}};const Cn=Sn;function Pn(t){return"string"==typeof t?new kn([[document.querySelector(t)]],[document.documentElement]):new kn([[t]],En)}function jn(t,n){if((e=(t=n?t.toExponential(n-1):t.toExponential()).indexOf("e"))<0)return null;var e,r=t.slice(0,e);return[r.length>1?r[0]+r.slice(2):r,+t.slice(e+1)]}function qn(t){return(t=jn(Math.abs(t)))?t[1]:NaN}var On,Ln=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function Tn(t){if(!(n=Ln.exec(t)))throw new Error("invalid format: "+t);var n;return new Bn({fill:n[1],align:n[2],sign:n[3],symbol:n[4],zero:n[5],width:n[6],comma:n[7],precision:n[8]&&n[8].slice(1),trim:n[9],type:n[10]})}function Bn(t){this.fill=void 0===t.fill?" ":t.fill+"",this.align=void 0===t.align?">":t.align+"",this.sign=void 0===t.sign?"-":t.sign+"",this.symbol=void 0===t.symbol?"":t.symbol+"",this.zero=!!t.zero,this.width=void 0===t.width?void 0:+t.width,this.comma=!!t.comma,this.precision=void 0===t.precision?void 0:+t.precision,this.trim=!!t.trim,this.type=void 0===t.type?"":t.type+""}function Dn(t,n){var e=jn(t,n);if(!e)return t+"";var r=e[0],i=e[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}Tn.prototype=Bn.prototype,Bn.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,0|this.precision))+(this.trim?"~":"")+this.type};const Hn={"%":(t,n)=>(100*t).toFixed(n),b:t=>Math.round(t).toString(2),c:t=>t+"",d:function(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)},e:(t,n)=>t.toExponential(n),f:(t,n)=>t.toFixed(n),g:(t,n)=>t.toPrecision(n),o:t=>Math.round(t).toString(8),p:(t,n)=>Dn(100*t,n),r:Dn,s:function(t,n){var e=jn(t,n);if(!e)return t+"";var r=e[0],i=e[1],o=i-(On=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,u=r.length;return o===u?r:o>u?r+new Array(o-u+1).join("0"):o>0?r.slice(0,o)+"."+r.slice(o):"0."+new Array(1-o).join("0")+jn(t,Math.max(0,n+o-1))[0]},X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)};function Rn(t){return t}var Vn,Xn,zn,In=Array.prototype.map,$n=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function Un(t,n){return null==t||null==n?NaN:t<n?-1:t>n?1:t>=n?0:NaN}function Yn(t){t.x0=Math.round(t.x0),t.y0=Math.round(t.y0),t.x1=Math.round(t.x1),t.y1=Math.round(t.y1)}function Fn(t){var n=0,e=t.children,r=e&&e.length;if(r)for(;--r>=0;)n+=e[r].value;else n=1;t.value=n}function Zn(t,n){t instanceof Map?(t=[void 0,t],void 0===n&&(n=Jn)):void 0===n&&(n=Gn);for(var e,r,i,o,u,a=new Wn(t),l=[a];e=l.pop();)if((i=n(e.data))&&(u=(i=Array.from(i)).length))for(e.children=i,o=u-1;o>=0;--o)l.push(r=i[o]=new Wn(i[o])),r.parent=e,r.depth=e.depth+1;return a.eachBefore(Qn)}function Gn(t){return t.children}function Jn(t){return Array.isArray(t)?t[1]:null}function Kn(t){void 0!==t.data.value&&(t.value=t.data.value),t.data=t.data.data}function Qn(t){var n=0;do{t.height=n}while((t=t.parent)&&t.height<++n)}function Wn(t){this.data=t,this.depth=this.height=0,this.parent=null}Vn=function(t){var n,e,r=void 0===t.grouping||void 0===t.thousands?Rn:(n=In.call(t.grouping,Number),e=t.thousands+"",function(t,r){for(var i=t.length,o=[],u=0,a=n[0],l=0;i>0&&a>0&&(l+a+1>r&&(a=Math.max(1,r-l)),o.push(t.substring(i-=a,i+a)),!((l+=a+1)>r));)a=n[u=(u+1)%n.length];return o.reverse().join(e)}),i=void 0===t.currency?"":t.currency[0]+"",o=void 0===t.currency?"":t.currency[1]+"",u=void 0===t.decimal?".":t.decimal+"",a=void 0===t.numerals?Rn:function(t){return function(n){return n.replace(/[0-9]/g,(function(n){return t[+n]}))}}(In.call(t.numerals,String)),l=void 0===t.percent?"%":t.percent+"",s=void 0===t.minus?"−":t.minus+"",c=void 0===t.nan?"NaN":t.nan+"";function f(t){var n=(t=Tn(t)).fill,e=t.align,f=t.sign,h=t.symbol,p=t.zero,d=t.width,g=t.comma,v=t.precision,y=t.trim,m=t.type;"n"===m?(g=!0,m="g"):Hn[m]||(void 0===v&&(v=12),y=!0,m="g"),(p||"0"===n&&"="===e)&&(p=!0,n="0",e="=");var _="$"===h?i:"#"===h&&/[boxX]/.test(m)?"0"+m.toLowerCase():"",w="$"===h?o:/[%p]/.test(m)?l:"",b=Hn[m],x=/[defgprs%]/.test(m);function M(t){var i,o,l,h=_,M=w;if("c"===m)M=b(t)+M,t="";else{var A=(t=+t)<0||1/t<0;if(t=isNaN(t)?c:b(Math.abs(t),v),y&&(t=function(t){t:for(var n,e=t.length,r=1,i=-1;r<e;++r)switch(t[r]){case".":i=n=r;break;case"0":0===i&&(i=r),n=r;break;default:if(!+t[r])break t;i>0&&(i=0)}return i>0?t.slice(0,i)+t.slice(n+1):t}(t)),A&&0==+t&&"+"!==f&&(A=!1),h=(A?"("===f?f:s:"-"===f||"("===f?"":f)+h,M=("s"===m?$n[8+On/3]:"")+M+(A&&"("===f?")":""),x)for(i=-1,o=t.length;++i<o;)if(48>(l=t.charCodeAt(i))||l>57){M=(46===l?u+t.slice(i+1):t.slice(i))+M,t=t.slice(0,i);break}}g&&!p&&(t=r(t,1/0));var N=h.length+t.length+M.length,E=N<d?new Array(d-N+1).join(n):"";switch(g&&p&&(t=r(E+t,E.length?d-M.length:1/0),E=""),e){case"<":t=h+t+M+E;break;case"=":t=h+E+t+M;break;case"^":t=E.slice(0,N=E.length>>1)+h+t+M+E.slice(N);break;default:t=E+h+t+M}return a(t)}return v=void 0===v?6:/[gprs]/.test(m)?Math.max(1,Math.min(21,v)):Math.max(0,Math.min(20,v)),M.toString=function(){return t+""},M}return{format:f,formatPrefix:function(t,n){var e=f(((t=Tn(t)).type="f",t)),r=3*Math.max(-8,Math.min(8,Math.floor(qn(n)/3))),i=Math.pow(10,-r),o=$n[8+r/3];return function(t){return e(i*t)+o}}}}({thousands:",",grouping:[3],currency:["$",""]}),Xn=Vn.format,zn=Vn.formatPrefix,Wn.prototype=Zn.prototype={constructor:Wn,count:function(){return this.eachAfter(Fn)},each:function(t,n){let e=-1;for(const r of this)t.call(n,r,++e,this);return this},eachAfter:function(t,n){for(var e,r,i,o=this,u=[o],a=[],l=-1;o=u.pop();)if(a.push(o),e=o.children)for(r=0,i=e.length;r<i;++r)u.push(e[r]);for(;o=a.pop();)t.call(n,o,++l,this);return this},eachBefore:function(t,n){for(var e,r,i=this,o=[i],u=-1;i=o.pop();)if(t.call(n,i,++u,this),e=i.children)for(r=e.length-1;r>=0;--r)o.push(e[r]);return this},find:function(t,n){let e=-1;for(const r of this)if(t.call(n,r,++e,this))return r},sum:function(t){return this.eachAfter((function(n){for(var e=+t(n.data)||0,r=n.children,i=r&&r.length;--i>=0;)e+=r[i].value;n.value=e}))},sort:function(t){return this.eachBefore((function(n){n.children&&n.children.sort(t)}))},path:function(t){for(var n=this,e=function(t,n){if(t===n)return t;var e=t.ancestors(),r=n.ancestors(),i=null;for(t=e.pop(),n=r.pop();t===n;)i=t,t=e.pop(),n=r.pop();return i}(n,t),r=[n];n!==e;)n=n.parent,r.push(n);for(var i=r.length;t!==e;)r.splice(i,0,t),t=t.parent;return r},ancestors:function(){for(var t=this,n=[t];t=t.parent;)n.push(t);return n},descendants:function(){return Array.from(this)},leaves:function(){var t=[];return this.eachBefore((function(n){n.children||t.push(n)})),t},links:function(){var t=this,n=[];return t.each((function(e){e!==t&&n.push({source:e.parent,target:e})})),n},copy:function(){return Zn(this).eachBefore(Kn)},[Symbol.iterator]:function*(){var t,n,e,r,i=this,o=[i];do{for(t=o.reverse(),o=[];i=t.pop();)if(yield i,n=i.children)for(e=0,r=n.length;e<r;++e)o.push(n[e])}while(o.length)}};var te=Math.sqrt(50),ne=Math.sqrt(10),ee=Math.sqrt(2);function re(t,n,e){var r=(n-t)/Math.max(0,e),i=Math.floor(Math.log(r)/Math.LN10),o=r/Math.pow(10,i);return i>=0?(o>=te?10:o>=ne?5:o>=ee?2:1)*Math.pow(10,i):-Math.pow(10,-i)/(o>=te?10:o>=ne?5:o>=ee?2:1)}function ie(t){let n=t,e=t,r=t;function i(t,n,i=0,o=t.length){if(i<o){if(0!==e(n,n))return o;do{const e=i+o>>>1;r(t[e],n)<0?i=e+1:o=e}while(i<o)}return i}return 2!==t.length&&(n=(n,e)=>t(n)-e,e=Un,r=(n,e)=>Un(t(n),e)),{left:i,center:function(t,e,r=0,o=t.length){const u=i(t,e,r,o-1);return u>r&&n(t[u-1],e)>-n(t[u],e)?u-1:u},right:function(t,n,i=0,o=t.length){if(i<o){if(0!==e(n,n))return o;do{const e=i+o>>>1;r(t[e],n)<=0?i=e+1:o=e}while(i<o)}return i}}}const oe=ie(Un),ue=oe.right,ae=(oe.left,ie((function(t){return null===t?NaN:+t})).center,ue);function le(t,n,e){t.prototype=n.prototype=e,e.constructor=t}function se(t,n){var e=Object.create(t.prototype);for(var r in n)e[r]=n[r];return e}function ce(){}var fe=.7,he=1/fe,pe="\\s*([+-]?\\d+)\\s*",de="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",ge="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",ve=/^#([0-9a-f]{3,8})$/,ye=new RegExp("^rgb\\("+[pe,pe,pe]+"\\)$"),me=new RegExp("^rgb\\("+[ge,ge,ge]+"\\)$"),_e=new RegExp("^rgba\\("+[pe,pe,pe,de]+"\\)$"),we=new RegExp("^rgba\\("+[ge,ge,ge,de]+"\\)$"),be=new RegExp("^hsl\\("+[de,ge,ge]+"\\)$"),xe=new RegExp("^hsla\\("+[de,ge,ge,de]+"\\)$"),Me={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};function Ae(){return this.rgb().formatHex()}function Ne(){return this.rgb().formatRgb()}function Ee(t){var n,e;return t=(t+"").trim().toLowerCase(),(n=ve.exec(t))?(e=n[1].length,n=parseInt(n[1],16),6===e?ke(n):3===e?new je(n>>8&15|n>>4&240,n>>4&15|240&n,(15&n)<<4|15&n,1):8===e?Se(n>>24&255,n>>16&255,n>>8&255,(255&n)/255):4===e?Se(n>>12&15|n>>8&240,n>>8&15|n>>4&240,n>>4&15|240&n,((15&n)<<4|15&n)/255):null):(n=ye.exec(t))?new je(n[1],n[2],n[3],1):(n=me.exec(t))?new je(255*n[1]/100,255*n[2]/100,255*n[3]/100,1):(n=_e.exec(t))?Se(n[1],n[2],n[3],n[4]):(n=we.exec(t))?Se(255*n[1]/100,255*n[2]/100,255*n[3]/100,n[4]):(n=be.exec(t))?Te(n[1],n[2]/100,n[3]/100,1):(n=xe.exec(t))?Te(n[1],n[2]/100,n[3]/100,n[4]):Me.hasOwnProperty(t)?ke(Me[t]):"transparent"===t?new je(NaN,NaN,NaN,0):null}function ke(t){return new je(t>>16&255,t>>8&255,255&t,1)}function Se(t,n,e,r){return r<=0&&(t=n=e=NaN),new je(t,n,e,r)}function Ce(t){return t instanceof ce||(t=Ee(t)),t?new je((t=t.rgb()).r,t.g,t.b,t.opacity):new je}function Pe(t,n,e,r){return 1===arguments.length?Ce(t):new je(t,n,e,null==r?1:r)}function je(t,n,e,r){this.r=+t,this.g=+n,this.b=+e,this.opacity=+r}function qe(){return"#"+Le(this.r)+Le(this.g)+Le(this.b)}function Oe(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function Le(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function Te(t,n,e,r){return r<=0?t=n=e=NaN:e<=0||e>=1?t=n=NaN:n<=0&&(t=NaN),new De(t,n,e,r)}function Be(t){if(t instanceof De)return new De(t.h,t.s,t.l,t.opacity);if(t instanceof ce||(t=Ee(t)),!t)return new De;if(t instanceof De)return t;var n=(t=t.rgb()).r/255,e=t.g/255,r=t.b/255,i=Math.min(n,e,r),o=Math.max(n,e,r),u=NaN,a=o-i,l=(o+i)/2;return a?(u=n===o?(e-r)/a+6*(e<r):e===o?(r-n)/a+2:(n-e)/a+4,a/=l<.5?o+i:2-o-i,u*=60):a=l>0&&l<1?0:u,new De(u,a,l,t.opacity)}function De(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function He(t,n,e){return 255*(t<60?n+(e-n)*t/60:t<180?e:t<240?n+(e-n)*(240-t)/60:n)}function Re(t,n,e,r,i){var o=t*t,u=o*t;return((1-3*t+3*o-u)*n+(4-6*o+3*u)*e+(1+3*t+3*o-3*u)*r+u*i)/6}function Ve(t){return function(){return t}}function Xe(t,n){var e=n-t;return e?function(t,n){return function(e){return t+e*n}}(t,e):Ve(isNaN(t)?n:t)}le(ce,Ee,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:Ae,formatHex:Ae,formatHsl:function(){return Be(this).formatHsl()},formatRgb:Ne,toString:Ne}),le(je,Pe,se(ce,{brighter:function(t){return t=null==t?he:Math.pow(he,t),new je(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?fe:Math.pow(fe,t),new je(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:qe,formatHex:qe,formatRgb:Oe,toString:Oe})),le(De,(function(t,n,e,r){return 1===arguments.length?Be(t):new De(t,n,e,null==r?1:r)}),se(ce,{brighter:function(t){return t=null==t?he:Math.pow(he,t),new De(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?fe:Math.pow(fe,t),new De(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),n=isNaN(t)||isNaN(this.s)?0:this.s,e=this.l,r=e+(e<.5?e:1-e)*n,i=2*e-r;return new je(He(t>=240?t-240:t+120,i,r),He(t,i,r),He(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));const ze=function t(n){var e=function(t){return 1==(t=+t)?Xe:function(n,e){return e-n?function(t,n,e){return t=Math.pow(t,e),n=Math.pow(n,e)-t,e=1/e,function(r){return Math.pow(t+r*n,e)}}(n,e,t):Ve(isNaN(n)?e:n)}}(n);function r(t,n){var r=e((t=Pe(t)).r,(n=Pe(n)).r),i=e(t.g,n.g),o=e(t.b,n.b),u=Xe(t.opacity,n.opacity);return function(n){return t.r=r(n),t.g=i(n),t.b=o(n),t.opacity=u(n),t+""}}return r.gamma=t,r}(1);function Ie(t){return function(n){var e,r,i=n.length,o=new Array(i),u=new Array(i),a=new Array(i);for(e=0;e<i;++e)r=Pe(n[e]),o[e]=r.r||0,u[e]=r.g||0,a[e]=r.b||0;return o=t(o),u=t(u),a=t(a),r.opacity=1,function(t){return r.r=o(t),r.g=u(t),r.b=a(t),r+""}}}function $e(t,n){var e,r=n?n.length:0,i=t?Math.min(r,t.length):0,o=new Array(i),u=new Array(r);for(e=0;e<i;++e)o[e]=Qe(t[e],n[e]);for(;e<r;++e)u[e]=n[e];return function(t){for(e=0;e<i;++e)u[e]=o[e](t);return u}}function Ue(t,n){var e=new Date;return t=+t,n=+n,function(r){return e.setTime(t*(1-r)+n*r),e}}function Ye(t,n){return t=+t,n=+n,function(e){return t*(1-e)+n*e}}function Fe(t,n){var e,r={},i={};for(e in null!==t&&"object"==typeof t||(t={}),null!==n&&"object"==typeof n||(n={}),n)e in t?r[e]=Qe(t[e],n[e]):i[e]=n[e];return function(t){for(e in r)i[e]=r[e](t);return i}}Ie((function(t){var n=t.length-1;return function(e){var r=e<=0?e=0:e>=1?(e=1,n-1):Math.floor(e*n),i=t[r],o=t[r+1],u=r>0?t[r-1]:2*i-o,a=r<n-1?t[r+2]:2*o-i;return Re((e-r/n)*n,u,i,o,a)}})),Ie((function(t){var n=t.length;return function(e){var r=Math.floor(((e%=1)<0?++e:e)*n),i=t[(r+n-1)%n],o=t[r%n],u=t[(r+1)%n],a=t[(r+2)%n];return Re((e-r/n)*n,i,o,u,a)}}));var Ze=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Ge=new RegExp(Ze.source,"g");function Je(t,n){var e,r,i,o=Ze.lastIndex=Ge.lastIndex=0,u=-1,a=[],l=[];for(t+="",n+="";(e=Ze.exec(t))&&(r=Ge.exec(n));)(i=r.index)>o&&(i=n.slice(o,i),a[u]?a[u]+=i:a[++u]=i),(e=e[0])===(r=r[0])?a[u]?a[u]+=r:a[++u]=r:(a[++u]=null,l.push({i:u,x:Ye(e,r)})),o=Ge.lastIndex;return o<n.length&&(i=n.slice(o),a[u]?a[u]+=i:a[++u]=i),a.length<2?l[0]?function(t){return function(n){return t(n)+""}}(l[0].x):function(t){return function(){return t}}(n):(n=l.length,function(t){for(var e,r=0;r<n;++r)a[(e=l[r]).i]=e.x(t);return a.join("")})}function Ke(t,n){n||(n=[]);var e,r=t?Math.min(n.length,t.length):0,i=n.slice();return function(o){for(e=0;e<r;++e)i[e]=t[e]*(1-o)+n[e]*o;return i}}function Qe(t,n){var e,r,i=typeof n;return null==n||"boolean"===i?Ve(n):("number"===i?Ye:"string"===i?(e=Ee(n))?(n=e,ze):Je:n instanceof Ee?ze:n instanceof Date?Ue:(r=n,!ArrayBuffer.isView(r)||r instanceof DataView?Array.isArray(n)?$e:"function"!=typeof n.valueOf&&"function"!=typeof n.toString||isNaN(n)?Fe:Ye:Ke))(t,n)}function We(t,n){return t=+t,n=+n,function(e){return Math.round(t*(1-e)+n*e)}}function tr(t){return+t}var nr=[0,1];function er(t){return t}function rr(t,n){return(n-=t=+t)?function(e){return(e-t)/n}:(e=isNaN(n)?NaN:.5,function(){return e});var e}function ir(t,n,e){var r=t[0],i=t[1],o=n[0],u=n[1];return i<r?(r=rr(i,r),o=e(u,o)):(r=rr(r,i),o=e(o,u)),function(t){return o(r(t))}}function or(t,n,e){var r=Math.min(t.length,n.length)-1,i=new Array(r),o=new Array(r),u=-1;for(t[r]<t[0]&&(t=t.slice().reverse(),n=n.slice().reverse());++u<r;)i[u]=rr(t[u],t[u+1]),o[u]=e(n[u],n[u+1]);return function(n){var e=ae(t,n,1,r)-1;return o[e](i[e](n))}}function ur(t,n){return n.domain(t.domain()).range(t.range()).interpolate(t.interpolate()).clamp(t.clamp()).unknown(t.unknown())}function ar(){return function(){var t,n,e,r,i,o,u=nr,a=nr,l=Qe,s=er;function c(){var t,n,e,l=Math.min(u.length,a.length);return s!==er&&(t=u[0],n=u[l-1],t>n&&(e=t,t=n,n=e),s=function(e){return Math.max(t,Math.min(n,e))}),r=l>2?or:ir,i=o=null,f}function f(n){return null==n||isNaN(n=+n)?e:(i||(i=r(u.map(t),a,l)))(t(s(n)))}return f.invert=function(e){return s(n((o||(o=r(a,u.map(t),Ye)))(e)))},f.domain=function(t){return arguments.length?(u=Array.from(t,tr),c()):u.slice()},f.range=function(t){return arguments.length?(a=Array.from(t),c()):a.slice()},f.rangeRound=function(t){return a=Array.from(t),l=We,c()},f.clamp=function(t){return arguments.length?(s=!!t||er,c()):s!==er},f.interpolate=function(t){return arguments.length?(l=t,c()):l},f.unknown=function(t){return arguments.length?(e=t,f):e},function(e,r){return t=e,n=r,c()}}()(er,er)}function lr(t,n){switch(arguments.length){case 0:break;case 1:this.range(t);break;default:this.range(n).domain(t)}return this}function sr(t){var n=t.domain;return t.ticks=function(t){var e=n();return function(t,n,e){var r,i,o,u,a=-1;if(e=+e,(t=+t)==(n=+n)&&e>0)return[t];if((r=n<t)&&(i=t,t=n,n=i),0===(u=re(t,n,e))||!isFinite(u))return[];if(u>0){let e=Math.round(t/u),r=Math.round(n/u);for(e*u<t&&++e,r*u>n&&--r,o=new Array(i=r-e+1);++a<i;)o[a]=(e+a)*u}else{u=-u;let e=Math.round(t*u),r=Math.round(n*u);for(e/u<t&&++e,r/u>n&&--r,o=new Array(i=r-e+1);++a<i;)o[a]=(e+a)/u}return r&&o.reverse(),o}(e[0],e[e.length-1],null==t?10:t)},t.tickFormat=function(t,e){var r=n();return function(t,n,e,r){var i,o=function(t,n,e){var r=Math.abs(n-t)/Math.max(0,e),i=Math.pow(10,Math.floor(Math.log(r)/Math.LN10)),o=r/i;return o>=te?i*=10:o>=ne?i*=5:o>=ee&&(i*=2),n<t?-i:i}(t,n,e);switch((r=Tn(null==r?",f":r)).type){case"s":var u=Math.max(Math.abs(t),Math.abs(n));return null!=r.precision||isNaN(i=function(t,n){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(qn(n)/3)))-qn(Math.abs(t)))}(o,u))||(r.precision=i),zn(r,u);case"":case"e":case"g":case"p":case"r":null!=r.precision||isNaN(i=function(t,n){return t=Math.abs(t),n=Math.abs(n)-t,Math.max(0,qn(n)-qn(t))+1}(o,Math.max(Math.abs(t),Math.abs(n))))||(r.precision=i-("e"===r.type));break;case"f":case"%":null!=r.precision||isNaN(i=function(t){return Math.max(0,-qn(Math.abs(t)))}(o))||(r.precision=i-2*("%"===r.type))}return Xn(r)}(r[0],r[r.length-1],null==t?10:t,e)},t.nice=function(e){null==e&&(e=10);var r,i,o=n(),u=0,a=o.length-1,l=o[u],s=o[a],c=10;for(s<l&&(i=l,l=s,s=i,i=u,u=a,a=i);c-- >0;){if((i=re(l,s,e))===r)return o[u]=l,o[a]=s,n(o);if(i>0)l=Math.floor(l/i)*i,s=Math.ceil(s/i)*i;else{if(!(i<0))break;l=Math.ceil(l*i)/i,s=Math.floor(s*i)/i}r=i}return t},t}function cr(){var t=ar();return t.copy=function(){return ur(t,cr())},lr.apply(t,arguments),sr(t)}function fr(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}var hr={value:()=>{}};function pr(){for(var t,n=0,e=arguments.length,r={};n<e;++n){if(!(t=arguments[n]+"")||t in r||/[\s.]/.test(t))throw new Error("illegal type: "+t);r[t]=[]}return new dr(r)}function dr(t){this._=t}function gr(t,n){return t.trim().split(/^|\s+/).map((function(t){var e="",r=t.indexOf(".");if(r>=0&&(e=t.slice(r+1),t=t.slice(0,r)),t&&!n.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:e}}))}function vr(t,n){for(var e,r=0,i=t.length;r<i;++r)if((e=t[r]).name===n)return e.value}function yr(t,n,e){for(var r=0,i=t.length;r<i;++r)if(t[r].name===n){t[r]=hr,t=t.slice(0,r).concat(t.slice(r+1));break}return null!=e&&t.push({name:n,value:e}),t}dr.prototype=pr.prototype={constructor:dr,on:function(t,n){var e,r=this._,i=gr(t+"",r),o=-1,u=i.length;if(!(arguments.length<2)){if(null!=n&&"function"!=typeof n)throw new Error("invalid callback: "+n);for(;++o<u;)if(e=(t=i[o]).type)r[e]=yr(r[e],t.name,n);else if(null==n)for(e in r)r[e]=yr(r[e],t.name,null);return this}for(;++o<u;)if((e=(t=i[o]).type)&&(e=vr(r[e],t.name)))return e},copy:function(){var t={},n=this._;for(var e in n)t[e]=n[e].slice();return new dr(t)},call:function(t,n){if((e=arguments.length-2)>0)for(var e,r,i=new Array(e),o=0;o<e;++o)i[o]=arguments[o+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(o=0,e=(r=this._[t]).length;o<e;++o)r[o].value.apply(n,i)},apply:function(t,n,e){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var r=this._[t],i=0,o=r.length;i<o;++i)r[i].value.apply(n,e)}};const mr=pr;var _r,wr,br=0,xr=0,Mr=0,Ar=0,Nr=0,Er=0,kr="object"==typeof performance&&performance.now?performance:Date,Sr="object"==typeof window&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};function Cr(){return Nr||(Sr(Pr),Nr=kr.now()+Er)}function Pr(){Nr=0}function jr(){this._call=this._time=this._next=null}function qr(t,n,e){var r=new jr;return r.restart(t,n,e),r}function Or(){Nr=(Ar=kr.now())+Er,br=xr=0;try{!function(){Cr(),++br;for(var t,n=_r;n;)(t=Nr-n._time)>=0&&n._call.call(null,t),n=n._next;--br}()}finally{br=0,function(){for(var t,n,e=_r,r=1/0;e;)e._call?(r>e._time&&(r=e._time),t=e,e=e._next):(n=e._next,e._next=null,e=t?t._next=n:_r=n);wr=t,Tr(r)}(),Nr=0}}function Lr(){var t=kr.now(),n=t-Ar;n>1e3&&(Er-=n,Ar=t)}function Tr(t){br||(xr&&(xr=clearTimeout(xr)),t-Nr>24?(t<1/0&&(xr=setTimeout(Or,t-kr.now()-Er)),Mr&&(Mr=clearInterval(Mr))):(Mr||(Ar=kr.now(),Mr=setInterval(Lr,1e3)),br=1,Sr(Or)))}function Br(t,n,e){var r=new jr;return n=null==n?0:+n,r.restart((function(e){r.stop(),t(e+n)}),n,e),r}jr.prototype=qr.prototype={constructor:jr,restart:function(t,n,e){if("function"!=typeof t)throw new TypeError("callback is not a function");e=(null==e?Cr():+e)+(null==n?0:+n),this._next||wr===this||(wr?wr._next=this:_r=this,wr=this),this._call=t,this._time=e,Tr()},stop:function(){this._call&&(this._call=null,this._time=1/0,Tr())}};var Dr=mr("start","end","cancel","interrupt"),Hr=[];function Rr(t,n,e,r,i,o){var u=t.__transition;if(u){if(e in u)return}else t.__transition={};!function(t,n,e){var r,i=t.__transition;function o(l){var s,c,f,h;if(1!==e.state)return a();for(s in i)if((h=i[s]).name===e.name){if(3===h.state)return Br(o);4===h.state?(h.state=6,h.timer.stop(),h.on.call("interrupt",t,t.__data__,h.index,h.group),delete i[s]):+s<n&&(h.state=6,h.timer.stop(),h.on.call("cancel",t,t.__data__,h.index,h.group),delete i[s])}if(Br((function(){3===e.state&&(e.state=4,e.timer.restart(u,e.delay,e.time),u(l))})),e.state=2,e.on.call("start",t,t.__data__,e.index,e.group),2===e.state){for(e.state=3,r=new Array(f=e.tween.length),s=0,c=-1;s<f;++s)(h=e.tween[s].value.call(t,t.__data__,e.index,e.group))&&(r[++c]=h);r.length=c+1}}function u(n){for(var i=n<e.duration?e.ease.call(null,n/e.duration):(e.timer.restart(a),e.state=5,1),o=-1,u=r.length;++o<u;)r[o].call(t,i);5===e.state&&(e.on.call("end",t,t.__data__,e.index,e.group),a())}function a(){for(var r in e.state=6,e.timer.stop(),delete i[n],i)return;delete t.__transition}i[n]=e,e.timer=qr((function(t){e.state=1,e.timer.restart(o,e.delay,e.time),e.delay<=t&&o(t-e.delay)}),0,e.time)}(t,e,{name:n,index:r,group:i,on:Dr,tween:Hr,time:o.time,delay:o.delay,duration:o.duration,ease:o.ease,timer:null,state:0})}function Vr(t,n){var e=zr(t,n);if(e.state>0)throw new Error("too late; already scheduled");return e}function Xr(t,n){var e=zr(t,n);if(e.state>3)throw new Error("too late; already running");return e}function zr(t,n){var e=t.__transition;if(!e||!(e=e[n]))throw new Error("transition not found");return e}var Ir,$r,Ur,Yr,Fr=180/Math.PI,Zr={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1};function Gr(t,n,e,r,i,o){var u,a,l;return(u=Math.sqrt(t*t+n*n))&&(t/=u,n/=u),(l=t*e+n*r)&&(e-=t*l,r-=n*l),(a=Math.sqrt(e*e+r*r))&&(e/=a,r/=a,l/=a),t*r<n*e&&(t=-t,n=-n,l=-l,u=-u),{translateX:i,translateY:o,rotate:Math.atan2(n,t)*Fr,skewX:Math.atan(l)*Fr,scaleX:u,scaleY:a}}function Jr(t,n,e,r){function i(t){return t.length?t.pop()+" ":""}return function(o,u){var a=[],l=[];return o=t(o),u=t(u),function(t,r,i,o,u,a){if(t!==i||r!==o){var l=u.push("translate(",null,n,null,e);a.push({i:l-4,x:Ye(t,i)},{i:l-2,x:Ye(r,o)})}else(i||o)&&u.push("translate("+i+n+o+e)}(o.translateX,o.translateY,u.translateX,u.translateY,a,l),function(t,n,e,o){t!==n?(t-n>180?n+=360:n-t>180&&(t+=360),o.push({i:e.push(i(e)+"rotate(",null,r)-2,x:Ye(t,n)})):n&&e.push(i(e)+"rotate("+n+r)}(o.rotate,u.rotate,a,l),function(t,n,e,o){t!==n?o.push({i:e.push(i(e)+"skewX(",null,r)-2,x:Ye(t,n)}):n&&e.push(i(e)+"skewX("+n+r)}(o.skewX,u.skewX,a,l),function(t,n,e,r,o,u){if(t!==e||n!==r){var a=o.push(i(o)+"scale(",null,",",null,")");u.push({i:a-4,x:Ye(t,e)},{i:a-2,x:Ye(n,r)})}else 1===e&&1===r||o.push(i(o)+"scale("+e+","+r+")")}(o.scaleX,o.scaleY,u.scaleX,u.scaleY,a,l),o=u=null,function(t){for(var n,e=-1,r=l.length;++e<r;)a[(n=l[e]).i]=n.x(t);return a.join("")}}}var Kr=Jr((function(t){return"none"===t?Zr:(Ir||(Ir=document.createElement("DIV"),$r=document.documentElement,Ur=document.defaultView),Ir.style.transform=t,t=Ur.getComputedStyle($r.appendChild(Ir),null).getPropertyValue("transform"),$r.removeChild(Ir),Gr(+(t=t.slice(7,-1).split(","))[0],+t[1],+t[2],+t[3],+t[4],+t[5]))}),"px, ","px)","deg)"),Qr=Jr((function(t){return null==t?Zr:(Yr||(Yr=document.createElementNS("http://www.w3.org/2000/svg","g")),Yr.setAttribute("transform",t),(t=Yr.transform.baseVal.consolidate())?Gr((t=t.matrix).a,t.b,t.c,t.d,t.e,t.f):Zr)}),", ",")",")");function Wr(t,n){var e,r;return function(){var i=Xr(this,t),o=i.tween;if(o!==e)for(var u=0,a=(r=e=o).length;u<a;++u)if(r[u].name===n){(r=r.slice()).splice(u,1);break}i.tween=r}}function ti(t,n,e){var r,i;if("function"!=typeof e)throw new Error;return function(){var o=Xr(this,t),u=o.tween;if(u!==r){i=(r=u).slice();for(var a={name:n,value:e},l=0,s=i.length;l<s;++l)if(i[l].name===n){i[l]=a;break}l===s&&i.push(a)}o.tween=i}}function ni(t,n,e){var r=t._id;return t.each((function(){var t=Xr(this,r);(t.value||(t.value={}))[n]=e.apply(this,arguments)})),function(t){return zr(t,r).value[n]}}function ei(t,n){var e;return("number"==typeof n?Ye:n instanceof Ee?ze:(e=Ee(n))?(n=e,ze):Je)(t,n)}function ri(t){return function(){this.removeAttribute(t)}}function ii(t){return function(){this.removeAttributeNS(t.space,t.local)}}function oi(t,n,e){var r,i,o=e+"";return function(){var u=this.getAttribute(t);return u===o?null:u===r?i:i=n(r=u,e)}}function ui(t,n,e){var r,i,o=e+"";return function(){var u=this.getAttributeNS(t.space,t.local);return u===o?null:u===r?i:i=n(r=u,e)}}function ai(t,n,e){var r,i,o;return function(){var u,a,l=e(this);if(null!=l)return(u=this.getAttribute(t))===(a=l+"")?null:u===r&&a===i?o:(i=a,o=n(r=u,l));this.removeAttribute(t)}}function li(t,n,e){var r,i,o;return function(){var u,a,l=e(this);if(null!=l)return(u=this.getAttributeNS(t.space,t.local))===(a=l+"")?null:u===r&&a===i?o:(i=a,o=n(r=u,l));this.removeAttributeNS(t.space,t.local)}}function si(t,n){return function(e){this.setAttribute(t,n.call(this,e))}}function ci(t,n){return function(e){this.setAttributeNS(t.space,t.local,n.call(this,e))}}function fi(t,n){var e,r;function i(){var i=n.apply(this,arguments);return i!==r&&(e=(r=i)&&ci(t,i)),e}return i._value=n,i}function hi(t,n){var e,r;function i(){var i=n.apply(this,arguments);return i!==r&&(e=(r=i)&&si(t,i)),e}return i._value=n,i}function pi(t,n){return function(){Vr(this,t).delay=+n.apply(this,arguments)}}function di(t,n){return n=+n,function(){Vr(this,t).delay=n}}function gi(t,n){return function(){Xr(this,t).duration=+n.apply(this,arguments)}}function vi(t,n){return n=+n,function(){Xr(this,t).duration=n}}function yi(t,n){if("function"!=typeof n)throw new Error;return function(){Xr(this,t).ease=n}}function mi(t,n,e){var r,i,o=function(t){return(t+"").trim().split(/^|\s+/).every((function(t){var n=t.indexOf(".");return n>=0&&(t=t.slice(0,n)),!t||"start"===t}))}(n)?Vr:Xr;return function(){var u=o(this,t),a=u.on;a!==r&&(i=(r=a).copy()).on(n,e),u.on=i}}var _i=Cn.prototype.constructor;function wi(t){return function(){this.style.removeProperty(t)}}function bi(t,n,e){return function(r){this.style.setProperty(t,n.call(this,r),e)}}function xi(t,n,e){var r,i;function o(){var o=n.apply(this,arguments);return o!==i&&(r=(i=o)&&bi(t,o,e)),r}return o._value=n,o}function Mi(t){return function(n){this.textContent=t.call(this,n)}}function Ai(t){var n,e;function r(){var r=t.apply(this,arguments);return r!==e&&(n=(e=r)&&Mi(r)),n}return r._value=t,r}var Ni=0;function Ei(t,n,e,r){this._groups=t,this._parents=n,this._name=e,this._id=r}function ki(){return++Ni}var Si=Cn.prototype;Ei.prototype=function(t){return Cn().transition(t)}.prototype={constructor:Ei,select:function(t){var n=this._name,e=this._id;"function"!=typeof t&&(t=gt(t));for(var r=this._groups,i=r.length,o=new Array(i),u=0;u<i;++u)for(var a,l,s=r[u],c=s.length,f=o[u]=new Array(c),h=0;h<c;++h)(a=s[h])&&(l=t.call(a,a.__data__,h,s))&&("__data__"in a&&(l.__data__=a.__data__),f[h]=l,Rr(f[h],n,e,h,f,zr(a,e)));return new Ei(o,this._parents,n,e)},selectAll:function(t){var n=this._name,e=this._id;"function"!=typeof t&&(t=mt(t));for(var r=this._groups,i=r.length,o=[],u=[],a=0;a<i;++a)for(var l,s=r[a],c=s.length,f=0;f<c;++f)if(l=s[f]){for(var h,p=t.call(l,l.__data__,f,s),d=zr(l,e),g=0,v=p.length;g<v;++g)(h=p[g])&&Rr(h,n,e,g,p,d);o.push(p),u.push(l)}return new Ei(o,u,n,e)},selectChild:Si.selectChild,selectChildren:Si.selectChildren,filter:function(t){"function"!=typeof t&&(t=_t(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u=n[i],a=u.length,l=r[i]=[],s=0;s<a;++s)(o=u[s])&&t.call(o,o.__data__,s,u)&&l.push(o);return new Ei(r,this._parents,this._name,this._id)},merge:function(t){if(t._id!==this._id)throw new Error;for(var n=this._groups,e=t._groups,r=n.length,i=e.length,o=Math.min(r,i),u=new Array(r),a=0;a<o;++a)for(var l,s=n[a],c=e[a],f=s.length,h=u[a]=new Array(f),p=0;p<f;++p)(l=s[p]||c[p])&&(h[p]=l);for(;a<r;++a)u[a]=n[a];return new Ei(u,this._parents,this._name,this._id)},selection:function(){return new _i(this._groups,this._parents)},transition:function(){for(var t=this._name,n=this._id,e=ki(),r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],l=a.length,s=0;s<l;++s)if(u=a[s]){var c=zr(u,n);Rr(u,t,e,s,a,{time:c.time+c.delay+c.duration,delay:0,duration:c.duration,ease:c.ease})}return new Ei(r,this._parents,t,e)},call:Si.call,nodes:Si.nodes,node:Si.node,size:Si.size,empty:Si.empty,each:Si.each,on:function(t,n){var e=this._id;return arguments.length<2?zr(this.node(),e).on.on(t):this.each(mi(e,t,n))},attr:function(t,n){var e=Tt(t),r="transform"===e?Qr:ei;return this.attrTween(t,"function"==typeof n?(e.local?li:ai)(e,r,ni(this,"attr."+t,n)):null==n?(e.local?ii:ri)(e):(e.local?ui:oi)(e,r,n))},attrTween:function(t,n){var e="attr."+t;if(arguments.length<2)return(e=this.tween(e))&&e._value;if(null==n)return this.tween(e,null);if("function"!=typeof n)throw new Error;var r=Tt(t);return this.tween(e,(r.local?fi:hi)(r,n))},style:function(t,n,e){var r="transform"==(t+="")?Kr:ei;return null==n?this.styleTween(t,function(t,n){var e,r,i;return function(){var o=Yt(this,t),u=(this.style.removeProperty(t),Yt(this,t));return o===u?null:o===e&&u===r?i:i=n(e=o,r=u)}}(t,r)).on("end.style."+t,wi(t)):"function"==typeof n?this.styleTween(t,function(t,n,e){var r,i,o;return function(){var u=Yt(this,t),a=e(this),l=a+"";return null==a&&(this.style.removeProperty(t),l=a=Yt(this,t)),u===l?null:u===r&&l===i?o:(i=l,o=n(r=u,a))}}(t,r,ni(this,"style."+t,n))).each(function(t,n){var e,r,i,o,u="style."+n,a="end."+u;return function(){var l=Xr(this,t),s=l.on,c=null==l.value[u]?o||(o=wi(n)):void 0;s===e&&i===c||(r=(e=s).copy()).on(a,i=c),l.on=r}}(this._id,t)):this.styleTween(t,function(t,n,e){var r,i,o=e+"";return function(){var u=Yt(this,t);return u===o?null:u===r?i:i=n(r=u,e)}}(t,r,n),e).on("end.style."+t,null)},styleTween:function(t,n,e){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==n)return this.tween(r,null);if("function"!=typeof n)throw new Error;return this.tween(r,xi(t,n,null==e?"":e))},text:function(t){return this.tween("text","function"==typeof t?function(t){return function(){var n=t(this);this.textContent=null==n?"":n}}(ni(this,"text",t)):function(t){return function(){this.textContent=t}}(null==t?"":t+""))},textTween:function(t){var n="text";if(arguments.length<1)return(n=this.tween(n))&&n._value;if(null==t)return this.tween(n,null);if("function"!=typeof t)throw new Error;return this.tween(n,Ai(t))},remove:function(){return this.on("end.remove",function(t){return function(){var n=this.parentNode;for(var e in this.__transition)if(+e!==t)return;n&&n.removeChild(this)}}(this._id))},tween:function(t,n){var e=this._id;if(t+="",arguments.length<2){for(var r,i=zr(this.node(),e).tween,o=0,u=i.length;o<u;++o)if((r=i[o]).name===t)return r.value;return null}return this.each((null==n?Wr:ti)(e,t,n))},delay:function(t){var n=this._id;return arguments.length?this.each(("function"==typeof t?pi:di)(n,t)):zr(this.node(),n).delay},duration:function(t){var n=this._id;return arguments.length?this.each(("function"==typeof t?gi:vi)(n,t)):zr(this.node(),n).duration},ease:function(t){var n=this._id;return arguments.length?this.each(yi(n,t)):zr(this.node(),n).ease},easeVarying:function(t){if("function"!=typeof t)throw new Error;return this.each(function(t,n){return function(){var e=n.apply(this,arguments);if("function"!=typeof e)throw new Error;Xr(this,t).ease=e}}(this._id,t))},end:function(){var t,n,e=this,r=e._id,i=e.size();return new Promise((function(o,u){var a={value:u},l={value:function(){0==--i&&o()}};e.each((function(){var e=Xr(this,r),i=e.on;i!==t&&((n=(t=i).copy())._.cancel.push(a),n._.interrupt.push(a),n._.end.push(l)),e.on=n})),0===i&&o()}))},[Symbol.iterator]:Si[Symbol.iterator]};var Ci={time:null,delay:0,duration:250,ease:fr};function Pi(t,n){for(var e;!(e=t.__transition)||!(e=e[n]);)if(!(t=t.parentNode))throw new Error(` + "`" + `transition ${n} not found` + "`" + `);return e}function ji(){let t=960,n=null,e=18,r=null,i=null,o="",u=750,a=fr,l=!1,s=!1,c=null,f=null,h=0,p=null,d=null,g=!1,v=!1,y=!1,m=null,_=!1,w=null,b=function(t){return t.data.n||t.data.name},x=function(t){return"v"in t?t.v:t.value},M=function(t){return t.c||t.children},A=function(t){return t.data.l||t.data.libtype},N=function(t){return"d"in t.data?t.data.d:t.data.delta},E=function(t,n,e){d=()=>{p&&(p.textContent="search: "+n+" of "+e+" total samples ( "+Xn(".3f")(n/e*100,3)+"%)")},d()};const k=E;let S=(t,n,e=!1)=>{if(!n)return!1;let r=b(t);e&&(n=n.toLowerCase(),r=r.toLowerCase());const i=new RegExp(n);return void 0!==r&&r&&r.match(i)};const C=S;let P=function(t){p&&(t?p.textContent=t:"function"==typeof d?d():p.textContent="")};const j=P;let q=function(t){return b(t)+" ("+Xn(".3f")(100*(t.x1-t.x0),3)+"%, "+x(t)+" samples)"},O=function(t){return t.highlight?"#E600E6":function(t,n){let e=w||"warm";w||void 0===n||""===n||(e="red",void 0!==t&&t&&t.match(/::/)&&(e="yellow"),"kernel"===n?e="orange":"jit"===n?e="green":"inlined"===n&&(e="aqua"));const r=function(t){let n=0;if(t){const e=t.split("` + "`" + `");e.length>1&&(t=e[e.length-1]),n=function(t){let n=0,e=0,r=1;if(t){for(let i=0;i<t.length&&!(i>6);i++)n+=r*(t.charCodeAt(i)%10),e+=9*r,r*=.7;e>0&&(n/=e)}return n}(t=t.split("(")[0])}return n}(t);return function(t,n){let e,r,i;return"red"===t?(e=200+Math.round(55*n),r=50+Math.round(80*n),i=r):"orange"===t?(e=190+Math.round(65*n),r=90+Math.round(65*n),i=0):"yellow"===t?(e=175+Math.round(55*n),r=e,i=50+Math.round(20*n)):"green"===t?(e=50+Math.round(60*n),r=200+Math.round(55*n),i=e):"pastelgreen"===t?(e=163+Math.round(75*n),r=195+Math.round(49*n),i=72+Math.round(149*n)):"blue"===t?(e=91+Math.round(126*n),r=156+Math.round(76*n),i=221+Math.round(26*n)):"aqua"===t?(e=50+Math.round(60*n),r=165+Math.round(55*n),i=r):"cold"===t?(e=0+Math.round(55*(1-n)),r=0+Math.round(230*(1-n)),i=200+Math.round(55*n)):(e=200+Math.round(55*n),r=0+Math.round(230*(1-n)),i=0+Math.round(55*(1-n))),"rgb("+e+","+r+","+i+")"}(e,r)}(b(t),A(t))};const L=O;function T(t){t.data.fade=!1,t.data.hide=!1,t.children&&t.children.forEach(T)}function B(t){t.parent&&(t.parent.data.fade=!0,B(t.parent))}function D(t){if(i&&i.hide(),function(t){let n,e,r,i=t,o=i.parent;for(;o;){for(n=o.children,e=n.length;e--;)r=n[e],r!==i&&(r.data.hide=!0);i=o,o=i.parent}}(t),T(t),B(t),z(),y){const n=Pn(this).select("svg")._groups[0][0].parentNode.offsetTop,r=(window.innerHeight-n)/e,i=(t.height-r+10)*e;window.scrollTo({top:n+i,left:0,behavior:"smooth"})}"function"==typeof c&&c(t)}function H(t,n){if(t.id===n)return t;{const e=M(t);if(e)for(let t=0;t<e.length;t++){const r=H(e[t],n);if(r)return r}}}function R(t){t.highlight=!1,M(t)&&M(t).forEach((function(t){R(t)}))}function V(t,n){return"function"==typeof l?l(t,n):l?Un(b(t),b(n)):void 0}const X=function(){var t=1,n=1,e=0,r=!1;function i(i){var o=i.height+1;return i.x0=i.y0=e,i.x1=t,i.y1=n/o,i.eachBefore(function(t,n){return function(r){r.children&&function(t,n,e,r,i){for(var o,u=t.children,a=-1,l=u.length,s=t.value&&(r-n)/t.value;++a<l;)(o=u[a]).y0=e,o.y1=i,o.x0=n,o.x1=n+=o.value*s}(r,r.x0,t*(r.depth+1)/n,r.x1,t*(r.depth+2)/n);var i=r.x0,o=r.y0,u=r.x1-e,a=r.y1-e;u<i&&(i=u=(i+u)/2),a<o&&(o=a=(o+a)/2),r.x0=i,r.y0=o,r.x1=u,r.y1=a}}(n,o)),r&&i.eachBefore(Yn),i}return i.round=function(t){return arguments.length?(r=!!t,i):r},i.size=function(e){return arguments.length?(t=+e[0],n=+e[1],i):[t,n]},i.padding=function(t){return arguments.length?(e=+t,i):e},i}();function z(){r.each((function(r){const o=cr().range([0,t]),c=cr().range([0,e]);$(r),l&&r.sort(V),X(r);const p=t/(r.x1-r.x0);function d(t){return(t.x1-t.x0)*p}const g=function(n){let e=n.descendants();if(h>0){const r=t/(n.x1-n.x0);e=e.filter((function(t){return(t.x1-t.x0)*r>h}))}return e}(r),y=Pn(this).select("svg");y.attr("width",t);let _=y.selectAll("g").data(g,(function(t){return t.id}));if(!n||v){const t=Math.max.apply(null,g.map((function(t){return t.depth})));n=(t+3)*e,n<m&&(n=m),y.attr("height",n)}_.transition().duration(u).ease(a).attr("transform",(function(t){return"translate("+o(t.x0)+","+(s?c(t.depth):n-c(t.depth)-e)+")"})),_.select("rect").transition().duration(u).ease(a).attr("width",d);const w=_.enter().append("svg:g").attr("transform",(function(t){return"translate("+o(t.x0)+","+(s?c(t.depth):n-c(t.depth)-e)+")"}));w.append("svg:rect").transition().delay(u/2).attr("width",d),i||w.append("svg:title"),w.append("foreignObject").append("xhtml:div"),_=y.selectAll("g").data(g,(function(t){return t.id})),_.attr("width",d).attr("height",(function(t){return e})).attr("name",(function(t){return b(t)})).attr("class",(function(t){return t.data.fade?"frame fade":"frame"})),_.select("rect").attr("height",(function(t){return e})).attr("fill",(function(t){return O(t)})),i||_.select("title").text(q),_.select("foreignObject").attr("width",d).attr("height",(function(t){return e})).select("div").attr("class","d3-flame-graph-label").style("display",(function(t){return d(t)<35?"none":"block"})).transition().delay(u).text(b),_.on("click",((t,n)=>{D(n)})),_.exit().remove(),_.on("mouseover",(function(t,n){i&&i.show(n,this),P(q(n)),"function"==typeof f&&f(n)})).on("mouseout",(function(){i&&i.hide(),P(null)}))}))}function I(t,n){n.forEach((function(n){const e=t.find((function(t){return t.name===n.name}));e?(e.value+=n.value,n.children&&(e.children||(e.children=[]),I(e.children,n.children))):t.push(n)}))}function $(t){let n,e,r,i,o,u,a,l;const s=[],c=[],f=[],h=!g;let p=t.data;for(p.hide?(t.value=0,e=t.children,e&&f.push(e)):(t.value=p.fade?0:x(p),s.push(t));n=s.pop();)if(e=n.children,e&&(o=e.length)){for(i=0;o--;)a=e[o],p=a.data,p.hide?(a.value=0,r=a.children,r&&f.push(r)):(p.fade?a.value=0:(l=x(p),a.value=l,i+=l),s.push(a));h&&n.value&&(n.value-=i),c.push(e)}for(o=c.length;o--;){for(e=c[o],i=0,u=e.length;u--;)i+=e[u].value;e[0].parent.value+=i}for(;f.length;)for(e=f.pop(),u=e.length;u--;)a=e[u],a.value=0,r=a.children,r&&f.push(r)}function U(){r.datum((t=>{if("Node"!==t.constructor.name){const n=Zn(t,M);return function(t){let n=0;!function(t,n){n(t);let e=t.children;if(e){const t=[e];let r,i,o;for(;t.length;)for(e=t.pop(),r=e.length;r--;)i=e[r],n(i),o=i.children,o&&t.push(o)}}(t,(function(t){t.id=n++}))}(n),$(n),n.originalValue=n.value,_&&n.eachAfter((t=>{let n=N(t);const e=t.children;let r=e&&e.length;for(;--r>=0;)n+=e[r].delta;t.delta=n})),n}}))}function Y(e){if(!arguments.length)return Y;r=e,U(),r.each((function(e){if(0===Pn(this).select("svg").size()){const e=Pn(this).append("svg:svg").attr("width",t).attr("class","partition d3-flame-graph");n&&(n<m&&(n=m),e.attr("height",n)),e.append("svg:text").attr("class","title").attr("text-anchor","middle").attr("y","25").attr("x",t/2).attr("fill","#808080").text(o),i&&e.call(i)}})),z()}return Y.height=function(t){return arguments.length?(n=t,Y):n},Y.minHeight=function(t){return arguments.length?(m=t,Y):m},Y.width=function(n){return arguments.length?(t=n,Y):t},Y.cellHeight=function(t){return arguments.length?(e=t,Y):e},Y.tooltip=function(t){return arguments.length?("function"==typeof t&&(i=t),Y):i},Y.title=function(t){return arguments.length?(o=t,Y):o},Y.transitionDuration=function(t){return arguments.length?(u=t,Y):u},Y.transitionEase=function(t){return arguments.length?(a=t,Y):a},Y.sort=function(t){return arguments.length?(l=t,Y):l},Y.inverted=function(t){return arguments.length?(s=t,Y):s},Y.computeDelta=function(t){return arguments.length?(_=t,Y):_},Y.setLabelHandler=function(t){return arguments.length?(q=t,Y):q},Y.label=Y.setLabelHandler,Y.search=function(t){const n=[];let e=0,i=0;r.each((function(r){const o=function(t,n){const e=[];let r=0;return function t(i,o){let u=!1;S(i,n)?(i.highlight=!0,u=!0,o||(r+=x(i)),e.push(i)):i.highlight=!1,M(i)&&M(i).forEach((function(n){t(n,o||u)}))}(t,!1),[e,r]}(r,t);n.push(...o[0]),e+=o[1],i+=r.originalValue})),E(n,e,i),z()},Y.findById=function(t){if(null==t)return null;let n=null;return r.each((function(e){null===n&&(n=H(e,t))})),n},Y.clear=function(){P(null),r.each((function(t){R(t),z()}))},Y.zoomTo=function(t){D(t)},Y.resetZoom=function(){r.each((function(t){D(t)}))},Y.onClick=function(t){return arguments.length?(c=t,Y):c},Y.onHover=function(t){return arguments.length?(f=t,Y):f},Y.merge=function(t){return r?(this.resetZoom(),d=null,P(null),r.datum((n=>(I([n.data],[t]),n.data))),U(),z(),Y):Y},Y.update=function(t){return r?(t&&(r.datum(t),U()),z(),Y):Y},Y.destroy=function(){return r?(i&&(i.hide(),"function"==typeof i.destroy&&i.destroy()),r.selectAll("svg").remove(),Y):Y},Y.setColorMapper=function(t){return arguments.length?(O=n=>{const e=L(n);return t(n,e)},Y):(O=L,Y)},Y.color=Y.setColorMapper,Y.setColorHue=function(t){return arguments.length?(w=t,Y):(w=null,Y)},Y.minFrameSize=function(t){return arguments.length?(h=t,Y):h},Y.setDetailsElement=function(t){return arguments.length?(p=t,Y):p},Y.details=Y.setDetailsElement,Y.selfValue=function(t){return arguments.length?(g=t,Y):g},Y.resetHeightOnZoom=function(t){return arguments.length?(v=t,Y):v},Y.scrollOnZoom=function(t){return arguments.length?(y=t,Y):y},Y.getName=function(t){return arguments.length?(b=t,Y):b},Y.getValue=function(t){return arguments.length?(x=t,Y):x},Y.getChildren=function(t){return arguments.length?(M=t,Y):M},Y.getLibtype=function(t){return arguments.length?(A=t,Y):A},Y.getDelta=function(t){return arguments.length?(N=t,Y):N},Y.setSearchHandler=function(t){return arguments.length?(E=t,Y):(E=k,Y)},Y.setDetailsHandler=function(t){return arguments.length?(P=t,Y):(P=j,Y)},Y.setSearchMatch=function(t){return arguments.length?(S=t,Y):(S=C,Y)},Y}return Cn.prototype.interrupt=function(t){return this.each((function(){!function(t,n){var e,r,i,o=t.__transition,u=!0;if(o){for(i in n=null==n?null:n+"",o)(e=o[i]).name===n?(r=e.state>2&&e.state<5,e.state=6,e.timer.stop(),e.on.call(r?"interrupt":"cancel",t,t.__data__,e.index,e.group),delete o[i]):u=!1;u&&delete t.__transition}}(this,t)}))},Cn.prototype.transition=function(t){var n,e;t instanceof Ei?(n=t._id,t=t._name):(n=ki(),(e=Ci).time=Cr(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],l=a.length,s=0;s<l;++s)(u=a[s])&&Rr(u,t,n,s,a,e||Pi(u,n));return new Ei(r,this._parents,t,n)},n})()})); ` // CSSSource returns the d3-flamegraph.css file @@ -951,59 +53,13 @@ const CSSSource = ` } .d3-flame-graph-tip { - line-height: 1; - font-family: Verdana; - font-size: 12px; - padding: 12px; - background: rgba(0, 0, 0, 0.8); - color: #fff; - border-radius: 2px; - pointer-events: none; -} - -/* Creates a small triangle extender for the tooltip */ -.d3-flame-graph-tip:after { - box-sizing: border-box; - display: inline; - font-size: 10px; - width: 100%; - line-height: 1; - color: rgba(0, 0, 0, 0.8); - position: absolute; - pointer-events: none; -} - -/* Northward tooltips */ -.d3-flame-graph-tip.n:after { - content: "\25BC"; - margin: -1px 0 0 0; - top: 100%; - left: 0; - text-align: center; -} - -/* Eastward tooltips */ -.d3-flame-graph-tip.e:after { - content: "\25C0"; - margin: -4px 0 0 0; - top: 50%; - left: -8px; -} - -/* Southward tooltips */ -.d3-flame-graph-tip.s:after { - content: "\25B2"; - margin: 0 0 1px 0; - top: -8px; - left: 0; - text-align: center; -} - -/* Westward tooltips */ -.d3-flame-graph-tip.w:after { - content: "\25B6"; - margin: -4px 0 0 -1px; - top: 50%; - left: 100%; + background-color: black; + border: none; + border-radius: 3px; + padding: 5px 10px 5px 10px; + min-width: 250px; + text-align: left; + color: white; + z-index: 10; } ` diff --git a/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/index.js b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/index.js new file mode 100644 index 0000000000000000000000000000000000000000..d6e0b5b6edce94cfa1cbdd981553bc8d340a4a3b --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/index.js @@ -0,0 +1,13 @@ +// This file exports a stripped-down API surface of d3 and d3-flame-graph, +// using only the functions used by pprof. + +export { + select, +} from "d3-selection"; + +export { + default as flamegraph +// If we export from "d3-flame-graph" that exports the "dist" version which +// includes another copy of d3-selection. To avoid including d3-selection +// twice in the output, instead import the "src" version. +} from "d3-flame-graph/src/flamegraph"; diff --git a/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/package-lock.json b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..d5caba62f85b5aac639597909be1322165984e6b --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/package-lock.json @@ -0,0 +1,1106 @@ +{ + "name": "d3-pprof", + "version": "2.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@discoveryjs/json-ext": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz", + "integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==", + "dev": true + }, + "@types/eslint": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.2.1.tgz", + "integrity": "sha512-UP9rzNn/XyGwb5RQ2fok+DzcIRIYwc16qTXse5+Smsy8MOIccCChT15KAwnsgQx4PzJkaMq4myFyZ4CL5TjhIQ==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha512-SCFeogqiptms4Fg29WpOTk5nHIzfpKCemSN63ksBQYKTcXoJEmJagV+DhVmbapZzY4/5YaOV1nZwrsU79fFm1g==", + "dev": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.50", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", + "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, + "@types/node": { + "version": "16.11.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz", + "integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webpack-cli/configtest": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.0.tgz", + "integrity": "sha512-ttOkEkoalEHa7RaFYpM0ErK1xc4twg3Am9hfHhL7MVqlHebnkYd2wuI/ZqTDj0cVzZho6PdinY0phFZV3O0Mzg==", + "dev": true + }, + "@webpack-cli/info": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.0.tgz", + "integrity": "sha512-F6b+Man0rwE4n0409FyAJHStYA5OIZERxmnUfLVwv0mc0V1wLad3V7jqRlMkgKBeAq07jUvglacNaa6g9lOpuw==", + "dev": true, + "requires": { + "envinfo": "^7.7.3" + } + }, + "@webpack-cli/serve": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.0.tgz", + "integrity": "sha512-ZkVeqEmRpBV2GHvjjUZqEai2PpUbuq8Bqd//vEYsp63J8WyexI8ppCqVS3Zs0QADf6aWuPdU+0XsPI647PVlQA==", + "dev": true + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "acorn": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", + "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", + "dev": true + }, + "acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, + "browserslist": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.18.1.tgz", + "integrity": "sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", + "escalade": "^3.1.1", + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001284", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001284.tgz", + "integrity": "sha512-t28SKa7g6kiIQi6NHeOcKrOrGMzCRrXvlasPwWC26TH2QNdglgzQIRUuJ0cR3NeQPH+5jpuveeeSFDLm2zbkEw==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "d3-color": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", + "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==" + }, + "d3-flame-graph": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/d3-flame-graph/-/d3-flame-graph-4.1.3.tgz", + "integrity": "sha512-NijuhJZhaTMwobVgwGQ67x9PovqMMHXBbs0FMHEGJvsWZGuL4M7OsB03v8mHdyVyHhnQYGsYnb5w021e9+R+RQ==", + "requires": { + "d3-array": "^3.1.1", + "d3-dispatch": "^3.0.1", + "d3-ease": "^3.0.1", + "d3-format": "^3.0.1", + "d3-hierarchy": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-selection": "^3.0.0", + "d3-transition": "^3.0.1" + }, + "dependencies": { + "d3-array": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.1.1.tgz", + "integrity": "sha512-33qQ+ZoZlli19IFiQx4QEpf2CBEayMRzhlisJHSCsSUbDXv6ZishqS1x7uFVClKG4Wr7rZVHvaAttoLow6GqdQ==", + "requires": { + "internmap": "1 - 2" + } + }, + "d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==" + }, + "d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==" + }, + "d3-format": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.0.1.tgz", + "integrity": "sha512-hdL7+HBIohpgfolhBxr1KX47VMD6+vVD/oEFrxk5yhmzV2prk99EkFKYpXuhVkFpTgHdJ6/4bYcjdLPPXV4tIA==" + }, + "d3-hierarchy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.0.1.tgz", + "integrity": "sha512-RlLTaofEoOrMK1JoXYIGhKTkJFI/6rFrYPgxy6QlZo2BcVc4HGTqEU0rPpzuMq5T/5XcMtAzv1XiLA3zRTfygw==" + }, + "d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "requires": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + } + }, + "d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==" + }, + "d3-time": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.0.0.tgz", + "integrity": "sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==", + "requires": { + "d3-array": "2 - 3" + } + }, + "d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "requires": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + } + } + } + }, + "d3-interpolate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", + "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", + "requires": { + "d3-color": "1" + } + }, + "d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==" + }, + "d3-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", + "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==" + }, + "d3-time-format": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", + "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", + "requires": { + "d3-time": "1" + } + }, + "d3-timer": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", + "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==" + }, + "electron-to-chromium": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.11.tgz", + "integrity": "sha512-2OhsaYgsWGhWjx2et8kaUcdktPbBGjKM2X0BReUCKcSCPttEY+hz2zie820JLbttU8jwL92+JJysWwkut3wZgA==", + "dev": true + }, + "enhanced-resolve": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", + "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true + }, + "es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "import-local": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz", + "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==" + }, + "interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true + }, + "is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-worker": { + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.2.tgz", + "integrity": "sha512-0QMy/zPovLfUPyHuOuuU4E+kGACXXE84nRnq6lBVI9GJg5DCBiA97SATi+ZP8CpiJwEQy1oCPjRBf8AnLjN+Ag==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "dev": true + }, + "mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dev": true, + "requires": { + "mime-db": "1.51.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node-releases": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", + "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "requires": { + "resolve": "^1.9.0" + } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + }, + "terser": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz", + "integrity": "sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.2.5.tgz", + "integrity": "sha512-3luOVHku5l0QBeYS8r4CdHYWEGMmIj3H1U64jgkdZzECcSOJAyJ9TjuqcQZvw1Y+4AOBN9SeYJPJmFn2cM4/2g==", + "dev": true, + "requires": { + "jest-worker": "^27.0.6", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.2" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "watchpack": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.0.tgz", + "integrity": "sha512-MnN0Q1OsvB/GGHETrFeZPQaOelWh/7O+EiFlj8sM9GPjtQkis7k01aAxrg/18kTfoIVcLL+haEVFlXDaSRwKRw==", + "dev": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "webpack": { + "version": "5.64.4", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.64.4.tgz", + "integrity": "sha512-LWhqfKjCLoYJLKJY8wk2C3h77i8VyHowG3qYNZiIqD6D0ZS40439S/KVuc/PY48jp2yQmy0mhMknq8cys4jFMw==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.0", + "@types/estree": "^0.0.50", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.8.3", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.4", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.0", + "webpack-sources": "^3.2.2" + } + }, + "webpack-cli": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.1.tgz", + "integrity": "sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ==", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.1.0", + "@webpack-cli/info": "^1.4.0", + "@webpack-cli/serve": "^1.6.0", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "execa": "^5.0.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "webpack-merge": "^5.7.3" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true + } + } + }, + "webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.2.tgz", + "integrity": "sha512-cp5qdmHnu5T8wRg2G3vZZHoJPN14aqQ89SyQ11NpGH5zEMDCclt49rzo+MaRazk7/UeILhAI+/sEtcM+7Fr0nw==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + } + } +} diff --git a/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/package.json b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/package.json new file mode 100644 index 0000000000000000000000000000000000000000..1df57f03996aa0451f898cc649e05f6548c4fc37 --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/package.json @@ -0,0 +1,17 @@ +{ + "name": "d3-pprof", + "version": "2.0.0", + "description": "A d3.js bundle for pprof.", + "scripts": { + "prepare": "webpack --mode production" + }, + "license": "Apache-2.0", + "dependencies": { + "d3-flame-graph": "^4.1.3", + "d3-selection": "^3.0.0" + }, + "devDependencies": { + "webpack": "^5.64.4", + "webpack-cli": "^4.9.1" + } +} diff --git a/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/update.sh b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/update.sh new file mode 100644 index 0000000000000000000000000000000000000000..7076c66673c2aeb35fc2182abc0d0fcc83f878be --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/update.sh @@ -0,0 +1,62 @@ +# Copyright 2021 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/usr/bin/env bash + +set -eu +set -o pipefail + +D3FLAMEGRAPH_CSS="d3-flamegraph.css" + +cd $(dirname $0) + +generate_d3_flame_graph_go() { + npm install + # https://stackoverflow.com/a/21199041/171898 + local d3_js=$(cat d3.js | sed 's/`/`+"`"+`/g') + local d3_css=$(cat "node_modules/d3-flame-graph/dist/${D3FLAMEGRAPH_CSS}") + + cat <<-EOF > d3_flame_graph.go +// D3.js is a JavaScript library for manipulating documents based on data. +// https://github.com/d3/d3 +// See D3_LICENSE file for license details + +// d3-flame-graph is a D3.js plugin that produces flame graphs from hierarchical data. +// https://github.com/spiermar/d3-flame-graph +// See D3_FLAME_GRAPH_LICENSE file for license details + +package d3flamegraph + +// JSSource returns the d3 and d3-flame-graph JavaScript bundle +const JSSource = \` + +$d3_js +\` + +// CSSSource returns the $D3FLAMEGRAPH_CSS file +const CSSSource = \` +$d3_css +\` + +EOF + gofmt -w d3_flame_graph.go +} + +get_licenses() { + cp node_modules/d3-selection/LICENSE D3_LICENSE + cp node_modules/d3-flame-graph/LICENSE D3_FLAME_GRAPH_LICENSE +} + +get_licenses +generate_d3_flame_graph_go diff --git a/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/webpack.config.js b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/webpack.config.js new file mode 100644 index 0000000000000000000000000000000000000000..71239d9e9684a84970d19719bc91f2f8c2aebb8c --- /dev/null +++ b/src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/webpack.config.js @@ -0,0 +1,13 @@ +// Minimal webpack config to package a minified JS bundle (including +// dependencies) for execution in a <script> tag in the browser. +module.exports = { + entry: './index.js', + output: { + path: __dirname, // Directory containing this webpack.config.js file. + filename: 'd3.js', + // Arbitrary; many module formats could be used, just keeping Universal + // Module Definition as it's the same as what we used in a previous + // version. + libraryTarget: 'umd', + }, +}; diff --git a/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go b/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go index 7b9178f1bb09e0b2ad985a40a4758585f716506a..20d8a9982e27d8142d2e604e0f9a5bfecf3155ea 100644 --- a/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go +++ b/src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go @@ -1451,6 +1451,34 @@ func (ft *FixedType) goString(indent int, field string) string { ft.Base.goString(indent+2, "Base: ")) } +// BinaryFP is a binary floating-point type. +type BinaryFP struct { + Bits int +} + +func (bfp *BinaryFP) print(ps *printState) { + fmt.Fprintf(&ps.buf, "_Float%d", bfp.Bits) +} + +func (bfp *BinaryFP) Traverse(fn func(AST) bool) { + fn(bfp) +} + +func (bfp *BinaryFP) Copy(fn func(AST) AST, skip func(AST) bool) AST { + if skip(bfp) { + return nil + } + return fn(bfp) +} + +func (bfp *BinaryFP) GoString() string { + return bfp.goString(0, "") +} + +func (bfp *BinaryFP) goString(indent int, field string) string { + return fmt.Sprintf("%*s%sBinaryFP: %d", indent, "", field, bfp.Bits) +} + // VectorType is a vector type. type VectorType struct { Dimension AST @@ -2492,6 +2520,7 @@ func (u *Unary) print(ps *printState) { } if !u.Suffix { + isDelete := op != nil && (op.Name == "delete " || op.Name == "delete[] ") if op != nil && op.Name == "::" { // Don't use parentheses after ::. ps.print(expr) @@ -2506,11 +2535,11 @@ func (u *Unary) print(ps *printState) { ps.print(expr) ps.writeByte(')') } else if ps.llvmStyle { - if op == nil || op.Name != `operator"" ` { + if op == nil || (op.Name != `operator"" ` && !isDelete) { ps.writeByte('(') } ps.print(expr) - if op == nil || op.Name != `operator"" ` { + if op == nil || (op.Name != `operator"" ` && !isDelete) { ps.writeByte(')') } } else { @@ -2653,6 +2682,9 @@ func (b *Binary) print(ps *printState) { case ".", "->": skipBothParens = true addSpaces = false + case "->*": + skipParens = true + addSpaces = false } } @@ -3115,8 +3147,20 @@ type New struct { } func (n *New) print(ps *printState) { - // Op doesn't really matter for printing--we always print "new". - ps.writeString("new ") + if !ps.llvmStyle { + // Op doesn't really matter for printing--we always print "new". + ps.writeString("new ") + } else { + op, _ := n.Op.(*Operator) + if op != nil { + ps.writeString(op.Name) + if n.Place == nil { + ps.writeByte(' ') + } + } else { + ps.print(n.Op) + } + } if n.Place != nil { parenthesize(ps, n.Place) ps.writeByte(' ') diff --git a/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go b/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go index 9eec0aa3c83921792418b06ed6513d95ee2e6502..66ac7dde62a553f70519d8cd3141784f5bb1c9d6 100644 --- a/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go +++ b/src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go @@ -73,19 +73,26 @@ func ToString(name string, options ...Option) (string, error) { // Check for an old-style Rust mangled name. // It starts with _ZN and ends with "17h" followed by 16 hex digits - // followed by "E". - if strings.HasPrefix(name, "_ZN") && strings.HasSuffix(name, "E") && len(name) > 23 && name[len(name)-20:len(name)-17] == "17h" { - noRust := false - for _, o := range options { - if o == NoRust { - noRust = true - break + // followed by "E" followed by an optional suffix starting with "." + // (which we ignore). + if strings.HasPrefix(name, "_ZN") { + rname := name + if pos := strings.LastIndex(rname, "E."); pos > 0 { + rname = rname[:pos+1] + } + if strings.HasSuffix(rname, "E") && len(rname) > 23 && rname[len(rname)-20:len(rname)-17] == "17h" { + noRust := false + for _, o := range options { + if o == NoRust { + noRust = true + break + } } - } - if !noRust { - s, ok := oldRustToString(name, options) - if ok { - return s, nil + if !noRust { + s, ok := oldRustToString(rname, options) + if ok { + return s, nil + } } } } @@ -332,9 +339,11 @@ const ( notForLocalName ) -// encoding ::= <(function) name> <bare-function-type> -// <(data) name> -// <special-name> +// encoding parses: +// +// encoding ::= <(function) name> <bare-function-type> +// <(data) name> +// <special-name> func (st *state) encoding(params bool, local forLocalNameType) AST { if len(st.str) < 1 { st.fail("expected encoding") @@ -499,7 +508,9 @@ func isCDtorConversion(a AST) bool { } } -// <tagged-name> ::= <name> B <source-name> +// taggedName parses: +// +// <tagged-name> ::= <name> B <source-name> func (st *state) taggedName(a AST) AST { for len(st.str) > 0 && st.str[0] == 'B' { st.advance(1) @@ -509,16 +520,18 @@ func (st *state) taggedName(a AST) AST { return a } -// <name> ::= <nested-name> -// ::= <unscoped-name> -// ::= <unscoped-template-name> <template-args> -// ::= <local-name> +// name parses: // -// <unscoped-name> ::= <unqualified-name> -// ::= St <unqualified-name> +// <name> ::= <nested-name> +// ::= <unscoped-name> +// ::= <unscoped-template-name> <template-args> +// ::= <local-name> // -// <unscoped-template-name> ::= <unscoped-name> -// ::= <substitution> +// <unscoped-name> ::= <unqualified-name> +// ::= St <unqualified-name> +// +// <unscoped-template-name> ::= <unscoped-name> +// ::= <substitution> func (st *state) name() AST { if len(st.str) < 1 { st.fail("expected name") @@ -593,8 +606,10 @@ func (st *state) name() AST { } } -// <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E -// ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E +// nestedName parses: +// +// <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E +// ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E func (st *state) nestedName() AST { st.checkChar('N') q := st.cvQualifiers() @@ -610,19 +625,21 @@ func (st *state) nestedName() AST { return a } -// <prefix> ::= <prefix> <unqualified-name> -// ::= <template-prefix> <template-args> -// ::= <template-param> -// ::= <decltype> -// ::= -// ::= <substitution> +// prefix parses: +// +// <prefix> ::= <prefix> <unqualified-name> +// ::= <template-prefix> <template-args> +// ::= <template-param> +// ::= <decltype> +// ::= +// ::= <substitution> // -// <template-prefix> ::= <prefix> <(template) unqualified-name> -// ::= <template-param> -// ::= <substitution> +// <template-prefix> ::= <prefix> <(template) unqualified-name> +// ::= <template-param> +// ::= <substitution> // -// <decltype> ::= Dt <expression> E -// ::= DT <expression> E +// <decltype> ::= Dt <expression> E +// ::= DT <expression> E func (st *state) prefix() AST { var a AST @@ -777,12 +794,14 @@ func (st *state) prefix() AST { } } -// <unqualified-name> ::= <operator-name> -// ::= <ctor-dtor-name> -// ::= <source-name> -// ::= <local-source-name> +// unqualifiedName parses: // -// <local-source-name> ::= L <source-name> <discriminator> +// <unqualified-name> ::= <operator-name> +// ::= <ctor-dtor-name> +// ::= <source-name> +// ::= <local-source-name> +// +// <local-source-name> ::= L <source-name> <discriminator> func (st *state) unqualifiedName() (r AST, isCast bool) { if len(st.str) < 1 { st.fail("expected unqualified name") @@ -852,8 +871,10 @@ func (st *state) unqualifiedName() (r AST, isCast bool) { return a, isCast } -// <source-name> ::= <(positive length) number> <identifier> -// identifier ::= <(unqualified source code identifier)> +// sourceName parses: +// +// <source-name> ::= <(positive length) number> <identifier> +// identifier ::= <(unqualified source code identifier)> func (st *state) sourceName() AST { val := st.number() if val <= 0 { @@ -880,7 +901,9 @@ func (st *state) sourceName() AST { return n } -// number ::= [n] <(non-negative decimal integer)> +// number parses: +// +// number ::= [n] <(non-negative decimal integer)> func (st *state) number() int { neg := false if len(st.str) > 0 && st.str[0] == 'n' { @@ -906,7 +929,9 @@ func (st *state) number() int { return val } -// <seq-id> ::= <0-9A-Z>+ +// seqID parses: +// +// <seq-id> ::= <0-9A-Z>+ // // We expect this to be followed by an underscore. func (st *state) seqID(eofOK bool) int { @@ -1030,9 +1055,11 @@ var operators = map[string]operator{ "tw": {"throw ", 1}, } -// operator_name ::= many different two character encodings. -// ::= cv <type> -// ::= v <digit> <source-name> +// operatorName parses: +// +// operator_name ::= many different two character encodings. +// ::= cv <type> +// ::= v <digit> <source-name> // // We need to know whether we are in an expression because it affects // how we handle template parameters in the type of a cast operator. @@ -1068,9 +1095,11 @@ func (st *state) operatorName(inExpression bool) (AST, int) { } } -// <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>] -// ::= Z <(function) encoding> E s [<discriminator>] -// ::= Z <(function) encoding> E d [<parameter> number>] _ <entity name> +// localName parses: +// +// <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>] +// ::= Z <(function) encoding> E s [<discriminator>] +// ::= Z <(function) encoding> E d [<parameter> number>] _ <entity name> func (st *state) localName() AST { st.checkChar('Z') fn := st.encoding(true, forLocalName) @@ -1139,23 +1168,25 @@ func (st *state) javaResource() AST { return &Special{Prefix: "java resource ", Val: &Name{Name: final}} } -// <special-name> ::= TV <type> -// ::= TT <type> -// ::= TI <type> -// ::= TS <type> -// ::= TA <template-arg> -// ::= GV <(object) name> -// ::= T <call-offset> <(base) encoding> -// ::= Tc <call-offset> <call-offset> <(base) encoding> -// Also g++ extensions: -// ::= TC <type> <(offset) number> _ <(base) type> -// ::= TF <type> -// ::= TJ <type> -// ::= GR <name> -// ::= GA <encoding> -// ::= Gr <resource name> -// ::= GTt <encoding> -// ::= GTn <encoding> +// specialName parses: +// +// <special-name> ::= TV <type> +// ::= TT <type> +// ::= TI <type> +// ::= TS <type> +// ::= TA <template-arg> +// ::= GV <(object) name> +// ::= T <call-offset> <(base) encoding> +// ::= Tc <call-offset> <call-offset> <(base) encoding> +// g++ extensions: +// ::= TC <type> <(offset) number> _ <(base) type> +// ::= TF <type> +// ::= TJ <type> +// ::= GR <name> +// ::= GA <encoding> +// ::= Gr <resource name> +// ::= GTt <encoding> +// ::= GTn <encoding> func (st *state) specialName() AST { if st.str[0] == 'T' { st.advance(1) @@ -1268,12 +1299,14 @@ func (st *state) specialName() AST { } } -// <call-offset> ::= h <nv-offset> _ -// ::= v <v-offset> _ +// callOffset parses: +// +// <call-offset> ::= h <nv-offset> _ +// ::= v <v-offset> _ // -// <nv-offset> ::= <(offset) number> +// <nv-offset> ::= <(offset) number> // -// <v-offset> ::= <(offset) number> _ <(virtual offset) number> +// <v-offset> ::= <(offset) number> _ <(virtual offset) number> // // The c parameter, if not 0, is a character we just read which is the // start of the <call-offset>. @@ -1331,24 +1364,26 @@ var builtinTypes = map[byte]string{ 'z': "...", } -// <type> ::= <builtin-type> -// ::= <function-type> -// ::= <class-enum-type> -// ::= <array-type> -// ::= <pointer-to-member-type> -// ::= <template-param> -// ::= <template-template-param> <template-args> -// ::= <substitution> -// ::= <CV-qualifiers> <type> -// ::= P <type> -// ::= R <type> -// ::= O <type> (C++0x) -// ::= C <type> -// ::= G <type> -// ::= U <source-name> <type> +// demangleType parses: +// +// <type> ::= <builtin-type> +// ::= <function-type> +// ::= <class-enum-type> +// ::= <array-type> +// ::= <pointer-to-member-type> +// ::= <template-param> +// ::= <template-template-param> <template-args> +// ::= <substitution> +// ::= <CV-qualifiers> <type> +// ::= P <type> +// ::= R <type> +// ::= O <type> (C++0x) +// ::= C <type> +// ::= G <type> +// ::= U <source-name> <type> // -// <builtin-type> ::= various one letter codes -// ::= u <source-name> +// <builtin-type> ::= various one letter codes +// ::= u <source-name> func (st *state) demangleType(isCast bool) AST { if len(st.str) == 0 { st.fail("expected type") @@ -1544,24 +1579,32 @@ func (st *state) demangleType(isCast bool) AST { case 'F': accum := false + bits := 0 if len(st.str) > 0 && isDigit(st.str[0]) { accum = true - // We don't care about the bits. - _ = st.number() + bits = st.number() } - base := st.demangleType(isCast) - if len(st.str) > 0 && isDigit(st.str[0]) { - // We don't care about the bits. - st.number() - } - sat := false - if len(st.str) > 0 { - if st.str[0] == 's' { - sat = true + if len(st.str) > 0 && st.str[0] == '_' { + if bits == 0 { + st.fail("expected non-zero number of bits") } st.advance(1) + ret = &BinaryFP{Bits: bits} + } else { + base := st.demangleType(isCast) + if len(st.str) > 0 && isDigit(st.str[0]) { + // We don't care about the bits. + st.number() + } + sat := false + if len(st.str) > 0 { + if st.str[0] == 's' { + sat = true + } + st.advance(1) + } + ret = &FixedType{Base: base, Accum: accum, Sat: sat} } - ret = &FixedType{Base: base, Accum: accum, Sat: sat} case 'v': ret = st.vectorType(isCast) @@ -1615,25 +1658,25 @@ func (st *state) demangleType(isCast bool) AST { // is if there is another set of template-args immediately after this // set. That would look like this: // -// <nested-name> -// -> <template-prefix> <template-args> -// -> <prefix> <template-unqualified-name> <template-args> -// -> <unqualified-name> <template-unqualified-name> <template-args> -// -> <source-name> <template-unqualified-name> <template-args> -// -> <source-name> <operator-name> <template-args> -// -> <source-name> cv <type> <template-args> -// -> <source-name> cv <template-template-param> <template-args> <template-args> +// <nested-name> +// -> <template-prefix> <template-args> +// -> <prefix> <template-unqualified-name> <template-args> +// -> <unqualified-name> <template-unqualified-name> <template-args> +// -> <source-name> <template-unqualified-name> <template-args> +// -> <source-name> <operator-name> <template-args> +// -> <source-name> cv <type> <template-args> +// -> <source-name> cv <template-template-param> <template-args> <template-args> // // Otherwise, we have this derivation: // -// <nested-name> -// -> <template-prefix> <template-args> -// -> <prefix> <template-unqualified-name> <template-args> -// -> <unqualified-name> <template-unqualified-name> <template-args> -// -> <source-name> <template-unqualified-name> <template-args> -// -> <source-name> <operator-name> <template-args> -// -> <source-name> cv <type> <template-args> -// -> <source-name> cv <template-param> <template-args> +// <nested-name> +// -> <template-prefix> <template-args> +// -> <prefix> <template-unqualified-name> <template-args> +// -> <unqualified-name> <template-unqualified-name> <template-args> +// -> <source-name> <template-unqualified-name> <template-args> +// -> <source-name> <operator-name> <template-args> +// -> <source-name> cv <type> <template-args> +// -> <source-name> cv <template-param> <template-args> // // in which the template-args are actually part of the prefix. For // the special case where this arises, demangleType is called with @@ -1710,7 +1753,9 @@ var qualifiers = map[byte]string{ 'K': "const", } -// <CV-qualifiers> ::= [r] [V] [K] +// cvQualifiers parses: +// +// <CV-qualifiers> ::= [r] [V] [K] func (st *state) cvQualifiers() AST { var q []AST qualLoop: @@ -1758,8 +1803,10 @@ qualLoop: return &Qualifiers{Qualifiers: q} } -// <ref-qualifier> ::= R -// ::= O +// refQualifier parses: +// +// <ref-qualifier> ::= R +// ::= O func (st *state) refQualifier() string { if len(st.str) > 0 { switch st.str[0] { @@ -1774,7 +1821,9 @@ func (st *state) refQualifier() string { return "" } -// <type>+ +// parmlist parses: +// +// <type>+ func (st *state) parmlist() []AST { var ret []AST for { @@ -1809,7 +1858,9 @@ func (st *state) parmlist() []AST { return ret } -// <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E +// functionType parses: +// +// <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E func (st *state) functionType() AST { st.checkChar('F') if len(st.str) > 0 && st.str[0] == 'Y' { @@ -1828,7 +1879,9 @@ func (st *state) functionType() AST { return ret } -// <bare-function-type> ::= [J]<type>+ +// bareFunctionType parses: +// +// <bare-function-type> ::= [J]<type>+ func (st *state) bareFunctionType(hasReturnType bool) AST { if len(st.str) > 0 && st.str[0] == 'J' { hasReturnType = true @@ -1846,8 +1899,10 @@ func (st *state) bareFunctionType(hasReturnType bool) AST { } } -// <array-type> ::= A <(positive dimension) number> _ <(element) type> -// ::= A [<(dimension) expression>] _ <(element) type> +// arrayType parses: +// +// <array-type> ::= A <(positive dimension) number> _ <(element) type> +// ::= A [<(dimension) expression>] _ <(element) type> func (st *state) arrayType(isCast bool) AST { st.checkChar('A') @@ -1887,8 +1942,10 @@ func (st *state) arrayType(isCast bool) AST { return arr } -// <vector-type> ::= Dv <number> _ <type> -// ::= Dv _ <expression> _ <type> +// vectorType parses: +// +// <vector-type> ::= Dv <number> _ <type> +// ::= Dv _ <expression> _ <type> func (st *state) vectorType(isCast bool) AST { if len(st.str) == 0 { st.fail("expected vector dimension") @@ -1913,7 +1970,9 @@ func (st *state) vectorType(isCast bool) AST { return &VectorType{Dimension: dim, Base: t} } -// <pointer-to-member-type> ::= M <(class) type> <(member) type> +// pointerToMemberType parses: +// +// <pointer-to-member-type> ::= M <(class) type> <(member) type> func (st *state) pointerToMemberType(isCast bool) AST { st.checkChar('M') cl := st.demangleType(false) @@ -1939,7 +1998,9 @@ func (st *state) pointerToMemberType(isCast bool) AST { return &PtrMem{Class: cl, Member: mem} } -// <non-negative number> _ */ +// compactNumber parses: +// +// <non-negative number> _ func (st *state) compactNumber() int { if len(st.str) == 0 { st.fail("missing index") @@ -1958,10 +2019,12 @@ func (st *state) compactNumber() int { return n + 1 } -// <template-param> ::= T_ -// ::= T <(parameter-2 non-negative) number> _ -// ::= TL <level-1> __ -// ::= TL <level-1> _ <parameter-2 non-negative number> _ +// templateParam parses: +// +// <template-param> ::= T_ +// ::= T <(parameter-2 non-negative) number> _ +// ::= TL <level-1> __ +// ::= TL <level-1> _ <parameter-2 non-negative number> _ // // When a template parameter is a substitution candidate, any // reference to that substitution refers to the template parameter @@ -2058,7 +2121,9 @@ func (st *state) clearTemplateArgs(args []AST) { } } -// <template-args> ::= I <template-arg>+ E +// templateArgs parses: +// +// <template-args> ::= I <template-arg>+ E func (st *state) templateArgs() []AST { if len(st.str) == 0 || (st.str[0] != 'I' && st.str[0] != 'J') { panic("internal error") @@ -2074,9 +2139,11 @@ func (st *state) templateArgs() []AST { return ret } -// <template-arg> ::= <type> -// ::= X <expression> E -// ::= <expr-primary> +// templateArg parses: +// +// <template-arg> ::= <type> +// ::= X <expression> E +// ::= <expr-primary> func (st *state) templateArg() AST { if len(st.str) == 0 { st.fail("missing template argument") @@ -2122,66 +2189,67 @@ func (st *state) exprList(stop byte) AST { return &ExprList{Exprs: exprs} } -// <expression> ::= <(unary) operator-name> <expression> -// ::= <(binary) operator-name> <expression> <expression> -// ::= <(trinary) operator-name> <expression> <expression> <expression> -// ::= pp_ <expression> -// ::= mm_ <expression> -// ::= cl <expression>+ E -// ::= cl <expression>+ E -// ::= cv <type> <expression> -// ::= cv <type> _ <expression>* E -// ::= tl <type> <braced-expression>* E -// ::= il <braced-expression>* E -// ::= [gs] nw <expression>* _ <type> E -// ::= [gs] nw <expression>* _ <type> <initializer> -// ::= [gs] na <expression>* _ <type> E -// ::= [gs] na <expression>* _ <type> <initializer> -// ::= [gs] dl <expression> -// ::= [gs] da <expression> -// ::= dc <type> <expression> -// ::= sc <type> <expression> -// ::= cc <type> <expression> -// ::= mc <parameter type> <expr> [<offset number>] E -// ::= rc <type> <expression> -// ::= ti <type> -// ::= te <expression> -// ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E -// ::= st <type> -// ::= sz <expression> -// ::= at <type> -// ::= az <expression> -// ::= nx <expression> -// ::= <template-param> -// ::= <function-param> -// ::= dt <expression> <unresolved-name> -// ::= pt <expression> <unresolved-name> -// ::= ds <expression> <expression> -// ::= sZ <template-param> -// ::= sZ <function-param> -// ::= sP <template-arg>* E -// ::= sp <expression> -// ::= fl <binary operator-name> <expression> -// ::= fr <binary operator-name> <expression> -// ::= fL <binary operator-name> <expression> <expression> -// ::= fR <binary operator-name> <expression> <expression> -// ::= tw <expression> -// ::= tr -// ::= u <source-name> <template-arg>* E -// ::= <unresolved-name> -// ::= <expr-primary> +// expression parses: // -// <function-param> ::= fp <CV-qualifiers> _ -// ::= fp <CV-qualifiers> <number> -// ::= fL <number> p <CV-qualifiers> _ -// ::= fL <number> p <CV-qualifiers> <number> -// ::= fpT +// <expression> ::= <(unary) operator-name> <expression> +// ::= <(binary) operator-name> <expression> <expression> +// ::= <(trinary) operator-name> <expression> <expression> <expression> +// ::= pp_ <expression> +// ::= mm_ <expression> +// ::= cl <expression>+ E +// ::= cl <expression>+ E +// ::= cv <type> <expression> +// ::= cv <type> _ <expression>* E +// ::= tl <type> <braced-expression>* E +// ::= il <braced-expression>* E +// ::= [gs] nw <expression>* _ <type> E +// ::= [gs] nw <expression>* _ <type> <initializer> +// ::= [gs] na <expression>* _ <type> E +// ::= [gs] na <expression>* _ <type> <initializer> +// ::= [gs] dl <expression> +// ::= [gs] da <expression> +// ::= dc <type> <expression> +// ::= sc <type> <expression> +// ::= cc <type> <expression> +// ::= mc <parameter type> <expr> [<offset number>] E +// ::= rc <type> <expression> +// ::= ti <type> +// ::= te <expression> +// ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E +// ::= st <type> +// ::= sz <expression> +// ::= at <type> +// ::= az <expression> +// ::= nx <expression> +// ::= <template-param> +// ::= <function-param> +// ::= dt <expression> <unresolved-name> +// ::= pt <expression> <unresolved-name> +// ::= ds <expression> <expression> +// ::= sZ <template-param> +// ::= sZ <function-param> +// ::= sP <template-arg>* E +// ::= sp <expression> +// ::= fl <binary operator-name> <expression> +// ::= fr <binary operator-name> <expression> +// ::= fL <binary operator-name> <expression> <expression> +// ::= fR <binary operator-name> <expression> <expression> +// ::= tw <expression> +// ::= tr +// ::= u <source-name> <template-arg>* E +// ::= <unresolved-name> +// ::= <expr-primary> // -// <braced-expression> ::= <expression> -// ::= di <field source-name> <braced-expression> -// ::= dx <index expression> <braced-expression> -// ::= dX <range begin expression> <range end expression> <braced-expression> +// <function-param> ::= fp <CV-qualifiers> _ +// ::= fp <CV-qualifiers> <number> +// ::= fL <number> p <CV-qualifiers> _ +// ::= fL <number> p <CV-qualifiers> <number> +// ::= fpT // +// <braced-expression> ::= <expression> +// ::= di <field source-name> <braced-expression> +// ::= dx <index expression> <braced-expression> +// ::= dX <range begin expression> <range end expression> <braced-expression> func (st *state) expression() AST { if len(st.str) == 0 { st.fail("expected expression") @@ -2426,8 +2494,10 @@ func (st *state) expression() AST { } } -// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E -// <union-selector> ::= _ [<number>] +// subobject parses: +// +// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E +// <union-selector> ::= _ [<number>] func (st *state) subobject() AST { typ := st.demangleType(false) expr := st.expression() @@ -2462,10 +2532,12 @@ func (st *state) subobject() AST { } } -// <unresolved-name> ::= [gs] <base-unresolved-name> -// ::= sr <unresolved-type> <base-unresolved-name> -// ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name> -// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name> +// unresolvedName parses: +// +// <unresolved-name> ::= [gs] <base-unresolved-name> +// ::= sr <unresolved-type> <base-unresolved-name> +// ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name> +// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name> func (st *state) unresolvedName() AST { if len(st.str) >= 2 && st.str[:2] == "gs" { st.advance(2) @@ -2538,12 +2610,14 @@ func (st *state) unresolvedName() AST { } } -// <base-unresolved-name> ::= <simple-id> -// ::= on <operator-name> -// ::= on <operator-name> <template-args> -// ::= dn <destructor-name> +// baseUnresolvedName parses: +// +// <base-unresolved-name> ::= <simple-id> +// ::= on <operator-name> +// ::= on <operator-name> <template-args> +// ::= dn <destructor-name> // -//<simple-id> ::= <source-name> [ <template-args> ] +// <simple-id> ::= <source-name> [ <template-args> ] func (st *state) baseUnresolvedName() AST { var n AST if len(st.str) >= 2 && st.str[:2] == "on" { @@ -2572,9 +2646,11 @@ func (st *state) baseUnresolvedName() AST { return n } -// <expr-primary> ::= L <type> <(value) number> E -// ::= L <type> <(value) float> E -// ::= L <mangled-name> E +// exprPrimary parses: +// +// <expr-primary> ::= L <type> <(value) number> E +// ::= L <type> <(value) float> E +// ::= L <mangled-name> E func (st *state) exprPrimary() AST { st.checkChar('L') if len(st.str) == 0 { @@ -2642,8 +2718,10 @@ func (st *state) exprPrimary() AST { return ret } -// <discriminator> ::= _ <(non-negative) number> (when number < 10) -// __ <(non-negative) number> _ (when number >= 10) +// discriminator parses: +// +// <discriminator> ::= _ <(non-negative) number> (when number < 10) +// __ <(non-negative) number> _ (when number >= 10) func (st *state) discriminator(a AST) AST { if len(st.str) == 0 || st.str[0] != '_' { // clang can generate a discriminator at the end of @@ -2679,8 +2757,10 @@ func (st *state) discriminator(a AST) AST { return a } -// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ -// <lambda-sig> ::= <parameter type>+ +// closureTypeName parses: +// +// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ +// <lambda-sig> ::= <parameter type>+ func (st *state) closureTypeName() AST { st.checkChar('U') st.checkChar('l') @@ -2721,10 +2801,12 @@ func (st *state) closureTypeName() AST { return &Closure{TemplateArgs: templateArgs, Types: types, Num: num} } -// <template-param-decl> ::= Ty # type parameter -// ::= Tn <type> # non-type parameter -// ::= Tt <template-param-decl>* E # template parameter -// ::= Tp <template-param-decl> # parameter pack +// templateParamDecl parses: +// +// <template-param-decl> ::= Ty # type parameter +// ::= Tn <type> # non-type parameter +// ::= Tt <template-param-decl>* E # template parameter +// ::= Tp <template-param-decl> # parameter pack // // Returns the new AST to include in the AST we are building and the // new AST to add to the list of template parameters. @@ -2807,7 +2889,9 @@ func (st *state) templateParamDecl() (AST, AST) { } } -// <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ +// unnamedTypeName parses: +// +// <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ func (st *state) unnamedTypeName() AST { st.checkChar('U') st.checkChar('t') @@ -2821,9 +2905,9 @@ func (st *state) unnamedTypeName() AST { // but are added by GCC when cloning functions. func (st *state) cloneSuffix(a AST) AST { i := 0 - if len(st.str) > 1 && st.str[0] == '.' && (isLower(st.str[1]) || st.str[1] == '_') { + if len(st.str) > 1 && st.str[0] == '.' && (isLower(st.str[1]) || isDigit(st.str[1]) || st.str[1] == '_') { i += 2 - for len(st.str) > i && (isLower(st.str[i]) || st.str[i] == '_') { + for len(st.str) > i && (isLower(st.str[i]) || isDigit(st.str[i]) || st.str[i] == '_') { i++ } } @@ -2903,15 +2987,17 @@ var verboseAST = map[byte]AST{ Args: []AST{&BuiltinType{Name: "char"}}}}}, } -// <substitution> ::= S <seq-id> _ -// ::= S_ -// ::= St -// ::= Sa -// ::= Sb -// ::= Ss -// ::= Si -// ::= So -// ::= Sd +// substitution parses: +// +// <substitution> ::= S <seq-id> _ +// ::= S_ +// ::= St +// ::= Sa +// ::= Sb +// ::= Ss +// ::= Si +// ::= So +// ::= Sd func (st *state) substitution(forPrefix bool) AST { st.checkChar('S') if len(st.str) == 0 { diff --git a/src/cmd/vendor/github.com/ianlancetaylor/demangle/rust.go b/src/cmd/vendor/github.com/ianlancetaylor/demangle/rust.go index 140b631644250ab1caf8485679c0fdd3ca3a562a..39792189acc5c341541b7bd2c4fe1173a08683df 100644 --- a/src/cmd/vendor/github.com/ianlancetaylor/demangle/rust.go +++ b/src/cmd/vendor/github.com/ianlancetaylor/demangle/rust.go @@ -47,10 +47,19 @@ func rustToString(name string, options []Option) (ret string, err error) { } if suffix != "" { - rst.skip = false - rst.writeString(" (") - rst.writeString(suffix) - rst.writeByte(')') + llvmStyle := false + for _, o := range options { + if o == LLVMStyle { + llvmStyle = true + break + } + } + if llvmStyle { + rst.skip = false + rst.writeString(" (") + rst.writeString(suffix) + rst.writeByte(')') + } } return rst.buf.String(), nil @@ -110,8 +119,10 @@ func (rst *rustState) writeString(s string) { } } -// <symbol-name> = "_R" [<decimal-number>] <path> [<instantiating-crate>] -// <instantiating-crate> = <path> +// symbolName parses: +// +// <symbol-name> = "_R" [<decimal-number>] <path> [<instantiating-crate>] +// <instantiating-crate> = <path> // // We've already skipped the "_R". func (rst *rustState) symbolName() { @@ -131,17 +142,19 @@ func (rst *rustState) symbolName() { } } -// <path> = "C" <identifier> // crate root -// | "M" <impl-path> <type> // <T> (inherent impl) -// | "X" <impl-path> <type> <path> // <T as Trait> (trait impl) -// | "Y" <type> <path> // <T as Trait> (trait definition) -// | "N" <namespace> <path> <identifier> // ...::ident (nested path) -// | "I" <path> {<generic-arg>} "E" // ...<T, U> (generic args) -// | <backref> -// <namespace> = "C" // closure -// | "S" // shim -// | <A-Z> // other special namespaces -// | <a-z> // internal namespaces +// path parses: +// +// <path> = "C" <identifier> // crate root +// | "M" <impl-path> <type> // <T> (inherent impl) +// | "X" <impl-path> <type> <path> // <T as Trait> (trait impl) +// | "Y" <type> <path> // <T as Trait> (trait definition) +// | "N" <namespace> <path> <identifier> // ...::ident (nested path) +// | "I" <path> {<generic-arg>} "E" // ...<T, U> (generic args) +// | <backref> +// <namespace> = "C" // closure +// | "S" // shim +// | <A-Z> // other special namespaces +// | <a-z> // internal namespaces // // needsSeparator is true if we need to write out :: for a generic; // it is passed as false if we are in the middle of a type. @@ -237,7 +250,9 @@ func (rst *rustState) path(needsSeparator bool) { } } -// <impl-path> = [<disambiguator>] <path> +// implPath parses: +// +// <impl-path> = [<disambiguator>] <path> func (rst *rustState) implPath() { // This path is not part of the demangled string. hold := rst.skip @@ -250,16 +265,20 @@ func (rst *rustState) implPath() { rst.path(false) } -// <identifier> = [<disambiguator>] <undisambiguated-identifier> -// Returns the disambiguator and the identifier. +// identifier parses: +// +// <identifier> = [<disambiguator>] <undisambiguated-identifier> +// +// It returns the disambiguator and the identifier. func (rst *rustState) identifier() (int64, string) { dis := rst.disambiguator() - ident := rst.undisambiguatedIdentifier() + ident, _ := rst.undisambiguatedIdentifier() return dis, ident } -// <disambiguator> = "s" <base-62-number> -// This is optional. +// disambiguator parses an optional: +// +// <disambiguator> = "s" <base-62-number> func (rst *rustState) disambiguator() int64 { if len(rst.str) == 0 || rst.str[0] != 's' { return 0 @@ -268,12 +287,14 @@ func (rst *rustState) disambiguator() int64 { return rst.base62Number() + 1 } -// <undisambiguated-identifier> = ["u"] <decimal-number> ["_"] <bytes> -func (rst *rustState) undisambiguatedIdentifier() string { - punycode := false +// undisambiguatedIdentifier parses: +// +// <undisambiguated-identifier> = ["u"] <decimal-number> ["_"] <bytes> +func (rst *rustState) undisambiguatedIdentifier() (id string, isPunycode bool) { + isPunycode = false if len(rst.str) > 0 && rst.str[0] == 'u' { rst.advance(1) - punycode = true + isPunycode = true } val := rst.decimalNumber() @@ -285,7 +306,7 @@ func (rst *rustState) undisambiguatedIdentifier() string { if len(rst.str) < val { rst.fail("not enough characters for identifier") } - id := rst.str[:val] + id = rst.str[:val] rst.advance(val) for i := 0; i < len(id); i++ { @@ -300,11 +321,11 @@ func (rst *rustState) undisambiguatedIdentifier() string { } } - if punycode { + if isPunycode { id = rst.expandPunycode(id) } - return id + return id, isPunycode } // expandPunycode decodes the Rust version of punycode. @@ -320,14 +341,18 @@ func (rst *rustState) expandPunycode(s string) string { initialN = 128 ) + var ( + output []rune + encoding string + ) idx := strings.LastIndex(s, "_") - if idx < 0 { - rst.fail("missing underscore in punycode string") + if idx >= 0 { + output = []rune(s[:idx]) + encoding = s[idx+1:] + } else { + encoding = s } - output := []rune(s[:idx]) - encoding := s[idx+1:] - i := 0 n := initialN bias := initialBias @@ -398,6 +423,8 @@ func (rst *rustState) expandPunycode(s string) string { n += i / (len(output) + 1) if n > utf8.MaxRune { rst.fail("punycode rune overflow") + } else if !utf8.ValidRune(rune(n)) { + rst.fail("punycode invalid code point") } i %= len(output) + 1 output = append(output, 0) @@ -409,10 +436,12 @@ func (rst *rustState) expandPunycode(s string) string { return string(output) } -// <generic-arg> = <lifetime> -// | <type> -// | "K" <const> // forward-compat for const generics -// <lifetime> = "L" <base-62-number> +// genericArg parses: +// +// <generic-arg> = <lifetime> +// | <type> +// | "K" <const> // forward-compat for const generics +// <lifetime> = "L" <base-62-number> func (rst *rustState) genericArg() { if len(rst.str) < 1 { rst.fail("expected generic-arg") @@ -428,8 +457,9 @@ func (rst *rustState) genericArg() { } } -// <binder> = "G" <base-62-number> -// This is optional. +// binder parses an optional: +// +// <binder> = "G" <base-62-number> func (rst *rustState) binder() { if len(rst.str) < 1 || rst.str[0] != 'G' { return @@ -454,18 +484,20 @@ func (rst *rustState) binder() { rst.writeString("> ") } -// <type> = <basic-type> -// | <path> // named type -// | "A" <type> <const> // [T; N] -// | "S" <type> // [T] -// | "T" {<type>} "E" // (T1, T2, T3, ...) -// | "R" [<lifetime>] <type> // &T -// | "Q" [<lifetime>] <type> // &mut T -// | "P" <type> // *const T -// | "O" <type> // *mut T -// | "F" <fn-sig> // fn(...) -> ... -// | "D" <dyn-bounds> <lifetime> // dyn Trait<Assoc = X> + Send + 'a -// | <backref> +// demangleType parses: +// +// <type> = <basic-type> +// | <path> // named type +// | "A" <type> <const> // [T; N] +// | "S" <type> // [T] +// | "T" {<type>} "E" // (T1, T2, T3, ...) +// | "R" [<lifetime>] <type> // &T +// | "Q" [<lifetime>] <type> // &mut T +// | "P" <type> // *const T +// | "O" <type> // *mut T +// | "F" <fn-sig> // fn(...) -> ... +// | "D" <dyn-bounds> <lifetime> // dyn Trait<Assoc = X> + Send + 'a +// | <backref> func (rst *rustState) demangleType() { if len(rst.str) < 1 { rst.fail("expected type") @@ -577,7 +609,9 @@ var rustBasicTypes = map[byte]string{ 'z': "!", } -// <basic-type> +// basicType parses: +// +// <basic-type> func (rst *rustState) basicType() { if len(rst.str) < 1 { rst.fail("expected basic type") @@ -590,9 +624,11 @@ func (rst *rustState) basicType() { rst.writeString(str) } -// <fn-sig> = [<binder>] ["U"] ["K" <abi>] {<type>} "E" <type> -// <abi> = "C" -// | <undisambiguated-identifier> +// fnSig parses: +// +// <fn-sig> = [<binder>] ["U"] ["K" <abi>] {<type>} "E" <type> +// <abi> = "C" +// | <undisambiguated-identifier> func (rst *rustState) fnSig() { rst.binder() if len(rst.str) > 0 && rst.str[0] == 'U' { @@ -606,7 +642,10 @@ func (rst *rustState) fnSig() { rst.writeString(`extern "C" `) } else { rst.writeString(`extern "`) - id := rst.undisambiguatedIdentifier() + id, isPunycode := rst.undisambiguatedIdentifier() + if isPunycode { + rst.fail("punycode used in ABI string") + } id = strings.ReplaceAll(id, "_", "-") rst.writeString(id) rst.writeString(`" `) @@ -632,7 +671,9 @@ func (rst *rustState) fnSig() { } } -// <dyn-bounds> = [<binder>] {<dyn-trait>} "E" +// dynBounds parses: +// +// <dyn-bounds> = [<binder>] {<dyn-trait>} "E" func (rst *rustState) dynBounds() { rst.writeString("dyn ") rst.binder() @@ -648,8 +689,10 @@ func (rst *rustState) dynBounds() { rst.checkChar('E') } -// <dyn-trait> = <path> {<dyn-trait-assoc-binding>} -// <dyn-trait-assoc-binding> = "p" <undisambiguated-identifier> <type> +// dynTrait parses: +// +// <dyn-trait> = <path> {<dyn-trait-assoc-binding>} +// <dyn-trait-assoc-binding> = "p" <undisambiguated-identifier> <type> func (rst *rustState) dynTrait() { started := rst.pathStartGenerics() for len(rst.str) > 0 && rst.str[0] == 'p' { @@ -660,7 +703,8 @@ func (rst *rustState) dynTrait() { rst.writeByte('<') started = true } - rst.writeString(rst.undisambiguatedIdentifier()) + id, _ := rst.undisambiguatedIdentifier() + rst.writeString(id) rst.writeString(" = ") rst.demangleType() } @@ -722,10 +766,12 @@ func (rst *rustState) writeLifetime(lifetime int64) { } } -// <const> = <type> <const-data> -// | "p" // placeholder, shown as _ -// | <backref> -// <const-data> = ["n"] {<hex-digit>} "_" +// demangleConst parses: +// +// <const> = <type> <const-data> +// | "p" // placeholder, shown as _ +// | <backref> +// <const-data> = ["n"] {<hex-digit>} "_" func (rst *rustState) demangleConst() { if len(rst.str) < 1 { rst.fail("expected constant") @@ -856,7 +902,9 @@ digitLoop: } } -// <base-62-number> = {<0-9a-zA-Z>} "_" +// base62Number parses: +// +// <base-62-number> = {<0-9a-zA-Z>} "_" func (rst *rustState) base62Number() int64 { if len(rst.str) > 0 && rst.str[0] == '_' { rst.advance(1) @@ -884,7 +932,9 @@ func (rst *rustState) base62Number() int64 { return 0 } -// <backref> = "B" <base-62-number> +// backref parses: +// +// <backref> = "B" <base-62-number> func (rst *rustState) backref(demangle func()) { backoff := rst.off @@ -954,7 +1004,7 @@ func oldRustToString(name string, options []Option) (string, bool) { // followed by "E". We check that the 16 characters are all hex digits. // Also the hex digits must contain at least 5 distinct digits. seen := uint16(0) - for i := len(name) - 17; i < len(name) - 1; i++ { + for i := len(name) - 17; i < len(name)-1; i++ { digit, ok := hexDigit(name[i]) if !ok { return "", false @@ -1012,7 +1062,7 @@ func oldRustToString(name string, options []Option) (string, bool) { for len(id) > 0 { switch c := id[0]; c { case '$': - codes := map[string]byte { + codes := map[string]byte{ "SP": '@', "BP": '*', "RF": '&', diff --git a/src/cmd/vendor/golang.org/x/sys/plan9/syscall_plan9.go b/src/cmd/vendor/golang.org/x/sys/plan9/syscall_plan9.go index 84e14714811d3cdf82fe7d05f6de53f7c7e53c8c..723b1f4002aa6521c5c43a7824b135c673d1cd7c 100644 --- a/src/cmd/vendor/golang.org/x/sys/plan9/syscall_plan9.go +++ b/src/cmd/vendor/golang.org/x/sys/plan9/syscall_plan9.go @@ -132,8 +132,10 @@ func Pipe(p []int) (err error) { } var pp [2]int32 err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ioctl_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/ioctl_linux.go index 1dadead21e6d6a1ea5b7edebdbdcdec773dec1c6..884430b810ccc15fa3a38a3a424634554afe40a8 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ioctl_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ioctl_linux.go @@ -194,3 +194,26 @@ func ioctlIfreqData(fd int, req uint, value *ifreqData) error { // identical so pass *IfreqData directly. return ioctlPtr(fd, req, unsafe.Pointer(value)) } + +// IoctlKCMClone attaches a new file descriptor to a multiplexor by cloning an +// existing KCM socket, returning a structure containing the file descriptor of +// the new socket. +func IoctlKCMClone(fd int) (*KCMClone, error) { + var info KCMClone + if err := ioctlPtr(fd, SIOCKCMCLONE, unsafe.Pointer(&info)); err != nil { + return nil, err + } + + return &info, nil +} + +// IoctlKCMAttach attaches a TCP socket and associated BPF program file +// descriptor to a multiplexor. +func IoctlKCMAttach(fd int, info KCMAttach) error { + return ioctlPtr(fd, SIOCKCMATTACH, unsafe.Pointer(&info)) +} + +// IoctlKCMUnattach unattaches a TCP socket file descriptor from a multiplexor. +func IoctlKCMUnattach(fd int, info KCMUnattach) error { + return ioctlPtr(fd, SIOCKCMUNATTACH, unsafe.Pointer(&info)) +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh index 4945739ea0a99b1002f24876eea98353b17a3b13..a037087481db7422f1a76f76aab834e48381ad35 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -205,6 +205,7 @@ struct ltchars { #include <linux/bpf.h> #include <linux/can.h> #include <linux/can/error.h> +#include <linux/can/netlink.h> #include <linux/can/raw.h> #include <linux/capability.h> #include <linux/cryptouser.h> @@ -231,6 +232,7 @@ struct ltchars { #include <linux/if_packet.h> #include <linux/if_xdp.h> #include <linux/input.h> +#include <linux/kcm.h> #include <linux/kexec.h> #include <linux/keyctl.h> #include <linux/landlock.h> @@ -261,6 +263,7 @@ struct ltchars { #include <linux/vm_sockets.h> #include <linux/wait.h> #include <linux/watchdog.h> +#include <linux/wireguard.h> #include <mtd/ubi-user.h> #include <mtd/mtd-user.h> @@ -502,6 +505,7 @@ ccflags="$@" $2 ~ /^O?XTABS$/ || $2 ~ /^TC[IO](ON|OFF)$/ || $2 ~ /^IN_/ || + $2 ~ /^KCM/ || $2 ~ /^LANDLOCK_/ || $2 ~ /^LOCK_(SH|EX|NB|UN)$/ || $2 ~ /^LO_(KEY|NAME)_SIZE$/ || @@ -596,6 +600,7 @@ ccflags="$@" $2 ~ /^DEVLINK_/ || $2 ~ /^ETHTOOL_/ || $2 ~ /^LWTUNNEL_IP/ || + $2 ~ /^ITIMER_/ || $2 !~ "WMESGLEN" && $2 ~ /^W[A-Z0-9]+$/ || $2 ~/^PPPIOC/ || @@ -606,6 +611,7 @@ ccflags="$@" $2 ~ /^MTD/ || $2 ~ /^OTP/ || $2 ~ /^MEM/ || + $2 ~ /^WG/ || $2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)} $2 ~ /^__WCOREFLAG$/ {next} $2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_aix.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_aix.go index 6192750ce31b31d6f930252c0fe65d573d97d2cd..4f55c8d999608617d9a5bce3a8e561da3ba3c12e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_aix.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_aix.go @@ -519,8 +519,10 @@ func Pipe(p []int) (err error) { } var pp [2]_C_int err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go index 8826f41435e92bcde35f597426c87482e1f80996..0eaab91314c6b85a2642a26232f9dea4b2421e93 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -159,8 +159,10 @@ func Pipe(p []int) (err error) { } var x [2]int32 err = pipe(&x) - p[0] = int(x[0]) - p[1] = int(x[1]) + if err == nil { + p[0] = int(x[0]) + p[1] = int(x[1]) + } return } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go index 5af108a50385ecc31c864aa3558a215f0fcf6f58..2e37c3167f391c31809d6d6d8b34df4a049aae23 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go @@ -101,7 +101,10 @@ func Pipe(p []int) (err error) { if len(p) != 2 { return EINVAL } - p[0], p[1], err = pipe() + r, w, err := pipe() + if err == nil { + p[0], p[1] = r, w + } return } @@ -114,7 +117,10 @@ func Pipe2(p []int, flags int) (err error) { var pp [2]_C_int // pipe2 on dragonfly takes an fds array as an argument, but still // returns the file descriptors. - p[0], p[1], err = pipe2(&pp, flags) + r, w, err := pipe2(&pp, flags) + if err == nil { + p[0], p[1] = r, w + } return err } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_freebsd.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_freebsd.go index 18c392cf3692ff01a3470e5c4925c425bda93a90..2f650ae665cc8bf9d7e74bdd09253223940b4779 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_freebsd.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_freebsd.go @@ -110,8 +110,10 @@ func Pipe2(p []int, flags int) error { } var pp [2]_C_int err := pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return err } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go index 4bc5baf77d9630d1bfe17d37e6052e325675a3d3..5f28f8fdeda19e2422628970426e684b06c80e86 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -14,6 +14,7 @@ package unix import ( "encoding/binary" "syscall" + "time" "unsafe" ) @@ -131,8 +132,10 @@ func Pipe2(p []int, flags int) error { } var pp [2]_C_int err := pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return err } @@ -247,6 +250,13 @@ func Getwd() (wd string, err error) { if n < 1 || n > len(buf) || buf[n-1] != 0 { return "", EINVAL } + // In some cases, Linux can return a path that starts with the + // "(unreachable)" prefix, which can potentially be a valid relative + // path. To work around that, return ENOENT if path is not absolute. + if buf[0] != '/' { + return "", ENOENT + } + return string(buf[0 : n-1]), nil } @@ -2312,11 +2322,56 @@ type RemoteIovec struct { //sys shmdt(addr uintptr) (err error) //sys shmget(key int, size int, flag int) (id int, err error) +//sys getitimer(which int, currValue *Itimerval) (err error) +//sys setitimer(which int, newValue *Itimerval, oldValue *Itimerval) (err error) + +// MakeItimerval creates an Itimerval from interval and value durations. +func MakeItimerval(interval, value time.Duration) Itimerval { + return Itimerval{ + Interval: NsecToTimeval(interval.Nanoseconds()), + Value: NsecToTimeval(value.Nanoseconds()), + } +} + +// A value which may be passed to the which parameter for Getitimer and +// Setitimer. +type ItimerWhich int + +// Possible which values for Getitimer and Setitimer. +const ( + ItimerReal ItimerWhich = ITIMER_REAL + ItimerVirtual ItimerWhich = ITIMER_VIRTUAL + ItimerProf ItimerWhich = ITIMER_PROF +) + +// Getitimer wraps getitimer(2) to return the current value of the timer +// specified by which. +func Getitimer(which ItimerWhich) (Itimerval, error) { + var it Itimerval + if err := getitimer(int(which), &it); err != nil { + return Itimerval{}, err + } + + return it, nil +} + +// Setitimer wraps setitimer(2) to arm or disarm the timer specified by which. +// It returns the previous value of the timer. +// +// If the Itimerval argument is the zero value, the timer will be disarmed. +func Setitimer(which ItimerWhich, it Itimerval) (Itimerval, error) { + var prev Itimerval + if err := setitimer(int(which), &it, &prev); err != nil { + return Itimerval{}, err + } + + return prev, nil +} + /* * Unimplemented */ // AfsSyscall -// Alarm // ArchPrctl // Brk // ClockNanosleep @@ -2332,7 +2387,6 @@ type RemoteIovec struct { // GetMempolicy // GetRobustList // GetThreadArea -// Getitimer // Getpmsg // IoCancel // IoDestroy diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go index 5f757e8aa770632541210c36ba7dd9e1f600924a..d44b8ad5339d1c931069f69557fc5fe9ecc9d2a0 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go @@ -173,14 +173,6 @@ const ( _SENDMMSG = 20 ) -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - fd, e := socketcall(_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0) - if e != 0 { - err = e - } - return -} - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { fd, e := socketcall(_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) if e != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_alarm.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_alarm.go new file mode 100644 index 0000000000000000000000000000000000000000..08086ac6a4c411bb917b18846eaa109d53812bf7 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_alarm.go @@ -0,0 +1,14 @@ +// Copyright 2022 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. + +//go:build linux && (386 || amd64 || mips || mipsle || mips64 || mipsle || ppc64 || ppc64le || ppc || s390x || sparc64) +// +build linux +// +build 386 amd64 mips mipsle mips64 mipsle ppc64 ppc64le ppc s390x sparc64 + +package unix + +// SYS_ALARM is not defined on arm or riscv, but is available for other GOARCH +// values. + +//sys Alarm(seconds uint) (remaining uint, err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go index 4299125aa7cca0af1a6a33b2e4596a2b6008ec58..bd21d93bf84a4900a56dc829a9b5d4a8f8149e23 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go @@ -62,7 +62,6 @@ func Stat(path string, stat *Stat_t) (err error) { //sys SyncFileRange(fd int, off int64, n int64, flags int) (err error) //sys Truncate(path string, length int64) (err error) //sys Ustat(dev int, ubuf *Ustat_t) (err error) -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go index 79edeb9cb14a5723c613901a13744acdf0a5daa2..343c91f6b31dd6fe101df36929b6900b4a75c885 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm.go @@ -27,7 +27,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { return newoffset, nil } -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go index 862890de29bf224582a6c89fa46fd67f4942e238..8c562868480f8725558bb373407ecae7275f4d03 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -66,7 +66,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { return ENOSYS } -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go index 8932e34ad2ad7ddc811c2eee83624a782fd5d659..f0b138002c165092b6c4954714a22dc7348f1b8f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go @@ -48,7 +48,6 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err //sys SyncFileRange(fd int, off int64, n int64, flags int) (err error) //sys Truncate(path string, length int64) (err error) //sys Ustat(dev int, ubuf *Ustat_t) (err error) -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go index 7821c25d9f778fce7fc6452bef05193ed6ecd38d..e6163c30fe9417541d7f35ef326e35362c8a4eae 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go @@ -41,7 +41,6 @@ func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, //sys SyncFileRange(fd int, off int64, n int64, flags int) (err error) //sys Truncate(path string, length int64) (err error) = SYS_TRUNCATE64 //sys Ustat(dev int, ubuf *Ustat_t) (err error) -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go index c5053a0f03fdc5414803a2cfc473b313bc379548..4740e80a8ec9ed5929fe699435b5d6944608dcc7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc.go @@ -43,7 +43,6 @@ import ( //sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64 //sys Truncate(path string, length int64) (err error) = SYS_TRUNCATE64 //sys Ustat(dev int, ubuf *Ustat_t) (err error) -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go index 25786c4216b514abcda12d9d46d3040324da3b06..78bc9166ef6f776aa78cd4a7a26cd28c03ea939c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go @@ -45,7 +45,6 @@ package unix //sys Statfs(path string, buf *Statfs_t) (err error) //sys Truncate(path string, length int64) (err error) //sys Ustat(dev int, ubuf *Ustat_t) (err error) -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go index 6f9f710414f0672420d101ee43f2e3dd43847828..3d6c4eb068100d214c3bce38ccb734e3b79ee97c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go @@ -65,7 +65,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { return ENOSYS } -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go index 6aa59cb270db00b3c7a79cecaab6e37c47c87f56..89ce84a4168004b98dba277ea3e2324fe4cd2900 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go @@ -145,15 +145,6 @@ const ( netSendMMsg = 20 ) -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (int, error) { - args := [3]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))} - fd, _, err := Syscall(SYS_SOCKETCALL, netAccept, uintptr(unsafe.Pointer(&args)), 0) - if err != 0 { - return 0, err - } - return int(fd), nil -} - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (int, error) { args := [4]uintptr{uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags)} fd, _, err := Syscall(SYS_SOCKETCALL, netAccept4, uintptr(unsafe.Pointer(&args)), 0) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go index bbe8d174f8c12ebbe0eb87a77b70ed73fcc49336..35bdb098c5bafb079a3345b5e6dba0486adebd45 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go @@ -42,7 +42,6 @@ package unix //sys Statfs(path string, buf *Statfs_t) (err error) //sys SyncFileRange(fd int, off int64, n int64, flags int) (err error) //sys Truncate(path string, length int64) (err error) -//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) //sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_netbsd.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_netbsd.go index 853d5f0f4365d6aff5f479a37769cb5c11e17482..696fed496f6847cb744eef5223ca014d4fea600c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_netbsd.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_netbsd.go @@ -110,14 +110,8 @@ func direntNamlen(buf []byte) (uint64, bool) { return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen)) } -//sysnb pipe() (fd1 int, fd2 int, err error) - func Pipe(p []int) (err error) { - if len(p) != 2 { - return EINVAL - } - p[0], p[1], err = pipe() - return + return Pipe2(p, 0) } //sysnb pipe2(p *[2]_C_int, flags int) (err error) @@ -128,8 +122,10 @@ func Pipe2(p []int, flags int) error { } var pp [2]_C_int err := pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return err } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_openbsd.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_openbsd.go index 22b55038501f5f6e266dae89ca48d0a93d1c63c2..11b1d419da91f5993f65a96495862103e748420f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_openbsd.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_openbsd.go @@ -87,8 +87,10 @@ func Pipe2(p []int, flags int) error { } var pp [2]_C_int err := pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return err } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go index 8b88ac213333dcdf1805e2bf6b7a47732fe3cc3c..5c813921e855c77a95293b2a444ce4eca4f5cc43 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -66,8 +66,10 @@ func Pipe(p []int) (err error) { if n != 0 { return err } - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return nil } @@ -79,8 +81,10 @@ func Pipe2(p []int, flags int) error { } var pp [2]_C_int err := pipe2(&pp, flags) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return err } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go index 5fb76a146843c54227a6954a0aeb2116de0c7982..f8616f454ec69314df269833effb6e47128bebff 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go @@ -579,8 +579,10 @@ func Pipe(p []int) (err error) { } var pp [2]_C_int err = pipe(&pp) - p[0] = int(pp[0]) - p[1] = int(pp[1]) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } return } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go index d175aae896cbc8d7f7a4402225dfd65446890696..bc7c9d0755988f58a94862eb50bf7376f762a0ca 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -38,7 +38,8 @@ const ( AF_KEY = 0xf AF_LLC = 0x1a AF_LOCAL = 0x1 - AF_MAX = 0x2d + AF_MAX = 0x2e + AF_MCTP = 0x2d AF_MPLS = 0x1c AF_NETBEUI = 0xd AF_NETLINK = 0x10 @@ -259,6 +260,17 @@ const ( BUS_USB = 0x3 BUS_VIRTUAL = 0x6 CAN_BCM = 0x2 + CAN_CTRLMODE_3_SAMPLES = 0x4 + CAN_CTRLMODE_BERR_REPORTING = 0x10 + CAN_CTRLMODE_CC_LEN8_DLC = 0x100 + CAN_CTRLMODE_FD = 0x20 + CAN_CTRLMODE_FD_NON_ISO = 0x80 + CAN_CTRLMODE_LISTENONLY = 0x2 + CAN_CTRLMODE_LOOPBACK = 0x1 + CAN_CTRLMODE_ONE_SHOT = 0x8 + CAN_CTRLMODE_PRESUME_ACK = 0x40 + CAN_CTRLMODE_TDC_AUTO = 0x200 + CAN_CTRLMODE_TDC_MANUAL = 0x400 CAN_EFF_FLAG = 0x80000000 CAN_EFF_ID_BITS = 0x1d CAN_EFF_MASK = 0x1fffffff @@ -336,6 +348,7 @@ const ( CAN_RTR_FLAG = 0x40000000 CAN_SFF_ID_BITS = 0xb CAN_SFF_MASK = 0x7ff + CAN_TERMINATION_DISABLED = 0x0 CAN_TP16 = 0x3 CAN_TP20 = 0x4 CAP_AUDIT_CONTROL = 0x1e @@ -741,6 +754,7 @@ const ( ETH_P_QINQ2 = 0x9200 ETH_P_QINQ3 = 0x9300 ETH_P_RARP = 0x8035 + ETH_P_REALTEK = 0x8899 ETH_P_SCA = 0x6007 ETH_P_SLOW = 0x8809 ETH_P_SNAP = 0x5 @@ -810,10 +824,12 @@ const ( FAN_EPIDFD = -0x2 FAN_EVENT_INFO_TYPE_DFID = 0x3 FAN_EVENT_INFO_TYPE_DFID_NAME = 0x2 + FAN_EVENT_INFO_TYPE_ERROR = 0x5 FAN_EVENT_INFO_TYPE_FID = 0x1 FAN_EVENT_INFO_TYPE_PIDFD = 0x4 FAN_EVENT_METADATA_LEN = 0x18 FAN_EVENT_ON_CHILD = 0x8000000 + FAN_FS_ERROR = 0x8000 FAN_MARK_ADD = 0x1 FAN_MARK_DONT_FOLLOW = 0x4 FAN_MARK_FILESYSTEM = 0x100 @@ -1264,9 +1280,14 @@ const ( IP_XFRM_POLICY = 0x11 ISOFS_SUPER_MAGIC = 0x9660 ISTRIP = 0x20 + ITIMER_PROF = 0x2 + ITIMER_REAL = 0x0 + ITIMER_VIRTUAL = 0x1 IUTF8 = 0x4000 IXANY = 0x800 JFFS2_SUPER_MAGIC = 0x72b6 + KCMPROTO_CONNECTED = 0x0 + KCM_RECV_DISABLE = 0x1 KEXEC_ARCH_386 = 0x30000 KEXEC_ARCH_68K = 0x40000 KEXEC_ARCH_AARCH64 = 0xb70000 @@ -1827,6 +1848,8 @@ const ( PERF_MEM_BLK_DATA = 0x2 PERF_MEM_BLK_NA = 0x1 PERF_MEM_BLK_SHIFT = 0x28 + PERF_MEM_HOPS_0 = 0x1 + PERF_MEM_HOPS_SHIFT = 0x2b PERF_MEM_LOCK_LOCKED = 0x2 PERF_MEM_LOCK_NA = 0x1 PERF_MEM_LOCK_SHIFT = 0x18 @@ -1986,6 +2009,9 @@ const ( PR_SCHED_CORE_CREATE = 0x1 PR_SCHED_CORE_GET = 0x0 PR_SCHED_CORE_MAX = 0x4 + PR_SCHED_CORE_SCOPE_PROCESS_GROUP = 0x2 + PR_SCHED_CORE_SCOPE_THREAD = 0x0 + PR_SCHED_CORE_SCOPE_THREAD_GROUP = 0x1 PR_SCHED_CORE_SHARE_FROM = 0x3 PR_SCHED_CORE_SHARE_TO = 0x2 PR_SET_CHILD_SUBREAPER = 0x24 @@ -2167,12 +2193,23 @@ const ( RTCF_NAT = 0x800000 RTCF_VALVE = 0x200000 RTC_AF = 0x20 + RTC_BSM_DIRECT = 0x1 + RTC_BSM_DISABLED = 0x0 + RTC_BSM_LEVEL = 0x2 + RTC_BSM_STANDBY = 0x3 RTC_FEATURE_ALARM = 0x0 + RTC_FEATURE_ALARM_RES_2S = 0x3 RTC_FEATURE_ALARM_RES_MINUTE = 0x1 - RTC_FEATURE_CNT = 0x3 + RTC_FEATURE_BACKUP_SWITCH_MODE = 0x6 + RTC_FEATURE_CNT = 0x7 + RTC_FEATURE_CORRECTION = 0x5 RTC_FEATURE_NEED_WEEK_DAY = 0x2 + RTC_FEATURE_UPDATE_INTERRUPT = 0x4 RTC_IRQF = 0x80 RTC_MAX_FREQ = 0x2000 + RTC_PARAM_BACKUP_SWITCH_MODE = 0x2 + RTC_PARAM_CORRECTION = 0x1 + RTC_PARAM_FEATURES = 0x0 RTC_PF = 0x40 RTC_UF = 0x10 RTF_ADDRCLASSMASK = 0xf8000000 @@ -2423,6 +2460,9 @@ const ( SIOCGSTAMPNS = 0x8907 SIOCGSTAMPNS_OLD = 0x8907 SIOCGSTAMP_OLD = 0x8906 + SIOCKCMATTACH = 0x89e0 + SIOCKCMCLONE = 0x89e2 + SIOCKCMUNATTACH = 0x89e1 SIOCOUTQNSD = 0x894b SIOCPROTOPRIVATE = 0x89e0 SIOCRTMSG = 0x890d @@ -2532,6 +2572,8 @@ const ( SO_VM_SOCKETS_BUFFER_MIN_SIZE = 0x1 SO_VM_SOCKETS_BUFFER_SIZE = 0x0 SO_VM_SOCKETS_CONNECT_TIMEOUT = 0x6 + SO_VM_SOCKETS_CONNECT_TIMEOUT_NEW = 0x8 + SO_VM_SOCKETS_CONNECT_TIMEOUT_OLD = 0x6 SO_VM_SOCKETS_NONBLOCK_TXRX = 0x7 SO_VM_SOCKETS_PEER_HOST_VM_ID = 0x3 SO_VM_SOCKETS_TRUSTED = 0x5 @@ -2826,6 +2868,13 @@ const ( WDIOS_TEMPPANIC = 0x4 WDIOS_UNKNOWN = -0x1 WEXITED = 0x4 + WGALLOWEDIP_A_MAX = 0x3 + WGDEVICE_A_MAX = 0x8 + WGPEER_A_MAX = 0xa + WG_CMD_MAX = 0x1 + WG_GENL_NAME = "wireguard" + WG_GENL_VERSION = 0x1 + WG_KEY_LEN = 0x20 WIN_ACKMEDIACHANGE = 0xdb WIN_CHECKPOWERMODE1 = 0xe5 WIN_CHECKPOWERMODE2 = 0x98 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 3ca40ca7f02abf2d9bec49693f67c8b24f7a4eed..234fd4a5d1ade3e03178d040f1142ebeea6123d8 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -250,6 +250,8 @@ const ( RTC_EPOCH_SET = 0x4004700e RTC_IRQP_READ = 0x8004700b RTC_IRQP_SET = 0x4004700c + RTC_PARAM_GET = 0x40187013 + RTC_PARAM_SET = 0x40187014 RTC_PIE_OFF = 0x7006 RTC_PIE_ON = 0x7005 RTC_PLL_GET = 0x801c7011 @@ -327,6 +329,7 @@ const ( SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index ead332091afded9131afde203606d5cc37faceb7..58619b7589b0aa472621b9d5368d0498e67b2dd4 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -251,6 +251,8 @@ const ( RTC_EPOCH_SET = 0x4008700e RTC_IRQP_READ = 0x8008700b RTC_IRQP_SET = 0x4008700c + RTC_PARAM_GET = 0x40187013 + RTC_PARAM_SET = 0x40187014 RTC_PIE_OFF = 0x7006 RTC_PIE_ON = 0x7005 RTC_PLL_GET = 0x80207011 @@ -328,6 +330,7 @@ const ( SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 39bdc9455899a85dba94754071dc4502d3be6d56..3a64ff59dcecf0a8be2ee6d1ee14dc6a95a107de 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -257,6 +257,8 @@ const ( RTC_EPOCH_SET = 0x4004700e RTC_IRQP_READ = 0x8004700b RTC_IRQP_SET = 0x4004700c + RTC_PARAM_GET = 0x40187013 + RTC_PARAM_SET = 0x40187014 RTC_PIE_OFF = 0x7006 RTC_PIE_ON = 0x7005 RTC_PLL_GET = 0x801c7011 @@ -334,6 +336,7 @@ const ( SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 9aec987db1ce6c7da7e2a71df03a1c9571df1d52..abe0b925789f4d7153d6ac996e7a5805736f9421 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -247,6 +247,8 @@ const ( RTC_EPOCH_SET = 0x4008700e RTC_IRQP_READ = 0x8008700b RTC_IRQP_SET = 0x4008700c + RTC_PARAM_GET = 0x40187013 + RTC_PARAM_SET = 0x40187014 RTC_PIE_OFF = 0x7006 RTC_PIE_ON = 0x7005 RTC_PLL_GET = 0x80207011 @@ -324,6 +326,7 @@ const ( SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index a8bba9491e8260f079dceca2057c7d25ef03ecfe..14d7a84399de4b684f0862ac963936060a0174fd 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -250,6 +250,8 @@ const ( RTC_EPOCH_SET = 0x8004700e RTC_IRQP_READ = 0x4004700b RTC_IRQP_SET = 0x8004700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 RTC_PIE_OFF = 0x20007006 RTC_PIE_ON = 0x20007005 RTC_PLL_GET = 0x401c7011 @@ -327,6 +329,7 @@ const ( SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 SO_RXQ_OVFL = 0x28 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index ee9e7e2020eaa46760dab83009a2ca705a33b1ad..99e7c4ac0b454949cd245fca9ef4b19f81265bf4 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -250,6 +250,8 @@ const ( RTC_EPOCH_SET = 0x8008700e RTC_IRQP_READ = 0x4008700b RTC_IRQP_SET = 0x8008700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 RTC_PIE_OFF = 0x20007006 RTC_PIE_ON = 0x20007005 RTC_PLL_GET = 0x40207011 @@ -327,6 +329,7 @@ const ( SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 SO_RXQ_OVFL = 0x28 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index ba4b288a3c0681990e7a7b6671b4b75c1425d1bd..496364c33cc6e2159e5502403b12be3bc8b1a73b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -250,6 +250,8 @@ const ( RTC_EPOCH_SET = 0x8008700e RTC_IRQP_READ = 0x4008700b RTC_IRQP_SET = 0x8008700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 RTC_PIE_OFF = 0x20007006 RTC_PIE_ON = 0x20007005 RTC_PLL_GET = 0x40207011 @@ -327,6 +329,7 @@ const ( SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 SO_RXQ_OVFL = 0x28 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index bc93afc36751391dce6e3469fc2b76171d74ed32..3e40830857dd0f32114387a040354386933a3702 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -250,6 +250,8 @@ const ( RTC_EPOCH_SET = 0x8004700e RTC_IRQP_READ = 0x4004700b RTC_IRQP_SET = 0x8004700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 RTC_PIE_OFF = 0x20007006 RTC_PIE_ON = 0x20007005 RTC_PLL_GET = 0x401c7011 @@ -327,6 +329,7 @@ const ( SO_RCVTIMEO = 0x1006 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x1006 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 SO_RXQ_OVFL = 0x28 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index 9295e69478529ab98e22e41cc0f2f1d652cbc400..1151a7dfab3379a9e872fa45012113639cac890d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -305,6 +305,8 @@ const ( RTC_EPOCH_SET = 0x8004700e RTC_IRQP_READ = 0x4004700b RTC_IRQP_SET = 0x8004700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 RTC_PIE_OFF = 0x20007006 RTC_PIE_ON = 0x20007005 RTC_PLL_GET = 0x401c7011 @@ -382,6 +384,7 @@ const ( SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 1fa081c9a6733951d8a1da37766e05c4f7a951c7..ed17f249e758a317ea37a3f6dbcfc8dfd719a26d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -309,6 +309,8 @@ const ( RTC_EPOCH_SET = 0x8008700e RTC_IRQP_READ = 0x4008700b RTC_IRQP_SET = 0x8008700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 RTC_PIE_OFF = 0x20007006 RTC_PIE_ON = 0x20007005 RTC_PLL_GET = 0x40207011 @@ -386,6 +388,7 @@ const ( SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 74b321149463dd6cade944cc03474781bf1795e1..d84a37c1ac23bb9b62089b64babbb6ac5a53eaea 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -309,6 +309,8 @@ const ( RTC_EPOCH_SET = 0x8008700e RTC_IRQP_READ = 0x4008700b RTC_IRQP_SET = 0x8008700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 RTC_PIE_OFF = 0x20007006 RTC_PIE_ON = 0x20007005 RTC_PLL_GET = 0x40207011 @@ -386,6 +388,7 @@ const ( SO_RCVTIMEO = 0x12 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x12 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index c91c8ac5b01dcaa956f297dc2e38bf541ea58781..5cafba83f6b49a9119043add3ba46d11f5ccde64 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -238,6 +238,8 @@ const ( RTC_EPOCH_SET = 0x4008700e RTC_IRQP_READ = 0x8008700b RTC_IRQP_SET = 0x4008700c + RTC_PARAM_GET = 0x40187013 + RTC_PARAM_SET = 0x40187014 RTC_PIE_OFF = 0x7006 RTC_PIE_ON = 0x7005 RTC_PLL_GET = 0x80207011 @@ -315,6 +317,7 @@ const ( SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index b66bf22289490cff36748ee020e0b8d66c035f9e..6d122da41c53c2deeb9fbb38d02332b1bc22665c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -313,6 +313,8 @@ const ( RTC_EPOCH_SET = 0x4008700e RTC_IRQP_READ = 0x8008700b RTC_IRQP_SET = 0x4008700c + RTC_PARAM_GET = 0x40187013 + RTC_PARAM_SET = 0x40187014 RTC_PIE_OFF = 0x7006 RTC_PIE_ON = 0x7005 RTC_PLL_GET = 0x80207011 @@ -390,6 +392,7 @@ const ( SO_RCVTIMEO = 0x14 SO_RCVTIMEO_NEW = 0x42 SO_RCVTIMEO_OLD = 0x14 + SO_RESERVE_MEM = 0x49 SO_REUSEADDR = 0x2 SO_REUSEPORT = 0xf SO_RXQ_OVFL = 0x28 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index f7fb149b0c98db82667f91b310f96e30b82ffa16..6bd19e51dbb9e47b0615b202518c01908bef8024 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -304,6 +304,8 @@ const ( RTC_EPOCH_SET = 0x8008700e RTC_IRQP_READ = 0x4008700b RTC_IRQP_SET = 0x8008700c + RTC_PARAM_GET = 0x80187013 + RTC_PARAM_SET = 0x80187014 RTC_PIE_OFF = 0x20007006 RTC_PIE_ON = 0x20007005 RTC_PLL_GET = 0x40207011 @@ -381,6 +383,7 @@ const ( SO_RCVTIMEO = 0x2000 SO_RCVTIMEO_NEW = 0x44 SO_RCVTIMEO_OLD = 0x2000 + SO_RESERVE_MEM = 0x52 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 SO_RXQ_OVFL = 0x24 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go index 93edda4c49394a3d74bcd3b22b6c96bf35d8e3c9..30fa4055ec1f3f0d7496c5fdd2d09690af8e5d68 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go @@ -2032,3 +2032,23 @@ func shmget(key int, size int, flag int) (id int, err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getitimer(which int, currValue *Itimerval) (err error) { + _, _, e1 := Syscall(SYS_GETITIMER, uintptr(which), uintptr(unsafe.Pointer(currValue)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setitimer(which int, newValue *Itimerval, oldValue *Itimerval) (err error) { + _, _, e1 := Syscall(SYS_SETITIMER, uintptr(which), uintptr(unsafe.Pointer(newValue)), uintptr(unsafe.Pointer(oldValue))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go index ff90c81e7300eb19641ea5c9b7eb273fde949121..2fc6271f47cf07658316cb88958d3da35500806f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -l32 -tags linux,386 syscall_linux.go syscall_linux_386.go +// go run mksyscall.go -l32 -tags linux,386 syscall_linux.go syscall_linux_386.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && 386 @@ -524,3 +524,14 @@ func utimes(path string, times *[2]Timeval) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go index fa7d3dbe4e94d5ec4912d851cb2acee633c52473..43d9f0128146ad1e6e5f1b489946d627fbb2d26d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -tags linux,amd64 syscall_linux.go syscall_linux_amd64.go +// go run mksyscall.go -tags linux,amd64 syscall_linux.go syscall_linux_amd64.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && amd64 @@ -444,17 +444,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -691,3 +680,14 @@ func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, f } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go index 654f91530f6950860dfdbbc443cf0fa4111c38ea..7df0cb1795864934b9f2597b01ca48ec9d1f5e6c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go @@ -46,17 +46,6 @@ func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go index e893f987f91de672ba121bff0765d76874ed91e7..076e8f1c5bbbd7e9d0a34e7af7e6f58a4ddea606 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go @@ -389,17 +389,6 @@ func Truncate(path string, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go index 6d1552885314b402c1462928dfa6b2de62eb2bb0..7b3c84746780195c1604dbcdbb49f549ca87a943 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -b32 -arm -tags linux,mips syscall_linux.go syscall_linux_mipsx.go +// go run mksyscall.go -b32 -arm -tags linux,mips syscall_linux.go syscall_linux_mipsx.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && mips @@ -344,17 +344,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -702,3 +691,14 @@ func setrlimit(resource int, rlim *rlimit32) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go index 1e20d72df21ec3a4e57d272f9c57ace9ee495c29..0d3c45fbddad93b9ec42849b08c409c1e158109b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -tags linux,mips64 syscall_linux.go syscall_linux_mips64x.go +// go run mksyscall.go -tags linux,mips64 syscall_linux.go syscall_linux_mips64x.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && mips64 @@ -399,17 +399,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -696,3 +685,14 @@ func stat(path string, st *stat_t) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go index 82b5e2d9eda459f5f669f442b2cd948b41bd0f9b..cb46b2aaa227e1e8c4b10998d029021e6f7f22da 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go @@ -399,17 +399,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go index a0440c1d43be3b9757038590a819bc9dfa6f85f4..21c9baa6ab140aaa2d17c324b82eda4368b7a024 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -l32 -arm -tags linux,mipsle syscall_linux.go syscall_linux_mipsx.go +// go run mksyscall.go -l32 -arm -tags linux,mipsle syscall_linux.go syscall_linux_mipsx.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && mipsle @@ -344,17 +344,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -702,3 +691,14 @@ func setrlimit(resource int, rlim *rlimit32) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go index 5864b9ca64903564e0122568d12beff0760b19e8..02b8f08871e4ad328946f43951ae690af285e1e7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -b32 -tags linux,ppc syscall_linux.go syscall_linux_ppc.go +// go run mksyscall.go -b32 -tags linux,ppc syscall_linux.go syscall_linux_ppc.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && ppc @@ -409,17 +409,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -707,3 +696,14 @@ func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, f } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go index beeb49e34217a8623d54fb97c96ad0ceaee09c4b..ac8cb09ba35009dcaeec42400f2ef6c19828ba90 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -tags linux,ppc64 syscall_linux.go syscall_linux_ppc64x.go +// go run mksyscall.go -tags linux,ppc64 syscall_linux.go syscall_linux_ppc64x.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && ppc64 @@ -475,17 +475,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -753,3 +742,14 @@ func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, f } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go index 53139b82c7be1a49e803ab9ff1697d099316c04d..bd08d887a14005f6d187fc9a33bcb76d0ca8366e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -tags linux,ppc64le syscall_linux.go syscall_linux_ppc64x.go +// go run mksyscall.go -tags linux,ppc64le syscall_linux.go syscall_linux_ppc64x.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && ppc64le @@ -475,17 +475,6 @@ func Ustat(dev int, ubuf *Ustat_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -753,3 +742,14 @@ func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, f } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go index 63b393b8027d4c03d00e2e29d684e0359797a038..a834d217304241b908445daafbb5327cb4ce13e9 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go @@ -369,17 +369,6 @@ func Truncate(path string, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go index 202add37d10a544127ce0a5c6387204207e0a5a8..9e462a96fbe3a3ac746242341388d4ae73758d7d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -tags linux,s390x syscall_linux.go syscall_linux_s390x.go +// go run mksyscall.go -tags linux,s390x syscall_linux.go syscall_linux_s390x.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && s390x @@ -533,3 +533,14 @@ func kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, f } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go index 2ab268c3435930fc51b6e5efe36b958845552ffe..96d340242c405dc3c3001724cc0714a82ad75ea2 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -tags linux,sparc64 syscall_linux.go syscall_linux_sparc64.go +// go run mksyscall.go -tags linux,sparc64 syscall_linux.go syscall_linux_sparc64.go syscall_linux_alarm.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build linux && sparc64 @@ -455,17 +455,6 @@ func Truncate(path string, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0) fd = int(r0) @@ -697,3 +686,14 @@ func utimes(path string, times *[2]Timeval) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Alarm(seconds uint) (remaining uint, err error) { + r0, _, e1 := Syscall(SYS_ALARM, uintptr(seconds), 0, 0) + remaining = uint(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go index 4726ab30a8fa6586fb581584c53f625370cb1fc8..51d0c0742bfab903ae9ad4b94fde4617bad51ed3 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go @@ -351,18 +351,6 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (fd1 int, fd2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - fd1 = int(r0) - fd2 = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func pipe2(p *[2]_C_int, flags int) (err error) { _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go index fe71456dbc0f865be5f241cdd32f13f4ca90dc04..df2efb6db3fa6739287c462470aff3910ff108dd 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go @@ -351,18 +351,6 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (fd1 int, fd2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - fd1 = int(r0) - fd2 = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func pipe2(p *[2]_C_int, flags int) (err error) { _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go index 0b5b2f0143bea88fc032d7813e9f5f8212bcdfdc..c8536c2c9f09b37e5c01e66a00fe9eccb639839c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go @@ -351,18 +351,6 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (fd1 int, fd2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - fd1 = int(r0) - fd2 = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func pipe2(p *[2]_C_int, flags int) (err error) { _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go index bfca28648fb594940ee2fa6b827defbaf102bc2e..8b981bfc2eb957e33331e190f843115eb90cc4d2 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go @@ -351,18 +351,6 @@ func Munlockall() (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pipe() (fd1 int, fd2 int, err error) { - r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0) - fd1 = int(r0) - fd2 = int(r1) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func pipe2(p *[2]_C_int, flags int) (err error) { _, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index 31847d2305faedc8cb99c523faa02e3e698e9c2d..cac1f758bf7e08af728c34d2fa7dd270ecb4b225 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -445,4 +445,5 @@ const ( SYS_LANDLOCK_RESTRICT_SELF = 446 SYS_MEMFD_SECRET = 447 SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 3503cbbde385d04caeeea52a183f8806c4a153ff..f327e4a0bccbd97ab59fda66ca9ea519626c0522 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -367,4 +367,5 @@ const ( SYS_LANDLOCK_RESTRICT_SELF = 446 SYS_MEMFD_SECRET = 447 SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 5ecd24bf683c2bbaa45c5be05ad91b2d74d3e12c..fb06a08d4ee8f638f29744b61db65b15da5a969e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -409,4 +409,5 @@ const ( SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index 7e5c94cc7feac23bd98b15ff66bc6a253feabef3..58285646eb797138788f5eec9b034b35b0ab2bdc 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -312,4 +312,5 @@ const ( SYS_LANDLOCK_RESTRICT_SELF = 446 SYS_MEMFD_SECRET = 447 SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index e1e2a2bf59ed9aecb56e8f76ebd50d815161eb4a..3b0418e6894413d3164ac54e040bdff99d512a86 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -429,4 +429,5 @@ const ( SYS_LANDLOCK_ADD_RULE = 4445 SYS_LANDLOCK_RESTRICT_SELF = 4446 SYS_PROCESS_MRELEASE = 4448 + SYS_FUTEX_WAITV = 4449 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 7651915a3adc2c3fa707a7f7edd910fee4474a4f..314ebf166ab9cdb405edd4682456ecb1dcda8e6c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -359,4 +359,5 @@ const ( SYS_LANDLOCK_ADD_RULE = 5445 SYS_LANDLOCK_RESTRICT_SELF = 5446 SYS_PROCESS_MRELEASE = 5448 + SYS_FUTEX_WAITV = 5449 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index a26a2c050bcaab953c3ea28ec42269d27ec38ea4..b8fbb937a333c75df1ac16b106e6ddf96774d6bb 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -359,4 +359,5 @@ const ( SYS_LANDLOCK_ADD_RULE = 5445 SYS_LANDLOCK_RESTRICT_SELF = 5446 SYS_PROCESS_MRELEASE = 5448 + SYS_FUTEX_WAITV = 5449 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index fda9a6a991310e9a759e1b69f7bafa120f8a6aeb..ee309b2bac96080e3d9f844628d016daf3878fdc 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -429,4 +429,5 @@ const ( SYS_LANDLOCK_ADD_RULE = 4445 SYS_LANDLOCK_RESTRICT_SELF = 4446 SYS_PROCESS_MRELEASE = 4448 + SYS_FUTEX_WAITV = 4449 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index e8496150d41022814a03ba147ace0b83df29808b..ac3748104ed0303c03c942d255561e962a5321e0 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -436,4 +436,5 @@ const ( SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index 5ee0678a360c8b3af40a43e3b97dccf418609ba4..5aa472111041c5f2145578f385a4ffd7d936075e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -408,4 +408,5 @@ const ( SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index 29c0f9a39eadf62198b74f545aad7d529c99b3fc..0793ac1a65be1985ac860cd91ed0ec7ad4dbab2f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -408,4 +408,5 @@ const ( SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index 5c9a9a3b61c9f66eea7ab3bb475384e940829edc..a520962e3954721d561ba4972ba6caba99b76b4a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -310,4 +310,5 @@ const ( SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index 913f50f98b9098c8ea4cf8cb4f61f403f5ee9f51..d1738586b4f62f5f168e0eafd4ed9cbef5cc0d21 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -373,4 +373,5 @@ const ( SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 0de03a7227c3a49749f68b557657434cf4cc6261..dfd5660f9741fb27c8ed8d592b92ff567bb66ab4 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -387,4 +387,5 @@ const ( SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 SYS_PROCESS_MRELEASE = 448 + SYS_FUTEX_WAITV = 449 ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go index 37b521436bc2b7315880a5daf0f1fee19134f557..2c26466e07c7345d5c6120ceb20efd5c4dfd340e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -24,6 +24,11 @@ type ItimerSpec struct { Value Timespec } +type Itimerval struct { + Interval Timeval + Value Timeval +} + const ( TIME_OK = 0x0 TIME_INS = 0x1 @@ -867,6 +872,7 @@ const ( CTRL_CMD_NEWMCAST_GRP = 0x7 CTRL_CMD_DELMCAST_GRP = 0x8 CTRL_CMD_GETMCAST_GRP = 0x9 + CTRL_CMD_GETPOLICY = 0xa CTRL_ATTR_UNSPEC = 0x0 CTRL_ATTR_FAMILY_ID = 0x1 CTRL_ATTR_FAMILY_NAME = 0x2 @@ -875,12 +881,19 @@ const ( CTRL_ATTR_MAXATTR = 0x5 CTRL_ATTR_OPS = 0x6 CTRL_ATTR_MCAST_GROUPS = 0x7 + CTRL_ATTR_POLICY = 0x8 + CTRL_ATTR_OP_POLICY = 0x9 + CTRL_ATTR_OP = 0xa CTRL_ATTR_OP_UNSPEC = 0x0 CTRL_ATTR_OP_ID = 0x1 CTRL_ATTR_OP_FLAGS = 0x2 CTRL_ATTR_MCAST_GRP_UNSPEC = 0x0 CTRL_ATTR_MCAST_GRP_NAME = 0x1 CTRL_ATTR_MCAST_GRP_ID = 0x2 + CTRL_ATTR_POLICY_UNSPEC = 0x0 + CTRL_ATTR_POLICY_DO = 0x1 + CTRL_ATTR_POLICY_DUMP = 0x2 + CTRL_ATTR_POLICY_DUMP_MAX = 0x2 ) const ( @@ -1136,7 +1149,8 @@ const ( PERF_RECORD_BPF_EVENT = 0x12 PERF_RECORD_CGROUP = 0x13 PERF_RECORD_TEXT_POKE = 0x14 - PERF_RECORD_MAX = 0x15 + PERF_RECORD_AUX_OUTPUT_HW_ID = 0x15 + PERF_RECORD_MAX = 0x16 PERF_RECORD_KSYMBOL_TYPE_UNKNOWN = 0x0 PERF_RECORD_KSYMBOL_TYPE_BPF = 0x1 PERF_RECORD_KSYMBOL_TYPE_OOL = 0x2 @@ -1776,7 +1790,8 @@ const ( const ( NF_NETDEV_INGRESS = 0x0 - NF_NETDEV_NUMHOOKS = 0x1 + NF_NETDEV_EGRESS = 0x1 + NF_NETDEV_NUMHOOKS = 0x2 ) const ( @@ -3158,7 +3173,13 @@ const ( DEVLINK_ATTR_RELOAD_ACTION_INFO = 0xa2 DEVLINK_ATTR_RELOAD_ACTION_STATS = 0xa3 DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 0xa4 - DEVLINK_ATTR_MAX = 0xa9 + DEVLINK_ATTR_RATE_TYPE = 0xa5 + DEVLINK_ATTR_RATE_TX_SHARE = 0xa6 + DEVLINK_ATTR_RATE_TX_MAX = 0xa7 + DEVLINK_ATTR_RATE_NODE_NAME = 0xa8 + DEVLINK_ATTR_RATE_PARENT_NODE_NAME = 0xa9 + DEVLINK_ATTR_REGION_MAX_SNAPSHOTS = 0xaa + DEVLINK_ATTR_MAX = 0xaa DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 @@ -3455,7 +3476,14 @@ const ( ETHTOOL_MSG_CABLE_TEST_ACT = 0x1a ETHTOOL_MSG_CABLE_TEST_TDR_ACT = 0x1b ETHTOOL_MSG_TUNNEL_INFO_GET = 0x1c - ETHTOOL_MSG_USER_MAX = 0x21 + ETHTOOL_MSG_FEC_GET = 0x1d + ETHTOOL_MSG_FEC_SET = 0x1e + ETHTOOL_MSG_MODULE_EEPROM_GET = 0x1f + ETHTOOL_MSG_STATS_GET = 0x20 + ETHTOOL_MSG_PHC_VCLOCKS_GET = 0x21 + ETHTOOL_MSG_MODULE_GET = 0x22 + ETHTOOL_MSG_MODULE_SET = 0x23 + ETHTOOL_MSG_USER_MAX = 0x23 ETHTOOL_MSG_KERNEL_NONE = 0x0 ETHTOOL_MSG_STRSET_GET_REPLY = 0x1 ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2 @@ -3486,7 +3514,14 @@ const ( ETHTOOL_MSG_CABLE_TEST_NTF = 0x1b ETHTOOL_MSG_CABLE_TEST_TDR_NTF = 0x1c ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY = 0x1d - ETHTOOL_MSG_KERNEL_MAX = 0x22 + ETHTOOL_MSG_FEC_GET_REPLY = 0x1e + ETHTOOL_MSG_FEC_NTF = 0x1f + ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY = 0x20 + ETHTOOL_MSG_STATS_GET_REPLY = 0x21 + ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY = 0x22 + ETHTOOL_MSG_MODULE_GET_REPLY = 0x23 + ETHTOOL_MSG_MODULE_NTF = 0x24 + ETHTOOL_MSG_KERNEL_MAX = 0x24 ETHTOOL_A_HEADER_UNSPEC = 0x0 ETHTOOL_A_HEADER_DEV_INDEX = 0x1 ETHTOOL_A_HEADER_DEV_NAME = 0x2 @@ -3736,6 +3771,8 @@ const ( ETHTOOL_A_TUNNEL_INFO_MAX = 0x2 ) +const SPEED_UNKNOWN = -0x1 + type EthtoolDrvinfo struct { Cmd uint32 Driver [32]byte @@ -3968,3 +4005,1530 @@ type MountAttr struct { Propagation uint64 Userns_fd uint64 } + +const ( + WG_CMD_GET_DEVICE = 0x0 + WG_CMD_SET_DEVICE = 0x1 + WGDEVICE_F_REPLACE_PEERS = 0x1 + WGDEVICE_A_UNSPEC = 0x0 + WGDEVICE_A_IFINDEX = 0x1 + WGDEVICE_A_IFNAME = 0x2 + WGDEVICE_A_PRIVATE_KEY = 0x3 + WGDEVICE_A_PUBLIC_KEY = 0x4 + WGDEVICE_A_FLAGS = 0x5 + WGDEVICE_A_LISTEN_PORT = 0x6 + WGDEVICE_A_FWMARK = 0x7 + WGDEVICE_A_PEERS = 0x8 + WGPEER_F_REMOVE_ME = 0x1 + WGPEER_F_REPLACE_ALLOWEDIPS = 0x2 + WGPEER_F_UPDATE_ONLY = 0x4 + WGPEER_A_UNSPEC = 0x0 + WGPEER_A_PUBLIC_KEY = 0x1 + WGPEER_A_PRESHARED_KEY = 0x2 + WGPEER_A_FLAGS = 0x3 + WGPEER_A_ENDPOINT = 0x4 + WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL = 0x5 + WGPEER_A_LAST_HANDSHAKE_TIME = 0x6 + WGPEER_A_RX_BYTES = 0x7 + WGPEER_A_TX_BYTES = 0x8 + WGPEER_A_ALLOWEDIPS = 0x9 + WGPEER_A_PROTOCOL_VERSION = 0xa + WGALLOWEDIP_A_UNSPEC = 0x0 + WGALLOWEDIP_A_FAMILY = 0x1 + WGALLOWEDIP_A_IPADDR = 0x2 + WGALLOWEDIP_A_CIDR_MASK = 0x3 +) + +const ( + NL_ATTR_TYPE_INVALID = 0x0 + NL_ATTR_TYPE_FLAG = 0x1 + NL_ATTR_TYPE_U8 = 0x2 + NL_ATTR_TYPE_U16 = 0x3 + NL_ATTR_TYPE_U32 = 0x4 + NL_ATTR_TYPE_U64 = 0x5 + NL_ATTR_TYPE_S8 = 0x6 + NL_ATTR_TYPE_S16 = 0x7 + NL_ATTR_TYPE_S32 = 0x8 + NL_ATTR_TYPE_S64 = 0x9 + NL_ATTR_TYPE_BINARY = 0xa + NL_ATTR_TYPE_STRING = 0xb + NL_ATTR_TYPE_NUL_STRING = 0xc + NL_ATTR_TYPE_NESTED = 0xd + NL_ATTR_TYPE_NESTED_ARRAY = 0xe + NL_ATTR_TYPE_BITFIELD32 = 0xf + + NL_POLICY_TYPE_ATTR_UNSPEC = 0x0 + NL_POLICY_TYPE_ATTR_TYPE = 0x1 + NL_POLICY_TYPE_ATTR_MIN_VALUE_S = 0x2 + NL_POLICY_TYPE_ATTR_MAX_VALUE_S = 0x3 + NL_POLICY_TYPE_ATTR_MIN_VALUE_U = 0x4 + NL_POLICY_TYPE_ATTR_MAX_VALUE_U = 0x5 + NL_POLICY_TYPE_ATTR_MIN_LENGTH = 0x6 + NL_POLICY_TYPE_ATTR_MAX_LENGTH = 0x7 + NL_POLICY_TYPE_ATTR_POLICY_IDX = 0x8 + NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE = 0x9 + NL_POLICY_TYPE_ATTR_BITFIELD32_MASK = 0xa + NL_POLICY_TYPE_ATTR_PAD = 0xb + NL_POLICY_TYPE_ATTR_MASK = 0xc + NL_POLICY_TYPE_ATTR_MAX = 0xc +) + +type CANBitTiming struct { + Bitrate uint32 + Sample_point uint32 + Tq uint32 + Prop_seg uint32 + Phase_seg1 uint32 + Phase_seg2 uint32 + Sjw uint32 + Brp uint32 +} + +type CANBitTimingConst struct { + Name [16]uint8 + Tseg1_min uint32 + Tseg1_max uint32 + Tseg2_min uint32 + Tseg2_max uint32 + Sjw_max uint32 + Brp_min uint32 + Brp_max uint32 + Brp_inc uint32 +} + +type CANClock struct { + Freq uint32 +} + +type CANBusErrorCounters struct { + Txerr uint16 + Rxerr uint16 +} + +type CANCtrlMode struct { + Mask uint32 + Flags uint32 +} + +type CANDeviceStats struct { + Bus_error uint32 + Error_warning uint32 + Error_passive uint32 + Bus_off uint32 + Arbitration_lost uint32 + Restarts uint32 +} + +const ( + CAN_STATE_ERROR_ACTIVE = 0x0 + CAN_STATE_ERROR_WARNING = 0x1 + CAN_STATE_ERROR_PASSIVE = 0x2 + CAN_STATE_BUS_OFF = 0x3 + CAN_STATE_STOPPED = 0x4 + CAN_STATE_SLEEPING = 0x5 + CAN_STATE_MAX = 0x6 +) + +const ( + IFLA_CAN_UNSPEC = 0x0 + IFLA_CAN_BITTIMING = 0x1 + IFLA_CAN_BITTIMING_CONST = 0x2 + IFLA_CAN_CLOCK = 0x3 + IFLA_CAN_STATE = 0x4 + IFLA_CAN_CTRLMODE = 0x5 + IFLA_CAN_RESTART_MS = 0x6 + IFLA_CAN_RESTART = 0x7 + IFLA_CAN_BERR_COUNTER = 0x8 + IFLA_CAN_DATA_BITTIMING = 0x9 + IFLA_CAN_DATA_BITTIMING_CONST = 0xa + IFLA_CAN_TERMINATION = 0xb + IFLA_CAN_TERMINATION_CONST = 0xc + IFLA_CAN_BITRATE_CONST = 0xd + IFLA_CAN_DATA_BITRATE_CONST = 0xe + IFLA_CAN_BITRATE_MAX = 0xf +) + +type KCMAttach struct { + Fd int32 + Bpf_fd int32 +} + +type KCMUnattach struct { + Fd int32 +} + +type KCMClone struct { + Fd int32 +} + +const ( + NL80211_AC_BE = 0x2 + NL80211_AC_BK = 0x3 + NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED = 0x0 + NL80211_ACL_POLICY_DENY_UNLESS_LISTED = 0x1 + NL80211_AC_VI = 0x1 + NL80211_AC_VO = 0x0 + NL80211_ATTR_4ADDR = 0x53 + NL80211_ATTR_ACK = 0x5c + NL80211_ATTR_ACK_SIGNAL = 0x107 + NL80211_ATTR_ACL_POLICY = 0xa5 + NL80211_ATTR_ADMITTED_TIME = 0xd4 + NL80211_ATTR_AIRTIME_WEIGHT = 0x112 + NL80211_ATTR_AKM_SUITES = 0x4c + NL80211_ATTR_AP_ISOLATE = 0x60 + NL80211_ATTR_AUTH_DATA = 0x9c + NL80211_ATTR_AUTH_TYPE = 0x35 + NL80211_ATTR_BANDS = 0xef + NL80211_ATTR_BEACON_HEAD = 0xe + NL80211_ATTR_BEACON_INTERVAL = 0xc + NL80211_ATTR_BEACON_TAIL = 0xf + NL80211_ATTR_BG_SCAN_PERIOD = 0x98 + NL80211_ATTR_BSS_BASIC_RATES = 0x24 + NL80211_ATTR_BSS = 0x2f + NL80211_ATTR_BSS_CTS_PROT = 0x1c + NL80211_ATTR_BSS_HT_OPMODE = 0x6d + NL80211_ATTR_BSSID = 0xf5 + NL80211_ATTR_BSS_SELECT = 0xe3 + NL80211_ATTR_BSS_SHORT_PREAMBLE = 0x1d + NL80211_ATTR_BSS_SHORT_SLOT_TIME = 0x1e + NL80211_ATTR_CENTER_FREQ1 = 0xa0 + NL80211_ATTR_CENTER_FREQ1_OFFSET = 0x123 + NL80211_ATTR_CENTER_FREQ2 = 0xa1 + NL80211_ATTR_CHANNEL_WIDTH = 0x9f + NL80211_ATTR_CH_SWITCH_BLOCK_TX = 0xb8 + NL80211_ATTR_CH_SWITCH_COUNT = 0xb7 + NL80211_ATTR_CIPHER_SUITE_GROUP = 0x4a + NL80211_ATTR_CIPHER_SUITES = 0x39 + NL80211_ATTR_CIPHER_SUITES_PAIRWISE = 0x49 + NL80211_ATTR_CNTDWN_OFFS_BEACON = 0xba + NL80211_ATTR_CNTDWN_OFFS_PRESP = 0xbb + NL80211_ATTR_COALESCE_RULE = 0xb6 + NL80211_ATTR_COALESCE_RULE_CONDITION = 0x2 + NL80211_ATTR_COALESCE_RULE_DELAY = 0x1 + NL80211_ATTR_COALESCE_RULE_MAX = 0x3 + NL80211_ATTR_COALESCE_RULE_PKT_PATTERN = 0x3 + NL80211_ATTR_CONN_FAILED_REASON = 0x9b + NL80211_ATTR_CONTROL_PORT = 0x44 + NL80211_ATTR_CONTROL_PORT_ETHERTYPE = 0x66 + NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT = 0x67 + NL80211_ATTR_CONTROL_PORT_NO_PREAUTH = 0x11e + NL80211_ATTR_CONTROL_PORT_OVER_NL80211 = 0x108 + NL80211_ATTR_COOKIE = 0x58 + NL80211_ATTR_CQM_BEACON_LOSS_EVENT = 0x8 + NL80211_ATTR_CQM = 0x5e + NL80211_ATTR_CQM_MAX = 0x9 + NL80211_ATTR_CQM_PKT_LOSS_EVENT = 0x4 + NL80211_ATTR_CQM_RSSI_HYST = 0x2 + NL80211_ATTR_CQM_RSSI_LEVEL = 0x9 + NL80211_ATTR_CQM_RSSI_THOLD = 0x1 + NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT = 0x3 + NL80211_ATTR_CQM_TXE_INTVL = 0x7 + NL80211_ATTR_CQM_TXE_PKTS = 0x6 + NL80211_ATTR_CQM_TXE_RATE = 0x5 + NL80211_ATTR_CRIT_PROT_ID = 0xb3 + NL80211_ATTR_CSA_C_OFF_BEACON = 0xba + NL80211_ATTR_CSA_C_OFF_PRESP = 0xbb + NL80211_ATTR_CSA_C_OFFSETS_TX = 0xcd + NL80211_ATTR_CSA_IES = 0xb9 + NL80211_ATTR_DEVICE_AP_SME = 0x8d + NL80211_ATTR_DFS_CAC_TIME = 0x7 + NL80211_ATTR_DFS_REGION = 0x92 + NL80211_ATTR_DISABLE_HE = 0x12d + NL80211_ATTR_DISABLE_HT = 0x93 + NL80211_ATTR_DISABLE_VHT = 0xaf + NL80211_ATTR_DISCONNECTED_BY_AP = 0x47 + NL80211_ATTR_DONT_WAIT_FOR_ACK = 0x8e + NL80211_ATTR_DTIM_PERIOD = 0xd + NL80211_ATTR_DURATION = 0x57 + NL80211_ATTR_EXT_CAPA = 0xa9 + NL80211_ATTR_EXT_CAPA_MASK = 0xaa + NL80211_ATTR_EXTERNAL_AUTH_ACTION = 0x104 + NL80211_ATTR_EXTERNAL_AUTH_SUPPORT = 0x105 + NL80211_ATTR_EXT_FEATURES = 0xd9 + NL80211_ATTR_FEATURE_FLAGS = 0x8f + NL80211_ATTR_FILS_CACHE_ID = 0xfd + NL80211_ATTR_FILS_DISCOVERY = 0x126 + NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM = 0xfb + NL80211_ATTR_FILS_ERP_REALM = 0xfa + NL80211_ATTR_FILS_ERP_RRK = 0xfc + NL80211_ATTR_FILS_ERP_USERNAME = 0xf9 + NL80211_ATTR_FILS_KEK = 0xf2 + NL80211_ATTR_FILS_NONCES = 0xf3 + NL80211_ATTR_FRAME = 0x33 + NL80211_ATTR_FRAME_MATCH = 0x5b + NL80211_ATTR_FRAME_TYPE = 0x65 + NL80211_ATTR_FREQ_AFTER = 0x3b + NL80211_ATTR_FREQ_BEFORE = 0x3a + NL80211_ATTR_FREQ_FIXED = 0x3c + NL80211_ATTR_FREQ_RANGE_END = 0x3 + NL80211_ATTR_FREQ_RANGE_MAX_BW = 0x4 + NL80211_ATTR_FREQ_RANGE_START = 0x2 + NL80211_ATTR_FTM_RESPONDER = 0x10e + NL80211_ATTR_FTM_RESPONDER_STATS = 0x10f + NL80211_ATTR_GENERATION = 0x2e + NL80211_ATTR_HANDLE_DFS = 0xbf + NL80211_ATTR_HE_6GHZ_CAPABILITY = 0x125 + NL80211_ATTR_HE_BSS_COLOR = 0x11b + NL80211_ATTR_HE_CAPABILITY = 0x10d + NL80211_ATTR_HE_OBSS_PD = 0x117 + NL80211_ATTR_HIDDEN_SSID = 0x7e + NL80211_ATTR_HT_CAPABILITY = 0x1f + NL80211_ATTR_HT_CAPABILITY_MASK = 0x94 + NL80211_ATTR_IE_ASSOC_RESP = 0x80 + NL80211_ATTR_IE = 0x2a + NL80211_ATTR_IE_PROBE_RESP = 0x7f + NL80211_ATTR_IE_RIC = 0xb2 + NL80211_ATTR_IFACE_SOCKET_OWNER = 0xcc + NL80211_ATTR_IFINDEX = 0x3 + NL80211_ATTR_IFNAME = 0x4 + NL80211_ATTR_IFTYPE_AKM_SUITES = 0x11c + NL80211_ATTR_IFTYPE = 0x5 + NL80211_ATTR_IFTYPE_EXT_CAPA = 0xe6 + NL80211_ATTR_INACTIVITY_TIMEOUT = 0x96 + NL80211_ATTR_INTERFACE_COMBINATIONS = 0x78 + NL80211_ATTR_KEY_CIPHER = 0x9 + NL80211_ATTR_KEY = 0x50 + NL80211_ATTR_KEY_DATA = 0x7 + NL80211_ATTR_KEY_DEFAULT = 0xb + NL80211_ATTR_KEY_DEFAULT_MGMT = 0x28 + NL80211_ATTR_KEY_DEFAULT_TYPES = 0x6e + NL80211_ATTR_KEY_IDX = 0x8 + NL80211_ATTR_KEYS = 0x51 + NL80211_ATTR_KEY_SEQ = 0xa + NL80211_ATTR_KEY_TYPE = 0x37 + NL80211_ATTR_LOCAL_MESH_POWER_MODE = 0xa4 + NL80211_ATTR_LOCAL_STATE_CHANGE = 0x5f + NL80211_ATTR_MAC_ACL_MAX = 0xa7 + NL80211_ATTR_MAC_ADDRS = 0xa6 + NL80211_ATTR_MAC = 0x6 + NL80211_ATTR_MAC_HINT = 0xc8 + NL80211_ATTR_MAC_MASK = 0xd7 + NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca + NL80211_ATTR_MAX = 0x133 + NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4 + NL80211_ATTR_MAX_CSA_COUNTERS = 0xce + NL80211_ATTR_MAX_MATCH_SETS = 0x85 + NL80211_ATTR_MAX_NUM_PMKIDS = 0x56 + NL80211_ATTR_MAX_NUM_SCAN_SSIDS = 0x2b + NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS = 0xde + NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS = 0x7b + NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION = 0x6f + NL80211_ATTR_MAX_SCAN_IE_LEN = 0x38 + NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL = 0xdf + NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS = 0xe0 + NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN = 0x7c + NL80211_ATTR_MCAST_RATE = 0x6b + NL80211_ATTR_MDID = 0xb1 + NL80211_ATTR_MEASUREMENT_DURATION = 0xeb + NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY = 0xec + NL80211_ATTR_MESH_CONFIG = 0x23 + NL80211_ATTR_MESH_ID = 0x18 + NL80211_ATTR_MESH_PEER_AID = 0xed + NL80211_ATTR_MESH_SETUP = 0x70 + NL80211_ATTR_MGMT_SUBTYPE = 0x29 + NL80211_ATTR_MNTR_FLAGS = 0x17 + NL80211_ATTR_MPATH_INFO = 0x1b + NL80211_ATTR_MPATH_NEXT_HOP = 0x1a + NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED = 0xf4 + NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR = 0xe8 + NL80211_ATTR_MU_MIMO_GROUP_DATA = 0xe7 + NL80211_ATTR_NAN_FUNC = 0xf0 + NL80211_ATTR_NAN_MASTER_PREF = 0xee + NL80211_ATTR_NAN_MATCH = 0xf1 + NL80211_ATTR_NETNS_FD = 0xdb + NL80211_ATTR_NOACK_MAP = 0x95 + NL80211_ATTR_NSS = 0x106 + NL80211_ATTR_OFFCHANNEL_TX_OK = 0x6c + NL80211_ATTR_OPER_CLASS = 0xd6 + NL80211_ATTR_OPMODE_NOTIF = 0xc2 + NL80211_ATTR_P2P_CTWINDOW = 0xa2 + NL80211_ATTR_P2P_OPPPS = 0xa3 + NL80211_ATTR_PAD = 0xe5 + NL80211_ATTR_PBSS = 0xe2 + NL80211_ATTR_PEER_AID = 0xb5 + NL80211_ATTR_PEER_MEASUREMENTS = 0x111 + NL80211_ATTR_PID = 0x52 + NL80211_ATTR_PMK = 0xfe + NL80211_ATTR_PMKID = 0x55 + NL80211_ATTR_PMK_LIFETIME = 0x11f + NL80211_ATTR_PMKR0_NAME = 0x102 + NL80211_ATTR_PMK_REAUTH_THRESHOLD = 0x120 + NL80211_ATTR_PMKSA_CANDIDATE = 0x86 + NL80211_ATTR_PORT_AUTHORIZED = 0x103 + NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN = 0x5 + NL80211_ATTR_POWER_RULE_MAX_EIRP = 0x6 + NL80211_ATTR_PREV_BSSID = 0x4f + NL80211_ATTR_PRIVACY = 0x46 + NL80211_ATTR_PROBE_RESP = 0x91 + NL80211_ATTR_PROBE_RESP_OFFLOAD = 0x90 + NL80211_ATTR_PROTOCOL_FEATURES = 0xad + NL80211_ATTR_PS_STATE = 0x5d + NL80211_ATTR_QOS_MAP = 0xc7 + NL80211_ATTR_RADAR_EVENT = 0xa8 + NL80211_ATTR_REASON_CODE = 0x36 + NL80211_ATTR_RECEIVE_MULTICAST = 0x121 + NL80211_ATTR_RECONNECT_REQUESTED = 0x12b + NL80211_ATTR_REG_ALPHA2 = 0x21 + NL80211_ATTR_REG_INDOOR = 0xdd + NL80211_ATTR_REG_INITIATOR = 0x30 + NL80211_ATTR_REG_RULE_FLAGS = 0x1 + NL80211_ATTR_REG_RULES = 0x22 + NL80211_ATTR_REG_TYPE = 0x31 + NL80211_ATTR_REKEY_DATA = 0x7a + NL80211_ATTR_REQ_IE = 0x4d + NL80211_ATTR_RESP_IE = 0x4e + NL80211_ATTR_ROAM_SUPPORT = 0x83 + NL80211_ATTR_RX_FRAME_TYPES = 0x64 + NL80211_ATTR_RXMGMT_FLAGS = 0xbc + NL80211_ATTR_RX_SIGNAL_DBM = 0x97 + NL80211_ATTR_S1G_CAPABILITY = 0x128 + NL80211_ATTR_S1G_CAPABILITY_MASK = 0x129 + NL80211_ATTR_SAE_DATA = 0x9c + NL80211_ATTR_SAE_PASSWORD = 0x115 + NL80211_ATTR_SAE_PWE = 0x12a + NL80211_ATTR_SAR_SPEC = 0x12c + NL80211_ATTR_SCAN_FLAGS = 0x9e + NL80211_ATTR_SCAN_FREQ_KHZ = 0x124 + NL80211_ATTR_SCAN_FREQUENCIES = 0x2c + NL80211_ATTR_SCAN_GENERATION = 0x2e + NL80211_ATTR_SCAN_SSIDS = 0x2d + NL80211_ATTR_SCAN_START_TIME_TSF_BSSID = 0xea + NL80211_ATTR_SCAN_START_TIME_TSF = 0xe9 + NL80211_ATTR_SCAN_SUPP_RATES = 0x7d + NL80211_ATTR_SCHED_SCAN_DELAY = 0xdc + NL80211_ATTR_SCHED_SCAN_INTERVAL = 0x77 + NL80211_ATTR_SCHED_SCAN_MATCH = 0x84 + NL80211_ATTR_SCHED_SCAN_MATCH_SSID = 0x1 + NL80211_ATTR_SCHED_SCAN_MAX_REQS = 0x100 + NL80211_ATTR_SCHED_SCAN_MULTI = 0xff + NL80211_ATTR_SCHED_SCAN_PLANS = 0xe1 + NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI = 0xf6 + NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST = 0xf7 + NL80211_ATTR_SMPS_MODE = 0xd5 + NL80211_ATTR_SOCKET_OWNER = 0xcc + NL80211_ATTR_SOFTWARE_IFTYPES = 0x79 + NL80211_ATTR_SPLIT_WIPHY_DUMP = 0xae + NL80211_ATTR_SSID = 0x34 + NL80211_ATTR_STA_AID = 0x10 + NL80211_ATTR_STA_CAPABILITY = 0xab + NL80211_ATTR_STA_EXT_CAPABILITY = 0xac + NL80211_ATTR_STA_FLAGS2 = 0x43 + NL80211_ATTR_STA_FLAGS = 0x11 + NL80211_ATTR_STA_INFO = 0x15 + NL80211_ATTR_STA_LISTEN_INTERVAL = 0x12 + NL80211_ATTR_STA_PLINK_ACTION = 0x19 + NL80211_ATTR_STA_PLINK_STATE = 0x74 + NL80211_ATTR_STA_SUPPORTED_CHANNELS = 0xbd + NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES = 0xbe + NL80211_ATTR_STA_SUPPORTED_RATES = 0x13 + NL80211_ATTR_STA_SUPPORT_P2P_PS = 0xe4 + NL80211_ATTR_STATUS_CODE = 0x48 + NL80211_ATTR_STA_TX_POWER = 0x114 + NL80211_ATTR_STA_TX_POWER_SETTING = 0x113 + NL80211_ATTR_STA_VLAN = 0x14 + NL80211_ATTR_STA_WME = 0x81 + NL80211_ATTR_SUPPORT_10_MHZ = 0xc1 + NL80211_ATTR_SUPPORT_5_MHZ = 0xc0 + NL80211_ATTR_SUPPORT_AP_UAPSD = 0x82 + NL80211_ATTR_SUPPORTED_COMMANDS = 0x32 + NL80211_ATTR_SUPPORTED_IFTYPES = 0x20 + NL80211_ATTR_SUPPORT_IBSS_RSN = 0x68 + NL80211_ATTR_SUPPORT_MESH_AUTH = 0x73 + NL80211_ATTR_SURVEY_INFO = 0x54 + NL80211_ATTR_SURVEY_RADIO_STATS = 0xda + NL80211_ATTR_TDLS_ACTION = 0x88 + NL80211_ATTR_TDLS_DIALOG_TOKEN = 0x89 + NL80211_ATTR_TDLS_EXTERNAL_SETUP = 0x8c + NL80211_ATTR_TDLS_INITIATOR = 0xcf + NL80211_ATTR_TDLS_OPERATION = 0x8a + NL80211_ATTR_TDLS_PEER_CAPABILITY = 0xcb + NL80211_ATTR_TDLS_SUPPORT = 0x8b + NL80211_ATTR_TESTDATA = 0x45 + NL80211_ATTR_TID_CONFIG = 0x11d + NL80211_ATTR_TIMED_OUT = 0x41 + NL80211_ATTR_TIMEOUT = 0x110 + NL80211_ATTR_TIMEOUT_REASON = 0xf8 + NL80211_ATTR_TSID = 0xd2 + NL80211_ATTR_TWT_RESPONDER = 0x116 + NL80211_ATTR_TX_FRAME_TYPES = 0x63 + NL80211_ATTR_TX_NO_CCK_RATE = 0x87 + NL80211_ATTR_TXQ_LIMIT = 0x10a + NL80211_ATTR_TXQ_MEMORY_LIMIT = 0x10b + NL80211_ATTR_TXQ_QUANTUM = 0x10c + NL80211_ATTR_TXQ_STATS = 0x109 + NL80211_ATTR_TX_RATES = 0x5a + NL80211_ATTR_UNSOL_BCAST_PROBE_RESP = 0x127 + NL80211_ATTR_UNSPEC = 0x0 + NL80211_ATTR_USE_MFP = 0x42 + NL80211_ATTR_USER_PRIO = 0xd3 + NL80211_ATTR_USER_REG_HINT_TYPE = 0x9a + NL80211_ATTR_USE_RRM = 0xd0 + NL80211_ATTR_VENDOR_DATA = 0xc5 + NL80211_ATTR_VENDOR_EVENTS = 0xc6 + NL80211_ATTR_VENDOR_ID = 0xc3 + NL80211_ATTR_VENDOR_SUBCMD = 0xc4 + NL80211_ATTR_VHT_CAPABILITY = 0x9d + NL80211_ATTR_VHT_CAPABILITY_MASK = 0xb0 + NL80211_ATTR_VLAN_ID = 0x11a + NL80211_ATTR_WANT_1X_4WAY_HS = 0x101 + NL80211_ATTR_WDEV = 0x99 + NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX = 0x72 + NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX = 0x71 + NL80211_ATTR_WIPHY_ANTENNA_RX = 0x6a + NL80211_ATTR_WIPHY_ANTENNA_TX = 0x69 + NL80211_ATTR_WIPHY_BANDS = 0x16 + NL80211_ATTR_WIPHY_CHANNEL_TYPE = 0x27 + NL80211_ATTR_WIPHY = 0x1 + NL80211_ATTR_WIPHY_COVERAGE_CLASS = 0x59 + NL80211_ATTR_WIPHY_DYN_ACK = 0xd1 + NL80211_ATTR_WIPHY_EDMG_BW_CONFIG = 0x119 + NL80211_ATTR_WIPHY_EDMG_CHANNELS = 0x118 + NL80211_ATTR_WIPHY_FRAG_THRESHOLD = 0x3f + NL80211_ATTR_WIPHY_FREQ = 0x26 + NL80211_ATTR_WIPHY_FREQ_HINT = 0xc9 + NL80211_ATTR_WIPHY_FREQ_OFFSET = 0x122 + NL80211_ATTR_WIPHY_NAME = 0x2 + NL80211_ATTR_WIPHY_RETRY_LONG = 0x3e + NL80211_ATTR_WIPHY_RETRY_SHORT = 0x3d + NL80211_ATTR_WIPHY_RTS_THRESHOLD = 0x40 + NL80211_ATTR_WIPHY_SELF_MANAGED_REG = 0xd8 + NL80211_ATTR_WIPHY_TX_POWER_LEVEL = 0x62 + NL80211_ATTR_WIPHY_TX_POWER_SETTING = 0x61 + NL80211_ATTR_WIPHY_TXQ_PARAMS = 0x25 + NL80211_ATTR_WOWLAN_TRIGGERS = 0x75 + NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED = 0x76 + NL80211_ATTR_WPA_VERSIONS = 0x4b + NL80211_AUTHTYPE_AUTOMATIC = 0x8 + NL80211_AUTHTYPE_FILS_PK = 0x7 + NL80211_AUTHTYPE_FILS_SK = 0x5 + NL80211_AUTHTYPE_FILS_SK_PFS = 0x6 + NL80211_AUTHTYPE_FT = 0x2 + NL80211_AUTHTYPE_MAX = 0x7 + NL80211_AUTHTYPE_NETWORK_EAP = 0x3 + NL80211_AUTHTYPE_OPEN_SYSTEM = 0x0 + NL80211_AUTHTYPE_SAE = 0x4 + NL80211_AUTHTYPE_SHARED_KEY = 0x1 + NL80211_BAND_2GHZ = 0x0 + NL80211_BAND_5GHZ = 0x1 + NL80211_BAND_60GHZ = 0x2 + NL80211_BAND_6GHZ = 0x3 + NL80211_BAND_ATTR_EDMG_BW_CONFIG = 0xb + NL80211_BAND_ATTR_EDMG_CHANNELS = 0xa + NL80211_BAND_ATTR_FREQS = 0x1 + NL80211_BAND_ATTR_HT_AMPDU_DENSITY = 0x6 + NL80211_BAND_ATTR_HT_AMPDU_FACTOR = 0x5 + NL80211_BAND_ATTR_HT_CAPA = 0x4 + NL80211_BAND_ATTR_HT_MCS_SET = 0x3 + NL80211_BAND_ATTR_IFTYPE_DATA = 0x9 + NL80211_BAND_ATTR_MAX = 0xb + NL80211_BAND_ATTR_RATES = 0x2 + NL80211_BAND_ATTR_VHT_CAPA = 0x8 + NL80211_BAND_ATTR_VHT_MCS_SET = 0x7 + NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA = 0x6 + NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC = 0x2 + NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET = 0x4 + NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY = 0x3 + NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE = 0x5 + NL80211_BAND_IFTYPE_ATTR_IFTYPES = 0x1 + NL80211_BAND_IFTYPE_ATTR_MAX = 0x7 + NL80211_BAND_S1GHZ = 0x4 + NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE = 0x2 + NL80211_BITRATE_ATTR_MAX = 0x2 + NL80211_BITRATE_ATTR_RATE = 0x1 + NL80211_BSS_BEACON_IES = 0xb + NL80211_BSS_BEACON_INTERVAL = 0x4 + NL80211_BSS_BEACON_TSF = 0xd + NL80211_BSS_BSSID = 0x1 + NL80211_BSS_CAPABILITY = 0x5 + NL80211_BSS_CHAIN_SIGNAL = 0x13 + NL80211_BSS_CHAN_WIDTH_10 = 0x1 + NL80211_BSS_CHAN_WIDTH_1 = 0x3 + NL80211_BSS_CHAN_WIDTH_20 = 0x0 + NL80211_BSS_CHAN_WIDTH_2 = 0x4 + NL80211_BSS_CHAN_WIDTH_5 = 0x2 + NL80211_BSS_CHAN_WIDTH = 0xc + NL80211_BSS_FREQUENCY = 0x2 + NL80211_BSS_FREQUENCY_OFFSET = 0x14 + NL80211_BSS_INFORMATION_ELEMENTS = 0x6 + NL80211_BSS_LAST_SEEN_BOOTTIME = 0xf + NL80211_BSS_MAX = 0x14 + NL80211_BSS_PAD = 0x10 + NL80211_BSS_PARENT_BSSID = 0x12 + NL80211_BSS_PARENT_TSF = 0x11 + NL80211_BSS_PRESP_DATA = 0xe + NL80211_BSS_SEEN_MS_AGO = 0xa + NL80211_BSS_SELECT_ATTR_BAND_PREF = 0x2 + NL80211_BSS_SELECT_ATTR_MAX = 0x3 + NL80211_BSS_SELECT_ATTR_RSSI_ADJUST = 0x3 + NL80211_BSS_SELECT_ATTR_RSSI = 0x1 + NL80211_BSS_SIGNAL_MBM = 0x7 + NL80211_BSS_SIGNAL_UNSPEC = 0x8 + NL80211_BSS_STATUS_ASSOCIATED = 0x1 + NL80211_BSS_STATUS_AUTHENTICATED = 0x0 + NL80211_BSS_STATUS = 0x9 + NL80211_BSS_STATUS_IBSS_JOINED = 0x2 + NL80211_BSS_TSF = 0x3 + NL80211_CHAN_HT20 = 0x1 + NL80211_CHAN_HT40MINUS = 0x2 + NL80211_CHAN_HT40PLUS = 0x3 + NL80211_CHAN_NO_HT = 0x0 + NL80211_CHAN_WIDTH_10 = 0x7 + NL80211_CHAN_WIDTH_160 = 0x5 + NL80211_CHAN_WIDTH_16 = 0xc + NL80211_CHAN_WIDTH_1 = 0x8 + NL80211_CHAN_WIDTH_20 = 0x1 + NL80211_CHAN_WIDTH_20_NOHT = 0x0 + NL80211_CHAN_WIDTH_2 = 0x9 + NL80211_CHAN_WIDTH_40 = 0x2 + NL80211_CHAN_WIDTH_4 = 0xa + NL80211_CHAN_WIDTH_5 = 0x6 + NL80211_CHAN_WIDTH_80 = 0x3 + NL80211_CHAN_WIDTH_80P80 = 0x4 + NL80211_CHAN_WIDTH_8 = 0xb + NL80211_CMD_ABORT_SCAN = 0x72 + NL80211_CMD_ACTION = 0x3b + NL80211_CMD_ACTION_TX_STATUS = 0x3c + NL80211_CMD_ADD_NAN_FUNCTION = 0x75 + NL80211_CMD_ADD_TX_TS = 0x69 + NL80211_CMD_ASSOCIATE = 0x26 + NL80211_CMD_AUTHENTICATE = 0x25 + NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL = 0x38 + NL80211_CMD_CHANGE_NAN_CONFIG = 0x77 + NL80211_CMD_CHANNEL_SWITCH = 0x66 + NL80211_CMD_CH_SWITCH_NOTIFY = 0x58 + NL80211_CMD_CH_SWITCH_STARTED_NOTIFY = 0x6e + NL80211_CMD_CONNECT = 0x2e + NL80211_CMD_CONN_FAILED = 0x5b + NL80211_CMD_CONTROL_PORT_FRAME = 0x81 + NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS = 0x8b + NL80211_CMD_CRIT_PROTOCOL_START = 0x62 + NL80211_CMD_CRIT_PROTOCOL_STOP = 0x63 + NL80211_CMD_DEAUTHENTICATE = 0x27 + NL80211_CMD_DEL_BEACON = 0x10 + NL80211_CMD_DEL_INTERFACE = 0x8 + NL80211_CMD_DEL_KEY = 0xc + NL80211_CMD_DEL_MPATH = 0x18 + NL80211_CMD_DEL_NAN_FUNCTION = 0x76 + NL80211_CMD_DEL_PMK = 0x7c + NL80211_CMD_DEL_PMKSA = 0x35 + NL80211_CMD_DEL_STATION = 0x14 + NL80211_CMD_DEL_TX_TS = 0x6a + NL80211_CMD_DEL_WIPHY = 0x4 + NL80211_CMD_DISASSOCIATE = 0x28 + NL80211_CMD_DISCONNECT = 0x30 + NL80211_CMD_EXTERNAL_AUTH = 0x7f + NL80211_CMD_FLUSH_PMKSA = 0x36 + NL80211_CMD_FRAME = 0x3b + NL80211_CMD_FRAME_TX_STATUS = 0x3c + NL80211_CMD_FRAME_WAIT_CANCEL = 0x43 + NL80211_CMD_FT_EVENT = 0x61 + NL80211_CMD_GET_BEACON = 0xd + NL80211_CMD_GET_COALESCE = 0x64 + NL80211_CMD_GET_FTM_RESPONDER_STATS = 0x82 + NL80211_CMD_GET_INTERFACE = 0x5 + NL80211_CMD_GET_KEY = 0x9 + NL80211_CMD_GET_MESH_CONFIG = 0x1c + NL80211_CMD_GET_MESH_PARAMS = 0x1c + NL80211_CMD_GET_MPATH = 0x15 + NL80211_CMD_GET_MPP = 0x6b + NL80211_CMD_GET_POWER_SAVE = 0x3e + NL80211_CMD_GET_PROTOCOL_FEATURES = 0x5f + NL80211_CMD_GET_REG = 0x1f + NL80211_CMD_GET_SCAN = 0x20 + NL80211_CMD_GET_STATION = 0x11 + NL80211_CMD_GET_SURVEY = 0x32 + NL80211_CMD_GET_WIPHY = 0x1 + NL80211_CMD_GET_WOWLAN = 0x49 + NL80211_CMD_JOIN_IBSS = 0x2b + NL80211_CMD_JOIN_MESH = 0x44 + NL80211_CMD_JOIN_OCB = 0x6c + NL80211_CMD_LEAVE_IBSS = 0x2c + NL80211_CMD_LEAVE_MESH = 0x45 + NL80211_CMD_LEAVE_OCB = 0x6d + NL80211_CMD_MAX = 0x92 + NL80211_CMD_MICHAEL_MIC_FAILURE = 0x29 + NL80211_CMD_NAN_MATCH = 0x78 + NL80211_CMD_NEW_BEACON = 0xf + NL80211_CMD_NEW_INTERFACE = 0x7 + NL80211_CMD_NEW_KEY = 0xb + NL80211_CMD_NEW_MPATH = 0x17 + NL80211_CMD_NEW_PEER_CANDIDATE = 0x48 + NL80211_CMD_NEW_SCAN_RESULTS = 0x22 + NL80211_CMD_NEW_STATION = 0x13 + NL80211_CMD_NEW_SURVEY_RESULTS = 0x33 + NL80211_CMD_NEW_WIPHY = 0x3 + NL80211_CMD_NOTIFY_CQM = 0x40 + NL80211_CMD_NOTIFY_RADAR = 0x86 + NL80211_CMD_PEER_MEASUREMENT_COMPLETE = 0x85 + NL80211_CMD_PEER_MEASUREMENT_RESULT = 0x84 + NL80211_CMD_PEER_MEASUREMENT_START = 0x83 + NL80211_CMD_PMKSA_CANDIDATE = 0x50 + NL80211_CMD_PORT_AUTHORIZED = 0x7d + NL80211_CMD_PROBE_CLIENT = 0x54 + NL80211_CMD_PROBE_MESH_LINK = 0x88 + NL80211_CMD_RADAR_DETECT = 0x5e + NL80211_CMD_REG_BEACON_HINT = 0x2a + NL80211_CMD_REG_CHANGE = 0x24 + NL80211_CMD_REGISTER_ACTION = 0x3a + NL80211_CMD_REGISTER_BEACONS = 0x55 + NL80211_CMD_REGISTER_FRAME = 0x3a + NL80211_CMD_RELOAD_REGDB = 0x7e + NL80211_CMD_REMAIN_ON_CHANNEL = 0x37 + NL80211_CMD_REQ_SET_REG = 0x1b + NL80211_CMD_ROAM = 0x2f + NL80211_CMD_SCAN_ABORTED = 0x23 + NL80211_CMD_SCHED_SCAN_RESULTS = 0x4d + NL80211_CMD_SCHED_SCAN_STOPPED = 0x4e + NL80211_CMD_SET_BEACON = 0xe + NL80211_CMD_SET_BSS = 0x19 + NL80211_CMD_SET_CHANNEL = 0x41 + NL80211_CMD_SET_COALESCE = 0x65 + NL80211_CMD_SET_CQM = 0x3f + NL80211_CMD_SET_INTERFACE = 0x6 + NL80211_CMD_SET_KEY = 0xa + NL80211_CMD_SET_MAC_ACL = 0x5d + NL80211_CMD_SET_MCAST_RATE = 0x5c + NL80211_CMD_SET_MESH_CONFIG = 0x1d + NL80211_CMD_SET_MESH_PARAMS = 0x1d + NL80211_CMD_SET_MGMT_EXTRA_IE = 0x1e + NL80211_CMD_SET_MPATH = 0x16 + NL80211_CMD_SET_MULTICAST_TO_UNICAST = 0x79 + NL80211_CMD_SET_NOACK_MAP = 0x57 + NL80211_CMD_SET_PMK = 0x7b + NL80211_CMD_SET_PMKSA = 0x34 + NL80211_CMD_SET_POWER_SAVE = 0x3d + NL80211_CMD_SET_QOS_MAP = 0x68 + NL80211_CMD_SET_REG = 0x1a + NL80211_CMD_SET_REKEY_OFFLOAD = 0x4f + NL80211_CMD_SET_SAR_SPECS = 0x8c + NL80211_CMD_SET_STATION = 0x12 + NL80211_CMD_SET_TID_CONFIG = 0x89 + NL80211_CMD_SET_TX_BITRATE_MASK = 0x39 + NL80211_CMD_SET_WDS_PEER = 0x42 + NL80211_CMD_SET_WIPHY = 0x2 + NL80211_CMD_SET_WIPHY_NETNS = 0x31 + NL80211_CMD_SET_WOWLAN = 0x4a + NL80211_CMD_STA_OPMODE_CHANGED = 0x80 + NL80211_CMD_START_AP = 0xf + NL80211_CMD_START_NAN = 0x73 + NL80211_CMD_START_P2P_DEVICE = 0x59 + NL80211_CMD_START_SCHED_SCAN = 0x4b + NL80211_CMD_STOP_AP = 0x10 + NL80211_CMD_STOP_NAN = 0x74 + NL80211_CMD_STOP_P2P_DEVICE = 0x5a + NL80211_CMD_STOP_SCHED_SCAN = 0x4c + NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH = 0x70 + NL80211_CMD_TDLS_CHANNEL_SWITCH = 0x6f + NL80211_CMD_TDLS_MGMT = 0x52 + NL80211_CMD_TDLS_OPER = 0x51 + NL80211_CMD_TESTMODE = 0x2d + NL80211_CMD_TRIGGER_SCAN = 0x21 + NL80211_CMD_UNEXPECTED_4ADDR_FRAME = 0x56 + NL80211_CMD_UNEXPECTED_FRAME = 0x53 + NL80211_CMD_UNPROT_BEACON = 0x8a + NL80211_CMD_UNPROT_DEAUTHENTICATE = 0x46 + NL80211_CMD_UNPROT_DISASSOCIATE = 0x47 + NL80211_CMD_UNSPEC = 0x0 + NL80211_CMD_UPDATE_CONNECT_PARAMS = 0x7a + NL80211_CMD_UPDATE_FT_IES = 0x60 + NL80211_CMD_UPDATE_OWE_INFO = 0x87 + NL80211_CMD_VENDOR = 0x67 + NL80211_CMD_WIPHY_REG_CHANGE = 0x71 + NL80211_COALESCE_CONDITION_MATCH = 0x0 + NL80211_COALESCE_CONDITION_NO_MATCH = 0x1 + NL80211_CONN_FAIL_BLOCKED_CLIENT = 0x1 + NL80211_CONN_FAIL_MAX_CLIENTS = 0x0 + NL80211_CQM_RSSI_BEACON_LOSS_EVENT = 0x2 + NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH = 0x1 + NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW = 0x0 + NL80211_CQM_TXE_MAX_INTVL = 0x708 + NL80211_CRIT_PROTO_APIPA = 0x3 + NL80211_CRIT_PROTO_DHCP = 0x1 + NL80211_CRIT_PROTO_EAPOL = 0x2 + NL80211_CRIT_PROTO_MAX_DURATION = 0x1388 + NL80211_CRIT_PROTO_UNSPEC = 0x0 + NL80211_DFS_AVAILABLE = 0x2 + NL80211_DFS_ETSI = 0x2 + NL80211_DFS_FCC = 0x1 + NL80211_DFS_JP = 0x3 + NL80211_DFS_UNAVAILABLE = 0x1 + NL80211_DFS_UNSET = 0x0 + NL80211_DFS_USABLE = 0x0 + NL80211_EDMG_BW_CONFIG_MAX = 0xf + NL80211_EDMG_BW_CONFIG_MIN = 0x4 + NL80211_EDMG_CHANNELS_MAX = 0x3c + NL80211_EDMG_CHANNELS_MIN = 0x1 + NL80211_EXTERNAL_AUTH_ABORT = 0x1 + NL80211_EXTERNAL_AUTH_START = 0x0 + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK = 0x32 + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X = 0x10 + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK = 0xf + NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP = 0x12 + NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT = 0x1b + NL80211_EXT_FEATURE_AIRTIME_FAIRNESS = 0x21 + NL80211_EXT_FEATURE_AP_PMKSA_CACHING = 0x22 + NL80211_EXT_FEATURE_AQL = 0x28 + NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT = 0x2e + NL80211_EXT_FEATURE_BEACON_PROTECTION = 0x29 + NL80211_EXT_FEATURE_BEACON_RATE_HE = 0x36 + NL80211_EXT_FEATURE_BEACON_RATE_HT = 0x7 + NL80211_EXT_FEATURE_BEACON_RATE_LEGACY = 0x6 + NL80211_EXT_FEATURE_BEACON_RATE_VHT = 0x8 + NL80211_EXT_FEATURE_BSS_PARENT_TSF = 0x4 + NL80211_EXT_FEATURE_CAN_REPLACE_PTK0 = 0x1f + NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH = 0x2a + NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211 = 0x1a + NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS = 0x30 + NL80211_EXT_FEATURE_CQM_RSSI_LIST = 0xd + NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT = 0x1b + NL80211_EXT_FEATURE_DEL_IBSS_STA = 0x2c + NL80211_EXT_FEATURE_DFS_OFFLOAD = 0x19 + NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER = 0x20 + NL80211_EXT_FEATURE_EXT_KEY_ID = 0x24 + NL80211_EXT_FEATURE_FILS_DISCOVERY = 0x34 + NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME = 0x11 + NL80211_EXT_FEATURE_FILS_SK_OFFLOAD = 0xe + NL80211_EXT_FEATURE_FILS_STA = 0x9 + NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN = 0x18 + NL80211_EXT_FEATURE_LOW_POWER_SCAN = 0x17 + NL80211_EXT_FEATURE_LOW_SPAN_SCAN = 0x16 + NL80211_EXT_FEATURE_MFP_OPTIONAL = 0x15 + NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA = 0xa + NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED = 0xb + NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS = 0x2d + NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER = 0x2 + NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = 0x14 + NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE = 0x13 + NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION = 0x31 + NL80211_EXT_FEATURE_PROTECTED_TWT = 0x2b + NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE = 0x39 + NL80211_EXT_FEATURE_RRM = 0x1 + NL80211_EXT_FEATURE_SAE_OFFLOAD_AP = 0x33 + NL80211_EXT_FEATURE_SAE_OFFLOAD = 0x26 + NL80211_EXT_FEATURE_SCAN_FREQ_KHZ = 0x2f + NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT = 0x1e + NL80211_EXT_FEATURE_SCAN_RANDOM_SN = 0x1d + NL80211_EXT_FEATURE_SCAN_START_TIME = 0x3 + NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD = 0x23 + NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI = 0xc + NL80211_EXT_FEATURE_SECURE_LTF = 0x37 + NL80211_EXT_FEATURE_SECURE_RTT = 0x38 + NL80211_EXT_FEATURE_SET_SCAN_DWELL = 0x5 + NL80211_EXT_FEATURE_STA_TX_PWR = 0x25 + NL80211_EXT_FEATURE_TXQS = 0x1c + NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP = 0x35 + NL80211_EXT_FEATURE_VHT_IBSS = 0x0 + NL80211_EXT_FEATURE_VLAN_OFFLOAD = 0x27 + NL80211_FEATURE_ACKTO_ESTIMATION = 0x800000 + NL80211_FEATURE_ACTIVE_MONITOR = 0x20000 + NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 0x4000 + NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE = 0x40000 + NL80211_FEATURE_AP_SCAN = 0x100 + NL80211_FEATURE_CELL_BASE_REG_HINTS = 0x8 + NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES = 0x80000 + NL80211_FEATURE_DYNAMIC_SMPS = 0x2000000 + NL80211_FEATURE_FULL_AP_CLIENT_STATE = 0x8000 + NL80211_FEATURE_HT_IBSS = 0x2 + NL80211_FEATURE_INACTIVITY_TIMER = 0x4 + NL80211_FEATURE_LOW_PRIORITY_SCAN = 0x40 + NL80211_FEATURE_MAC_ON_CREATE = 0x8000000 + NL80211_FEATURE_ND_RANDOM_MAC_ADDR = 0x80000000 + NL80211_FEATURE_NEED_OBSS_SCAN = 0x400 + NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 0x10 + NL80211_FEATURE_P2P_GO_CTWIN = 0x800 + NL80211_FEATURE_P2P_GO_OPPPS = 0x1000 + NL80211_FEATURE_QUIET = 0x200000 + NL80211_FEATURE_SAE = 0x20 + NL80211_FEATURE_SCAN_FLUSH = 0x80 + NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR = 0x20000000 + NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR = 0x40000000 + NL80211_FEATURE_SK_TX_STATUS = 0x1 + NL80211_FEATURE_STATIC_SMPS = 0x1000000 + NL80211_FEATURE_SUPPORTS_WMM_ADMISSION = 0x4000000 + NL80211_FEATURE_TDLS_CHANNEL_SWITCH = 0x10000000 + NL80211_FEATURE_TX_POWER_INSERTION = 0x400000 + NL80211_FEATURE_USERSPACE_MPM = 0x10000 + NL80211_FEATURE_VIF_TXPOWER = 0x200 + NL80211_FEATURE_WFA_TPC_IE_IN_PROBES = 0x100000 + NL80211_FILS_DISCOVERY_ATTR_INT_MAX = 0x2 + NL80211_FILS_DISCOVERY_ATTR_INT_MIN = 0x1 + NL80211_FILS_DISCOVERY_ATTR_MAX = 0x3 + NL80211_FILS_DISCOVERY_ATTR_TMPL = 0x3 + NL80211_FILS_DISCOVERY_TMPL_MIN_LEN = 0x2a + NL80211_FREQUENCY_ATTR_16MHZ = 0x19 + NL80211_FREQUENCY_ATTR_1MHZ = 0x15 + NL80211_FREQUENCY_ATTR_2MHZ = 0x16 + NL80211_FREQUENCY_ATTR_4MHZ = 0x17 + NL80211_FREQUENCY_ATTR_8MHZ = 0x18 + NL80211_FREQUENCY_ATTR_DFS_CAC_TIME = 0xd + NL80211_FREQUENCY_ATTR_DFS_STATE = 0x7 + NL80211_FREQUENCY_ATTR_DFS_TIME = 0x8 + NL80211_FREQUENCY_ATTR_DISABLED = 0x2 + NL80211_FREQUENCY_ATTR_FREQ = 0x1 + NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf + NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe + NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf + NL80211_FREQUENCY_ATTR_MAX = 0x19 + NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6 + NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11 + NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc + NL80211_FREQUENCY_ATTR_NO_20MHZ = 0x10 + NL80211_FREQUENCY_ATTR_NO_80MHZ = 0xb + NL80211_FREQUENCY_ATTR_NO_HE = 0x13 + NL80211_FREQUENCY_ATTR_NO_HT40_MINUS = 0x9 + NL80211_FREQUENCY_ATTR_NO_HT40_PLUS = 0xa + NL80211_FREQUENCY_ATTR_NO_IBSS = 0x3 + NL80211_FREQUENCY_ATTR_NO_IR = 0x3 + NL80211_FREQUENCY_ATTR_OFFSET = 0x14 + NL80211_FREQUENCY_ATTR_PASSIVE_SCAN = 0x3 + NL80211_FREQUENCY_ATTR_RADAR = 0x5 + NL80211_FREQUENCY_ATTR_WMM = 0x12 + NL80211_FTM_RESP_ATTR_CIVICLOC = 0x3 + NL80211_FTM_RESP_ATTR_ENABLED = 0x1 + NL80211_FTM_RESP_ATTR_LCI = 0x2 + NL80211_FTM_RESP_ATTR_MAX = 0x3 + NL80211_FTM_STATS_ASAP_NUM = 0x4 + NL80211_FTM_STATS_FAILED_NUM = 0x3 + NL80211_FTM_STATS_MAX = 0xa + NL80211_FTM_STATS_NON_ASAP_NUM = 0x5 + NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM = 0x9 + NL80211_FTM_STATS_PAD = 0xa + NL80211_FTM_STATS_PARTIAL_NUM = 0x2 + NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM = 0x8 + NL80211_FTM_STATS_SUCCESS_NUM = 0x1 + NL80211_FTM_STATS_TOTAL_DURATION_MSEC = 0x6 + NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM = 0x7 + NL80211_GENL_NAME = "nl80211" + NL80211_HE_BSS_COLOR_ATTR_COLOR = 0x1 + NL80211_HE_BSS_COLOR_ATTR_DISABLED = 0x2 + NL80211_HE_BSS_COLOR_ATTR_MAX = 0x3 + NL80211_HE_BSS_COLOR_ATTR_PARTIAL = 0x3 + NL80211_HE_MAX_CAPABILITY_LEN = 0x36 + NL80211_HE_MIN_CAPABILITY_LEN = 0x10 + NL80211_HE_NSS_MAX = 0x8 + NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP = 0x4 + NL80211_HE_OBSS_PD_ATTR_MAX = 0x6 + NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET = 0x2 + NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET = 0x1 + NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET = 0x3 + NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP = 0x5 + NL80211_HE_OBSS_PD_ATTR_SR_CTRL = 0x6 + NL80211_HIDDEN_SSID_NOT_IN_USE = 0x0 + NL80211_HIDDEN_SSID_ZERO_CONTENTS = 0x2 + NL80211_HIDDEN_SSID_ZERO_LEN = 0x1 + NL80211_HT_CAPABILITY_LEN = 0x1a + NL80211_IFACE_COMB_BI_MIN_GCD = 0x7 + NL80211_IFACE_COMB_LIMITS = 0x1 + NL80211_IFACE_COMB_MAXNUM = 0x2 + NL80211_IFACE_COMB_NUM_CHANNELS = 0x4 + NL80211_IFACE_COMB_RADAR_DETECT_REGIONS = 0x6 + NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS = 0x5 + NL80211_IFACE_COMB_STA_AP_BI_MATCH = 0x3 + NL80211_IFACE_COMB_UNSPEC = 0x0 + NL80211_IFACE_LIMIT_MAX = 0x1 + NL80211_IFACE_LIMIT_TYPES = 0x2 + NL80211_IFACE_LIMIT_UNSPEC = 0x0 + NL80211_IFTYPE_ADHOC = 0x1 + NL80211_IFTYPE_AKM_ATTR_IFTYPES = 0x1 + NL80211_IFTYPE_AKM_ATTR_MAX = 0x2 + NL80211_IFTYPE_AKM_ATTR_SUITES = 0x2 + NL80211_IFTYPE_AP = 0x3 + NL80211_IFTYPE_AP_VLAN = 0x4 + NL80211_IFTYPE_MAX = 0xc + NL80211_IFTYPE_MESH_POINT = 0x7 + NL80211_IFTYPE_MONITOR = 0x6 + NL80211_IFTYPE_NAN = 0xc + NL80211_IFTYPE_OCB = 0xb + NL80211_IFTYPE_P2P_CLIENT = 0x8 + NL80211_IFTYPE_P2P_DEVICE = 0xa + NL80211_IFTYPE_P2P_GO = 0x9 + NL80211_IFTYPE_STATION = 0x2 + NL80211_IFTYPE_UNSPECIFIED = 0x0 + NL80211_IFTYPE_WDS = 0x5 + NL80211_KCK_EXT_LEN = 0x18 + NL80211_KCK_LEN = 0x10 + NL80211_KEK_EXT_LEN = 0x20 + NL80211_KEK_LEN = 0x10 + NL80211_KEY_CIPHER = 0x3 + NL80211_KEY_DATA = 0x1 + NL80211_KEY_DEFAULT_BEACON = 0xa + NL80211_KEY_DEFAULT = 0x5 + NL80211_KEY_DEFAULT_MGMT = 0x6 + NL80211_KEY_DEFAULT_TYPE_MULTICAST = 0x2 + NL80211_KEY_DEFAULT_TYPES = 0x8 + NL80211_KEY_DEFAULT_TYPE_UNICAST = 0x1 + NL80211_KEY_IDX = 0x2 + NL80211_KEY_MAX = 0xa + NL80211_KEY_MODE = 0x9 + NL80211_KEY_NO_TX = 0x1 + NL80211_KEY_RX_TX = 0x0 + NL80211_KEY_SEQ = 0x4 + NL80211_KEY_SET_TX = 0x2 + NL80211_KEY_TYPE = 0x7 + NL80211_KEYTYPE_GROUP = 0x0 + NL80211_KEYTYPE_PAIRWISE = 0x1 + NL80211_KEYTYPE_PEERKEY = 0x2 + NL80211_MAX_NR_AKM_SUITES = 0x2 + NL80211_MAX_NR_CIPHER_SUITES = 0x5 + NL80211_MAX_SUPP_HT_RATES = 0x4d + NL80211_MAX_SUPP_RATES = 0x20 + NL80211_MAX_SUPP_REG_RULES = 0x80 + NL80211_MESHCONF_ATTR_MAX = 0x1f + NL80211_MESHCONF_AUTO_OPEN_PLINKS = 0x7 + NL80211_MESHCONF_AWAKE_WINDOW = 0x1b + NL80211_MESHCONF_CONFIRM_TIMEOUT = 0x2 + NL80211_MESHCONF_CONNECTED_TO_AS = 0x1f + NL80211_MESHCONF_CONNECTED_TO_GATE = 0x1d + NL80211_MESHCONF_ELEMENT_TTL = 0xf + NL80211_MESHCONF_FORWARDING = 0x13 + NL80211_MESHCONF_GATE_ANNOUNCEMENTS = 0x11 + NL80211_MESHCONF_HOLDING_TIMEOUT = 0x3 + NL80211_MESHCONF_HT_OPMODE = 0x16 + NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT = 0xb + NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL = 0x19 + NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES = 0x8 + NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME = 0xd + NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT = 0x17 + NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL = 0x12 + NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL = 0xc + NL80211_MESHCONF_HWMP_RANN_INTERVAL = 0x10 + NL80211_MESHCONF_HWMP_ROOT_INTERVAL = 0x18 + NL80211_MESHCONF_HWMP_ROOTMODE = 0xe + NL80211_MESHCONF_MAX_PEER_LINKS = 0x4 + NL80211_MESHCONF_MAX_RETRIES = 0x5 + NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT = 0xa + NL80211_MESHCONF_NOLEARN = 0x1e + NL80211_MESHCONF_PATH_REFRESH_TIME = 0x9 + NL80211_MESHCONF_PLINK_TIMEOUT = 0x1c + NL80211_MESHCONF_POWER_MODE = 0x1a + NL80211_MESHCONF_RETRY_TIMEOUT = 0x1 + NL80211_MESHCONF_RSSI_THRESHOLD = 0x14 + NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR = 0x15 + NL80211_MESHCONF_TTL = 0x6 + NL80211_MESH_POWER_ACTIVE = 0x1 + NL80211_MESH_POWER_DEEP_SLEEP = 0x3 + NL80211_MESH_POWER_LIGHT_SLEEP = 0x2 + NL80211_MESH_POWER_MAX = 0x3 + NL80211_MESH_POWER_UNKNOWN = 0x0 + NL80211_MESH_SETUP_ATTR_MAX = 0x8 + NL80211_MESH_SETUP_AUTH_PROTOCOL = 0x8 + NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC = 0x2 + NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL = 0x1 + NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC = 0x6 + NL80211_MESH_SETUP_IE = 0x3 + NL80211_MESH_SETUP_USERSPACE_AMPE = 0x5 + NL80211_MESH_SETUP_USERSPACE_AUTH = 0x4 + NL80211_MESH_SETUP_USERSPACE_MPM = 0x7 + NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE = 0x3 + NL80211_MFP_NO = 0x0 + NL80211_MFP_OPTIONAL = 0x2 + NL80211_MFP_REQUIRED = 0x1 + NL80211_MIN_REMAIN_ON_CHANNEL_TIME = 0xa + NL80211_MNTR_FLAG_ACTIVE = 0x6 + NL80211_MNTR_FLAG_CONTROL = 0x3 + NL80211_MNTR_FLAG_COOK_FRAMES = 0x5 + NL80211_MNTR_FLAG_FCSFAIL = 0x1 + NL80211_MNTR_FLAG_MAX = 0x6 + NL80211_MNTR_FLAG_OTHER_BSS = 0x4 + NL80211_MNTR_FLAG_PLCPFAIL = 0x2 + NL80211_MPATH_FLAG_ACTIVE = 0x1 + NL80211_MPATH_FLAG_FIXED = 0x8 + NL80211_MPATH_FLAG_RESOLVED = 0x10 + NL80211_MPATH_FLAG_RESOLVING = 0x2 + NL80211_MPATH_FLAG_SN_VALID = 0x4 + NL80211_MPATH_INFO_DISCOVERY_RETRIES = 0x7 + NL80211_MPATH_INFO_DISCOVERY_TIMEOUT = 0x6 + NL80211_MPATH_INFO_EXPTIME = 0x4 + NL80211_MPATH_INFO_FLAGS = 0x5 + NL80211_MPATH_INFO_FRAME_QLEN = 0x1 + NL80211_MPATH_INFO_HOP_COUNT = 0x8 + NL80211_MPATH_INFO_MAX = 0x9 + NL80211_MPATH_INFO_METRIC = 0x3 + NL80211_MPATH_INFO_PATH_CHANGE = 0x9 + NL80211_MPATH_INFO_SN = 0x2 + NL80211_MULTICAST_GROUP_CONFIG = "config" + NL80211_MULTICAST_GROUP_MLME = "mlme" + NL80211_MULTICAST_GROUP_NAN = "nan" + NL80211_MULTICAST_GROUP_REG = "regulatory" + NL80211_MULTICAST_GROUP_SCAN = "scan" + NL80211_MULTICAST_GROUP_TESTMODE = "testmode" + NL80211_MULTICAST_GROUP_VENDOR = "vendor" + NL80211_NAN_FUNC_ATTR_MAX = 0x10 + NL80211_NAN_FUNC_CLOSE_RANGE = 0x9 + NL80211_NAN_FUNC_FOLLOW_UP = 0x2 + NL80211_NAN_FUNC_FOLLOW_UP_DEST = 0x8 + NL80211_NAN_FUNC_FOLLOW_UP_ID = 0x6 + NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID = 0x7 + NL80211_NAN_FUNC_INSTANCE_ID = 0xf + NL80211_NAN_FUNC_MAX_TYPE = 0x2 + NL80211_NAN_FUNC_PUBLISH_BCAST = 0x4 + NL80211_NAN_FUNC_PUBLISH = 0x0 + NL80211_NAN_FUNC_PUBLISH_TYPE = 0x3 + NL80211_NAN_FUNC_RX_MATCH_FILTER = 0xd + NL80211_NAN_FUNC_SERVICE_ID = 0x2 + NL80211_NAN_FUNC_SERVICE_ID_LEN = 0x6 + NL80211_NAN_FUNC_SERVICE_INFO = 0xb + NL80211_NAN_FUNC_SERVICE_SPEC_INFO_MAX_LEN = 0xff + NL80211_NAN_FUNC_SRF = 0xc + NL80211_NAN_FUNC_SRF_MAX_LEN = 0xff + NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE = 0x5 + NL80211_NAN_FUNC_SUBSCRIBE = 0x1 + NL80211_NAN_FUNC_TERM_REASON = 0x10 + NL80211_NAN_FUNC_TERM_REASON_ERROR = 0x2 + NL80211_NAN_FUNC_TERM_REASON_TTL_EXPIRED = 0x1 + NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST = 0x0 + NL80211_NAN_FUNC_TTL = 0xa + NL80211_NAN_FUNC_TX_MATCH_FILTER = 0xe + NL80211_NAN_FUNC_TYPE = 0x1 + NL80211_NAN_MATCH_ATTR_MAX = 0x2 + NL80211_NAN_MATCH_FUNC_LOCAL = 0x1 + NL80211_NAN_MATCH_FUNC_PEER = 0x2 + NL80211_NAN_SOLICITED_PUBLISH = 0x1 + NL80211_NAN_SRF_ATTR_MAX = 0x4 + NL80211_NAN_SRF_BF = 0x2 + NL80211_NAN_SRF_BF_IDX = 0x3 + NL80211_NAN_SRF_INCLUDE = 0x1 + NL80211_NAN_SRF_MAC_ADDRS = 0x4 + NL80211_NAN_UNSOLICITED_PUBLISH = 0x2 + NL80211_NUM_ACS = 0x4 + NL80211_P2P_PS_SUPPORTED = 0x1 + NL80211_P2P_PS_UNSUPPORTED = 0x0 + NL80211_PKTPAT_MASK = 0x1 + NL80211_PKTPAT_OFFSET = 0x3 + NL80211_PKTPAT_PATTERN = 0x2 + NL80211_PLINK_ACTION_BLOCK = 0x2 + NL80211_PLINK_ACTION_NO_ACTION = 0x0 + NL80211_PLINK_ACTION_OPEN = 0x1 + NL80211_PLINK_BLOCKED = 0x6 + NL80211_PLINK_CNF_RCVD = 0x3 + NL80211_PLINK_ESTAB = 0x4 + NL80211_PLINK_HOLDING = 0x5 + NL80211_PLINK_LISTEN = 0x0 + NL80211_PLINK_OPN_RCVD = 0x2 + NL80211_PLINK_OPN_SNT = 0x1 + NL80211_PMKSA_CANDIDATE_BSSID = 0x2 + NL80211_PMKSA_CANDIDATE_INDEX = 0x1 + NL80211_PMKSA_CANDIDATE_PREAUTH = 0x3 + NL80211_PMSR_ATTR_MAX = 0x5 + NL80211_PMSR_ATTR_MAX_PEERS = 0x1 + NL80211_PMSR_ATTR_PEERS = 0x5 + NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR = 0x3 + NL80211_PMSR_ATTR_REPORT_AP_TSF = 0x2 + NL80211_PMSR_ATTR_TYPE_CAPA = 0x4 + NL80211_PMSR_FTM_CAPA_ATTR_ASAP = 0x1 + NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS = 0x6 + NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT = 0x7 + NL80211_PMSR_FTM_CAPA_ATTR_MAX = 0xa + NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST = 0x8 + NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP = 0x2 + NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED = 0xa + NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES = 0x5 + NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC = 0x4 + NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI = 0x3 + NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED = 0x9 + NL80211_PMSR_FTM_FAILURE_BAD_CHANGED_PARAMS = 0x7 + NL80211_PMSR_FTM_FAILURE_INVALID_TIMESTAMP = 0x5 + NL80211_PMSR_FTM_FAILURE_NO_RESPONSE = 0x1 + NL80211_PMSR_FTM_FAILURE_PEER_BUSY = 0x6 + NL80211_PMSR_FTM_FAILURE_PEER_NOT_CAPABLE = 0x4 + NL80211_PMSR_FTM_FAILURE_REJECTED = 0x2 + NL80211_PMSR_FTM_FAILURE_UNSPECIFIED = 0x0 + NL80211_PMSR_FTM_FAILURE_WRONG_CHANNEL = 0x3 + NL80211_PMSR_FTM_REQ_ATTR_ASAP = 0x1 + NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION = 0x5 + NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD = 0x4 + NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST = 0x6 + NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK = 0xc + NL80211_PMSR_FTM_REQ_ATTR_MAX = 0xd + NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED = 0xb + NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP = 0x3 + NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES = 0x7 + NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE = 0x2 + NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC = 0x9 + NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI = 0x8 + NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED = 0xa + NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION = 0x7 + NL80211_PMSR_FTM_RESP_ATTR_BURST_INDEX = 0x2 + NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME = 0x5 + NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC = 0x14 + NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG = 0x10 + NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD = 0x12 + NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE = 0x11 + NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON = 0x1 + NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST = 0x8 + NL80211_PMSR_FTM_RESP_ATTR_LCI = 0x13 + NL80211_PMSR_FTM_RESP_ATTR_MAX = 0x15 + NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP = 0x6 + NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS = 0x3 + NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES = 0x4 + NL80211_PMSR_FTM_RESP_ATTR_PAD = 0x15 + NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG = 0x9 + NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD = 0xa + NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG = 0xd + NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD = 0xf + NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE = 0xe + NL80211_PMSR_FTM_RESP_ATTR_RX_RATE = 0xc + NL80211_PMSR_FTM_RESP_ATTR_TX_RATE = 0xb + NL80211_PMSR_PEER_ATTR_ADDR = 0x1 + NL80211_PMSR_PEER_ATTR_CHAN = 0x2 + NL80211_PMSR_PEER_ATTR_MAX = 0x4 + NL80211_PMSR_PEER_ATTR_REQ = 0x3 + NL80211_PMSR_PEER_ATTR_RESP = 0x4 + NL80211_PMSR_REQ_ATTR_DATA = 0x1 + NL80211_PMSR_REQ_ATTR_GET_AP_TSF = 0x2 + NL80211_PMSR_REQ_ATTR_MAX = 0x2 + NL80211_PMSR_RESP_ATTR_AP_TSF = 0x4 + NL80211_PMSR_RESP_ATTR_DATA = 0x1 + NL80211_PMSR_RESP_ATTR_FINAL = 0x5 + NL80211_PMSR_RESP_ATTR_HOST_TIME = 0x3 + NL80211_PMSR_RESP_ATTR_MAX = 0x6 + NL80211_PMSR_RESP_ATTR_PAD = 0x6 + NL80211_PMSR_RESP_ATTR_STATUS = 0x2 + NL80211_PMSR_STATUS_FAILURE = 0x3 + NL80211_PMSR_STATUS_REFUSED = 0x1 + NL80211_PMSR_STATUS_SUCCESS = 0x0 + NL80211_PMSR_STATUS_TIMEOUT = 0x2 + NL80211_PMSR_TYPE_FTM = 0x1 + NL80211_PMSR_TYPE_INVALID = 0x0 + NL80211_PMSR_TYPE_MAX = 0x1 + NL80211_PREAMBLE_DMG = 0x3 + NL80211_PREAMBLE_HE = 0x4 + NL80211_PREAMBLE_HT = 0x1 + NL80211_PREAMBLE_LEGACY = 0x0 + NL80211_PREAMBLE_VHT = 0x2 + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U = 0x8 + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P = 0x4 + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 = 0x2 + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS = 0x1 + NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 0x1 + NL80211_PS_DISABLED = 0x0 + NL80211_PS_ENABLED = 0x1 + NL80211_RADAR_CAC_ABORTED = 0x2 + NL80211_RADAR_CAC_FINISHED = 0x1 + NL80211_RADAR_CAC_STARTED = 0x5 + NL80211_RADAR_DETECTED = 0x0 + NL80211_RADAR_NOP_FINISHED = 0x3 + NL80211_RADAR_PRE_CAC_EXPIRED = 0x4 + NL80211_RATE_INFO_10_MHZ_WIDTH = 0xb + NL80211_RATE_INFO_160_MHZ_WIDTH = 0xa + NL80211_RATE_INFO_40_MHZ_WIDTH = 0x3 + NL80211_RATE_INFO_5_MHZ_WIDTH = 0xc + NL80211_RATE_INFO_80_MHZ_WIDTH = 0x8 + NL80211_RATE_INFO_80P80_MHZ_WIDTH = 0x9 + NL80211_RATE_INFO_BITRATE32 = 0x5 + NL80211_RATE_INFO_BITRATE = 0x1 + NL80211_RATE_INFO_HE_1XLTF = 0x0 + NL80211_RATE_INFO_HE_2XLTF = 0x1 + NL80211_RATE_INFO_HE_4XLTF = 0x2 + NL80211_RATE_INFO_HE_DCM = 0x10 + NL80211_RATE_INFO_HE_GI_0_8 = 0x0 + NL80211_RATE_INFO_HE_GI_1_6 = 0x1 + NL80211_RATE_INFO_HE_GI_3_2 = 0x2 + NL80211_RATE_INFO_HE_GI = 0xf + NL80211_RATE_INFO_HE_MCS = 0xd + NL80211_RATE_INFO_HE_NSS = 0xe + NL80211_RATE_INFO_HE_RU_ALLOC_106 = 0x2 + NL80211_RATE_INFO_HE_RU_ALLOC_242 = 0x3 + NL80211_RATE_INFO_HE_RU_ALLOC_26 = 0x0 + NL80211_RATE_INFO_HE_RU_ALLOC_2x996 = 0x6 + NL80211_RATE_INFO_HE_RU_ALLOC_484 = 0x4 + NL80211_RATE_INFO_HE_RU_ALLOC_52 = 0x1 + NL80211_RATE_INFO_HE_RU_ALLOC_996 = 0x5 + NL80211_RATE_INFO_HE_RU_ALLOC = 0x11 + NL80211_RATE_INFO_MAX = 0x11 + NL80211_RATE_INFO_MCS = 0x2 + NL80211_RATE_INFO_SHORT_GI = 0x4 + NL80211_RATE_INFO_VHT_MCS = 0x6 + NL80211_RATE_INFO_VHT_NSS = 0x7 + NL80211_REGDOM_SET_BY_CORE = 0x0 + NL80211_REGDOM_SET_BY_COUNTRY_IE = 0x3 + NL80211_REGDOM_SET_BY_DRIVER = 0x2 + NL80211_REGDOM_SET_BY_USER = 0x1 + NL80211_REGDOM_TYPE_COUNTRY = 0x0 + NL80211_REGDOM_TYPE_CUSTOM_WORLD = 0x2 + NL80211_REGDOM_TYPE_INTERSECTION = 0x3 + NL80211_REGDOM_TYPE_WORLD = 0x1 + NL80211_REG_RULE_ATTR_MAX = 0x7 + NL80211_REKEY_DATA_AKM = 0x4 + NL80211_REKEY_DATA_KCK = 0x2 + NL80211_REKEY_DATA_KEK = 0x1 + NL80211_REKEY_DATA_REPLAY_CTR = 0x3 + NL80211_REPLAY_CTR_LEN = 0x8 + NL80211_RRF_AUTO_BW = 0x800 + NL80211_RRF_DFS = 0x10 + NL80211_RRF_GO_CONCURRENT = 0x1000 + NL80211_RRF_IR_CONCURRENT = 0x1000 + NL80211_RRF_NO_160MHZ = 0x10000 + NL80211_RRF_NO_80MHZ = 0x8000 + NL80211_RRF_NO_CCK = 0x2 + NL80211_RRF_NO_HE = 0x20000 + NL80211_RRF_NO_HT40 = 0x6000 + NL80211_RRF_NO_HT40MINUS = 0x2000 + NL80211_RRF_NO_HT40PLUS = 0x4000 + NL80211_RRF_NO_IBSS = 0x80 + NL80211_RRF_NO_INDOOR = 0x4 + NL80211_RRF_NO_IR_ALL = 0x180 + NL80211_RRF_NO_IR = 0x80 + NL80211_RRF_NO_OFDM = 0x1 + NL80211_RRF_NO_OUTDOOR = 0x8 + NL80211_RRF_PASSIVE_SCAN = 0x80 + NL80211_RRF_PTMP_ONLY = 0x40 + NL80211_RRF_PTP_ONLY = 0x20 + NL80211_RXMGMT_FLAG_ANSWERED = 0x1 + NL80211_RXMGMT_FLAG_EXTERNAL_AUTH = 0x2 + NL80211_SAE_PWE_BOTH = 0x3 + NL80211_SAE_PWE_HASH_TO_ELEMENT = 0x2 + NL80211_SAE_PWE_HUNT_AND_PECK = 0x1 + NL80211_SAE_PWE_UNSPECIFIED = 0x0 + NL80211_SAR_ATTR_MAX = 0x2 + NL80211_SAR_ATTR_SPECS = 0x2 + NL80211_SAR_ATTR_SPECS_END_FREQ = 0x4 + NL80211_SAR_ATTR_SPECS_MAX = 0x4 + NL80211_SAR_ATTR_SPECS_POWER = 0x1 + NL80211_SAR_ATTR_SPECS_RANGE_INDEX = 0x2 + NL80211_SAR_ATTR_SPECS_START_FREQ = 0x3 + NL80211_SAR_ATTR_TYPE = 0x1 + NL80211_SAR_TYPE_POWER = 0x0 + NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP = 0x20 + NL80211_SCAN_FLAG_AP = 0x4 + NL80211_SCAN_FLAG_COLOCATED_6GHZ = 0x4000 + NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME = 0x10 + NL80211_SCAN_FLAG_FLUSH = 0x2 + NL80211_SCAN_FLAG_FREQ_KHZ = 0x2000 + NL80211_SCAN_FLAG_HIGH_ACCURACY = 0x400 + NL80211_SCAN_FLAG_LOW_POWER = 0x200 + NL80211_SCAN_FLAG_LOW_PRIORITY = 0x1 + NL80211_SCAN_FLAG_LOW_SPAN = 0x100 + NL80211_SCAN_FLAG_MIN_PREQ_CONTENT = 0x1000 + NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = 0x80 + NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE = 0x40 + NL80211_SCAN_FLAG_RANDOM_ADDR = 0x8 + NL80211_SCAN_FLAG_RANDOM_SN = 0x800 + NL80211_SCAN_RSSI_THOLD_OFF = -0x12c + NL80211_SCHED_SCAN_MATCH_ATTR_BSSID = 0x5 + NL80211_SCHED_SCAN_MATCH_ATTR_MAX = 0x6 + NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI = 0x3 + NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST = 0x4 + NL80211_SCHED_SCAN_MATCH_ATTR_RSSI = 0x2 + NL80211_SCHED_SCAN_MATCH_ATTR_SSID = 0x1 + NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI = 0x6 + NL80211_SCHED_SCAN_PLAN_INTERVAL = 0x1 + NL80211_SCHED_SCAN_PLAN_ITERATIONS = 0x2 + NL80211_SCHED_SCAN_PLAN_MAX = 0x2 + NL80211_SMPS_DYNAMIC = 0x2 + NL80211_SMPS_MAX = 0x2 + NL80211_SMPS_OFF = 0x0 + NL80211_SMPS_STATIC = 0x1 + NL80211_STA_BSS_PARAM_BEACON_INTERVAL = 0x5 + NL80211_STA_BSS_PARAM_CTS_PROT = 0x1 + NL80211_STA_BSS_PARAM_DTIM_PERIOD = 0x4 + NL80211_STA_BSS_PARAM_MAX = 0x5 + NL80211_STA_BSS_PARAM_SHORT_PREAMBLE = 0x2 + NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME = 0x3 + NL80211_STA_FLAG_ASSOCIATED = 0x7 + NL80211_STA_FLAG_AUTHENTICATED = 0x5 + NL80211_STA_FLAG_AUTHORIZED = 0x1 + NL80211_STA_FLAG_MAX = 0x7 + NL80211_STA_FLAG_MAX_OLD_API = 0x6 + NL80211_STA_FLAG_MFP = 0x4 + NL80211_STA_FLAG_SHORT_PREAMBLE = 0x2 + NL80211_STA_FLAG_TDLS_PEER = 0x6 + NL80211_STA_FLAG_WME = 0x3 + NL80211_STA_INFO_ACK_SIGNAL_AVG = 0x23 + NL80211_STA_INFO_ACK_SIGNAL = 0x22 + NL80211_STA_INFO_AIRTIME_LINK_METRIC = 0x29 + NL80211_STA_INFO_AIRTIME_WEIGHT = 0x28 + NL80211_STA_INFO_ASSOC_AT_BOOTTIME = 0x2a + NL80211_STA_INFO_BEACON_LOSS = 0x12 + NL80211_STA_INFO_BEACON_RX = 0x1d + NL80211_STA_INFO_BEACON_SIGNAL_AVG = 0x1e + NL80211_STA_INFO_BSS_PARAM = 0xf + NL80211_STA_INFO_CHAIN_SIGNAL_AVG = 0x1a + NL80211_STA_INFO_CHAIN_SIGNAL = 0x19 + NL80211_STA_INFO_CONNECTED_TIME = 0x10 + NL80211_STA_INFO_CONNECTED_TO_AS = 0x2b + NL80211_STA_INFO_CONNECTED_TO_GATE = 0x26 + NL80211_STA_INFO_DATA_ACK_SIGNAL_AVG = 0x23 + NL80211_STA_INFO_EXPECTED_THROUGHPUT = 0x1b + NL80211_STA_INFO_FCS_ERROR_COUNT = 0x25 + NL80211_STA_INFO_INACTIVE_TIME = 0x1 + NL80211_STA_INFO_LLID = 0x4 + NL80211_STA_INFO_LOCAL_PM = 0x14 + NL80211_STA_INFO_MAX = 0x2b + NL80211_STA_INFO_NONPEER_PM = 0x16 + NL80211_STA_INFO_PAD = 0x21 + NL80211_STA_INFO_PEER_PM = 0x15 + NL80211_STA_INFO_PLID = 0x5 + NL80211_STA_INFO_PLINK_STATE = 0x6 + NL80211_STA_INFO_RX_BITRATE = 0xe + NL80211_STA_INFO_RX_BYTES64 = 0x17 + NL80211_STA_INFO_RX_BYTES = 0x2 + NL80211_STA_INFO_RX_DROP_MISC = 0x1c + NL80211_STA_INFO_RX_DURATION = 0x20 + NL80211_STA_INFO_RX_MPDUS = 0x24 + NL80211_STA_INFO_RX_PACKETS = 0x9 + NL80211_STA_INFO_SIGNAL_AVG = 0xd + NL80211_STA_INFO_SIGNAL = 0x7 + NL80211_STA_INFO_STA_FLAGS = 0x11 + NL80211_STA_INFO_TID_STATS = 0x1f + NL80211_STA_INFO_T_OFFSET = 0x13 + NL80211_STA_INFO_TX_BITRATE = 0x8 + NL80211_STA_INFO_TX_BYTES64 = 0x18 + NL80211_STA_INFO_TX_BYTES = 0x3 + NL80211_STA_INFO_TX_DURATION = 0x27 + NL80211_STA_INFO_TX_FAILED = 0xc + NL80211_STA_INFO_TX_PACKETS = 0xa + NL80211_STA_INFO_TX_RETRIES = 0xb + NL80211_STA_WME_MAX = 0x2 + NL80211_STA_WME_MAX_SP = 0x2 + NL80211_STA_WME_UAPSD_QUEUES = 0x1 + NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY = 0x5 + NL80211_SURVEY_INFO_CHANNEL_TIME = 0x4 + NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY = 0x6 + NL80211_SURVEY_INFO_CHANNEL_TIME_RX = 0x7 + NL80211_SURVEY_INFO_CHANNEL_TIME_TX = 0x8 + NL80211_SURVEY_INFO_FREQUENCY = 0x1 + NL80211_SURVEY_INFO_FREQUENCY_OFFSET = 0xc + NL80211_SURVEY_INFO_IN_USE = 0x3 + NL80211_SURVEY_INFO_MAX = 0xc + NL80211_SURVEY_INFO_NOISE = 0x2 + NL80211_SURVEY_INFO_PAD = 0xa + NL80211_SURVEY_INFO_TIME_BSS_RX = 0xb + NL80211_SURVEY_INFO_TIME_BUSY = 0x5 + NL80211_SURVEY_INFO_TIME = 0x4 + NL80211_SURVEY_INFO_TIME_EXT_BUSY = 0x6 + NL80211_SURVEY_INFO_TIME_RX = 0x7 + NL80211_SURVEY_INFO_TIME_SCAN = 0x9 + NL80211_SURVEY_INFO_TIME_TX = 0x8 + NL80211_TDLS_DISABLE_LINK = 0x4 + NL80211_TDLS_DISCOVERY_REQ = 0x0 + NL80211_TDLS_ENABLE_LINK = 0x3 + NL80211_TDLS_PEER_HE = 0x8 + NL80211_TDLS_PEER_HT = 0x1 + NL80211_TDLS_PEER_VHT = 0x2 + NL80211_TDLS_PEER_WMM = 0x4 + NL80211_TDLS_SETUP = 0x1 + NL80211_TDLS_TEARDOWN = 0x2 + NL80211_TID_CONFIG_ATTR_AMPDU_CTRL = 0x9 + NL80211_TID_CONFIG_ATTR_AMSDU_CTRL = 0xb + NL80211_TID_CONFIG_ATTR_MAX = 0xd + NL80211_TID_CONFIG_ATTR_NOACK = 0x6 + NL80211_TID_CONFIG_ATTR_OVERRIDE = 0x4 + NL80211_TID_CONFIG_ATTR_PAD = 0x1 + NL80211_TID_CONFIG_ATTR_PEER_SUPP = 0x3 + NL80211_TID_CONFIG_ATTR_RETRY_LONG = 0x8 + NL80211_TID_CONFIG_ATTR_RETRY_SHORT = 0x7 + NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL = 0xa + NL80211_TID_CONFIG_ATTR_TIDS = 0x5 + NL80211_TID_CONFIG_ATTR_TX_RATE = 0xd + NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE = 0xc + NL80211_TID_CONFIG_ATTR_VIF_SUPP = 0x2 + NL80211_TID_CONFIG_DISABLE = 0x1 + NL80211_TID_CONFIG_ENABLE = 0x0 + NL80211_TID_STATS_MAX = 0x6 + NL80211_TID_STATS_PAD = 0x5 + NL80211_TID_STATS_RX_MSDU = 0x1 + NL80211_TID_STATS_TX_MSDU = 0x2 + NL80211_TID_STATS_TX_MSDU_FAILED = 0x4 + NL80211_TID_STATS_TX_MSDU_RETRIES = 0x3 + NL80211_TID_STATS_TXQ_STATS = 0x6 + NL80211_TIMEOUT_ASSOC = 0x3 + NL80211_TIMEOUT_AUTH = 0x2 + NL80211_TIMEOUT_SCAN = 0x1 + NL80211_TIMEOUT_UNSPECIFIED = 0x0 + NL80211_TKIP_DATA_OFFSET_ENCR_KEY = 0x0 + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY = 0x18 + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY = 0x10 + NL80211_TX_POWER_AUTOMATIC = 0x0 + NL80211_TX_POWER_FIXED = 0x2 + NL80211_TX_POWER_LIMITED = 0x1 + NL80211_TXQ_ATTR_AC = 0x1 + NL80211_TXQ_ATTR_AIFS = 0x5 + NL80211_TXQ_ATTR_CWMAX = 0x4 + NL80211_TXQ_ATTR_CWMIN = 0x3 + NL80211_TXQ_ATTR_MAX = 0x5 + NL80211_TXQ_ATTR_QUEUE = 0x1 + NL80211_TXQ_ATTR_TXOP = 0x2 + NL80211_TXQ_Q_BE = 0x2 + NL80211_TXQ_Q_BK = 0x3 + NL80211_TXQ_Q_VI = 0x1 + NL80211_TXQ_Q_VO = 0x0 + NL80211_TXQ_STATS_BACKLOG_BYTES = 0x1 + NL80211_TXQ_STATS_BACKLOG_PACKETS = 0x2 + NL80211_TXQ_STATS_COLLISIONS = 0x8 + NL80211_TXQ_STATS_DROPS = 0x4 + NL80211_TXQ_STATS_ECN_MARKS = 0x5 + NL80211_TXQ_STATS_FLOWS = 0x3 + NL80211_TXQ_STATS_MAX = 0xb + NL80211_TXQ_STATS_MAX_FLOWS = 0xb + NL80211_TXQ_STATS_OVERLIMIT = 0x6 + NL80211_TXQ_STATS_OVERMEMORY = 0x7 + NL80211_TXQ_STATS_TX_BYTES = 0x9 + NL80211_TXQ_STATS_TX_PACKETS = 0xa + NL80211_TX_RATE_AUTOMATIC = 0x0 + NL80211_TXRATE_DEFAULT_GI = 0x0 + NL80211_TX_RATE_FIXED = 0x2 + NL80211_TXRATE_FORCE_LGI = 0x2 + NL80211_TXRATE_FORCE_SGI = 0x1 + NL80211_TXRATE_GI = 0x4 + NL80211_TXRATE_HE = 0x5 + NL80211_TXRATE_HE_GI = 0x6 + NL80211_TXRATE_HE_LTF = 0x7 + NL80211_TXRATE_HT = 0x2 + NL80211_TXRATE_LEGACY = 0x1 + NL80211_TX_RATE_LIMITED = 0x1 + NL80211_TXRATE_MAX = 0x7 + NL80211_TXRATE_MCS = 0x2 + NL80211_TXRATE_VHT = 0x3 + NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT = 0x1 + NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX = 0x2 + NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL = 0x2 + NL80211_USER_REG_HINT_CELL_BASE = 0x1 + NL80211_USER_REG_HINT_INDOOR = 0x2 + NL80211_USER_REG_HINT_USER = 0x0 + NL80211_VENDOR_ID_IS_LINUX = 0x80000000 + NL80211_VHT_CAPABILITY_LEN = 0xc + NL80211_VHT_NSS_MAX = 0x8 + NL80211_WIPHY_NAME_MAXLEN = 0x40 + NL80211_WMMR_AIFSN = 0x3 + NL80211_WMMR_CW_MAX = 0x2 + NL80211_WMMR_CW_MIN = 0x1 + NL80211_WMMR_MAX = 0x4 + NL80211_WMMR_TXOP = 0x4 + NL80211_WOWLAN_PKTPAT_MASK = 0x1 + NL80211_WOWLAN_PKTPAT_OFFSET = 0x3 + NL80211_WOWLAN_PKTPAT_PATTERN = 0x2 + NL80211_WOWLAN_TCP_DATA_INTERVAL = 0x9 + NL80211_WOWLAN_TCP_DATA_PAYLOAD = 0x6 + NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ = 0x7 + NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN = 0x8 + NL80211_WOWLAN_TCP_DST_IPV4 = 0x2 + NL80211_WOWLAN_TCP_DST_MAC = 0x3 + NL80211_WOWLAN_TCP_DST_PORT = 0x5 + NL80211_WOWLAN_TCP_SRC_IPV4 = 0x1 + NL80211_WOWLAN_TCP_SRC_PORT = 0x4 + NL80211_WOWLAN_TCP_WAKE_MASK = 0xb + NL80211_WOWLAN_TCP_WAKE_PAYLOAD = 0xa + NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE = 0x8 + NL80211_WOWLAN_TRIG_ANY = 0x1 + NL80211_WOWLAN_TRIG_DISCONNECT = 0x2 + NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST = 0x7 + NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE = 0x6 + NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED = 0x5 + NL80211_WOWLAN_TRIG_MAGIC_PKT = 0x3 + NL80211_WOWLAN_TRIG_NET_DETECT = 0x12 + NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS = 0x13 + NL80211_WOWLAN_TRIG_PKT_PATTERN = 0x4 + NL80211_WOWLAN_TRIG_RFKILL_RELEASE = 0x9 + NL80211_WOWLAN_TRIG_TCP_CONNECTION = 0xe + NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 = 0xa + NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN = 0xb + NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 = 0xc + NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN = 0xd + NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST = 0x10 + NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH = 0xf + NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS = 0x11 + NL80211_WPA_VERSION_1 = 0x1 + NL80211_WPA_VERSION_2 = 0x2 + NL80211_WPA_VERSION_3 = 0x4 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 6358806106f088687d47f8b1517d5322408e6e9d..c426c35763a80810ac3429a5dc1aadb2af7c5d12 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -210,8 +210,8 @@ type PtraceFpregs struct { } type PtracePer struct { - _ [0]uint64 - _ [32]byte + Control_regs [3]uint64 + _ [8]byte Starting_addr uint64 Ending_addr uint64 Perc_atmid uint16 diff --git a/src/cmd/vendor/golang.org/x/sys/windows/exec_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/exec_windows.go index 7a11e83b7ec10206ebaf5b547690db3cfeb1de90..855698bb28280ea9a8d4205fb3d1d2066bcdc581 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/exec_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/exec_windows.go @@ -9,8 +9,6 @@ package windows import ( errorspkg "errors" "unsafe" - - "golang.org/x/sys/internal/unsafeheader" ) // EscapeArg rewrites command line argument s as prescribed @@ -147,8 +145,12 @@ func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeListCo } return nil, err } + alloc, err := LocalAlloc(LMEM_FIXED, uint32(size)) + if err != nil { + return nil, err + } // size is guaranteed to be ≥1 by InitializeProcThreadAttributeList. - al := &ProcThreadAttributeListContainer{data: (*ProcThreadAttributeList)(unsafe.Pointer(&make([]byte, size)[0]))} + al := &ProcThreadAttributeListContainer{data: (*ProcThreadAttributeList)(unsafe.Pointer(alloc))} err = initializeProcThreadAttributeList(al.data, maxAttrCount, 0, &size) if err != nil { return nil, err @@ -157,36 +159,17 @@ func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeListCo } // Update modifies the ProcThreadAttributeList using UpdateProcThreadAttribute. -// Note that the value passed to this function will be copied into memory -// allocated by LocalAlloc, the contents of which should not contain any -// Go-managed pointers, even if the passed value itself is a Go-managed -// pointer. func (al *ProcThreadAttributeListContainer) Update(attribute uintptr, value unsafe.Pointer, size uintptr) error { - alloc, err := LocalAlloc(LMEM_FIXED, uint32(size)) - if err != nil { - return err - } - var src, dst []byte - hdr := (*unsafeheader.Slice)(unsafe.Pointer(&src)) - hdr.Data = value - hdr.Cap = int(size) - hdr.Len = int(size) - hdr = (*unsafeheader.Slice)(unsafe.Pointer(&dst)) - hdr.Data = unsafe.Pointer(alloc) - hdr.Cap = int(size) - hdr.Len = int(size) - copy(dst, src) - al.heapAllocations = append(al.heapAllocations, alloc) - return updateProcThreadAttribute(al.data, 0, attribute, unsafe.Pointer(alloc), size, nil, nil) + al.pointers = append(al.pointers, value) + return updateProcThreadAttribute(al.data, 0, attribute, value, size, nil, nil) } // Delete frees ProcThreadAttributeList's resources. func (al *ProcThreadAttributeListContainer) Delete() { deleteProcThreadAttributeList(al.data) - for i := range al.heapAllocations { - LocalFree(Handle(al.heapAllocations[i])) - } - al.heapAllocations = nil + LocalFree(Handle(unsafe.Pointer(al.data))) + al.data = nil + al.pointers = nil } // List returns the actual ProcThreadAttributeList to be passed to StartupInfoEx. diff --git a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go index 200b62a00320dc230a05e22fef70ed34731cd0f0..cf44e69337905fb3a2da5cbc1a158cbfa9e77ae7 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -363,6 +363,8 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys SetProcessWorkingSetSizeEx(hProcess Handle, dwMinimumWorkingSetSize uintptr, dwMaximumWorkingSetSize uintptr, flags uint32) (err error) //sys GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) //sys SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) +//sys GetActiveProcessorCount(groupNumber uint16) (ret uint32) +//sys GetMaximumProcessorCount(groupNumber uint16) (ret uint32) // Volume Management Functions //sys DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) = DefineDosDeviceW diff --git a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go index 73087bf5e56dc9f09e7cda48026e85d98b81f594..e19471c6a852fa58e91d9d288ce8231f4b83a065 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/types_windows.go @@ -938,8 +938,8 @@ type StartupInfoEx struct { type ProcThreadAttributeList struct{} type ProcThreadAttributeListContainer struct { - data *ProcThreadAttributeList - heapAllocations []uintptr + data *ProcThreadAttributeList + pointers []unsafe.Pointer } type ProcessInformation struct { @@ -2749,6 +2749,43 @@ type PROCESS_BASIC_INFORMATION struct { InheritedFromUniqueProcessId uintptr } +type SYSTEM_PROCESS_INFORMATION struct { + NextEntryOffset uint32 + NumberOfThreads uint32 + WorkingSetPrivateSize int64 + HardFaultCount uint32 + NumberOfThreadsHighWatermark uint32 + CycleTime uint64 + CreateTime int64 + UserTime int64 + KernelTime int64 + ImageName NTUnicodeString + BasePriority int32 + UniqueProcessID uintptr + InheritedFromUniqueProcessID uintptr + HandleCount uint32 + SessionID uint32 + UniqueProcessKey *uint32 + PeakVirtualSize uintptr + VirtualSize uintptr + PageFaultCount uint32 + PeakWorkingSetSize uintptr + WorkingSetSize uintptr + QuotaPeakPagedPoolUsage uintptr + QuotaPagedPoolUsage uintptr + QuotaPeakNonPagedPoolUsage uintptr + QuotaNonPagedPoolUsage uintptr + PagefileUsage uintptr + PeakPagefileUsage uintptr + PrivatePageCount uintptr + ReadOperationCount int64 + WriteOperationCount int64 + OtherOperationCount int64 + ReadTransferCount int64 + WriteTransferCount int64 + OtherTransferCount int64 +} + // SystemInformationClasses for NtQuerySystemInformation and NtSetSystemInformation const ( SystemBasicInformation = iota @@ -3135,3 +3172,5 @@ type ModuleInfo struct { SizeOfImage uint32 EntryPoint uintptr } + +const ALL_PROCESSOR_GROUPS = 0xFFFF diff --git a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 1055d47ed336f1cc7b2beb1b7e38dd11a5b80506..9ea1a44f04de1af43f02c64905b06ffa4b1a630b 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -226,6 +226,7 @@ var ( procFreeLibrary = modkernel32.NewProc("FreeLibrary") procGenerateConsoleCtrlEvent = modkernel32.NewProc("GenerateConsoleCtrlEvent") procGetACP = modkernel32.NewProc("GetACP") + procGetActiveProcessorCount = modkernel32.NewProc("GetActiveProcessorCount") procGetCommTimeouts = modkernel32.NewProc("GetCommTimeouts") procGetCommandLineW = modkernel32.NewProc("GetCommandLineW") procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") @@ -251,6 +252,7 @@ var ( procGetLogicalDriveStringsW = modkernel32.NewProc("GetLogicalDriveStringsW") procGetLogicalDrives = modkernel32.NewProc("GetLogicalDrives") procGetLongPathNameW = modkernel32.NewProc("GetLongPathNameW") + procGetMaximumProcessorCount = modkernel32.NewProc("GetMaximumProcessorCount") procGetModuleFileNameW = modkernel32.NewProc("GetModuleFileNameW") procGetModuleHandleExW = modkernel32.NewProc("GetModuleHandleExW") procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW") @@ -1967,6 +1969,12 @@ func GetACP() (acp uint32) { return } +func GetActiveProcessorCount(groupNumber uint16) (ret uint32) { + r0, _, _ := syscall.Syscall(procGetActiveProcessorCount.Addr(), 1, uintptr(groupNumber), 0, 0) + ret = uint32(r0) + return +} + func GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) { r1, _, e1 := syscall.Syscall(procGetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0) if r1 == 0 { @@ -2169,6 +2177,12 @@ func GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err er return } +func GetMaximumProcessorCount(groupNumber uint16) (ret uint32) { + r0, _, _ := syscall.Syscall(procGetMaximumProcessorCount.Addr(), 1, uintptr(groupNumber), 0, 0) + ret = uint32(r0) + return +} + func GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) { r0, _, e1 := syscall.Syscall(procGetModuleFileNameW.Addr(), 3, uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size)) n = uint32(r0) diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 03732f575fbd308da8fd3dd949c89a03e98d1a24..0e67e3bd19029113e30fbd66385d47fd875f8540 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -1,5 +1,5 @@ -# github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31 -## explicit; go 1.14 +# github.com/google/pprof v0.0.0-20220729232143-a41b82acbcb1 +## explicit; go 1.17 github.com/google/pprof/driver github.com/google/pprof/internal/binutils github.com/google/pprof/internal/driver @@ -12,10 +12,9 @@ github.com/google/pprof/internal/symbolizer github.com/google/pprof/internal/symbolz github.com/google/pprof/internal/transport github.com/google/pprof/profile -github.com/google/pprof/third_party/d3 github.com/google/pprof/third_party/d3flamegraph github.com/google/pprof/third_party/svgpan -# github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d +# github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2 ## explicit; go 1.12 github.com/ianlancetaylor/demangle # golang.org/x/arch v0.0.0-20210923205945-b76863e36670 @@ -42,7 +41,7 @@ golang.org/x/mod/zip # golang.org/x/sync v0.0.0-20210220032951-036812b2e83c ## explicit golang.org/x/sync/semaphore -# golang.org/x/sys v0.0.0-20211205182925-97ca703d548d +# golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 ## explicit; go 1.17 golang.org/x/sys/internal/unsafeheader golang.org/x/sys/plan9 diff --git a/src/compress/gzip/gunzip.go b/src/compress/gzip/gunzip.go index 924bce10b7c0cb1a901f47255afea99efcfc298a..237b2b928bfed0cd3223982e94b7afda212614cb 100644 --- a/src/compress/gzip/gunzip.go +++ b/src/compress/gzip/gunzip.go @@ -248,42 +248,40 @@ func (z *Reader) Read(p []byte) (n int, err error) { return 0, z.err } - n, z.err = z.decompressor.Read(p) - z.digest = crc32.Update(z.digest, crc32.IEEETable, p[:n]) - z.size += uint32(n) - if z.err != io.EOF { - // In the normal case we return here. - return n, z.err - } + for n == 0 { + n, z.err = z.decompressor.Read(p) + z.digest = crc32.Update(z.digest, crc32.IEEETable, p[:n]) + z.size += uint32(n) + if z.err != io.EOF { + // In the normal case we return here. + return n, z.err + } - // Finished file; check checksum and size. - if _, err := io.ReadFull(z.r, z.buf[:8]); err != nil { - z.err = noEOF(err) - return n, z.err - } - digest := le.Uint32(z.buf[:4]) - size := le.Uint32(z.buf[4:8]) - if digest != z.digest || size != z.size { - z.err = ErrChecksum - return n, z.err - } - z.digest, z.size = 0, 0 + // Finished file; check checksum and size. + if _, err := io.ReadFull(z.r, z.buf[:8]); err != nil { + z.err = noEOF(err) + return n, z.err + } + digest := le.Uint32(z.buf[:4]) + size := le.Uint32(z.buf[4:8]) + if digest != z.digest || size != z.size { + z.err = ErrChecksum + return n, z.err + } + z.digest, z.size = 0, 0 - // File is ok; check if there is another. - if !z.multistream { - return n, io.EOF - } - z.err = nil // Remove io.EOF + // File is ok; check if there is another. + if !z.multistream { + return n, io.EOF + } + z.err = nil // Remove io.EOF - if _, z.err = z.readHeader(); z.err != nil { - return n, z.err + if _, z.err = z.readHeader(); z.err != nil { + return n, z.err + } } - // Read from next file, if necessary. - if n > 0 { - return n, nil - } - return z.Read(p) + return n, nil } // Close closes the Reader. It does not close the underlying io.Reader. diff --git a/src/compress/gzip/gunzip_test.go b/src/compress/gzip/gunzip_test.go index 17c23e8a9be8585e386c97442c07533e3d2677a9..6fe8ddcf558eb6c4a671032dbb44069bdfde941f 100644 --- a/src/compress/gzip/gunzip_test.go +++ b/src/compress/gzip/gunzip_test.go @@ -515,3 +515,19 @@ func TestTruncatedStreams(t *testing.T) { } } } + +func TestCVE202230631(t *testing.T) { + var empty = []byte{0x1f, 0x8b, 0x08, 0x00, 0xa7, 0x8f, 0x43, 0x62, 0x00, + 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + r := bytes.NewReader(bytes.Repeat(empty, 4e6)) + z, err := NewReader(r) + if err != nil { + t.Fatalf("NewReader: got %v, want nil", err) + } + // Prior to CVE-2022-30631 fix, this would cause an unrecoverable panic due + // to stack exhaustion. + _, err = z.Read(make([]byte, 10)) + if err != io.EOF { + t.Errorf("Reader.Read: got %v, want %v", err, io.EOF) + } +} diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index 097046340b87b6714ad1ff7d8684c7b3d6a6a496..aaf8b21c43910ac94b37a8a1234397e21f4d1f98 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -240,7 +240,7 @@ func (hs *serverHandshakeState) processClientHello() error { hs.ecdheOk = supportsECDHE(c.config, hs.clientHello.supportedCurves, hs.clientHello.supportedPoints) - if hs.ecdheOk { + if hs.ecdheOk && len(hs.clientHello.supportedPoints) > 0 { // Although omitting the ec_point_formats extension is permitted, some // old OpenSSL version will refuse to handshake if not present. // @@ -321,6 +321,13 @@ func supportsECDHE(c *Config, supportedCurves []CurveID, supportedPoints []uint8 break } } + // Per RFC 8422, Section 5.1.2, if the Supported Point Formats extension is + // missing, uncompressed points are supported. If supportedPoints is empty, + // the extension must be missing, as an empty extension body is rejected by + // the parser. See https://go.dev/issue/49126. + if len(supportedPoints) == 0 { + supportsPointFormat = true + } return supportsCurve && supportsPointFormat } diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go index 6d2c4056261feea212d893c93ea874f82741d372..ca7f3b288abbc41f140d15d08951596d37bd155e 100644 --- a/src/crypto/tls/handshake_server_test.go +++ b/src/crypto/tls/handshake_server_test.go @@ -281,7 +281,7 @@ func TestTLS12OnlyCipherSuites(t *testing.T) { func TestTLSPointFormats(t *testing.T) { // Test that a Server returns the ec_point_format extension when ECC is - // negotiated, and not returned on RSA handshake. + // negotiated, and not on a RSA handshake or if ec_point_format is missing. tests := []struct { name string cipherSuites []uint16 @@ -289,8 +289,11 @@ func TestTLSPointFormats(t *testing.T) { supportedPoints []uint8 wantSupportedPoints bool }{ - {"ECC", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, []uint8{compressionNone}, true}, + {"ECC", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, []uint8{pointFormatUncompressed}, true}, + {"ECC without ec_point_format", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, nil, false}, + {"ECC with extra values", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, []uint8{13, 37, pointFormatUncompressed, 42}, true}, {"RSA", []uint16{TLS_RSA_WITH_AES_256_GCM_SHA384}, nil, nil, false}, + {"RSA with ec_point_format", []uint16{TLS_RSA_WITH_AES_256_GCM_SHA384}, nil, []uint8{pointFormatUncompressed}, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -330,18 +333,8 @@ func TestTLSPointFormats(t *testing.T) { t.Fatalf("didn't get ServerHello message in reply. Got %v\n", reply) } if tt.wantSupportedPoints { - if len(serverHello.supportedPoints) < 1 { - t.Fatal("missing ec_point_format extension from server") - } - found := false - for _, p := range serverHello.supportedPoints { - if p == pointFormatUncompressed { - found = true - break - } - } - if !found { - t.Fatal("missing uncompressed format in ec_point_format extension from server") + if !bytes.Equal(serverHello.supportedPoints, []uint8{pointFormatUncompressed}) { + t.Fatal("incorrect ec_point_format extension from server") } } else { if len(serverHello.supportedPoints) != 0 { diff --git a/src/crypto/x509/internal/macos/corefoundation.go b/src/crypto/x509/internal/macos/corefoundation.go index 75c212910b67cfa6e31c36a74c861b03ac8ca4c9..2b20b52dc6cb724d149c3c9757be544a8701baf6 100644 --- a/src/crypto/x509/internal/macos/corefoundation.go +++ b/src/crypto/x509/internal/macos/corefoundation.go @@ -184,6 +184,13 @@ func CFErrorCopyDescription(errRef CFRef) CFRef { } func x509_CFErrorCopyDescription_trampoline() +//go:cgo_import_dynamic x509_CFErrorGetCode CFErrorGetCode "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" + +func CFErrorGetCode(errRef CFRef) int { + return int(syscall(abi.FuncPCABI0(x509_CFErrorGetCode_trampoline), uintptr(errRef), 0, 0, 0, 0, 0)) +} +func x509_CFErrorGetCode_trampoline() + //go:cgo_import_dynamic x509_CFStringCreateExternalRepresentation CFStringCreateExternalRepresentation "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" func CFStringCreateExternalRepresentation(strRef CFRef) CFRef { diff --git a/src/crypto/x509/internal/macos/corefoundation.s b/src/crypto/x509/internal/macos/corefoundation.s index d69f72f795cd949504851c32a9b4be7599076f59..49cd084467b2c396e22cb2a06c983c6966dc8d7c 100644 --- a/src/crypto/x509/internal/macos/corefoundation.s +++ b/src/crypto/x509/internal/macos/corefoundation.s @@ -37,5 +37,7 @@ TEXT ·x509_CFDataCreate_trampoline(SB),NOSPLIT,$0-0 JMP x509_CFDataCreate(SB) TEXT ·x509_CFErrorCopyDescription_trampoline(SB),NOSPLIT,$0-0 JMP x509_CFErrorCopyDescription(SB) +TEXT ·x509_CFErrorGetCode_trampoline(SB),NOSPLIT,$0-0 + JMP x509_CFErrorGetCode(SB) TEXT ·x509_CFStringCreateExternalRepresentation_trampoline(SB),NOSPLIT,$0-0 JMP x509_CFStringCreateExternalRepresentation(SB) diff --git a/src/crypto/x509/internal/macos/security.go b/src/crypto/x509/internal/macos/security.go index ef64bda49fd258bf42807b3792d913076e6781a4..0b7958eaa2891b84039a80df1e12ef75fc304228 100644 --- a/src/crypto/x509/internal/macos/security.go +++ b/src/crypto/x509/internal/macos/security.go @@ -8,7 +8,6 @@ package macOS import ( "errors" - "fmt" "internal/abi" "strconv" "unsafe" @@ -51,6 +50,15 @@ const ( SecTrustSettingsDomainSystem ) +const ( + // various macOS error codes that can be returned from + // SecTrustEvaluateWithError that we can map to Go cert + // verification error types. + ErrSecCertificateExpired = -67818 + ErrSecHostNameMismatch = -67602 + ErrSecNotTrusted = -67843 +) + type OSStatus struct { call string status int32 @@ -190,17 +198,18 @@ func x509_SecTrustGetResult_trampoline() //go:cgo_import_dynamic x509_SecTrustEvaluateWithError SecTrustEvaluateWithError "/System/Library/Frameworks/Security.framework/Versions/A/Security" -func SecTrustEvaluateWithError(trustObj CFRef) error { +func SecTrustEvaluateWithError(trustObj CFRef) (int, error) { var errRef CFRef ret := syscall(abi.FuncPCABI0(x509_SecTrustEvaluateWithError_trampoline), uintptr(trustObj), uintptr(unsafe.Pointer(&errRef)), 0, 0, 0, 0) if int32(ret) != 1 { errStr := CFErrorCopyDescription(errRef) - err := fmt.Errorf("x509: %s", CFStringToString(errStr)) + err := errors.New(CFStringToString(errStr)) + errCode := CFErrorGetCode(errRef) CFRelease(errRef) CFRelease(errStr) - return err + return errCode, err } - return nil + return 0, nil } func x509_SecTrustEvaluateWithError_trampoline() diff --git a/src/crypto/x509/root_darwin.go b/src/crypto/x509/root_darwin.go index ad365f577e79634644672a03a47294931776e5d7..c35885ace8358985204235759f0b93b892dd14fa 100644 --- a/src/crypto/x509/root_darwin.go +++ b/src/crypto/x509/root_darwin.go @@ -7,6 +7,7 @@ package x509 import ( macOS "crypto/x509/internal/macos" "errors" + "fmt" ) func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { @@ -54,8 +55,17 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate // always enforce its SCT requirements, and there are still _some_ people // using TLS or OCSP for that. - if err := macOS.SecTrustEvaluateWithError(trustObj); err != nil { - return nil, err + if ret, err := macOS.SecTrustEvaluateWithError(trustObj); err != nil { + switch ret { + case macOS.ErrSecCertificateExpired: + return nil, CertificateInvalidError{c, Expired, err.Error()} + case macOS.ErrSecHostNameMismatch: + return nil, HostnameError{c, opts.DNSName} + case macOS.ErrSecNotTrusted: + return nil, UnknownAuthorityError{Cert: c} + default: + return nil, fmt.Errorf("x509: %s", err) + } } chain := [][]*Certificate{{}} diff --git a/src/crypto/x509/root_darwin_test.go b/src/crypto/x509/root_darwin_test.go index 90a464f624960a75bd39d390d7e1d492a499a511..299cecf5563f682a2f18f1d51b440c0329d7b41c 100644 --- a/src/crypto/x509/root_darwin_test.go +++ b/src/crypto/x509/root_darwin_test.go @@ -42,23 +42,23 @@ func TestPlatformVerifier(t *testing.T) { { name: "expired leaf", host: "expired.badssl.com", - expectedErr: "x509: “*.badssl.com†certificate is expired", + expectedErr: "x509: certificate has expired or is not yet valid: “*.badssl.com†certificate is expired", }, { name: "wrong host for leaf", host: "wrong.host.badssl.com", verifyName: "wrong.host.badssl.com", - expectedErr: "x509: “*.badssl.com†certificate name does not match input", + expectedErr: "x509: certificate is valid for *.badssl.com, badssl.com, not wrong.host.badssl.com", }, { name: "self-signed leaf", host: "self-signed.badssl.com", - expectedErr: "x509: “*.badssl.com†certificate is not trusted", + expectedErr: "x509: certificate signed by unknown authority", }, { name: "untrusted root", host: "untrusted-root.badssl.com", - expectedErr: "x509: “BadSSL Untrusted Root Certificate Authority†certificate is not trusted", + expectedErr: "x509: certificate signed by unknown authority", }, { name: "revoked leaf", @@ -74,7 +74,7 @@ func TestPlatformVerifier(t *testing.T) { name: "expired leaf (custom time)", host: "google.com", verifyTime: time.Time{}.Add(time.Hour), - expectedErr: "x509: “*.google.com†certificate is expired", + expectedErr: "x509: certificate has expired or is not yet valid: “*.google.com†certificate is expired", }, { name: "valid chain (custom time)", diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go index 100a8ff0f94ae4c134d7ba61beacbd855fa4f81c..c3ef503b27784b52fa93d196d3ff59d3db5dee44 100644 --- a/src/crypto/x509/verify_test.go +++ b/src/crypto/x509/verify_test.go @@ -540,8 +540,8 @@ func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) { func TestGoVerify(t *testing.T) { // Temporarily enable SHA-1 verification since a number of test chains // require it. TODO(filippo): regenerate test chains. - defer func(old bool) { debugAllowSHA1 = old }(debugAllowSHA1) - debugAllowSHA1 = true + t.Setenv("GODEBUG", "x509sha1=1") + for _, test := range verifyTests { t.Run(test.name, func(t *testing.T) { testVerify(t, test, false) diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index 85720b3ccbef9d74e982fd23bec93fac406b55cf..dc470f53f2dbcb62480cd83c12bc993f752ea7b4 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -730,9 +730,6 @@ type Certificate struct { // involves algorithms that are not currently implemented. var ErrUnsupportedAlgorithm = errors.New("x509: cannot verify signature: algorithm unimplemented") -// debugAllowSHA1 allows SHA-1 signatures. See issue 41682. -var debugAllowSHA1 = godebug.Get("x509sha1") == "1" - // An InsecureAlgorithmError indicates that the SignatureAlgorithm used to // generate the signature is not secure, and the signature has been rejected. // @@ -792,7 +789,7 @@ func (c *Certificate) CheckSignatureFrom(parent *Certificate) error { // TODO(agl): don't ignore the path length constraint. - return checkSignature(c.SignatureAlgorithm, c.RawTBSCertificate, c.Signature, parent.PublicKey, debugAllowSHA1) + return checkSignature(c.SignatureAlgorithm, c.RawTBSCertificate, c.Signature, parent.PublicKey, false) } // CheckSignature verifies that signature is a valid signature over signed from @@ -839,7 +836,8 @@ func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey case crypto.MD5: return InsecureAlgorithmError(algo) case crypto.SHA1: - if !allowSHA1 { + // SHA-1 signatures are mostly disabled. See go.dev/issue/41682. + if !allowSHA1 && godebug.Get("x509sha1") != "1" { return InsecureAlgorithmError(algo) } fallthrough diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index 6c1e95a2032d4438bbef936899be014b19a7e141..48a864057df486c91e45ea1977724b83bc2bef0d 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -1864,9 +1864,7 @@ func TestSHA1(t *testing.T) { t.Fatalf("certificate verification returned %v (%T), wanted InsecureAlgorithmError", err, err) } - defer func(old bool) { debugAllowSHA1 = old }(debugAllowSHA1) - debugAllowSHA1 = true - + t.Setenv("GODEBUG", "x509sha1=1") if err = cert.CheckSignatureFrom(cert); err != nil { t.Fatalf("SHA-1 certificate did not verify with GODEBUG=x509sha1=1: %v", err) } @@ -3335,8 +3333,7 @@ func TestLargeOID(t *testing.T) { } func TestDisableSHA1ForCertOnly(t *testing.T) { - defer func(old bool) { debugAllowSHA1 = old }(debugAllowSHA1) - debugAllowSHA1 = false + t.Setenv("GODEBUG", "") tmpl := &Certificate{ SerialNumber: big.NewInt(1), diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go index 34f302a5cf54d60e6e5cf9d163d4ad8f6f9c7a6b..eea2924f1ad6274f48fdbe0f5c63bce07a1be41c 100644 --- a/src/encoding/gob/decode.go +++ b/src/encoding/gob/decode.go @@ -871,8 +871,13 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg return &op } +var maxIgnoreNestingDepth = 10000 + // decIgnoreOpFor returns the decoding op for a field that has no destination. -func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp) *decOp { +func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp, depth int) *decOp { + if depth > maxIgnoreNestingDepth { + error_(errors.New("invalid nesting depth")) + } // If this type is already in progress, it's a recursive type (e.g. map[string]*T). // Return the pointer to the op we're already building. if opPtr := inProgress[wireId]; opPtr != nil { @@ -896,7 +901,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp) errorf("bad data: undefined type %s", wireId.string()) case wire.ArrayT != nil: elemId := wire.ArrayT.Elem - elemOp := dec.decIgnoreOpFor(elemId, inProgress) + elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1) op = func(i *decInstr, state *decoderState, value reflect.Value) { state.dec.ignoreArray(state, *elemOp, wire.ArrayT.Len) } @@ -904,15 +909,15 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp) case wire.MapT != nil: keyId := dec.wireType[wireId].MapT.Key elemId := dec.wireType[wireId].MapT.Elem - keyOp := dec.decIgnoreOpFor(keyId, inProgress) - elemOp := dec.decIgnoreOpFor(elemId, inProgress) + keyOp := dec.decIgnoreOpFor(keyId, inProgress, depth+1) + elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1) op = func(i *decInstr, state *decoderState, value reflect.Value) { state.dec.ignoreMap(state, *keyOp, *elemOp) } case wire.SliceT != nil: elemId := wire.SliceT.Elem - elemOp := dec.decIgnoreOpFor(elemId, inProgress) + elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1) op = func(i *decInstr, state *decoderState, value reflect.Value) { state.dec.ignoreSlice(state, *elemOp) } @@ -1073,7 +1078,7 @@ func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *de func (dec *Decoder) compileIgnoreSingle(remoteId typeId) *decEngine { engine := new(decEngine) engine.instr = make([]decInstr, 1) // one item - op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp)) + op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp), 0) ovfl := overflow(dec.typeString(remoteId)) engine.instr[0] = decInstr{*op, 0, nil, ovfl} engine.numInstr = 1 @@ -1118,7 +1123,7 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn localField, present := srt.FieldByName(wireField.Name) // TODO(r): anonymous names if !present || !isExported(wireField.Name) { - op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp)) + op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp), 0) engine.instr[fieldnum] = decInstr{*op, fieldnum, nil, ovfl} continue } diff --git a/src/encoding/gob/gobencdec_test.go b/src/encoding/gob/gobencdec_test.go index 1d5dde22a4eeb50b490b04272a476e11d6d46371..3d49887c016767805c704a398c37b86fd5520b0c 100644 --- a/src/encoding/gob/gobencdec_test.go +++ b/src/encoding/gob/gobencdec_test.go @@ -12,6 +12,7 @@ import ( "fmt" "io" "net" + "reflect" "strings" "testing" "time" @@ -796,3 +797,26 @@ func TestNetIP(t *testing.T) { t.Errorf("decoded to %v, want 1.2.3.4", ip.String()) } } + +func TestIngoreDepthLimit(t *testing.T) { + // We don't test the actual depth limit because it requires building an + // extremely large message, which takes quite a while. + oldNestingDepth := maxIgnoreNestingDepth + maxIgnoreNestingDepth = 100 + defer func() { maxIgnoreNestingDepth = oldNestingDepth }() + b := new(bytes.Buffer) + enc := NewEncoder(b) + typ := reflect.TypeOf(int(0)) + nested := reflect.ArrayOf(1, typ) + for i := 0; i < 100; i++ { + nested = reflect.ArrayOf(1, nested) + } + badStruct := reflect.New(reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}})) + enc.Encode(badStruct.Interface()) + dec := NewDecoder(b) + var output struct{ Hello int } + expectedErr := "invalid nesting depth" + if err := dec.Decode(&output); err == nil || err.Error() != expectedErr { + t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err) + } +} diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go index 0701e18625953e0b18abb44caea0ede01c57a51f..cfd4407f7130a7bbf81f8b31c0c320b7081c49ba 100644 --- a/src/encoding/xml/read.go +++ b/src/encoding/xml/read.go @@ -148,7 +148,7 @@ func (d *Decoder) DecodeElement(v any, start *StartElement) error { if val.Kind() != reflect.Pointer { return errors.New("non-pointer passed to Unmarshal") } - return d.unmarshal(val.Elem(), start) + return d.unmarshal(val.Elem(), start, 0) } // An UnmarshalError represents an error in the unmarshaling process. @@ -304,8 +304,15 @@ var ( textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() ) +const maxUnmarshalDepth = 10000 + +var errExeceededMaxUnmarshalDepth = errors.New("exceeded max depth") + // Unmarshal a single XML element into val. -func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error { +func (d *Decoder) unmarshal(val reflect.Value, start *StartElement, depth int) error { + if depth >= maxUnmarshalDepth { + return errExeceededMaxUnmarshalDepth + } // Find start element if we need it. if start == nil { for { @@ -398,7 +405,7 @@ func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error { v.Set(reflect.Append(val, reflect.Zero(v.Type().Elem()))) // Recur to read element into slice. - if err := d.unmarshal(v.Index(n), start); err != nil { + if err := d.unmarshal(v.Index(n), start, depth+1); err != nil { v.SetLen(n) return err } @@ -521,13 +528,15 @@ Loop: case StartElement: consumed := false if sv.IsValid() { - consumed, err = d.unmarshalPath(tinfo, sv, nil, &t) + // unmarshalPath can call unmarshal, so we need to pass the depth through so that + // we can continue to enforce the maximum recusion limit. + consumed, err = d.unmarshalPath(tinfo, sv, nil, &t, depth) if err != nil { return err } if !consumed && saveAny.IsValid() { consumed = true - if err := d.unmarshal(saveAny, &t); err != nil { + if err := d.unmarshal(saveAny, &t, depth+1); err != nil { return err } } @@ -672,7 +681,7 @@ func copyValue(dst reflect.Value, src []byte) (err error) { // The consumed result tells whether XML elements have been consumed // from the Decoder until start's matching end element, or if it's // still untouched because start is uninteresting for sv's fields. -func (d *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) { +func (d *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement, depth int) (consumed bool, err error) { recurse := false Loop: for i := range tinfo.fields { @@ -687,7 +696,7 @@ Loop: } if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local { // It's a perfect match, unmarshal the field. - return true, d.unmarshal(finfo.value(sv, initNilPointers), start) + return true, d.unmarshal(finfo.value(sv, initNilPointers), start, depth+1) } if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local { // It's a prefix for the field. Break and recurse @@ -716,7 +725,9 @@ Loop: } switch t := tok.(type) { case StartElement: - consumed2, err := d.unmarshalPath(tinfo, sv, parents, &t) + // the recursion depth of unmarshalPath is limited to the path length specified + // by the struct field tag, so we don't increment the depth here. + consumed2, err := d.unmarshalPath(tinfo, sv, parents, &t, depth) if err != nil { return true, err } @@ -732,12 +743,12 @@ Loop: } // Skip reads tokens until it has consumed the end element -// matching the most recent start element already consumed. -// It recurs if it encounters a start element, so it can be used to -// skip nested structures. +// matching the most recent start element already consumed, +// skipping nested structures. // It returns nil if it finds an end element matching the start // element; otherwise it returns an error describing the problem. func (d *Decoder) Skip() error { + var depth int64 for { tok, err := d.Token() if err != nil { @@ -745,11 +756,12 @@ func (d *Decoder) Skip() error { } switch tok.(type) { case StartElement: - if err := d.Skip(); err != nil { - return err - } + depth++ case EndElement: - return nil + if depth == 0 { + return nil + } + depth-- } } } diff --git a/src/encoding/xml/read_test.go b/src/encoding/xml/read_test.go index 391fe731a800f5af9d95c030c4d3095231d2eb5e..1362f7f2874c832d91c5b71491bdcb2f8dad3eaa 100644 --- a/src/encoding/xml/read_test.go +++ b/src/encoding/xml/read_test.go @@ -5,6 +5,8 @@ package xml import ( + "bytes" + "errors" "io" "reflect" "strings" @@ -1079,3 +1081,32 @@ func TestUnmarshalWhitespaceAttrs(t *testing.T) { t.Fatalf("whitespace attrs: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want) } } + +func TestCVE202230633(t *testing.T) { + if testing.Short() { + t.Skip("test requires significant memory") + } + defer func() { + p := recover() + if p != nil { + t.Fatal("Unmarshal panicked") + } + }() + var example struct { + Things []string + } + Unmarshal(bytes.Repeat([]byte("<a>"), 17_000_000), &example) +} + +func TestCVE202228131(t *testing.T) { + type nested struct { + Parent *nested `xml:",any"` + } + var n nested + err := Unmarshal(bytes.Repeat([]byte("<a>"), maxUnmarshalDepth+1), &n) + if err == nil { + t.Fatal("Unmarshal did not fail") + } else if !errors.Is(err, errExeceededMaxUnmarshalDepth) { + t.Fatalf("Unmarshal unexpected error: got %q, want %q", err, errExeceededMaxUnmarshalDepth) + } +} diff --git a/src/go.mod b/src/go.mod index bd6308add021dc163fdf5b44cd384da3eb2414fe..e11c6d7df80053e2c47d8d26047377629d4fc6b3 100644 --- a/src/go.mod +++ b/src/go.mod @@ -4,10 +4,10 @@ go 1.18 require ( golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 - golang.org/x/net v0.0.0-20211209124913-491a49abca63 + golang.org/x/net v0.0.0-20221214163811-6143a133e5c9 ) require ( - golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 // indirect ) diff --git a/src/go.sum b/src/go.sum index 8bf08531de62dd57ef513ec15fc4855b99c8c4e9..d2bfed64dc97389e5ceba0664d3b55568fe90b0e 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,8 +1,8 @@ golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E= -golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/net v0.0.0-20221214163811-6143a133e5c9 h1:gcbGP3ZkgsHGpX/48qvg7Q/YmTtzZRWc/zpvN8XGSBg= +golang.org/x/net v0.0.0-20221214163811-6143a133e5c9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y= golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0= diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 72465659dc24e871b06fc56f923aba2a3bf73e5c..20a3d0fb86aa18bc1a6f7ae664cb91b27975a475 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -168,6 +168,7 @@ var depsRules = ` io/fs < internal/testlog < internal/poll + < internal/safefilepath < os < os/signal; diff --git a/src/go/parser/interface.go b/src/go/parser/interface.go index e4f8c281ea734e80feac4111581fb6a72f7f9c5f..3eea729e050342c2d29c4afcba62ac227268af18 100644 --- a/src/go/parser/interface.go +++ b/src/go/parser/interface.go @@ -97,8 +97,11 @@ func ParseFile(fset *token.FileSet, filename string, src any, mode Mode) (f *ast defer func() { if e := recover(); e != nil { // resume same panic if it's not a bailout - if _, ok := e.(bailout); !ok { + bail, ok := e.(bailout) + if !ok { panic(e) + } else if bail.msg != "" { + p.errors.Add(p.file.Position(bail.pos), bail.msg) } } @@ -203,8 +206,11 @@ func ParseExprFrom(fset *token.FileSet, filename string, src any, mode Mode) (ex defer func() { if e := recover(); e != nil { // resume same panic if it's not a bailout - if _, ok := e.(bailout); !ok { + bail, ok := e.(bailout) + if !ok { panic(e) + } else if bail.msg != "" { + p.errors.Add(p.file.Position(bail.pos), bail.msg) } } p.errors.Sort() diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index 51a3c3e67f9d8dbe9733a449c96f6475715530fe..c34cceab0f03a3d0eae652f0e2762fb817a4dfce 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -60,6 +60,10 @@ type parser struct { inRhs bool // if set, the parser is parsing a rhs expression imports []*ast.ImportSpec // list of imports + + // nestLev is used to track and limit the recursion depth + // during parsing. + nestLev int } func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mode) { @@ -109,6 +113,24 @@ func un(p *parser) { p.printTrace(")") } +// maxNestLev is the deepest we're willing to recurse during parsing +const maxNestLev int = 1e5 + +func incNestLev(p *parser) *parser { + p.nestLev++ + if p.nestLev > maxNestLev { + p.error(p.pos, "exceeded max nesting depth") + panic(bailout{}) + } + return p +} + +// decNestLev is used to track nesting depth during parsing to prevent stack exhaustion. +// It is used along with incNestLev in a similar fashion to how un and trace are used. +func decNestLev(p *parser) { + p.nestLev-- +} + // Advance to the next token. func (p *parser) next0() { // Because of one-token look-ahead, print the previous token @@ -221,8 +243,12 @@ func (p *parser) next() { } } -// A bailout panic is raised to indicate early termination. -type bailout struct{} +// A bailout panic is raised to indicate early termination. pos and msg are +// only populated when bailing out of object resolution. +type bailout struct { + pos token.Pos + msg string +} func (p *parser) error(pos token.Pos, msg string) { if p.trace { @@ -1252,6 +1278,8 @@ func (p *parser) parseTypeInstance(typ ast.Expr) ast.Expr { } func (p *parser) tryIdentOrType() ast.Expr { + defer decNestLev(incNestLev(p)) + switch p.tok { case token.IDENT: typ := p.parseTypeName(nil) @@ -1664,7 +1692,13 @@ func (p *parser) parsePrimaryExpr(x ast.Expr) ast.Expr { if x == nil { x = p.parseOperand() } - for { + // We track the nesting here rather than at the entry for the function, + // since it can iteratively produce a nested output, and we want to + // limit how deep a structure we generate. + var n int + defer func() { p.nestLev -= n }() + for n = 1; ; n++ { + incNestLev(p) switch p.tok { case token.PERIOD: p.next() @@ -1724,6 +1758,8 @@ func (p *parser) parsePrimaryExpr(x ast.Expr) ast.Expr { } func (p *parser) parseUnaryExpr() ast.Expr { + defer decNestLev(incNestLev(p)) + if p.trace { defer un(trace(p, "UnaryExpr")) } @@ -1813,7 +1849,13 @@ func (p *parser) parseBinaryExpr(x ast.Expr, prec1 int, check bool) ast.Expr { if x == nil { x = p.parseUnaryExpr() } - for { + // We track the nesting here rather than at the entry for the function, + // since it can iteratively produce a nested output, and we want to + // limit how deep a structure we generate. + var n int + defer func() { p.nestLev -= n }() + for n = 1; ; n++ { + incNestLev(p) op, oprec := p.tokPrec() if oprec < prec1 { return x @@ -2123,6 +2165,8 @@ func (p *parser) parseIfHeader() (init ast.Stmt, cond ast.Expr) { } func (p *parser) parseIfStmt() *ast.IfStmt { + defer decNestLev(incNestLev(p)) + if p.trace { defer un(trace(p, "IfStmt")) } @@ -2426,6 +2470,8 @@ func (p *parser) parseForStmt() ast.Stmt { } func (p *parser) parseStmt() (s ast.Stmt) { + defer decNestLev(incNestLev(p)) + if p.trace { defer un(trace(p, "Statement")) } diff --git a/src/go/parser/parser_test.go b/src/go/parser/parser_test.go index a4f882d3688195fb2c9dd7b9270828edcf0c4cd0..1a46c878663478c02673baaf07172f64577c15ef 100644 --- a/src/go/parser/parser_test.go +++ b/src/go/parser/parser_test.go @@ -10,6 +10,7 @@ import ( "go/ast" "go/token" "io/fs" + "runtime" "strings" "testing" ) @@ -577,3 +578,171 @@ type x int // comment t.Errorf("got %q, want %q", comment, "// comment") } } + +var parseDepthTests = []struct { + name string + format string + // multipler is used when a single statement may result in more than one + // change in the depth level, for instance "1+(..." produces a BinaryExpr + // followed by a UnaryExpr, which increments the depth twice. The test + // case comment explains which nodes are triggering the multiple depth + // changes. + parseMultiplier int + // scope is true if we should also test the statement for the resolver scope + // depth limit. + scope bool + // scopeMultiplier does the same as parseMultiplier, but for the scope + // depths. + scopeMultiplier int +}{ + // The format expands the part inside « » many times. + // A second set of brackets nested inside the first stops the repetition, + // so that for example «(«1»)» expands to (((...((((1))))...))). + {name: "array", format: "package main; var x «[1]»int"}, + {name: "slice", format: "package main; var x «[]»int"}, + {name: "struct", format: "package main; var x «struct { X «int» }»", scope: true}, + {name: "pointer", format: "package main; var x «*»int"}, + {name: "func", format: "package main; var x «func()»int", scope: true}, + {name: "chan", format: "package main; var x «chan »int"}, + {name: "chan2", format: "package main; var x «<-chan »int"}, + {name: "interface", format: "package main; var x «interface { M() «int» }»", scope: true, scopeMultiplier: 2}, // Scopes: InterfaceType, FuncType + {name: "map", format: "package main; var x «map[int]»int"}, + {name: "slicelit", format: "package main; var x = «[]any{«»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit + {name: "arraylit", format: "package main; var x = «[1]any{«nil»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit + {name: "structlit", format: "package main; var x = «struct{x any}{«nil»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit + {name: "maplit", format: "package main; var x = «map[int]any{1:«nil»}»", parseMultiplier: 2}, // Parser nodes: CompositeLit, KeyValueExpr + {name: "dot", format: "package main; var x = «x.»x"}, + {name: "index", format: "package main; var x = x«[1]»"}, + {name: "slice", format: "package main; var x = x«[1:2]»"}, + {name: "slice3", format: "package main; var x = x«[1:2:3]»"}, + {name: "dottype", format: "package main; var x = x«.(any)»"}, + {name: "callseq", format: "package main; var x = x«()»"}, + {name: "methseq", format: "package main; var x = x«.m()»", parseMultiplier: 2}, // Parser nodes: SelectorExpr, CallExpr + {name: "binary", format: "package main; var x = «1+»1"}, + {name: "binaryparen", format: "package main; var x = «1+(«1»)»", parseMultiplier: 2}, // Parser nodes: BinaryExpr, ParenExpr + {name: "unary", format: "package main; var x = «^»1"}, + {name: "addr", format: "package main; var x = «& »x"}, + {name: "star", format: "package main; var x = «*»x"}, + {name: "recv", format: "package main; var x = «<-»x"}, + {name: "call", format: "package main; var x = «f(«1»)»", parseMultiplier: 2}, // Parser nodes: Ident, CallExpr + {name: "conv", format: "package main; var x = «(*T)(«1»)»", parseMultiplier: 2}, // Parser nodes: ParenExpr, CallExpr + {name: "label", format: "package main; func main() { «Label:» }"}, + {name: "if", format: "package main; func main() { «if true { «» }»}", parseMultiplier: 2, scope: true, scopeMultiplier: 2}, // Parser nodes: IfStmt, BlockStmt. Scopes: IfStmt, BlockStmt + {name: "ifelse", format: "package main; func main() { «if true {} else » {} }", scope: true}, + {name: "switch", format: "package main; func main() { «switch { default: «» }»}", scope: true, scopeMultiplier: 2}, // Scopes: TypeSwitchStmt, CaseClause + {name: "typeswitch", format: "package main; func main() { «switch x.(type) { default: «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: TypeSwitchStmt, CaseClause + {name: "for0", format: "package main; func main() { «for { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: ForStmt, BlockStmt + {name: "for1", format: "package main; func main() { «for x { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: ForStmt, BlockStmt + {name: "for3", format: "package main; func main() { «for f(); g(); h() { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: ForStmt, BlockStmt + {name: "forrange0", format: "package main; func main() { «for range x { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: RangeStmt, BlockStmt + {name: "forrange1", format: "package main; func main() { «for x = range z { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: RangeStmt, BlockStmt + {name: "forrange2", format: "package main; func main() { «for x, y = range z { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: RangeStmt, BlockStmt + {name: "go", format: "package main; func main() { «go func() { «» }()» }", parseMultiplier: 2, scope: true}, // Parser nodes: GoStmt, FuncLit + {name: "defer", format: "package main; func main() { «defer func() { «» }()» }", parseMultiplier: 2, scope: true}, // Parser nodes: DeferStmt, FuncLit + {name: "select", format: "package main; func main() { «select { default: «» }» }", scope: true}, +} + +// split splits pre«mid»post into pre, mid, post. +// If the string does not have that form, split returns x, "", "". +func split(x string) (pre, mid, post string) { + start, end := strings.Index(x, "«"), strings.LastIndex(x, "»") + if start < 0 || end < 0 { + return x, "", "" + } + return x[:start], x[start+len("«") : end], x[end+len("»"):] +} + +func TestParseDepthLimit(t *testing.T) { + if runtime.GOARCH == "wasm" { + t.Skip("causes call stack exhaustion on js/wasm") + } + for _, tt := range parseDepthTests { + for _, size := range []string{"small", "big"} { + t.Run(tt.name+"/"+size, func(t *testing.T) { + n := maxNestLev + 1 + if tt.parseMultiplier > 0 { + n /= tt.parseMultiplier + } + if size == "small" { + // Decrease the number of statements by 10, in order to check + // that we do not fail when under the limit. 10 is used to + // provide some wiggle room for cases where the surrounding + // scaffolding syntax adds some noise to the depth that changes + // on a per testcase basis. + n -= 10 + } + + pre, mid, post := split(tt.format) + if strings.Contains(mid, "«") { + left, base, right := split(mid) + mid = strings.Repeat(left, n) + base + strings.Repeat(right, n) + } else { + mid = strings.Repeat(mid, n) + } + input := pre + mid + post + + fset := token.NewFileSet() + _, err := ParseFile(fset, "", input, ParseComments|SkipObjectResolution) + if size == "small" { + if err != nil { + t.Errorf("ParseFile(...): %v (want success)", err) + } + } else { + expected := "exceeded max nesting depth" + if err == nil || !strings.HasSuffix(err.Error(), expected) { + t.Errorf("ParseFile(...) = _, %v, want %q", err, expected) + } + } + }) + } + } +} + +func TestScopeDepthLimit(t *testing.T) { + if runtime.GOARCH == "wasm" { + t.Skip("causes call stack exhaustion on js/wasm") + } + for _, tt := range parseDepthTests { + if !tt.scope { + continue + } + for _, size := range []string{"small", "big"} { + t.Run(tt.name+"/"+size, func(t *testing.T) { + n := maxScopeDepth + 1 + if tt.scopeMultiplier > 0 { + n /= tt.scopeMultiplier + } + if size == "small" { + // Decrease the number of statements by 10, in order to check + // that we do not fail when under the limit. 10 is used to + // provide some wiggle room for cases where the surrounding + // scaffolding syntax adds some noise to the depth that changes + // on a per testcase basis. + n -= 10 + } + + pre, mid, post := split(tt.format) + if strings.Contains(mid, "«") { + left, base, right := split(mid) + mid = strings.Repeat(left, n) + base + strings.Repeat(right, n) + } else { + mid = strings.Repeat(mid, n) + } + input := pre + mid + post + + fset := token.NewFileSet() + _, err := ParseFile(fset, "", input, DeclarationErrors) + if size == "small" { + if err != nil { + t.Errorf("ParseFile(...): %v (want success)", err) + } + } else { + expected := "exceeded max scope depth during object resolution" + if err == nil || !strings.HasSuffix(err.Error(), expected) { + t.Errorf("ParseFile(...) = _, %v, want %q", err, expected) + } + } + }) + } + } +} diff --git a/src/go/parser/resolver.go b/src/go/parser/resolver.go index d66a194c12bb0b589050583121e8956f5a22e6e2..82ba48cd9696251246a65b09925e15b11b051d34 100644 --- a/src/go/parser/resolver.go +++ b/src/go/parser/resolver.go @@ -54,6 +54,8 @@ func resolveFile(file *ast.File, handle *token.File, declErr func(token.Pos, str file.Unresolved = r.unresolved[0:i] } +const maxScopeDepth int = 1e3 + type resolver struct { handle *token.File declErr func(token.Pos, string) @@ -85,16 +87,19 @@ func (r *resolver) sprintf(format string, args ...any) string { } func (r *resolver) openScope(pos token.Pos) { + r.depth++ + if r.depth > maxScopeDepth { + panic(bailout{pos: pos, msg: "exceeded max scope depth during object resolution"}) + } if debugResolve { r.trace("opening scope @%v", pos) - r.depth++ } r.topScope = ast.NewScope(r.topScope) } func (r *resolver) closeScope() { + r.depth-- if debugResolve { - r.depth-- r.trace("closing scope") } r.topScope = r.topScope.Outer diff --git a/src/go/types/issues_test.go b/src/go/types/issues_test.go index bd98f481778437be635f6de78114198d62fe939b..2892aab38e33d5de104d6afdf84c7721a01b0985 100644 --- a/src/go/types/issues_test.go +++ b/src/go/types/issues_test.go @@ -664,3 +664,40 @@ func TestIssue50646(t *testing.T) { t.Errorf("comparable not assignable to any") } } + +func TestIssue55030(t *testing.T) { + // makeSig makes the signature func(typ...) + makeSig := func(typ Type) { + par := NewVar(token.NoPos, nil, "", typ) + params := NewTuple(par) + NewSignatureType(nil, nil, nil, params, nil, true) + } + + // makeSig must not panic for the following (example) types: + // []int + makeSig(NewSlice(Typ[Int])) + + // string + makeSig(Typ[String]) + + // P where P's core type is string + { + P := NewTypeName(token.NoPos, nil, "P", nil) // [P string] + makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{Typ[String]}))) + } + + // P where P's core type is an (unnamed) slice + { + P := NewTypeName(token.NoPos, nil, "P", nil) // [P []int] + makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{NewSlice(Typ[Int])}))) + } + + // P where P's core type is bytestring (i.e., string or []byte) + { + t1 := NewTerm(true, Typ[String]) // ~string + t2 := NewTerm(false, NewSlice(Typ[Byte])) // []byte + u := NewUnion([]*Term{t1, t2}) // ~string | []byte + P := NewTypeName(token.NoPos, nil, "P", nil) // [P ~string | []byte] + makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u}))) + } +} diff --git a/src/go/types/signature.go b/src/go/types/signature.go index a340ac701eaa53d535bcdb4dbd64b8793791efa0..d22646d7a87817c91fd39b1ffcb7ded659d067e2 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -5,6 +5,7 @@ package types import ( + "fmt" "go/ast" "go/token" ) @@ -41,16 +42,18 @@ func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { // NewSignatureType creates a new function type for the given receiver, // receiver type parameters, type parameters, parameters, and results. If // variadic is set, params must hold at least one parameter and the last -// parameter must be of unnamed slice type. If recv is non-nil, typeParams must -// be empty. If recvTypeParams is non-empty, recv must be non-nil. +// parameter's core type must be of unnamed slice or bytestring type. +// If recv is non-nil, typeParams must be empty. If recvTypeParams is +// non-empty, recv must be non-nil. func NewSignatureType(recv *Var, recvTypeParams, typeParams []*TypeParam, params, results *Tuple, variadic bool) *Signature { if variadic { n := params.Len() if n == 0 { panic("variadic function must have at least one parameter") } - if _, ok := params.At(n - 1).typ.(*Slice); !ok { - panic("variadic parameter must be of unnamed slice type") + core := coreString(params.At(n - 1).typ) + if _, ok := core.(*Slice); !ok && !isString(core) { + panic(fmt.Sprintf("got %s, want variadic parameter with unnamed slice type or string as core type", core.String())) } } sig := &Signature{recv: recv, params: params, results: results, variadic: variadic} diff --git a/src/internal/poll/sock_cloexec.go b/src/internal/poll/sock_cloexec.go index d849fda0b06f87584c16b82d3333025f3e1f1d57..4c70abd9b1441ee349250c23391e14baa0adf17e 100644 --- a/src/internal/poll/sock_cloexec.go +++ b/src/internal/poll/sock_cloexec.go @@ -5,7 +5,7 @@ // This file implements accept for platforms that provide a fast path for // setting SetNonblock and CloseOnExec. -//go:build dragonfly || freebsd || illumos || linux || netbsd || openbsd +//go:build dragonfly || freebsd || illumos || (linux && !arm) || netbsd || openbsd package poll diff --git a/src/internal/poll/sock_cloexec_accept.go b/src/internal/poll/sock_cloexec_accept.go new file mode 100644 index 0000000000000000000000000000000000000000..4b86de59e092997bc7bc99abfedd5e6ad646bc3e --- /dev/null +++ b/src/internal/poll/sock_cloexec_accept.go @@ -0,0 +1,51 @@ +// Copyright 2013 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. + +// This file implements accept for platforms that provide a fast path for +// setting SetNonblock and CloseOnExec, but don't necessarily have accept4. +// This is the code we used for accept in Go 1.17 and earlier. +// On Linux the accept4 system call was introduced in 2.6.28 kernel, +// and our minimum requirement is 2.6.32, so we simplified the function. +// Unfortunately, on ARM accept4 wasn't added until 2.6.36, so for ARM +// only we continue using the older code. + +//go:build linux && arm + +package poll + +import "syscall" + +// Wrapper around the accept system call that marks the returned file +// descriptor as nonblocking and close-on-exec. +func accept(s int) (int, syscall.Sockaddr, string, error) { + ns, sa, err := Accept4Func(s, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC) + switch err { + case nil: + return ns, sa, "", nil + default: // errors other than the ones listed + return -1, sa, "accept4", err + case syscall.ENOSYS: // syscall missing + case syscall.EINVAL: // some Linux use this instead of ENOSYS + case syscall.EACCES: // some Linux use this instead of ENOSYS + case syscall.EFAULT: // some Linux use this instead of ENOSYS + } + + // See ../syscall/exec_unix.go for description of ForkLock. + // It is probably okay to hold the lock across syscall.Accept + // because we have put fd.sysfd into non-blocking mode. + // However, a call to the File method will put it back into + // blocking mode. We can't take that risk, so no use of ForkLock here. + ns, sa, err = AcceptFunc(s) + if err == nil { + syscall.CloseOnExec(ns) + } + if err != nil { + return -1, nil, "accept", err + } + if err = syscall.SetNonblock(ns, true); err != nil { + CloseFunc(ns) + return -1, nil, "setnonblock", err + } + return ns, sa, "", nil +} diff --git a/src/internal/safefilepath/path.go b/src/internal/safefilepath/path.go new file mode 100644 index 0000000000000000000000000000000000000000..0f0a270c3034be8de47421d3808497a432e42102 --- /dev/null +++ b/src/internal/safefilepath/path.go @@ -0,0 +1,21 @@ +// Copyright 2022 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. + +// Package safefilepath manipulates operating-system file paths. +package safefilepath + +import ( + "errors" +) + +var errInvalidPath = errors.New("invalid path") + +// FromFS converts a slash-separated path into an operating-system path. +// +// FromFS returns an error if the path cannot be represented by the operating +// system. For example, paths containing '\' and ':' characters are rejected +// on Windows. +func FromFS(path string) (string, error) { + return fromFS(path) +} diff --git a/src/internal/safefilepath/path_other.go b/src/internal/safefilepath/path_other.go new file mode 100644 index 0000000000000000000000000000000000000000..f93da18680d01c1fc30b8613183905acc20efac1 --- /dev/null +++ b/src/internal/safefilepath/path_other.go @@ -0,0 +1,23 @@ +// Copyright 2022 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. + +//go:build !windows + +package safefilepath + +import "runtime" + +func fromFS(path string) (string, error) { + if runtime.GOOS == "plan9" { + if len(path) > 0 && path[0] == '#' { + return path, errInvalidPath + } + } + for i := range path { + if path[i] == 0 { + return "", errInvalidPath + } + } + return path, nil +} diff --git a/src/internal/safefilepath/path_test.go b/src/internal/safefilepath/path_test.go new file mode 100644 index 0000000000000000000000000000000000000000..dc662c18b3d03bb56043da8f70e1e2a46e164590 --- /dev/null +++ b/src/internal/safefilepath/path_test.go @@ -0,0 +1,88 @@ +// Copyright 2022 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. + +package safefilepath_test + +import ( + "internal/safefilepath" + "os" + "path/filepath" + "runtime" + "testing" +) + +type PathTest struct { + path, result string +} + +const invalid = "" + +var fspathtests = []PathTest{ + {".", "."}, + {"/a/b/c", "/a/b/c"}, + {"a\x00b", invalid}, +} + +var winreservedpathtests = []PathTest{ + {`a\b`, `a\b`}, + {`a:b`, `a:b`}, + {`a/b:c`, `a/b:c`}, + {`NUL`, `NUL`}, + {`./com1`, `./com1`}, + {`a/nul/b`, `a/nul/b`}, +} + +// Whether a reserved name with an extension is reserved or not varies by +// Windows version. +var winreservedextpathtests = []PathTest{ + {"nul.txt", "nul.txt"}, + {"a/nul.txt/b", "a/nul.txt/b"}, +} + +var plan9reservedpathtests = []PathTest{ + {`#c`, `#c`}, +} + +func TestFromFS(t *testing.T) { + switch runtime.GOOS { + case "windows": + if canWriteFile(t, "NUL") { + t.Errorf("can unexpectedly write a file named NUL on Windows") + } + if canWriteFile(t, "nul.txt") { + fspathtests = append(fspathtests, winreservedextpathtests...) + } else { + winreservedpathtests = append(winreservedpathtests, winreservedextpathtests...) + } + for i := range winreservedpathtests { + winreservedpathtests[i].result = invalid + } + for i := range fspathtests { + fspathtests[i].result = filepath.FromSlash(fspathtests[i].result) + } + case "plan9": + for i := range plan9reservedpathtests { + plan9reservedpathtests[i].result = invalid + } + } + tests := fspathtests + tests = append(tests, winreservedpathtests...) + tests = append(tests, plan9reservedpathtests...) + for _, test := range tests { + got, err := safefilepath.FromFS(test.path) + if (got == "") != (err != nil) { + t.Errorf(`FromFS(%q) = %q, %v; want "" only if err != nil`, test.path, got, err) + } + if got != test.result { + t.Errorf("FromFS(%q) = %q, %v; want %q", test.path, got, err, test.result) + } + } +} + +func canWriteFile(t *testing.T, name string) bool { + path := filepath.Join(t.TempDir(), name) + os.WriteFile(path, []byte("ok"), 0666) + b, _ := os.ReadFile(path) + return string(b) == "ok" +} diff --git a/src/internal/safefilepath/path_windows.go b/src/internal/safefilepath/path_windows.go new file mode 100644 index 0000000000000000000000000000000000000000..909c150edc87a281d94f648ae760163418e8edb1 --- /dev/null +++ b/src/internal/safefilepath/path_windows.go @@ -0,0 +1,95 @@ +// Copyright 2022 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. + +package safefilepath + +import ( + "syscall" + "unicode/utf8" +) + +func fromFS(path string) (string, error) { + if !utf8.ValidString(path) { + return "", errInvalidPath + } + for len(path) > 1 && path[0] == '/' && path[1] == '/' { + path = path[1:] + } + containsSlash := false + for p := path; p != ""; { + // Find the next path element. + i := 0 + dot := -1 + for i < len(p) && p[i] != '/' { + switch p[i] { + case 0, '\\', ':': + return "", errInvalidPath + case '.': + if dot < 0 { + dot = i + } + } + i++ + } + part := p[:i] + if i < len(p) { + containsSlash = true + p = p[i+1:] + } else { + p = "" + } + // Trim the extension and look for a reserved name. + base := part + if dot >= 0 { + base = part[:dot] + } + if isReservedName(base) { + if dot < 0 { + return "", errInvalidPath + } + // The path element is a reserved name with an extension. + // Some Windows versions consider this a reserved name, + // while others do not. Use FullPath to see if the name is + // reserved. + if p, _ := syscall.FullPath(part); len(p) >= 4 && p[:4] == `\\.\` { + return "", errInvalidPath + } + } + } + if containsSlash { + // We can't depend on strings, so substitute \ for / manually. + buf := []byte(path) + for i, b := range buf { + if b == '/' { + buf[i] = '\\' + } + } + path = string(buf) + } + return path, nil +} + +// isReservedName reports if name is a Windows reserved device name. +// It does not detect names with an extension, which are also reserved on some Windows versions. +// +// For details, search for PRN in +// https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file. +func isReservedName(name string) bool { + if 3 <= len(name) && len(name) <= 4 { + switch string([]byte{toUpper(name[0]), toUpper(name[1]), toUpper(name[2])}) { + case "CON", "PRN", "AUX", "NUL": + return len(name) == 3 + case "COM", "LPT": + return len(name) == 4 && '1' <= name[3] && name[3] <= '9' + } + } + return false +} + +func toUpper(c byte) byte { + if 'a' <= c && c <= 'z' { + return c - ('a' - 'A') + } + return c +} diff --git a/src/io/fs/glob.go b/src/io/fs/glob.go index 45d9cb61b9632af83bf9834ef99d47e6133b193b..0e529cd05d139e20e639a97cc5caa6cc440be033 100644 --- a/src/io/fs/glob.go +++ b/src/io/fs/glob.go @@ -31,6 +31,16 @@ type GlobFS interface { // Otherwise, Glob uses ReadDir to traverse the directory tree // and look for matches for the pattern. func Glob(fsys FS, pattern string) (matches []string, err error) { + return globWithLimit(fsys, pattern, 0) +} + +func globWithLimit(fsys FS, pattern string, depth int) (matches []string, err error) { + // This limit is added to prevent stack exhaustion issues. See + // CVE-2022-30630. + const pathSeparatorsLimit = 10000 + if depth > pathSeparatorsLimit { + return nil, path.ErrBadPattern + } if fsys, ok := fsys.(GlobFS); ok { return fsys.Glob(pattern) } @@ -59,9 +69,9 @@ func Glob(fsys FS, pattern string) (matches []string, err error) { } var m []string - m, err = Glob(fsys, dir) + m, err = globWithLimit(fsys, dir, depth+1) if err != nil { - return + return nil, err } for _, d := range m { matches, err = glob(fsys, d, file, matches) diff --git a/src/io/fs/glob_test.go b/src/io/fs/glob_test.go index f19bebed77f6c7c7e9fad7017b94b9c557a77bca..d052eab371366f00a17692774c87fec260b89946 100644 --- a/src/io/fs/glob_test.go +++ b/src/io/fs/glob_test.go @@ -8,6 +8,7 @@ import ( . "io/fs" "os" "path" + "strings" "testing" ) @@ -55,6 +56,15 @@ func TestGlobError(t *testing.T) { } } +func TestCVE202230630(t *testing.T) { + // Prior to CVE-2022-30630, a stack exhaustion would occur given a large + // number of separators. There is now a limit of 10,000. + _, err := Glob(os.DirFS("."), "/*"+strings.Repeat("/", 10001)) + if err != path.ErrBadPattern { + t.Fatalf("Glob returned err=%v, want %v", err, path.ErrBadPattern) + } +} + // contains reports whether vector contains the string s. func contains(vector []string, s string) bool { for _, elem := range vector { diff --git a/src/math/big/floatmarsh.go b/src/math/big/floatmarsh.go index d1c1dab069178f2861d990f5a1adfff617473544..990e085abe8d053c4c170dbac474753f63e3dd6a 100644 --- a/src/math/big/floatmarsh.go +++ b/src/math/big/floatmarsh.go @@ -8,6 +8,7 @@ package big import ( "encoding/binary" + "errors" "fmt" ) @@ -67,6 +68,9 @@ func (z *Float) GobDecode(buf []byte) error { *z = Float{} return nil } + if len(buf) < 6 { + return errors.New("Float.GobDecode: buffer too small") + } if buf[0] != floatGobVersion { return fmt.Errorf("Float.GobDecode: encoding version %d not supported", buf[0]) @@ -83,6 +87,9 @@ func (z *Float) GobDecode(buf []byte) error { z.prec = binary.BigEndian.Uint32(buf[2:]) if z.form == finite { + if len(buf) < 10 { + return errors.New("Float.GobDecode: buffer too small for finite form float") + } z.exp = int32(binary.BigEndian.Uint32(buf[6:])) z.mant = z.mant.setBytes(buf[10:]) } diff --git a/src/math/big/floatmarsh_test.go b/src/math/big/floatmarsh_test.go index c056d78b8008cd338f72241a168bfe7d866d4fd7..401f45a51fe7e046f08e13ef76d581701fa7cede 100644 --- a/src/math/big/floatmarsh_test.go +++ b/src/math/big/floatmarsh_test.go @@ -137,3 +137,15 @@ func TestFloatJSONEncoding(t *testing.T) { } } } + +func TestFloatGobDecodeShortBuffer(t *testing.T) { + for _, tc := range [][]byte{ + []byte{0x1, 0x0, 0x0, 0x0}, + []byte{0x1, 0xfa, 0x0, 0x0, 0x0, 0x0}, + } { + err := NewFloat(0).GobDecode(tc) + if err == nil { + t.Error("expected GobDecode to return error for malformed input") + } + } +} diff --git a/src/math/big/ratmarsh.go b/src/math/big/ratmarsh.go index fbc7b6002d9509459d2c5bc7f5bf2b86564d4810..56102e845b779cdfeae226989fda09dc10aaa686 100644 --- a/src/math/big/ratmarsh.go +++ b/src/math/big/ratmarsh.go @@ -45,12 +45,18 @@ func (z *Rat) GobDecode(buf []byte) error { *z = Rat{} return nil } + if len(buf) < 5 { + return errors.New("Rat.GobDecode: buffer too small") + } b := buf[0] if b>>1 != ratGobVersion { return fmt.Errorf("Rat.GobDecode: encoding version %d not supported", b>>1) } const j = 1 + 4 i := j + binary.BigEndian.Uint32(buf[j-4:j]) + if len(buf) < int(i) { + return errors.New("Rat.GobDecode: buffer too small") + } z.a.neg = b&1 != 0 z.a.abs = z.a.abs.setBytes(buf[j:i]) z.b.abs = z.b.abs.setBytes(buf[i:]) diff --git a/src/math/big/ratmarsh_test.go b/src/math/big/ratmarsh_test.go index 351d109f8d849a378ee5b73c952e3b7b416cac5d..55a9878bb871b1166317f99514c5ec8a8f80bdca 100644 --- a/src/math/big/ratmarsh_test.go +++ b/src/math/big/ratmarsh_test.go @@ -123,3 +123,15 @@ func TestRatXMLEncoding(t *testing.T) { } } } + +func TestRatGobDecodeShortBuffer(t *testing.T) { + for _, tc := range [][]byte{ + []byte{0x2}, + []byte{0x2, 0x0, 0x0, 0x0, 0xff}, + } { + err := NewRat(1, 2).GobDecode(tc) + if err == nil { + t.Error("expected GobDecode to return error for malformed input") + } + } +} diff --git a/src/net/http/fs.go b/src/net/http/fs.go index 6caee9ed931e871337a56687c380bd8dc700c415..583203043f3ad170d3b2f9c3532f0d8923cbd76c 100644 --- a/src/net/http/fs.go +++ b/src/net/http/fs.go @@ -9,6 +9,7 @@ package http import ( "errors" "fmt" + "internal/safefilepath" "io" "io/fs" "mime" @@ -69,14 +70,15 @@ func mapOpenError(originalErr error, name string, sep rune, stat func(string) (f // Open implements FileSystem using os.Open, opening files for reading rooted // and relative to the directory d. func (d Dir) Open(name string) (File, error) { - if filepath.Separator != '/' && strings.ContainsRune(name, filepath.Separator) { - return nil, errors.New("http: invalid character in file path") + path, err := safefilepath.FromFS(path.Clean("/" + name)) + if err != nil { + return nil, errors.New("http: invalid or unsafe file path") } dir := string(d) if dir == "" { dir = "." } - fullName := filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name))) + fullName := filepath.Join(dir, path) f, err := os.Open(fullName) if err != nil { return nil, mapOpenError(err, fullName, filepath.Separator, os.Stat) diff --git a/src/net/http/fs_test.go b/src/net/http/fs_test.go index d627dfd4be965287cb1d929ba8dc5621c02525cc..323360d55014d02258847817f925e0e9fce8e679 100644 --- a/src/net/http/fs_test.go +++ b/src/net/http/fs_test.go @@ -648,6 +648,34 @@ func TestFileServerZeroByte(t *testing.T) { } } +func TestFileServerNamesEscape(t *testing.T) { + t.Run("h1", func(t *testing.T) { + testFileServerNamesEscape(t, h1Mode) + }) + t.Run("h2", func(t *testing.T) { + testFileServerNamesEscape(t, h2Mode) + }) +} +func testFileServerNamesEscape(t *testing.T, h2 bool) { + defer afterTest(t) + ts := newClientServerTest(t, h2, FileServer(Dir("testdata"))).ts + defer ts.Close() + for _, path := range []string{ + "/../testdata/file", + "/NUL", // don't read from device files on Windows + } { + res, err := ts.Client().Get(ts.URL + path) + if err != nil { + t.Fatal(err) + } + res.Body.Close() + if res.StatusCode < 400 || res.StatusCode > 599 { + t.Errorf("Get(%q): got status %v, want 4xx or 5xx", path, res.StatusCode) + } + + } +} + type fakeFileInfo struct { dir bool basename string diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index bb82f2458589d83c3b03bb5351d3bfdd8f111772..3a21ecac3dcadab0b5a76a2a5f20cbabfae0df41 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -3384,10 +3384,11 @@ func (s http2SettingID) String() string { // name (key). See httpguts.ValidHeaderName for the base rules. // // Further, http2 says: -// "Just as in HTTP/1.x, header field names are strings of ASCII -// characters that are compared in a case-insensitive -// fashion. However, header field names MUST be converted to -// lowercase prior to their encoding in HTTP/2. " +// +// "Just as in HTTP/1.x, header field names are strings of ASCII +// characters that are compared in a case-insensitive +// fashion. However, header field names MUST be converted to +// lowercase prior to their encoding in HTTP/2. " func http2validWireHeaderFieldName(v string) bool { if len(v) == 0 { return false @@ -3578,8 +3579,8 @@ func (s *http2sorter) SortStrings(ss []string) { // validPseudoPath reports whether v is a valid :path pseudo-header // value. It must be either: // -// *) a non-empty string starting with '/' -// *) the string '*', for OPTIONS requests. +// *) a non-empty string starting with '/' +// *) the string '*', for OPTIONS requests. // // For now this is only used a quick check for deciding when to clean // up Opaque URLs before sending requests from the Transport. @@ -4242,6 +4243,7 @@ type http2serverConn struct { headerTableSize uint32 peerMaxHeaderListSize uint32 // zero means unknown (default) canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case + canonHeaderKeysSize int // canonHeader keys size in bytes writingFrame bool // started writing a frame (on serve goroutine or separate) writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh needsFrameFlush bool // last frame write wasn't a flush @@ -4421,6 +4423,13 @@ func (sc *http2serverConn) condlogf(err error, format string, args ...interface{ } } +// maxCachedCanonicalHeadersKeysSize is an arbitrarily-chosen limit on the size +// of the entries in the canonHeader cache. +// This should be larger than the size of unique, uncommon header keys likely to +// be sent by the peer, while not so high as to permit unreasonable memory usage +// if the peer sends an unbounded number of unique header keys. +const http2maxCachedCanonicalHeadersKeysSize = 2048 + func (sc *http2serverConn) canonicalHeader(v string) string { sc.serveG.check() http2buildCommonHeaderMapsOnce() @@ -4436,14 +4445,10 @@ func (sc *http2serverConn) canonicalHeader(v string) string { sc.canonHeader = make(map[string]string) } cv = CanonicalHeaderKey(v) - // maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of - // entries in the canonHeader cache. This should be larger than the number - // of unique, uncommon header keys likely to be sent by the peer, while not - // so high as to permit unreaasonable memory usage if the peer sends an unbounded - // number of unique header keys. - const maxCachedCanonicalHeaders = 32 - if len(sc.canonHeader) < maxCachedCanonicalHeaders { + size := 100 + len(v)*2 // 100 bytes of map overhead + key + value + if sc.canonHeaderKeysSize+size <= http2maxCachedCanonicalHeadersKeysSize { sc.canonHeader[v] = cv + sc.canonHeaderKeysSize += size } return cv } @@ -5053,6 +5058,9 @@ func (sc *http2serverConn) startGracefulShutdownInternal() { func (sc *http2serverConn) goAway(code http2ErrCode) { sc.serveG.check() if sc.inGoAway { + if sc.goAwayCode == http2ErrCodeNo { + sc.goAwayCode = code + } return } sc.inGoAway = true @@ -5752,12 +5760,6 @@ func (sc *http2serverConn) newWriterAndRequest(st *http2stream, f *http2MetaHead return nil, nil, sc.countError("bad_path_method", http2streamError(f.StreamID, http2ErrCodeProtocol)) } - bodyOpen := !f.StreamEnded() - if rp.method == "HEAD" && bodyOpen { - // HEAD requests can't have bodies - return nil, nil, sc.countError("head_body", http2streamError(f.StreamID, http2ErrCodeProtocol)) - } - rp.header = make(Header) for _, hf := range f.RegularFields() { rp.header.Add(sc.canonicalHeader(hf.Name), hf.Value) @@ -5770,6 +5772,7 @@ func (sc *http2serverConn) newWriterAndRequest(st *http2stream, f *http2MetaHead if err != nil { return nil, nil, err } + bodyOpen := !f.StreamEnded() if bodyOpen { if vv, ok := rp.header["Content-Length"]; ok { if cl, err := strconv.ParseUint(vv[0], 10, 63); err == nil { @@ -6265,8 +6268,9 @@ func (rws *http2responseWriterState) writeChunk(p []byte) (n int, err error) { // prior to the headers being written. If the set of trailers is fixed // or known before the header is written, the normal Go trailers mechanism // is preferred: -// https://golang.org/pkg/net/http/#ResponseWriter -// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers +// +// https://golang.org/pkg/net/http/#ResponseWriter +// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers const http2TrailerPrefix = "Trailer:" // promoteUndeclaredTrailers permits http.Handlers to set trailers diff --git a/src/net/http/header.go b/src/net/http/header.go index 6487e5025d718d20ef8994bcd06c634169643034..6437f2d2c07529a35a2268fc0ef7fde404835d5b 100644 --- a/src/net/http/header.go +++ b/src/net/http/header.go @@ -103,6 +103,12 @@ func (h Header) Clone() Header { sv := make([]string, nv) // shared backing array for headers' values h2 := make(Header, len(h)) for k, vv := range h { + if vv == nil { + // Preserve nil values. ReverseProxy distinguishes + // between nil and zero-length header values. + h2[k] = nil + continue + } n := copy(sv, vv) h2[k] = sv[:n:n] sv = sv[n:] diff --git a/src/net/http/header_test.go b/src/net/http/header_test.go index 57d16f51a5d62e662847b47fbf33203048c8b8bb..0b13d311aca2a3bd1f7025ceb4513fe7baf93aeb 100644 --- a/src/net/http/header_test.go +++ b/src/net/http/header_test.go @@ -248,6 +248,11 @@ func TestCloneOrMakeHeader(t *testing.T) { in: Header{"foo": {"bar"}}, want: Header{"foo": {"bar"}}, }, + { + name: "nil value", + in: Header{"foo": nil}, + want: Header{"foo": nil}, + }, } for _, tt := range tests { diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go index 319e2a3f3f0430af0bb7feaf28f73f97d3d2c930..0abc32b833e028ee4f686cf0b3f3ab70ceacb9f5 100644 --- a/src/net/http/httputil/reverseproxy.go +++ b/src/net/http/httputil/reverseproxy.go @@ -250,6 +250,9 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } p.Director(outreq) + if outreq.Form != nil { + outreq.URL.RawQuery = cleanQueryParams(outreq.URL.RawQuery) + } outreq.Close = false reqUpType := upgradeType(outreq.Header) @@ -629,3 +632,36 @@ func (c switchProtocolCopier) copyToBackend(errc chan<- error) { _, err := io.Copy(c.backend, c.user) errc <- err } + +func cleanQueryParams(s string) string { + reencode := func(s string) string { + v, _ := url.ParseQuery(s) + return v.Encode() + } + for i := 0; i < len(s); { + switch s[i] { + case ';': + return reencode(s) + case '%': + if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) { + return reencode(s) + } + i += 3 + default: + i++ + } + } + return s +} + +func ishex(c byte) bool { + switch { + case '0' <= c && c <= '9': + return true + case 'a' <= c && c <= 'f': + return true + case 'A' <= c && c <= 'F': + return true + } + return false +} diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go index 90e8903e9cfd5bfa3086422cb9f442a0861bd250..33b1adea3aa8a5adf658921df0b035b4b1501c4c 100644 --- a/src/net/http/httputil/reverseproxy_test.go +++ b/src/net/http/httputil/reverseproxy_test.go @@ -1537,3 +1537,77 @@ func TestJoinURLPath(t *testing.T) { } } } + +const ( + testWantsCleanQuery = true + testWantsRawQuery = false +) + +func TestReverseProxyQueryParameterSmugglingDirectorDoesNotParseForm(t *testing.T) { + testReverseProxyQueryParameterSmuggling(t, testWantsRawQuery, func(u *url.URL) *ReverseProxy { + proxyHandler := NewSingleHostReverseProxy(u) + oldDirector := proxyHandler.Director + proxyHandler.Director = func(r *http.Request) { + oldDirector(r) + } + return proxyHandler + }) +} + +func TestReverseProxyQueryParameterSmugglingDirectorParsesForm(t *testing.T) { + testReverseProxyQueryParameterSmuggling(t, testWantsCleanQuery, func(u *url.URL) *ReverseProxy { + proxyHandler := NewSingleHostReverseProxy(u) + oldDirector := proxyHandler.Director + proxyHandler.Director = func(r *http.Request) { + // Parsing the form causes ReverseProxy to remove unparsable + // query parameters before forwarding. + r.FormValue("a") + oldDirector(r) + } + return proxyHandler + }) +} + +func testReverseProxyQueryParameterSmuggling(t *testing.T, wantCleanQuery bool, newProxy func(*url.URL) *ReverseProxy) { + const content = "response_content" + backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(r.URL.RawQuery)) + })) + defer backend.Close() + backendURL, err := url.Parse(backend.URL) + if err != nil { + t.Fatal(err) + } + proxyHandler := newProxy(backendURL) + frontend := httptest.NewServer(proxyHandler) + defer frontend.Close() + + // Don't spam output with logs of queries containing semicolons. + backend.Config.ErrorLog = log.New(io.Discard, "", 0) + frontend.Config.ErrorLog = log.New(io.Discard, "", 0) + + for _, test := range []struct { + rawQuery string + cleanQuery string + }{{ + rawQuery: "a=1&a=2;b=3", + cleanQuery: "a=1", + }, { + rawQuery: "a=1&a=%zz&b=3", + cleanQuery: "a=1&b=3", + }} { + res, err := frontend.Client().Get(frontend.URL + "?" + test.rawQuery) + if err != nil { + t.Fatalf("Get: %v", err) + } + defer res.Body.Close() + body, _ := io.ReadAll(res.Body) + wantQuery := test.rawQuery + if wantCleanQuery { + wantQuery = test.cleanQuery + } + if got, want := string(body), wantQuery; got != want { + t.Errorf("proxy forwarded raw query %q as %q, want %q", test.rawQuery, got, want) + } + } +} diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index fb18cb2c6f5b2e156bb10a177b7615f8a6e40bbe..3f3e1421a938ae94515052527e33aabea6a1f719 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -6250,6 +6250,7 @@ func TestUnsupportedTransferEncodingsReturn501(t *testing.T) { "fugazi", "foo-bar", "unknown", + "\rchunked", } for _, badTE := range unsupportedTEs { diff --git a/src/net/http/transfer.go b/src/net/http/transfer.go index 6d51178ee9082dc8cdb12eba6fce8f9f0d8b1f4d..de69d835ac6e67af05310268a156e945e20055c3 100644 --- a/src/net/http/transfer.go +++ b/src/net/http/transfer.go @@ -640,7 +640,7 @@ func (t *transferReader) parseTransferEncoding() error { if len(raw) != 1 { return &unsupportedTEError{fmt.Sprintf("too many transfer encodings: %q", raw)} } - if !ascii.EqualFold(textproto.TrimString(raw[0]), "chunked") { + if !ascii.EqualFold(raw[0], "chunked") { return &unsupportedTEError{fmt.Sprintf("unsupported transfer encoding: %q", raw[0])} } diff --git a/src/net/ipsock_posix.go b/src/net/ipsock_posix.go index e433e8a91c75c0b025e657a98bebc33da9658e6e..b3868454e48ece6c48e03df88f6967059ff5667a 100644 --- a/src/net/ipsock_posix.go +++ b/src/net/ipsock_posix.go @@ -215,8 +215,12 @@ func addrPortToSockaddrInet4(ap netip.AddrPort) (syscall.SockaddrInet4, error) { func addrPortToSockaddrInet6(ap netip.AddrPort) (syscall.SockaddrInet6, error) { // ipToSockaddrInet6 has special handling here for zero length slices. // We do not, because netip has no concept of a generic zero IP address. + // + // addr is allowed to be an IPv4 address, because As16 will convert it + // to an IPv4-mapped IPv6 address. + // The error message is kept consistent with ipToSockaddrInet6. addr := ap.Addr() - if !addr.Is6() { + if !addr.IsValid() { return syscall.SockaddrInet6{}, &AddrError{Err: "non-IPv6 address", Addr: addr.String()} } sa := syscall.SockaddrInet6{ diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go index 3a31f56bea845056a6afe3ebe2b12a28b2ef9577..32e7f8ef990f7bc1a9ee7e0f5d34b3a07d7461b9 100644 --- a/src/net/lookup_test.go +++ b/src/net/lookup_test.go @@ -49,21 +49,21 @@ var lookupGoogleSRVTests = []struct { cname, target string }{ { - "xmpp-server", "tcp", "google.com", + "ldap", "tcp", "google.com", "google.com.", "google.com.", }, { - "xmpp-server", "tcp", "google.com.", + "ldap", "tcp", "google.com.", "google.com.", "google.com.", }, // non-standard back door { - "", "", "_xmpp-server._tcp.google.com", + "", "", "_ldap._tcp.google.com", "google.com.", "google.com.", }, { - "", "", "_xmpp-server._tcp.google.com.", + "", "", "_ldap._tcp.google.com.", "google.com.", "google.com.", }, } @@ -701,16 +701,16 @@ func testDots(t *testing.T, mode string) { } } - cname, srvs, err := LookupSRV("xmpp-server", "tcp", "google.com") + cname, srvs, err := LookupSRV("ldap", "tcp", "google.com") if err != nil { - t.Errorf("LookupSRV(xmpp-server, tcp, google.com): %v (mode=%v)", err, mode) + t.Errorf("LookupSRV(ldap, tcp, google.com): %v (mode=%v)", err, mode) } else { if !hasSuffixFold(cname, ".google.com.") { - t.Errorf("LookupSRV(xmpp-server, tcp, google.com) returned cname=%v, want name ending in .google.com. with trailing dot (mode=%v)", cname, mode) + t.Errorf("LookupSRV(ldap, tcp, google.com) returned cname=%v, want name ending in .google.com. with trailing dot (mode=%v)", cname, mode) } for _, srv := range srvs { if !hasSuffixFold(srv.Target, ".google.com.") { - t.Errorf("LookupSRV(xmpp-server, tcp, google.com) returned addrs=%v, want names ending in .google.com. with trailing dot (mode=%v)", srvString(srvs), mode) + t.Errorf("LookupSRV(ldap, tcp, google.com) returned addrs=%v, want names ending in .google.com. with trailing dot (mode=%v)", srvString(srvs), mode) break } } diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go index f8acf6a028a04fe757ebcbb9c2a91653faa9b07b..4ceacde10e43f8e5ce3cd7b2c56ea189b825602b 100644 --- a/src/net/udpsock_test.go +++ b/src/net/udpsock_test.go @@ -9,6 +9,7 @@ package net import ( "errors" "internal/testenv" + "net/netip" "os" "reflect" "runtime" @@ -622,3 +623,47 @@ func TestUDPIPVersionReadMsg(t *testing.T) { t.Error("returned UDPAddr is not IPv4") } } + +// TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion verifies that +// WriteMsgUDPAddrPort accepts IPv4, IPv4-mapped IPv6, and IPv6 target addresses +// on a UDPConn listening on "::". +func TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) { + if !supportsIPv6() { + t.Skip("IPv6 is not supported") + } + + switch runtime.GOOS { + case "dragonfly", "openbsd": + // DragonflyBSD's IPv6 sockets are always IPv6-only, according to the man page: + // https://www.dragonflybsd.org/cgi/web-man?command=ip6 (search for IPV6_V6ONLY). + // OpenBSD's IPv6 sockets are always IPv6-only, according to the man page: + // https://man.openbsd.org/ip6#IPV6_V6ONLY + t.Skipf("skipping on %v", runtime.GOOS) + } + + conn, err := ListenUDP("udp", nil) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + + daddr4 := netip.AddrPortFrom(netip.MustParseAddr("127.0.0.1"), 12345) + daddr4in6 := netip.AddrPortFrom(netip.MustParseAddr("::ffff:127.0.0.1"), 12345) + daddr6 := netip.AddrPortFrom(netip.MustParseAddr("::1"), 12345) + buf := make([]byte, 8) + + _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4) + if err != nil { + t.Fatal(err) + } + + _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6) + if err != nil { + t.Fatal(err) + } + + _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr6) + if err != nil { + t.Fatal(err) + } +} diff --git a/src/os/exec/env_test.go b/src/os/exec/env_test.go index b5ac398c274db405b1e2144cb5d6dc3c0cabadfb..43d14fb56dd1203bca8aea414a99e896df1f8a60 100644 --- a/src/os/exec/env_test.go +++ b/src/os/exec/env_test.go @@ -11,9 +11,11 @@ import ( func TestDedupEnv(t *testing.T) { tests := []struct { - noCase bool - in []string - want []string + noCase bool + nulOK bool + in []string + want []string + wantErr bool }{ { noCase: true, @@ -29,11 +31,23 @@ func TestDedupEnv(t *testing.T) { in: []string{"=a", "=b", "foo", "bar"}, want: []string{"=b", "foo", "bar"}, }, + { + // Filter out entries containing NULs. + in: []string{"A=a\x00b", "B=b", "C\x00C=c"}, + want: []string{"B=b"}, + wantErr: true, + }, + { + // Plan 9 needs to preserve environment variables with NUL (#56544). + nulOK: true, + in: []string{"path=one\x00two"}, + want: []string{"path=one\x00two"}, + }, } for _, tt := range tests { - got := dedupEnvCase(tt.noCase, tt.in) - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Dedup(%v, %q) = %q; want %q", tt.noCase, tt.in, got, tt.want) + got, err := dedupEnvCase(tt.noCase, tt.nulOK, tt.in) + if !reflect.DeepEqual(got, tt.want) || (err != nil) != tt.wantErr { + t.Errorf("Dedup(%v, %q) = %q, %v; want %q, error:%v", tt.noCase, tt.in, got, err, tt.want, tt.wantErr) } } } diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go index ecddee690de7c83a84d968bd8113131f274d9400..e1147b75fa59e420ca4b9b5a48c4aec70c5855fc 100644 --- a/src/os/exec/exec.go +++ b/src/os/exec/exec.go @@ -422,10 +422,14 @@ func (c *Cmd) Start() error { return err } + env, err := dedupEnv(envv) + if err != nil { + return err + } c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{ Dir: c.Dir, Files: c.childFiles, - Env: addCriticalEnv(dedupEnv(envv)), + Env: addCriticalEnv(env), Sys: c.SysProcAttr, }) if err != nil { @@ -741,16 +745,27 @@ func minInt(a, b int) int { // dedupEnv returns a copy of env with any duplicates removed, in favor of // later values. // Items not of the normal environment "key=value" form are preserved unchanged. -func dedupEnv(env []string) []string { - return dedupEnvCase(runtime.GOOS == "windows", env) +// Except on Plan 9, items containing NUL characters are removed, and +// an error is returned along with the remaining values. +func dedupEnv(env []string) ([]string, error) { + return dedupEnvCase(runtime.GOOS == "windows", runtime.GOOS == "plan9", env) } // dedupEnvCase is dedupEnv with a case option for testing. // If caseInsensitive is true, the case of keys is ignored. -func dedupEnvCase(caseInsensitive bool, env []string) []string { +// If nulOK is false, items containing NUL characters are allowed. +func dedupEnvCase(caseInsensitive, nulOK bool, env []string) ([]string, error) { + var err error out := make([]string, 0, len(env)) saw := make(map[string]int, len(env)) // key => index into out for _, kv := range env { + // Reject NUL in environment variables to prevent security issues (#56284); + // except on Plan 9, which uses NUL as os.PathListSeparator (#56544). + if !nulOK && strings.IndexByte(kv, 0) != -1 { + err = errors.New("exec: environment variable contains NUL") + continue + } + k, _, ok := strings.Cut(kv, "=") if !ok { out = append(out, kv) @@ -766,7 +781,7 @@ func dedupEnvCase(caseInsensitive bool, env []string) []string { saw[k] = len(out) out = append(out, kv) } - return out + return out, err } // addCriticalEnv adds any critical environment variables that are required diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index 1913ae81c8976f1eaa92a2cd81126421847736e7..99bc0329d12c633f4051eac2ab61e1d7255e2cad 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -1029,6 +1029,18 @@ func TestDedupEnvEcho(t *testing.T) { } } +func TestEnvNULCharacter(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("plan9 explicitly allows NUL in the enviroment") + } + cmd := helperCommand(t, "echoenv", "FOO", "BAR") + cmd.Env = append(cmd.Env, "FOO=foo\x00BAR=bar") + out, err := cmd.CombinedOutput() + if err == nil { + t.Errorf("output = %q; want error", string(out)) + } +} + func TestString(t *testing.T) { echoPath, err := exec.LookPath("echo") if err != nil { diff --git a/src/os/file.go b/src/os/file.go index 28231285542a19b8ffd6d545ffb5d460cc3c8fe1..8afc6e3540937cf7e1d355ace95082fc473e6c24 100644 --- a/src/os/file.go +++ b/src/os/file.go @@ -37,12 +37,12 @@ // Note: The maximum number of concurrent operations on a File may be limited by // the OS or the system. The number should be high, but exceeding it may degrade // performance or cause other issues. -// package os import ( "errors" "internal/poll" + "internal/safefilepath" "internal/testlog" "internal/unsafeheader" "io" @@ -623,6 +623,8 @@ func isWindowsNulName(name string) bool { // the /prefix tree, then using DirFS does not stop the access any more than using // os.Open does. DirFS is therefore not a general substitute for a chroot-style security // mechanism when the directory tree contains arbitrary content. +// +// The directory dir must not be "". func DirFS(dir string) fs.FS { return dirFS(dir) } @@ -641,10 +643,11 @@ func containsAny(s, chars string) bool { type dirFS string func (dir dirFS) Open(name string) (fs.File, error) { - if !fs.ValidPath(name) || runtime.GOOS == "windows" && containsAny(name, `\:`) { - return nil, &PathError{Op: "open", Path: name, Err: ErrInvalid} + fullname, err := dir.join(name) + if err != nil { + return nil, &PathError{Op: "stat", Path: name, Err: err} } - f, err := Open(string(dir) + "/" + name) + f, err := Open(fullname) if err != nil { return nil, err // nil fs.File } @@ -652,16 +655,35 @@ func (dir dirFS) Open(name string) (fs.File, error) { } func (dir dirFS) Stat(name string) (fs.FileInfo, error) { - if !fs.ValidPath(name) || runtime.GOOS == "windows" && containsAny(name, `\:`) { - return nil, &PathError{Op: "stat", Path: name, Err: ErrInvalid} + fullname, err := dir.join(name) + if err != nil { + return nil, &PathError{Op: "stat", Path: name, Err: err} } - f, err := Stat(string(dir) + "/" + name) + f, err := Stat(fullname) if err != nil { return nil, err } return f, nil } +// join returns the path for name in dir. +func (dir dirFS) join(name string) (string, error) { + if dir == "" { + return "", errors.New("os: DirFS with empty root") + } + if !fs.ValidPath(name) { + return "", ErrInvalid + } + name, err := safefilepath.FromFS(name) + if err != nil { + return "", ErrInvalid + } + if IsPathSeparator(dir[len(dir)-1]) { + return string(dir) + name, nil + } + return string(dir) + string(PathSeparator) + name, nil +} + // ReadFile reads the named file and returns the contents. // A successful call returns err == nil, not err == EOF. // Because ReadFile reads the whole file, it does not treat an EOF from Read diff --git a/src/os/os_test.go b/src/os/os_test.go index 63427deb6e01cfbd0f3b8051428ffd5f817f2141..3721e15027d5b5b9286fc73d5827a83adcc90c95 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -252,9 +252,11 @@ func TestLstat(t *testing.T) { if !equal(sfname, dir.Name()) { t.Error("name should be ", sfname, "; is", dir.Name()) } - filesize := size(path, t) - if dir.Size() != filesize { - t.Error("size should be", filesize, "; is", dir.Size()) + if dir.Mode()&ModeSymlink == 0 { + filesize := size(path, t) + if dir.Size() != filesize { + t.Error("size should be", filesize, "; is", dir.Size()) + } } } @@ -2696,6 +2698,44 @@ func TestDirFS(t *testing.T) { if err == nil { t.Fatalf(`Open testdata\dirfs succeeded`) } + + // Test that Open does not open Windows device files. + _, err = d.Open(`NUL`) + if err == nil { + t.Errorf(`Open NUL succeeded`) + } +} + +func TestDirFSRootDir(t *testing.T) { + cwd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + cwd = cwd[len(filepath.VolumeName(cwd)):] // trim volume prefix (C:) on Windows + cwd = filepath.ToSlash(cwd) // convert \ to / + cwd = strings.TrimPrefix(cwd, "/") // trim leading / + + // Test that Open can open a path starting at /. + d := DirFS("/") + f, err := d.Open(cwd + "/testdata/dirfs/a") + if err != nil { + t.Fatal(err) + } + f.Close() +} + +func TestDirFSEmptyDir(t *testing.T) { + d := DirFS("") + cwd, _ := os.Getwd() + for _, path := range []string{ + "testdata/dirfs/a", // not DirFS(".") + filepath.ToSlash(cwd) + "/testdata/dirfs/a", // not DirFS("/") + } { + _, err := d.Open(path) + if err == nil { + t.Fatalf(`DirFS("").Open(%q) succeeded`, path) + } + } } func TestDirFSPathsValid(t *testing.T) { diff --git a/src/path/filepath/match.go b/src/path/filepath/match.go index c77a26952a657f2c53bd9dafbf98deb4a7071f56..55ed1d75ae1b0eb4f579652c04727315b77dcace 100644 --- a/src/path/filepath/match.go +++ b/src/path/filepath/match.go @@ -241,6 +241,16 @@ func getEsc(chunk string) (r rune, nchunk string, err error) { // The only possible returned error is ErrBadPattern, when pattern // is malformed. func Glob(pattern string) (matches []string, err error) { + return globWithLimit(pattern, 0) +} + +func globWithLimit(pattern string, depth int) (matches []string, err error) { + // This limit is used prevent stack exhaustion issues. See CVE-2022-30632. + const pathSeparatorsLimit = 10000 + if depth == pathSeparatorsLimit { + return nil, ErrBadPattern + } + // Check pattern is well-formed. if _, err := Match(pattern, ""); err != nil { return nil, err @@ -270,7 +280,7 @@ func Glob(pattern string) (matches []string, err error) { } var m []string - m, err = Glob(dir) + m, err = globWithLimit(dir, depth+1) if err != nil { return } diff --git a/src/path/filepath/match_test.go b/src/path/filepath/match_test.go index 375c41a7e9d5d06615ba59451850bc8c552b45a9..d6282596fedbb93aeabc93fdc8029d43266098ae 100644 --- a/src/path/filepath/match_test.go +++ b/src/path/filepath/match_test.go @@ -155,6 +155,16 @@ func TestGlob(t *testing.T) { } } +func TestCVE202230632(t *testing.T) { + // Prior to CVE-2022-30632, this would cause a stack exhaustion given a + // large number of separators (more than 4,000,000). There is now a limit + // of 10,000. + _, err := Glob("/*" + strings.Repeat("/", 10001)) + if err != ErrBadPattern { + t.Fatalf("Glob returned err=%v, want ErrBadPattern", err) + } +} + func TestGlobError(t *testing.T) { bad := []string{`[]`, `nonexist/[]`} for _, pattern := range bad { diff --git a/src/regexp/syntax/parse.go b/src/regexp/syntax/parse.go index 0f6587ab27f313b7d80b6a3237f497d527e9a0c5..df839800c40c43d8f7c73524f13f40a12103c411 100644 --- a/src/regexp/syntax/parse.go +++ b/src/regexp/syntax/parse.go @@ -90,15 +90,49 @@ const ( // until we've allocated at least maxHeight Regexp structures. const maxHeight = 1000 +// maxSize is the maximum size of a compiled regexp in Insts. +// It too is somewhat arbitrarily chosen, but the idea is to be large enough +// to allow significant regexps while at the same time small enough that +// the compiled form will not take up too much memory. +// 128 MB is enough for a 3.3 million Inst structures, which roughly +// corresponds to a 3.3 MB regexp. +const ( + maxSize = 128 << 20 / instSize + instSize = 5 * 8 // byte, 2 uint32, slice is 5 64-bit words +) + +// maxRunes is the maximum number of runes allowed in a regexp tree +// counting the runes in all the nodes. +// Ignoring character classes p.numRunes is always less than the length of the regexp. +// Character classes can make it much larger: each \pL adds 1292 runes. +// 128 MB is enough for 32M runes, which is over 26k \pL instances. +// Note that repetitions do not make copies of the rune slices, +// so \pL{1000} is only one rune slice, not 1000. +// We could keep a cache of character classes we've seen, +// so that all the \pL we see use the same rune list, +// but that doesn't remove the problem entirely: +// consider something like [\pL01234][\pL01235][\pL01236]...[\pL^&*()]. +// And because the Rune slice is exposed directly in the Regexp, +// there is not an opportunity to change the representation to allow +// partial sharing between different character classes. +// So the limit is the best we can do. +const ( + maxRunes = 128 << 20 / runeSize + runeSize = 4 // rune is int32 +) + type parser struct { flags Flags // parse mode flags stack []*Regexp // stack of parsed expressions free *Regexp numCap int // number of capturing groups seen wholeRegexp string - tmpClass []rune // temporary char class work space - numRegexp int // number of regexps allocated - height map[*Regexp]int // regexp height for height limit check + tmpClass []rune // temporary char class work space + numRegexp int // number of regexps allocated + numRunes int // number of runes in char classes + repeats int64 // product of all repetitions seen + height map[*Regexp]int // regexp height, for height limit check + size map[*Regexp]int64 // regexp compiled size, for size limit check } func (p *parser) newRegexp(op Op) *Regexp { @@ -122,6 +156,104 @@ func (p *parser) reuse(re *Regexp) { p.free = re } +func (p *parser) checkLimits(re *Regexp) { + if p.numRunes > maxRunes { + panic(ErrInternalError) + } + p.checkSize(re) + p.checkHeight(re) +} + +func (p *parser) checkSize(re *Regexp) { + if p.size == nil { + // We haven't started tracking size yet. + // Do a relatively cheap check to see if we need to start. + // Maintain the product of all the repeats we've seen + // and don't track if the total number of regexp nodes + // we've seen times the repeat product is in budget. + if p.repeats == 0 { + p.repeats = 1 + } + if re.Op == OpRepeat { + n := re.Max + if n == -1 { + n = re.Min + } + if n <= 0 { + n = 1 + } + if int64(n) > maxSize/p.repeats { + p.repeats = maxSize + } else { + p.repeats *= int64(n) + } + } + if int64(p.numRegexp) < maxSize/p.repeats { + return + } + + // We need to start tracking size. + // Make the map and belatedly populate it + // with info about everything we've constructed so far. + p.size = make(map[*Regexp]int64) + for _, re := range p.stack { + p.checkSize(re) + } + } + + if p.calcSize(re, true) > maxSize { + panic(ErrInternalError) + } +} + +func (p *parser) calcSize(re *Regexp, force bool) int64 { + if !force { + if size, ok := p.size[re]; ok { + return size + } + } + + var size int64 + switch re.Op { + case OpLiteral: + size = int64(len(re.Rune)) + case OpCapture, OpStar: + // star can be 1+ or 2+; assume 2 pessimistically + size = 2 + p.calcSize(re.Sub[0], false) + case OpPlus, OpQuest: + size = 1 + p.calcSize(re.Sub[0], false) + case OpConcat: + for _, sub := range re.Sub { + size += p.calcSize(sub, false) + } + case OpAlternate: + for _, sub := range re.Sub { + size += p.calcSize(sub, false) + } + if len(re.Sub) > 1 { + size += int64(len(re.Sub)) - 1 + } + case OpRepeat: + sub := p.calcSize(re.Sub[0], false) + if re.Max == -1 { + if re.Min == 0 { + size = 2 + sub // x* + } else { + size = 1 + int64(re.Min)*sub // xxx+ + } + break + } + // x{2,5} = xx(x(x(x)?)?)? + size = int64(re.Max)*sub + int64(re.Max-re.Min) + } + + if size < 1 { + size = 1 + } + p.size[re] = size + return size +} + func (p *parser) checkHeight(re *Regexp) { if p.numRegexp < maxHeight { return @@ -158,6 +290,7 @@ func (p *parser) calcHeight(re *Regexp, force bool) int { // push pushes the regexp re onto the parse stack and returns the regexp. func (p *parser) push(re *Regexp) *Regexp { + p.numRunes += len(re.Rune) if re.Op == OpCharClass && len(re.Rune) == 2 && re.Rune[0] == re.Rune[1] { // Single rune. if p.maybeConcat(re.Rune[0], p.flags&^FoldCase) { @@ -189,7 +322,7 @@ func (p *parser) push(re *Regexp) *Regexp { } p.stack = append(p.stack, re) - p.checkHeight(re) + p.checkLimits(re) return re } @@ -299,7 +432,7 @@ func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) ( re.Sub = re.Sub0[:1] re.Sub[0] = sub p.stack[n-1] = re - p.checkHeight(re) + p.checkLimits(re) if op == OpRepeat && (min >= 2 || max >= 2) && !repeatIsValid(re, 1000) { return "", &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]} @@ -503,6 +636,7 @@ func (p *parser) factor(sub []*Regexp) []*Regexp { for j := start; j < i; j++ { sub[j] = p.removeLeadingString(sub[j], len(str)) + p.checkLimits(sub[j]) } suffix := p.collapse(sub[start:i], OpAlternate) // recurse @@ -560,6 +694,7 @@ func (p *parser) factor(sub []*Regexp) []*Regexp { for j := start; j < i; j++ { reuse := j != start // prefix came from sub[start] sub[j] = p.removeLeadingRegexp(sub[j], reuse) + p.checkLimits(sub[j]) } suffix := p.collapse(sub[start:i], OpAlternate) // recurse diff --git a/src/regexp/syntax/parse_test.go b/src/regexp/syntax/parse_test.go index 1ef6d8a3fe09ba9034fef1c2a4dda6c7784c2d26..67e3c5622a0fef2d4793c76b9bce70603edd21bd 100644 --- a/src/regexp/syntax/parse_test.go +++ b/src/regexp/syntax/parse_test.go @@ -484,12 +484,15 @@ var invalidRegexps = []string{ `(?P<>a)`, `[a-Z]`, `(?i)[a-Z]`, - `a{100000}`, - `a{100000,}`, - "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})", - strings.Repeat("(", 1000) + strings.Repeat(")", 1000), - strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000), `\Q\E*`, + `a{100000}`, // too much repetition + `a{100000,}`, // too much repetition + "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})", // too much repetition + strings.Repeat("(", 1000) + strings.Repeat(")", 1000), // too deep + strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000), // too deep + "(" + strings.Repeat("(xx?)", 1000) + "){1000}", // too long + strings.Repeat("(xx?){1000}", 1000), // too long + strings.Repeat(`\pL`, 27000), // too many runes } var onlyPerl = []string{ diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s index b47184e36bc9801e1c2c2080b9a9ef629122304a..591ef2a399fb76711a609b1920d1ae32354439bd 100644 --- a/src/runtime/asm_arm.s +++ b/src/runtime/asm_arm.s @@ -387,6 +387,13 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 RET TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 + // Force SPWRITE. This function doesn't actually write SP, + // but it is called with a special calling convention where + // the caller doesn't save LR on stack but passes it as a + // register (R3), and the unwinder currently doesn't understand. + // Make it SPWRITE to stop unwinding. (See issue 54332) + MOVW R13, R13 + MOVW $0, R7 B runtime·morestack(SB) diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s index fd65969b628ac7eebc1d5972434d6b155c0e43ca..64121b11aa64024c2b5f7f438699ad7a1036eabe 100644 --- a/src/runtime/asm_arm64.s +++ b/src/runtime/asm_arm64.s @@ -318,6 +318,13 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 UNDEF TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 + // Force SPWRITE. This function doesn't actually write SP, + // but it is called with a special calling convention where + // the caller doesn't save LR on stack but passes it as a + // register (R3), and the unwinder currently doesn't understand. + // Make it SPWRITE to stop unwinding. (See issue 54332) + MOVD RSP, RSP + MOVW $0, R26 B runtime·morestack(SB) diff --git a/src/runtime/asm_mips64x.s b/src/runtime/asm_mips64x.s index 3597ebec57c74ffad714f5fdc751d55c94032531..1abadb9c7df308857a84c30885c47c587f560df6 100644 --- a/src/runtime/asm_mips64x.s +++ b/src/runtime/asm_mips64x.s @@ -258,6 +258,13 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 UNDEF TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 + // Force SPWRITE. This function doesn't actually write SP, + // but it is called with a special calling convention where + // the caller doesn't save LR on stack but passes it as a + // register (R3), and the unwinder currently doesn't understand. + // Make it SPWRITE to stop unwinding. (See issue 54332) + MOVV R29, R29 + MOVV R0, REGCTXT JMP runtime·morestack(SB) diff --git a/src/runtime/asm_mipsx.s b/src/runtime/asm_mipsx.s index 4a086b8eb302cf167f028351012b052c9ab9b4b8..877c1bb97b7bcf8bec5dcc287f44ccfc050abf13 100644 --- a/src/runtime/asm_mipsx.s +++ b/src/runtime/asm_mipsx.s @@ -257,6 +257,13 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 UNDEF TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0 + // Force SPWRITE. This function doesn't actually write SP, + // but it is called with a special calling convention where + // the caller doesn't save LR on stack but passes it as a + // register (R3), and the unwinder currently doesn't understand. + // Make it SPWRITE to stop unwinding. (See issue 54332) + MOVW R29, R29 + MOVW R0, REGCTXT JMP runtime·morestack(SB) diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s index ae14213999534c9bf490f1cd5e8170d10a34fc46..10ae161a13f5a04da5e56af503c2ffac627a247c 100644 --- a/src/runtime/asm_ppc64x.s +++ b/src/runtime/asm_ppc64x.s @@ -338,6 +338,13 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 UNDEF TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 + // Force SPWRITE. This function doesn't actually write SP, + // but it is called with a special calling convention where + // the caller doesn't save LR on stack but passes it as a + // register (R5), and the unwinder currently doesn't understand. + // Make it SPWRITE to stop unwinding. (See issue 54332) + MOVD R1, R1 + MOVD R0, R11 BR runtime·morestack(SB) diff --git a/src/runtime/asm_riscv64.s b/src/runtime/asm_riscv64.s index 2a4837b3991b5b7577548ca15f8f6a46b1c2196f..c88bef6ed8620ac0b62c128bda2ece25fec6fae4 100644 --- a/src/runtime/asm_riscv64.s +++ b/src/runtime/asm_riscv64.s @@ -158,8 +158,8 @@ TEXT runtime·getcallerpc(SB),NOSPLIT|NOFRAME,$0-8 */ // Called during function prolog when more stack is needed. -// Caller has already loaded: -// R1: framesize, R2: argsize, R3: LR +// Called with return address (i.e. caller's PC) in X5 (aka T0), +// and the LR register contains the caller's LR. // // The traceback routines see morestack on a g0 as being // the top of a stack (for example, morestack calling newstack @@ -209,6 +209,13 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 // func morestack_noctxt() TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 + // Force SPWRITE. This function doesn't actually write SP, + // but it is called with a special calling convention where + // the caller doesn't save LR on stack but passes it as a + // register, and the unwinder currently doesn't understand. + // Make it SPWRITE to stop unwinding. (See issue 54332) + MOV X2, X2 + MOV ZERO, CTXT JMP runtime·morestack(SB) diff --git a/src/runtime/asm_s390x.s b/src/runtime/asm_s390x.s index 9159a673721ff3aad7928c446ebfb136dee8c51c..334e1aa909d3ef7a554cd479aef99cdf36853560 100644 --- a/src/runtime/asm_s390x.s +++ b/src/runtime/asm_s390x.s @@ -346,6 +346,13 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 UNDEF TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 + // Force SPWRITE. This function doesn't actually write SP, + // but it is called with a special calling convention where + // the caller doesn't save LR on stack but passes it as a + // register (R5), and the unwinder currently doesn't understand. + // Make it SPWRITE to stop unwinding. (See issue 54332) + MOVD R15, R15 + MOVD $0, R12 BR runtime·morestack(SB) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 0ac15ce82c6882dfc009f9d205ebd266ceb993e6..d209e421bea2c44e09129d615469e2e06d9053f0 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -307,9 +307,9 @@ func ReadMetricsSlow(memStats *MemStats, samplesp unsafe.Pointer, len, cap int) // Initialize the metrics beforehand because this could // allocate and skew the stats. - semacquire(&metricsSema) + metricsLock() initMetrics() - semrelease(&metricsSema) + metricsUnlock() systemstack(func() { // Read memstats first. It's going to flush diff --git a/src/runtime/internal/atomic/atomic_test.go b/src/runtime/internal/atomic/atomic_test.go index 2ae60b8507ef5831e2d5345514224696c0b85623..2427bfd211ee9cd84e858783d3a2c63473b7c2fe 100644 --- a/src/runtime/internal/atomic/atomic_test.go +++ b/src/runtime/internal/atomic/atomic_test.go @@ -345,6 +345,36 @@ func TestBitwiseContended(t *testing.T) { } } +func TestCasRel(t *testing.T) { + const _magic = 0x5a5aa5a5 + var x struct { + before uint32 + i uint32 + after uint32 + o uint32 + n uint32 + } + + x.before = _magic + x.after = _magic + for j := 0; j < 32; j += 1 { + x.i = (1 << j) + 0 + x.o = (1 << j) + 0 + x.n = (1 << j) + 1 + if !atomic.CasRel(&x.i, x.o, x.n) { + t.Fatalf("should have swapped %#x %#x", x.o, x.n) + } + + if x.i != x.n { + t.Fatalf("wrong x.i after swap: x.i=%#x x.n=%#x", x.i, x.n) + } + + if x.before != _magic || x.after != _magic { + t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, _magic, _magic) + } + } +} + func TestStorepNoWB(t *testing.T) { var p [2]*int for i := range p { diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 6ed6ceade2d4ca115c6ad8c87184377fc267fe8e..d738644c7ece16e02caee0f5e7a6158e128e361f 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -1135,6 +1135,16 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { // the garbage collector could follow a pointer to x, // but see uninitialized memory or stale heap bits. publicationBarrier() + // As x and the heap bits are initialized, update + // freeIndexForScan now so x is seen by the GC + // (including convervative scan) as an allocated object. + // While this pointer can't escape into user code as a + // _live_ pointer until we return, conservative scanning + // may find a dead pointer that happens to point into this + // object. Delaying this update until now ensures that + // conservative scanning considers this pointer dead until + // this point. + span.freeIndexForScan = span.freeindex // Allocate black during GC. // All slots hold nil so no scanning is needed. diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go index 937968807b0eadd44688b6c3d398eb342e1ab50f..95d88d8c610581ea8d77172fabe02f2d3e9e3cb9 100644 --- a/src/runtime/mbitmap.go +++ b/src/runtime/mbitmap.go @@ -220,7 +220,7 @@ func (s *mspan) nextFreeIndex() uintptr { // been no preemption points since ensuring this (which could allow a // GC transition, which would allow the state to change). func (s *mspan) isFree(index uintptr) bool { - if index < s.freeindex { + if index < s.freeIndexForScan { return false } bytep, mask := s.allocBits.bitp(index) diff --git a/src/runtime/mcache.go b/src/runtime/mcache.go index 86a8958b9dc66347b227e360e84d84f158fcf0cd..c58e05dd2966d778be6a02ccc944efd85d623f46 100644 --- a/src/runtime/mcache.go +++ b/src/runtime/mcache.go @@ -175,11 +175,11 @@ func (c *mcache) refill(spc spanClass) { // Assume all objects from this span will be allocated in the // mcache. If it gets uncached, we'll adjust this. stats := memstats.heapStats.acquire() - atomic.Xadduintptr(&stats.smallAllocCount[spc.sizeclass()], uintptr(s.nelems)-uintptr(s.allocCount)) + atomic.Xadd64(&stats.smallAllocCount[spc.sizeclass()], int64(s.nelems)-int64(s.allocCount)) // Flush tinyAllocs. if spc == tinySpanClass { - atomic.Xadduintptr(&stats.tinyAllocCount, c.tinyAllocs) + atomic.Xadd64(&stats.tinyAllocCount, int64(c.tinyAllocs)) c.tinyAllocs = 0 } memstats.heapStats.release() @@ -215,8 +215,8 @@ func (c *mcache) allocLarge(size uintptr, noscan bool) *mspan { throw("out of memory") } stats := memstats.heapStats.acquire() - atomic.Xadduintptr(&stats.largeAlloc, npages*pageSize) - atomic.Xadduintptr(&stats.largeAllocCount, 1) + atomic.Xadd64(&stats.largeAlloc, int64(npages*pageSize)) + atomic.Xadd64(&stats.largeAllocCount, 1) memstats.heapStats.release() // Update heapLive. @@ -241,9 +241,9 @@ func (c *mcache) releaseAll() { s := c.alloc[i] if s != &emptymspan { // Adjust nsmallalloc in case the span wasn't fully allocated. - n := uintptr(s.nelems) - uintptr(s.allocCount) + n := int64(s.nelems) - int64(s.allocCount) stats := memstats.heapStats.acquire() - atomic.Xadduintptr(&stats.smallAllocCount[spanClass(i).sizeclass()], -n) + atomic.Xadd64(&stats.smallAllocCount[spanClass(i).sizeclass()], -n) memstats.heapStats.release() if s.sweepgen != sg+1 { // refill conservatively counted unallocated slots in gcController.heapLive. @@ -253,7 +253,7 @@ func (c *mcache) releaseAll() { // gcController.heapLive was totally recomputed since // caching this span, so we don't do this for // stale spans. - dHeapLive -= int64(n) * int64(s.elemsize) + dHeapLive -= n * int64(s.elemsize) } // Release the span to the mcentral. mheap_.central[i].mcentral.uncacheSpan(s) @@ -266,7 +266,7 @@ func (c *mcache) releaseAll() { // Flush tinyAllocs. stats := memstats.heapStats.acquire() - atomic.Xadduintptr(&stats.tinyAllocCount, c.tinyAllocs) + atomic.Xadd64(&stats.tinyAllocCount, int64(c.tinyAllocs)) c.tinyAllocs = 0 memstats.heapStats.release() diff --git a/src/runtime/metrics.go b/src/runtime/metrics.go index ba0a920a5d16bc75d0e4d868702d1745f3da2770..922dd2f81493c6c1586998332e04dc994d470634 100644 --- a/src/runtime/metrics.go +++ b/src/runtime/metrics.go @@ -12,9 +12,12 @@ import ( ) var ( - // metrics is a map of runtime/metrics keys to - // data used by the runtime to sample each metric's - // value. + // metrics is a map of runtime/metrics keys to data used by the runtime + // to sample each metric's value. metricsInit indicates it has been + // initialized. + // + // These fields are protected by metricsSema which should be + // locked/unlocked with metricsLock() / metricsUnlock(). metricsSema uint32 = 1 metricsInit bool metrics map[string]metricData @@ -34,6 +37,23 @@ type metricData struct { compute func(in *statAggregate, out *metricValue) } +func metricsLock() { + // Acquire the metricsSema but with handoff. Operations are typically + // expensive enough that queueing up goroutines and handing off between + // them will be noticeably better-behaved. + semacquire1(&metricsSema, true, 0, 0) + if raceenabled { + raceacquire(unsafe.Pointer(&metricsSema)) + } +} + +func metricsUnlock() { + if raceenabled { + racerelease(unsafe.Pointer(&metricsSema)) + } + semrelease(&metricsSema) +} + // initMetrics initializes the metrics map if it hasn't been yet. // // metricsSema must be held. @@ -388,13 +408,13 @@ func (a *heapStatsAggregate) compute() { memstats.heapStats.read(&a.heapStatsDelta) // Calculate derived stats. - a.totalAllocs = uint64(a.largeAllocCount) - a.totalFrees = uint64(a.largeFreeCount) - a.totalAllocated = uint64(a.largeAlloc) - a.totalFreed = uint64(a.largeFree) + a.totalAllocs = a.largeAllocCount + a.totalFrees = a.largeFreeCount + a.totalAllocated = a.largeAlloc + a.totalFreed = a.largeFree for i := range a.smallAllocCount { - na := uint64(a.smallAllocCount[i]) - nf := uint64(a.smallFreeCount[i]) + na := a.smallAllocCount[i] + nf := a.smallFreeCount[i] a.totalAllocs += na a.totalFrees += nf a.totalAllocated += na * uint64(class_to_size[i]) @@ -546,10 +566,7 @@ func readMetrics(samplesp unsafe.Pointer, len int, cap int) { sl := slice{samplesp, len, cap} samples := *(*[]metricSample)(unsafe.Pointer(&sl)) - // Acquire the metricsSema but with handoff. This operation - // is expensive enough that queueing up goroutines and handing - // off between them will be noticeably better-behaved. - semacquire1(&metricsSema, true, 0, 0) + metricsLock() // Ensure the map is initialized. initMetrics() @@ -573,5 +590,5 @@ func readMetrics(samplesp unsafe.Pointer, len int, cap int) { data.compute(&agg, &sample.value) } - semrelease(&metricsSema) + metricsUnlock() } diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go index a46f4ec2c6cf893b5d607e34432e28d3383ac077..2aa670e1b864ddb7346586ae77815ca715d0f5e6 100644 --- a/src/runtime/mgcsweep.go +++ b/src/runtime/mgcsweep.go @@ -623,6 +623,7 @@ func (sl *sweepLocked) sweep(preserve bool) bool { s.allocCount = nalloc s.freeindex = 0 // reset allocation index to start of span. + s.freeIndexForScan = 0 if trace.enabled { getg().m.p.ptr().traceReclaimed += uintptr(nfreed) * s.elemsize } @@ -666,7 +667,7 @@ func (sl *sweepLocked) sweep(preserve bool) bool { // free slots zeroed. s.needzero = 1 stats := memstats.heapStats.acquire() - atomic.Xadduintptr(&stats.smallFreeCount[spc.sizeclass()], uintptr(nfreed)) + atomic.Xadd64(&stats.smallFreeCount[spc.sizeclass()], int64(nfreed)) memstats.heapStats.release() } if !preserve { @@ -713,8 +714,8 @@ func (sl *sweepLocked) sweep(preserve bool) bool { mheap_.freeSpan(s) } stats := memstats.heapStats.acquire() - atomic.Xadduintptr(&stats.largeFreeCount, 1) - atomic.Xadduintptr(&stats.largeFree, size) + atomic.Xadd64(&stats.largeFreeCount, 1) + atomic.Xadd64(&stats.largeFree, int64(size)) memstats.heapStats.release() return true } diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index ecbd0a3a492a33fede00394babd9b813de530e11..134387562e1e548626a6eb4e7cf143f274330b4c 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -459,6 +459,14 @@ type mspan struct { limit uintptr // end of data in span speciallock mutex // guards specials list specials *special // linked list of special records sorted by offset. + + // freeIndexForScan is like freeindex, except that freeindex is + // used by the allocator whereas freeIndexForScan is used by the + // GC scanner. They are two fields so that the GC sees the object + // is allocated only when the object and the heap bits are + // initialized (see also the assignment of freeIndexForScan in + // mallocgc, and issue 54596). + freeIndexForScan uintptr } func (s *mspan) base() uintptr { @@ -1250,6 +1258,7 @@ HaveSpan: // Initialize mark and allocation structures. s.freeindex = 0 + s.freeIndexForScan = 0 s.allocCache = ^uint64(0) // all 1s indicating all free. s.gcmarkBits = newMarkBits(s.nelems) s.allocBits = newAllocBits(s.nelems) @@ -1565,6 +1574,7 @@ func (span *mspan) init(base uintptr, npages uintptr) { span.specials = nil span.needzero = 0 span.freeindex = 0 + span.freeIndexForScan = 0 span.allocBits = nil span.gcmarkBits = nil span.state.set(mSpanDead) diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go index c2303e5b8ec0617f9777f63248e4a8d5e797af2c..2c1ec79bf8e41a158949d113490139f4147e460b 100644 --- a/src/runtime/mstats.go +++ b/src/runtime/mstats.go @@ -7,7 +7,6 @@ package runtime import ( - "internal/goarch" "runtime/internal/atomic" "unsafe" ) @@ -565,29 +564,29 @@ func updatememstats() { memstats.heapStats.unsafeRead(&consStats) // Collect large allocation stats. - totalAlloc := uint64(consStats.largeAlloc) - memstats.nmalloc += uint64(consStats.largeAllocCount) - totalFree := uint64(consStats.largeFree) - memstats.nfree += uint64(consStats.largeFreeCount) + totalAlloc := consStats.largeAlloc + memstats.nmalloc += consStats.largeAllocCount + totalFree := consStats.largeFree + memstats.nfree += consStats.largeFreeCount // Collect per-sizeclass stats. for i := 0; i < _NumSizeClasses; i++ { // Malloc stats. - a := uint64(consStats.smallAllocCount[i]) + a := consStats.smallAllocCount[i] totalAlloc += a * uint64(class_to_size[i]) memstats.nmalloc += a memstats.by_size[i].nmalloc = a // Free stats. - f := uint64(consStats.smallFreeCount[i]) + f := consStats.smallFreeCount[i] totalFree += f * uint64(class_to_size[i]) memstats.nfree += f memstats.by_size[i].nfree = f } // Account for tiny allocations. - memstats.nfree += uint64(consStats.tinyAllocCount) - memstats.nmalloc += uint64(consStats.tinyAllocCount) + memstats.nfree += consStats.tinyAllocCount + memstats.nmalloc += consStats.tinyAllocCount // Calculate derived stats. memstats.total_alloc = totalAlloc @@ -703,17 +702,20 @@ type heapStatsDelta struct { inPtrScalarBits int64 // byte delta of memory reserved for unrolled GC prog bits // Allocator stats. - tinyAllocCount uintptr // number of tiny allocations - largeAlloc uintptr // bytes allocated for large objects - largeAllocCount uintptr // number of large object allocations - smallAllocCount [_NumSizeClasses]uintptr // number of allocs for small objects - largeFree uintptr // bytes freed for large objects (>maxSmallSize) - largeFreeCount uintptr // number of frees for large objects (>maxSmallSize) - smallFreeCount [_NumSizeClasses]uintptr // number of frees for small objects (<=maxSmallSize) - - // Add a uint32 to ensure this struct is a multiple of 8 bytes in size. - // Only necessary on 32-bit platforms. - _ [(goarch.PtrSize / 4) % 2]uint32 + // + // These are all uint64 because they're cumulative, and could quickly wrap + // around otherwise. + tinyAllocCount uint64 // number of tiny allocations + largeAlloc uint64 // bytes allocated for large objects + largeAllocCount uint64 // number of large object allocations + smallAllocCount [_NumSizeClasses]uint64 // number of allocs for small objects + largeFree uint64 // bytes freed for large objects (>maxSmallSize) + largeFreeCount uint64 // number of frees for large objects (>maxSmallSize) + smallFreeCount [_NumSizeClasses]uint64 // number of frees for small objects (<=maxSmallSize) + + // NOTE: This struct must be a multiple of 8 bytes in size because it + // is stored in an array. If it's not, atomic accesses to the above + // fields may be unaligned and fail on 32-bit platforms. } // merge adds in the deltas from b into a. diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go index 4aba0ff64ba3da16d3ac78b21e2fe6940a9454fe..3ccce776ca35d64c7bb58762ec248fda784d056b 100644 --- a/src/runtime/os3_solaris.go +++ b/src/runtime/os3_solaris.go @@ -7,6 +7,7 @@ package runtime import ( "internal/abi" "internal/goarch" + "runtime/internal/atomic" "unsafe" ) @@ -184,7 +185,7 @@ func newosproc(mp *m) { } } -func exitThread(wait *uint32) { +func exitThread(wait *atomic.Uint32) { // We should never reach exitThread on Solaris because we let // libc clean up threads. throw("exitThread") diff --git a/src/runtime/os_aix.go b/src/runtime/os_aix.go index 292ff94795677a65c8c661867a7f118e742e1d96..41352b3a5a1f19109f31adb128e9a2ce977d46a7 100644 --- a/src/runtime/os_aix.go +++ b/src/runtime/os_aix.go @@ -8,6 +8,7 @@ package runtime import ( "internal/abi" + "runtime/internal/atomic" "unsafe" ) @@ -232,7 +233,7 @@ func newosproc(mp *m) { } -func exitThread(wait *uint32) { +func exitThread(wait *atomic.Uint32) { // We should never reach exitThread on AIX because we let // libc clean up threads. throw("exitThread") diff --git a/src/runtime/os_js.go b/src/runtime/os_js.go index 9ed916705bc517e906f1f1618fc0e58ae3492277..6f358d36d6f1621d15c4da2b9687aef0085bc2dc 100644 --- a/src/runtime/os_js.go +++ b/src/runtime/os_js.go @@ -7,6 +7,7 @@ package runtime import ( + "runtime/internal/atomic" "unsafe" ) @@ -35,7 +36,7 @@ func usleep_no_g(usec uint32) { usleep(usec) } -func exitThread(wait *uint32) +func exitThread(wait *atomic.Uint32) type mOS struct{} diff --git a/src/runtime/os_openbsd_syscall2.go b/src/runtime/os_openbsd_syscall2.go index 99542fb2de161786d8974b17fb96d3476205b99e..810d599508886f8ba555ee0ee3635c0053492524 100644 --- a/src/runtime/os_openbsd_syscall2.go +++ b/src/runtime/os_openbsd_syscall2.go @@ -7,6 +7,7 @@ package runtime import ( + "runtime/internal/atomic" "unsafe" ) @@ -48,11 +49,11 @@ func open(name *byte, mode, perm int32) int32 // return value is only set on linux to be used in osinit() func madvise(addr unsafe.Pointer, n uintptr, flags int32) int32 -// exitThread terminates the current thread, writing *wait = 0 when +// exitThread terminates the current thread, writing *wait = freeMStack when // the stack is safe to reclaim. // //go:noescape -func exitThread(wait *uint32) +func exitThread(wait *atomic.Uint32) //go:noescape func obsdsigprocmask(how int32, new sigset) sigset diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go index 975d460a7da924ede62917c0b6800d826cfdf4c5..2bb6ec0fcee7e8a2f2ce22e742afd998fa2f938a 100644 --- a/src/runtime/os_plan9.go +++ b/src/runtime/os_plan9.go @@ -458,7 +458,7 @@ func newosproc(mp *m) { } } -func exitThread(wait *uint32) { +func exitThread(wait *atomic.Uint32) { // We should never reach exitThread on Plan 9 because we let // the OS clean up threads. throw("exitThread") diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index c76add78025a26bb72455dc4a8728f449ade88ed..b49e9baec5880302871fcc34770c0a85e39be6d8 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -939,7 +939,7 @@ func newosproc0(mp *m, stk unsafe.Pointer) { throw("bad newosproc0") } -func exitThread(wait *uint32) { +func exitThread(wait *atomic.Uint32) { // We should never reach exitThread on Windows because we let // the OS clean up threads. throw("exitThread") diff --git a/src/runtime/proc.go b/src/runtime/proc.go index b997a467bab447b58edd9475504a6ab0de8a5614..cae15bc8e2c32d6df7f53f2bded6fa742e845c76 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -1508,19 +1508,18 @@ func mexit(osStack bool) { } throw("m not found in allm") found: - if !osStack { - // Delay reaping m until it's done with the stack. - // - // If this is using an OS stack, the OS will free it - // so there's no need for reaping. - atomic.Store(&m.freeWait, 1) - // Put m on the free list, though it will not be reaped until - // freeWait is 0. Note that the free list must not be linked - // through alllink because some functions walk allm without - // locking, so may be using alllink. - m.freelink = sched.freem - sched.freem = m - } + // Delay reaping m until it's done with the stack. + // + // Put mp on the free list, though it will not be reaped while freeWait + // is freeMWait. mp is no longer reachable via allm, so even if it is + // on an OS stack, we must keep a reference to mp alive so that the GC + // doesn't free mp while we are still using it. + // + // Note that the free list must not be linked through alllink because + // some functions walk allm without locking, so may be using alllink. + m.freeWait.Store(freeMWait) + m.freelink = sched.freem + sched.freem = m unlock(&sched.lock) atomic.Xadd64(&ncgocall, int64(m.ncgocall)) @@ -1550,6 +1549,9 @@ found: mdestroy(m) if osStack { + // No more uses of mp, so it is safe to drop the reference. + m.freeWait.Store(freeMRef) + // Return from mstart and let the system thread // library free the g0 stack and terminate the thread. return @@ -1721,19 +1723,25 @@ func allocm(_p_ *p, fn func(), id int64) *m { lock(&sched.lock) var newList *m for freem := sched.freem; freem != nil; { - if freem.freeWait != 0 { + wait := freem.freeWait.Load() + if wait == freeMWait { next := freem.freelink freem.freelink = newList newList = freem freem = next continue } - // stackfree must be on the system stack, but allocm is - // reachable off the system stack transitively from - // startm. - systemstack(func() { - stackfree(freem.g0.stack) - }) + // Free the stack if needed. For freeMRef, there is + // nothing to do except drop freem from the sched.freem + // list. + if wait == freeMStack { + // stackfree must be on the system stack, but allocm is + // reachable off the system stack transitively from + // startm. + systemstack(func() { + stackfree(freem.g0.stack) + }) + } freem = freem.freelink } sched.freem = newList diff --git a/src/runtime/rt0_linux_ppc64.s b/src/runtime/rt0_linux_ppc64.s index 897d61052a823c797d74f5baf00741a55ec29991..c9300a9caf602f8b3863b0b15e621ddfe4fe0955 100644 --- a/src/runtime/rt0_linux_ppc64.s +++ b/src/runtime/rt0_linux_ppc64.s @@ -22,6 +22,7 @@ TEXT _main<>(SB),NOSPLIT,$-8 // There is no TLS base pointer. // // TODO(austin): Support ABI v1 dynamic linking entry point + XOR R0, R0 // Note, newer kernels may not always set R0 to 0. MOVD $runtime·rt0_go(SB), R12 MOVD R12, CTR MOVBZ runtime·iscgo(SB), R5 diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index b40045e4a5b36e399192068c52e6881807062401..9cd4777cf8de2d7e8ebdc038064a6fad639a9893 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -510,6 +510,13 @@ const ( tlsSize = tlsSlots * goarch.PtrSize ) +// Values for m.freeWait. +const ( + freeMStack = 0 // M done, free stack and reference. + freeMRef = 1 // M done, free reference. + freeMWait = 2 // M still in use. +) + type m struct { g0 *g // goroutine with scheduling stack morebuf gobuf // gobuf arg to morestack @@ -540,7 +547,7 @@ type m struct { newSigstack bool // minit on C thread called sigaltstack printlock int8 incgo bool // m is executing a cgo call - freeWait uint32 // if == 0, safe to free g0 and delete m (atomic) + freeWait atomic.Uint32 // Whether it is safe to free g0 and delete m (one of freeMRef, freeMStack, freeMWait) fastrand uint64 needextram bool traceback uint8 diff --git a/src/runtime/signal_darwin_amd64.go b/src/runtime/signal_darwin_amd64.go index abc212ad5151e267efc6a17808898fec6dde1e38..20544d8489b8e622a8159f48844bd8fbf69a9032 100644 --- a/src/runtime/signal_darwin_amd64.go +++ b/src/runtime/signal_darwin_amd64.go @@ -84,6 +84,10 @@ func (c *sigctxt) fixsigcode(sig uint32) { // in real life, people will probably search for it and find this code. // There are no Google hits for b01dfacedebac1e or 0xb01dfacedebac1e // as I type this comment. + // + // Note: if this code is removed, please consider + // enabling TestSignalForwardingGo for darwin-amd64 in + // misc/cgo/testcarchive/carchive_test.go. if c.sigcode() == _SI_USER { c.set_sigcode(_SI_USER + 1) c.set_sigaddr(0xb01dfacedebac1e) diff --git a/src/runtime/stubs2.go b/src/runtime/stubs2.go index 9aa965454d991a4fda9dd84c786d65f5d9f94f8d..0d211e2db98e44609b381c374375c1fae0a37d78 100644 --- a/src/runtime/stubs2.go +++ b/src/runtime/stubs2.go @@ -6,7 +6,10 @@ package runtime -import "unsafe" +import ( + "runtime/internal/atomic" + "unsafe" +) // read calls the read system call. // It returns a non-negative number of bytes written or a negative errno value. @@ -33,8 +36,8 @@ func open(name *byte, mode, perm int32) int32 // return value is only set on linux to be used in osinit() func madvise(addr unsafe.Pointer, n uintptr, flags int32) int32 -// exitThread terminates the current thread, writing *wait = 0 when +// exitThread terminates the current thread, writing *wait = freeMStack when // the stack is safe to reclaim. // //go:noescape -func exitThread(wait *uint32) +func exitThread(wait *atomic.Uint32) diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go index 58b3a9171c79740c98b786eb0af32dbed618d723..c90cc78968caca7e79888e1e0632fdf8a2112404 100644 --- a/src/runtime/sys_darwin.go +++ b/src/runtime/sys_darwin.go @@ -6,6 +6,7 @@ package runtime import ( "internal/abi" + "runtime/internal/atomic" "unsafe" ) @@ -473,7 +474,7 @@ func pthread_cond_signal(c *pthreadcond) int32 { func pthread_cond_signal_trampoline() // Not used on Darwin, but must be defined. -func exitThread(wait *uint32) { +func exitThread(wait *atomic.Uint32) { } //go:nosplit diff --git a/src/runtime/sys_dragonfly_amd64.s b/src/runtime/sys_dragonfly_amd64.s index d57bc2a7a4ee8591a5e2c58cde77772668f6aaa0..3af0928828a7af1bd08cc46519311b16eb91e699 100644 --- a/src/runtime/sys_dragonfly_amd64.s +++ b/src/runtime/sys_dragonfly_amd64.s @@ -65,7 +65,7 @@ TEXT runtime·exit(SB),NOSPLIT,$-8 MOVL $0xf1, 0xf1 // crash RET -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT,$0-8 MOVQ wait+0(FP), AX // We're done using the stack. diff --git a/src/runtime/sys_freebsd_386.s b/src/runtime/sys_freebsd_386.s index 97e6d9ab36634ced64091e5831d2d4589405824d..d4c4cc7fdbbd076ec65a18eafae84d5a6d5d85f6 100644 --- a/src/runtime/sys_freebsd_386.s +++ b/src/runtime/sys_freebsd_386.s @@ -63,7 +63,7 @@ GLOBL exitStack<>(SB),RODATA,$8 DATA exitStack<>+0x00(SB)/4, $0 DATA exitStack<>+0x04(SB)/4, $0 -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT,$0-4 MOVL wait+0(FP), AX // We're done using the stack. diff --git a/src/runtime/sys_freebsd_amd64.s b/src/runtime/sys_freebsd_amd64.s index 165e97c60d735881ea3797df151f5c3aa79f9409..57ae0399a5f4b9f950f85d42c98deb8bc5ae01d0 100644 --- a/src/runtime/sys_freebsd_amd64.s +++ b/src/runtime/sys_freebsd_amd64.s @@ -60,7 +60,7 @@ TEXT runtime·exit(SB),NOSPLIT,$-8 MOVL $0xf1, 0xf1 // crash RET -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.uint32) TEXT runtime·exitThread(SB),NOSPLIT,$0-8 MOVQ wait+0(FP), AX // We're done using the stack. diff --git a/src/runtime/sys_freebsd_arm.s b/src/runtime/sys_freebsd_arm.s index b12e47c576daeb8a3b3556f405e5c5fbea0d4007..8546eba8058e2285e7d7d7d98c65a72dd853376f 100644 --- a/src/runtime/sys_freebsd_arm.s +++ b/src/runtime/sys_freebsd_arm.s @@ -86,7 +86,7 @@ TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0 MOVW.CS R8, (R8) RET -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT,$0-4 MOVW wait+0(FP), R0 // We're done using the stack. diff --git a/src/runtime/sys_freebsd_arm64.s b/src/runtime/sys_freebsd_arm64.s index 1aa09e87ca1dc3fc304ff01f8925525a9c72dcf5..7dab3028de41e6a41c27f23ebc27505c60fcc02e 100644 --- a/src/runtime/sys_freebsd_arm64.s +++ b/src/runtime/sys_freebsd_arm64.s @@ -98,7 +98,7 @@ TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4 MOVD $0, R0 MOVD R0, (R0) -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8 MOVD wait+0(FP), R0 // We're done using the stack. diff --git a/src/runtime/sys_linux_386.s b/src/runtime/sys_linux_386.s index 6df812234c3f9cf4591a83375a2dc39b4745662f..ddc5534352526120f859da9a6fa71765a1bca029 100644 --- a/src/runtime/sys_linux_386.s +++ b/src/runtime/sys_linux_386.s @@ -78,7 +78,7 @@ TEXT exit1<>(SB),NOSPLIT,$0 INT $3 // not reached RET -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT,$0-4 MOVL wait+0(FP), AX // We're done using the stack. diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s index f0e58e11db36ec56ed0bf2de730f198a64cec0a3..5431dea4fc178c0c4dde9bb9f32c0cf066dddff6 100644 --- a/src/runtime/sys_linux_amd64.s +++ b/src/runtime/sys_linux_amd64.s @@ -60,7 +60,7 @@ TEXT runtime·exit(SB),NOSPLIT,$0-4 SYSCALL RET -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT,$0-8 MOVQ wait+0(FP), AX // We're done using the stack. diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s index ca443b699fdcf3b2cf6b3866fadad8a008ff5c57..e41afdb066a3bb34bebddf77d532ded6c5745304 100644 --- a/src/runtime/sys_linux_arm.s +++ b/src/runtime/sys_linux_arm.s @@ -131,7 +131,7 @@ TEXT exit1<>(SB),NOSPLIT|NOFRAME,$0 MOVW $1003, R1 MOVW R0, (R1) // fail hard -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-4 MOVW wait+0(FP), R0 // We're done using the stack. diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s index 1276c077d701f2c8bf894d780a79d8938d05268e..47e17182527fd9713aa48c63c17e8e7c2bc7e4b0 100644 --- a/src/runtime/sys_linux_arm64.s +++ b/src/runtime/sys_linux_arm64.s @@ -59,7 +59,7 @@ TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4 SVC RET -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8 MOVD wait+0(FP), R0 // We're done using the stack. diff --git a/src/runtime/sys_linux_mips64x.s b/src/runtime/sys_linux_mips64x.s index 0df25979939357b4b464e0aaa44586903ef7be44..315a6e48354f46ca04e3ba66d06295a4f8871ac9 100644 --- a/src/runtime/sys_linux_mips64x.s +++ b/src/runtime/sys_linux_mips64x.s @@ -56,7 +56,7 @@ TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4 SYSCALL RET -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8 MOVV wait+0(FP), R1 // We're done using the stack. diff --git a/src/runtime/sys_linux_mipsx.s b/src/runtime/sys_linux_mipsx.s index 2207e9ab98f702fb0a2b43ddf6d2a6d19a1d668d..991b7ba60e252f5a2e514d986de38fa25b1f5080 100644 --- a/src/runtime/sys_linux_mipsx.s +++ b/src/runtime/sys_linux_mipsx.s @@ -56,7 +56,7 @@ TEXT runtime·exit(SB),NOSPLIT,$0-4 UNDEF RET -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT,$0-4 MOVW wait+0(FP), R1 // We're done using the stack. diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s index dc3d89fae741c7ff808cf38bc253e2287ef91d4c..b86a820ab2de0f9353506e4712009f527bee9431 100644 --- a/src/runtime/sys_linux_ppc64x.s +++ b/src/runtime/sys_linux_ppc64x.s @@ -55,7 +55,7 @@ TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4 SYSCALL $SYS_exit_group RET -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8 MOVD wait+0(FP), R1 // We're done using the stack. @@ -119,16 +119,23 @@ TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20 MOVW R3, errno+16(FP) RET +// func usleep(usec uint32) TEXT runtime·usleep(SB),NOSPLIT,$16-4 MOVW usec+0(FP), R3 - MOVD R3, R5 - MOVW $1000000, R4 - DIVD R4, R3 - MOVD R3, 8(R1) - MOVW $1000, R4 - MULLD R3, R4 - SUB R4, R5 - MOVD R5, 16(R1) + + // Use magic constant 0x8637bd06 and shift right 51 + // to perform usec/1000000. + ORIS $0x8637, R0, R4 // Note, R0 always contains 0 here. + OR $0xbd06, R4, R4 + MULLD R3, R4, R4 // Convert usec to S. + SRD $51, R4, R4 + MOVD R4, 8(R1) // Store to tv_sec + + MOVD $1000000, R5 + MULLW R4, R5, R5 // Convert tv_sec back into uS + SUB R5, R3, R5 // Compute remainder uS. + MULLD $1000, R5, R5 // Convert to nsec + MOVD R5, 16(R1) // Store to tv_nsec // nanosleep(&ts, 0) ADD $8, R1, R3 diff --git a/src/runtime/sys_linux_riscv64.s b/src/runtime/sys_linux_riscv64.s index a3da46d1362fbcd615ff4378cbc229b302d6e644..8b1b26b03b5b34aec2810c0acac8921df36b2e72 100644 --- a/src/runtime/sys_linux_riscv64.s +++ b/src/runtime/sys_linux_riscv64.s @@ -61,7 +61,7 @@ TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4 ECALL RET -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8 MOV wait+0(FP), A0 // We're done using the stack. diff --git a/src/runtime/sys_linux_s390x.s b/src/runtime/sys_linux_s390x.s index 886add8b543b3c927db0e362f535a1c90ec6d1cb..ca080b422517f0476158eb2ba91907540f969316 100644 --- a/src/runtime/sys_linux_s390x.s +++ b/src/runtime/sys_linux_s390x.s @@ -52,7 +52,7 @@ TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4 SYSCALL RET -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8 MOVD wait+0(FP), R1 // We're done using the stack. diff --git a/src/runtime/sys_netbsd_386.s b/src/runtime/sys_netbsd_386.s index 8a33894892f1f1e0ca8b1b9612b470984aee89a9..6c5386bcf1270b059ad5d8851890a8d9531ef42c 100644 --- a/src/runtime/sys_netbsd_386.s +++ b/src/runtime/sys_netbsd_386.s @@ -53,7 +53,7 @@ TEXT runtime·exit(SB),NOSPLIT,$-4 MOVL $0xf1, 0xf1 // crash RET -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT,$0-4 MOVL wait+0(FP), AX // We're done using the stack. diff --git a/src/runtime/sys_netbsd_amd64.s b/src/runtime/sys_netbsd_amd64.s index 02f5b4ba3b71c386ee2beb37db3e8c332e3aff34..c1cd95df1493d12cbffe1409c1d16ea994c8dc31 100644 --- a/src/runtime/sys_netbsd_amd64.s +++ b/src/runtime/sys_netbsd_amd64.s @@ -122,7 +122,7 @@ TEXT runtime·exit(SB),NOSPLIT,$-8 MOVL $0xf1, 0xf1 // crash RET -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT,$0-8 MOVQ wait+0(FP), AX // We're done using the stack. diff --git a/src/runtime/sys_netbsd_arm.s b/src/runtime/sys_netbsd_arm.s index 3a763b2a6a7730035488b5323ff32023c129f50e..2422b0282e99de34991f022d043dfc63bc90d478 100644 --- a/src/runtime/sys_netbsd_arm.s +++ b/src/runtime/sys_netbsd_arm.s @@ -56,7 +56,7 @@ TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0 MOVW.CS R8, (R8) RET -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT,$0-4 MOVW wait+0(FP), R0 // We're done using the stack. diff --git a/src/runtime/sys_netbsd_arm64.s b/src/runtime/sys_netbsd_arm64.s index 8a0496e80722e349bfc59ffe405be2419b99cc02..6d2c31631d0e7c28952ce82eba199479c9313fe9 100644 --- a/src/runtime/sys_netbsd_arm64.s +++ b/src/runtime/sys_netbsd_arm64.s @@ -114,7 +114,7 @@ TEXT runtime·exit(SB),NOSPLIT,$-8 MOVD $0, R0 // If we're still running, MOVD R0, (R0) // crash -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT,$0-8 MOVD wait+0(FP), R0 // We're done using the stack. diff --git a/src/runtime/sys_openbsd2.go b/src/runtime/sys_openbsd2.go index 4d50b4f6b136f23d5c615acadf1ad28748e130cc..cba35cfee3e73db7f5b3c749961c08d1fa96bdfc 100644 --- a/src/runtime/sys_openbsd2.go +++ b/src/runtime/sys_openbsd2.go @@ -8,6 +8,7 @@ package runtime import ( "internal/abi" + "runtime/internal/atomic" "unsafe" ) @@ -250,7 +251,7 @@ func sigaltstack(new *stackt, old *stackt) { func sigaltstack_trampoline() // Not used on OpenBSD, but must be defined. -func exitThread(wait *uint32) { +func exitThread(wait *atomic.Uint32) { } //go:nosplit diff --git a/src/runtime/sys_openbsd_mips64.s b/src/runtime/sys_openbsd_mips64.s index f8ae8e7c3014b7eb8a0ff28a5d517354ded709fc..bc392e4c54d436bdb01f317dfdc51ac95b30d363 100644 --- a/src/runtime/sys_openbsd_mips64.s +++ b/src/runtime/sys_openbsd_mips64.s @@ -24,7 +24,7 @@ TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0 MOVV R2, (R2) RET -// func exitThread(wait *uint32) +// func exitThread(wait *atomic.Uint32) TEXT runtime·exitThread(SB),NOSPLIT,$0 MOVV wait+0(FP), R4 // arg 1 - notdead MOVV $302, R2 // sys___threxit diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go index 9c38facf081f7a8760b1145aa2412a00dc99d941..d36f5718f33c286309c46bcbe521d246e72f77fa 100644 --- a/src/runtime/syscall_windows.go +++ b/src/runtime/syscall_windows.go @@ -12,12 +12,30 @@ import ( // cbs stores all registered Go callbacks. var cbs struct { - lock mutex + lock mutex // use cbsLock / cbsUnlock for race instrumentation. ctxt [cb_max]winCallback index map[winCallbackKey]int n int } +func cbsLock() { + lock(&cbs.lock) + // compileCallback is used by goenvs prior to completion of schedinit. + // raceacquire involves a racecallback to get the proc, which is not + // safe prior to scheduler initialization. Thus avoid instrumentation + // until then. + if raceenabled && mainStarted { + raceacquire(unsafe.Pointer(&cbs.lock)) + } +} + +func cbsUnlock() { + if raceenabled && mainStarted { + racerelease(unsafe.Pointer(&cbs.lock)) + } + unlock(&cbs.lock) +} + // winCallback records information about a registered Go callback. type winCallback struct { fn *funcval // Go function @@ -302,11 +320,11 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) { key := winCallbackKey{(*funcval)(fn.data), cdecl} - lock(&cbs.lock) // We don't unlock this in a defer because this is used from the system stack. + cbsLock() // Check if this callback is already registered. if n, ok := cbs.index[key]; ok { - unlock(&cbs.lock) + cbsUnlock() return callbackasmAddr(n) } @@ -316,7 +334,7 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) { } n := cbs.n if n >= len(cbs.ctxt) { - unlock(&cbs.lock) + cbsUnlock() throw("too many callback functions") } c := winCallback{key.fn, retPop, abiMap} @@ -324,7 +342,7 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) { cbs.index[key] = n cbs.n++ - unlock(&cbs.lock) + cbsUnlock() return callbackasmAddr(n) } diff --git a/src/runtime/time.go b/src/runtime/time.go index a9ad62077644eed6af2560985d03dcc46169860b..a47f6b522ddb4ddbdd5fb90b0f189f9c3d3d930c 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -391,7 +391,11 @@ func dodeltimer(pp *p, i int) int { if i == 0 { updateTimer0When(pp) } - atomic.Xadd(&pp.numTimers, -1) + n := atomic.Xadd(&pp.numTimers, -1) + if n == 0 { + // If there are no timers, then clearly none are modified. + atomic.Store64(&pp.timerModifiedEarliest, 0) + } return smallestChanged } @@ -415,7 +419,11 @@ func dodeltimer0(pp *p) { siftdownTimer(pp.timers, 0) } updateTimer0When(pp) - atomic.Xadd(&pp.numTimers, -1) + n := atomic.Xadd(&pp.numTimers, -1) + if n == 0 { + // If there are no timers, then clearly none are modified. + atomic.Store64(&pp.timerModifiedEarliest, 0) + } } // modtimer modifies an existing timer. diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index 229e3a9105520e8ca2ba231656228c3a8a94143c..b8f580f084cbe286aec32b2643b65c95ba4e83e8 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -82,6 +82,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in } waspanic := false cgoCtxt := gp.cgoCtxt + stack := gp.stack printing := pcbuf == nil && callback == nil // If the PC is zero, it's likely a nil function call. @@ -114,7 +115,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in if !f.valid() { if callback != nil || printing { print("runtime: unknown pc ", hex(frame.pc), "\n") - tracebackHexdump(gp.stack, &frame, 0) + tracebackHexdump(stack, &frame, 0) } if callback != nil { throw("unknown pc") @@ -174,12 +175,26 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in frame.fn = findfunc(frame.pc) f = frame.fn flag = f.flag + frame.lr = gp.m.curg.sched.lr frame.sp = gp.m.curg.sched.sp + stack = gp.m.curg.stack cgoCtxt = gp.m.curg.cgoCtxt case funcID_systemstack: // systemstack returns normally, so just follow the // stack transition. + if usesLR && funcspdelta(f, frame.pc, &cache) == 0 { + // We're at the function prologue and the stack + // switch hasn't happened, or epilogue where we're + // about to return. Just unwind normally. + // Do this only on LR machines because on x86 + // systemstack doesn't have an SP delta (the CALL + // instruction opens the frame), therefore no way + // to check. + flag &^= funcFlag_SPWRITE + break + } frame.sp = gp.m.curg.sched.sp + stack = gp.m.curg.stack cgoCtxt = gp.m.curg.cgoCtxt flag &^= funcFlag_SPWRITE } @@ -248,7 +263,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in } if callback != nil || doPrint { print("runtime: unexpected return pc for ", funcname(f), " called from ", hex(frame.lr), "\n") - tracebackHexdump(gp.stack, &frame, lrPtr) + tracebackHexdump(stack, &frame, lrPtr) } if callback != nil { throw("unknown caller pc") @@ -477,6 +492,13 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in break } + if frame.pc == frame.lr && frame.sp == frame.fp { + // If the next frame is identical to the current frame, we cannot make progress. + print("runtime: traceback stuck. pc=", hex(frame.pc), " sp=", hex(frame.sp), "\n") + tracebackHexdump(stack, &frame, frame.sp) + throw("traceback stuck") + } + // Unwind to next frame. frame.fn = flr frame.pc = frame.lr diff --git a/src/syscall/exec_windows.go b/src/syscall/exec_windows.go index 9d10d6a51271f62c2b7daa86db0c774dff5084b6..50892bee442f26afdc1fa34a1082bc08c38b0a83 100644 --- a/src/syscall/exec_windows.go +++ b/src/syscall/exec_windows.go @@ -7,6 +7,7 @@ package syscall import ( + "internal/bytealg" "runtime" "sync" "unicode/utf16" @@ -115,12 +116,16 @@ func makeCmdLine(args []string) string { // the representation required by CreateProcess: a sequence of NUL // terminated strings followed by a nil. // Last bytes are two UCS-2 NULs, or four NUL bytes. -func createEnvBlock(envv []string) *uint16 { +// If any string contains a NUL, it returns (nil, EINVAL). +func createEnvBlock(envv []string) (*uint16, error) { if len(envv) == 0 { - return &utf16.Encode([]rune("\x00\x00"))[0] + return &utf16.Encode([]rune("\x00\x00"))[0], nil } length := 0 for _, s := range envv { + if bytealg.IndexByteString(s, 0) != -1 { + return nil, EINVAL + } length += len(s) + 1 } length += 1 @@ -135,7 +140,7 @@ func createEnvBlock(envv []string) *uint16 { } copy(b[i:i+1], []byte{0}) - return &utf16.Encode([]rune(string(b)))[0] + return &utf16.Encode([]rune(string(b)))[0], nil } func CloseOnExec(fd Handle) { @@ -400,12 +405,17 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle } } + envBlock, err := createEnvBlock(attr.Env) + if err != nil { + return 0, 0, err + } + pi := new(ProcessInformation) flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT | _EXTENDED_STARTUPINFO_PRESENT if sys.Token != 0 { - err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi) + err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, envBlock, dirp, &si.StartupInfo, pi) } else { - err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi) + err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, envBlock, dirp, &si.StartupInfo, pi) } if err != nil { return 0, 0, err diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index f32020ca6ceb39891e1fa3540efc617e71536c7b..f694d8ca35e019bf8ffe64ef23618514033b303a 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -546,21 +546,6 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { return nil, EAFNOSUPPORT } -func Accept(fd int) (nfd int, sa Sockaddr, err error) { - var rsa RawSockaddrAny - var len _Socklen = SizeofSockaddrAny - nfd, err = accept4(fd, &rsa, &len, 0) - if err != nil { - return - } - sa, err = anyToSockaddr(&rsa) - if err != nil { - Close(nfd) - nfd = 0 - } - return -} - func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) { var rsa RawSockaddrAny var len _Socklen = SizeofSockaddrAny diff --git a/src/syscall/syscall_linux_accept.go b/src/syscall/syscall_linux_accept.go new file mode 100644 index 0000000000000000000000000000000000000000..2ba60f06366a8d5f3210593779c09f200f014832 --- /dev/null +++ b/src/syscall/syscall_linux_accept.go @@ -0,0 +1,32 @@ +// Copyright 2009 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. + +// We require Linux kernel version 2.6.32. The accept4 system call was +// added in version 2.6.28, so in general we can use accept4. +// Unfortunately, for ARM only, accept4 was added in version 2.6.36. +// Handle that case here, by using a copy of the Accept function that +// we used in Go 1.17. + +//go:build linux && arm + +package syscall + +func Accept(fd int) (nfd int, sa Sockaddr, err error) { + var rsa RawSockaddrAny + var len _Socklen = SizeofSockaddrAny + // Try accept4 first for Android and newer kernels. + nfd, err = accept4(fd, &rsa, &len, 0) + if err == ENOSYS { + nfd, err = accept(fd, &rsa, &len) + } + if err != nil { + return + } + sa, err = anyToSockaddr(&rsa) + if err != nil { + Close(nfd) + nfd = 0 + } + return +} diff --git a/src/syscall/syscall_linux_accept4.go b/src/syscall/syscall_linux_accept4.go new file mode 100644 index 0000000000000000000000000000000000000000..74898672c0466ab26de838467788458747783e79 --- /dev/null +++ b/src/syscall/syscall_linux_accept4.go @@ -0,0 +1,25 @@ +// Copyright 2009 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. + +// This file provides the Accept function used on all systems +// other than arm. See syscall_linux_accept.go for why. + +//go:build linux && !arm + +package syscall + +func Accept(fd int) (nfd int, sa Sockaddr, err error) { + var rsa RawSockaddrAny + var len _Socklen = SizeofSockaddrAny + nfd, err = accept4(fd, &rsa, &len, 0) + if err != nil { + return + } + sa, err = anyToSockaddr(&rsa) + if err != nil { + Close(nfd) + nfd = 0 + } + return +} diff --git a/src/testing/testing.go b/src/testing/testing.go index df4dfe4490439e89c9a15e9f5b241805ec897d6b..05d8f22affdb5a5b8df74963fb6e7e0ef6a46412 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1122,7 +1122,7 @@ func removeAll(path string) error { ) for { err := os.RemoveAll(path) - if !isWindowsAccessDenied(err) { + if !isWindowsRetryable(err) { return err } if start.IsZero() { diff --git a/src/testing/testing_other.go b/src/testing/testing_other.go index 29496d81bc7f1aa03a1542ead1070003b87499bb..99a6276a4a39a99cd7be9acc8c88ef4f09cabb7f 100644 --- a/src/testing/testing_other.go +++ b/src/testing/testing_other.go @@ -6,8 +6,8 @@ package testing -// isWindowsAccessDenied reports whether err is ERROR_ACCESS_DENIED, -// which is defined only on Windows. -func isWindowsAccessDenied(err error) bool { +// isWindowsRetryable reports whether err is a Windows error code +// that may be fixed by retrying a failed filesystem operation. +func isWindowsRetryable(err error) bool { return false } diff --git a/src/testing/testing_windows.go b/src/testing/testing_windows.go index bc76cb80ccc0c2f9ccb65edea0b19c42e887ea97..fd48ae9579e05251b369f89bb1811b06f99db0a4 100644 --- a/src/testing/testing_windows.go +++ b/src/testing/testing_windows.go @@ -8,11 +8,25 @@ package testing import ( "errors" + "internal/syscall/windows" "syscall" ) -// isWindowsAccessDenied reports whether err is ERROR_ACCESS_DENIED, -// which is defined only on Windows. -func isWindowsAccessDenied(err error) bool { - return errors.Is(err, syscall.ERROR_ACCESS_DENIED) +// isWindowsRetryable reports whether err is a Windows error code +// that may be fixed by retrying a failed filesystem operation. +func isWindowsRetryable(err error) bool { + for { + unwrapped := errors.Unwrap(err) + if unwrapped == nil { + break + } + err = unwrapped + } + if err == syscall.ERROR_ACCESS_DENIED { + return true // Observed in https://go.dev/issue/50051. + } + if err == windows.ERROR_SHARING_VIOLATION { + return true // Observed in https://go.dev/issue/51442. + } + return false } diff --git a/src/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go b/src/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go index a864f24d7589aa0d84734690953a55c27b2d9bba..96134157a10d18881e5b7fd9db35d5b3a2fc0952 100644 --- a/src/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go +++ b/src/vendor/golang.org/x/sys/cpu/syscall_aix_gccgo.go @@ -5,7 +5,7 @@ // Recreate a getsystemcfg syscall handler instead of // using the one provided by x/sys/unix to avoid having // the dependency between them. (See golang.org/issue/32102) -// Morever, this file will be used during the building of +// Moreover, this file will be used during the building of // gccgo's libgo and thus must not used a CGo method. //go:build aix && gccgo diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 3a975cde9e838a5fe24d89346de2ef1524abe505..157c1fe602a31e76a33c3ece39c9111ed641081d 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -9,7 +9,7 @@ golang.org/x/crypto/curve25519/internal/field golang.org/x/crypto/hkdf golang.org/x/crypto/internal/poly1305 golang.org/x/crypto/internal/subtle -# golang.org/x/net v0.0.0-20211209124913-491a49abca63 +# golang.org/x/net v0.0.0-20221214163811-6143a133e5c9 ## explicit; go 1.17 golang.org/x/net/dns/dnsmessage golang.org/x/net/http/httpguts @@ -19,7 +19,7 @@ golang.org/x/net/idna golang.org/x/net/lif golang.org/x/net/nettest golang.org/x/net/route -# golang.org/x/sys v0.0.0-20211205182925-97ca703d548d +# golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 ## explicit; go 1.17 golang.org/x/sys/cpu # golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 diff --git a/test/fixedbugs/issue52788.go b/test/fixedbugs/issue52788.go new file mode 100644 index 0000000000000000000000000000000000000000..b0d7d142fc25de1d3d9e565695ddbd3d35adcd66 --- /dev/null +++ b/test/fixedbugs/issue52788.go @@ -0,0 +1,27 @@ +// run + +// Copyright 2022 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. + +// Issue 52788: miscompilation for boolean comparison on ARM64. + +package main + +import ( + "fmt" + "reflect" +) + +func f(next func() bool) { + for b := next(); b; b = next() { + fmt.Printf("next() returned %v\n", b) + } +} + +func main() { + next := reflect.MakeFunc(reflect.TypeOf((func() bool)(nil)), func(_ []reflect.Value) []reflect.Value { + return []reflect.Value{reflect.ValueOf(false)} + }) + reflect.ValueOf(f).Call([]reflect.Value{next}) +} diff --git a/test/fixedbugs/issue52788a.go b/test/fixedbugs/issue52788a.go new file mode 100644 index 0000000000000000000000000000000000000000..38b8416150c924fb697bd54862d5caee60a89032 --- /dev/null +++ b/test/fixedbugs/issue52788a.go @@ -0,0 +1,29 @@ +// run + +// Copyright 2022 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. + +// Issue 52788: miscompilation for boolean ops on ARM64. + +package main + +import ( + "fmt" + "reflect" + "os" +) + +func f(next func() bool) { + for b := next(); b; b = next() { + fmt.Printf("%v\n", b) + os.Exit(0) + } +} + +func main() { + next := reflect.MakeFunc(reflect.TypeOf((func() bool)(nil)), func(_ []reflect.Value) []reflect.Value { + return []reflect.Value{reflect.ValueOf(true)} + }) + reflect.ValueOf(f).Call([]reflect.Value{next}) +} diff --git a/test/fixedbugs/issue52788a.out b/test/fixedbugs/issue52788a.out new file mode 100644 index 0000000000000000000000000000000000000000..27ba77ddaf61532f217964734769a42cdabc17dc --- /dev/null +++ b/test/fixedbugs/issue52788a.out @@ -0,0 +1 @@ +true diff --git a/test/fixedbugs/issue52953.go b/test/fixedbugs/issue52953.go new file mode 100644 index 0000000000000000000000000000000000000000..2085e4e3fe36ec11998d556ad5ad7f739fa693ff --- /dev/null +++ b/test/fixedbugs/issue52953.go @@ -0,0 +1,29 @@ +// run + +// Copyright 2022 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. + +// Issue 52953: miscompilation for composite literal assignment +// when LHS is address-taken. + +package main + +type T struct { + Field1 bool +} + +func main() { + var ret T + ret.Field1 = true + var v *bool = &ret.Field1 + ret = T{Field1: *v} + check(ret.Field1) +} + +//go:noinline +func check(b bool) { + if !b { + panic("FAIL") + } +} diff --git a/test/fixedbugs/issue53137.dir/main.go b/test/fixedbugs/issue53137.dir/main.go new file mode 100644 index 0000000000000000000000000000000000000000..88632bf0cbc04889f3093825ced83d368ed9423d --- /dev/null +++ b/test/fixedbugs/issue53137.dir/main.go @@ -0,0 +1,30 @@ +// Copyright 2022 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. + +package main + +import ( + "unsafe" +) + +type Embedded struct { + B int +} + +type S[K any] struct { + A K + Embedded +} + +func showOffsets[K any](d *S[K]) { + o1 := unsafe.Offsetof(d.B) + o2 := unsafe.Offsetof(d.Embedded) + if o1 != o2 { + panic("offset mismatch") + } +} + +func main() { + showOffsets(new(S[int])) +} diff --git a/test/fixedbugs/issue53137.go b/test/fixedbugs/issue53137.go new file mode 100644 index 0000000000000000000000000000000000000000..aefbe673109b6c7187837e3464eef47858d0eb00 --- /dev/null +++ b/test/fixedbugs/issue53137.go @@ -0,0 +1,7 @@ +// rundir + +// Copyright 2022 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. + +package ignored diff --git a/test/fixedbugs/issue53454.go b/test/fixedbugs/issue53454.go new file mode 100644 index 0000000000000000000000000000000000000000..8b16d8183988bbf59cd5d1bc1c99e5d7bfe115d7 --- /dev/null +++ b/test/fixedbugs/issue53454.go @@ -0,0 +1,89 @@ +// compile + +// Copyright 2022 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. + +package main + +type T1 struct { + A T5 + B T2 + C T7 + D T4 +} + +type T2 struct { + T3 + A float64 + E float64 + C float64 +} + +type T3 struct { + F float64 + G float64 + H float64 + I float64 + J float64 + K float64 + L float64 +} + +type T4 struct { + M float64 + N float64 + O float64 + P float64 +} + +type T5 struct { + Q float64 + R float64 + S float64 + T float64 + U float64 + V float64 +} + +type T6 struct { + T9 + C T10 +} + +type T7 struct { + T10 + T11 +} + +type T8 struct { + T9 + C T7 +} + +type T9 struct { + A T5 + B T3 + D T4 +} + +type T10 struct { + W float64 +} + +type T11 struct { + X float64 + Y float64 +} + +func MainTest(x T1, y T8, z T6) float64 { + return Test(x.B, x.A, x.D, x.C, y.B, y.A, y.D, y.C, z.B, z.A, z.D, + T7{ + T10: T10{ + W: z.C.W, + }, + T11: T11{}, + }, + ) +} +func Test(a T2, b T5, c T4, d T7, e T3, f T5, g T4, h T7, i T3, j T5, k T4, l T7) float64 diff --git a/test/fixedbugs/issue53600.go b/test/fixedbugs/issue53600.go new file mode 100644 index 0000000000000000000000000000000000000000..fd3a9e5e470aa729714e940faf771e199fd83707 --- /dev/null +++ b/test/fixedbugs/issue53600.go @@ -0,0 +1,42 @@ +// run + +// Copyright 2022 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. + +package main + +import "math" + +func main() { + f() + g() + h() +} +func f() { + for i := int64(math.MaxInt64); i <= math.MaxInt64; i++ { + if i < 0 { + println("done") + return + } + println(i, i < 0) + } +} +func g() { + for i := int64(math.MaxInt64) - 1; i <= math.MaxInt64; i++ { + if i < 0 { + println("done") + return + } + println(i, i < 0) + } +} +func h() { + for i := int64(math.MaxInt64) - 2; i <= math.MaxInt64; i += 2 { + if i < 0 { + println("done") + return + } + println(i, i < 0) + } +} diff --git a/test/fixedbugs/issue53600.out b/test/fixedbugs/issue53600.out new file mode 100644 index 0000000000000000000000000000000000000000..5590c7dcfb7070f0ef9027674165f24da0591ac4 --- /dev/null +++ b/test/fixedbugs/issue53600.out @@ -0,0 +1,8 @@ +9223372036854775807 false +done +9223372036854775806 false +9223372036854775807 false +done +9223372036854775805 false +9223372036854775807 false +done diff --git a/test/fixedbugs/issue53702.go b/test/fixedbugs/issue53702.go new file mode 100644 index 0000000000000000000000000000000000000000..0b251c2d7be969ba13253c14a403b9b345f64693 --- /dev/null +++ b/test/fixedbugs/issue53702.go @@ -0,0 +1,39 @@ +// run + +// Copyright 2022 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. + +package main + +type Elem struct{} + +func (*Elem) Wait(callback func()) {} + +type Base struct { + elem [8]*Elem +} + +var g_val = 1 + +func (s *Base) Do() *int { + resp := &g_val + for _, e := range s.elem { + e.Wait(func() { + *resp = 0 + }) + } + return resp +} + +type Sub struct { + *Base +} + +func main() { + a := Sub{new(Base)} + resp := a.Do() + if resp != nil && *resp != 1 { + panic("FAIL") + } +} diff --git a/test/fixedbugs/issue54467.go b/test/fixedbugs/issue54467.go new file mode 100644 index 0000000000000000000000000000000000000000..42e221c95412646f5f68aae72bcf49bffaa529f0 --- /dev/null +++ b/test/fixedbugs/issue54467.go @@ -0,0 +1,26 @@ +// run + +// Copyright 2022 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. + +package main + +import "fmt" + +func main() { + var x [64]byte + for i := range x { + x[i] = byte(i) + } + y := x + + copy(x[4:36], x[2:34]) + *(*[32]byte)(y[4:36]) = *(*[32]byte)(y[2:34]) + + for i := range x { + if x[i] != y[i] { + fmt.Printf("x[%v] = %v; y[%v] = %v\n", i, x[i], i, y[i]) + } + } +} diff --git a/test/fixedbugs/issue55122.go b/test/fixedbugs/issue55122.go new file mode 100644 index 0000000000000000000000000000000000000000..24da89dcb6d31fb692df9967058d6b15b9219d70 --- /dev/null +++ b/test/fixedbugs/issue55122.go @@ -0,0 +1,42 @@ +// run + +// Copyright 2022 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. + +package main + +func main() { + for i := 0; i < 10000; i++ { + h(i) + sink = make([]byte, 1024) // generate some garbage + } +} + +func h(iter int) { + var x [32]byte + for i := 0; i < 32; i++ { + x[i] = 99 + } + g(&x) + if x == ([32]byte{}) { + return + } + for i := 0; i < 32; i++ { + println(x[i]) + } + panic(iter) +} + +//go:noinline +func g(x interface{}) { + switch e := x.(type) { + case *[32]byte: + var c [32]byte + *e = c + case *[]byte: + *e = nil + } +} + +var sink []byte diff --git a/test/fixedbugs/issue55122b.go b/test/fixedbugs/issue55122b.go new file mode 100644 index 0000000000000000000000000000000000000000..a911a9f1b6aa562c485356addef0d127096d4f18 --- /dev/null +++ b/test/fixedbugs/issue55122b.go @@ -0,0 +1,43 @@ +// run + +// Copyright 2022 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. + +package main + +func main() { + for i := 0; i < 10000; i++ { + h(i) + sink = make([]byte, 1024) // generate some garbage + } +} + +func h(iter int) { + var x [32]byte + for i := 0; i < 32; i++ { + x[i] = 99 + } + g(&x) + if x == ([32]byte{}) { + return + } + for i := 0; i < 32; i++ { + println(x[i]) + } + panic(iter) +} + +//go:noinline +func g(x interface{}) { + switch e := x.(type) { + case *[32]byte: + var c [32]byte + *e = c + case *[3]*byte: + var c [3]*byte + *e = c + } +} + +var sink []byte diff --git a/test/fixedbugs/issue55889.go b/test/fixedbugs/issue55889.go new file mode 100644 index 0000000000000000000000000000000000000000..68812c2157b851dc273580136985ef80cf3af7c6 --- /dev/null +++ b/test/fixedbugs/issue55889.go @@ -0,0 +1,21 @@ +// errorcheck -0 -lang=go1.17 + +// Copyright 2022 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. + +// Prior to Go 1.18, ineffectual //go:linkname directives were treated +// as noops. Ensure that modules that contain these directives (e.g., +// x/sys prior to go.dev/cl/274573) continue to compile. + +package p + +import _ "unsafe" + +//go:linkname nonexistent nonexistent + +//go:linkname constant constant +const constant = 42 + +//go:linkname typename typename +type typename int diff --git a/test/fixedbugs/issue57184.go b/test/fixedbugs/issue57184.go new file mode 100644 index 0000000000000000000000000000000000000000..1384b50be8779df1624128c301d1411f2c94a7d9 --- /dev/null +++ b/test/fixedbugs/issue57184.go @@ -0,0 +1,40 @@ +// run + +// Copyright 2022 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. + +package main + +import ( + "log" + "reflect" + "sort" +) + +func main() { + const length = 257 + x := make([]int64, length) + for i := 0; i < length; i++ { + x[i] = int64(i) * 27644437 % int64(length) + } + + isLessStatic := func(i, j int) bool { + return x[i] < x[j] + } + + isLessReflect := reflect.MakeFunc(reflect.TypeOf(isLessStatic), func(args []reflect.Value) []reflect.Value { + i := args[0].Int() + j := args[1].Int() + b := x[i] < x[j] + return []reflect.Value{reflect.ValueOf(b)} + }).Interface().(func(i, j int) bool) + + sort.SliceStable(x, isLessReflect) + + for i := 0; i < length-1; i++ { + if x[i] >= x[i+1] { + log.Fatalf("not sorted! (length=%v, idx=%v)\n%v\n", length, i, x) + } + } +} diff --git a/test/nilptr5.go b/test/nilptr5.go index 2c48c0b26101969bb998a1e78819bb3421cbca1b..118746e4aa9086ddc1cd6f7e66e6248c22ab71df 100644 --- a/test/nilptr5.go +++ b/test/nilptr5.go @@ -1,7 +1,7 @@ // errorcheck -0 -d=nil -// +build !wasm -// +build !aix +//go:build !wasm && !aix +// +build !wasm,!aix // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -20,7 +20,7 @@ func f5(p *float32, q *float64, r *float32, s *float64) float64 { return x + y } -type T [29]byte +type T struct{ b [29]byte } func f6(p, q *T) { x := *p // ERROR "removed nil check" @@ -28,6 +28,6 @@ func f6(p, q *T) { } // make sure to remove nil check for memory move (issue #18003) -func f8(t *[8]int) [8]int { +func f8(t *struct{ b [8]int }) struct{ b [8]int } { return *t // ERROR "removed nil check" } diff --git a/test/typeparam/issue51840.go b/test/typeparam/issue51840.go deleted file mode 100644 index f0ca9d1a1dbd082b69b211d65191cc63b996b26d..0000000000000000000000000000000000000000 --- a/test/typeparam/issue51840.go +++ /dev/null @@ -1,36 +0,0 @@ -// compile -G=3 - -// Copyright 2022 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. - -package main - -type Addr struct { - hi uint64 - lo uint64 - z *byte -} - -func EqualMap[M1, M2 ~map[K]V, K, V comparable](m1 M1, m2 M2) bool { - for k, v1 := range m1 { - if v2, ok := m2[k]; !ok || v1 != v2 { - return false - } - } - return true -} - -type Set[T comparable] map[T]struct{} - -func NewSet[T comparable](items ...T) Set[T] { - return nil -} - -func (s Set[T]) Equals(other Set[T]) bool { - return EqualMap(s, other) -} - -func main() { - NewSet[Addr](Addr{0, 0, nil}) -} diff --git a/test/typeparam/issue53419.go b/test/typeparam/issue53419.go new file mode 100644 index 0000000000000000000000000000000000000000..0bef4a91a079210df72abfa8dda1491ec5290ee7 --- /dev/null +++ b/test/typeparam/issue53419.go @@ -0,0 +1,28 @@ +// run -gcflags=-G=3 + +// Copyright 2022 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. + +package main + +type T1 struct{} +type T2 struct{} +type Both struct { + T1 + T2 +} + +func (T1) m() { panic("FAIL") } +func (T2) m() { panic("FAIL") } +func (Both) m() {} + +func f[T interface{ m() }](c T) { + c.m() +} + +func main() { + var b Both + b.m() + f(b) +} diff --git a/test/typeparam/issue53477.go b/test/typeparam/issue53477.go new file mode 100644 index 0000000000000000000000000000000000000000..314171a7586847740f4308e6b48d51c3eddd7bee --- /dev/null +++ b/test/typeparam/issue53477.go @@ -0,0 +1,34 @@ +// run -gcflags=-G=3 + +// Copyright 2022 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. + +// Test that generic interface-interface comparisons resulting from +// value switch statements are handled correctly. + +package main + +func main() { + f[X](0) +} + +type Mer[T any] interface{ M(T) } +type MNer[T any] interface { + Mer[T] + N() +} + +type X int + +func (X) M(X) {} +func (X) N() {} + +func f[T MNer[T]](t T) { + switch Mer[T](t) { + case MNer[T](t): + // ok + default: + panic("FAIL") + } +} diff --git a/test/typeparam/issue54911.go b/test/typeparam/issue54911.go new file mode 100644 index 0000000000000000000000000000000000000000..0df2b99563e3d71bf3e8ef91906fb6b5afc5d891 --- /dev/null +++ b/test/typeparam/issue54911.go @@ -0,0 +1,21 @@ +// compile -G=3 + +// Copyright 2022 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. + +package main + +type Set[T comparable] map[T]struct{} + +func (s Set[T]) Add() Set[T] { + return s +} + +func (s Set[T]) Copy() Set[T] { + return Set[T].Add(s) +} + +func main() { + _ = Set[int]{42: {}} +}