diff options
author | Thomas Koenig <tkoenig@gcc.gnu.org> | 2020-10-28 18:41:24 +0100 |
---|---|---|
committer | Thomas Koenig <tkoenig@gcc.gnu.org> | 2020-10-28 18:41:24 +0100 |
commit | bf6dad60c338a42a7fb85f7b2a5870c0fb2e20f8 (patch) | |
tree | e513781ef717465e7db0358e987a5a6cbef5665c /libgo | |
parent | 0c261d5b5c931d9e9214d06531bdc7e9e16aeaab (diff) | |
parent | 47d13acbda9a5d8eb57ff169ba74857cd54108e4 (diff) | |
download | gcc-bf6dad60c338a42a7fb85f7b2a5870c0fb2e20f8.zip gcc-bf6dad60c338a42a7fb85f7b2a5870c0fb2e20f8.tar.gz gcc-bf6dad60c338a42a7fb85f7b2a5870c0fb2e20f8.tar.bz2 |
Merge branch 'master' into devel/coarray_native.
Merge into devel/coarray_native to prepare for later merging of
coarray_native with master.
Diffstat (limited to 'libgo')
103 files changed, 1440 insertions, 253 deletions
diff --git a/libgo/MERGE b/libgo/MERGE index a84f1e3..cfbf488 100644 --- a/libgo/MERGE +++ b/libgo/MERGE @@ -1,4 +1,4 @@ -c4f8cb43caf0bcd0c730d7d04a3fce129393cecc +9706f510a5e2754595d716bd64be8375997311fb The first line of this file holds the git revision number of the last merge done from the master library sources. diff --git a/libgo/Makefile.am b/libgo/Makefile.am index 9ce0cab..26e8385 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -620,7 +620,7 @@ s-zstdpkglist: Makefile echo 'package goroot' > zstdpkglist.go.tmp echo "" >> zstdpkglist.go.tmp echo 'var stdpkg = map[string]bool{' >> zstdpkglist.go.tmp - echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's|[a-z0-9_./]*_c\.lo||g' | sed 's|\([a-z0-9_./]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp + echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's|[a-z0-9_./]*_c\.lo||g' | sed 's|golang\.org/[a-z0-9_./]*\.lo||g' | sed 's|\([a-z0-9_./]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp echo '}' >> zstdpkglist.go.tmp $(SHELL) $(srcdir)/mvifdiff.sh zstdpkglist.go.tmp zstdpkglist.go $(STAMP) $@ @@ -973,6 +973,12 @@ endif # Also use -fno-inline to get better results from the memory profiler. runtime_pprof_check_GOCFLAGS = -static-libgo -fno-inline +if LIBGO_IS_AIX +# reflect tests must be done with -static-libgo. Otherwize, +# there will be a duplication of the canonicalization map. +reflect_check_GOCFLAGS = -static-libgo -Wl,-bbigtoc +endif + if HAVE_STATIC_LINK # Use -static for the syscall tests if possible, because otherwise when # running as root the re-execs ignore LD_LIBRARY_PATH. @@ -1090,7 +1096,7 @@ if LIBGO_IS_BSD $(eval $(call PACKAGE_template,golang.org/x/net/route)) golangorg_x_net_route_lo = \ - golang.org/net/route.lo + golang.org/x/net/route.lo endif diff --git a/libgo/Makefile.in b/libgo/Makefile.in index b577083..d300ab6 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -1114,6 +1114,10 @@ runtime_internal_sys_lo_check_GOCFLAGS = -fgo-compiling-runtime # Also use -fno-inline to get better results from the memory profiler. runtime_pprof_check_GOCFLAGS = -static-libgo -fno-inline +# reflect tests must be done with -static-libgo. Otherwize, +# there will be a duplication of the canonicalization map. +@LIBGO_IS_AIX_TRUE@reflect_check_GOCFLAGS = -static-libgo -Wl,-bbigtoc + # Use -static for the syscall tests if possible, because otherwise when # running as root the re-execs ignore LD_LIBRARY_PATH. @HAVE_STATIC_LINK_TRUE@syscall_check_GOCFLAGS = -static @@ -1149,7 +1153,7 @@ extra_check_libs_cmd_vet_internal_cfg = $(abs_builddir)/libgotool.a @HAVE_STAT_TIMESPEC_TRUE@@LIBGO_IS_SOLARIS_TRUE@matchargs_os = --tag=solaristag @LIBGO_IS_SOLARIS_FALSE@matchargs_os = @LIBGO_IS_BSD_TRUE@golangorg_x_net_route_lo = \ -@LIBGO_IS_BSD_TRUE@ golang.org/net/route.lo +@LIBGO_IS_BSD_TRUE@ golang.org/x/net/route.lo @LIBGO_IS_SOLARIS_TRUE@golangorg_x_net_lif_lo = \ @LIBGO_IS_SOLARIS_TRUE@ golang.org/x/net/lif.lo @@ -2784,7 +2788,7 @@ s-zstdpkglist: Makefile echo 'package goroot' > zstdpkglist.go.tmp echo "" >> zstdpkglist.go.tmp echo 'var stdpkg = map[string]bool{' >> zstdpkglist.go.tmp - echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's|[a-z0-9_./]*_c\.lo||g' | sed 's|\([a-z0-9_./]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp + echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's|[a-z0-9_./]*_c\.lo||g' | sed 's|golang\.org/[a-z0-9_./]*\.lo||g' | sed 's|\([a-z0-9_./]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp echo '}' >> zstdpkglist.go.tmp $(SHELL) $(srcdir)/mvifdiff.sh zstdpkglist.go.tmp zstdpkglist.go $(STAMP) $@ diff --git a/libgo/VERSION b/libgo/VERSION index 2d962d8..c19def3 100644 --- a/libgo/VERSION +++ b/libgo/VERSION @@ -1 +1 @@ -go1.15rc2 +go1.15.2 diff --git a/libgo/config.h.in b/libgo/config.h.in index bbb2516..532640b 100644 --- a/libgo/config.h.in +++ b/libgo/config.h.in @@ -174,6 +174,9 @@ /* Define to 1 if you have the <netpacket/packet.h> header file. */ #undef HAVE_NETPACKET_PACKET_H +/* Define to 1 if you have the <net/bpf.h> header file. */ +#undef HAVE_NET_BPF_H + /* Define to 1 if you have the <net/if_arp.h> header file. */ #undef HAVE_NET_IF_ARP_H @@ -294,6 +297,9 @@ /* Define to 1 if you have the <sys/syscall.h> header file. */ #undef HAVE_SYS_SYSCALL_H +/* Define to 1 if you have the <sys/sysctl.h> header file. */ +#undef HAVE_SYS_SYSCTL_H + /* Define to 1 if you have the <sys/sysinfo.h> header file. */ #undef HAVE_SYS_SYSINFO_H diff --git a/libgo/configure b/libgo/configure index 7be9571..81331dd 100755 --- a/libgo/configure +++ b/libgo/configure @@ -4711,10 +4711,6 @@ fi case ${host} in *-*-aix*) - # static hash tables crashes on AIX when libgo is built with O2 - CFLAGS="$CFLAGS -fno-section-anchors" - GOCFLAGS="$GOCFLAGS -fno-section-anchors" - # Check default architecture for FAT library creation if test -z "`$CC -x c -E /dev/null -g3 -o - | grep 64BIT`" ; then AIX_EXTRA_ARCH='64' @@ -11501,7 +11497,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11504 "configure" +#line 11500 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11607,7 +11603,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11610 "configure" +#line 11606 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -14226,8 +14222,21 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ;; - riscv64-*-*) - GOARCH=riscv64 + riscv*-*-*) + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if __riscv_xlen == 64 +#error 64-bit +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + GOARCH=riscv +else + GOARCH=riscv64 +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ;; s390*-*-*) cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -15193,7 +15202,7 @@ $as_echo "#define HAVE_GETIPINFO 1" >>confdefs.h fi -for ac_header in port.h sched.h semaphore.h sys/file.h sys/mman.h syscall.h sys/epoll.h sys/event.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/ptrace.h linux/reboot.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h +for ac_header in port.h sched.h semaphore.h sys/file.h sys/mman.h syscall.h sys/epoll.h sys/event.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/sysctl.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/bpf.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/ptrace.h linux/reboot.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" diff --git a/libgo/configure.ac b/libgo/configure.ac index abc58b8..f87ab65 100644 --- a/libgo/configure.ac +++ b/libgo/configure.ac @@ -33,10 +33,6 @@ AC_SUBST(CFLAGS) case ${host} in *-*-aix*) - # static hash tables crashes on AIX when libgo is built with O2 - CFLAGS="$CFLAGS -fno-section-anchors" - GOCFLAGS="$GOCFLAGS -fno-section-anchors" - # Check default architecture for FAT library creation if test -z "`$CC -x c -E /dev/null -g3 -o - | grep 64BIT`" ; then AIX_EXTRA_ARCH='64' @@ -342,8 +338,14 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([ [GOARCH=ppc64le], [GOARCH=ppc64])]) ;; - riscv64-*-*) - GOARCH=riscv64 + riscv*-*-*) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([ +#if __riscv_xlen == 64 +#error 64-bit +#endif +])], +[GOARCH=riscv], +[GOARCH=riscv64]) ;; s390*-*-*) AC_COMPILE_IFELSE([AC_LANG_SOURCE([ @@ -578,7 +580,7 @@ AC_C_BIGENDIAN GCC_CHECK_UNWIND_GETIPINFO -AC_CHECK_HEADERS(port.h sched.h semaphore.h sys/file.h sys/mman.h syscall.h sys/epoll.h sys/event.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/ptrace.h linux/reboot.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h) +AC_CHECK_HEADERS(port.h sched.h semaphore.h sys/file.h sys/mman.h syscall.h sys/epoll.h sys/event.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/sysctl.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/bpf.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/ptrace.h linux/reboot.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h) AC_CHECK_HEADERS([netinet/icmp6.h], [], [], [#include <netinet/in.h> diff --git a/libgo/go/cmd/cgo/main.go b/libgo/go/cmd/cgo/main.go index 80f3568..6de6d69 100644 --- a/libgo/go/cmd/cgo/main.go +++ b/libgo/go/cmd/cgo/main.go @@ -184,6 +184,7 @@ var ptrSizeMap = map[string]int64{ "ppc": 4, "ppc64": 8, "ppc64le": 8, + "riscv": 4, "riscv64": 8, "s390": 4, "s390x": 8, @@ -210,6 +211,7 @@ var intSizeMap = map[string]int64{ "ppc": 4, "ppc64": 8, "ppc64le": 8, + "riscv": 4, "riscv64": 8, "s390": 4, "s390x": 8, diff --git a/libgo/go/cmd/go/internal/test/test.go b/libgo/go/cmd/go/internal/test/test.go index 873a76a..77bfc11 100644 --- a/libgo/go/cmd/go/internal/test/test.go +++ b/libgo/go/cmd/go/internal/test/test.go @@ -1079,9 +1079,13 @@ func (c *runCache) builderRunTest(b *work.Builder, a *work.Action) error { } var stdout io.Writer = os.Stdout + var err error if testJSON { json := test2json.NewConverter(lockedStdout{}, a.Package.ImportPath, test2json.Timestamp) - defer json.Close() + defer func() { + json.Exited(err) + json.Close() + }() stdout = json } @@ -1185,7 +1189,7 @@ func (c *runCache) builderRunTest(b *work.Builder, a *work.Action) error { } t0 := time.Now() - err := cmd.Start() + err = cmd.Start() // This is a last-ditch deadline to detect and // stop wedged test binaries, to keep the builders diff --git a/libgo/go/cmd/go/internal/test/testflag.go b/libgo/go/cmd/go/internal/test/testflag.go index 1ff34f7..4f0a892 100644 --- a/libgo/go/cmd/go/internal/test/testflag.go +++ b/libgo/go/cmd/go/internal/test/testflag.go @@ -214,9 +214,13 @@ func testFlags(args []string) (packageNames, passToTest []string) { explicitArgs := make([]string, 0, len(args)) inPkgList := false + afterFlagWithoutValue := false for len(args) > 0 { f, remainingArgs, err := cmdflag.ParseOne(&CmdTest.Flag, args) + wasAfterFlagWithoutValue := afterFlagWithoutValue + afterFlagWithoutValue = false // provisionally + if errors.Is(err, flag.ErrHelp) { exitWithUsage() } @@ -233,10 +237,24 @@ func testFlags(args []string) (packageNames, passToTest []string) { if nf := (cmdflag.NonFlagError{}); errors.As(err, &nf) { if !inPkgList && packageNames != nil { // We already saw the package list previously, and this argument is not - // a flag, so it — and everything after it — must be a literal argument - // to the test binary. - explicitArgs = append(explicitArgs, args...) - break + // a flag, so it — and everything after it — must be either a value for + // a preceding flag or a literal argument to the test binary. + if wasAfterFlagWithoutValue { + // This argument could syntactically be a flag value, so + // optimistically assume that it is and keep looking for go command + // flags after it. + // + // (If we're wrong, we'll at least be consistent with historical + // behavior; see https://golang.org/issue/40763.) + explicitArgs = append(explicitArgs, nf.RawArg) + args = remainingArgs + continue + } else { + // This argument syntactically cannot be a flag value, so it must be a + // positional argument, and so must everything after it. + explicitArgs = append(explicitArgs, args...) + break + } } inPkgList = true @@ -272,6 +290,9 @@ func testFlags(args []string) (packageNames, passToTest []string) { explicitArgs = append(explicitArgs, nd.RawArg) args = remainingArgs + if !nd.HasValue { + afterFlagWithoutValue = true + } continue } diff --git a/libgo/go/cmd/go/testdata/script/link_syso_issue33139.txt b/libgo/go/cmd/go/testdata/script/link_syso_issue33139.txt index 46b0ef4..3030ee9 100644 --- a/libgo/go/cmd/go/testdata/script/link_syso_issue33139.txt +++ b/libgo/go/cmd/go/testdata/script/link_syso_issue33139.txt @@ -8,8 +8,9 @@ # See: https://github.com/golang/go/issues/8912 [linux] [ppc64] skip -# External linking is not supported on linux/riscv64. +# External linking is not supported on linux/riscv, linux/riscv64. # See: https://github.com/golang/go/issues/36739 +[linux] [riscv] skip [linux] [riscv64] skip cc -c -o syso/objTestImpl.syso syso/src/objTestImpl.c diff --git a/libgo/go/cmd/go/testdata/script/test_flags.txt b/libgo/go/cmd/go/testdata/script/test_flags.txt new file mode 100644 index 0000000..63385e6 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_flags.txt @@ -0,0 +1,132 @@ +env GO111MODULE=on + +[short] skip + +# Arguments after the flag terminator should be ignored. +# If we pass '-- -test.v', we should not get verbose output +# *and* output from the test should not be echoed. +go test ./x -- -test.v +stdout '\Aok\s+example.com/x\s+[0-9.s]+\n\z' +! stderr . + +# For backward-compatibility with previous releases of the 'go' command, +# arguments that appear after unrecognized flags should not be treated +# as packages, even if they are unambiguously not arguments to flags. +# Even though ./x looks like a package path, the real package should be +# the implicit '.'. +! go test --answer=42 ./x +stderr '^no Go files in .+$' +! stderr '/x' + +# However, *flags* that appear after unrecognized flags should still be +# interpreted as flags, under the (possibly-erroneous) assumption that +# unrecognized flags are non-boolean. + +go test -v -x ./x -timeout 24h -boolflag=true foo -timeout 25h +stdout 'args: foo -timeout 25h' +stdout 'timeout: 24h0m0s$' # -timeout is unambiguously not a flag, so the real flag wins. + +go test -v -x ./x -timeout 24h -boolflag foo -timeout 25h +stdout 'args: foo -test\.timeout=25h0m0s' # For legacy reasons, '-timeout ' is erroneously rewritten to -test.timeout; see https://golang.org/issue/40763. +stdout 'timeout: 24h0m0s$' # Actual flag wins. + +go test -v -x ./x -timeout 24h -stringflag foo -timeout 25h +stdout 'args: $' +stdout 'timeout: 25h0m0s$' # Later flag wins. + +# An explicit '-outputdir=' argument should set test.outputdir +# to the 'go' command's working directory, not zero it out +# for the test binary. +go test -x -coverprofile=cover.out '-outputdir=' ./x +stderr '-test.outputdir=[^ ]' +exists ./cover.out +! exists ./x/cover.out + +# Test flags from GOFLAGS should be forwarded to the test binary, +# with the 'test.' prefix in the GOFLAGS entry... +env GOFLAGS='-test.timeout=24h0m0s -count=1' +go test -v -x ./x +stdout 'timeout: 24h0m0s$' +stderr '-test.count=1' + +# ...or without. +env GOFLAGS='-timeout=24h0m0s -count=1' +go test -v -x ./x +stdout 'timeout: 24h0m0s$' +stderr '-test.count=1' + +# Arguments from the command line should override GOFLAGS... +go test -v -x -timeout=25h0m0s ./x +stdout 'timeout: 25h0m0s$' +stderr '-test.count=1' + +# ...even if they use a different flag name. +go test -v -x -test.timeout=26h0m0s ./x +stdout 'timeout: 26h0m0s$' +stderr '-test\.timeout=26h0m0s' +! stderr 'timeout=24h0m0s' +stderr '-test.count=1' + +# Invalid flags should be reported exactly once. +! go test -covermode=walrus ./x +stderr -count=1 'invalid value "walrus" for flag -covermode: valid modes are .*$' +stderr '^usage: go test .*$' +stderr '^Run ''go help test'' and ''go help testflag'' for details.$' + +# Passing -help to the test binary should show flag help. +go test ./x -args -help +stdout 'usage_message' + +# -covermode, -coverpkg, and -coverprofile should imply -cover +go test -covermode=set ./x +stdout '\s+coverage:\s+' + +go test -coverpkg=encoding/binary ./x +stdout '\s+coverage:\s+' + +go test -coverprofile=cover.out ./x +stdout '\s+coverage:\s+' +exists ./cover.out +rm ./cover.out + +# -*profile and -trace flags should force output to the current working directory +# or -outputdir, not the directory containing the test. + +go test -memprofile=mem.out ./x +exists ./mem.out +rm ./mem.out + +go test -trace=trace.out ./x +exists ./trace.out +rm ./trace.out + +# Relative paths with -outputdir should be relative to the go command's working +# directory, not the directory containing the test. +mkdir profiles +go test -memprofile=mem.out -outputdir=./profiles ./x +exists ./profiles/mem.out +rm profiles + +-- go.mod -- +module example.com +go 1.14 +-- x/x_test.go -- +package x + +import ( + "flag" + "strings" + "testing" +) + +var _ = flag.String("usage_message", "", "dummy flag to check usage message") +var boolflag = flag.Bool("boolflag", false, "ignored boolean flag") +var stringflag = flag.String("stringflag", "", "ignored string flag") + +func TestLogTimeout(t *testing.T) { + t.Logf("timeout: %v", flag.Lookup("test.timeout").Value) +} + +func TestLogArgs(t *testing.T) { + t.Logf("args: %s", strings.Join(flag.Args(), " ")) +} diff --git a/libgo/go/cmd/internal/sys/arch.go b/libgo/go/cmd/internal/sys/arch.go index e868736..60a3b3c 100644 --- a/libgo/go/cmd/internal/sys/arch.go +++ b/libgo/go/cmd/internal/sys/arch.go @@ -19,6 +19,7 @@ const ( MIPS MIPS64 PPC64 + RISCV RISCV64 S390X Wasm @@ -143,6 +144,15 @@ var ArchPPC64LE = &Arch{ MinLC: 4, } +var ArchRISCV = &Arch{ + Name: "riscv", + Family: RISCV, + ByteOrder: binary.LittleEndian, + PtrSize: 4, + RegSize: 4, + MinLC: 4, +} + var ArchRISCV64 = &Arch{ Name: "riscv64", Family: RISCV64, @@ -181,6 +191,7 @@ var Archs = [...]*Arch{ ArchMIPS64LE, ArchPPC64, ArchPPC64LE, + ArchRISCV, ArchRISCV64, ArchS390X, ArchWasm, diff --git a/libgo/go/cmd/internal/test2json/test2json.go b/libgo/go/cmd/internal/test2json/test2json.go index f805213..4eb6dd4 100644 --- a/libgo/go/cmd/internal/test2json/test2json.go +++ b/libgo/go/cmd/internal/test2json/test2json.go @@ -45,10 +45,10 @@ type textBytes []byte func (b textBytes) MarshalText() ([]byte, error) { return b, nil } -// A converter holds the state of a test-to-JSON conversion. +// A Converter holds the state of a test-to-JSON conversion. // It implements io.WriteCloser; the caller writes test output in, // and the converter writes JSON output to w. -type converter struct { +type Converter struct { w io.Writer // JSON output stream pkg string // package to name in events mode Mode // mode bits @@ -100,9 +100,9 @@ var ( // // The pkg string, if present, specifies the import path to // report in the JSON stream. -func NewConverter(w io.Writer, pkg string, mode Mode) io.WriteCloser { - c := new(converter) - *c = converter{ +func NewConverter(w io.Writer, pkg string, mode Mode) *Converter { + c := new(Converter) + *c = Converter{ w: w, pkg: pkg, mode: mode, @@ -122,15 +122,31 @@ func NewConverter(w io.Writer, pkg string, mode Mode) io.WriteCloser { } // Write writes the test input to the converter. -func (c *converter) Write(b []byte) (int, error) { +func (c *Converter) Write(b []byte) (int, error) { c.input.write(b) return len(b), nil } +// Exited marks the test process as having exited with the given error. +func (c *Converter) Exited(err error) { + if err == nil { + c.result = "pass" + } else { + c.result = "fail" + } +} + var ( + // printed by test on successful run. bigPass = []byte("PASS\n") + + // printed by test after a normal test failure. bigFail = []byte("FAIL\n") + // printed by 'go test' along with an error if the test binary terminates + // with an error. + bigFailErrorPrefix = []byte("FAIL\t") + updates = [][]byte{ []byte("=== RUN "), []byte("=== PAUSE "), @@ -153,9 +169,9 @@ var ( // handleInputLine handles a single whole test output line. // It must write the line to c.output but may choose to do so // before or after emitting other events. -func (c *converter) handleInputLine(line []byte) { +func (c *Converter) handleInputLine(line []byte) { // Final PASS or FAIL. - if bytes.Equal(line, bigPass) || bytes.Equal(line, bigFail) { + if bytes.Equal(line, bigPass) || bytes.Equal(line, bigFail) || bytes.HasPrefix(line, bigFailErrorPrefix) { c.flushReport(0) c.output.write(line) if bytes.Equal(line, bigPass) { @@ -204,8 +220,18 @@ func (c *converter) handleInputLine(line []byte) { } } + // Not a special test output line. if !ok { - // Not a special test output line. + // Lookup the name of the test which produced the output using the + // indentation of the output as an index into the stack of the current + // subtests. + // If the indentation is greater than the number of current subtests + // then the output must have included extra indentation. We can't + // determine which subtest produced this output, so we default to the + // old behaviour of assuming the most recently run subtest produced it. + if indent > 0 && indent <= len(c.report) { + c.testName = c.report[indent-1].Test + } c.output.write(origLine) return } @@ -269,7 +295,7 @@ func (c *converter) handleInputLine(line []byte) { } // flushReport flushes all pending PASS/FAIL reports at levels >= depth. -func (c *converter) flushReport(depth int) { +func (c *Converter) flushReport(depth int) { c.testName = "" for len(c.report) > depth { e := c.report[len(c.report)-1] @@ -281,23 +307,22 @@ func (c *converter) flushReport(depth int) { // Close marks the end of the go test output. // It flushes any pending input and then output (only partial lines at this point) // and then emits the final overall package-level pass/fail event. -func (c *converter) Close() error { +func (c *Converter) Close() error { c.input.flush() c.output.flush() - e := &event{Action: "fail"} if c.result != "" { - e.Action = c.result - } - if c.mode&Timestamp != 0 { - dt := time.Since(c.start).Round(1 * time.Millisecond).Seconds() - e.Elapsed = &dt + e := &event{Action: c.result} + if c.mode&Timestamp != 0 { + dt := time.Since(c.start).Round(1 * time.Millisecond).Seconds() + e.Elapsed = &dt + } + c.writeEvent(e) } - c.writeEvent(e) return nil } // writeOutputEvent writes a single output event with the given bytes. -func (c *converter) writeOutputEvent(out []byte) { +func (c *Converter) writeOutputEvent(out []byte) { c.writeEvent(&event{ Action: "output", Output: (*textBytes)(&out), @@ -306,7 +331,7 @@ func (c *converter) writeOutputEvent(out []byte) { // writeEvent writes a single event. // It adds the package, time (if requested), and test name (if needed). -func (c *converter) writeEvent(e *event) { +func (c *Converter) writeEvent(e *event) { e.Package = c.pkg if c.mode&Timestamp != 0 { t := time.Now() diff --git a/libgo/go/cmd/internal/test2json/testdata/benchshort.json b/libgo/go/cmd/internal/test2json/testdata/benchshort.json index 8c61d95..34b03b9 100644 --- a/libgo/go/cmd/internal/test2json/testdata/benchshort.json +++ b/libgo/go/cmd/internal/test2json/testdata/benchshort.json @@ -4,4 +4,3 @@ {"Action":"output","Output":"# but to avoid questions of timing, we just use a file with no \\n at all.\n"} {"Action":"output","Output":"BenchmarkFoo \t"} {"Action":"output","Output":"10000 early EOF"} -{"Action":"fail"} diff --git a/libgo/go/cmd/internal/test2json/testdata/empty.json b/libgo/go/cmd/internal/test2json/testdata/empty.json new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/empty.json diff --git a/libgo/go/cmd/internal/test2json/testdata/empty.test b/libgo/go/cmd/internal/test2json/testdata/empty.test new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/empty.test diff --git a/libgo/go/cmd/internal/test2json/testdata/issue29755.json b/libgo/go/cmd/internal/test2json/testdata/issue29755.json new file mode 100644 index 0000000..2e8ba48 --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/issue29755.json @@ -0,0 +1,38 @@ +{"Action":"run","Test":"TestOutputWithSubtest"} +{"Action":"output","Test":"TestOutputWithSubtest","Output":"=== RUN TestOutputWithSubtest\n"} +{"Action":"run","Test":"TestOutputWithSubtest/sub_test"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test","Output":"=== RUN TestOutputWithSubtest/sub_test\n"} +{"Action":"run","Test":"TestOutputWithSubtest/sub_test/sub2"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test/sub2","Output":"=== RUN TestOutputWithSubtest/sub_test/sub2\n"} +{"Action":"run","Test":"TestOutputWithSubtest/sub_test2"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test2","Output":"=== RUN TestOutputWithSubtest/sub_test2\n"} +{"Action":"run","Test":"TestOutputWithSubtest/sub_test2/sub2"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test2/sub2","Output":"=== RUN TestOutputWithSubtest/sub_test2/sub2\n"} +{"Action":"output","Test":"TestOutputWithSubtest","Output":"--- FAIL: TestOutputWithSubtest (0.00s)\n"} +{"Action":"output","Test":"TestOutputWithSubtest","Output":" foo_test.go:6: output before sub tests\n"} +{"Action":"output","Test":"TestOutputWithSubtest","Output":" foo_test.go:10: output from root test\n"} +{"Action":"output","Test":"TestOutputWithSubtest","Output":" foo_test.go:15: output from root test\n"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test","Output":" --- PASS: TestOutputWithSubtest/sub_test (0.00s)\n"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test","Output":" foo_test.go:9: output from sub test\n"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test","Output":" foo_test.go:11: more output from sub test\n"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test","Output":" foo_test.go:16: more output from sub test\n"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test/sub2","Output":" --- PASS: TestOutputWithSubtest/sub_test/sub2 (0.00s)\n"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test/sub2","Output":" foo_test.go:14: output from sub2 test\n"} +{"Action":"output","Test":"TestOutputWithSubtest","Output":" foo_test.go:22: output from root test\n"} +{"Action":"output","Test":"TestOutputWithSubtest","Output":" foo_test.go:27: output from root test\n"} +{"Action":"pass","Test":"TestOutputWithSubtest/sub_test/sub2"} +{"Action":"pass","Test":"TestOutputWithSubtest/sub_test"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test2","Output":" --- PASS: TestOutputWithSubtest/sub_test2 (0.00s)\n"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test2","Output":" foo_test.go:21: output from sub test2\n"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test2","Output":" foo_test.go:23: more output from sub test2\n"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test2","Output":" foo_test.go:28: more output from sub test2\n"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test2/sub2","Output":" --- PASS: TestOutputWithSubtest/sub_test2/sub2 (0.00s)\n"} +{"Action":"output","Test":"TestOutputWithSubtest/sub_test2/sub2","Output":" foo_test.go:26: output from sub2 test\n"} +{"Action":"output","Test":"TestOutputWithSubtest","Output":" foo_test.go:32: output after sub test\n"} +{"Action":"pass","Test":"TestOutputWithSubtest/sub_test2/sub2"} +{"Action":"pass","Test":"TestOutputWithSubtest/sub_test2"} +{"Action":"fail","Test":"TestOutputWithSubtest"} +{"Action":"output","Output":"FAIL\n"} +{"Action":"output","Output":"FAIL\tgotest.tools/gotestsum/foo\t0.001s\n"} +{"Action":"output","Output":"FAIL\n"} +{"Action":"fail"} diff --git a/libgo/go/cmd/internal/test2json/testdata/issue29755.test b/libgo/go/cmd/internal/test2json/testdata/issue29755.test new file mode 100644 index 0000000..b0c596c --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/issue29755.test @@ -0,0 +1,27 @@ +=== RUN TestOutputWithSubtest +=== RUN TestOutputWithSubtest/sub_test +=== RUN TestOutputWithSubtest/sub_test/sub2 +=== RUN TestOutputWithSubtest/sub_test2 +=== RUN TestOutputWithSubtest/sub_test2/sub2 +--- FAIL: TestOutputWithSubtest (0.00s) + foo_test.go:6: output before sub tests + foo_test.go:10: output from root test + foo_test.go:15: output from root test + --- PASS: TestOutputWithSubtest/sub_test (0.00s) + foo_test.go:9: output from sub test + foo_test.go:11: more output from sub test + foo_test.go:16: more output from sub test + --- PASS: TestOutputWithSubtest/sub_test/sub2 (0.00s) + foo_test.go:14: output from sub2 test + foo_test.go:22: output from root test + foo_test.go:27: output from root test + --- PASS: TestOutputWithSubtest/sub_test2 (0.00s) + foo_test.go:21: output from sub test2 + foo_test.go:23: more output from sub test2 + foo_test.go:28: more output from sub test2 + --- PASS: TestOutputWithSubtest/sub_test2/sub2 (0.00s) + foo_test.go:26: output from sub2 test + foo_test.go:32: output after sub test +FAIL +FAIL gotest.tools/gotestsum/foo 0.001s +FAIL diff --git a/libgo/go/cmd/internal/test2json/testdata/panic.json b/libgo/go/cmd/internal/test2json/testdata/panic.json new file mode 100644 index 0000000..f773814 --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/panic.json @@ -0,0 +1,19 @@ +{"Action":"output","Test":"TestPanic","Output":"--- FAIL: TestPanic (0.00s)\n"} +{"Action":"output","Test":"TestPanic","Output":"panic: oops [recovered]\n"} +{"Action":"output","Test":"TestPanic","Output":"\tpanic: oops\n"} +{"Action":"output","Test":"TestPanic","Output":"\n"} +{"Action":"output","Test":"TestPanic","Output":"goroutine 7 [running]:\n"} +{"Action":"output","Test":"TestPanic","Output":"testing.tRunner.func1(0xc000092100)\n"} +{"Action":"output","Test":"TestPanic","Output":"\t/go/src/testing/testing.go:874 +0x3a3\n"} +{"Action":"output","Test":"TestPanic","Output":"panic(0x1110ea0, 0x116aea0)\n"} +{"Action":"output","Test":"TestPanic","Output":"\t/go/src/runtime/panic.go:679 +0x1b2\n"} +{"Action":"output","Test":"TestPanic","Output":"command-line-arguments.TestPanic(0xc000092100)\n"} +{"Action":"output","Test":"TestPanic","Output":"\ta_test.go:6 +0x39\n"} +{"Action":"output","Test":"TestPanic","Output":"testing.tRunner(0xc000092100, 0x114f500)\n"} +{"Action":"output","Test":"TestPanic","Output":"\tgo/src/testing/testing.go:909 +0xc9\n"} +{"Action":"output","Test":"TestPanic","Output":"created by testing.(*T).Run\n"} +{"Action":"output","Test":"TestPanic","Output":"\tgo/src/testing/testing.go:960 +0x350\n"} +{"Action":"fail","Test":"TestPanic"} +{"Action":"output","Output":"FAIL\tcommand-line-arguments\t0.042s\n"} +{"Action":"output","Output":"FAIL\n"} +{"Action":"fail"} diff --git a/libgo/go/cmd/internal/test2json/testdata/panic.test b/libgo/go/cmd/internal/test2json/testdata/panic.test new file mode 100644 index 0000000..517ebaf --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/panic.test @@ -0,0 +1,17 @@ +--- FAIL: TestPanic (0.00s) +panic: oops [recovered] + panic: oops + +goroutine 7 [running]: +testing.tRunner.func1(0xc000092100) + /go/src/testing/testing.go:874 +0x3a3 +panic(0x1110ea0, 0x116aea0) + /go/src/runtime/panic.go:679 +0x1b2 +command-line-arguments.TestPanic(0xc000092100) + a_test.go:6 +0x39 +testing.tRunner(0xc000092100, 0x114f500) + go/src/testing/testing.go:909 +0xc9 +created by testing.(*T).Run + go/src/testing/testing.go:960 +0x350 +FAIL command-line-arguments 0.042s +FAIL diff --git a/libgo/go/cmd/internal/test2json/testdata/smiley.json b/libgo/go/cmd/internal/test2json/testdata/smiley.json index afa990d..f49180d 100644 --- a/libgo/go/cmd/internal/test2json/testdata/smiley.json +++ b/libgo/go/cmd/internal/test2json/testdata/smiley.json @@ -116,13 +116,13 @@ {"Action":"output","Test":"Test☺☹/2","Output":"=== CONT Test☺☹/2\n"} {"Action":"output","Test":"TestTags","Output":"--- PASS: TestTags (0.00s)\n"} {"Action":"output","Test":"TestTags/x_testtag_y","Output":" --- PASS: TestTags/x_testtag_y (0.04s)\n"} -{"Action":"output","Test":"TestTags/x_testtag_y","Output":" \tvet_test.go:187: -tags=x testtag y\n"} +{"Action":"output","Test":"TestTags/x_testtag_y","Output":" vet_test.go:187: -tags=x testtag y\n"} {"Action":"pass","Test":"TestTags/x_testtag_y"} {"Action":"output","Test":"TestTags/x,testtag,y","Output":" --- PASS: TestTags/x,testtag,y (0.04s)\n"} -{"Action":"output","Test":"TestTags/x,testtag,y","Output":" \tvet_test.go:187: -tags=x,testtag,y\n"} +{"Action":"output","Test":"TestTags/x,testtag,y","Output":" vet_test.go:187: -tags=x,testtag,y\n"} {"Action":"pass","Test":"TestTags/x,testtag,y"} {"Action":"output","Test":"TestTags/testtag","Output":" --- PASS: TestTags/testtag (0.04s)\n"} -{"Action":"output","Test":"TestTags/testtag","Output":" \tvet_test.go:187: -tags=testtag\n"} +{"Action":"output","Test":"TestTags/testtag","Output":" vet_test.go:187: -tags=testtag\n"} {"Action":"pass","Test":"TestTags/testtag"} {"Action":"pass","Test":"TestTags"} {"Action":"cont","Test":"Test☺☹/1"} @@ -139,28 +139,28 @@ {"Action":"output","Test":"Test☺☹Dirs/cgo","Output":"=== CONT Test☺☹Dirs/cgo\n"} {"Action":"output","Test":"Test☺☹","Output":"--- PASS: Test☺☹ (0.39s)\n"} {"Action":"output","Test":"Test☺☹/5","Output":" --- PASS: Test☺☹/5 (0.07s)\n"} -{"Action":"output","Test":"Test☺☹/5","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/copylock_func.go\" \"testdata/rangeloop.go\"]\n"} +{"Action":"output","Test":"Test☺☹/5","Output":" vet_test.go:114: φιλεσ: [\"testdata/copylock_func.go\" \"testdata/rangeloop.go\"]\n"} {"Action":"pass","Test":"Test☺☹/5"} {"Action":"output","Test":"Test☺☹/3","Output":" --- PASS: Test☺☹/3 (0.07s)\n"} -{"Action":"output","Test":"Test☺☹/3","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/composite.go\" \"testdata/nilfunc.go\"]\n"} +{"Action":"output","Test":"Test☺☹/3","Output":" vet_test.go:114: φιλεσ: [\"testdata/composite.go\" \"testdata/nilfunc.go\"]\n"} {"Action":"pass","Test":"Test☺☹/3"} {"Action":"output","Test":"Test☺☹/6","Output":" --- PASS: Test☺☹/6 (0.07s)\n"} -{"Action":"output","Test":"Test☺☹/6","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/copylock_range.go\" \"testdata/shadow.go\"]\n"} +{"Action":"output","Test":"Test☺☹/6","Output":" vet_test.go:114: φιλεσ: [\"testdata/copylock_range.go\" \"testdata/shadow.go\"]\n"} {"Action":"pass","Test":"Test☺☹/6"} {"Action":"output","Test":"Test☺☹/2","Output":" --- PASS: Test☺☹/2 (0.07s)\n"} -{"Action":"output","Test":"Test☺☹/2","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/bool.go\" \"testdata/method.go\" \"testdata/unused.go\"]\n"} +{"Action":"output","Test":"Test☺☹/2","Output":" vet_test.go:114: φιλεσ: [\"testdata/bool.go\" \"testdata/method.go\" \"testdata/unused.go\"]\n"} {"Action":"pass","Test":"Test☺☹/2"} {"Action":"output","Test":"Test☺☹/0","Output":" --- PASS: Test☺☹/0 (0.13s)\n"} -{"Action":"output","Test":"Test☺☹/0","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/assign.go\" \"testdata/httpresponse.go\" \"testdata/structtag.go\"]\n"} +{"Action":"output","Test":"Test☺☹/0","Output":" vet_test.go:114: φιλεσ: [\"testdata/assign.go\" \"testdata/httpresponse.go\" \"testdata/structtag.go\"]\n"} {"Action":"pass","Test":"Test☺☹/0"} {"Action":"output","Test":"Test☺☹/4","Output":" --- PASS: Test☺☹/4 (0.16s)\n"} -{"Action":"output","Test":"Test☺☹/4","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/copylock.go\" \"testdata/print.go\"]\n"} +{"Action":"output","Test":"Test☺☹/4","Output":" vet_test.go:114: φιλεσ: [\"testdata/copylock.go\" \"testdata/print.go\"]\n"} {"Action":"pass","Test":"Test☺☹/4"} {"Action":"output","Test":"Test☺☹/1","Output":" --- PASS: Test☺☹/1 (0.07s)\n"} -{"Action":"output","Test":"Test☺☹/1","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/atomic.go\" \"testdata/lostcancel.go\" \"testdata/unsafeptr.go\"]\n"} +{"Action":"output","Test":"Test☺☹/1","Output":" vet_test.go:114: φιλεσ: [\"testdata/atomic.go\" \"testdata/lostcancel.go\" \"testdata/unsafeptr.go\"]\n"} {"Action":"pass","Test":"Test☺☹/1"} {"Action":"output","Test":"Test☺☹/7","Output":" --- PASS: Test☺☹/7 (0.19s)\n"} -{"Action":"output","Test":"Test☺☹/7","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/deadcode.go\" \"testdata/shift.go\"]\n"} +{"Action":"output","Test":"Test☺☹/7","Output":" vet_test.go:114: φιλεσ: [\"testdata/deadcode.go\" \"testdata/shift.go\"]\n"} {"Action":"pass","Test":"Test☺☹/7"} {"Action":"pass","Test":"Test☺☹"} {"Action":"output","Test":"Test☺☹Dirs","Output":"--- PASS: Test☺☹Dirs (0.01s)\n"} diff --git a/libgo/go/cmd/internal/test2json/testdata/smiley.test b/libgo/go/cmd/internal/test2json/testdata/smiley.test index 05edf5a..bd1ed2d 100644 --- a/libgo/go/cmd/internal/test2json/testdata/smiley.test +++ b/libgo/go/cmd/internal/test2json/testdata/smiley.test @@ -58,11 +58,11 @@ === CONT Test☺☹/2 --- PASS: TestTags (0.00s) --- PASS: TestTags/x_testtag_y (0.04s) - vet_test.go:187: -tags=x testtag y + vet_test.go:187: -tags=x testtag y --- PASS: TestTags/x,testtag,y (0.04s) - vet_test.go:187: -tags=x,testtag,y + vet_test.go:187: -tags=x,testtag,y --- PASS: TestTags/testtag (0.04s) - vet_test.go:187: -tags=testtag + vet_test.go:187: -tags=testtag === CONT Test☺☹/1 === CONT Test☺☹Dirs/testingpkg === CONT Test☺☹Dirs/buildtag @@ -71,21 +71,21 @@ === CONT Test☺☹Dirs/cgo --- PASS: Test☺☹ (0.39s) --- PASS: Test☺☹/5 (0.07s) - vet_test.go:114: φιλεσ: ["testdata/copylock_func.go" "testdata/rangeloop.go"] + vet_test.go:114: φιλεσ: ["testdata/copylock_func.go" "testdata/rangeloop.go"] --- PASS: Test☺☹/3 (0.07s) - vet_test.go:114: φιλεσ: ["testdata/composite.go" "testdata/nilfunc.go"] + vet_test.go:114: φιλεσ: ["testdata/composite.go" "testdata/nilfunc.go"] --- PASS: Test☺☹/6 (0.07s) - vet_test.go:114: φιλεσ: ["testdata/copylock_range.go" "testdata/shadow.go"] + vet_test.go:114: φιλεσ: ["testdata/copylock_range.go" "testdata/shadow.go"] --- PASS: Test☺☹/2 (0.07s) - vet_test.go:114: φιλεσ: ["testdata/bool.go" "testdata/method.go" "testdata/unused.go"] + vet_test.go:114: φιλεσ: ["testdata/bool.go" "testdata/method.go" "testdata/unused.go"] --- PASS: Test☺☹/0 (0.13s) - vet_test.go:114: φιλεσ: ["testdata/assign.go" "testdata/httpresponse.go" "testdata/structtag.go"] + vet_test.go:114: φιλεσ: ["testdata/assign.go" "testdata/httpresponse.go" "testdata/structtag.go"] --- PASS: Test☺☹/4 (0.16s) - vet_test.go:114: φιλεσ: ["testdata/copylock.go" "testdata/print.go"] + vet_test.go:114: φιλεσ: ["testdata/copylock.go" "testdata/print.go"] --- PASS: Test☺☹/1 (0.07s) - vet_test.go:114: φιλεσ: ["testdata/atomic.go" "testdata/lostcancel.go" "testdata/unsafeptr.go"] + vet_test.go:114: φιλεσ: ["testdata/atomic.go" "testdata/lostcancel.go" "testdata/unsafeptr.go"] --- PASS: Test☺☹/7 (0.19s) - vet_test.go:114: φιλεσ: ["testdata/deadcode.go" "testdata/shift.go"] + vet_test.go:114: φιλεσ: ["testdata/deadcode.go" "testdata/shift.go"] --- PASS: Test☺☹Dirs (0.01s) --- PASS: Test☺☹Dirs/testingpkg (0.06s) --- PASS: Test☺☹Dirs/divergent (0.05s) diff --git a/libgo/go/cmd/internal/test2json/testdata/vet.json b/libgo/go/cmd/internal/test2json/testdata/vet.json index 8c5921d..2558d61 100644 --- a/libgo/go/cmd/internal/test2json/testdata/vet.json +++ b/libgo/go/cmd/internal/test2json/testdata/vet.json @@ -116,13 +116,13 @@ {"Action":"output","Test":"TestVet/2","Output":"=== CONT TestVet/2\n"} {"Action":"output","Test":"TestTags","Output":"--- PASS: TestTags (0.00s)\n"} {"Action":"output","Test":"TestTags/x_testtag_y","Output":" --- PASS: TestTags/x_testtag_y (0.04s)\n"} -{"Action":"output","Test":"TestTags/x_testtag_y","Output":" \tvet_test.go:187: -tags=x testtag y\n"} +{"Action":"output","Test":"TestTags/x_testtag_y","Output":" vet_test.go:187: -tags=x testtag y\n"} {"Action":"pass","Test":"TestTags/x_testtag_y"} {"Action":"output","Test":"TestTags/x,testtag,y","Output":" --- PASS: TestTags/x,testtag,y (0.04s)\n"} -{"Action":"output","Test":"TestTags/x,testtag,y","Output":" \tvet_test.go:187: -tags=x,testtag,y\n"} +{"Action":"output","Test":"TestTags/x,testtag,y","Output":" vet_test.go:187: -tags=x,testtag,y\n"} {"Action":"pass","Test":"TestTags/x,testtag,y"} {"Action":"output","Test":"TestTags/testtag","Output":" --- PASS: TestTags/testtag (0.04s)\n"} -{"Action":"output","Test":"TestTags/testtag","Output":" \tvet_test.go:187: -tags=testtag\n"} +{"Action":"output","Test":"TestTags/testtag","Output":" vet_test.go:187: -tags=testtag\n"} {"Action":"pass","Test":"TestTags/testtag"} {"Action":"pass","Test":"TestTags"} {"Action":"cont","Test":"TestVet/1"} @@ -139,28 +139,28 @@ {"Action":"output","Test":"TestVetDirs/cgo","Output":"=== CONT TestVetDirs/cgo\n"} {"Action":"output","Test":"TestVet","Output":"--- PASS: TestVet (0.39s)\n"} {"Action":"output","Test":"TestVet/5","Output":" --- PASS: TestVet/5 (0.07s)\n"} -{"Action":"output","Test":"TestVet/5","Output":" \tvet_test.go:114: files: [\"testdata/copylock_func.go\" \"testdata/rangeloop.go\"]\n"} +{"Action":"output","Test":"TestVet/5","Output":" vet_test.go:114: files: [\"testdata/copylock_func.go\" \"testdata/rangeloop.go\"]\n"} {"Action":"pass","Test":"TestVet/5"} {"Action":"output","Test":"TestVet/3","Output":" --- PASS: TestVet/3 (0.07s)\n"} -{"Action":"output","Test":"TestVet/3","Output":" \tvet_test.go:114: files: [\"testdata/composite.go\" \"testdata/nilfunc.go\"]\n"} +{"Action":"output","Test":"TestVet/3","Output":" vet_test.go:114: files: [\"testdata/composite.go\" \"testdata/nilfunc.go\"]\n"} {"Action":"pass","Test":"TestVet/3"} {"Action":"output","Test":"TestVet/6","Output":" --- PASS: TestVet/6 (0.07s)\n"} -{"Action":"output","Test":"TestVet/6","Output":" \tvet_test.go:114: files: [\"testdata/copylock_range.go\" \"testdata/shadow.go\"]\n"} +{"Action":"output","Test":"TestVet/6","Output":" vet_test.go:114: files: [\"testdata/copylock_range.go\" \"testdata/shadow.go\"]\n"} {"Action":"pass","Test":"TestVet/6"} {"Action":"output","Test":"TestVet/2","Output":" --- PASS: TestVet/2 (0.07s)\n"} -{"Action":"output","Test":"TestVet/2","Output":" \tvet_test.go:114: files: [\"testdata/bool.go\" \"testdata/method.go\" \"testdata/unused.go\"]\n"} +{"Action":"output","Test":"TestVet/2","Output":" vet_test.go:114: files: [\"testdata/bool.go\" \"testdata/method.go\" \"testdata/unused.go\"]\n"} {"Action":"pass","Test":"TestVet/2"} {"Action":"output","Test":"TestVet/0","Output":" --- PASS: TestVet/0 (0.13s)\n"} -{"Action":"output","Test":"TestVet/0","Output":" \tvet_test.go:114: files: [\"testdata/assign.go\" \"testdata/httpresponse.go\" \"testdata/structtag.go\"]\n"} +{"Action":"output","Test":"TestVet/0","Output":" vet_test.go:114: files: [\"testdata/assign.go\" \"testdata/httpresponse.go\" \"testdata/structtag.go\"]\n"} {"Action":"pass","Test":"TestVet/0"} {"Action":"output","Test":"TestVet/4","Output":" --- PASS: TestVet/4 (0.16s)\n"} -{"Action":"output","Test":"TestVet/4","Output":" \tvet_test.go:114: files: [\"testdata/copylock.go\" \"testdata/print.go\"]\n"} +{"Action":"output","Test":"TestVet/4","Output":" vet_test.go:114: files: [\"testdata/copylock.go\" \"testdata/print.go\"]\n"} {"Action":"pass","Test":"TestVet/4"} {"Action":"output","Test":"TestVet/1","Output":" --- PASS: TestVet/1 (0.07s)\n"} -{"Action":"output","Test":"TestVet/1","Output":" \tvet_test.go:114: files: [\"testdata/atomic.go\" \"testdata/lostcancel.go\" \"testdata/unsafeptr.go\"]\n"} +{"Action":"output","Test":"TestVet/1","Output":" vet_test.go:114: files: [\"testdata/atomic.go\" \"testdata/lostcancel.go\" \"testdata/unsafeptr.go\"]\n"} {"Action":"pass","Test":"TestVet/1"} {"Action":"output","Test":"TestVet/7","Output":" --- PASS: TestVet/7 (0.19s)\n"} -{"Action":"output","Test":"TestVet/7","Output":" \tvet_test.go:114: files: [\"testdata/deadcode.go\" \"testdata/shift.go\"]\n"} +{"Action":"output","Test":"TestVet/7","Output":" vet_test.go:114: files: [\"testdata/deadcode.go\" \"testdata/shift.go\"]\n"} {"Action":"pass","Test":"TestVet/7"} {"Action":"pass","Test":"TestVet"} {"Action":"output","Test":"TestVetDirs","Output":"--- PASS: TestVetDirs (0.01s)\n"} diff --git a/libgo/go/cmd/internal/test2json/testdata/vet.test b/libgo/go/cmd/internal/test2json/testdata/vet.test index 3389559..59d187e 100644 --- a/libgo/go/cmd/internal/test2json/testdata/vet.test +++ b/libgo/go/cmd/internal/test2json/testdata/vet.test @@ -58,11 +58,11 @@ === CONT TestVet/2 --- PASS: TestTags (0.00s) --- PASS: TestTags/x_testtag_y (0.04s) - vet_test.go:187: -tags=x testtag y + vet_test.go:187: -tags=x testtag y --- PASS: TestTags/x,testtag,y (0.04s) - vet_test.go:187: -tags=x,testtag,y + vet_test.go:187: -tags=x,testtag,y --- PASS: TestTags/testtag (0.04s) - vet_test.go:187: -tags=testtag + vet_test.go:187: -tags=testtag === CONT TestVet/1 === CONT TestVetDirs/testingpkg === CONT TestVetDirs/buildtag @@ -71,21 +71,21 @@ === CONT TestVetDirs/cgo --- PASS: TestVet (0.39s) --- PASS: TestVet/5 (0.07s) - vet_test.go:114: files: ["testdata/copylock_func.go" "testdata/rangeloop.go"] + vet_test.go:114: files: ["testdata/copylock_func.go" "testdata/rangeloop.go"] --- PASS: TestVet/3 (0.07s) - vet_test.go:114: files: ["testdata/composite.go" "testdata/nilfunc.go"] + vet_test.go:114: files: ["testdata/composite.go" "testdata/nilfunc.go"] --- PASS: TestVet/6 (0.07s) - vet_test.go:114: files: ["testdata/copylock_range.go" "testdata/shadow.go"] + vet_test.go:114: files: ["testdata/copylock_range.go" "testdata/shadow.go"] --- PASS: TestVet/2 (0.07s) - vet_test.go:114: files: ["testdata/bool.go" "testdata/method.go" "testdata/unused.go"] + vet_test.go:114: files: ["testdata/bool.go" "testdata/method.go" "testdata/unused.go"] --- PASS: TestVet/0 (0.13s) - vet_test.go:114: files: ["testdata/assign.go" "testdata/httpresponse.go" "testdata/structtag.go"] + vet_test.go:114: files: ["testdata/assign.go" "testdata/httpresponse.go" "testdata/structtag.go"] --- PASS: TestVet/4 (0.16s) - vet_test.go:114: files: ["testdata/copylock.go" "testdata/print.go"] + vet_test.go:114: files: ["testdata/copylock.go" "testdata/print.go"] --- PASS: TestVet/1 (0.07s) - vet_test.go:114: files: ["testdata/atomic.go" "testdata/lostcancel.go" "testdata/unsafeptr.go"] + vet_test.go:114: files: ["testdata/atomic.go" "testdata/lostcancel.go" "testdata/unsafeptr.go"] --- PASS: TestVet/7 (0.19s) - vet_test.go:114: files: ["testdata/deadcode.go" "testdata/shift.go"] + vet_test.go:114: files: ["testdata/deadcode.go" "testdata/shift.go"] --- PASS: TestVetDirs (0.01s) --- PASS: TestVetDirs/testingpkg (0.06s) --- PASS: TestVetDirs/divergent (0.05s) diff --git a/libgo/go/cmd/test2json/main.go b/libgo/go/cmd/test2json/main.go index 0385d8f2..57a8741 100644 --- a/libgo/go/cmd/test2json/main.go +++ b/libgo/go/cmd/test2json/main.go @@ -118,12 +118,16 @@ func main() { w := &countWriter{0, c} cmd.Stdout = w cmd.Stderr = w - if err := cmd.Run(); err != nil { + err := cmd.Run() + if err != nil { if w.n > 0 { // Assume command printed why it failed. } else { fmt.Fprintf(c, "test2json: %v\n", err) } + } + c.Exited(err) + if err != nil { c.Close() os.Exit(1) } diff --git a/libgo/go/debug/elf/file.go b/libgo/go/debug/elf/file.go index b9a8b1e..48178d4 100644 --- a/libgo/go/debug/elf/file.go +++ b/libgo/go/debug/elf/file.go @@ -617,6 +617,8 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error { return f.applyRelocationsMIPS(dst, rels) case f.Class == ELFCLASS64 && f.Machine == EM_MIPS: return f.applyRelocationsMIPS64(dst, rels) + case f.Class == ELFCLASS32 && f.Machine == EM_RISCV: + return f.applyRelocationsRISCV(dst, rels) case f.Class == ELFCLASS64 && f.Machine == EM_RISCV: return f.applyRelocationsRISCV64(dst, rels) case f.Class == ELFCLASS64 && f.Machine == EM_S390: @@ -1008,6 +1010,47 @@ func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error { return nil } +func (f *File) applyRelocationsRISCV(dst []byte, rels []byte) error { + // 12 is the size of Rela32. + if len(rels)%12 != 0 { + return errors.New("length of relocation section is not a multiple of 12") + } + + symbols, _, err := f.getSymbols(SHT_SYMTAB) + if err != nil { + return err + } + + b := bytes.NewReader(rels) + var rela Rela32 + + for b.Len() > 0 { + binary.Read(b, f.ByteOrder, &rela) + symNo := rela.Info >> 8 + t := R_RISCV(rela.Info & 0xff) + + if symNo == 0 || symNo > uint32(len(symbols)) { + continue + } + sym := &symbols[symNo-1] + needed, val := relocSymbolTargetOK(sym) + if !needed { + continue + } + + switch t { + case R_RISCV_32: + if rela.Off+4 >= uint32(len(dst)) || rela.Addend < 0 { + continue + } + val32 := uint32(val) + uint32(rela.Addend) + f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) + } + } + + return nil +} + func (f *File) applyRelocationsRISCV64(dst []byte, rels []byte) error { // 24 is the size of Rela64. if len(rels)%24 != 0 { diff --git a/libgo/go/go/internal/gccgoimporter/importer.go b/libgo/go/go/internal/gccgoimporter/importer.go index ff484a7..391477d 100644 --- a/libgo/go/go/internal/gccgoimporter/importer.go +++ b/libgo/go/go/internal/gccgoimporter/importer.go @@ -198,7 +198,7 @@ func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Impo return } - if magics == archiveMagic { + if magics == archiveMagic || magics == aixbigafMagic { reader, err = arExportData(reader) if err != nil { return diff --git a/libgo/go/go/types/sizes.go b/libgo/go/go/types/sizes.go index 6ab6157..4787b24 100644 --- a/libgo/go/go/types/sizes.go +++ b/libgo/go/go/types/sizes.go @@ -167,6 +167,7 @@ var gcArchSizes = map[string]*StdSizes{ "mips64le": {8, 8}, "ppc64": {8, 8}, "ppc64le": {8, 8}, + "riscv": {4, 4}, "riscv64": {8, 8}, "s390x": {8, 8}, "sparc64": {8, 8}, @@ -180,7 +181,8 @@ var gcArchSizes = map[string]*StdSizes{ // // Supported architectures for compiler "gc": // "386", "arm", "arm64", "amd64", "amd64p32", "mips", "mipsle", -// "mips64", "mips64le", "ppc64", "ppc64le", "riscv64", "s390x", "sparc64", "wasm". +// "mips64", "mips64le", "ppc64", "ppc64le", "riscv", "riscv64", +// "s390x", "sparc64", "wasm". func SizesFor(compiler, arch string) Sizes { var m map[string]*StdSizes switch compiler { diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_riscv.go b/libgo/go/golang.org/x/sys/cpu/cpu_riscv.go new file mode 100644 index 0000000..891cb98 --- /dev/null +++ b/libgo/go/golang.org/x/sys/cpu/cpu_riscv.go @@ -0,0 +1,7 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build riscv + +package cpu diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go b/libgo/go/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go index e6bfe71..0f52150 100644 --- a/libgo/go/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go +++ b/libgo/go/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go @@ -87,6 +87,7 @@ var ( asmArchMips64LE = asmArch{name: "mips64le", bigEndian: false, stack: "R29", lr: true} asmArchPpc64 = asmArch{name: "ppc64", bigEndian: true, stack: "R1", lr: true} asmArchPpc64LE = asmArch{name: "ppc64le", bigEndian: false, stack: "R1", lr: true} + asmArchRISCV = asmArch{name: "riscv", bigEndian: false, stack: "SP", lr: true} asmArchRISCV64 = asmArch{name: "riscv64", bigEndian: false, stack: "SP", lr: true} asmArchS390X = asmArch{name: "s390x", bigEndian: true, stack: "R15", lr: true} asmArchWasm = asmArch{name: "wasm", bigEndian: false, stack: "SP", lr: false} @@ -102,6 +103,7 @@ var ( &asmArchMips64LE, &asmArchPpc64, &asmArchPpc64LE, + &asmArchRISCV, &asmArchRISCV64, &asmArchS390X, &asmArchWasm, diff --git a/libgo/go/internal/bytealg/indexbyte_generic.go b/libgo/go/internal/bytealg/indexbyte_generic.go index a863d81..46325dd 100644 --- a/libgo/go/internal/bytealg/indexbyte_generic.go +++ b/libgo/go/internal/bytealg/indexbyte_generic.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build ignore_for_gccgo -// +build !386,!amd64,!s390x,!arm,!arm64,!ppc64,!ppc64le,!mips,!mipsle,!mips64,!mips64le,!riscv64,!wasm +// +build !386,!amd64,!s390x,!arm,!arm64,!ppc64,!ppc64le,!mips,!mipsle,!mips64,!mips64le,!riscv,!riscv64,!wasm package bytealg diff --git a/libgo/go/internal/bytealg/indexbyte_native.go b/libgo/go/internal/bytealg/indexbyte_native.go index 20da788..c427e66 100644 --- a/libgo/go/internal/bytealg/indexbyte_native.go +++ b/libgo/go/internal/bytealg/indexbyte_native.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// -build 386 amd64 s390x arm arm64 ppc64 ppc64le mips mipsle mips64 mips64le riscv64 wasm +// -build 386 amd64 s390x arm arm64 ppc64 ppc64le mips mipsle mips64 mips64le riscv riscv64 wasm package bytealg diff --git a/libgo/go/internal/cpu/cpu_no_init.go b/libgo/go/internal/cpu/cpu_no_init.go index fb381e1..e7ff873 100644 --- a/libgo/go/internal/cpu/cpu_no_init.go +++ b/libgo/go/internal/cpu/cpu_no_init.go @@ -6,6 +6,7 @@ // +build !amd64 // +build !arm // +build !arm64 +// +build !ppc // +build !ppc64 // +build !ppc64le // +build !s390x diff --git a/libgo/go/internal/cpu/cpu_ppc64x.go b/libgo/go/internal/cpu/cpu_ppcx.go index b726cc8..56ff875 100644 --- a/libgo/go/internal/cpu/cpu_ppc64x.go +++ b/libgo/go/internal/cpu/cpu_ppcx.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build ppc64 ppc64le +// +build ppc ppc64 ppc64le package cpu diff --git a/libgo/go/internal/poll/copy_file_range_linux.go b/libgo/go/internal/poll/copy_file_range_linux.go index 604607f..09de299 100644 --- a/libgo/go/internal/poll/copy_file_range_linux.go +++ b/libgo/go/internal/poll/copy_file_range_linux.go @@ -41,7 +41,7 @@ func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err // use copy_file_range(2) again. atomic.StoreInt32(©FileRangeSupported, 0) return 0, false, nil - case syscall.EXDEV, syscall.EINVAL: + case syscall.EXDEV, syscall.EINVAL, syscall.EOPNOTSUPP, syscall.EPERM: // Prior to Linux 5.3, it was not possible to // copy_file_range across file systems. Similarly to // the ENOSYS case above, if we see EXDEV, we have @@ -52,6 +52,14 @@ func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err // dst or src refer to a pipe rather than a regular // file. This is another case where no data has been // transfered, so we consider it unhandled. + // + // If the file is on NFS, we can see EOPNOTSUPP. + // See issue #40731. + // + // If the process is running inside a Docker container, + // we might see EPERM instead of ENOSYS. See issue + // #40893. Since EPERM might also be a legitimate error, + // don't mark copy_file_range(2) as unsupported. return 0, false, nil case nil: if n == 0 { diff --git a/libgo/go/internal/reflectlite/eqtype.go b/libgo/go/internal/reflectlite/eqtype.go new file mode 100644 index 0000000..a03cf1c --- /dev/null +++ b/libgo/go/internal/reflectlite/eqtype.go @@ -0,0 +1,12 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !aix !gccgo + +package reflectlite + +// rtypeEqual returns true if both types are identical. +func rtypeEqual(t1, t2 *rtype) bool { + return t1 == t2 +} diff --git a/libgo/go/internal/reflectlite/eqtype_aix_gccgo.go b/libgo/go/internal/reflectlite/eqtype_aix_gccgo.go new file mode 100644 index 0000000..38b507f --- /dev/null +++ b/libgo/go/internal/reflectlite/eqtype_aix_gccgo.go @@ -0,0 +1,26 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build aix,gccgo + +// AIX linker isn't able to merge identical type descriptors coming from +// different objects. Thus, two rtypes might have two different pointers +// even if they are the same. Thus, instead of pointer equality, string +// field is checked. + +package reflectlite + +// rtypeEqual returns true if both types are identical. +func rtypeEqual(t1, t2 *rtype) bool { + switch { + case t1 == t2: + return true + case t1 == nil || t2 == nil: + return false + case t1.kind != t2.kind || t1.hash != t2.hash: + return false + default: + return t1.String() == t2.String() + } +} diff --git a/libgo/go/internal/reflectlite/type.go b/libgo/go/internal/reflectlite/type.go index e700a55..1609a06 100644 --- a/libgo/go/internal/reflectlite/type.go +++ b/libgo/go/internal/reflectlite/type.go @@ -539,7 +539,7 @@ func implements(T, V *rtype) bool { for j := 0; j < len(v.methods); j++ { tm := &t.methods[i] vm := &v.methods[j] - if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && toType(vm.typ).common() == toType(tm.typ).common() { + if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && rtypeEqual(toType(vm.typ).common(), toType(tm.typ).common()) { if i++; i >= len(t.methods) { return true } @@ -556,7 +556,7 @@ func implements(T, V *rtype) bool { for j := 0; j < len(v.methods); j++ { tm := &t.methods[i] vm := &v.methods[j] - if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && toType(vm.mtyp).common() == toType(tm.typ).common() { + if *vm.name == *tm.name && (vm.pkgPath == tm.pkgPath || (vm.pkgPath != nil && tm.pkgPath != nil && *vm.pkgPath == *tm.pkgPath)) && rtypeEqual(toType(vm.mtyp).common(), toType(tm.typ).common()) { if i++; i >= len(t.methods) { return true } @@ -572,7 +572,7 @@ func implements(T, V *rtype) bool { // and the ideal constant rules (no ideal constants at run time). func directlyAssignable(T, V *rtype) bool { // x's type V is identical to T? - if T == V { + if rtypeEqual(T, V) { return true } @@ -599,7 +599,7 @@ func haveIdenticalType(T, V Type, cmpTags bool) bool { } func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool { - if T == V { + if rtypeEqual(T, V) { return true } diff --git a/libgo/go/internal/syscall/unix/sysnum_linux_generic.go b/libgo/go/internal/syscall/unix/sysnum_linux_generic.go index 3e00703..3d34fdb 100644 --- a/libgo/go/internal/syscall/unix/sysnum_linux_generic.go +++ b/libgo/go/internal/syscall/unix/sysnum_linux_generic.go @@ -9,7 +9,7 @@ package unix // This file is named "generic" because at a certain point Linux started // standardizing on system call numbers across architectures. So far this -// means only arm64, nios2 and riscv use the standard numbers. +// means only arm64, nios2, riscv and riscv64 use the standard numbers. const ( getrandomTrap uintptr = 278 diff --git a/libgo/go/net/fd_posix.go b/libgo/go/net/fd_posix.go index 53abd15..b2f99bc 100644 --- a/libgo/go/net/fd_posix.go +++ b/libgo/go/net/fd_posix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows +// +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris windows package net diff --git a/libgo/go/net/http/cgi/child.go b/libgo/go/net/http/cgi/child.go index 9474175..61de616 100644 --- a/libgo/go/net/http/cgi/child.go +++ b/libgo/go/net/http/cgi/child.go @@ -163,10 +163,12 @@ func Serve(handler http.Handler) error { } type response struct { - req *http.Request - header http.Header - bufw *bufio.Writer - headerSent bool + req *http.Request + header http.Header + code int + wroteHeader bool + wroteCGIHeader bool + bufw *bufio.Writer } func (r *response) Flush() { @@ -178,26 +180,38 @@ func (r *response) Header() http.Header { } func (r *response) Write(p []byte) (n int, err error) { - if !r.headerSent { + if !r.wroteHeader { r.WriteHeader(http.StatusOK) } + if !r.wroteCGIHeader { + r.writeCGIHeader(p) + } return r.bufw.Write(p) } func (r *response) WriteHeader(code int) { - if r.headerSent { + if r.wroteHeader { // Note: explicitly using Stderr, as Stdout is our HTTP output. fmt.Fprintf(os.Stderr, "CGI attempted to write header twice on request for %s", r.req.URL) return } - r.headerSent = true - fmt.Fprintf(r.bufw, "Status: %d %s\r\n", code, http.StatusText(code)) + r.wroteHeader = true + r.code = code +} - // Set a default Content-Type +// writeCGIHeader finalizes the header sent to the client and writes it to the output. +// p is not written by writeHeader, but is the first chunk of the body +// that will be written. It is sniffed for a Content-Type if none is +// set explicitly. +func (r *response) writeCGIHeader(p []byte) { + if r.wroteCGIHeader { + return + } + r.wroteCGIHeader = true + fmt.Fprintf(r.bufw, "Status: %d %s\r\n", r.code, http.StatusText(r.code)) if _, hasType := r.header["Content-Type"]; !hasType { - r.header.Add("Content-Type", "text/html; charset=utf-8") + r.header.Set("Content-Type", http.DetectContentType(p)) } - r.header.Write(r.bufw) r.bufw.WriteString("\r\n") r.bufw.Flush() diff --git a/libgo/go/net/http/cgi/child_test.go b/libgo/go/net/http/cgi/child_test.go index 14e0af4..f6ecb6e 100644 --- a/libgo/go/net/http/cgi/child_test.go +++ b/libgo/go/net/http/cgi/child_test.go @@ -7,6 +7,11 @@ package cgi import ( + "bufio" + "bytes" + "net/http" + "net/http/httptest" + "strings" "testing" ) @@ -148,3 +153,67 @@ func TestRequestWithoutRemotePort(t *testing.T) { t.Errorf("RemoteAddr: got %q; want %q", g, e) } } + +type countingWriter int + +func (c *countingWriter) Write(p []byte) (int, error) { + *c += countingWriter(len(p)) + return len(p), nil +} +func (c *countingWriter) WriteString(p string) (int, error) { + *c += countingWriter(len(p)) + return len(p), nil +} + +func TestResponse(t *testing.T) { + var tests = []struct { + name string + body string + wantCT string + }{ + { + name: "no body", + wantCT: "text/plain; charset=utf-8", + }, + { + name: "html", + body: "<html><head><title>test page</title></head><body>This is a body</body></html>", + wantCT: "text/html; charset=utf-8", + }, + { + name: "text", + body: strings.Repeat("gopher", 86), + wantCT: "text/plain; charset=utf-8", + }, + { + name: "jpg", + body: "\xFF\xD8\xFF" + strings.Repeat("B", 1024), + wantCT: "image/jpeg", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var buf bytes.Buffer + resp := response{ + req: httptest.NewRequest("GET", "/", nil), + header: http.Header{}, + bufw: bufio.NewWriter(&buf), + } + n, err := resp.Write([]byte(tt.body)) + if err != nil { + t.Errorf("Write: unexpected %v", err) + } + if want := len(tt.body); n != want { + t.Errorf("reported short Write: got %v want %v", n, want) + } + resp.writeCGIHeader(nil) + resp.Flush() + if got := resp.Header().Get("Content-Type"); got != tt.wantCT { + t.Errorf("wrong content-type: got %q, want %q", got, tt.wantCT) + } + if !bytes.HasSuffix(buf.Bytes(), []byte(tt.body)) { + t.Errorf("body was not correctly written") + } + }) + } +} diff --git a/libgo/go/net/http/cgi/host.go b/libgo/go/net/http/cgi/host.go index 863f406..eff67ca 100644 --- a/libgo/go/net/http/cgi/host.go +++ b/libgo/go/net/http/cgi/host.go @@ -37,15 +37,15 @@ var trailingPort = regexp.MustCompile(`:([0-9]+)$`) var osDefaultInheritEnv = func() []string { switch runtime.GOOS { - case "darwin": + case "darwin", "ios": return []string{"DYLD_LIBRARY_PATH"} - case "linux", "freebsd", "openbsd": + case "linux", "freebsd", "netbsd", "openbsd": return []string{"LD_LIBRARY_PATH"} case "hpux": return []string{"LD_LIBRARY_PATH", "SHLIB_PATH"} case "irix": return []string{"LD_LIBRARY_PATH", "LD_LIBRARYN32_PATH", "LD_LIBRARY64_PATH"} - case "solaris": + case "illumos", "solaris": return []string{"LD_LIBRARY_PATH", "LD_LIBRARY_PATH_32", "LD_LIBRARY_PATH_64"} case "windows": return []string{"SystemRoot", "COMSPEC", "PATHEXT", "WINDIR"} diff --git a/libgo/go/net/http/cgi/integration_test.go b/libgo/go/net/http/cgi/integration_test.go index 32d59c0..295c3b8 100644 --- a/libgo/go/net/http/cgi/integration_test.go +++ b/libgo/go/net/http/cgi/integration_test.go @@ -16,7 +16,9 @@ import ( "io" "net/http" "net/http/httptest" + "net/url" "os" + "strings" "testing" "time" ) @@ -52,7 +54,7 @@ func TestHostingOurselves(t *testing.T) { } replay := runCgiTest(t, h, "GET /test.go?foo=bar&a=b HTTP/1.0\nHost: example.com\n\n", expectedMap) - if expected, got := "text/html; charset=utf-8", replay.Header().Get("Content-Type"); got != expected { + if expected, got := "text/plain; charset=utf-8", replay.Header().Get("Content-Type"); got != expected { t.Errorf("got a Content-Type of %q; expected %q", got, expected) } if expected, got := "X-Test-Value", replay.Header().Get("X-Test-Header"); got != expected { @@ -152,6 +154,51 @@ func TestChildOnlyHeaders(t *testing.T) { } } +func TestChildContentType(t *testing.T) { + testenv.MustHaveExec(t) + + h := &Handler{ + Path: os.Args[0], + Root: "/test.go", + Args: []string{"-test.run=TestBeChildCGIProcess"}, + } + var tests = []struct { + name string + body string + wantCT string + }{ + { + name: "no body", + wantCT: "text/plain; charset=utf-8", + }, + { + name: "html", + body: "<html><head><title>test page</title></head><body>This is a body</body></html>", + wantCT: "text/html; charset=utf-8", + }, + { + name: "text", + body: strings.Repeat("gopher", 86), + wantCT: "text/plain; charset=utf-8", + }, + { + name: "jpg", + body: "\xFF\xD8\xFF" + strings.Repeat("B", 1024), + wantCT: "image/jpeg", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + expectedMap := map[string]string{"_body": tt.body} + req := fmt.Sprintf("GET /test.go?exact-body=%s HTTP/1.0\nHost: example.com\n\n", url.QueryEscape(tt.body)) + replay := runCgiTest(t, h, req, expectedMap) + if got := replay.Header().Get("Content-Type"); got != tt.wantCT { + t.Errorf("got a Content-Type of %q; expected it to start with %q", got, tt.wantCT) + } + }) + } +} + // golang.org/issue/7198 func Test500WithNoHeaders(t *testing.T) { want500Test(t, "/immediate-disconnect") } func Test500WithNoContentType(t *testing.T) { want500Test(t, "/no-content-type") } @@ -203,6 +250,10 @@ func TestBeChildCGIProcess(t *testing.T) { if req.FormValue("no-body") == "1" { return } + if eb, ok := req.Form["exact-body"]; ok { + io.WriteString(rw, eb[0]) + return + } if req.FormValue("write-forever") == "1" { io.Copy(rw, neverEnding('a')) for { diff --git a/libgo/go/net/http/fcgi/child.go b/libgo/go/net/http/fcgi/child.go index 30a6b2c..a31273b 100644 --- a/libgo/go/net/http/fcgi/child.go +++ b/libgo/go/net/http/fcgi/child.go @@ -74,10 +74,12 @@ func (r *request) parseParams() { // response implements http.ResponseWriter. type response struct { - req *request - header http.Header - w *bufWriter - wroteHeader bool + req *request + header http.Header + code int + wroteHeader bool + wroteCGIHeader bool + w *bufWriter } func newResponse(c *child, req *request) *response { @@ -92,11 +94,14 @@ func (r *response) Header() http.Header { return r.header } -func (r *response) Write(data []byte) (int, error) { +func (r *response) Write(p []byte) (n int, err error) { if !r.wroteHeader { r.WriteHeader(http.StatusOK) } - return r.w.Write(data) + if !r.wroteCGIHeader { + r.writeCGIHeader(p) + } + return r.w.Write(p) } func (r *response) WriteHeader(code int) { @@ -104,22 +109,34 @@ func (r *response) WriteHeader(code int) { return } r.wroteHeader = true + r.code = code if code == http.StatusNotModified { // Must not have body. r.header.Del("Content-Type") r.header.Del("Content-Length") r.header.Del("Transfer-Encoding") - } else if r.header.Get("Content-Type") == "" { - r.header.Set("Content-Type", "text/html; charset=utf-8") } - if r.header.Get("Date") == "" { r.header.Set("Date", time.Now().UTC().Format(http.TimeFormat)) } +} - fmt.Fprintf(r.w, "Status: %d %s\r\n", code, http.StatusText(code)) +// writeCGIHeader finalizes the header sent to the client and writes it to the output. +// p is not written by writeHeader, but is the first chunk of the body +// that will be written. It is sniffed for a Content-Type if none is +// set explicitly. +func (r *response) writeCGIHeader(p []byte) { + if r.wroteCGIHeader { + return + } + r.wroteCGIHeader = true + fmt.Fprintf(r.w, "Status: %d %s\r\n", r.code, http.StatusText(r.code)) + if _, hasType := r.header["Content-Type"]; r.code != http.StatusNotModified && !hasType { + r.header.Set("Content-Type", http.DetectContentType(p)) + } r.header.Write(r.w) r.w.WriteString("\r\n") + r.w.Flush() } func (r *response) Flush() { @@ -290,6 +307,8 @@ func (c *child) serveRequest(req *request, body io.ReadCloser) { httpReq = httpReq.WithContext(envVarCtx) c.handler.ServeHTTP(r, httpReq) } + // Make sure we serve something even if nothing was written to r + r.Write(nil) r.Close() c.mu.Lock() delete(c.requests, req.reqId) diff --git a/libgo/go/net/http/fcgi/fcgi_test.go b/libgo/go/net/http/fcgi/fcgi_test.go index e9d2b34..59246c2 100644 --- a/libgo/go/net/http/fcgi/fcgi_test.go +++ b/libgo/go/net/http/fcgi/fcgi_test.go @@ -10,6 +10,7 @@ import ( "io" "io/ioutil" "net/http" + "strings" "testing" ) @@ -344,3 +345,55 @@ func TestChildServeReadsEnvVars(t *testing.T) { <-done } } + +func TestResponseWriterSniffsContentType(t *testing.T) { + t.Skip("this test is flaky, see Issue 41167") + var tests = []struct { + name string + body string + wantCT string + }{ + { + name: "no body", + wantCT: "text/plain; charset=utf-8", + }, + { + name: "html", + body: "<html><head><title>test page</title></head><body>This is a body</body></html>", + wantCT: "text/html; charset=utf-8", + }, + { + name: "text", + body: strings.Repeat("gopher", 86), + wantCT: "text/plain; charset=utf-8", + }, + { + name: "jpg", + body: "\xFF\xD8\xFF" + strings.Repeat("B", 1024), + wantCT: "image/jpeg", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + input := make([]byte, len(streamFullRequestStdin)) + copy(input, streamFullRequestStdin) + rc := nopWriteCloser{bytes.NewBuffer(input)} + done := make(chan bool) + var resp *response + c := newChild(rc, http.HandlerFunc(func( + w http.ResponseWriter, + r *http.Request, + ) { + io.WriteString(w, tt.body) + resp = w.(*response) + done <- true + })) + defer c.cleanUp() + go c.serve() + <-done + if got := resp.Header().Get("Content-Type"); got != tt.wantCT { + t.Errorf("got a Content-Type of %q; expected it to start with %q", got, tt.wantCT) + } + }) + } +} diff --git a/libgo/go/net/interface_aix.go b/libgo/go/net/interface_aix.go index f57c5ff..bd55386 100644 --- a/libgo/go/net/interface_aix.go +++ b/libgo/go/net/interface_aix.go @@ -33,8 +33,6 @@ const _RTAX_NETMASK = 2 const _RTAX_IFA = 5 const _RTAX_MAX = 8 -const _SIOCGIFMTU = -0x3fd796aa - func getIfList() ([]byte, error) { needed, err := syscall.Getkerninfo(_KINFO_RT_IFLIST, 0, 0, 0) if err != nil { diff --git a/libgo/go/net/mail/message.go b/libgo/go/net/mail/message.go index 6833cfa..09fb794 100644 --- a/libgo/go/net/mail/message.go +++ b/libgo/go/net/mail/message.go @@ -279,9 +279,6 @@ func (p *addrParser) parseAddressList() ([]*Address, error) { if p.consume(',') { continue } - if p.empty() { - break - } addrs, err := p.parseAddress(true) if err != nil { @@ -295,9 +292,17 @@ func (p *addrParser) parseAddressList() ([]*Address, error) { if p.empty() { break } - if !p.consume(',') { + if p.peek() != ',' { return nil, errors.New("mail: expected comma") } + + // Skip empty entries for obs-addr-list. + for p.consume(',') { + p.skipSpace() + } + if p.empty() { + break + } } return list, nil } diff --git a/libgo/go/net/mail/message_test.go b/libgo/go/net/mail/message_test.go index 75db767..67e3643 100644 --- a/libgo/go/net/mail/message_test.go +++ b/libgo/go/net/mail/message_test.go @@ -446,6 +446,19 @@ func TestAddressParsing(t *testing.T) { }, }, { + ` , joe@where.test,,John <jdoe@one.test>,,`, + []*Address{ + { + Name: "", + Address: "joe@where.test", + }, + { + Name: "John", + Address: "jdoe@one.test", + }, + }, + }, + { `Group1: <addr1@example.com>;, Group 2: addr2@example.com;, John <addr3@example.com>`, []*Address{ { @@ -1067,3 +1080,22 @@ func TestAddressFormattingAndParsing(t *testing.T) { } } } + +func TestEmptyAddress(t *testing.T) { + parsed, err := ParseAddress("") + if parsed != nil || err == nil { + t.Errorf(`ParseAddress("") = %v, %v, want nil, error`, parsed, err) + } + list, err := ParseAddressList("") + if len(list) > 0 || err == nil { + t.Errorf(`ParseAddressList("") = %v, %v, want nil, error`, list, err) + } + list, err = ParseAddressList(",") + if len(list) > 0 || err == nil { + t.Errorf(`ParseAddressList("") = %v, %v, want nil, error`, list, err) + } + list, err = ParseAddressList("a@b c@d") + if len(list) > 0 || err == nil { + t.Errorf(`ParseAddressList("") = %v, %v, want nil, error`, list, err) + } +} diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go index ee37359..68efab6 100644 --- a/libgo/go/reflect/all_test.go +++ b/libgo/go/reflect/all_test.go @@ -2396,8 +2396,14 @@ func TestVariadicMethodValue(t *testing.T) { points := []Point{{20, 21}, {22, 23}, {24, 25}} want := int64(p.TotalDist(points[0], points[1], points[2])) + // Variadic method of type. + tfunc := TypeOf((func(Point, ...Point) int)(nil)) + if tt := TypeOf(p).Method(4).Type; tt != tfunc { + t.Errorf("Variadic Method Type from TypeOf is %s; want %s", tt, tfunc) + } + // Curried method of value. - tfunc := TypeOf((func(...Point) int)(nil)) + tfunc = TypeOf((func(...Point) int)(nil)) v := ValueOf(p).Method(4) if tt := v.Type(); tt != tfunc { t.Errorf("Variadic Method Type is %s; want %s", tt, tfunc) diff --git a/libgo/go/reflect/eqtype.go b/libgo/go/reflect/eqtype.go new file mode 100644 index 0000000..5639bc5 --- /dev/null +++ b/libgo/go/reflect/eqtype.go @@ -0,0 +1,24 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !aix !gccgo + +package reflect + +// rtypeEqual returns true if both rtypes are identical. +func rtypeEqual(t1, t2 *rtype) bool { + return t1 == t2 +} + +// typeEqual returns true if both Types are identical. +func typeEqual(t1, t2 Type) bool { + return t1 == t2 +} + +func toType(p *rtype) Type { + if p == nil { + return nil + } + return p +} diff --git a/libgo/go/reflect/eqtype_aix_gccgo.go b/libgo/go/reflect/eqtype_aix_gccgo.go new file mode 100644 index 0000000..7afbf10 --- /dev/null +++ b/libgo/go/reflect/eqtype_aix_gccgo.go @@ -0,0 +1,74 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build aix,gccgo + +// AIX linker isn't able to merge identical type descriptors coming from +// different objects. Thus, two rtypes might have two different pointers +// even if they are the same. Thus, instead of pointer equality, string +// field is checked. + +package reflect + +import ( + "sync" +) + +// rtypeEqual returns true if both rtypes are identical. +func rtypeEqual(t1, t2 *rtype) bool { + switch { + case t1 == t2: + return true + case t1 == nil || t2 == nil: + return false + case t1.kind != t2.kind || t1.hash != t2.hash: + return false + default: + return t1.String() == t2.String() + } +} + +// typeEqual returns true if both Types are identical. +func typeEqual(t1, t2 Type) bool { + return rtypeEqual(t1.common(), t2.common()) +} + +// toType converts from a *rtype to a Type that can be returned +// to the client of package reflect. The only concern is that +// a nil *rtype must be replaced by a nil Type. +// On AIX, as type duplications can occur, it also ensure that +// multiple *rtype for the same type are coalesced into a single +// Type. + +var canonicalType = make(map[string]Type) + +var canonicalTypeLock sync.RWMutex + +func canonicalize(t Type) Type { + if t == nil { + return nil + } + s := t.rawString() + canonicalTypeLock.RLock() + if r, ok := canonicalType[s]; ok { + canonicalTypeLock.RUnlock() + return r + } + canonicalTypeLock.RUnlock() + canonicalTypeLock.Lock() + if r, ok := canonicalType[s]; ok { + canonicalTypeLock.Unlock() + return r + } + canonicalType[s] = t + canonicalTypeLock.Unlock() + return t +} + +func toType(p *rtype) Type { + if p == nil { + return nil + } + return canonicalize(p) +} diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go index 2ce1901f..73c09d4 100644 --- a/libgo/go/reflect/type.go +++ b/libgo/go/reflect/type.go @@ -1129,7 +1129,7 @@ func (t *rtype) ptrTo() *rtype { // Look in known types. s := "*" + *t.string if tt := lookupType(s); tt != nil { - p := (*ptrType)(unsafe.Pointer(tt)) + p := (*ptrType)(unsafe.Pointer(toType(tt).(*rtype))) if p.elem == t { pi, _ := ptrMap.LoadOrStore(t, p) return &pi.(*ptrType).rtype @@ -1158,7 +1158,9 @@ func (t *rtype) ptrTo() *rtype { pp.ptrToThis = nil pp.elem = t - pi, _ := ptrMap.LoadOrStore(t, &pp) + q := toType(&pp.rtype).(*rtype) + p := (*ptrType)(unsafe.Pointer(q)) + pi, _ := ptrMap.LoadOrStore(t, p) return &pi.(*ptrType).rtype } @@ -1273,7 +1275,7 @@ func specialChannelAssignability(T, V *rtype) bool { // and the ideal constant rules (no ideal constants at run time). func directlyAssignable(T, V *rtype) bool { // x's type V is identical to T? - if T == V { + if rtypeEqual(T, V) { return true } @@ -1304,7 +1306,7 @@ func haveIdenticalType(T, V Type, cmpTags bool) bool { } func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool { - if T == V { + if rtypeEqual(T, V) { return true } @@ -1449,7 +1451,7 @@ func ChanOf(dir ChanDir, t Type) Type { s = "chan " + *typ.string } if tt := lookupType(s); tt != nil { - ch := (*chanType)(unsafe.Pointer(tt)) + ch := (*chanType)(unsafe.Pointer(toType(tt).(*rtype))) if ch.elem == typ && ch.dir == uintptr(dir) { ti, _ := lookupCache.LoadOrStore(ckey, tt) return ti.(Type) @@ -1481,7 +1483,7 @@ func ChanOf(dir ChanDir, t Type) Type { ch.uncommonType = nil ch.ptrToThis = nil - ti, _ := lookupCache.LoadOrStore(ckey, &ch.rtype) + ti, _ := lookupCache.LoadOrStore(ckey, toType(&ch.rtype).(*rtype)) return ti.(Type) } @@ -1508,7 +1510,7 @@ func MapOf(key, elem Type) Type { // Look in known types. s := "map[" + *ktyp.string + "]" + *etyp.string if tt := lookupType(s); tt != nil { - mt := (*mapType)(unsafe.Pointer(tt)) + mt := (*mapType)(unsafe.Pointer(toType(tt).(*rtype))) if mt.key == ktyp && mt.elem == etyp { ti, _ := lookupCache.LoadOrStore(ckey, tt) return ti.(Type) @@ -1559,7 +1561,7 @@ func MapOf(key, elem Type) Type { mt.flags |= 16 } - ti, _ := lookupCache.LoadOrStore(ckey, &mt.rtype) + ti, _ := lookupCache.LoadOrStore(ckey, toType(&mt.rtype).(*rtype)) return ti.(Type) } @@ -1648,7 +1650,7 @@ func FuncOf(in, out []Type, variadic bool) Type { ft.string = &str ft.uncommonType = nil ft.ptrToThis = nil - return addToCache(&ft.rtype) + return addToCache(toType(&ft.rtype).(*rtype)) } // funcStr builds a string representation of a funcType. @@ -1909,7 +1911,7 @@ func SliceOf(t Type) Type { // Look in known types. s := "[]" + *typ.string if tt := lookupType(s); tt != nil { - slice := (*sliceType)(unsafe.Pointer(tt)) + slice := (*sliceType)(unsafe.Pointer(toType(tt).(*rtype))) if slice.elem == typ { ti, _ := lookupCache.LoadOrStore(ckey, tt) return ti.(Type) @@ -1930,7 +1932,7 @@ func SliceOf(t Type) Type { slice.uncommonType = nil slice.ptrToThis = nil - ti, _ := lookupCache.LoadOrStore(ckey, &slice.rtype) + ti, _ := lookupCache.LoadOrStore(ckey, toType(&slice.rtype).(*rtype)) return ti.(Type) } @@ -2234,7 +2236,7 @@ func StructOf(fields []StructField) Type { typ.uncommonType = nil typ.ptrToThis = nil - return addToCache(&typ.rtype) + return addToCache(toType(&typ.rtype).(*rtype)) } // runtimeStructField takes a StructField value passed to StructOf and @@ -2330,7 +2332,7 @@ func ArrayOf(count int, elem Type) Type { // Look in known types. s := "[" + strconv.Itoa(count) + "]" + *typ.string if tt := lookupType(s); tt != nil { - array := (*arrayType)(unsafe.Pointer(tt)) + array := (*arrayType)(unsafe.Pointer(toType(tt).(*rtype))) if array.elem == typ { ti, _ := lookupCache.LoadOrStore(ckey, tt) return ti.(Type) @@ -2446,7 +2448,7 @@ func ArrayOf(count int, elem Type) Type { array.kind &^= kindDirectIface } - ti, _ := lookupCache.LoadOrStore(ckey, &array.rtype) + ti, _ := lookupCache.LoadOrStore(ckey, toType(&array.rtype).(*rtype)) return ti.(Type) } @@ -2458,16 +2460,6 @@ func appendVarint(x []byte, v uintptr) []byte { return x } -// toType converts from a *rtype to a Type that can be returned -// to the client of package reflect. The only concern is that -// a nil *rtype must be replaced by a nil Type. -func toType(p *rtype) Type { - if p == nil { - return nil - } - return p -} - // Look up a compiler-generated type descriptor. // Implemented in runtime. func lookupType(s string) *rtype diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go index e60f84f..64f7432 100644 --- a/libgo/go/reflect/value.go +++ b/libgo/go/reflect/value.go @@ -1785,7 +1785,7 @@ type SliceHeader struct { } func typesMustMatch(what string, t1, t2 Type) { - if t1 != t2 { + if !typeEqual(t1, t2) { panic(what + ": " + t1.String() + " != " + t2.String()) } } diff --git a/libgo/go/runtime/checkptr_test.go b/libgo/go/runtime/checkptr_test.go index 76aa2cd..bd2d00f 100644 --- a/libgo/go/runtime/checkptr_test.go +++ b/libgo/go/runtime/checkptr_test.go @@ -31,6 +31,7 @@ func TestCheckPtr(t *testing.T) { {"CheckPtrAlignmentPtr", "fatal error: checkptr: misaligned pointer conversion\n"}, {"CheckPtrAlignmentNoPtr", ""}, {"CheckPtrArithmetic", "fatal error: checkptr: pointer arithmetic result points to invalid allocation\n"}, + {"CheckPtrArithmetic2", "fatal error: checkptr: pointer arithmetic result points to invalid allocation\n"}, {"CheckPtrSize", "fatal error: checkptr: converted pointer straddles multiple allocations\n"}, {"CheckPtrSmall", "fatal error: checkptr: pointer arithmetic computed bad pointer value\n"}, } diff --git a/libgo/go/runtime/gcinfo_test.go b/libgo/go/runtime/gcinfo_test.go index ddbe5dd..c26f411 100644 --- a/libgo/go/runtime/gcinfo_test.go +++ b/libgo/go/runtime/gcinfo_test.go @@ -157,7 +157,7 @@ type BigStruct struct { func infoBigStruct() []byte { switch runtime.GOARCH { - case "386", "arm", "mips", "mipsle": + case "386", "arm", "mips", "mipsle", "riscv": return []byte{ typePointer, // q *int typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // w byte; e [17]byte diff --git a/libgo/go/runtime/hash32.go b/libgo/go/runtime/hash32.go index fba6bc3..89efc1c 100644 --- a/libgo/go/runtime/hash32.go +++ b/libgo/go/runtime/hash32.go @@ -6,7 +6,7 @@ // xxhash: https://code.google.com/p/xxhash/ // cityhash: https://code.google.com/p/cityhash/ -// +build 386 arm armbe m68k mips mipsle nios2 ppc s390 sh shbe sparc +// +build 386 arm armbe m68k mips mipsle nios2 ppc riscv s390 sh shbe sparc package runtime diff --git a/libgo/go/runtime/lfstack_32bit.go b/libgo/go/runtime/lfstack_32bit.go index 6da037e..b3194dc 100644 --- a/libgo/go/runtime/lfstack_32bit.go +++ b/libgo/go/runtime/lfstack_32bit.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build 386 amd64p32 arm armbe m68k mips mipsle mips64p32 mips64p32le nios2 ppc s390 sh shbe sparc +// +build 386 amd64p32 arm armbe m68k mips mipsle mips64p32 mips64p32le nios2 ppc riscv s390 sh shbe sparc package runtime diff --git a/libgo/go/runtime/lockrank_off.go b/libgo/go/runtime/lockrank_off.go index 425ca8d..32378a9 100644 --- a/libgo/go/runtime/lockrank_off.go +++ b/libgo/go/runtime/lockrank_off.go @@ -18,19 +18,29 @@ func getLockRank(l *mutex) lockRank { return 0 } +// The following functions may be called in nosplit context. +// Nosplit is not strictly required for lockWithRank, unlockWithRank +// and lockWithRankMayAcquire, but these nosplit annotations must +// be kept consistent with the equivalent functions in lockrank_on.go. + +//go:nosplit func lockWithRank(l *mutex, rank lockRank) { lock2(l) } +//go:nosplit func acquireLockRank(rank lockRank) { } +//go:nosplit func unlockWithRank(l *mutex) { unlock2(l) } +//go:nosplit func releaseLockRank(rank lockRank) { } +//go:nosplit func lockWithRankMayAcquire(l *mutex, rank lockRank) { } diff --git a/libgo/go/runtime/mkpreempt.go b/libgo/go/runtime/mkpreempt.go index 1fe7766..268941d 100644 --- a/libgo/go/runtime/mkpreempt.go +++ b/libgo/go/runtime/mkpreempt.go @@ -83,6 +83,7 @@ var arches = map[string]func(){ "mips64x": func() { genMIPS(true) }, "mipsx": func() { genMIPS(false) }, "ppc64x": genPPC64, + "riscv": genRISCV, "riscv64": genRISCV64, "s390x": genS390X, "wasm": genWasm, @@ -501,6 +502,11 @@ func genPPC64() { p("JMP (CTR)") } +func genRISCV() { + p("// No async preemption on riscv - see issue 36711") + p("UNDEF") +} + func genRISCV64() { // X0 (zero), X1 (LR), X2 (SP), X4 (g), X31 (TMP) are special. var l = layout{sp: "X2", stack: 8} diff --git a/libgo/go/runtime/mpagealloc_32bit.go b/libgo/go/runtime/mpagealloc_32bit.go index d18970c..249b5fe 100644 --- a/libgo/go/runtime/mpagealloc_32bit.go +++ b/libgo/go/runtime/mpagealloc_32bit.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build 386 arm mips mipsle wasm darwin,arm64 amd64p32 armbe m68k mips64p32 mips64p32le nios2 ppc s390 sh shbe sparc +// +build 386 arm mips mipsle wasm darwin,arm64 amd64p32 armbe m68k mips64p32 mips64p32le nios2 ppc riscv s390 sh shbe sparc // wasm is a treated as a 32-bit architecture for the purposes of the page // allocator, even though it has 64-bit pointers. This is because any wasm diff --git a/libgo/go/runtime/os_aix.go b/libgo/go/runtime/os_aix.go index b337330..f49b83c 100644 --- a/libgo/go/runtime/os_aix.go +++ b/libgo/go/runtime/os_aix.go @@ -21,6 +21,10 @@ type mOS struct { waitsema uintptr // semaphore for parking on locks } +func getProcID() uint64 { + return uint64(gettid()) +} + //extern malloc func libc_malloc(uintptr) unsafe.Pointer @@ -46,7 +50,7 @@ func clock_gettime(clock_id int64, timeout *timespec) int32 //go:nosplit func semacreate(mp *m) { - if mp.mos.waitsema != 0 { + if mp.waitsema != 0 { return } @@ -59,7 +63,7 @@ func semacreate(mp *m) { if sem_init(sem, 0, 0) != 0 { throw("sem_init") } - mp.mos.waitsema = uintptr(unsafe.Pointer(sem)) + mp.waitsema = uintptr(unsafe.Pointer(sem)) } //go:nosplit @@ -85,7 +89,7 @@ func semasleep(ns int64) int32 { ts.tv_sec = timespec_sec_t(sec) ts.tv_nsec = timespec_nsec_t(nsec) - if sem_timedwait((*semt)(unsafe.Pointer(_m_.mos.waitsema)), &ts) != 0 { + if sem_timedwait((*semt)(unsafe.Pointer(_m_.waitsema)), &ts) != 0 { err := errno() if err == _ETIMEDOUT || err == _EAGAIN || err == _EINTR { return -1 @@ -96,7 +100,7 @@ func semasleep(ns int64) int32 { return 0 } for { - r1 := sem_wait((*semt)(unsafe.Pointer(_m_.mos.waitsema))) + r1 := sem_wait((*semt)(unsafe.Pointer(_m_.waitsema))) if r1 == 0 { break } @@ -110,7 +114,7 @@ func semasleep(ns int64) int32 { //go:nosplit func semawakeup(mp *m) { - if sem_post((*semt)(unsafe.Pointer(mp.mos.waitsema))) != 0 { + if sem_post((*semt)(unsafe.Pointer(mp.waitsema))) != 0 { throw("sem_post") } } @@ -128,7 +132,6 @@ const ( const ( // getsystemcfg constants - _SC_IMPL = 2 _IMPL_POWER8 = 0x10000 _IMPL_POWER9 = 0x20000 ) diff --git a/libgo/go/runtime/os_gccgo.go b/libgo/go/runtime/os_gccgo.go index ab19022..a8859c0 100644 --- a/libgo/go/runtime/os_gccgo.go +++ b/libgo/go/runtime/os_gccgo.go @@ -27,8 +27,7 @@ func mpreinit(mp *m) { func minit() { minitSignals() - // FIXME: only works on linux for now. - getg().m.procid = uint64(gettid()) + getg().m.procid = getProcID() } // Called from dropm to undo the effect of an minit. diff --git a/libgo/go/runtime/os_hurd.go b/libgo/go/runtime/os_hurd.go index b3c6f80..1613b41 100644 --- a/libgo/go/runtime/os_hurd.go +++ b/libgo/go/runtime/os_hurd.go @@ -18,6 +18,10 @@ type mOS struct { waitsema uintptr // semaphore for parking on locks } +func getProcID() uint64 { + return uint64(gettid()) +} + //extern malloc func libc_malloc(uintptr) unsafe.Pointer diff --git a/libgo/go/runtime/os_linux.go b/libgo/go/runtime/os_linux.go index 5d55064..627b6d6 100644 --- a/libgo/go/runtime/os_linux.go +++ b/libgo/go/runtime/os_linux.go @@ -13,6 +13,10 @@ type mOS struct { unused byte } +func getProcID() uint64 { + return uint64(gettid()) +} + func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32 { return int32(syscall(_SYS_futex, uintptr(addr), uintptr(op), uintptr(val), uintptr(ts), uintptr(addr2), uintptr(val3))) } diff --git a/libgo/go/runtime/os_netbsd.go b/libgo/go/runtime/os_netbsd.go index 69d2c71..9ebb652 100644 --- a/libgo/go/runtime/os_netbsd.go +++ b/libgo/go/runtime/os_netbsd.go @@ -14,25 +14,25 @@ type mOS struct { waitsemacount uint32 } +func getProcID() uint64 { + return uint64(lwp_self()) +} + +//extern _lwp_self +func lwp_self() int32 + //go:noescape -//extern lwp_park +//extern _lwp_park func lwp_park(ts int32, rel int32, abstime *timespec, unpark int32, hint, unparkhint unsafe.Pointer) int32 //go:noescape -//extern lwp_unpark +//extern _lwp_unpark func lwp_unpark(lwp int32, hint unsafe.Pointer) int32 //go:noescape //extern sysctl func sysctl(*uint32, uint32, *byte, *uintptr, *byte, uintptr) int32 -// From NetBSD's <sys/sysctl.h> -const ( - _CTL_HW = 6 - _HW_NCPU = 3 - _HW_PAGESIZE = 7 -) - func getncpu() int32 { mib := [2]uint32{_CTL_HW, _HW_NCPU} out := uint32(0) @@ -88,7 +88,7 @@ func semasleep(ns int64) int32 { tsp = &ts } ret := lwp_park(_CLOCK_MONOTONIC, _TIMER_RELTIME, tsp, 0, unsafe.Pointer(&_g_.m.waitsemacount), nil) - if ret == _ETIMEDOUT { + if ret != 0 && errno() == _ETIMEDOUT { return -1 } } @@ -101,10 +101,10 @@ func semawakeup(mp *m) { // "If the target LWP is not currently waiting, it will return // immediately upon the next call to _lwp_park()." ret := lwp_unpark(int32(mp.procid), unsafe.Pointer(&mp.waitsemacount)) - if ret != 0 && ret != _ESRCH { + if ret != 0 && errno() != _ESRCH { // semawakeup can be called on signal stack. systemstack(func() { - print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " ret=", ret, "\n") + print("thrwakeup addr=", &mp.waitsemacount, " sem=", mp.waitsemacount, " errno=", errno(), "\n") }) } } diff --git a/libgo/go/runtime/os_solaris.go b/libgo/go/runtime/os_solaris.go index 63b5cd7..c568629 100644 --- a/libgo/go/runtime/os_solaris.go +++ b/libgo/go/runtime/os_solaris.go @@ -10,6 +10,10 @@ type mOS struct { waitsema uintptr // semaphore for parking on locks } +func getProcID() uint64 { + return uint64(gettid()) +} + //extern malloc func libc_malloc(uintptr) unsafe.Pointer diff --git a/libgo/go/runtime/testdata/testprog/checkptr.go b/libgo/go/runtime/testdata/testprog/checkptr.go index 45e6fb1..e0a2794 100644 --- a/libgo/go/runtime/testdata/testprog/checkptr.go +++ b/libgo/go/runtime/testdata/testprog/checkptr.go @@ -10,6 +10,7 @@ func init() { register("CheckPtrAlignmentNoPtr", CheckPtrAlignmentNoPtr) register("CheckPtrAlignmentPtr", CheckPtrAlignmentPtr) register("CheckPtrArithmetic", CheckPtrArithmetic) + register("CheckPtrArithmetic2", CheckPtrArithmetic2) register("CheckPtrSize", CheckPtrSize) register("CheckPtrSmall", CheckPtrSmall) } @@ -32,6 +33,13 @@ func CheckPtrArithmetic() { sink2 = (*int)(unsafe.Pointer(i)) } +func CheckPtrArithmetic2() { + var x [2]int64 + p := unsafe.Pointer(&x[1]) + var one uintptr = 1 + sink2 = unsafe.Pointer(uintptr(p) & ^one) +} + func CheckPtrSize() { p := new(int64) sink2 = p diff --git a/libgo/go/sync/map.go b/libgo/go/sync/map.go index a61e2eb..9ad2535 100644 --- a/libgo/go/sync/map.go +++ b/libgo/go/sync/map.go @@ -274,6 +274,7 @@ func (m *Map) LoadAndDelete(key interface{}) (value interface{}, loaded bool) { e, ok = read.m[key] if !ok && read.amended { e, ok = m.dirty[key] + delete(m.dirty, key) // Regardless of whether the entry was present, record a miss: this key // will take the slow path until the dirty map is promoted to the read // map. diff --git a/libgo/go/sync/map_test.go b/libgo/go/sync/map_test.go index 4ae989a..7f163ca 100644 --- a/libgo/go/sync/map_test.go +++ b/libgo/go/sync/map_test.go @@ -9,6 +9,7 @@ import ( "reflect" "runtime" "sync" + "sync/atomic" "testing" "testing/quick" ) @@ -171,3 +172,26 @@ func TestConcurrentRange(t *testing.T) { } } } + +func TestIssue40999(t *testing.T) { + var m sync.Map + + // Since the miss-counting in missLocked (via Delete) + // compares the miss count with len(m.dirty), + // add an initial entry to bias len(m.dirty) above the miss count. + m.Store(nil, struct{}{}) + + var finalized uint32 + + // Set finalizers that count for collected keys. A non-zero count + // indicates that keys have not been leaked. + for atomic.LoadUint32(&finalized) == 0 { + p := new(int) + runtime.SetFinalizer(p, func(*int) { + atomic.AddUint32(&finalized, 1) + }) + m.Store(p, struct{}{}) + m.Delete(p) + runtime.GC() + } +} diff --git a/libgo/go/syscall/endian_little.go b/libgo/go/syscall/endian_little.go index 0cd2d75..22cac17 100644 --- a/libgo/go/syscall/endian_little.go +++ b/libgo/go/syscall/endian_little.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // -// +build 386 alpha amd64 amd64p32 arm arm64 ia64 mips64le mipsle mips64p32le nios2 ppc64le riscv64 sh wasm +// +build 386 alpha amd64 amd64p32 arm arm64 ia64 mips64le mipsle mips64p32le nios2 ppc64le riscv riscv64 sh wasm package syscall diff --git a/libgo/go/syscall/exec_bsd.go b/libgo/go/syscall/exec_bsd.go index 7e06943..ca7fdc0 100644 --- a/libgo/go/syscall/exec_bsd.go +++ b/libgo/go/syscall/exec_bsd.go @@ -93,7 +93,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr // Enable tracing if requested. if sys.Ptrace { - err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil) + err1 = raw_ptrace(_PTRACE_TRACEME, 0, 0, 0) if err1 != 0 { goto childerror } diff --git a/libgo/go/syscall/exec_linux.go b/libgo/go/syscall/exec_linux.go index 2f0a34f..3897581 100644 --- a/libgo/go/syscall/exec_linux.go +++ b/libgo/go/syscall/exec_linux.go @@ -538,7 +538,7 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att // Do this right before exec so that we don't unnecessarily trace the runtime // setting up after the fork. See issue #21428. if sys.Ptrace { - err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil) + err1 = raw_ptrace(_PTRACE_TRACEME, 0, 0, 0) if err1 != 0 { goto childerror } diff --git a/libgo/go/syscall/exec_stubs.go b/libgo/go/syscall/exec_stubs.go index e95b415..c837cf7 100644 --- a/libgo/go/syscall/exec_stubs.go +++ b/libgo/go/syscall/exec_stubs.go @@ -30,6 +30,6 @@ func (w WaitStatus) Signal() int { return 0 } func (w WaitStatus) StopSignal() int { return 0 } func (w WaitStatus) TrapCause() int { return 0 } -func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno { +func raw_ptrace(request int, pid int, addr uintptr, data uintptr) Errno { return ENOSYS } diff --git a/libgo/go/syscall/export_aix_test.go b/libgo/go/syscall/export_aix_test.go new file mode 100644 index 0000000..044337b --- /dev/null +++ b/libgo/go/syscall/export_aix_test.go @@ -0,0 +1,16 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build aix + +package syscall + +import ( + "unsafe" +) + +func Ioctl(fd, req, arg uintptr) (err Errno) { + _, err = raw_ioctl_ptr(int(fd), req, unsafe.Pointer(arg)) + return err +} diff --git a/libgo/go/syscall/export_unix_test.go b/libgo/go/syscall/export_unix_test.go index dc11f45..4d67be9 100644 --- a/libgo/go/syscall/export_unix_test.go +++ b/libgo/go/syscall/export_unix_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris +// +build darwin dragonfly freebsd hurd linux netbsd openbsd solaris package syscall diff --git a/libgo/go/syscall/libcall_aix.go b/libgo/go/syscall/libcall_aix.go index 8d9f59e..92c7f3c 100644 --- a/libgo/go/syscall/libcall_aix.go +++ b/libgo/go/syscall/libcall_aix.go @@ -16,13 +16,10 @@ const SYS_EXECVE = 0 //sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) //open64at(dirfd _C_int, path *byte, flags _C_int, mode Mode_t) _C_int -//sys ptrace(request int, id int, addr uintptr, data int, buff uintptr) (val int) -//ptrace(request _C_int, id int, addr uintptr, data _C_int, buff *byte) _C_int - //sys ptrace64(request int, id int64, addr int64, data int, buff uintptr) (err error) //ptrace64(request _C_int, id int64, addr int64, data _C_int, buff *byte) _C_int -func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno { +func raw_ptrace(request int, pid int, addr uintptr, data uintptr) Errno { if request == _PTRACE_TRACEME { // Convert to AIX ptrace call. err := ptrace64(_PT_TRACE_ME, 0, 0, 0, 0) diff --git a/libgo/go/syscall/libcall_bsd_regfile.go b/libgo/go/syscall/libcall_bsd_regfile.go index 388c8a7..0b9d01f 100644 --- a/libgo/go/syscall/libcall_bsd_regfile.go +++ b/libgo/go/syscall/libcall_bsd_regfile.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin dragonfly freebsd netbsd openbsd solaris,amd64 solaris,sparc64 +// +build darwin dragonfly freebsd openbsd solaris,amd64 solaris,sparc64 package syscall diff --git a/libgo/go/syscall/libcall_bsd.go b/libgo/go/syscall/libcall_bsd_sendfile.go index 93f5710..295a1f4 100644 --- a/libgo/go/syscall/libcall_bsd.go +++ b/libgo/go/syscall/libcall_bsd_sendfile.go @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin dragonfly freebsd netbsd openbsd solaris +// +build darwin dragonfly freebsd openbsd solaris -// BSD library calls. +// BSD sendfile support. package syscall diff --git a/libgo/go/syscall/libcall_glibc.go b/libgo/go/syscall/libcall_glibc.go index 823343d..a32d696 100644 --- a/libgo/go/syscall/libcall_glibc.go +++ b/libgo/go/syscall/libcall_glibc.go @@ -31,9 +31,6 @@ func Futimes(fd int, tv []Timeval) (err error) { return Utimes("/proc/self/fd/"+itoa(fd), tv) } -//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) -//__go_ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long - //sys accept4(fd int, sa *RawSockaddrAny, len *Socklen_t, flags int) (nfd int, err error) //accept4(fd _C_int, sa *RawSockaddrAny, len *Socklen_t, flags _C_int) _C_int diff --git a/libgo/go/syscall/libcall_hurd.go b/libgo/go/syscall/libcall_hurd.go index f0e038c..44ff46d 100644 --- a/libgo/go/syscall/libcall_hurd.go +++ b/libgo/go/syscall/libcall_hurd.go @@ -7,7 +7,7 @@ package syscall // Dummy function -func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno { +func raw_ptrace(request int, pid int, addr uintptr, data uintptr) Errno { return ENOSYS } diff --git a/libgo/go/syscall/libcall_irix.go b/libgo/go/syscall/libcall_irix.go index 9b6cdcc..9880766 100644 --- a/libgo/go/syscall/libcall_irix.go +++ b/libgo/go/syscall/libcall_irix.go @@ -6,5 +6,5 @@ package syscall -//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno) +//sysnb raw_ptrace(request int, pid int, addr uintptr, data uintptr) (err Errno) //ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long diff --git a/libgo/go/syscall/libcall_linux.go b/libgo/go/syscall/libcall_linux.go index 78fda0e..96974bd 100644 --- a/libgo/go/syscall/libcall_linux.go +++ b/libgo/go/syscall/libcall_linux.go @@ -10,7 +10,10 @@ import ( "unsafe" ) -//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno) +//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err Errno) +//__go_ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long + +//sysnb raw_ptrace(request int, pid int, addr uintptr, data uintptr) (err Errno) //__go_ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, err error) { diff --git a/libgo/go/syscall/libcall_solaris_386.go b/libgo/go/syscall/libcall_solaris_386.go index 20eba22..ef86f09 100644 --- a/libgo/go/syscall/libcall_solaris_386.go +++ b/libgo/go/syscall/libcall_solaris_386.go @@ -8,5 +8,5 @@ package syscall //sysnb Uname(buf *Utsname) (err error) //_nuname(buf *Utsname) _C_int -//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno) +//sysnb raw_ptrace(request int, pid int, addr uintptr, data uintptr) (err Errno) //ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long diff --git a/libgo/go/syscall/libcall_solaris_amd64.go b/libgo/go/syscall/libcall_solaris_amd64.go index 69b11ba..f44025e 100644 --- a/libgo/go/syscall/libcall_solaris_amd64.go +++ b/libgo/go/syscall/libcall_solaris_amd64.go @@ -5,6 +5,6 @@ package syscall // 64-bit ptrace(3C) doesn't exist -func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno { +func raw_ptrace(request int, pid int, addr uintptr, data uintptr) Errno { return ENOSYS } diff --git a/libgo/go/syscall/libcall_solaris_sparc.go b/libgo/go/syscall/libcall_solaris_sparc.go index 50863fa..3d50309 100644 --- a/libgo/go/syscall/libcall_solaris_sparc.go +++ b/libgo/go/syscall/libcall_solaris_sparc.go @@ -4,5 +4,5 @@ package syscall -//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (err Errno) +//sysnb raw_ptrace(request int, pid int, addr uintptr, data uintptr) (err Errno) //ptrace(request _C_int, pid Pid_t, addr *byte, data *byte) _C_long diff --git a/libgo/go/syscall/libcall_solaris_sparc64.go b/libgo/go/syscall/libcall_solaris_sparc64.go index 69b11ba..f44025e 100644 --- a/libgo/go/syscall/libcall_solaris_sparc64.go +++ b/libgo/go/syscall/libcall_solaris_sparc64.go @@ -5,6 +5,6 @@ package syscall // 64-bit ptrace(3C) doesn't exist -func raw_ptrace(request int, pid int, addr *byte, data *byte) Errno { +func raw_ptrace(request int, pid int, addr uintptr, data uintptr) Errno { return ENOSYS } diff --git a/libgo/go/syscall/route_bsd.go b/libgo/go/syscall/route_bsd.go index b364eea..0c32594 100644 --- a/libgo/go/syscall/route_bsd.go +++ b/libgo/go/syscall/route_bsd.go @@ -18,7 +18,7 @@ var ( // Round the length of a raw sockaddr up to align it properly. func rsaAlignOf(salen int) int { - salign := sizeofPtr + salign := int(sizeofPtr) if darwin64Bit { // Darwin kernels require 32-bit aligned access to // routing facilities. diff --git a/libgo/go/syscall/socket_bsd.go b/libgo/go/syscall/socket_bsd.go index f62457f..b230a32 100644 --- a/libgo/go/syscall/socket_bsd.go +++ b/libgo/go/syscall/socket_bsd.go @@ -13,6 +13,7 @@ import "unsafe" const SizeofSockaddrInet4 = 16 const SizeofSockaddrInet6 = 28 const SizeofSockaddrUnix = 110 +const SizeofSockaddrDatalink = 20 type RawSockaddrInet4 struct { Len uint8 @@ -52,13 +53,19 @@ func (sa *RawSockaddrUnix) setLen(n int) { } func (sa *RawSockaddrUnix) getLen() (int, error) { - if sa.Len < 3 || sa.Len > SizeofSockaddrUnix { + if sa.Len < 2 || sa.Len > SizeofSockaddrUnix { return 0, EINVAL } - n := int(sa.Len) - 3 // subtract leading Family, Len, terminating NUL. + + // Some BSDs include the trailing NUL in the length, whereas + // others do not. Work around this by subtracting the leading + // family and len. The path is then scanned to see if a NUL + // terminator still exists within the length. + n := int(sa.Len) - 2 // subtract leading Family, Len for i := 0; i < n; i++ { if sa.Path[i] == 0 { - // found early NUL; assume Len is overestimating. + // found early NUL; assume Len included the NUL + // or was overestimating. n = i break } @@ -70,6 +77,46 @@ func (sa *RawSockaddrUnix) adjustAbstract(sl Socklen_t) Socklen_t { return sl } +type SockaddrDatalink struct { + Len uint8 + Family uint8 + Index uint16 + Type uint8 + Nlen uint8 + Alen uint8 + Slen uint8 + Data [12]int8 + raw RawSockaddrDatalink +} + +func (sa *SockaddrDatalink) sockaddr() (*RawSockaddrAny, Socklen_t, error) { + if sa.Index == 0 { + return nil, 0, EINVAL + } + sa.raw.Len = sa.Len + sa.raw.Family = AF_LINK + sa.raw.Index = sa.Index + sa.raw.Type = sa.Type + sa.raw.Nlen = sa.Nlen + sa.raw.Alen = sa.Alen + sa.raw.Slen = sa.Slen + for i := 0; i < len(sa.raw.Data); i++ { + sa.raw.Data[i] = sa.Data[i] + } + return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrDatalink, nil +} + +type RawSockaddrDatalink struct { + Len uint8 + Family uint8 + Index uint16 + Type uint8 + Nlen uint8 + Alen uint8 + Slen uint8 + Data [12]int8 +} + type RawSockaddr struct { Len uint8 Family uint8 diff --git a/libgo/go/syscall/syscall_aix_ppc.go b/libgo/go/syscall/syscall_aix_ppc.go index 83ed1e6..23333e8 100644 --- a/libgo/go/syscall/syscall_aix_ppc.go +++ b/libgo/go/syscall/syscall_aix_ppc.go @@ -8,6 +8,9 @@ package syscall import "unsafe" +//sys ptrace(request int, id int, addr uintptr, data int, buff uintptr) (val int) +//ptrace(request _C_int, id int, addr uintptr, data _C_int, buff *byte) _C_int + // AIX does not define a specific structure but instead uses separate // ptrace calls for the different registers. type PtraceRegs struct { diff --git a/libgo/go/syscall/syscall_netbsd.go b/libgo/go/syscall/syscall_netbsd.go index c67550a..bbc6799 100644 --- a/libgo/go/syscall/syscall_netbsd.go +++ b/libgo/go/syscall/syscall_netbsd.go @@ -17,3 +17,64 @@ func direntReclen(buf []byte) (uint64, bool) { func direntNamlen(buf []byte) (uint64, bool) { return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen)) } + +func sysctlNodes(mib []_C_int) (nodes []Sysctlnode, err error) { + var olen uintptr + + // Get a list of all sysctl nodes below the given MIB by performing + // a sysctl for the given MIB with CTL_QUERY appended. + mib = append(mib, CTL_QUERY) + qnode := Sysctlnode{Flags: SYSCTL_VERS_1} + qp := (*byte)(unsafe.Pointer(&qnode)) + sz := unsafe.Sizeof(qnode) + if err = sysctl(mib, nil, &olen, qp, sz); err != nil { + return nil, err + } + + // Now that we know the size, get the actual nodes. + nodes = make([]Sysctlnode, olen/sz) + np := (*byte)(unsafe.Pointer(&nodes[0])) + if err = sysctl(mib, np, &olen, qp, sz); err != nil { + return nil, err + } + + return nodes, nil +} + +func nametomib(name string) (mib []_C_int, err error) { + // Split name into components. + var parts []string + last := 0 + for i := 0; i < len(name); i++ { + if name[i] == '.' { + parts = append(parts, name[last:i]) + last = i + 1 + } + } + parts = append(parts, name[last:]) + + // Discover the nodes and construct the MIB OID. + for partno, part := range parts { + nodes, err := sysctlNodes(mib) + if err != nil { + return nil, err + } + for _, node := range nodes { + n := make([]byte, 0) + for i := range node.Name { + if node.Name[i] != 0 { + n = append(n, byte(node.Name[i])) + } + } + if string(n) == part { + mib = append(mib, _C_int(node.Num)) + break + } + } + if len(mib) != partno+1 { + return nil, EINVAL + } + } + + return mib, nil +} diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go index dee77f7..fe6929d 100644 --- a/libgo/go/testing/testing.go +++ b/libgo/go/testing/testing.go @@ -357,10 +357,19 @@ func (p *testPrinter) Fprint(w io.Writer, testName, out string) { defer p.lastNameMu.Unlock() if !p.chatty || - strings.HasPrefix(out, "--- PASS") || - strings.HasPrefix(out, "--- FAIL") || - strings.HasPrefix(out, "=== CONT") || - strings.HasPrefix(out, "=== RUN") { + strings.HasPrefix(out, "--- PASS: ") || + strings.HasPrefix(out, "--- FAIL: ") || + strings.HasPrefix(out, "--- SKIP: ") || + strings.HasPrefix(out, "=== RUN ") || + strings.HasPrefix(out, "=== CONT ") || + strings.HasPrefix(out, "=== PAUSE ") { + // If we're buffering test output (!p.chatty), we don't really care which + // test is emitting which line so long as they are serialized. + // + // If the message already implies an association with a specific new test, + // we don't need to check what the old test name was or log an extra CONT + // line for it. (We're updating it anyway, and the current message already + // includes the test name.) p.lastName = testName fmt.Fprint(w, out) return @@ -887,11 +896,15 @@ func (c *common) Cleanup(f func()) { c.cleanup = func() { if oldCleanup != nil { defer func() { + c.mu.Lock() c.cleanupPc = oldCleanupPc + c.mu.Unlock() oldCleanup() }() } + c.mu.Lock() c.cleanupName = callerName(0) + c.mu.Unlock() f() } var pc [maxStackLen]uintptr @@ -1012,7 +1025,13 @@ func (t *T) Parallel() { for ; root.parent != nil; root = root.parent { } root.mu.Lock() - fmt.Fprintf(root.w, "=== PAUSE %s\n", t.name) + // Unfortunately, even though PAUSE indicates that the named test is *no + // longer* running, cmd/test2json interprets it as changing the active test + // for the purpose of log parsing. We could fix cmd/test2json, but that + // won't fix existing deployments of third-party tools that already shell + // out to older builds of cmd/test2json — so merely fixing cmd/test2json + // isn't enough for now. + printer.Fprint(root.w, t.name, fmt.Sprintf("=== PAUSE %s\n", t.name)) root.mu.Unlock() } diff --git a/libgo/match.sh b/libgo/match.sh index cd35942..04db8d2 100755 --- a/libgo/match.sh +++ b/libgo/match.sh @@ -116,7 +116,7 @@ for f in $gofiles; do aix | android | darwin | dragonfly | freebsd | illumos | hurd | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows) tag1=nonmatchingtag ;; - 386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm) + 386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm) tag1=nonmatchingtag ;; esac @@ -128,7 +128,7 @@ for f in $gofiles; do aix | android | darwin | dragonfly | freebsd | hurd | illumos | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows) tag2=nonmatchingtag ;; - 386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm) + 386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm) tag2=nonmatchingtag ;; esac @@ -151,18 +151,18 @@ for f in $gofiles; do fi match=false ;; - $goos | $goarch | $cgotag | $cmdlinetag | "gccgo" | go1.[0-9]) + $goos | $goarch | $cgotag | $cmdlinetag | "gccgo" | go1.[0-9] | go1.[0-9][0-9]) match=true ;; - "!"$goos | "!"$goarch | "!"$cgotag | "!"$cmdlinetag | "!gccgo" | "!"go1.[0-9]) + "!"$goos | "!"$goarch | "!"$cgotag | "!"$cmdlinetag | "!gccgo" | "!"go1.[0-9] | "!"go1.[0-9][0-9]) ;; *,*) cmatch=true for ctag in `echo $tag | sed -e 's/,/ /g'`; do case $ctag in - $goos | $goarch | $cgotag | $cmdlinetag | "gccgo" | go1.[0-9]) + $goos | $goarch | $cgotag | $cmdlinetag | "gccgo" | go1.[0-9] | go1.[0-9][0-9]) ;; - "!"$goos | "!"$goarch | "!"$cgotag | "!"$cmdlinetag | "!gccgo" | "!"go1.[0-9]) + "!"$goos | "!"$goarch | "!"$cgotag | "!"$cmdlinetag | "!gccgo" | "!"go1.[0-9] | "!"go1.[0-9][0-9]) cmatch=false ;; "!"*) diff --git a/libgo/merge.sh b/libgo/merge.sh index bddb132..f8de950 100755 --- a/libgo/merge.sh +++ b/libgo/merge.sh @@ -128,7 +128,7 @@ echo ${rev} > VERSION (cd ${NEWDIR}/src && find . -name '*.go' -print) | while read f; do skip=false case "$f" in - ./cmd/buildid/* | ./cmd/cgo/* | ./cmd/go/* | ./cmd/gofmt/* | ./cmd/testjson/* | ./cmd/vet/* | ./cmd/internal/browser/* | ./cmd/internal/buildid/* | ./cmd/internal/edit/* | ./cmd/internal/objabi/* | ./cmd/internal/testj2on/* | ./cmd/internal/sys/* | ./cmd/vendor/golang.org/x/tools/* | ./cmd/vendor/golang.org/x/mod/* | ./cmd/vendor/golang.org/x/xerrors/* | ./cmd/vendor/golang.org/x/crypto/ed25519) + ./cmd/buildid/* | ./cmd/cgo/* | ./cmd/go/* | ./cmd/gofmt/* | ./cmd/test2json/* | ./cmd/vet/* | ./cmd/internal/browser/* | ./cmd/internal/buildid/* | ./cmd/internal/edit/* | ./cmd/internal/objabi/* | ./cmd/internal/test2json/* | ./cmd/internal/sys/* | ./cmd/vendor/golang.org/x/tools/* | ./cmd/vendor/golang.org/x/mod/* | ./cmd/vendor/golang.org/x/xerrors/* | ./cmd/vendor/golang.org/x/crypto/ed25519) ;; ./cmd/*) skip=true @@ -150,7 +150,7 @@ done (cd ${NEWDIR}/src && find . -name testdata -print) | while read d; do skip=false case "$d" in - ./cmd/buildid/* | ./cmd/cgo/* | ./cmd/go/* | ./cmd/gofmt/* | ./cmd/testjson/* | ./cmd/vet/* | ./cmd/internal/browser/* | ./cmd/internal/buildid/* | ./cmd/internal/diff/* | ./cmd/internal/edit/* | ./cmd/internal/objabi/* | ./cmd/internal/testj2on/* | ./cmd/internal/sys/* | ./cmd/vendor/golang.org/x/tools/*) + ./cmd/buildid/* | ./cmd/cgo/* | ./cmd/go/* | ./cmd/gofmt/* | ./cmd/test2json/* | ./cmd/vet/* | ./cmd/internal/browser/* | ./cmd/internal/buildid/* | ./cmd/internal/diff/* | ./cmd/internal/edit/* | ./cmd/internal/objabi/* | ./cmd/internal/test2json/* | ./cmd/internal/sys/* | ./cmd/vendor/golang.org/x/tools/*) ;; ./cmd/*) skip=true diff --git a/libgo/misc/cgo/testcshared/testdata/libgo2/dup2.go b/libgo/misc/cgo/testcshared/testdata/libgo2/dup2.go index d343aa5..3b53e1c 100644 --- a/libgo/misc/cgo/testcshared/testdata/libgo2/dup2.go +++ b/libgo/misc/cgo/testcshared/testdata/libgo2/dup2.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin dragonfly freebsd linux,!arm64,!riscv64 netbsd openbsd +// +build darwin dragonfly freebsd linux,!arm64,!riscv,!riscv64 netbsd openbsd package main diff --git a/libgo/misc/cgo/testcshared/testdata/libgo2/dup3.go b/libgo/misc/cgo/testcshared/testdata/libgo2/dup3.go index 459f0dc..79a3773 100644 --- a/libgo/misc/cgo/testcshared/testdata/libgo2/dup3.go +++ b/libgo/misc/cgo/testcshared/testdata/libgo2/dup3.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux,arm64 linux,riscv64 +// +build linux,arm64 linux,riscv,riscv64 package main diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh index bd2ba32..deac5ce 100755 --- a/libgo/mksysinfo.sh +++ b/libgo/mksysinfo.sh @@ -225,6 +225,22 @@ if ! grep '^const _AT_FDCWD = ' ${OUT} >/dev/null 2>&1; then echo "const _AT_FDCWD = -100" >> ${OUT} fi +# sysctl constants. +grep '^const _CTL' gen-sysinfo.go | + sed -e 's/^\(const \)_\(CTL[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} + grep '^const _SYSCTL' gen-sysinfo.go | + sed -e 's/^\(const \)_\(SYSCTL[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} + grep '^const _NET_RT' gen-sysinfo.go | + sed -e 's/^\(const \)_\(NET_RT[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} + +# The sysctlnode struct. +grep '^type _sysctlnode ' gen-sysinfo.go | \ + sed -e 's/_sysctlnode/Sysctlnode/' \ + -e 's/sysctl_flags/Flags/' \ + -e 's/sysctl_name/Name/' \ + -e 's/sysctl_num/Num/' \ + >> ${OUT} + # sysconf constants. grep '^const __SC' gen-sysinfo.go | sed -e 's/^\(const \)__\(SC[^= ]*\)\(.*\)$/\1\2 = __\2/' >> ${OUT} @@ -491,6 +507,13 @@ if grep 'define st_dev st_fsid' gen-sysinfo.go > /dev/null 2>&1; then st_dev='-e s/st_fsid/Dev/' fi +# For historical reasons Go uses the suffix "timespec" instead of "tim" for +# stat_t's time fields on NetBSD. +st_times='-e s/st_atim/Atim/ -e s/st_mtim/Mtim/ -e s/st_ctim/Ctim/' +if test "${GOOS}" = "netbsd"; then + st_times='-e s/st_atim/Atimespec/ -e s/st_mtim/Mtimespec/ -e s/st_ctim/Ctimespec/' +fi + # The stat type. # Prefer largefile variant if available. stat=`grep '^type _stat64 ' gen-sysinfo.go || true` @@ -501,6 +524,7 @@ else fi | sed -e 's/type _stat64/type Stat_t/' \ -e 's/type _stat/type Stat_t/' \ ${st_dev} \ + ${st_times} \ -e 's/st_ino/Ino/g' \ -e 's/st_nlink/Nlink/' \ -e 's/st_mode/Mode/' \ @@ -510,9 +534,6 @@ fi | sed -e 's/type _stat64/type Stat_t/' \ -e 's/st_size/Size/' \ -e 's/st_blksize/Blksize/' \ -e 's/st_blocks/Blocks/' \ - -e 's/st_atim/Atim/' \ - -e 's/st_mtim/Mtim/' \ - -e 's/st_ctim/Ctim/' \ -e 's/\([^a-zA-Z0-9_]\)_timeval\([^a-zA-Z0-9_]\)/\1Timeval\2/g' \ -e 's/\([^a-zA-Z0-9_]\)_timespec_t\([^a-zA-Z0-9_]\)/\1Timespec\2/g' \ -e 's/\([^a-zA-Z0-9_]\)_st_timespec_t\([^a-zA-Z0-9_]\)/\1StTimespec\2/g' \ @@ -533,6 +554,7 @@ fi | sed -e 's/type _dirent64/type Dirent/' \ -e 's/d_name \[0+1\]/d_name [0+256]/' \ -e 's/d_name/Name/' \ -e 's/]int8/]byte/' \ + -e 's/d_fileno/Fileno/' \ -e 's/d_ino/Ino/' \ -e 's/d_namlen/Namlen/' \ -e 's/d_off/Off/' \ @@ -994,6 +1016,39 @@ grep '^type _rtgenmsg ' gen-sysinfo.go | \ -e 's/rtgen_family/Family/' \ >> ${OUT} +# The rt_msghdr struct. +grep '^type _rt_msghdr ' gen-sysinfo.go | \ + sed -e 's/_rt_msghdr/RtMsghdr/g' \ + -e 's/rtm_msglen/Msglen/' \ + -e 's/rtm_version/Version/' \ + -e 's/rtm_type/Type/' \ + -e 's/rtm_index/Index/' \ + -e 's/rtm_flags/Flags/' \ + -e 's/rtm_addrs/Addrs/' \ + -e 's/rtm_pid/Pid/' \ + -e 's/rtm_seq/Seq/' \ + -e 's/rtm_errno/Errno/' \ + -e 's/rtm_use/Use/' \ + -e 's/rtm_inits/Inits/' \ + -e 's/rtm_rmx/Rmx/' \ + -e 's/_rt_metrics/RtMetrics/' \ + >> ${OUT} + +# The rt_metrics struct. +grep '^type _rt_metrics ' gen-sysinfo.go | \ + sed -e 's/_rt_metrics/RtMetrics/g' \ + -e 's/rmx_locks/Locks/' \ + -e 's/rmx_mtu/Mtu/' \ + -e 's/rmx_hopcount/Hopcount/' \ + -e 's/rmx_recvpipe/Recvpipe/' \ + -e 's/rmx_sendpipe/Sendpipe/' \ + -e 's/rmx_ssthresh/Ssthresh/' \ + -e 's/rmx_rtt/Rtt/' \ + -e 's/rmx_rttvar/Rttvar/' \ + -e 's/rmx_expire/Expire/' \ + -e 's/rmx_pksent/Pksent/' \ + >> ${OUT} + # The routing message flags. grep '^const _RT_' gen-sysinfo.go | \ sed -e 's/^\(const \)_\(RT_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} @@ -1005,6 +1060,13 @@ grep '^const _RTCF' gen-sysinfo.go | \ sed -e 's/^\(const \)_\(RTCF[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} grep '^const _RTM' gen-sysinfo.go | \ sed -e 's/^\(const \)_\(RTM[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} +if test "${GOOS}" = "netbsd"; then + if ! grep "RTM_RESOLVE" ${OUT} >/dev/null 2>&1; then + # NetBSD 8.0 removed RTM_RESOLVE, but it is part of the syscall package's + # stable API, so add it manually. + echo "const RTM_RESOLVE = 0xb" >> ${OUT} + fi +fi grep '^const _RTN' gen-sysinfo.go | \ sed -e 's/^\(const \)_\(RTN[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} grep '^const _RTPROT' gen-sysinfo.go | \ @@ -1020,9 +1082,14 @@ grep '^type _ifinfomsg ' gen-sysinfo.go | \ -e 's/ifi_change/Change/' \ >> ${OUT} -# The if_msghdr struct. +# The if_msghdr struct. Upstream uses inconsistent capitalization for this type +# on AIX, so we do too. +ifmsghdr_name=IfMsghdr +if test "${GOOS}" = "aix"; then + ifmsghdr_name=IfMsgHdr +fi grep '^type _if_msghdr ' gen-sysinfo.go | \ - sed -e 's/_if_msghdr/IfMsgHdr/' \ + sed -e "s/_if_msghdr/${ifmsghdr_name}/" \ -e 's/ifm_msglen/Msglen/' \ -e 's/ifm_version/Version/' \ -e 's/ifm_type/Type/' \ @@ -1032,6 +1099,17 @@ grep '^type _if_msghdr ' gen-sysinfo.go | \ -e 's/ifm_addrlen/Addrlen/' \ >> ${OUT} +# The if_announcemsghdr struct. +grep '^type _if_announcemsghdr ' gen-sysinfo.go | \ + sed -e 's/_if_announcemsghdr/IfAnnounceMsghdr/g' \ + -e 's/ifan_msglen/Msglen/' \ + -e 's/ifan_version/Version/' \ + -e 's/ifan_type/Type/' \ + -e 's/ifan_index/Index/' \ + -e 's/ifan_name/Name/' \ + -e 's/ifan_what/What/' \ + >> ${OUT} + # The interface information types and flags. grep '^const _IFA' gen-sysinfo.go | \ sed -e 's/^\(const \)_\(IFA[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} @@ -1041,9 +1119,16 @@ grep '^const _IFF' gen-sysinfo.go | \ sed -e 's/^\(const \)_\(IFF[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} grep '^const _IFNAMSIZ' gen-sysinfo.go | \ sed -e 's/^\(const \)_\(IFNAMSIZ[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} -grep '^const _SIOC' gen-sysinfo.go | +grep '^const _SIOC' gen-sysinfo.go | \ + grep -v '_val =' | \ sed -e 's/^\(const \)_\(SIOC[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} +if ! grep '^const SIOCGIFMTU' ${OUT} >/dev/null 2>&1; then + if grep '^const _SIOCGIFMTU_val' ${OUT} >/dev/null 2>&1; then + echo 'const SIOCGIFMTU = _SIOCGIFMTU_val' >> ${OUT} + fi +fi + # The ifaddrmsg struct. grep '^type _ifaddrmsg ' gen-sysinfo.go | \ sed -e 's/_ifaddrmsg/IfAddrmsg/' \ @@ -1054,6 +1139,18 @@ grep '^type _ifaddrmsg ' gen-sysinfo.go | \ -e 's/ifa_index/Index/' \ >> ${OUT} +# The ifa_msghdr struct. +grep '^type _ifa_msghdr ' gen-sysinfo.go | \ + sed -e 's/_ifa_msghdr/IfaMsghdr/g' \ + -e 's/ifam_msglen/Msglen/' \ + -e 's/ifam_version/Version/' \ + -e 's/ifam_type/Type/' \ + -e 's/ifam_addrs/Addrs/' \ + -e 's/ifam_flags/Flags/' \ + -e 's/ifam_metric/Metric/' \ + -e 's/ifam_index/Index/' \ + >> ${OUT} + # The rtattr struct. grep '^type _rtattr ' gen-sysinfo.go | \ sed -e 's/_rtattr/RtAttr/' \ @@ -1061,6 +1158,54 @@ grep '^type _rtattr ' gen-sysinfo.go | \ -e 's/rta_type/Type/' \ >> ${OUT} +# The bpf_version struct. +grep '^type _bpf_version ' gen-sysinfo.go | \ + sed -e 's/_bpf_version/BpfVersion/g' \ + -e 's/bv_major/Major/' \ + -e 's/bv_minor/Minor/' \ + >> ${OUT} + +# The bpf_stat struct. +grep '^type _bpf_stat ' gen-sysinfo.go | \ + sed -e 's/_bpf_stat/BpfStat/g' \ + -e 's/bs_recv/Recv/' \ + -e 's/bs_drop/Drop/' \ + -e 's/bs_capt/Capt/' \ + -e 's/bs_padding/Padding/' \ + >> ${OUT} + +# The bpf_insn struct. +grep '^type _bpf_insn ' gen-sysinfo.go | \ + sed -e 's/_bpf_insn/BpfInsn/g' \ + -e 's/code/Code/' \ + -e 's/jt/Jt/' \ + -e 's/jf/Jf/' \ + -e 's/k/K/' \ + >> ${OUT} + +# The bpf_program struct. +grep '^type _bpf_program ' gen-sysinfo.go | \ + sed -e 's/_bpf_program/BpfProgram/g' \ + -e 's/bf_len/Len/' \ + -e 's/bf_insns/Insns/' \ + -e 's/_bpf_insn/BpfInsn/' \ + >> ${OUT} + +# The BPF ioctl constants. +grep '^const _BIOC' gen-sysinfo.go | \ + grep -v '_val =' | \ + sed -e 's/^\(const \)_\(BIOC[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} +for c in BIOCFLUSH BIOCGBLEN BIOCGDLT BIOCGETIF BIOCGHDRCMPLT BIOCGRTIMEOUT \ + BIOCGSTATS BIOCIMMEDIATE BIOCPROMISC BIOCSBLEN BIOCSDLT BIOCSETF \ + BIOCSETIF BIOCSHDRCMPLT BIOCSRTIMEOUT BIOCVERSION +do + if ! grep "^const ${c}" ${OUT} >/dev/null 2>&1; then + if grep "^const _${c}_val" ${OUT} >/dev/null 2>&1; then + echo "const ${c} = _${c}_val" >> ${OUT} + fi + fi +done + # The in_pktinfo struct. grep '^type _in_pktinfo ' gen-sysinfo.go | \ sed -e 's/_in_pktinfo/Inet4Pktinfo/' \ @@ -1337,10 +1482,11 @@ fi # Struct sizes. set cmsghdr Cmsghdr ip_mreq IPMreq ip_mreqn IPMreqn ipv6_mreq IPv6Mreq \ - ifaddrmsg IfAddrmsg ifinfomsg IfInfomsg in_pktinfo Inet4Pktinfo \ - in6_pktinfo Inet6Pktinfo inotify_event InotifyEvent linger Linger \ - msghdr Msghdr nlattr NlAttr nlmsgerr NlMsgerr nlmsghdr NlMsghdr \ - rtattr RtAttr rtgenmsg RtGenmsg rtmsg RtMsg rtnexthop RtNexthop \ + ifaddrmsg IfAddrmsg ifa_msghdr IfaMsghdr ifinfomsg IfInfomsg \ + if_msghdr IfMsghdr in_pktinfo Inet4Pktinfo in6_pktinfo Inet6Pktinfo \ + inotify_event InotifyEvent linger Linger msghdr Msghdr nlattr NlAttr \ + nlmsgerr NlMsgerr nlmsghdr NlMsghdr rtattr RtAttr rt_msghdr RtMsghdr \ + rtgenmsg RtGenmsg rtmsg RtMsg rtnexthop RtNexthop \ sock_filter SockFilter sock_fprog SockFprog ucred Ucred \ icmp6_filter ICMPv6Filter ip6_mtuinfo IPv6MTUInfo while test $# != 0; do diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c index b429fdb..d30d160 100644 --- a/libgo/runtime/go-signal.c +++ b/libgo/runtime/go-signal.c @@ -229,6 +229,8 @@ getSiginfo(siginfo_t *info, void *context __attribute__((unused))) ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.jmp_context.iar; #elif defined(__aarch64__) && defined(__linux__) ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.pc; +#elif defined(__NetBSD__) + ret.sigpc = _UC_MACHINE_PC(((ucontext_t*)(context))); #endif if (ret.sigpc == 0) { diff --git a/libgo/runtime/go-unwind.c b/libgo/runtime/go-unwind.c index ad3142c..16e0525 100644 --- a/libgo/runtime/go-unwind.c +++ b/libgo/runtime/go-unwind.c @@ -59,20 +59,22 @@ void rethrowException () { struct _Unwind_Exception *hdr; + _Unwind_Reason_Code reason; hdr = (struct _Unwind_Exception *) runtime_g()->exception; #ifdef __USING_SJLJ_EXCEPTIONS__ - _Unwind_SjLj_Resume_or_Rethrow (hdr); + reason = _Unwind_SjLj_Resume_or_Rethrow (hdr); #else #if defined(_LIBUNWIND_STD_ABI) - _Unwind_RaiseException (hdr); + reason = _Unwind_RaiseException (hdr); #else - _Unwind_Resume_or_Rethrow (hdr); + reason = _Unwind_Resume_or_Rethrow (hdr); #endif #endif /* Rethrowing the exception should not return. */ + runtime_printf ("failed to rethrow unwind exception (reason=%d)\n", reason); abort(); } @@ -105,6 +107,7 @@ throwException () { struct _Unwind_Exception *hdr; uintptr align; + _Unwind_Reason_Code reason; hdr = (struct _Unwind_Exception *)runtime_g ()->exception; @@ -119,12 +122,13 @@ throwException () hdr->exception_cleanup = NULL; #ifdef __USING_SJLJ_EXCEPTIONS__ - _Unwind_SjLj_RaiseException (hdr); + reason = _Unwind_SjLj_RaiseException (hdr); #else - _Unwind_RaiseException (hdr); + reason = _Unwind_RaiseException (hdr); #endif /* Raising an exception should not return. */ + runtime_printf ("failed to throw unwind exception (reason=%d)\n", reason); abort (); } diff --git a/libgo/runtime/go-varargs.c b/libgo/runtime/go-varargs.c index f9270a9..f848608 100644 --- a/libgo/runtime/go-varargs.c +++ b/libgo/runtime/go-varargs.c @@ -114,13 +114,14 @@ __go_syscall6(uintptr_t flag, uintptr_t a1, uintptr_t a2, uintptr_t a3, #endif -#ifdef HAVE_SYS_PTRACE_H + +#if defined(HAVE_SYS_PTRACE_H) && defined(__linux__) // Despite documented appearances, this is actually implemented as -// a variadic function within glibc. +// a variadic function within glibc on Linux. long -__go_ptrace(int request, pid_t pid, uintptr_t addr, uintptr_t data) +__go_ptrace(int request, pid_t pid, void *addr, void *data) { return ptrace (request, pid, addr, data); } diff --git a/libgo/sysinfo.c b/libgo/sysinfo.c index 7640559..ba84071 100644 --- a/libgo/sysinfo.c +++ b/libgo/sysinfo.c @@ -47,6 +47,9 @@ #if defined(HAVE_SYS_SYSCALL_H) #include <sys/syscall.h> #endif +#if defined(HAVE_SYS_SYSCTL_H) +#include <sys/sysctl.h> +#endif #if defined(HAVE_SYS_EPOLL_H) #include <sys/epoll.h> #endif @@ -117,6 +120,9 @@ #if defined(HAVE_LINUX_RTNETLINK_H) #include <linux/rtnetlink.h> #endif +#if defined(HAVE_NET_BPF_H) +#include <net/bpf.h> +#endif #if defined(HAVE_NET_IF_H) #include <net/if.h> #endif @@ -279,8 +285,64 @@ enum { #ifdef NLA_HDRLEN NLA_HDRLEN_val = NLA_HDRLEN, #endif +#ifdef BIOCFLUSH + BIOCFLUSH_val = BIOCFLUSH, +#endif +#ifdef BIOCGBLEN + BIOCGBLEN_val = BIOCGBLEN, +#endif +#ifdef BIOCGDLT + BIOCGDLT_val = BIOCGDLT, +#endif +#ifdef BIOCGETIF + BIOCGETIF_val = BIOCGETIF, +#endif +#ifdef BIOCGHDRCMPLT + BIOCGHDRCMPLT_val = BIOCGHDRCMPLT, +#endif +#ifdef BIOCGRTIMEOUT + BIOCGRTIMEOUT_val = BIOCGRTIMEOUT, +#endif +#ifdef BIOCGSTATS + BIOCGSTATS_val = BIOCGSTATS, +#endif +#ifdef BIOCIMMEDIATE + BIOCIMMEDIATE_val = BIOCIMMEDIATE, +#endif +#ifdef BIOCPROMISC + BIOCPROMISC_val = BIOCPROMISC, +#endif +#ifdef BIOCSBLEN + BIOCSBLEN_val = BIOCSBLEN, +#endif +#ifdef BIOCSDLT + BIOCSDLT_val = BIOCSDLT, +#endif +#ifdef BIOCSETF + BIOCSETF_val = BIOCSETF, +#endif +#ifdef BIOCSETIF + BIOCSETIF_val = BIOCSETIF, +#endif +#ifdef BIOCSHDRCMPLT + BIOCSHDRCMPLT_val = BIOCSHDRCMPLT, +#endif +#ifdef BIOCSRTIMEOUT + BIOCSRTIMEOUT_val = BIOCSRTIMEOUT, +#endif +#ifdef BIOCVERSION + BIOCVERSION_val = BIOCVERSION, +#endif }; +// SIOCGIFMTU can't be added in the above enum as it might +// be signed in some OSes. +#ifdef SIOCGIFMTU +enum { + SIOCGIFMTU_val = SIOCGIFMTU, +}; +#endif + #if defined(HAVE_SYS_EPOLL_H) enum { epoll_data_offset = offsetof(struct epoll_event, data) diff --git a/libgo/testsuite/gotest b/libgo/testsuite/gotest index eadafa1..0fd6419 100755 --- a/libgo/testsuite/gotest +++ b/libgo/testsuite/gotest @@ -308,7 +308,7 @@ x) aix | android | darwin | dragonfly | freebsd | hurd | illumos | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows) tag1=nonmatchingtag ;; - 386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm) + 386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm) tag1=nonmatchingtag ;; esac @@ -320,7 +320,7 @@ x) aix | android | darwin | dragonfly | freebsd | hurd | illumos | js | linux | nacl | netbsd | openbsd | plan9 | solaris | windows) tag2=nonmatchingtag ;; - 386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm) + 386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | nios2 | ppc | ppc64 | ppc64le | riscv | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64 | wasm) tag2=nonmatchingtag ;; esac @@ -342,18 +342,18 @@ x) fi match=false ;; - $goos | $goarch | cgo | gccgo | go1.[0-9]) + $goos | $goarch | cgo | gccgo | go1.[0-9] | go1.[0-9][0-9]) match=true ;; - "!"$goos | "!"$goarch | "!cgo" | "!gccgo" | "!"go1.[0-9]) + "!"$goos | "!"$goarch | "!cgo" | "!gccgo" | "!"go1.[0-9] | "!"go1.[0-9][0-9]) ;; *,*) cmatch=true for ctag in `echo $tag | sed -e 's/,/ /g'`; do case $ctag in - $goos | $goarch | cgo | gccgo | go1.[0-9]) + $goos | $goarch | cgo | gccgo | go1.[0-9] | go1.[0-9][0-9]) ;; - "!"$goos | "!"$goarch | "!cgo" | "!gccgo" | "!"go1.[0-9]) + "!"$goos | "!"$goarch | "!cgo" | "!gccgo" | "!"go1.[0-9] | "!"go1.[0-9][0-9]) cmatch=false ;; "!"*) |