diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-06-07 18:05:45 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-06-07 18:05:45 +0000 |
commit | ce311a8cae4489058f8601bebdf511b7fb5fce26 (patch) | |
tree | 81494302b4f5708ad6c96bad6ecfd9c109574c38 /libgo | |
parent | 48ec607c1f8d1f1783850f1d2729fd23716b1b1b (diff) | |
parent | dc23fb4d72eed9ea09fbf4704b26e0e36414a57a (diff) | |
download | gcc-ce311a8cae4489058f8601bebdf511b7fb5fce26.zip gcc-ce311a8cae4489058f8601bebdf511b7fb5fce26.tar.gz gcc-ce311a8cae4489058f8601bebdf511b7fb5fce26.tar.bz2 |
Merge from trunk revision 261284.
From-SVN: r261288
Diffstat (limited to 'libgo')
80 files changed, 2204 insertions, 2328 deletions
diff --git a/libgo/MERGE b/libgo/MERGE index 26b8869..6f31fab 100644 --- a/libgo/MERGE +++ b/libgo/MERGE @@ -1,4 +1,4 @@ -20e228f2fdb44350c858de941dff4aea9f3127b8 +71bdbf431b79dff61944f22c25c7e085ccfc25d5 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 531f8f0..d847413 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -397,8 +397,10 @@ noinst_DATA = \ golang_org/x/net/internal/nettest.gox \ golang_org/x/net/nettest.gox \ internal/testenv.gox \ + internal/trace.gox \ net/internal/socktest.gox \ - os/signal/internal/pty.gox + os/signal/internal/pty.gox \ + runtime/pprof/internal/profile.gox if LIBGO_IS_RTEMS rtems_task_variable_add_file = runtime/rtems-task-variable-add.c @@ -591,34 +593,22 @@ s-zdefaultcc: Makefile $(SHELL) $(srcdir)/../move-if-change zdefaultcc.go.tmp zdefaultcc.go $(STAMP) $@ -# _Complex_lock and _Reader_lock are Go translations of some AIX system -# types and should not be exported back to C -# semt is a Go translation of the C type sem_t; it fails to convert on -# some systems and need not be exported back to C. -# sigset conflicts with system type sigset on AIX, so we need to rename it +# Post-process runtime.inc.raw (raw output of -fgo-c-header option when +# compiling runtime) to prune out certain types that should not be +# exported back to C. See comments in mkruntimeinc.sh for more details. runtime.inc: s-runtime-inc; @true s-runtime-inc: runtime.lo Makefile - rm -f runtime.inc.tmp2 runtime.inc.tmp3 - grep -v "#define _" runtime.inc.tmp | grep -v "#define [cm][01234] " | grep -v "#define empty " > runtime.inc.tmp2 - for pattern in '_[GP][a-z]' _Max _Lock _Sig _Trace _MHeap _Num; do \ - grep "#define $$pattern" runtime.inc.tmp >> runtime.inc.tmp2; \ - done - for TYPE in _Complex_lock _Reader_lock semt; do \ - sed -e '/struct '$${TYPE}' {/,/^}/s/^.*$$//' runtime.inc.tmp2 > runtime.inc.tmp3; \ - mv runtime.inc.tmp3 runtime.inc.tmp2; \ - done - sed -e 's/sigset/sigset_go/' runtime.inc.tmp2 > runtime.inc.tmp3 - $(SHELL) $(srcdir)/mvifdiff.sh runtime.inc.tmp3 runtime.inc - rm -f runtime.inc.tmp2 runtime.inc.tmp3 + $(SHELL) $(srcdir)/mkruntimeinc.sh + $(SHELL) $(srcdir)/mvifdiff.sh tmp-runtime.inc runtime.inc $(STAMP) $@ -noinst_DATA += zstdpkglist.go zdefaultcc.go +noinst_DATA += zdefaultcc.go # Generate the list of go std packages that were included in libgo zstdpkglist.go: s-zstdpkglist; @true s-zstdpkglist: Makefile rm -f zstdpkglist.go.tmp - echo 'package load' > zstdpkglist.go.tmp + echo 'package build' > 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 @@ -712,184 +702,7 @@ else syscall_lib_clone_lo = endif -PACKAGES = \ - archive/tar \ - archive/zip \ - bufio \ - bytes \ - compress/bzip2 \ - compress/flate \ - compress/gzip \ - compress/lzw \ - compress/zlib \ - container/heap \ - container/list \ - container/ring \ - context \ - crypto \ - crypto/aes \ - crypto/cipher \ - crypto/des \ - crypto/dsa \ - crypto/ecdsa \ - crypto/elliptic \ - crypto/hmac \ - crypto/internal/cipherhw \ - crypto/md5 \ - crypto/rand \ - crypto/rc4 \ - crypto/rsa \ - crypto/sha1 \ - crypto/sha256 \ - crypto/sha512 \ - crypto/subtle \ - crypto/tls \ - crypto/x509 \ - crypto/x509/pkix \ - database/sql \ - database/sql/driver \ - debug/dwarf \ - debug/elf \ - debug/gosym \ - debug/macho \ - debug/pe \ - debug/plan9obj \ - debug/xcoff \ - encoding \ - encoding/ascii85 \ - encoding/asn1 \ - encoding/base32 \ - encoding/base64 \ - encoding/binary \ - encoding/csv \ - encoding/gob \ - encoding/hex \ - encoding/json \ - encoding/pem \ - encoding/xml \ - errors \ - expvar \ - flag \ - fmt \ - go/ast \ - go/build \ - go/constant \ - go/doc \ - go/format \ - go/importer \ - go/internal/gccgoimporter \ - go/internal/gcimporter \ - go/internal/srcimporter \ - go/parser \ - go/printer \ - go/scanner \ - go/token \ - go/types \ - golang_org/x/crypto/chacha20poly1305 \ - golang_org/x/crypto/chacha20poly1305/internal/chacha20 \ - golang_org/x/crypto/cryptobyte \ - golang_org/x/crypto/cryptobyte/asn1 \ - golang_org/x/crypto/curve25519 \ - golang_org/x/crypto/poly1305 \ - golang_org/x/net/http2/hpack \ - golang_org/x/net/idna \ - golang_org/x/net/internal/nettest \ - golang_org/x/net/lex/httplex \ - golang_org/x/net/nettest \ - golang_org/x/net/proxy \ - golang_org/x/text/secure/bidirule \ - golang_org/x/text/transform \ - golang_org/x/text/unicode/bidi \ - golang_org/x/text/unicode/norm \ - golang_org/x/text/width \ - hash \ - hash/adler32 \ - hash/crc32 \ - hash/crc64 \ - hash/fnv \ - html \ - html/template \ - image \ - image/color \ - image/color/palette \ - image/draw \ - image/gif \ - image/internal/imageutil \ - image/jpeg \ - image/png \ - index/suffixarray \ - internal/nettrace \ - internal/poll \ - internal/race \ - internal/singleflight \ - internal/syscall/unix \ - internal/testenv \ - internal/testlog \ - internal/trace \ - io \ - io/ioutil \ - log \ - log/syslog \ - math \ - math/big \ - math/bits \ - math/cmplx \ - math/rand \ - mime \ - mime/multipart \ - mime/quotedprintable \ - net \ - net/http \ - net/http/cgi \ - net/http/cookiejar \ - net/http/fcgi \ - net/http/httptest \ - net/http/httptrace \ - net/http/httputil \ - net/http/internal \ - net/http/pprof \ - net/internal/socktest \ - net/mail \ - net/rpc \ - net/rpc/jsonrpc \ - net/smtp \ - net/textproto \ - net/url \ - os \ - os/exec \ - os/signal \ - os/signal/internal/pty \ - os/user \ - path \ - path/filepath \ - reflect \ - regexp \ - regexp/syntax \ - runtime \ - runtime/debug \ - runtime/internal/atomic \ - runtime/internal/sys \ - runtime/pprof \ - runtime/pprof/internal/profile \ - runtime/trace \ - sort \ - strconv \ - strings \ - sync \ - sync/atomic \ - syscall \ - testing \ - testing/internal/testdeps \ - testing/iotest \ - testing/quick \ - text/scanner \ - text/tabwriter \ - text/template \ - text/template/parse \ - time \ - unicode \ - unicode/utf16 \ - unicode/utf8 +PACKAGES = $(shell cat $(srcdir)/libgo-packages.txt) libgo_go_objs = \ $(addsuffix .lo,$(PACKAGES)) \ @@ -937,37 +750,7 @@ libgolibbegin_a_SOURCES = \ libgolibbegin_a_CFLAGS = $(AM_CFLAGS) -fPIC -GOTOOL_PACKAGES = \ - cmd/go/internal/base \ - cmd/go/internal/bug \ - cmd/go/internal/cache \ - cmd/go/internal/cfg \ - cmd/go/internal/clean \ - cmd/go/internal/cmdflag \ - cmd/go/internal/doc \ - cmd/go/internal/envcmd \ - cmd/go/internal/fix \ - cmd/go/internal/fmtcmd \ - cmd/go/internal/generate \ - cmd/go/internal/get \ - cmd/go/internal/help \ - cmd/go/internal/list \ - cmd/go/internal/load \ - cmd/go/internal/run \ - cmd/go/internal/str \ - cmd/go/internal/test \ - cmd/go/internal/tool \ - cmd/go/internal/version \ - cmd/go/internal/vet \ - cmd/go/internal/web \ - cmd/go/internal/work \ - cmd/internal/browser \ - cmd/internal/buildid \ - cmd/internal/edit \ - cmd/internal/objabi \ - cmd/internal/test2json \ - cmd/vet/internal/cfg \ - cmd/vet/internal/whitelist +GOTOOL_PACKAGES = $(shell cat $(srcdir)/gotool-packages.txt) libgotool_a_SOURCES = libgotool_a_DEPENDENCIES = $(addsuffix .lo,$(GOTOOL_PACKAGES)) @@ -1093,6 +876,7 @@ CHECK_DEPS = \ $(toolexeclibgotext_DATA) \ $(toolexeclibgotexttemplate_DATA) \ $(toolexeclibgounicode_DATA) \ + $(noinst_DATA) \ $(noinst_LIBRARIES) if GOC_IS_LLGO @@ -1153,7 +937,7 @@ extra_go_files_syscall = \ syscall.lo.dep: $(extra_go_files_syscall) # Pass -fgo-compiling-runtime when compiling the runtime package. -runtime_lo_GOCFLAGS = -fgo-c-header=runtime.inc.tmp -fgo-compiling-runtime +runtime_lo_GOCFLAGS = -fgo-c-header=runtime.inc.raw -fgo-compiling-runtime runtime_check_GOCFLAGS = -fgo-compiling-runtime runtime_internal_atomic_lo_GOCFLAGS = -fgo-compiling-runtime runtime_internal_atomic_lo_check_GOCFLAGS = -fgo-compiling-runtime @@ -1176,6 +960,9 @@ runtime_pprof_check_GOCFLAGS = -static-libgo -fno-inline extra_go_files_runtime_internal_sys = version.go runtime/internal/sys.lo.dep: $(extra_go_files_runtime_internal_sys) +extra_go_files_go_build = zstdpkglist.go +go/build.lo.dep: $(extra_go_files_go_build) + extra_go_files_go_types = gccgosizes.go go/types.lo.dep: $(extra_go_files_go_types) @@ -1185,9 +972,6 @@ cmd/internal/objabi.lo.dep: $(extra_go_files_cmd_internal_objabi) extra_go_files_cmd_go_internal_cfg = zdefaultcc.go cmd/go/internal/cfg.lo.dep: $(extra_go_files_cmd_go_internal_cfg) -extra_go_files_cmd_go_internal_load = zstdpkglist.go -cmd/go/internal/load.lo.dep: $(extra_go_files_cmd_go_internal_load) - extra_check_libs_cmd_go_internal_cache = $(abs_builddir)/libgotool.a extra_check_libs_cmd_go_internal_generate = $(abs_builddir)/libgotool.a extra_check_libs_cmd_go_internal_get = $(abs_builddir)/libgotool.a @@ -1278,171 +1062,10 @@ golang_org_x_net_lif_check = \ endif -TEST_PACKAGES = \ - bufio/check \ - bytes/check \ - context/check \ - crypto/check \ - errors/check \ - expvar/check \ - flag/check \ - fmt/check \ - hash/check \ - html/check \ - image/check \ - io/check \ - log/check \ - math/check \ - mime/check \ - net/check \ - os/check \ - path/check \ - reflect/check \ - regexp/check \ - runtime/check \ - sort/check \ - strconv/check \ - strings/check \ - sync/check \ - syscall/check \ - time/check \ - unicode/check \ - archive/tar/check \ - archive/zip/check \ - cmd/go/internal/cache/check \ - cmd/go/internal/generate/check \ - cmd/go/internal/get/check \ - cmd/go/internal/load/check \ - cmd/go/internal/work/check \ - cmd/internal/buildid/check \ - cmd/internal/edit/check \ - cmd/internal/objabi/check \ - cmd/internal/test2json/check \ - cmd/vet/internal/cfg/check \ - compress/bzip2/check \ - compress/flate/check \ - compress/gzip/check \ - compress/lzw/check \ - compress/zlib/check \ - container/heap/check \ - container/list/check \ - container/ring/check \ - crypto/aes/check \ - crypto/cipher/check \ - crypto/des/check \ - crypto/dsa/check \ - crypto/ecdsa/check \ - crypto/elliptic/check \ - crypto/hmac/check \ - crypto/md5/check \ - crypto/rand/check \ - crypto/rc4/check \ - crypto/rsa/check \ - crypto/sha1/check \ - crypto/sha256/check \ - crypto/sha512/check \ - crypto/subtle/check \ - crypto/tls/check \ - crypto/x509/check \ - database/sql/check \ - database/sql/driver/check \ - debug/dwarf/check \ - debug/elf/check \ - debug/macho/check \ - debug/pe/check \ - debug/plan9obj/check \ - debug/xcoff/check \ - encoding/ascii85/check \ - encoding/asn1/check \ - encoding/base32/check \ - encoding/base64/check \ - encoding/binary/check \ - encoding/csv/check \ - encoding/gob/check \ - encoding/hex/check \ - encoding/json/check \ - encoding/pem/check \ - encoding/xml/check \ - html/template/check \ - go/ast/check \ - go/build/check \ - go/constant/check \ - go/doc/check \ - go/format/check \ - go/importer/check \ - go/internal/gcimporter/check \ - go/internal/gccgoimporter/check \ - go/internal/srcimporter/check \ - go/parser/check \ - go/printer/check \ - go/scanner/check \ - go/token/check \ - go/types/check \ - golang_org/x/crypto/chacha20poly1305/check \ - golang_org/x/crypto/chacha20poly1305/internal/chacha20/check \ - golang_org/x/crypto/cryptobyte/check \ - golang_org/x/crypto/curve25519/check \ - golang_org/x/crypto/poly1305/check \ - golang_org/x/net/http2/hpack/check \ - golang_org/x/net/idna/check \ - golang_org/x/net/lex/httplex/check \ +TPACKAGES = $(shell cat $(srcdir)/check-packages.txt) +TEST_PACKAGES = $(addsuffix /check,$(TPACKAGES)) \ $(golang_org_x_net_lif_check) \ - golang_org/x/net/proxy/check \ - $(golang_org_x_net_route_check) \ - hash/adler32/check \ - hash/crc32/check \ - hash/crc64/check \ - hash/fnv/check \ - image/color/check \ - image/draw/check \ - image/jpeg/check \ - image/png/check \ - index/suffixarray/check \ - internal/poll/check \ - internal/singleflight/check \ - internal/trace/check \ - io/ioutil/check \ - log/syslog/check \ - math/big/check \ - math/bits/check \ - math/cmplx/check \ - math/rand/check \ - mime/multipart/check \ - mime/quotedprintable/check \ - net/http/check \ - net/http/cgi/check \ - net/http/cookiejar/check \ - net/http/fcgi/check \ - net/http/httptest/check \ - net/http/httptrace/check \ - net/http/httputil/check \ - net/http/internal/check \ - net/internal/socktest/check \ - net/mail/check \ - net/rpc/check \ - net/smtp/check \ - net/textproto/check \ - net/url/check \ - net/rpc/jsonrpc/check \ - os/exec/check \ - os/signal/check \ - os/user/check \ - path/filepath/check \ - regexp/syntax/check \ - runtime/debug/check \ - runtime/internal/atomic/check \ - runtime/internal/sys/check \ - runtime/pprof/check \ - runtime/pprof/internal/profile/check \ - runtime/trace/check \ - sync/atomic/check \ - text/scanner/check \ - text/tabwriter/check \ - text/template/check \ - text/template/parse/check \ - testing/quick/check \ - unicode/utf16/check \ - unicode/utf8/check + $(golang_org_x_net_route_check) check: check-tail check-recursive: check-head diff --git a/libgo/Makefile.in b/libgo/Makefile.in index fbca83e..6b3c597 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -757,8 +757,9 @@ toolexeclibgounicode_DATA = \ # Force them to be built. noinst_DATA = golang_org/x/net/internal/nettest.gox \ golang_org/x/net/nettest.gox internal/testenv.gox \ - net/internal/socktest.gox os/signal/internal/pty.gox \ - zstdpkglist.go zdefaultcc.go + internal/trace.gox net/internal/socktest.gox \ + os/signal/internal/pty.gox runtime/pprof/internal/profile.gox \ + zdefaultcc.go @LIBGO_IS_RTEMS_FALSE@rtems_task_variable_add_file = @LIBGO_IS_RTEMS_TRUE@rtems_task_variable_add_file = runtime/rtems-task-variable-add.c @LIBGO_IS_AIX_FALSE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-none.c @@ -819,185 +820,7 @@ SYSINFO_FLAGS = \ @LIBGO_IS_LINUX_FALSE@syscall_lib_clone_lo = @LIBGO_IS_LINUX_TRUE@syscall_lib_clone_lo = syscall/clone_linux.lo -PACKAGES = \ - archive/tar \ - archive/zip \ - bufio \ - bytes \ - compress/bzip2 \ - compress/flate \ - compress/gzip \ - compress/lzw \ - compress/zlib \ - container/heap \ - container/list \ - container/ring \ - context \ - crypto \ - crypto/aes \ - crypto/cipher \ - crypto/des \ - crypto/dsa \ - crypto/ecdsa \ - crypto/elliptic \ - crypto/hmac \ - crypto/internal/cipherhw \ - crypto/md5 \ - crypto/rand \ - crypto/rc4 \ - crypto/rsa \ - crypto/sha1 \ - crypto/sha256 \ - crypto/sha512 \ - crypto/subtle \ - crypto/tls \ - crypto/x509 \ - crypto/x509/pkix \ - database/sql \ - database/sql/driver \ - debug/dwarf \ - debug/elf \ - debug/gosym \ - debug/macho \ - debug/pe \ - debug/plan9obj \ - debug/xcoff \ - encoding \ - encoding/ascii85 \ - encoding/asn1 \ - encoding/base32 \ - encoding/base64 \ - encoding/binary \ - encoding/csv \ - encoding/gob \ - encoding/hex \ - encoding/json \ - encoding/pem \ - encoding/xml \ - errors \ - expvar \ - flag \ - fmt \ - go/ast \ - go/build \ - go/constant \ - go/doc \ - go/format \ - go/importer \ - go/internal/gccgoimporter \ - go/internal/gcimporter \ - go/internal/srcimporter \ - go/parser \ - go/printer \ - go/scanner \ - go/token \ - go/types \ - golang_org/x/crypto/chacha20poly1305 \ - golang_org/x/crypto/chacha20poly1305/internal/chacha20 \ - golang_org/x/crypto/cryptobyte \ - golang_org/x/crypto/cryptobyte/asn1 \ - golang_org/x/crypto/curve25519 \ - golang_org/x/crypto/poly1305 \ - golang_org/x/net/http2/hpack \ - golang_org/x/net/idna \ - golang_org/x/net/internal/nettest \ - golang_org/x/net/lex/httplex \ - golang_org/x/net/nettest \ - golang_org/x/net/proxy \ - golang_org/x/text/secure/bidirule \ - golang_org/x/text/transform \ - golang_org/x/text/unicode/bidi \ - golang_org/x/text/unicode/norm \ - golang_org/x/text/width \ - hash \ - hash/adler32 \ - hash/crc32 \ - hash/crc64 \ - hash/fnv \ - html \ - html/template \ - image \ - image/color \ - image/color/palette \ - image/draw \ - image/gif \ - image/internal/imageutil \ - image/jpeg \ - image/png \ - index/suffixarray \ - internal/nettrace \ - internal/poll \ - internal/race \ - internal/singleflight \ - internal/syscall/unix \ - internal/testenv \ - internal/testlog \ - internal/trace \ - io \ - io/ioutil \ - log \ - log/syslog \ - math \ - math/big \ - math/bits \ - math/cmplx \ - math/rand \ - mime \ - mime/multipart \ - mime/quotedprintable \ - net \ - net/http \ - net/http/cgi \ - net/http/cookiejar \ - net/http/fcgi \ - net/http/httptest \ - net/http/httptrace \ - net/http/httputil \ - net/http/internal \ - net/http/pprof \ - net/internal/socktest \ - net/mail \ - net/rpc \ - net/rpc/jsonrpc \ - net/smtp \ - net/textproto \ - net/url \ - os \ - os/exec \ - os/signal \ - os/signal/internal/pty \ - os/user \ - path \ - path/filepath \ - reflect \ - regexp \ - regexp/syntax \ - runtime \ - runtime/debug \ - runtime/internal/atomic \ - runtime/internal/sys \ - runtime/pprof \ - runtime/pprof/internal/profile \ - runtime/trace \ - sort \ - strconv \ - strings \ - sync \ - sync/atomic \ - syscall \ - testing \ - testing/internal/testdeps \ - testing/iotest \ - testing/quick \ - text/scanner \ - text/tabwriter \ - text/template \ - text/template/parse \ - time \ - unicode \ - unicode/utf16 \ - unicode/utf8 - +PACKAGES = $(shell cat $(srcdir)/libgo-packages.txt) libgo_go_objs = \ $(addsuffix .lo,$(PACKAGES)) \ bytes/index.lo \ @@ -1041,38 +864,7 @@ libgolibbegin_a_SOURCES = \ runtime/go-libmain.c libgolibbegin_a_CFLAGS = $(AM_CFLAGS) -fPIC -GOTOOL_PACKAGES = \ - cmd/go/internal/base \ - cmd/go/internal/bug \ - cmd/go/internal/cache \ - cmd/go/internal/cfg \ - cmd/go/internal/clean \ - cmd/go/internal/cmdflag \ - cmd/go/internal/doc \ - cmd/go/internal/envcmd \ - cmd/go/internal/fix \ - cmd/go/internal/fmtcmd \ - cmd/go/internal/generate \ - cmd/go/internal/get \ - cmd/go/internal/help \ - cmd/go/internal/list \ - cmd/go/internal/load \ - cmd/go/internal/run \ - cmd/go/internal/str \ - cmd/go/internal/test \ - cmd/go/internal/tool \ - cmd/go/internal/version \ - cmd/go/internal/vet \ - cmd/go/internal/web \ - cmd/go/internal/work \ - cmd/internal/browser \ - cmd/internal/buildid \ - cmd/internal/edit \ - cmd/internal/objabi \ - cmd/internal/test2json \ - cmd/vet/internal/cfg \ - cmd/vet/internal/whitelist - +GOTOOL_PACKAGES = $(shell cat $(srcdir)/gotool-packages.txt) libgotool_a_SOURCES = libgotool_a_DEPENDENCIES = $(addsuffix .lo,$(GOTOOL_PACKAGES)) libgotool_a_LIBADD = $(addsuffix .o,$(GOTOOL_PACKAGES)) @@ -1170,7 +962,8 @@ CHECK_DEPS = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \ $(toolexeclibgoruntime_DATA) $(toolexeclibgosync_DATA) \ $(toolexeclibgotesting_DATA) $(toolexeclibgotext_DATA) \ $(toolexeclibgotexttemplate_DATA) $(toolexeclibgounicode_DATA) \ - $(noinst_LIBRARIES) $(am__append_3) $(am__append_4) + $(noinst_DATA) $(noinst_LIBRARIES) $(am__append_3) \ + $(am__append_4) # Pass -ffp-contract=off, or 386-specific options, when building the # math package. MATH_FLAG is defined in configure.ac. @@ -1189,7 +982,7 @@ extra_go_files_syscall = \ # Pass -fgo-compiling-runtime when compiling the runtime package. -runtime_lo_GOCFLAGS = -fgo-c-header=runtime.inc.tmp -fgo-compiling-runtime +runtime_lo_GOCFLAGS = -fgo-c-header=runtime.inc.raw -fgo-compiling-runtime runtime_check_GOCFLAGS = -fgo-compiling-runtime runtime_internal_atomic_lo_GOCFLAGS = -fgo-compiling-runtime runtime_internal_atomic_lo_check_GOCFLAGS = -fgo-compiling-runtime @@ -1206,10 +999,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 extra_go_files_runtime_internal_sys = version.go +extra_go_files_go_build = zstdpkglist.go extra_go_files_go_types = gccgosizes.go extra_go_files_cmd_internal_objabi = objabi.go extra_go_files_cmd_go_internal_cfg = zdefaultcc.go -extra_go_files_cmd_go_internal_load = zstdpkglist.go extra_check_libs_cmd_go_internal_cache = $(abs_builddir)/libgotool.a extra_check_libs_cmd_go_internal_generate = $(abs_builddir)/libgotool.a extra_check_libs_cmd_go_internal_get = $(abs_builddir)/libgotool.a @@ -1234,171 +1027,10 @@ extra_check_libs_cmd_vet_internal_cfg = $(abs_builddir)/libgotool.a @LIBGO_IS_SOLARIS_TRUE@golang_org_x_net_lif_check = \ @LIBGO_IS_SOLARIS_TRUE@ golang_org/x/net/lif/check -TEST_PACKAGES = \ - bufio/check \ - bytes/check \ - context/check \ - crypto/check \ - errors/check \ - expvar/check \ - flag/check \ - fmt/check \ - hash/check \ - html/check \ - image/check \ - io/check \ - log/check \ - math/check \ - mime/check \ - net/check \ - os/check \ - path/check \ - reflect/check \ - regexp/check \ - runtime/check \ - sort/check \ - strconv/check \ - strings/check \ - sync/check \ - syscall/check \ - time/check \ - unicode/check \ - archive/tar/check \ - archive/zip/check \ - cmd/go/internal/cache/check \ - cmd/go/internal/generate/check \ - cmd/go/internal/get/check \ - cmd/go/internal/load/check \ - cmd/go/internal/work/check \ - cmd/internal/buildid/check \ - cmd/internal/edit/check \ - cmd/internal/objabi/check \ - cmd/internal/test2json/check \ - cmd/vet/internal/cfg/check \ - compress/bzip2/check \ - compress/flate/check \ - compress/gzip/check \ - compress/lzw/check \ - compress/zlib/check \ - container/heap/check \ - container/list/check \ - container/ring/check \ - crypto/aes/check \ - crypto/cipher/check \ - crypto/des/check \ - crypto/dsa/check \ - crypto/ecdsa/check \ - crypto/elliptic/check \ - crypto/hmac/check \ - crypto/md5/check \ - crypto/rand/check \ - crypto/rc4/check \ - crypto/rsa/check \ - crypto/sha1/check \ - crypto/sha256/check \ - crypto/sha512/check \ - crypto/subtle/check \ - crypto/tls/check \ - crypto/x509/check \ - database/sql/check \ - database/sql/driver/check \ - debug/dwarf/check \ - debug/elf/check \ - debug/macho/check \ - debug/pe/check \ - debug/plan9obj/check \ - debug/xcoff/check \ - encoding/ascii85/check \ - encoding/asn1/check \ - encoding/base32/check \ - encoding/base64/check \ - encoding/binary/check \ - encoding/csv/check \ - encoding/gob/check \ - encoding/hex/check \ - encoding/json/check \ - encoding/pem/check \ - encoding/xml/check \ - html/template/check \ - go/ast/check \ - go/build/check \ - go/constant/check \ - go/doc/check \ - go/format/check \ - go/importer/check \ - go/internal/gcimporter/check \ - go/internal/gccgoimporter/check \ - go/internal/srcimporter/check \ - go/parser/check \ - go/printer/check \ - go/scanner/check \ - go/token/check \ - go/types/check \ - golang_org/x/crypto/chacha20poly1305/check \ - golang_org/x/crypto/chacha20poly1305/internal/chacha20/check \ - golang_org/x/crypto/cryptobyte/check \ - golang_org/x/crypto/curve25519/check \ - golang_org/x/crypto/poly1305/check \ - golang_org/x/net/http2/hpack/check \ - golang_org/x/net/idna/check \ - golang_org/x/net/lex/httplex/check \ +TPACKAGES = $(shell cat $(srcdir)/check-packages.txt) +TEST_PACKAGES = $(addsuffix /check,$(TPACKAGES)) \ $(golang_org_x_net_lif_check) \ - golang_org/x/net/proxy/check \ - $(golang_org_x_net_route_check) \ - hash/adler32/check \ - hash/crc32/check \ - hash/crc64/check \ - hash/fnv/check \ - image/color/check \ - image/draw/check \ - image/jpeg/check \ - image/png/check \ - index/suffixarray/check \ - internal/poll/check \ - internal/singleflight/check \ - internal/trace/check \ - io/ioutil/check \ - log/syslog/check \ - math/big/check \ - math/bits/check \ - math/cmplx/check \ - math/rand/check \ - mime/multipart/check \ - mime/quotedprintable/check \ - net/http/check \ - net/http/cgi/check \ - net/http/cookiejar/check \ - net/http/fcgi/check \ - net/http/httptest/check \ - net/http/httptrace/check \ - net/http/httputil/check \ - net/http/internal/check \ - net/internal/socktest/check \ - net/mail/check \ - net/rpc/check \ - net/smtp/check \ - net/textproto/check \ - net/url/check \ - net/rpc/jsonrpc/check \ - os/exec/check \ - os/signal/check \ - os/user/check \ - path/filepath/check \ - regexp/syntax/check \ - runtime/debug/check \ - runtime/internal/atomic/check \ - runtime/internal/sys/check \ - runtime/pprof/check \ - runtime/pprof/internal/profile/check \ - runtime/trace/check \ - sync/atomic/check \ - text/scanner/check \ - text/tabwriter/check \ - text/template/check \ - text/template/parse/check \ - testing/quick/check \ - unicode/utf16/check \ - unicode/utf8/check + $(golang_org_x_net_route_check) MOSTLYCLEANFILES = \ s-runtime_sysinfo s-sigtab s-runtime-inc s-zstdpkglist \ @@ -3171,32 +2803,20 @@ s-zdefaultcc: Makefile $(SHELL) $(srcdir)/../move-if-change zdefaultcc.go.tmp zdefaultcc.go $(STAMP) $@ -# _Complex_lock and _Reader_lock are Go translations of some AIX system -# types and should not be exported back to C -# semt is a Go translation of the C type sem_t; it fails to convert on -# some systems and need not be exported back to C. -# sigset conflicts with system type sigset on AIX, so we need to rename it +# Post-process runtime.inc.raw (raw output of -fgo-c-header option when +# compiling runtime) to prune out certain types that should not be +# exported back to C. See comments in mkruntimeinc.sh for more details. runtime.inc: s-runtime-inc; @true s-runtime-inc: runtime.lo Makefile - rm -f runtime.inc.tmp2 runtime.inc.tmp3 - grep -v "#define _" runtime.inc.tmp | grep -v "#define [cm][01234] " | grep -v "#define empty " > runtime.inc.tmp2 - for pattern in '_[GP][a-z]' _Max _Lock _Sig _Trace _MHeap _Num; do \ - grep "#define $$pattern" runtime.inc.tmp >> runtime.inc.tmp2; \ - done - for TYPE in _Complex_lock _Reader_lock semt; do \ - sed -e '/struct '$${TYPE}' {/,/^}/s/^.*$$//' runtime.inc.tmp2 > runtime.inc.tmp3; \ - mv runtime.inc.tmp3 runtime.inc.tmp2; \ - done - sed -e 's/sigset/sigset_go/' runtime.inc.tmp2 > runtime.inc.tmp3 - $(SHELL) $(srcdir)/mvifdiff.sh runtime.inc.tmp3 runtime.inc - rm -f runtime.inc.tmp2 runtime.inc.tmp3 + $(SHELL) $(srcdir)/mkruntimeinc.sh + $(SHELL) $(srcdir)/mvifdiff.sh tmp-runtime.inc runtime.inc $(STAMP) $@ # Generate the list of go std packages that were included in libgo zstdpkglist.go: s-zstdpkglist; @true s-zstdpkglist: Makefile rm -f zstdpkglist.go.tmp - echo 'package load' > zstdpkglist.go.tmp + echo 'package build' > 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 @@ -3323,10 +2943,10 @@ $(foreach package,$(GOTOOL_PACKAGES),$(eval $(call PACKAGE_template,$(package))) runtime.lo.dep: $(extra_go_files_runtime) syscall.lo.dep: $(extra_go_files_syscall) runtime/internal/sys.lo.dep: $(extra_go_files_runtime_internal_sys) +go/build.lo.dep: $(extra_go_files_go_build) go/types.lo.dep: $(extra_go_files_go_types) cmd/internal/objabi.lo.dep: $(extra_go_files_cmd_internal_objabi) cmd/go/internal/cfg.lo.dep: $(extra_go_files_cmd_go_internal_cfg) -cmd/go/internal/load.lo.dep: $(extra_go_files_cmd_go_internal_load) # FIXME: The following C files may as well move to the runtime # directory and be treated like other C files. diff --git a/libgo/VERSION b/libgo/VERSION index dc3cdca..98736c7 100644 --- a/libgo/VERSION +++ b/libgo/VERSION @@ -1 +1 @@ -go1.10rc2 +go1.10.2 diff --git a/libgo/check-packages.txt b/libgo/check-packages.txt new file mode 100644 index 0000000..82a08c6 --- /dev/null +++ b/libgo/check-packages.txt @@ -0,0 +1,163 @@ +archive/tar +archive/zip +bufio +bytes +cmd/go/internal/cache +cmd/go/internal/generate +cmd/go/internal/get +cmd/go/internal/load +cmd/go/internal/work +cmd/internal/buildid +cmd/internal/edit +cmd/internal/objabi +cmd/internal/test2json +cmd/vet/internal/cfg +compress/bzip2 +compress/flate +compress/gzip +compress/lzw +compress/zlib +container/heap +container/list +container/ring +context +crypto +crypto/aes +crypto/cipher +crypto/des +crypto/dsa +crypto/ecdsa +crypto/elliptic +crypto/hmac +crypto/md5 +crypto/rand +crypto/rc4 +crypto/rsa +crypto/sha1 +crypto/sha256 +crypto/sha512 +crypto/subtle +crypto/tls +crypto/x509 +database/sql +database/sql/driver +debug/dwarf +debug/elf +debug/macho +debug/pe +debug/plan9obj +debug/xcoff +encoding/ascii85 +encoding/asn1 +encoding/base32 +encoding/base64 +encoding/binary +encoding/csv +encoding/gob +encoding/hex +encoding/json +encoding/pem +encoding/xml +errors +expvar +flag +fmt +go/ast +go/build +go/constant +go/doc +go/format +go/importer +go/internal/gccgoimporter +go/internal/gcimporter +go/internal/srcimporter +go/parser +go/printer +go/scanner +go/token +go/types +golang_org/x/crypto/chacha20poly1305 +golang_org/x/crypto/chacha20poly1305/internal/chacha20 +golang_org/x/crypto/cryptobyte +golang_org/x/crypto/curve25519 +golang_org/x/crypto/poly1305 +golang_org/x/net/http2/hpack +golang_org/x/net/idna +golang_org/x/net/lex/httplex +golang_org/x/net/proxy +hash +hash/adler32 +hash/crc32 +hash/crc64 +hash/fnv +html +html/template +image +image/color +image/draw +image/jpeg +image/png +index/suffixarray +internal/poll +internal/singleflight +internal/trace +io +io/ioutil +log +log/syslog +math +math/big +math/bits +math/cmplx +math/rand +mime +mime/multipart +mime/quotedprintable +net +net/http +net/http/cgi +net/http/cookiejar +net/http/fcgi +net/http/httptest +net/http/httptrace +net/http/httputil +net/http/internal +net/http/pprof +net/internal/socktest +net/mail +net/rpc +net/rpc/jsonrpc +net/smtp +net/textproto +net/url +os +os/exec +os/signal +os/user +path +path/filepath +reflect +regexp +regexp/syntax +runtime +runtime/debug +runtime/internal/atomic +runtime/internal/sys +runtime/pprof +runtime/pprof/internal/profile +runtime/trace +sort +strconv +strings +sync +sync/atomic +syscall +testing/quick +text/scanner +text/tabwriter +text/template +text/template/parse +time +unicode +unicode/utf16 +unicode/utf8 diff --git a/libgo/configure b/libgo/configure index c5f8e8a..11e04aa 100755 --- a/libgo/configure +++ b/libgo/configure @@ -13653,10 +13653,10 @@ esac # - libgo/go/syscall/endian_XX.go # - possibly others # - possibly update files in libgo/go/internal/syscall/unix -ALLGOARCH="386 alpha amd64 amd64p32 arm armbe arm64 arm64be ia64 m68k mips mipsle mips64 mips64le mips64p32 mips64p32le ppc ppc64 ppc64le riscv64 s390 s390x sh shbe sparc sparc64" +ALLGOARCH="386 alpha amd64 amd64p32 arm armbe arm64 arm64be ia64 m68k mips mipsle mips64 mips64le mips64p32 mips64p32le nios2 ppc ppc64 ppc64le riscv64 s390 s390x sh shbe sparc sparc64" # All known GOARCH family values. -ALLGOARCHFAMILY="I386 ALPHA AMD64 ARM ARM64 IA64 M68K MIPS MIPS64 PPC PPC64 RISCV64 S390 S390X SH SPARC SPARC64" +ALLGOARCHFAMILY="I386 ALPHA AMD64 ARM ARM64 IA64 M68K MIPS MIPS64 NIOS2 PPC PPC64 RISCV64 S390 S390X SH SPARC SPARC64" GOARCH=unknown case ${host} in @@ -13745,6 +13745,9 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ;; esac ;; + nios2-*-*) + GOARCH=nios2 + ;; rs6000*-*-* | powerpc*-*-*) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ diff --git a/libgo/configure.ac b/libgo/configure.ac index eabe294..9f4bf50 100644 --- a/libgo/configure.ac +++ b/libgo/configure.ac @@ -224,10 +224,10 @@ AC_SUBST(USE_DEJAGNU) # - libgo/go/syscall/endian_XX.go # - possibly others # - possibly update files in libgo/go/internal/syscall/unix -ALLGOARCH="386 alpha amd64 amd64p32 arm armbe arm64 arm64be ia64 m68k mips mipsle mips64 mips64le mips64p32 mips64p32le ppc ppc64 ppc64le riscv64 s390 s390x sh shbe sparc sparc64" +ALLGOARCH="386 alpha amd64 amd64p32 arm armbe arm64 arm64be ia64 m68k mips mipsle mips64 mips64le mips64p32 mips64p32le nios2 ppc ppc64 ppc64le riscv64 s390 s390x sh shbe sparc sparc64" # All known GOARCH family values. -ALLGOARCHFAMILY="I386 ALPHA AMD64 ARM ARM64 IA64 M68K MIPS MIPS64 PPC PPC64 RISCV64 S390 S390X SH SPARC SPARC64" +ALLGOARCHFAMILY="I386 ALPHA AMD64 ARM ARM64 IA64 M68K MIPS MIPS64 NIOS2 PPC PPC64 RISCV64 S390 S390X SH SPARC SPARC64" GOARCH=unknown case ${host} in @@ -290,6 +290,9 @@ changequote([,])dnl ;; esac ;; + nios2-*-*) + GOARCH=nios2 + ;; rs6000*-*-* | powerpc*-*-*) AC_COMPILE_IFELSE([ #ifdef _ARCH_PPC64 diff --git a/libgo/go/archive/zip/reader.go b/libgo/go/archive/zip/reader.go index 1563e74..2444106 100644 --- a/libgo/go/archive/zip/reader.go +++ b/libgo/go/archive/zip/reader.go @@ -366,7 +366,7 @@ parseExtras: epoch := time.Date(1601, time.January, 1, 0, 0, 0, 0, time.UTC) modified = time.Unix(epoch.Unix()+secs, nsecs) } - case unixExtraID: + case unixExtraID, infoZipUnixExtraID: if len(fieldBuf) < 8 { continue parseExtras } @@ -379,12 +379,6 @@ parseExtras: } ts := int64(fieldBuf.uint32()) // ModTime since Unix epoch modified = time.Unix(ts, 0) - case infoZipUnixExtraID: - if len(fieldBuf) < 4 { - continue parseExtras - } - ts := int64(fieldBuf.uint32()) // ModTime since Unix epoch - modified = time.Unix(ts, 0) } } diff --git a/libgo/go/archive/zip/reader_test.go b/libgo/go/archive/zip/reader_test.go index 0d9040f..1e58b26 100644 --- a/libgo/go/archive/zip/reader_test.go +++ b/libgo/go/archive/zip/reader_test.go @@ -414,7 +414,7 @@ var tests = []ZipTest{ Name: "test.txt", Content: []byte{}, Size: 1<<32 - 1, - Modified: time.Date(2017, 10, 31, 21, 17, 27, 0, timeZone(-7*time.Hour)), + Modified: time.Date(2017, 10, 31, 21, 11, 57, 0, timeZone(-7*time.Hour)), Mode: 0644, }, }, diff --git a/libgo/go/cmd/cgo/main.go b/libgo/go/cmd/cgo/main.go index 6baabfd..890a365 100644 --- a/libgo/go/cmd/cgo/main.go +++ b/libgo/go/cmd/cgo/main.go @@ -165,6 +165,7 @@ var ptrSizeMap = map[string]int64{ "mips64le": 8, "mips64p32": 4, "mips64p32le": 4, + "nios2": 4, "ppc": 4, "ppc64": 8, "ppc64le": 8, @@ -190,6 +191,7 @@ var intSizeMap = map[string]int64{ "mips64le": 8, "mips64p32": 8, "mips64p32le": 8, + "nios2": 4, "ppc": 4, "ppc64": 8, "ppc64le": 8, diff --git a/libgo/go/cmd/go/alldocs.go b/libgo/go/cmd/go/alldocs.go index 5e1ac5a..aadf97c 100644 --- a/libgo/go/cmd/go/alldocs.go +++ b/libgo/go/cmd/go/alldocs.go @@ -1266,6 +1266,9 @@ // // Special-purpose environment variables: // +// GCCGOTOOLDIR +// If set, where to find gccgo tools, such as cgo. +// The default is based on how gccgo was configured. // GOROOT_FINAL // The root of the installed Go tree, when it is // installed in a location other than where it is built. @@ -1279,9 +1282,6 @@ // Defined by Git. A colon-separated list of schemes that are allowed to be used // with git fetch/clone. If set, any scheme not explicitly mentioned will be // considered insecure by 'go get'. -// GCCGOTOOLDIR -// If set, where to find gccgo tools, such as cgo. -// The default is based on how gccgo was configured. // // // Import path syntax diff --git a/libgo/go/cmd/go/go_test.go b/libgo/go/cmd/go/go_test.go index c5a3d7b..f6d6f42 100644 --- a/libgo/go/cmd/go/go_test.go +++ b/libgo/go/cmd/go/go_test.go @@ -1034,7 +1034,6 @@ func TestGoInstallRebuildsStalePackagesInOtherGOPATH(t *testing.T) { } func TestGoInstallDetectsRemovedFiles(t *testing.T) { - skipIfGccgo(t, "gccgo does not yet support package build IDs") tg := testgo(t) defer tg.cleanup() tg.parallel() @@ -1104,7 +1103,6 @@ func TestGoInstallErrorOnCrossCompileToBin(t *testing.T) { } func TestGoInstallDetectsRemovedFilesInPackageMain(t *testing.T) { - skipIfGccgo(t, "gccgo does not yet support package build IDs") tooSlow(t) tg := testgo(t) defer tg.cleanup() @@ -3223,7 +3221,6 @@ func TestGoGetInternalWildcard(t *testing.T) { } func TestGoVetWithExternalTests(t *testing.T) { - skipIfGccgo(t, "gccgo does not have vet") tg := testgo(t) defer tg.cleanup() tg.makeTempdir() @@ -3233,7 +3230,6 @@ func TestGoVetWithExternalTests(t *testing.T) { } func TestGoVetWithTags(t *testing.T) { - skipIfGccgo(t, "gccgo does not have vet") tg := testgo(t) defer tg.cleanup() tg.makeTempdir() @@ -3243,7 +3239,6 @@ func TestGoVetWithTags(t *testing.T) { } func TestGoVetWithFlagsOn(t *testing.T) { - skipIfGccgo(t, "gccgo does not have vet") tg := testgo(t) defer tg.cleanup() tg.makeTempdir() @@ -3253,7 +3248,6 @@ func TestGoVetWithFlagsOn(t *testing.T) { } func TestGoVetWithFlagsOff(t *testing.T) { - skipIfGccgo(t, "gccgo does not have vet") tg := testgo(t) defer tg.cleanup() tg.makeTempdir() @@ -3271,6 +3265,20 @@ func TestGoVetWithOnlyTestFiles(t *testing.T) { tg.run("vet", "p") } +// Issue 24193. +func TestVetWithOnlyCgoFiles(t *testing.T) { + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("src/p/p.go", "package p; import \"C\"; func F() {}") + tg.setenv("GOPATH", tg.path(".")) + tg.run("vet", "p") +} + // Issue 9767, 19769. func TestGoGetDotSlashDownload(t *testing.T) { testenv.MustHaveExternalNetwork(t) @@ -5105,6 +5113,28 @@ func TestCacheOutput(t *testing.T) { } } +func TestCacheListStale(t *testing.T) { + tooSlow(t) + if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + t.Skip("GODEBUG gocacheverify") + } + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOCACHE", tg.path("cache")) + tg.tempFile("gopath/src/p/p.go", "package p; import _ \"q\"; func F(){}\n") + tg.tempFile("gopath/src/q/q.go", "package q; func F(){}\n") + tg.tempFile("gopath/src/m/m.go", "package main; import _ \"q\"; func main(){}\n") + + tg.setenv("GOPATH", tg.path("gopath")) + tg.run("install", "p", "m") + tg.run("list", "-f={{.ImportPath}} {{.Stale}}", "m", "q", "p") + tg.grepStdout("^m false", "m should not be stale") + tg.grepStdout("^q true", "q should be stale") + tg.grepStdout("^p false", "p should not be stale") +} + func TestCacheCoverage(t *testing.T) { tooSlow(t) @@ -5798,6 +5828,22 @@ func TestAtomicCoverpkgAll(t *testing.T) { } } +// Issue 23882. +func TestCoverpkgAllRuntime(t *testing.T) { + skipIfGccgo(t, "gccgo has no cover tool") + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + + tg.tempFile("src/x/x.go", `package x; import _ "runtime"; func F() {}`) + tg.tempFile("src/x/x_test.go", `package x; import "testing"; func TestF(t *testing.T) { F() }`) + tg.setenv("GOPATH", tg.path(".")) + tg.run("test", "-coverpkg=all", "x") + if canRace { + tg.run("test", "-coverpkg=all", "-race", "x") + } +} + func TestBadCommandLines(t *testing.T) { tg := testgo(t) defer tg.cleanup() @@ -5955,3 +6001,36 @@ func TestBadCgoDirectives(t *testing.T) { tg.run("build", "-n", "x") tg.grepStderr("-D@foo", "did not find -D@foo in commands") } + +func TestTwoPkgConfigs(t *testing.T) { + if !canCgo { + t.Skip("no cgo") + } + if runtime.GOOS == "windows" || runtime.GOOS == "plan9" { + t.Skipf("no shell scripts on %s", runtime.GOOS) + } + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("src/x/a.go", `package x + // #cgo pkg-config: --static a + import "C" + `) + tg.tempFile("src/x/b.go", `package x + // #cgo pkg-config: --static a + import "C" + `) + tg.tempFile("pkg-config.sh", `#!/bin/sh +echo $* >>`+tg.path("pkg-config.out")) + tg.must(os.Chmod(tg.path("pkg-config.sh"), 0755)) + tg.setenv("GOPATH", tg.path(".")) + tg.setenv("PKG_CONFIG", tg.path("pkg-config.sh")) + tg.run("build", "x") + out, err := ioutil.ReadFile(tg.path("pkg-config.out")) + tg.must(err) + out = bytes.TrimSpace(out) + want := "--cflags --static --static -- a a\n--libs --static --static -- a a" + if !bytes.Equal(out, []byte(want)) { + t.Errorf("got %q want %q", out, want) + } +} diff --git a/libgo/go/cmd/go/internal/cfg/cfg.go b/libgo/go/cmd/go/internal/cfg/cfg.go index bfdd67e..f0a2277 100644 --- a/libgo/go/cmd/go/internal/cfg/cfg.go +++ b/libgo/go/cmd/go/internal/cfg/cfg.go @@ -92,11 +92,12 @@ var ( // Update build context to use our computed GOROOT. func init() { BuildContext.GOROOT = GOROOT - // Note that we must use runtime.GOOS and runtime.GOARCH here, - // as the tool directory does not move based on environment variables. - // This matches the initialization of ToolDir in go/build, - // except for using GOROOT rather than runtime.GOROOT(). if runtime.Compiler != "gccgo" { + // Note that we must use runtime.GOOS and runtime.GOARCH here, + // as the tool directory does not move based on environment + // variables. This matches the initialization of ToolDir in + // go/build, except for using GOROOT rather than + // runtime.GOROOT. build.ToolDir = filepath.Join(GOROOT, "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH) } } @@ -107,6 +108,8 @@ func findGOROOT() string { } def := filepath.Clean(runtime.GOROOT()) if runtime.Compiler == "gccgo" { + // gccgo has no real GOROOT, and it certainly doesn't + // depend on the executable's location. return def } exe, err := os.Executable() diff --git a/libgo/go/cmd/go/internal/get/vcs.go b/libgo/go/cmd/go/internal/get/vcs.go index 26693b1..0b2a04e 100644 --- a/libgo/go/cmd/go/internal/get/vcs.go +++ b/libgo/go/cmd/go/internal/get/vcs.go @@ -809,8 +809,8 @@ func repoRootForImportDynamic(importPath string, security web.SecurityMode) (*re } } - if !strings.Contains(mmi.RepoRoot, "://") { - return nil, fmt.Errorf("%s: invalid repo root %q; no scheme", urlStr, mmi.RepoRoot) + if err := validateRepoRootScheme(mmi.RepoRoot); err != nil { + return nil, fmt.Errorf("%s: invalid repo root %q: %v", urlStr, mmi.RepoRoot, err) } rr := &repoRoot{ vcs: vcsByCmd(mmi.VCS), @@ -824,6 +824,36 @@ func repoRootForImportDynamic(importPath string, security web.SecurityMode) (*re return rr, nil } +// validateRepoRootScheme returns an error if repoRoot does not seem +// to have a valid URL scheme. At this point we permit things that +// aren't valid URLs, although later, if not using -insecure, we will +// restrict repoRoots to be valid URLs. This is only because we've +// historically permitted them, and people may depend on that. +func validateRepoRootScheme(repoRoot string) error { + end := strings.Index(repoRoot, "://") + if end <= 0 { + return errors.New("no scheme") + } + + // RFC 3986 section 3.1. + for i := 0; i < end; i++ { + c := repoRoot[i] + switch { + case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z': + // OK. + case '0' <= c && c <= '9' || c == '+' || c == '-' || c == '.': + // OK except at start. + if i == 0 { + return errors.New("invalid scheme") + } + default: + return errors.New("invalid scheme") + } + } + + return nil +} + var fetchGroup singleflight.Group var ( fetchCacheMu sync.Mutex diff --git a/libgo/go/cmd/go/internal/get/vcs_test.go b/libgo/go/cmd/go/internal/get/vcs_test.go index e29338a..a6f8642 100644 --- a/libgo/go/cmd/go/internal/get/vcs_test.go +++ b/libgo/go/cmd/go/internal/get/vcs_test.go @@ -408,3 +408,46 @@ func TestMatchGoImport(t *testing.T) { } } } + +func TestValidateRepoRootScheme(t *testing.T) { + tests := []struct { + root string + err string + }{ + { + root: "", + err: "no scheme", + }, + { + root: "http://", + err: "", + }, + { + root: "a://", + err: "", + }, + { + root: "a#://", + err: "invalid scheme", + }, + { + root: "-config://", + err: "invalid scheme", + }, + } + + for _, test := range tests { + err := validateRepoRootScheme(test.root) + if err == nil { + if test.err != "" { + t.Errorf("validateRepoRootScheme(%q) = nil, want %q", test.root, test.err) + } + } else if test.err == "" { + if err != nil { + t.Errorf("validateRepoRootScheme(%q) = %q, want nil", test.root, test.err) + } + } else if err.Error() != test.err { + t.Errorf("validateRepoRootScheme(%q) = %q, want %q", test.root, err, test.err) + } + } +} diff --git a/libgo/go/cmd/go/internal/help/helpdoc.go b/libgo/go/cmd/go/internal/help/helpdoc.go index 9a9fc4e..6aa449a 100644 --- a/libgo/go/cmd/go/internal/help/helpdoc.go +++ b/libgo/go/cmd/go/internal/help/helpdoc.go @@ -526,6 +526,9 @@ Architecture-specific environment variables: Special-purpose environment variables: + GCCGOTOOLDIR + If set, where to find gccgo tools, such as cgo. + The default is based on how gccgo was configured. GOROOT_FINAL The root of the installed Go tree, when it is installed in a location other than where it is built. @@ -539,9 +542,6 @@ Special-purpose environment variables: Defined by Git. A colon-separated list of schemes that are allowed to be used with git fetch/clone. If set, any scheme not explicitly mentioned will be considered insecure by 'go get'. - GCCGOTOOLDIR - If set, where to find gccgo tools, such as cgo. - The default is based on how gccgo was configured. `, } diff --git a/libgo/go/cmd/go/internal/load/pkg.go b/libgo/go/cmd/go/internal/load/pkg.go index ac764b4..882b86d 100644 --- a/libgo/go/cmd/go/internal/load/pkg.go +++ b/libgo/go/cmd/go/internal/load/pkg.go @@ -13,7 +13,6 @@ import ( "os" pathpkg "path" "path/filepath" - "runtime" "sort" "strings" "unicode" @@ -224,9 +223,6 @@ func (p *Package) copyBuild(pp *build.Package) { // TODO? Target p.Goroot = pp.Goroot p.Standard = p.Goroot && p.ImportPath != "" && isStandardImportPath(p.ImportPath) - if cfg.BuildToolchainName == "gccgo" { - p.Standard = stdpkg[p.ImportPath] - } p.GoFiles = pp.GoFiles p.CgoFiles = pp.CgoFiles p.IgnoredGoFiles = pp.IgnoredGoFiles @@ -895,13 +891,6 @@ var foldPath = make(map[string]string) func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { p.copyBuild(bp) - // When using gccgo the go/build package will not be able to - // find a standard package. It would be nicer to not get that - // error, but go/build doesn't know stdpkg. - if cfg.BuildToolchainName == "gccgo" && err != nil && p.Standard { - err = nil - } - // Decide whether p was listed on the command line. // Given that load is called while processing the command line, // you might think we could simply pass a flag down into load @@ -976,7 +965,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { // This is for 'go tool'. // Override all the usual logic and force it into the tool directory. if cfg.BuildToolchainName == "gccgo" { - p.Target = filepath.Join(runtime.GCCGOTOOLDIR, elem) + p.Target = filepath.Join(base.ToolDir, elem) } else { p.Target = filepath.Join(cfg.GOROOTpkg, "tool", full) } @@ -1021,7 +1010,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { // Cgo translation adds imports of "runtime/cgo" and "syscall", // except for certain packages, to avoid circular dependencies. - if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) { + if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) && cfg.BuildContext.Compiler != "gccgo" { addImport("runtime/cgo") } if p.UsesCgo() && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) { @@ -1030,7 +1019,9 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { // SWIG adds imports of some standard packages. if p.UsesSwig() { - addImport("runtime/cgo") + if cfg.BuildContext.Compiler != "gccgo" { + addImport("runtime/cgo") + } addImport("syscall") addImport("sync") @@ -1097,9 +1088,6 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { continue } p1 := LoadImport(path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], UseVendor) - if cfg.BuildToolchainName == "gccgo" && p1.Standard { - continue - } if p.Standard && p.Error == nil && !p1.Standard && p1.Error == nil { p.Error = &PackageError{ ImportStack: stk.Copy(), @@ -1224,6 +1212,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { // GNU binutils flagfile specifiers, sometimes called "response files"). // To be conservative, we reject almost any arg beginning with non-alphanumeric ASCII. // We accept leading . _ and / as likely in file system paths. +// There is a copy of this function in cmd/compile/internal/gc/noder.go. func SafeArg(name string) bool { if name == "" { return false @@ -1238,7 +1227,7 @@ func LinkerDeps(p *Package) []string { deps := []string{"runtime"} // External linking mode forces an import of runtime/cgo. - if externalLinkingForced(p) { + if externalLinkingForced(p) && cfg.BuildContext.Compiler != "gccgo" { deps = append(deps, "runtime/cgo") } // On ARM with GOARM=5, it forces an import of math, for soft floating point. @@ -1610,9 +1599,6 @@ func GetTestPackagesFor(p *Package, forceTest bool) (ptest, pxtest *Package, err rawTestImports := str.StringList(p.TestImports) for i, path := range p.TestImports { p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], UseVendor) - if cfg.BuildToolchainName == "gccgo" && p1.Standard { - continue - } if p1.Error != nil { return nil, nil, p1.Error } @@ -1641,9 +1627,6 @@ func GetTestPackagesFor(p *Package, forceTest bool) (ptest, pxtest *Package, err rawXTestImports := str.StringList(p.XTestImports) for i, path := range p.XTestImports { p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], UseVendor) - if cfg.BuildToolchainName == "gccgo" && p1.Standard { - continue - } if p1.Error != nil { return nil, nil, p1.Error } diff --git a/libgo/go/cmd/go/internal/test/test.go b/libgo/go/cmd/go/internal/test/test.go index 9785470..72415cc 100644 --- a/libgo/go/cmd/go/internal/test/test.go +++ b/libgo/go/cmd/go/internal/test/test.go @@ -633,6 +633,8 @@ func runTest(cmd *base.Command, args []string) { a := &work.Action{Mode: "go test -i"} for _, p := range load.PackagesForBuild(all) { if cfg.BuildToolchainName == "gccgo" && p.Standard { + // gccgo's standard library packages + // can not be reinstalled. continue } a.Deps = append(a.Deps, b.CompileAction(work.ModeInstall, work.ModeInstall, p)) @@ -671,6 +673,14 @@ func runTest(cmd *base.Command, args []string) { continue } + // If using the race detector, silently ignore + // attempts to run coverage on the runtime + // packages. It will cause the race detector + // to be invoked before it has been initialized. + if cfg.BuildRace && p.Standard && (p.ImportPath == "runtime" || strings.HasPrefix(p.ImportPath, "runtime/internal")) { + continue + } + if haveMatch { testCoverPkgs = append(testCoverPkgs, p) } @@ -862,9 +872,6 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin pmain.Internal.Imports = append(pmain.Internal.Imports, ptest) } else { p1 := load.LoadImport(dep, "", nil, &stk, nil, 0) - if cfg.BuildToolchainName == "gccgo" && p1.Standard { - continue - } if p1.Error != nil { return nil, nil, nil, p1.Error } diff --git a/libgo/go/cmd/go/internal/vet/vet.go b/libgo/go/cmd/go/internal/vet/vet.go index 07eed89..a737ebd 100644 --- a/libgo/go/cmd/go/internal/vet/vet.go +++ b/libgo/go/cmd/go/internal/vet/vet.go @@ -62,11 +62,11 @@ func runVet(cmd *base.Command, args []string) { base.Errorf("%v", err) continue } - if len(ptest.GoFiles) == 0 && pxtest == nil { + if len(ptest.GoFiles) == 0 && len(ptest.CgoFiles) == 0 && pxtest == nil { base.Errorf("go vet %s: no Go files in %s", p.ImportPath, p.Dir) continue } - if len(ptest.GoFiles) > 0 { + if len(ptest.GoFiles) > 0 || len(ptest.CgoFiles) > 0 { root.Deps = append(root.Deps, b.VetAction(work.ModeBuild, work.ModeBuild, ptest)) } if pxtest != nil { diff --git a/libgo/go/cmd/go/internal/vet/vetflag.go b/libgo/go/cmd/go/internal/vet/vetflag.go index d4664cc..03770ea 100644 --- a/libgo/go/cmd/go/internal/vet/vetflag.go +++ b/libgo/go/cmd/go/internal/vet/vetflag.go @@ -90,7 +90,7 @@ func vetFlags(args []string) (passToVet, packageNames []string) { } switch f.Name { // Flags known to the build but not to vet, so must be dropped. - case "x", "n", "vettool": + case "x", "n", "vettool", "compiler": if extraWord { args = append(args[:i], args[i+2:]...) extraWord = false diff --git a/libgo/go/cmd/go/internal/work/buildid.go b/libgo/go/cmd/go/internal/work/buildid.go index e2ae850..733938e 100644 --- a/libgo/go/cmd/go/internal/work/buildid.go +++ b/libgo/go/cmd/go/internal/work/buildid.go @@ -235,6 +235,8 @@ func (b *Builder) gccgoToolID(name, language string) (string, error) { cmdline := str.StringList(cfg.BuildToolexec, name, "-###", "-x", language, "-c", "-") cmd := exec.Command(cmdline[0], cmdline[1:]...) cmd.Env = base.EnvForDir(cmd.Dir, os.Environ()) + // Force untranslated output so that we see the string "version". + cmd.Env = append(cmd.Env, "LC_ALL=C") out, err := cmd.CombinedOutput() if err != nil { return "", fmt.Errorf("%s: %v; output: %q", name, err, out) @@ -292,13 +294,36 @@ func (b *Builder) gccgoToolID(name, language string) (string, error) { return id, nil } +// Check if assembler used by gccgo is GNU as. +func assemblerIsGas() bool { + cmd := exec.Command(BuildToolchain.compiler(), "-print-prog-name=as") + assembler, err := cmd.Output() + if err == nil { + cmd := exec.Command(strings.TrimSpace(string(assembler)), "--version") + out, err := cmd.Output() + if err == nil && strings.Contains(string(out), "GNU") { + return true + } else { + return false + } + } else { + return false + } +} + // gccgoBuildIDELFFile creates an assembler file that records the // action's build ID in an SHF_EXCLUDE section. func (b *Builder) gccgoBuildIDELFFile(a *Action) (string, error) { sfile := a.Objdir + "_buildid.s" var buf bytes.Buffer - fmt.Fprintf(&buf, "\t"+`.section .go.buildid,"e"`+"\n") + if cfg.Goos != "solaris" || assemblerIsGas() { + fmt.Fprintf(&buf, "\t"+`.section .go.buildid,"e"`+"\n") + } else if cfg.Goarch == "sparc" || cfg.Goarch == "sparc64" { + fmt.Fprintf(&buf, "\t"+`.section ".go.buildid",#exclude`+"\n") + } else { // cfg.Goarch == "386" || cfg.Goarch == "amd64" + fmt.Fprintf(&buf, "\t"+`.section .go.buildid,#exclude`+"\n") + } fmt.Fprintf(&buf, "\t.byte ") for i := 0; i < len(a.buildID); i++ { if i > 0 { @@ -311,8 +336,10 @@ func (b *Builder) gccgoBuildIDELFFile(a *Action) (string, error) { fmt.Fprintf(&buf, "%#02x", a.buildID[i]) } fmt.Fprintf(&buf, "\n") - fmt.Fprintf(&buf, "\t"+`.section .note.GNU-stack,"",@progbits`+"\n") - fmt.Fprintf(&buf, "\t"+`.section .note.GNU-split-stack,"",@progbits`+"\n") + if cfg.Goos != "solaris" { + fmt.Fprintf(&buf, "\t"+`.section .note.GNU-stack,"",@progbits`+"\n") + fmt.Fprintf(&buf, "\t"+`.section .note.GNU-split-stack,"",@progbits`+"\n") + } if cfg.BuildN || cfg.BuildX { for _, line := range bytes.Split(buf.Bytes(), []byte("\n")) { @@ -434,15 +461,7 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID // If so, it's up to date and we can reuse it instead of rebuilding it. var buildID string if target != "" && !cfg.BuildA { - var err error - buildID, err = buildid.ReadFile(target) - if err != nil && b.ComputeStaleOnly { - if p != nil && !p.Stale { - p.Stale = true - p.StaleReason = "target missing" - } - return true - } + buildID, _ = buildid.ReadFile(target) if strings.HasPrefix(buildID, actionID+buildIDSeparator) { a.buildID = buildID a.built = target @@ -519,7 +538,10 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID } } } - return true + + // Fall through to update a.buildID from the build artifact cache, + // which will affect the computation of buildIDs for targets + // higher up in the dependency graph. } // Check the build artifact cache. @@ -547,6 +569,10 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID a.built = file a.Target = "DO NOT USE - using cache" a.buildID = buildID + if p := a.Package; p != nil { + // Clearer than explaining that something else is stale. + p.StaleReason = "not installed but available in build cache" + } return true } } @@ -557,6 +583,10 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID a.output = []byte{} } + if b.ComputeStaleOnly { + return true + } + return false } diff --git a/libgo/go/cmd/go/internal/work/exec.go b/libgo/go/cmd/go/internal/work/exec.go index 5527e90..5994dbc 100644 --- a/libgo/go/cmd/go/internal/work/exec.go +++ b/libgo/go/cmd/go/internal/work/exec.go @@ -512,6 +512,7 @@ func (b *Builder) build(a *Action) (err error) { ImportPath: a.Package.ImportPath, ImportMap: make(map[string]string), PackageFile: make(map[string]string), + Standard: make(map[string]bool), } a.vetCfg = vcfg for i, raw := range a.Package.Internal.RawImports { @@ -548,17 +549,24 @@ func (b *Builder) build(a *Action) (err error) { for _, a1 := range a.Deps { p1 := a1.Package - if p1 == nil || p1.ImportPath == "" || a1.built == "" { + if p1 == nil || p1.ImportPath == "" { continue } - fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, a1.built) + if a1.built != "" { + fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, a1.built) + } if vcfg != nil { // Add import mapping if needed // (for imports like "runtime/cgo" that appear only in generated code). if !vcfgMapped[p1.ImportPath] { vcfg.ImportMap[p1.ImportPath] = p1.ImportPath } - vcfg.PackageFile[p1.ImportPath] = a1.built + if a1.built != "" { + vcfg.PackageFile[p1.ImportPath] = a1.built + } + if p1.Standard { + vcfg.Standard[p1.ImportPath] = true + } } } @@ -693,6 +701,7 @@ type vetConfig struct { GoFiles []string ImportMap map[string]string PackageFile map[string]string + Standard map[string]bool ImportPath string SucceedOnTypecheckFailure bool @@ -722,7 +731,10 @@ func (b *Builder) vet(a *Action) error { if vcfg.ImportMap["fmt"] == "" { a1 := a.Deps[1] vcfg.ImportMap["fmt"] = "fmt" - vcfg.PackageFile["fmt"] = a1.built + if a1.built != "" { + vcfg.PackageFile["fmt"] = a1.built + } + vcfg.Standard["fmt"] = true } // During go test, ignore type-checking failures during vet. @@ -944,16 +956,29 @@ func splitPkgConfigOutput(out []byte) []string { // Calls pkg-config if needed and returns the cflags/ldflags needed to build the package. func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string, err error) { - if pkgs := p.CgoPkgConfig; len(pkgs) > 0 { + if pcargs := p.CgoPkgConfig; len(pcargs) > 0 { + // pkg-config permits arguments to appear anywhere in + // the command line. Move them all to the front, before --. + var pcflags []string + var pkgs []string + for _, pcarg := range pcargs { + if pcarg == "--" { + // We're going to add our own "--" argument. + } else if strings.HasPrefix(pcarg, "--") { + pcflags = append(pcflags, pcarg) + } else { + pkgs = append(pkgs, pcarg) + } + } for _, pkg := range pkgs { if !load.SafeArg(pkg) { return nil, nil, fmt.Errorf("invalid pkg-config package name: %s", pkg) } } var out []byte - out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--cflags", "--", pkgs) + out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--cflags", pcflags, "--", pkgs) if err != nil { - b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pkgs, " "), string(out)) + b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+strings.Join(pkgs, " "), string(out)) b.Print(err.Error() + "\n") return nil, nil, errPrintedOutput } @@ -963,15 +988,15 @@ func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string, return nil, nil, err } } - out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--libs", "--", pkgs) + out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--libs", pcflags, "--", pkgs) if err != nil { - b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pkgs, " "), string(out)) + b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+strings.Join(pkgs, " "), string(out)) b.Print(err.Error() + "\n") return nil, nil, errPrintedOutput } if len(out) > 0 { ldflags = strings.Fields(string(out)) - if err := checkLinkerFlags("CFLAGS", "pkg-config --cflags", ldflags); err != nil { + if err := checkLinkerFlags("LDFLAGS", "pkg-config --libs", ldflags); err != nil { return nil, nil, err } } @@ -1090,7 +1115,7 @@ func BuildInstallFunc(b *Builder, a *Action) (err error) { // We want to hide that awful detail as much as possible, so don't // advertise it by touching the mtimes (usually the libraries are up // to date). - if !a.buggyInstall { + if !a.buggyInstall && !b.ComputeStaleOnly { now := time.Now() os.Chtimes(a.Target, now, now) } @@ -1540,6 +1565,8 @@ func joinUnambiguously(a []string) string { buf.WriteByte(' ') } q := strconv.Quote(s) + // A gccgo command line can contain -( and -). + // Make sure we quote them since they are special to the shell. if s == "" || strings.ContainsAny(s, " ()") || len(q) > len(s)+2 { buf.WriteString(q) } else { @@ -1580,13 +1607,17 @@ func (b *Builder) Mkdir(dir string) error { // symlink creates a symlink newname -> oldname. func (b *Builder) Symlink(oldname, newname string) error { + // It's not an error to try to recreate an existing symlink. + if link, err := os.Readlink(newname); err == nil && link == oldname { + return nil + } + if cfg.BuildN || cfg.BuildX { - b.Showcmd("", "ln -sf %s %s", oldname, newname) + b.Showcmd("", "ln -s %s %s", oldname, newname) if cfg.BuildN { return nil } } - os.Remove(newname) return os.Symlink(oldname, newname) } diff --git a/libgo/go/cmd/go/internal/work/gccgo.go b/libgo/go/cmd/go/internal/work/gccgo.go index 72d4d9d..e8dab19 100644 --- a/libgo/go/cmd/go/internal/work/gccgo.go +++ b/libgo/go/cmd/go/internal/work/gccgo.go @@ -190,15 +190,15 @@ func (gccgoToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) } absAfile := mkAbs(objdir, afile) // Try with D modifier first, then without if that fails. - if b.run(a, p.Dir, p.ImportPath, nil, "ar", "rcD", absAfile, absOfiles) != nil { + if cfg.Goos == "aix" || b.run(a, p.Dir, p.ImportPath, nil, "ar", "rcD", absAfile, absOfiles) != nil { + var arArgs []string if cfg.Goos == "aix" && cfg.Goarch == "ppc64" { // AIX puts both 32-bit and 64-bit objects in the same archive. // Tell the AIX "ar" command to only care about 64-bit objects. // AIX "ar" command does not know D option. - return b.run(a, p.Dir, p.ImportPath, nil, "ar", "-X64", "rc", absAfile, absOfiles) - } else { - return b.run(a, p.Dir, p.ImportPath, nil, "ar", "rc", absAfile, absOfiles) + arArgs = append(arArgs, "-X64") } + return b.run(a, p.Dir, p.ImportPath, nil, "ar", arArgs, "rc", absAfile, absOfiles) } return nil } @@ -466,7 +466,10 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string ldflags = append(ldflags, goLibBegin...) ldflags = append(ldflags, "-lgo", "-lgcc_s", "-lgcc", "-lc", "-lgcc") case "shared": - ldflags = append(ldflags, "-zdefs", "-shared", "-nostdlib", "-lgo", "-lgcc_s", "-lgcc", "-lc") + if cfg.Goos != "aix" { + ldflags = append(ldflags, "-zdefs") + } + ldflags = append(ldflags, "-shared", "-nostdlib", "-lgo", "-lgcc_s", "-lgcc", "-lc") case "pie": ldflags = append(ldflags, "-pie") diff --git a/libgo/go/cmd/go/internal/work/security.go b/libgo/go/cmd/go/internal/work/security.go index fee5bee..5c67aa9 100644 --- a/libgo/go/cmd/go/internal/work/security.go +++ b/libgo/go/cmd/go/internal/work/security.go @@ -34,6 +34,7 @@ import ( "fmt" "os" "regexp" + "strings" ) var re = regexp.MustCompile @@ -45,27 +46,65 @@ var validCompilerFlags = []*regexp.Regexp{ re(`-O([^@\-].*)`), re(`-W`), re(`-W([^@,]+)`), // -Wall but not -Wa,-foo. + re(`-Wa,-mbig-obj`), + re(`-ansi`), + re(`-f(no-)?blocks`), + re(`-f(no-)?common`), + re(`-f(no-)?constant-cfstrings`), + re(`-fdiagnostics-show-note-include-stack`), + re(`-f(no-)?exceptions`), + re(`-f(no-)?inline-functions`), + re(`-finput-charset=([^@\-].*)`), + re(`-f(no-)?fat-lto-objects`), + re(`-f(no-)?lto`), + re(`-fmacro-backtrace-limit=(.+)`), + re(`-fmessage-length=(.+)`), + re(`-f(no-)?modules`), re(`-f(no-)?objc-arc`), re(`-f(no-)?omit-frame-pointer`), + re(`-f(no-)?openmp(-simd)?`), + re(`-f(no-)?permissive`), re(`-f(no-)?(pic|PIC|pie|PIE)`), + re(`-f(no-)?rtti`), re(`-f(no-)?split-stack`), re(`-f(no-)?stack-(.+)`), re(`-f(no-)?strict-aliasing`), + re(`-f(un)signed-char`), + re(`-f(no-)?use-linker-plugin`), // safe if -B is not used; we don't permit -B re(`-fsanitize=(.+)`), + re(`-ftemplate-depth-(.+)`), + re(`-fvisibility=(.+)`), re(`-g([^@\-].*)?`), + re(`-m32`), + re(`-m64`), re(`-m(arch|cpu|fpu|tune)=([^@\-].*)`), + re(`-m(no-)?avx[0-9a-z.]*`), + re(`-m(no-)?ms-bitfields`), re(`-m(no-)?stack-(.+)`), re(`-mmacosx-(.+)`), + re(`-mios-simulator-version-min=(.+)`), + re(`-miphoneos-version-min=(.+)`), re(`-mnop-fun-dllimport`), + re(`-m(no-)?sse[0-9.]*`), + re(`-mwindows`), + re(`-pedantic(-errors)?`), + re(`-pipe`), re(`-pthread`), - re(`-std=([^@\-].*)`), + re(`-?-std=([^@\-].*)`), + re(`-?-stdlib=([^@\-].*)`), + re(`-w`), re(`-x([^@\-].*)`), } var validCompilerFlagsWithNextArg = []string{ + "-arch", "-D", "-I", "-framework", + "-isysroot", + "-isystem", + "--sysroot", + "-target", "-x", } @@ -73,29 +112,65 @@ var validLinkerFlags = []*regexp.Regexp{ re(`-F([^@\-].*)`), re(`-l([^@\-].*)`), re(`-L([^@\-].*)`), + re(`-O`), + re(`-O([^@\-].*)`), re(`-f(no-)?(pic|PIC|pie|PIE)`), re(`-fsanitize=([^@\-].*)`), re(`-g([^@\-].*)?`), re(`-m(arch|cpu|fpu|tune)=([^@\-].*)`), + re(`-mmacosx-(.+)`), + re(`-mios-simulator-version-min=(.+)`), + re(`-miphoneos-version-min=(.+)`), + re(`-mwindows`), re(`-(pic|PIC|pie|PIE)`), re(`-pthread`), + re(`-shared`), + re(`-?-static([-a-z0-9+]*)`), + re(`-?-stdlib=([^@\-].*)`), // Note that any wildcards in -Wl need to exclude comma, // since -Wl splits its argument at commas and passes // them all to the linker uninterpreted. Allowing comma // in a wildcard would allow tunnelling arbitrary additional // linker arguments through one of these. - re(`-Wl,-rpath,([^,@\-][^,]+)`), + re(`-Wl,--(no-)?allow-multiple-definition`), + re(`-Wl,--(no-)?as-needed`), + re(`-Wl,-Bdynamic`), + re(`-Wl,-Bstatic`), + re(`-Wl,-d[ny]`), + re(`-Wl,--disable-new-dtags`), + re(`-Wl,--enable-new-dtags`), + re(`-Wl,--end-group`), + re(`-Wl,-framework,[^,@\-][^,]+`), + re(`-Wl,-headerpad_max_install_names`), + re(`-Wl,--no-undefined`), + re(`-Wl,-rpath[=,]([^,@\-][^,]+)`), + re(`-Wl,-search_paths_first`), + re(`-Wl,-sectcreate,([^,@\-][^,]+),([^,@\-][^,]+),([^,@\-][^,]+)`), + re(`-Wl,--start-group`), + re(`-Wl,-?-static`), + re(`-Wl,--subsystem,(native|windows|console|posix|xbox)`), + re(`-Wl,-undefined[=,]([^,@\-][^,]+)`), + re(`-Wl,-?-unresolved-symbols=[^,]+`), re(`-Wl,--(no-)?warn-([^,]+)`), + re(`-Wl,-z,(no)?execstack`), + re(`-Wl,-z,relro`), - re(`[a-zA-Z0-9_].*\.(o|obj|dll|dylib|so)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o) + re(`[a-zA-Z0-9_/].*\.(a|o|obj|dll|dylib|so)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o) } var validLinkerFlagsWithNextArg = []string{ + "-arch", "-F", "-l", "-L", "-framework", + "-isysroot", + "--sysroot", + "-target", + "-Wl,-framework", + "-Wl,-rpath", + "-Wl,-undefined", } func checkCompilerFlags(name, source string, list []string) error { @@ -147,10 +222,21 @@ Args: i++ continue Args } + + // Permit -Wl,-framework -Wl,name. + if i+1 < len(list) && + strings.HasPrefix(arg, "-Wl,") && + strings.HasPrefix(list[i+1], "-Wl,") && + load.SafeArg(list[i+1][4:]) && + !strings.Contains(list[i+1][4:], ",") { + i++ + continue Args + } + if i+1 < len(list) { - return fmt.Errorf("invalid flag in %s: %s %s", source, arg, list[i+1]) + return fmt.Errorf("invalid flag in %s: %s %s (see https://golang.org/s/invalidflag)", source, arg, list[i+1]) } - return fmt.Errorf("invalid flag in %s: %s without argument", source, arg) + return fmt.Errorf("invalid flag in %s: %s without argument (see https://golang.org/s/invalidflag)", source, arg) } } Bad: diff --git a/libgo/go/cmd/go/internal/work/security_test.go b/libgo/go/cmd/go/internal/work/security_test.go index 739ab5a..bd898c9 100644 --- a/libgo/go/cmd/go/internal/work/security_test.go +++ b/libgo/go/cmd/go/internal/work/security_test.go @@ -132,14 +132,14 @@ var goodLinkerFlags = [][]string{ {"-l", "世界"}, {"-L", "framework"}, {"-framework", "Chocolate"}, + {"-Wl,-framework", "-Wl,Chocolate"}, + {"-Wl,-framework,Chocolate"}, + {"-Wl,-unresolved-symbols=ignore-all"}, } var badLinkerFlags = [][]string{ {"-DFOO"}, {"-Dfoo=bar"}, - {"-O"}, - {"-O2"}, - {"-Osmall"}, {"-W"}, {"-Wall"}, {"-fobjc-arc"}, @@ -152,7 +152,6 @@ var badLinkerFlags = [][]string{ {"-fno-stack-xxx"}, {"-mstack-overflow"}, {"-mno-stack-overflow"}, - {"-mmacosx-version"}, {"-mnop-fun-dllimport"}, {"-std=c99"}, {"-xc"}, @@ -185,6 +184,10 @@ var badLinkerFlags = [][]string{ {"-l", "-foo"}, {"-framework", "-Caffeine"}, {"-framework", "@Home"}, + {"-Wl,-framework,-Caffeine"}, + {"-Wl,-framework", "-Wl,@Home"}, + {"-Wl,-framework", "@Home"}, + {"-Wl,-framework,Chocolate,@Home"}, {"-x", "--c"}, {"-x", "@obj"}, {"-Wl,-rpath,@foo"}, diff --git a/libgo/go/cmd/go/mkalldocs.sh b/libgo/go/cmd/go/mkalldocs.sh new file mode 100755 index 0000000..72886db --- /dev/null +++ b/libgo/go/cmd/go/mkalldocs.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# Copyright 2012 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. + +set -e + +go build -o go.latest +./go.latest help documentation >alldocs.go +gofmt -w alldocs.go +rm go.latest diff --git a/libgo/go/cmd/go/mkdoc.sh b/libgo/go/cmd/go/mkdoc.sh deleted file mode 100644 index 12fd7ba..0000000 --- a/libgo/go/cmd/go/mkdoc.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -# Copyright 2012 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -go install # So the next line will produce updated documentation. -go help documentation > doc.go -gofmt -w doc.go - diff --git a/libgo/go/cmd/internal/objabi/funcid.go b/libgo/go/cmd/internal/objabi/funcid.go new file mode 100644 index 0000000..55f1328 --- /dev/null +++ b/libgo/go/cmd/internal/objabi/funcid.go @@ -0,0 +1,34 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package objabi + +// A FuncID identifies particular functions that need to be treated +// specially by the runtime. +// Note that in some situations involving plugins, there may be multiple +// copies of a particular special runtime function. +// Note: this list must match the list in runtime/symtab.go. +type FuncID uint32 + +const ( + FuncID_normal FuncID = iota // not a special function + FuncID_goexit + FuncID_jmpdefer + FuncID_mcall + FuncID_morestack + FuncID_mstart + FuncID_rt0_go + FuncID_asmcgocall + FuncID_sigpanic + FuncID_runfinq + FuncID_bgsweep + FuncID_forcegchelper + FuncID_timerproc + FuncID_gcBgMarkWorker + FuncID_systemstack_switch + FuncID_systemstack + FuncID_cgocallback_gofunc + FuncID_gogo + FuncID_externalthreadhandler +) diff --git a/libgo/go/cmd/vet/main.go b/libgo/go/cmd/vet/main.go index 9d28ebd..49c1d32 100644 --- a/libgo/go/cmd/vet/main.go +++ b/libgo/go/cmd/vet/main.go @@ -292,6 +292,7 @@ type vetConfig struct { GoFiles []string ImportMap map[string]string PackageFile map[string]string + Standard map[string]bool SucceedOnTypecheckFailure bool @@ -309,7 +310,12 @@ func (v *vetConfig) Import(path string) (*types.Package, error) { if p == "" { return nil, fmt.Errorf("unknown import path %q", path) } - if v.PackageFile[p] == "" && v.Compiler != "gccgo" { + if v.PackageFile[p] == "" { + if v.Compiler == "gccgo" && v.Standard[path] { + // gccgo doesn't have sources for standard library packages, + // but the importer will do the right thing. + return v.imp.Import(path) + } return nil, fmt.Errorf("unknown package file for import %q", path) } return v.imp.Import(p) @@ -318,6 +324,10 @@ func (v *vetConfig) Import(path string) (*types.Package, error) { func (v *vetConfig) openPackageFile(path string) (io.ReadCloser, error) { file := v.PackageFile[path] if file == "" { + if v.Compiler == "gccgo" && v.Standard[path] { + // The importer knows how to handle this. + return nil, nil + } // Note that path here has been translated via v.ImportMap, // unlike in the error in Import above. We prefer the error in // Import, but it's worth diagnosing this one too, just in case. diff --git a/libgo/go/crypto/x509/name_constraints_test.go b/libgo/go/crypto/x509/name_constraints_test.go index 10cc348..bad488f 100644 --- a/libgo/go/crypto/x509/name_constraints_test.go +++ b/libgo/go/crypto/x509/name_constraints_test.go @@ -11,6 +11,7 @@ import ( "crypto/rand" "crypto/x509/pkix" "encoding/asn1" + "encoding/hex" "encoding/pem" "fmt" "io/ioutil" @@ -42,6 +43,7 @@ type nameConstraintsTest struct { roots []constraintsSpec intermediates [][]constraintsSpec leaf leafSpec + requestedEKUs []ExtKeyUsage expectedError string noOpenSSL bool } @@ -1444,6 +1446,118 @@ var nameConstraintsTests = []nameConstraintsTest{ }, expectedError: "\"https://example.com/test\" is excluded", }, + + // #75: While serverAuth in a CA certificate permits clientAuth in a leaf, + // serverAuth in a leaf shouldn't permit clientAuth when requested in + // VerifyOptions. + nameConstraintsTest{ + roots: []constraintsSpec{ + constraintsSpec{}, + }, + intermediates: [][]constraintsSpec{ + []constraintsSpec{ + constraintsSpec{}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + ekus: []string{"serverAuth"}, + }, + requestedEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth}, + expectedError: "incompatible key usage", + }, + + // #76: However, MSSGC in a leaf should match a request for serverAuth. + nameConstraintsTest{ + roots: []constraintsSpec{ + constraintsSpec{}, + }, + intermediates: [][]constraintsSpec{ + []constraintsSpec{ + constraintsSpec{}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + ekus: []string{"msSGC"}, + }, + requestedEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, + }, + + // An invalid DNS SAN should be detected only at validation time so + // that we can process CA certificates in the wild that have invalid SANs. + // See https://github.com/golang/go/issues/23995 + + // #77: an invalid DNS or mail SAN will not be detected if name constaint + // checking is not triggered. + nameConstraintsTest{ + roots: []constraintsSpec{ + constraintsSpec{}, + }, + intermediates: [][]constraintsSpec{ + []constraintsSpec{ + constraintsSpec{}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:this is invalid", "email:this @ is invalid"}, + }, + }, + + // #78: an invalid DNS SAN will be detected if any name constraint checking + // is triggered. + nameConstraintsTest{ + roots: []constraintsSpec{ + constraintsSpec{ + bad: []string{"uri:"}, + }, + }, + intermediates: [][]constraintsSpec{ + []constraintsSpec{ + constraintsSpec{}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:this is invalid"}, + }, + expectedError: "cannot parse dnsName", + }, + + // #79: an invalid email SAN will be detected if any name constraint + // checking is triggered. + nameConstraintsTest{ + roots: []constraintsSpec{ + constraintsSpec{ + bad: []string{"uri:"}, + }, + }, + intermediates: [][]constraintsSpec{ + []constraintsSpec{ + constraintsSpec{}, + }, + }, + leaf: leafSpec{ + sans: []string{"email:this @ is invalid"}, + }, + expectedError: "cannot parse rfc822Name", + }, + + // #80: if several EKUs are requested, satisfying any of them is sufficient. + nameConstraintsTest{ + roots: []constraintsSpec{ + constraintsSpec{}, + }, + intermediates: [][]constraintsSpec{ + []constraintsSpec{ + constraintsSpec{}, + }, + }, + leaf: leafSpec{ + sans: []string{"dns:example.com"}, + ekus: []string{"email"}, + }, + requestedEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageEmailProtection}, + }, } func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) { @@ -1459,7 +1573,7 @@ func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa. NotAfter: time.Unix(2000, 0), KeyUsage: KeyUsageCertSign, BasicConstraintsValid: true, - IsCA: true, + IsCA: true, } if err := addConstraintsToTemplate(constraints, template); err != nil { @@ -1497,7 +1611,7 @@ func makeConstraintsLeafCert(leaf leafSpec, key *ecdsa.PrivateKey, parent *Certi NotAfter: time.Unix(2000, 0), KeyUsage: KeyUsageDigitalSignature, BasicConstraintsValid: true, - IsCA: false, + IsCA: false, } for _, name := range leaf.sans { @@ -1512,6 +1626,13 @@ func makeConstraintsLeafCert(leaf leafSpec, key *ecdsa.PrivateKey, parent *Certi } template.IPAddresses = append(template.IPAddresses, ip) + case strings.HasPrefix(name, "invalidip:"): + ipBytes, err := hex.DecodeString(name[10:]) + if err != nil { + return nil, fmt.Errorf("cannot parse invalid IP: %s", err) + } + template.IPAddresses = append(template.IPAddresses, net.IP(ipBytes)) + case strings.HasPrefix(name, "email:"): template.EmailAddresses = append(template.EmailAddresses, name[6:]) @@ -1781,6 +1902,7 @@ func TestConstraintCases(t *testing.T) { Roots: rootPool, Intermediates: intermediatePool, CurrentTime: time.Unix(1500, 0), + KeyUsages: test.requestedEKUs, } _, err = leafCert.Verify(verifyOpts) @@ -1972,12 +2094,13 @@ func TestBadNamesInConstraints(t *testing.T) { } func TestBadNamesInSANs(t *testing.T) { - // Bad names in SANs should not parse. + // Bad names in URI and IP SANs should not parse. Bad DNS and email SANs + // will parse and are tested in name constraint tests at the top of this + // file. badNames := []string{ - "dns:foo.com.", - "email:abc@foo.com.", - "email:foo.com.", "uri:https://example.com./dsf", + "invalidip:0102", + "invalidip:0102030405", } priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) diff --git a/libgo/go/crypto/x509/root_aix.go b/libgo/go/crypto/x509/root_aix.go index de5702d..4e7e9dd 100644 --- a/libgo/go/crypto/x509/root_aix.go +++ b/libgo/go/crypto/x509/root_aix.go @@ -5,4 +5,6 @@ package x509 // Possible certificate files; stop after finding one. -var certFiles []string +var certFiles = []string{ + "/var/ssl/certs/ca-bundle.crt", +} diff --git a/libgo/go/crypto/x509/verify.go b/libgo/go/crypto/x509/verify.go index 9477e85..0ea214b 100644 --- a/libgo/go/crypto/x509/verify.go +++ b/libgo/go/crypto/x509/verify.go @@ -6,12 +6,14 @@ package x509 import ( "bytes" + "encoding/asn1" "errors" "fmt" "net" "net/url" "reflect" "runtime" + "strconv" "strings" "time" "unicode/utf8" @@ -178,10 +180,14 @@ type VerifyOptions struct { Intermediates *CertPool Roots *CertPool // if nil, the system roots are used CurrentTime time.Time // if zero, the current time is used - // KeyUsage specifies which Extended Key Usage values are acceptable. - // An empty list means ExtKeyUsageServerAuth. Key usage is considered a - // constraint down the chain which mirrors Windows CryptoAPI behavior, - // but not the spec. To accept any key usage, include ExtKeyUsageAny. + // KeyUsage specifies which Extended Key Usage values are acceptable. A leaf + // certificate is accepted if it contains any of the listed values. An empty + // list means ExtKeyUsageServerAuth. To accept any key usage, include + // ExtKeyUsageAny. + // + // Certificate chains are required to nest extended key usage values, + // irrespective of this value. This matches the Windows CryptoAPI behavior, + // but not the spec. KeyUsages []ExtKeyUsage // MaxConstraintComparisions is the maximum number of comparisons to // perform when checking a given certificate's name constraints. If @@ -543,11 +549,16 @@ func (c *Certificate) checkNameConstraints(count *int, return nil } +const ( + checkingAgainstIssuerCert = iota + checkingAgainstLeafCert +) + // ekuPermittedBy returns true iff the given extended key usage is permitted by // the given EKU from a certificate. Normally, this would be a simple // comparison plus a special case for the “any” EKU. But, in order to support // existing certificates, some exceptions are made. -func ekuPermittedBy(eku, certEKU ExtKeyUsage) bool { +func ekuPermittedBy(eku, certEKU ExtKeyUsage, context int) bool { if certEKU == ExtKeyUsageAny || eku == certEKU { return true } @@ -564,18 +575,23 @@ func ekuPermittedBy(eku, certEKU ExtKeyUsage) bool { eku = mapServerAuthEKUs(eku) certEKU = mapServerAuthEKUs(certEKU) - if eku == certEKU || - // ServerAuth in a CA permits ClientAuth in the leaf. - (eku == ExtKeyUsageClientAuth && certEKU == ExtKeyUsageServerAuth) || + if eku == certEKU { + return true + } + + // If checking a requested EKU against the list in a leaf certificate there + // are fewer exceptions. + if context == checkingAgainstLeafCert { + return false + } + + // ServerAuth in a CA permits ClientAuth in the leaf. + return (eku == ExtKeyUsageClientAuth && certEKU == ExtKeyUsageServerAuth) || // Any CA may issue an OCSP responder certificate. eku == ExtKeyUsageOCSPSigning || // Code-signing CAs can use Microsoft's commercial and // kernel-mode EKUs. - ((eku == ExtKeyUsageMicrosoftCommercialCodeSigning || eku == ExtKeyUsageMicrosoftKernelCodeSigning) && certEKU == ExtKeyUsageCodeSigning) { - return true - } - - return false + (eku == ExtKeyUsageMicrosoftCommercialCodeSigning || eku == ExtKeyUsageMicrosoftKernelCodeSigning) && certEKU == ExtKeyUsageCodeSigning } // isValid performs validity checks on c given that it is a candidate to append @@ -630,8 +646,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V name := string(data) mailbox, ok := parseRFC2821Mailbox(name) if !ok { - // This certificate should not have parsed. - return errors.New("x509: internal error: rfc822Name SAN failed to parse") + return fmt.Errorf("x509: cannot parse rfc822Name %q", mailbox) } if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox, @@ -643,6 +658,10 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V case nameTypeDNS: name := string(data) + if _, ok := domainToReverseLabels(name); !ok { + return fmt.Errorf("x509: cannot parse dnsName %q", name) + } + if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name, func(parsedName, constraint interface{}) (bool, error) { return matchDomainConstraint(parsedName.(string), constraint.(string)) @@ -716,7 +735,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V for _, caEKU := range c.ExtKeyUsage { comparisonCount++ - if ekuPermittedBy(eku, caEKU) { + if ekuPermittedBy(eku, caEKU, checkingAgainstIssuerCert) { continue NextEKU } } @@ -773,6 +792,18 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V return nil } +// formatOID formats an ASN.1 OBJECT IDENTIFER in the common, dotted style. +func formatOID(oid asn1.ObjectIdentifier) string { + ret := "" + for i, v := range oid { + if i > 0 { + ret += "." + } + ret += strconv.Itoa(v) + } + return ret +} + // Verify attempts to verify c by building one or more chains from c to a // certificate in opts.Roots, using certificates in opts.Intermediates if // needed. If successful, it returns one or more chains where the first @@ -847,16 +878,33 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e } if checkEKU { + foundMatch := false NextUsage: for _, eku := range requestedKeyUsages { for _, leafEKU := range c.ExtKeyUsage { - if ekuPermittedBy(eku, leafEKU) { - continue NextUsage + if ekuPermittedBy(eku, leafEKU, checkingAgainstLeafCert) { + foundMatch = true + break NextUsage } } + } - oid, _ := oidFromExtKeyUsage(eku) - return nil, CertificateInvalidError{c, IncompatibleUsage, fmt.Sprintf("%#v", oid)} + if !foundMatch { + msg := "leaf contains the following, recognized EKUs: " + + for i, leafEKU := range c.ExtKeyUsage { + oid, ok := oidFromExtKeyUsage(leafEKU) + if !ok { + continue + } + + if i > 0 { + msg += ", " + } + msg += formatOID(oid) + } + + return nil, CertificateInvalidError{c, IncompatibleUsage, msg} } } diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go index 86d9e82..ee08dd9 100644 --- a/libgo/go/crypto/x509/x509.go +++ b/libgo/go/crypto/x509/x509.go @@ -706,7 +706,9 @@ type Certificate struct { OCSPServer []string IssuingCertificateURL []string - // Subject Alternate Name values + // Subject Alternate Name values. (Note that these values may not be valid + // if invalid values were contained within a parsed certificate. For + // example, an element of DNSNames may not be a valid DNS domain name.) DNSNames []string EmailAddresses []string IPAddresses []net.IP @@ -1126,17 +1128,9 @@ func parseSANExtension(value []byte) (dnsNames, emailAddresses []string, ipAddre err = forEachSAN(value, func(tag int, data []byte) error { switch tag { case nameTypeEmail: - mailbox := string(data) - if _, ok := parseRFC2821Mailbox(mailbox); !ok { - return fmt.Errorf("x509: cannot parse rfc822Name %q", mailbox) - } - emailAddresses = append(emailAddresses, mailbox) + emailAddresses = append(emailAddresses, string(data)) case nameTypeDNS: - domain := string(data) - if _, ok := domainToReverseLabels(domain); !ok { - return fmt.Errorf("x509: cannot parse dnsName %q", string(data)) - } - dnsNames = append(dnsNames, domain) + dnsNames = append(dnsNames, string(data)) case nameTypeURI: uri, err := url.Parse(string(data)) if err != nil { @@ -1153,7 +1147,7 @@ func parseSANExtension(value []byte) (dnsNames, emailAddresses []string, ipAddre case net.IPv4len, net.IPv6len: ipAddresses = append(ipAddresses, data) default: - return errors.New("x509: certificate contained IP address of length " + strconv.Itoa(len(data))) + return errors.New("x509: cannot parse IP address of length " + strconv.Itoa(len(data))) } } @@ -2543,7 +2537,7 @@ func ParseCertificateRequest(asn1Data []byte) (*CertificateRequest, error) { func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error) { out := &CertificateRequest{ - Raw: in.Raw, + Raw: in.Raw, RawTBSCertificateRequest: in.TBSCSR.Raw, RawSubjectPublicKeyInfo: in.TBSCSR.PublicKey.Raw, RawSubject: in.TBSCSR.Subject.FullBytes, diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go index 536f25d..730fb92 100644 --- a/libgo/go/encoding/json/decode.go +++ b/libgo/go/encoding/json/decode.go @@ -443,10 +443,25 @@ func (d *decodeState) valueQuoted() interface{} { // if it encounters an Unmarshaler, indirect stops and returns that. // if decodingNull is true, indirect stops at the last pointer so it can be set to nil. func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { + // Issue #24153 indicates that it is generally not a guaranteed property + // that you may round-trip a reflect.Value by calling Value.Addr().Elem() + // and expect the value to still be settable for values derived from + // unexported embedded struct fields. + // + // The logic below effectively does this when it first addresses the value + // (to satisfy possible pointer methods) and continues to dereference + // subsequent pointers as necessary. + // + // After the first round-trip, we set v back to the original value to + // preserve the original RW flags contained in reflect.Value. + v0 := v + haveAddr := false + // If v is a named type and is addressable, // start with its address, so that if the type has pointer methods, // we find them. if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { + haveAddr = true v = v.Addr() } for { @@ -455,6 +470,7 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, if v.Kind() == reflect.Interface && !v.IsNil() { e := v.Elem() if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) { + haveAddr = false v = e continue } @@ -480,7 +496,13 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, } } } - v = v.Elem() + + if haveAddr { + v = v0 // restore original value after round-trip Value.Addr().Elem() + haveAddr = false + } else { + v = v.Elem() + } } return nil, nil, v } diff --git a/libgo/go/encoding/json/decode_test.go b/libgo/go/encoding/json/decode_test.go index 34b7ec6..fa1531f 100644 --- a/libgo/go/encoding/json/decode_test.go +++ b/libgo/go/encoding/json/decode_test.go @@ -615,9 +615,9 @@ var unmarshalTests = []unmarshalTest{ out: S5{S8: S8{S9: S9{Y: 2}}}, }, { - in: `{"X": 1,"Y":2}`, - ptr: new(S5), - err: fmt.Errorf("json: unknown field \"X\""), + in: `{"X": 1,"Y":2}`, + ptr: new(S5), + err: fmt.Errorf("json: unknown field \"X\""), disallowUnknownFields: true, }, { @@ -626,9 +626,9 @@ var unmarshalTests = []unmarshalTest{ out: S10{S13: S13{S8: S8{S9: S9{Y: 2}}}}, }, { - in: `{"X": 1,"Y":2}`, - ptr: new(S10), - err: fmt.Errorf("json: unknown field \"X\""), + in: `{"X": 1,"Y":2}`, + ptr: new(S10), + err: fmt.Errorf("json: unknown field \"X\""), disallowUnknownFields: true, }, @@ -835,8 +835,8 @@ var unmarshalTests = []unmarshalTest{ "Q": 18, "extra": true }`, - ptr: new(Top), - err: fmt.Errorf("json: unknown field \"extra\""), + ptr: new(Top), + err: fmt.Errorf("json: unknown field \"extra\""), disallowUnknownFields: true, }, { @@ -862,8 +862,8 @@ var unmarshalTests = []unmarshalTest{ "Z": 17, "Q": 18 }`, - ptr: new(Top), - err: fmt.Errorf("json: unknown field \"extra\""), + ptr: new(Top), + err: fmt.Errorf("json: unknown field \"extra\""), disallowUnknownFields: true, }, } @@ -2089,10 +2089,14 @@ func TestInvalidStringOption(t *testing.T) { } } -// Test unmarshal behavior with regards to embedded pointers to unexported structs. -// If unallocated, this returns an error because unmarshal cannot set the field. -// Issue 21357. -func TestUnmarshalEmbeddedPointerUnexported(t *testing.T) { +// Test unmarshal behavior with regards to embedded unexported structs. +// +// (Issue 21357) If the embedded struct is a pointer and is unallocated, +// this returns an error because unmarshal cannot set the field. +// +// (Issue 24152) If the embedded struct is given an explicit name, +// ensure that the normal unmarshal logic does not panic in reflect. +func TestUnmarshalEmbeddedUnexported(t *testing.T) { type ( embed1 struct{ Q int } embed2 struct{ Q int } @@ -2119,6 +2123,18 @@ func TestUnmarshalEmbeddedPointerUnexported(t *testing.T) { *embed3 R int } + S6 struct { + embed1 `json:"embed1"` + } + S7 struct { + embed1 `json:"embed1"` + embed2 + } + S8 struct { + embed1 `json:"embed1"` + embed2 `json:"embed2"` + Q int + } ) tests := []struct { @@ -2154,6 +2170,32 @@ func TestUnmarshalEmbeddedPointerUnexported(t *testing.T) { ptr: new(S5), out: &S5{R: 2}, err: fmt.Errorf("json: cannot set embedded pointer to unexported struct: json.embed3"), + }, { + // Issue 24152, ensure decodeState.indirect does not panic. + in: `{"embed1": {"Q": 1}}`, + ptr: new(S6), + out: &S6{embed1{1}}, + }, { + // Issue 24153, check that we can still set forwarded fields even in + // the presence of a name conflict. + // + // This relies on obscure behavior of reflect where it is possible + // to set a forwarded exported field on an unexported embedded struct + // even though there is a name conflict, even when it would have been + // impossible to do so according to Go visibility rules. + // Go forbids this because it is ambiguous whether S7.Q refers to + // S7.embed1.Q or S7.embed2.Q. Since embed1 and embed2 are unexported, + // it should be impossible for an external package to set either Q. + // + // It is probably okay for a future reflect change to break this. + in: `{"embed1": {"Q": 1}, "Q": 2}`, + ptr: new(S7), + out: &S7{embed1{1}, embed2{2}}, + }, { + // Issue 24153, similar to the S7 case. + in: `{"embed1": {"Q": 1}, "embed2": {"Q": 2}, "Q": 3}`, + ptr: new(S8), + out: &S8{embed1{1}, embed2{2}, 3}, }} for i, tt := range tests { diff --git a/libgo/go/go/build/build.go b/libgo/go/go/build/build.go index 7902404..9df4930 100644 --- a/libgo/go/go/build/build.go +++ b/libgo/go/go/build/build.go @@ -238,7 +238,7 @@ func (ctxt *Context) gopath() []string { // that do not exist. func (ctxt *Context) SrcDirs() []string { var all []string - if ctxt.GOROOT != "" { + if ctxt.GOROOT != "" && ctxt.Compiler != "gccgo" { dir := ctxt.joinPath(ctxt.GOROOT, "src") if ctxt.isDir(dir) { all = append(all, dir) @@ -540,7 +540,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa inTestdata := func(sub string) bool { return strings.Contains(sub, "/testdata/") || strings.HasSuffix(sub, "/testdata") || strings.HasPrefix(sub, "testdata/") || sub == "testdata" } - if ctxt.GOROOT != "" { + if ctxt.GOROOT != "" && ctxt.Compiler != "gccgo" { root := ctxt.joinPath(ctxt.GOROOT, "src") if sub, ok := ctxt.hasSubdir(root, p.Dir); ok && !inTestdata(sub) { p.Goroot = true @@ -557,7 +557,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa // We found a potential import path for dir, // but check that using it wouldn't find something // else first. - if ctxt.GOROOT != "" { + if ctxt.GOROOT != "" && ctxt.Compiler != "gccgo" { if dir := ctxt.joinPath(ctxt.GOROOT, "src", sub); ctxt.isDir(dir) { p.ConflictDir = dir goto Found @@ -622,7 +622,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa } return false } - if searchVendor(ctxt.GOROOT, true) { + if ctxt.Compiler != "gccgo" && searchVendor(ctxt.GOROOT, true) { goto Found } for _, root := range gopath { @@ -635,16 +635,24 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa // Determine directory from import path. if ctxt.GOROOT != "" { dir := ctxt.joinPath(ctxt.GOROOT, "src", path) - isDir := ctxt.isDir(dir) - binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(ctxt.GOROOT, pkga)) - if isDir || binaryOnly { - p.Dir = dir - p.Goroot = true - p.Root = ctxt.GOROOT - goto Found + if ctxt.Compiler != "gccgo" { + isDir := ctxt.isDir(dir) + binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(ctxt.GOROOT, pkga)) + if isDir || binaryOnly { + p.Dir = dir + p.Goroot = true + p.Root = ctxt.GOROOT + goto Found + } } tried.goroot = dir } + if ctxt.Compiler == "gccgo" && isStandardPackage(path) { + p.Dir = ctxt.joinPath(ctxt.GOROOT, "src", path) + p.Goroot = true + p.Root = ctxt.GOROOT + goto Found + } for _, root := range gopath { dir := ctxt.joinPath(root, "src", path) isDir := ctxt.isDir(dir) @@ -708,6 +716,11 @@ Found: return p, pkgerr } + if ctxt.Compiler == "gccgo" && p.Goroot { + // gccgo has no sources for GOROOT packages. + return p, nil + } + dirs, err := ctxt.readDir(p.Dir) if err != nil { return p, err @@ -1595,14 +1608,7 @@ func init() { } } -func getToolDir() string { - if runtime.Compiler == "gccgo" { - return envOr("GCCGOTOOLDIR", runtime.GCCGOTOOLDIR) - } else { - return filepath.Join(runtime.GOROOT(), "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH) - } -} - +// ToolDir is the directory containing build tools. var ToolDir = getToolDir() // IsLocalImport reports whether the import path is diff --git a/libgo/go/go/build/gc.go b/libgo/go/go/build/gc.go new file mode 100644 index 0000000..e2be2cb --- /dev/null +++ b/libgo/go/go/build/gc.go @@ -0,0 +1,137 @@ +// Copyright 2018 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 gc + +package build + +import ( + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "sync" +) + +// getToolDir returns the default value of ToolDir. +func getToolDir() string { + return filepath.Join(runtime.GOROOT(), "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH) +} + +// isStandardPackage is not used for the gc toolchain. +// However, this function may be called when using `go build -compiler=gccgo`. +func isStandardPackage(path string) bool { + return gccgoSearch.isStandard(path) +} + +// gccgoSearch holds the gccgo search directories. +type gccgoDirs struct { + once sync.Once + dirs []string +} + +// gccgoSearch is used to check whether a gccgo package exists in the +// standard library. +var gccgoSearch gccgoDirs + +// init finds the gccgo search directories. If this fails it leaves dirs == nil. +func (gd *gccgoDirs) init() { + gccgo := os.Getenv("GCCGO") + if gccgo == "" { + gccgo = "gccgo" + } + bin, err := exec.LookPath(gccgo) + if err != nil { + return + } + + allDirs, err := exec.Command(bin, "-print-search-dirs").Output() + if err != nil { + return + } + versionB, err := exec.Command(bin, "-dumpversion").Output() + if err != nil { + return + } + version := strings.TrimSpace(string(versionB)) + machineB, err := exec.Command(bin, "-dumpmachine").Output() + if err != nil { + return + } + machine := strings.TrimSpace(string(machineB)) + + dirsEntries := strings.Split(string(allDirs), "\n") + const prefix = "libraries: =" + var dirs []string + for _, dirEntry := range dirsEntries { + if strings.HasPrefix(dirEntry, prefix) { + dirs = filepath.SplitList(strings.TrimPrefix(dirEntry, prefix)) + break + } + } + if len(dirs) == 0 { + return + } + + var lastDirs []string + for _, dir := range dirs { + goDir := filepath.Join(dir, "go", version) + if fi, err := os.Stat(goDir); err == nil && fi.IsDir() { + gd.dirs = append(gd.dirs, goDir) + goDir = filepath.Join(goDir, machine) + if fi, err = os.Stat(goDir); err == nil && fi.IsDir() { + gd.dirs = append(gd.dirs, goDir) + } + } + if fi, err := os.Stat(dir); err == nil && fi.IsDir() { + lastDirs = append(lastDirs, dir) + } + } + gd.dirs = append(gd.dirs, lastDirs...) +} + +// isStandard returns whether path is a standard library for gccgo. +func (gd *gccgoDirs) isStandard(path string) bool { + // Quick check: if the first path component has a '.', it's not + // in the standard library. This skips most GOPATH directories. + i := strings.Index(path, "/") + if i < 0 { + i = len(path) + } + if strings.Contains(path[:i], ".") { + return false + } + + if path == "unsafe" { + // Special case. + return true + } + + gd.once.Do(gd.init) + if gd.dirs == nil { + // We couldn't find the gccgo search directories. + // Best guess, since the first component did not contain + // '.', is that this is a standard library package. + return true + } + + for _, dir := range gd.dirs { + full := filepath.Join(dir, path) + pkgdir, pkg := filepath.Split(full) + for _, p := range [...]string{ + full, + full + ".gox", + pkgdir + "lib" + pkg + ".so", + pkgdir + "lib" + pkg + ".a", + full + ".o", + } { + if fi, err := os.Stat(p); err == nil && !fi.IsDir() { + return true + } + } + } + + return false +} diff --git a/libgo/go/go/build/gccgo.go b/libgo/go/go/build/gccgo.go new file mode 100644 index 0000000..59e089d --- /dev/null +++ b/libgo/go/go/build/gccgo.go @@ -0,0 +1,20 @@ +// Copyright 2018 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 gccgo + +package build + +import "runtime" + +// getToolDir returns the default value of ToolDir. +func getToolDir() string { + return envOr("GCCGOTOOLDIR", runtime.GCCGOTOOLDIR) +} + +// isStandardPackage returns whether path names a standard library package. +// This uses a list generated at build time. +func isStandardPackage(path string) bool { + return stdpkg[path] +} diff --git a/libgo/go/go/build/syslist.go b/libgo/go/go/build/syslist.go index 679d195..0c39634 100644 --- a/libgo/go/go/build/syslist.go +++ b/libgo/go/go/build/syslist.go @@ -5,4 +5,4 @@ package build const goosList = "aix android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows zos " -const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be alpha m68k ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc riscv64 s390 s390x sh shbe sparc sparc64" +const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be alpha m68k ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le nios2 ppc riscv64 s390 s390x sh shbe sparc sparc64" diff --git a/libgo/go/go/internal/gccgoimporter/importer.go b/libgo/go/go/internal/gccgoimporter/importer.go index 843d196..ddaed40 100644 --- a/libgo/go/go/internal/gccgoimporter/importer.go +++ b/libgo/go/go/internal/gccgoimporter/importer.go @@ -176,7 +176,7 @@ func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Impo return p, nil } rc, err := lookup(pkgpath) - if err == nil { + if err == nil && rc != nil { defer rc.Close() rs, ok := rc.(io.ReadSeeker) if !ok { diff --git a/libgo/go/go/internal/srcimporter/srcimporter.go b/libgo/go/go/internal/srcimporter/srcimporter.go index b0dc8ab..9ed7e5e 100644 --- a/libgo/go/go/internal/srcimporter/srcimporter.go +++ b/libgo/go/go/internal/srcimporter/srcimporter.go @@ -44,9 +44,9 @@ func New(ctxt *build.Context, fset *token.FileSet, packages map[string]*types.Pa // for a package that is in the process of being imported. var importing types.Package -// Import(path) is a shortcut for ImportFrom(path, "", 0). +// Import(path) is a shortcut for ImportFrom(path, ".", 0). func (p *Importer) Import(path string) (*types.Package, error) { - return p.ImportFrom(path, "", 0) + return p.ImportFrom(path, ".", 0) // use "." rather than "" (see issue #24441) } // ImportFrom imports the package with the given import path resolved from the given srcDir, @@ -60,23 +60,10 @@ func (p *Importer) ImportFrom(path, srcDir string, mode types.ImportMode) (*type panic("non-zero import mode") } - // determine package path (do vendor resolution) - var bp *build.Package - var err error - switch { - default: - if abs, err := p.absPath(srcDir); err == nil { // see issue #14282 - srcDir = abs - } - bp, err = p.ctxt.Import(path, srcDir, build.FindOnly) - - case build.IsLocalImport(path): - // "./x" -> "srcDir/x" - bp, err = p.ctxt.ImportDir(filepath.Join(srcDir, path), build.FindOnly) - - case p.isAbsPath(path): - return nil, fmt.Errorf("invalid absolute import path %q", path) + if abs, err := p.absPath(srcDir); err == nil { // see issue #14282 + srcDir = abs } + bp, err := p.ctxt.Import(path, srcDir, 0) if err != nil { return nil, err // err may be *build.NoGoError - return as is } @@ -113,11 +100,6 @@ func (p *Importer) ImportFrom(path, srcDir string, mode types.ImportMode) (*type } }() - // collect package files - bp, err = p.ctxt.ImportDir(bp.Dir, 0) - if err != nil { - return nil, err // err may be *build.NoGoError - return as is - } var filenames []string filenames = append(filenames, bp.GoFiles...) filenames = append(filenames, bp.CgoFiles...) diff --git a/libgo/go/go/internal/srcimporter/srcimporter_test.go b/libgo/go/go/internal/srcimporter/srcimporter_test.go index 356e71d..dd4d56a 100644 --- a/libgo/go/go/internal/srcimporter/srcimporter_test.go +++ b/libgo/go/go/internal/srcimporter/srcimporter_test.go @@ -10,6 +10,7 @@ import ( "go/types" "internal/testenv" "io/ioutil" + "path" "path/filepath" "runtime" "strings" @@ -162,3 +163,34 @@ func TestIssue20855(t *testing.T) { t.Error("got no package despite no hard errors") } } + +func testImportPath(t *testing.T, pkgPath string) { + if !testenv.HasSrc() { + t.Skip("no source code available") + } + + pkgName := path.Base(pkgPath) + + pkg, err := importer.Import(pkgPath) + if err != nil { + t.Fatal(err) + } + + if pkg.Name() != pkgName { + t.Errorf("got %q; want %q", pkg.Name(), pkgName) + } + + if pkg.Path() != pkgPath { + t.Errorf("got %q; want %q", pkg.Path(), pkgPath) + } +} + +// TestIssue23092 tests relative imports. +func TestIssue23092(t *testing.T) { + testImportPath(t, "./testdata/issue23092") +} + +// TestIssue24392 tests imports against a path containing 'testdata'. +func TestIssue24392(t *testing.T) { + testImportPath(t, "go/internal/srcimporter/testdata/issue24392") +} diff --git a/libgo/go/go/internal/srcimporter/testdata/issue23092/issue23092.go b/libgo/go/go/internal/srcimporter/testdata/issue23092/issue23092.go new file mode 100644 index 0000000..608698b --- /dev/null +++ b/libgo/go/go/internal/srcimporter/testdata/issue23092/issue23092.go @@ -0,0 +1,5 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue23092 diff --git a/libgo/go/go/internal/srcimporter/testdata/issue24392/issue24392.go b/libgo/go/go/internal/srcimporter/testdata/issue24392/issue24392.go new file mode 100644 index 0000000..8ad5221 --- /dev/null +++ b/libgo/go/go/internal/srcimporter/testdata/issue24392/issue24392.go @@ -0,0 +1,5 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue24392 diff --git a/libgo/go/internal/singleflight/singleflight.go b/libgo/go/internal/singleflight/singleflight.go index 1e9960d..b2d82e2 100644 --- a/libgo/go/internal/singleflight/singleflight.go +++ b/libgo/go/internal/singleflight/singleflight.go @@ -103,11 +103,21 @@ func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) { g.mu.Unlock() } -// Forget tells the singleflight to forget about a key. Future calls -// to Do for this key will call the function rather than waiting for -// an earlier call to complete. -func (g *Group) Forget(key string) { +// ForgetUnshared tells the singleflight to forget about a key if it is not +// shared with any other goroutines. Future calls to Do for a forgotten key +// will call the function rather than waiting for an earlier call to complete. +// Returns whether the key was forgotten or unknown--that is, whether no +// other goroutines are waiting for the result. +func (g *Group) ForgetUnshared(key string) bool { g.mu.Lock() - delete(g.m, key) - g.mu.Unlock() + defer g.mu.Unlock() + c, ok := g.m[key] + if !ok { + return true + } + if c.dups == 0 { + delete(g.m, key) + return true + } + return false } diff --git a/libgo/go/internal/syscall/unix/getrandom_linux_generic.go b/libgo/go/internal/syscall/unix/getrandom_linux_generic.go index d6af3de..2d513df 100644 --- a/libgo/go/internal/syscall/unix/getrandom_linux_generic.go +++ b/libgo/go/internal/syscall/unix/getrandom_linux_generic.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 arm64 riscv64 +// +build arm64 nios2 riscv64 package unix diff --git a/libgo/go/net/http/pprof/pprof.go b/libgo/go/net/http/pprof/pprof.go index 21992d6..77e0bcd 100644 --- a/libgo/go/net/http/pprof/pprof.go +++ b/libgo/go/net/http/pprof/pprof.go @@ -80,6 +80,7 @@ func init() { // command line, with arguments separated by NUL bytes. // The package initialization registers it as /debug/pprof/cmdline. func Cmdline(w http.ResponseWriter, r *http.Request) { + w.Header().Set("X-Content-Type-Options", "nosniff") w.Header().Set("Content-Type", "text/plain; charset=utf-8") fmt.Fprintf(w, strings.Join(os.Args, "\x00")) } @@ -100,33 +101,36 @@ func durationExceedsWriteTimeout(r *http.Request, seconds float64) bool { return ok && srv.WriteTimeout != 0 && seconds >= srv.WriteTimeout.Seconds() } +func serveError(w http.ResponseWriter, status int, txt string) { + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + w.Header().Set("X-Go-Pprof", "1") + w.Header().Del("Content-Disposition") + w.WriteHeader(status) + fmt.Fprintln(w, txt) +} + // Profile responds with the pprof-formatted cpu profile. // The package initialization registers it as /debug/pprof/profile. func Profile(w http.ResponseWriter, r *http.Request) { + w.Header().Set("X-Content-Type-Options", "nosniff") sec, _ := strconv.ParseInt(r.FormValue("seconds"), 10, 64) if sec == 0 { sec = 30 } if durationExceedsWriteTimeout(r, float64(sec)) { - w.Header().Set("Content-Type", "text/plain; charset=utf-8") - w.Header().Set("X-Go-Pprof", "1") - w.WriteHeader(http.StatusBadRequest) - fmt.Fprintln(w, "profile duration exceeds server's WriteTimeout") + serveError(w, http.StatusBadRequest, "profile duration exceeds server's WriteTimeout") return } // Set Content Type assuming StartCPUProfile will work, // because if it does it starts writing. w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Disposition", `attachment; filename="profile"`) if err := pprof.StartCPUProfile(w); err != nil { // StartCPUProfile failed, so no writes yet. - // Can change header back to text content - // and send error code. - w.Header().Set("Content-Type", "text/plain; charset=utf-8") - w.Header().Set("X-Go-Pprof", "1") - w.WriteHeader(http.StatusInternalServerError) - fmt.Fprintf(w, "Could not enable CPU profiling: %s\n", err) + serveError(w, http.StatusInternalServerError, + fmt.Sprintf("Could not enable CPU profiling: %s", err)) return } sleep(w, time.Duration(sec)*time.Second) @@ -137,29 +141,25 @@ func Profile(w http.ResponseWriter, r *http.Request) { // Tracing lasts for duration specified in seconds GET parameter, or for 1 second if not specified. // The package initialization registers it as /debug/pprof/trace. func Trace(w http.ResponseWriter, r *http.Request) { + w.Header().Set("X-Content-Type-Options", "nosniff") sec, err := strconv.ParseFloat(r.FormValue("seconds"), 64) if sec <= 0 || err != nil { sec = 1 } if durationExceedsWriteTimeout(r, sec) { - w.Header().Set("Content-Type", "text/plain; charset=utf-8") - w.Header().Set("X-Go-Pprof", "1") - w.WriteHeader(http.StatusBadRequest) - fmt.Fprintln(w, "profile duration exceeds server's WriteTimeout") + serveError(w, http.StatusBadRequest, "profile duration exceeds server's WriteTimeout") return } // Set Content Type assuming trace.Start will work, // because if it does it starts writing. w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Disposition", `attachment; filename="trace"`) if err := trace.Start(w); err != nil { // trace.Start failed, so no writes yet. - // Can change header back to text content and send error code. - w.Header().Set("Content-Type", "text/plain; charset=utf-8") - w.Header().Set("X-Go-Pprof", "1") - w.WriteHeader(http.StatusInternalServerError) - fmt.Fprintf(w, "Could not enable tracing: %s\n", err) + serveError(w, http.StatusInternalServerError, + fmt.Sprintf("Could not enable tracing: %s", err)) return } sleep(w, time.Duration(sec*float64(time.Second))) @@ -170,6 +170,7 @@ func Trace(w http.ResponseWriter, r *http.Request) { // responding with a table mapping program counters to function names. // The package initialization registers it as /debug/pprof/symbol. func Symbol(w http.ResponseWriter, r *http.Request) { + w.Header().Set("X-Content-Type-Options", "nosniff") w.Header().Set("Content-Type", "text/plain; charset=utf-8") // We have to read the whole POST body before @@ -222,18 +223,23 @@ func Handler(name string) http.Handler { type handler string func (name handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/plain; charset=utf-8") - debug, _ := strconv.Atoi(r.FormValue("debug")) + w.Header().Set("X-Content-Type-Options", "nosniff") p := pprof.Lookup(string(name)) if p == nil { - w.WriteHeader(404) - fmt.Fprintf(w, "Unknown profile: %s\n", name) + serveError(w, http.StatusNotFound, "Unknown profile") return } gc, _ := strconv.Atoi(r.FormValue("gc")) if name == "heap" && gc > 0 { runtime.GC() } + debug, _ := strconv.Atoi(r.FormValue("debug")) + if debug != 0 { + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + } else { + w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, name)) + } p.WriteTo(w, debug) } diff --git a/libgo/go/net/http/pprof/pprof_test.go b/libgo/go/net/http/pprof/pprof_test.go new file mode 100644 index 0000000..47dd35b --- /dev/null +++ b/libgo/go/net/http/pprof/pprof_test.go @@ -0,0 +1,69 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package pprof + +import ( + "bytes" + "io/ioutil" + "net/http" + "net/http/httptest" + "testing" +) + +func TestHandlers(t *testing.T) { + testCases := []struct { + path string + handler http.HandlerFunc + statusCode int + contentType string + contentDisposition string + resp []byte + }{ + {"/debug/pprof/<script>scripty<script>", Index, http.StatusNotFound, "text/plain; charset=utf-8", "", []byte("Unknown profile\n")}, + {"/debug/pprof/heap", Index, http.StatusOK, "application/octet-stream", `attachment; filename="heap"`, nil}, + {"/debug/pprof/heap?debug=1", Index, http.StatusOK, "text/plain; charset=utf-8", "", nil}, + {"/debug/pprof/cmdline", Cmdline, http.StatusOK, "text/plain; charset=utf-8", "", nil}, + {"/debug/pprof/profile?seconds=1", Profile, http.StatusOK, "application/octet-stream", `attachment; filename="profile"`, nil}, + {"/debug/pprof/symbol", Symbol, http.StatusOK, "text/plain; charset=utf-8", "", nil}, + {"/debug/pprof/trace", Trace, http.StatusOK, "application/octet-stream", `attachment; filename="trace"`, nil}, + } + for _, tc := range testCases { + t.Run(tc.path, func(t *testing.T) { + req := httptest.NewRequest("GET", "http://example.com"+tc.path, nil) + w := httptest.NewRecorder() + tc.handler(w, req) + + resp := w.Result() + if got, want := resp.StatusCode, tc.statusCode; got != want { + t.Errorf("status code: got %d; want %d", got, want) + } + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Errorf("when reading response body, expected non-nil err; got %v", err) + } + if got, want := resp.Header.Get("X-Content-Type-Options"), "nosniff"; got != want { + t.Errorf("X-Content-Type-Options: got %q; want %q", got, want) + } + if got, want := resp.Header.Get("Content-Type"), tc.contentType; got != want { + t.Errorf("Content-Type: got %q; want %q", got, want) + } + if got, want := resp.Header.Get("Content-Disposition"), tc.contentDisposition; got != want { + t.Errorf("Content-Disposition: got %q; want %q", got, want) + } + + if resp.StatusCode == http.StatusOK { + return + } + if got, want := resp.Header.Get("X-Go-Pprof"), "1"; got != want { + t.Errorf("X-Go-Pprof: got %q; want %q", got, want) + } + if !bytes.Equal(body, tc.resp) { + t.Errorf("response: got %q; want %q", body, tc.resp) + } + }) + } + +} diff --git a/libgo/go/net/lookup.go b/libgo/go/net/lookup.go index 85e4729..a65b735 100644 --- a/libgo/go/net/lookup.go +++ b/libgo/go/net/lookup.go @@ -194,10 +194,16 @@ func (r *Resolver) LookupIPAddr(ctx context.Context, host string) ([]IPAddr, err resolverFunc = alt } + // We don't want a cancelation of ctx to affect the + // lookupGroup operation. Otherwise if our context gets + // canceled it might cause an error to be returned to a lookup + // using a completely different context. + lookupGroupCtx, lookupGroupCancel := context.WithCancel(context.Background()) + dnsWaitGroup.Add(1) ch, called := lookupGroup.DoChan(host, func() (interface{}, error) { defer dnsWaitGroup.Done() - return testHookLookupIP(ctx, resolverFunc, host) + return testHookLookupIP(lookupGroupCtx, resolverFunc, host) }) if !called { dnsWaitGroup.Done() @@ -205,20 +211,28 @@ func (r *Resolver) LookupIPAddr(ctx context.Context, host string) ([]IPAddr, err select { case <-ctx.Done(): - // If the DNS lookup timed out for some reason, force - // future requests to start the DNS lookup again - // rather than waiting for the current lookup to - // complete. See issue 8602. - ctxErr := ctx.Err() - if ctxErr == context.DeadlineExceeded { - lookupGroup.Forget(host) + // Our context was canceled. If we are the only + // goroutine looking up this key, then drop the key + // from the lookupGroup and cancel the lookup. + // If there are other goroutines looking up this key, + // let the lookup continue uncanceled, and let later + // lookups with the same key share the result. + // See issues 8602, 20703, 22724. + if lookupGroup.ForgetUnshared(host) { + lookupGroupCancel() + } else { + go func() { + <-ch + lookupGroupCancel() + }() } - err := mapErr(ctxErr) + err := mapErr(ctx.Err()) if trace != nil && trace.DNSDone != nil { trace.DNSDone(nil, false, err) } return nil, err case r := <-ch: + lookupGroupCancel() if trace != nil && trace.DNSDone != nil { addrs, _ := r.Val.([]IPAddr) trace.DNSDone(ipAddrsEface(addrs), r.Shared, r.Err) diff --git a/libgo/go/net/lookup_test.go b/libgo/go/net/lookup_test.go index bfb8725..24787cc 100644 --- a/libgo/go/net/lookup_test.go +++ b/libgo/go/net/lookup_test.go @@ -791,3 +791,28 @@ func TestLookupNonLDH(t *testing.T) { t.Fatalf("lookup error = %v, want %v", err, errNoSuchHost) } } + +func TestLookupContextCancel(t *testing.T) { + if testenv.Builder() == "" { + testenv.MustHaveExternalNetwork(t) + } + if runtime.GOOS == "nacl" { + t.Skip("skip on nacl") + } + + defer dnsWaitGroup.Wait() + + ctx, ctxCancel := context.WithCancel(context.Background()) + ctxCancel() + _, err := DefaultResolver.LookupIPAddr(ctx, "google.com") + if err != errCanceled { + testenv.SkipFlakyNet(t) + t.Fatal(err) + } + ctx = context.Background() + _, err = DefaultResolver.LookupIPAddr(ctx, "google.com") + if err != nil { + testenv.SkipFlakyNet(t) + t.Fatal(err) + } +} diff --git a/libgo/go/net/tcpsock_unix_test.go b/libgo/go/net/tcpsock_unix_test.go index 3af1834..95c02d2 100644 --- a/libgo/go/net/tcpsock_unix_test.go +++ b/libgo/go/net/tcpsock_unix_test.go @@ -87,6 +87,7 @@ func TestTCPSpuriousConnSetupCompletionWithCancel(t *testing.T) { if testenv.Builder() == "" { testenv.MustHaveExternalNetwork(t) } + defer dnsWaitGroup.Wait() t.Parallel() const tries = 10000 var wg sync.WaitGroup diff --git a/libgo/go/os/signal/signal_cgo_test.go b/libgo/go/os/signal/signal_cgo_test.go index 84a2a08..16aeea8 100644 --- a/libgo/go/os/signal/signal_cgo_test.go +++ b/libgo/go/os/signal/signal_cgo_test.go @@ -89,6 +89,8 @@ func TestTerminalSignal(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() cmd := exec.CommandContext(ctx, bash, "--norc", "--noprofile", "-i") + // Clear HISTFILE so that we don't read or clobber the user's bash history. + cmd.Env = append(os.Environ(), "HISTFILE=") cmd.Stdin = slave cmd.Stdout = slave cmd.Stderr = slave diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go index 3070aac..96b57ef 100644 --- a/libgo/go/reflect/all_test.go +++ b/libgo/go/reflect/all_test.go @@ -3928,8 +3928,8 @@ func TestOverflow(t *testing.T) { } } -func checkSameType(t *testing.T, x, y interface{}) { - if TypeOf(x) != TypeOf(y) { +func checkSameType(t *testing.T, x Type, y interface{}) { + if x != TypeOf(y) || TypeOf(Zero(x).Interface()) != TypeOf(y) { t.Errorf("did not find preexisting type for %s (vs %s)", TypeOf(x), TypeOf(y)) } } @@ -4058,7 +4058,7 @@ func TestArrayOf(t *testing.T) { // check that type already in binary is found type T int - checkSameType(t, Zero(ArrayOf(5, TypeOf(T(1)))).Interface(), [5]T{}) + checkSameType(t, ArrayOf(5, TypeOf(T(1))), [5]T{}) } func TestArrayOfGC(t *testing.T) { @@ -4195,7 +4195,7 @@ func TestSliceOf(t *testing.T) { // check that type already in binary is found type T1 int - checkSameType(t, Zero(SliceOf(TypeOf(T1(1)))).Interface(), []T1{}) + checkSameType(t, SliceOf(TypeOf(T1(1))), []T1{}) } func TestSliceOverflow(t *testing.T) { @@ -4410,7 +4410,18 @@ func TestStructOf(t *testing.T) { }) }) // check that type already in binary is found - checkSameType(t, Zero(StructOf(fields[2:3])).Interface(), struct{ Y uint64 }{}) + checkSameType(t, StructOf(fields[2:3]), struct{ Y uint64 }{}) + + // gccgo used to fail this test. + type structFieldType interface{} + checkSameType(t, + StructOf([]StructField{ + StructField{ + Name: "F", + Type: TypeOf((*structFieldType)(nil)).Elem(), + }, + }), + struct{ F structFieldType }{}) } func TestStructOfExportRules(t *testing.T) { @@ -4963,7 +4974,7 @@ func TestChanOf(t *testing.T) { // check that type already in binary is found type T1 int - checkSameType(t, Zero(ChanOf(BothDir, TypeOf(T1(1)))).Interface(), (chan T1)(nil)) + checkSameType(t, ChanOf(BothDir, TypeOf(T1(1))), (chan T1)(nil)) } func TestChanOfDir(t *testing.T) { @@ -4974,8 +4985,8 @@ func TestChanOfDir(t *testing.T) { // check that type already in binary is found type T1 int - checkSameType(t, Zero(ChanOf(RecvDir, TypeOf(T1(1)))).Interface(), (<-chan T1)(nil)) - checkSameType(t, Zero(ChanOf(SendDir, TypeOf(T1(1)))).Interface(), (chan<- T1)(nil)) + checkSameType(t, ChanOf(RecvDir, TypeOf(T1(1))), (<-chan T1)(nil)) + checkSameType(t, ChanOf(SendDir, TypeOf(T1(1))), (chan<- T1)(nil)) // check String form of ChanDir if crt.ChanDir().String() != "<-chan" { @@ -5051,7 +5062,7 @@ func TestMapOf(t *testing.T) { } // check that type already in binary is found - checkSameType(t, Zero(MapOf(TypeOf(V(0)), TypeOf(K("")))).Interface(), map[V]K(nil)) + checkSameType(t, MapOf(TypeOf(V(0)), TypeOf(K(""))), map[V]K(nil)) // check that invalid key type panics shouldPanic(func() { MapOf(TypeOf((func())(nil)), TypeOf(false)) }) @@ -5181,7 +5192,7 @@ func TestFuncOf(t *testing.T) { {in: []Type{TypeOf(int(0))}, out: []Type{TypeOf(false), TypeOf("")}, want: (func(int) (bool, string))(nil)}, } for _, tt := range testCases { - checkSameType(t, Zero(FuncOf(tt.in, tt.out, tt.variadic)).Interface(), tt.want) + checkSameType(t, FuncOf(tt.in, tt.out, tt.variadic), tt.want) } // check that variadic requires last element be a slice. diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go index 6b082c1..07fe4d0 100644 --- a/libgo/go/reflect/type.go +++ b/libgo/go/reflect/type.go @@ -1475,8 +1475,10 @@ func ChanOf(dir ChanDir, t Type) Type { ch.uncommonType = nil ch.ptrToThis = nil - ti, _ := lookupCache.LoadOrStore(ckey, &ch.rtype) - return ti.(Type) + // Canonicalize before storing in lookupCache + ti := toType(&ch.rtype) + lookupCache.Store(ckey, ti.(*rtype)) + return ti } func ismapkey(*rtype) bool // implemented in runtime @@ -1537,8 +1539,10 @@ func MapOf(key, elem Type) Type { mt.reflexivekey = isReflexive(ktyp) mt.needkeyupdate = needKeyUpdate(ktyp) - ti, _ := lookupCache.LoadOrStore(ckey, &mt.rtype) - return ti.(Type) + // Canonicalize before storing in lookupCache + ti := toType(&mt.rtype) + lookupCache.Store(ckey, ti.(*rtype)) + return ti } // FuncOf returns the function type with the given argument and result types. @@ -1621,7 +1625,10 @@ func FuncOf(in, out []Type, variadic bool) Type { ft.string = &str ft.uncommonType = nil ft.ptrToThis = nil - return addToCache(&ft.rtype) + + // Canonicalize before storing in funcLookupCache + tc := toType(&ft.rtype) + return addToCache(tc.(*rtype)) } // funcStr builds a string representation of a funcType. @@ -1855,8 +1862,10 @@ func SliceOf(t Type) Type { slice.uncommonType = nil slice.ptrToThis = nil - ti, _ := lookupCache.LoadOrStore(ckey, &slice.rtype) - return ti.(Type) + // Canonicalize before storing in lookupCache + ti := toType(&slice.rtype) + lookupCache.Store(ckey, ti.(*rtype)) + return ti } // The structLookupCache caches StructOf lookups. @@ -1903,7 +1912,7 @@ func isValidFieldName(fieldName string) bool { // This limitation may be lifted in a future version. func StructOf(fields []StructField) Type { var ( - hash = uint32(0) + hash = uint32(12) size uintptr typalign int8 comparable = true @@ -1988,7 +1997,7 @@ func StructOf(fields []StructField) Type { } fset[name] = struct{}{} - repr = append(repr, (" " + ft.String())...) + repr = append(repr, (" " + *ft.string)...) if f.tag != nil { repr = append(repr, (" " + strconv.Quote(*f.tag))...) } @@ -2172,7 +2181,9 @@ func StructOf(fields []StructField) Type { typ.uncommonType = nil typ.ptrToThis = nil - return addToCache(&typ.rtype) + // Canonicalize before storing in structLookupCache + ti := toType(&typ.rtype) + return addToCache(ti.(*rtype)) } func runtimeStructField(field StructField) structField { @@ -2400,8 +2411,10 @@ func ArrayOf(count int, elem Type) Type { } } - ti, _ := lookupCache.LoadOrStore(ckey, &array.rtype) - return ti.(Type) + // Canonicalize before storing in lookupCache + ti := toType(&array.rtype) + lookupCache.Store(ckey, ti.(*rtype)) + return ti } func appendVarint(x []byte, v uintptr) []byte { diff --git a/libgo/go/runtime/crash_test.go b/libgo/go/runtime/crash_test.go index 7a099be..602630d 100644 --- a/libgo/go/runtime/crash_test.go +++ b/libgo/go/runtime/crash_test.go @@ -150,6 +150,9 @@ var ( func checkStaleRuntime(t *testing.T) { staleRuntimeOnce.Do(func() { + if runtime.Compiler == "gccgo" { + return + } // 'go run' uses the installed copy of runtime.a, which may be out of date. out, err := testenv.CleanCmdEnv(exec.Command(testenv.GoToolPath(t), "list", "-gcflags=all="+os.Getenv("GO_GCFLAGS"), "-f", "{{.Stale}}", "runtime")).CombinedOutput() if err != nil { diff --git a/libgo/go/runtime/error.go b/libgo/go/runtime/error.go index 34b7d37..1a038cf 100644 --- a/libgo/go/runtime/error.go +++ b/libgo/go/runtime/error.go @@ -139,14 +139,12 @@ func typestring(x interface{}) string { } // printany prints an argument passed to panic. +// If panic is called with a value that has a String or Error method, +// it has already been converted into a string by preprintpanics. func printany(i interface{}) { switch v := i.(type) { case nil: print("nil") - case stringer: - print(v.String()) - case error: - print(v.Error()) case bool: print(v) case int: diff --git a/libgo/go/runtime/hash32.go b/libgo/go/runtime/hash32.go index 22daec5..3449127 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 ppc s390 sh shbe sparc +// +build 386 arm armbe m68k mips mipsle nios2 ppc s390 sh shbe sparc package runtime diff --git a/libgo/go/runtime/lfstack_32bit.go b/libgo/go/runtime/lfstack_32bit.go index bbc421a..1288c1a 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 arm nacl armbe m68k mips mipsle mips64p32 mips64p32le ppc s390 sh shbe sparc +// +build 386 arm nacl armbe m68k mips mipsle mips64p32 mips64p32le nios2 ppc s390 sh shbe sparc package runtime diff --git a/libgo/go/runtime/malloc.go b/libgo/go/runtime/malloc.go index c27aa48..c8d5284 100644 --- a/libgo/go/runtime/malloc.go +++ b/libgo/go/runtime/malloc.go @@ -296,8 +296,8 @@ func mallocinit() { // allocation at 0x40 << 32 because when using 4k pages with 3-level // translation buffers, the user address space is limited to 39 bits // On darwin/arm64, the address space is even smaller. - // On AIX, mmap adresses range start at 0x07000000_00000000 for 64 bits - // processes. + // On AIX, mmap adresses range starts at 0x0700000000000000 for 64-bit + // processes. The new address space allocator starts at 0x0A00000000000000. arenaSize := round(_MaxMem, _PageSize) pSize = bitmapSize + spansSize + arenaSize + _PageSize for i := 0; i <= 0x7f; i++ { @@ -307,13 +307,16 @@ func mallocinit() { case GOARCH == "arm64": p = uintptr(i)<<40 | uintptrMask&(0x0040<<32) case GOOS == "aix": - i = 1 - p = uintptr(i)<<32 | uintptrMask&(0x70<<52) + if i == 0 { + p = uintptrMask&(1<<42) | uintptrMask&(0xa0<<52) + } else { + p = uintptr(i)<<42 | uintptrMask&(0x70<<52) + } default: p = uintptr(i)<<40 | uintptrMask&(0x00c0<<32) } p = uintptr(sysReserve(unsafe.Pointer(p), pSize, &reserved)) - if p != 0 || GOOS == "aix" { // Useless to loop on AIX, as i is forced to 1 + if p != 0 { break } } diff --git a/libgo/go/runtime/panic.go b/libgo/go/runtime/panic.go index fbdb17e..6b490b7 100644 --- a/libgo/go/runtime/panic.go +++ b/libgo/go/runtime/panic.go @@ -384,7 +384,6 @@ func Goexit() { // Call all Error and String methods before freezing the world. // Used when crashing with panicking. -// This must match types handled by printany. func preprintpanics(p *_panic) { defer func() { if recover() != nil { @@ -410,8 +409,6 @@ func printpanics(p *_panic) { print("\t") } print("panic: ") - // Because of preprintpanics, p.arg cannot be an error or - // stringer, so this won't call into user code. printany(p.arg) if p.recovered { print(" [recovered]") diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go index 20fa0ad..a6746c9 100644 --- a/libgo/go/runtime/proc.go +++ b/libgo/go/runtime/proc.go @@ -423,6 +423,12 @@ func releaseSudog(s *sudog) { // funcPC returns the entry PC of the function f. // It assumes that f is a func value. Otherwise the behavior is undefined. +// CAREFUL: In programs with plugins, funcPC can return different values +// for the same function (because there are actually multiple copies of +// the same function in the address space). To be safe, don't use the +// results of this function in any == expression. It is only safe to +// use the result as an address at which to start executing code. +// // For gccgo note that this differs from the gc implementation; the gc // implementation adds sys.PtrSize to the address of the interface // value, but GCC's alias analysis decides that that can not be a diff --git a/libgo/go/runtime/stack.go b/libgo/go/runtime/stack.go deleted file mode 100644 index fd99e4d..0000000 --- a/libgo/go/runtime/stack.go +++ /dev/null @@ -1,1229 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build ignore - -package runtime - -import ( - "runtime/internal/atomic" - "runtime/internal/sys" - "unsafe" -) - -/* -Stack layout parameters. -Included both by runtime (compiled via 6c) and linkers (compiled via gcc). - -The per-goroutine g->stackguard is set to point StackGuard bytes -above the bottom of the stack. Each function compares its stack -pointer against g->stackguard to check for overflow. To cut one -instruction from the check sequence for functions with tiny frames, -the stack is allowed to protrude StackSmall bytes below the stack -guard. Functions with large frames don't bother with the check and -always call morestack. The sequences are (for amd64, others are -similar): - - guard = g->stackguard - frame = function's stack frame size - argsize = size of function arguments (call + return) - - stack frame size <= StackSmall: - CMPQ guard, SP - JHI 3(PC) - MOVQ m->morearg, $(argsize << 32) - CALL morestack(SB) - - stack frame size > StackSmall but < StackBig - LEAQ (frame-StackSmall)(SP), R0 - CMPQ guard, R0 - JHI 3(PC) - MOVQ m->morearg, $(argsize << 32) - CALL morestack(SB) - - stack frame size >= StackBig: - MOVQ m->morearg, $((argsize << 32) | frame) - CALL morestack(SB) - -The bottom StackGuard - StackSmall bytes are important: there has -to be enough room to execute functions that refuse to check for -stack overflow, either because they need to be adjacent to the -actual caller's frame (deferproc) or because they handle the imminent -stack overflow (morestack). - -For example, deferproc might call malloc, which does one of the -above checks (without allocating a full frame), which might trigger -a call to morestack. This sequence needs to fit in the bottom -section of the stack. On amd64, morestack's frame is 40 bytes, and -deferproc's frame is 56 bytes. That fits well within the -StackGuard - StackSmall bytes at the bottom. -The linkers explore all possible call traces involving non-splitting -functions to make sure that this limit cannot be violated. -*/ - -const ( - // StackSystem is a number of additional bytes to add - // to each stack below the usual guard area for OS-specific - // purposes like signal handling. Used on Windows, Plan 9, - // and Darwin/ARM because they do not use a separate stack. - _StackSystem = sys.GoosWindows*512*sys.PtrSize + sys.GoosPlan9*512 + sys.GoosDarwin*sys.GoarchArm*1024 - - // The minimum size of stack used by Go code - _StackMin = 2048 - - // The minimum stack size to allocate. - // The hackery here rounds FixedStack0 up to a power of 2. - _FixedStack0 = _StackMin + _StackSystem - _FixedStack1 = _FixedStack0 - 1 - _FixedStack2 = _FixedStack1 | (_FixedStack1 >> 1) - _FixedStack3 = _FixedStack2 | (_FixedStack2 >> 2) - _FixedStack4 = _FixedStack3 | (_FixedStack3 >> 4) - _FixedStack5 = _FixedStack4 | (_FixedStack4 >> 8) - _FixedStack6 = _FixedStack5 | (_FixedStack5 >> 16) - _FixedStack = _FixedStack6 + 1 - - // Functions that need frames bigger than this use an extra - // instruction to do the stack split check, to avoid overflow - // in case SP - framesize wraps below zero. - // This value can be no bigger than the size of the unmapped - // space at zero. - _StackBig = 4096 - - // The stack guard is a pointer this many bytes above the - // bottom of the stack. - _StackGuard = 880*sys.StackGuardMultiplier + _StackSystem - - // After a stack split check the SP is allowed to be this - // many bytes below the stack guard. This saves an instruction - // in the checking sequence for tiny frames. - _StackSmall = 128 - - // The maximum number of bytes that a chain of NOSPLIT - // functions can use. - _StackLimit = _StackGuard - _StackSystem - _StackSmall -) - -// Goroutine preemption request. -// Stored into g->stackguard0 to cause split stack check failure. -// Must be greater than any real sp. -// 0xfffffade in hex. -const ( - _StackPreempt = uintptrMask & -1314 - _StackFork = uintptrMask & -1234 -) - -const ( - // stackDebug == 0: no logging - // == 1: logging of per-stack operations - // == 2: logging of per-frame operations - // == 3: logging of per-word updates - // == 4: logging of per-word reads - stackDebug = 0 - stackFromSystem = 0 // allocate stacks from system memory instead of the heap - stackFaultOnFree = 0 // old stacks are mapped noaccess to detect use after free - stackPoisonCopy = 0 // fill stack that should not be accessed with garbage, to detect bad dereferences during copy - - stackCache = 1 - - // check the BP links during traceback. - debugCheckBP = false -) - -const ( - uintptrMask = 1<<(8*sys.PtrSize) - 1 - - // Goroutine preemption request. - // Stored into g->stackguard0 to cause split stack check failure. - // Must be greater than any real sp. - // 0xfffffade in hex. - stackPreempt = uintptrMask & -1314 - - // Thread is forking. - // Stored into g->stackguard0 to cause split stack check failure. - // Must be greater than any real sp. - stackFork = uintptrMask & -1234 -) - -// Global pool of spans that have free stacks. -// Stacks are assigned an order according to size. -// order = log_2(size/FixedStack) -// There is a free list for each order. -// TODO: one lock per order? -var stackpool [_NumStackOrders]mSpanList -var stackpoolmu mutex - -// Global pool of large stack spans. -var stackLarge struct { - lock mutex - free [_MHeapMap_Bits]mSpanList // free lists by log_2(s.npages) -} - -func stackinit() { - if _StackCacheSize&_PageMask != 0 { - throw("cache size must be a multiple of page size") - } - for i := range stackpool { - stackpool[i].init() - } - for i := range stackLarge.free { - stackLarge.free[i].init() - } -} - -// stacklog2 returns ⌊log_2(n)⌋. -func stacklog2(n uintptr) int { - log2 := 0 - for n > 1 { - n >>= 1 - log2++ - } - return log2 -} - -// Allocates a stack from the free pool. Must be called with -// stackpoolmu held. -func stackpoolalloc(order uint8) gclinkptr { - list := &stackpool[order] - s := list.first - if s == nil { - // no free stacks. Allocate another span worth. - s = mheap_.allocStack(_StackCacheSize >> _PageShift) - if s == nil { - throw("out of memory") - } - if s.allocCount != 0 { - throw("bad allocCount") - } - if s.stackfreelist.ptr() != nil { - throw("bad stackfreelist") - } - for i := uintptr(0); i < _StackCacheSize; i += _FixedStack << order { - x := gclinkptr(s.base() + i) - x.ptr().next = s.stackfreelist - s.stackfreelist = x - } - list.insert(s) - } - x := s.stackfreelist - if x.ptr() == nil { - throw("span has no free stacks") - } - s.stackfreelist = x.ptr().next - s.allocCount++ - if s.stackfreelist.ptr() == nil { - // all stacks in s are allocated. - list.remove(s) - } - return x -} - -// Adds stack x to the free pool. Must be called with stackpoolmu held. -func stackpoolfree(x gclinkptr, order uint8) { - s := mheap_.lookup(unsafe.Pointer(x)) - if s.state != _MSpanStack { - throw("freeing stack not in a stack span") - } - if s.stackfreelist.ptr() == nil { - // s will now have a free stack - stackpool[order].insert(s) - } - x.ptr().next = s.stackfreelist - s.stackfreelist = x - s.allocCount-- - if gcphase == _GCoff && s.allocCount == 0 { - // Span is completely free. Return it to the heap - // immediately if we're sweeping. - // - // If GC is active, we delay the free until the end of - // GC to avoid the following type of situation: - // - // 1) GC starts, scans a SudoG but does not yet mark the SudoG.elem pointer - // 2) The stack that pointer points to is copied - // 3) The old stack is freed - // 4) The containing span is marked free - // 5) GC attempts to mark the SudoG.elem pointer. The - // marking fails because the pointer looks like a - // pointer into a free span. - // - // By not freeing, we prevent step #4 until GC is done. - stackpool[order].remove(s) - s.stackfreelist = 0 - mheap_.freeStack(s) - } -} - -// stackcacherefill/stackcacherelease implement a global pool of stack segments. -// The pool is required to prevent unlimited growth of per-thread caches. -// -//go:systemstack -func stackcacherefill(c *mcache, order uint8) { - if stackDebug >= 1 { - print("stackcacherefill order=", order, "\n") - } - - // Grab some stacks from the global cache. - // Grab half of the allowed capacity (to prevent thrashing). - var list gclinkptr - var size uintptr - lock(&stackpoolmu) - for size < _StackCacheSize/2 { - x := stackpoolalloc(order) - x.ptr().next = list - list = x - size += _FixedStack << order - } - unlock(&stackpoolmu) - c.stackcache[order].list = list - c.stackcache[order].size = size -} - -//go:systemstack -func stackcacherelease(c *mcache, order uint8) { - if stackDebug >= 1 { - print("stackcacherelease order=", order, "\n") - } - x := c.stackcache[order].list - size := c.stackcache[order].size - lock(&stackpoolmu) - for size > _StackCacheSize/2 { - y := x.ptr().next - stackpoolfree(x, order) - x = y - size -= _FixedStack << order - } - unlock(&stackpoolmu) - c.stackcache[order].list = x - c.stackcache[order].size = size -} - -//go:systemstack -func stackcache_clear(c *mcache) { - if stackDebug >= 1 { - print("stackcache clear\n") - } - lock(&stackpoolmu) - for order := uint8(0); order < _NumStackOrders; order++ { - x := c.stackcache[order].list - for x.ptr() != nil { - y := x.ptr().next - stackpoolfree(x, order) - x = y - } - c.stackcache[order].list = 0 - c.stackcache[order].size = 0 - } - unlock(&stackpoolmu) -} - -// stackalloc allocates an n byte stack. -// -// stackalloc must run on the system stack because it uses per-P -// resources and must not split the stack. -// -//go:systemstack -func stackalloc(n uint32) (stack, []stkbar) { - // Stackalloc must be called on scheduler stack, so that we - // never try to grow the stack during the code that stackalloc runs. - // Doing so would cause a deadlock (issue 1547). - thisg := getg() - if thisg != thisg.m.g0 { - throw("stackalloc not on scheduler stack") - } - if n&(n-1) != 0 { - throw("stack size not a power of 2") - } - if stackDebug >= 1 { - print("stackalloc ", n, "\n") - } - - // Compute the size of stack barrier array. - maxstkbar := gcMaxStackBarriers(int(n)) - nstkbar := unsafe.Sizeof(stkbar{}) * uintptr(maxstkbar) - var stkbarSlice slice - - if debug.efence != 0 || stackFromSystem != 0 { - v := sysAlloc(round(uintptr(n), _PageSize), &memstats.stacks_sys) - if v == nil { - throw("out of memory (stackalloc)") - } - top := uintptr(n) - nstkbar - if maxstkbar != 0 { - stkbarSlice = slice{add(v, top), 0, maxstkbar} - } - return stack{uintptr(v), uintptr(v) + top}, *(*[]stkbar)(unsafe.Pointer(&stkbarSlice)) - } - - // Small stacks are allocated with a fixed-size free-list allocator. - // If we need a stack of a bigger size, we fall back on allocating - // a dedicated span. - var v unsafe.Pointer - if stackCache != 0 && n < _FixedStack<<_NumStackOrders && n < _StackCacheSize { - order := uint8(0) - n2 := n - for n2 > _FixedStack { - order++ - n2 >>= 1 - } - var x gclinkptr - c := thisg.m.mcache - if c == nil || thisg.m.preemptoff != "" || thisg.m.helpgc != 0 { - // c == nil can happen in the guts of exitsyscall or - // procresize. Just get a stack from the global pool. - // Also don't touch stackcache during gc - // as it's flushed concurrently. - lock(&stackpoolmu) - x = stackpoolalloc(order) - unlock(&stackpoolmu) - } else { - x = c.stackcache[order].list - if x.ptr() == nil { - stackcacherefill(c, order) - x = c.stackcache[order].list - } - c.stackcache[order].list = x.ptr().next - c.stackcache[order].size -= uintptr(n) - } - v = unsafe.Pointer(x) - } else { - var s *mspan - npage := uintptr(n) >> _PageShift - log2npage := stacklog2(npage) - - // Try to get a stack from the large stack cache. - lock(&stackLarge.lock) - if !stackLarge.free[log2npage].isEmpty() { - s = stackLarge.free[log2npage].first - stackLarge.free[log2npage].remove(s) - } - unlock(&stackLarge.lock) - - if s == nil { - // Allocate a new stack from the heap. - s = mheap_.allocStack(npage) - if s == nil { - throw("out of memory") - } - } - v = unsafe.Pointer(s.base()) - } - - if raceenabled { - racemalloc(v, uintptr(n)) - } - if msanenabled { - msanmalloc(v, uintptr(n)) - } - if stackDebug >= 1 { - print(" allocated ", v, "\n") - } - top := uintptr(n) - nstkbar - if maxstkbar != 0 { - stkbarSlice = slice{add(v, top), 0, maxstkbar} - } - return stack{uintptr(v), uintptr(v) + top}, *(*[]stkbar)(unsafe.Pointer(&stkbarSlice)) -} - -// stackfree frees an n byte stack allocation at stk. -// -// stackfree must run on the system stack because it uses per-P -// resources and must not split the stack. -// -//go:systemstack -func stackfree(stk stack, n uintptr) { - gp := getg() - v := unsafe.Pointer(stk.lo) - if n&(n-1) != 0 { - throw("stack not a power of 2") - } - if stk.lo+n < stk.hi { - throw("bad stack size") - } - if stackDebug >= 1 { - println("stackfree", v, n) - memclrNoHeapPointers(v, n) // for testing, clobber stack data - } - if debug.efence != 0 || stackFromSystem != 0 { - if debug.efence != 0 || stackFaultOnFree != 0 { - sysFault(v, n) - } else { - sysFree(v, n, &memstats.stacks_sys) - } - return - } - if msanenabled { - msanfree(v, n) - } - if stackCache != 0 && n < _FixedStack<<_NumStackOrders && n < _StackCacheSize { - order := uint8(0) - n2 := n - for n2 > _FixedStack { - order++ - n2 >>= 1 - } - x := gclinkptr(v) - c := gp.m.mcache - if c == nil || gp.m.preemptoff != "" || gp.m.helpgc != 0 { - lock(&stackpoolmu) - stackpoolfree(x, order) - unlock(&stackpoolmu) - } else { - if c.stackcache[order].size >= _StackCacheSize { - stackcacherelease(c, order) - } - x.ptr().next = c.stackcache[order].list - c.stackcache[order].list = x - c.stackcache[order].size += n - } - } else { - s := mheap_.lookup(v) - if s.state != _MSpanStack { - println(hex(s.base()), v) - throw("bad span state") - } - if gcphase == _GCoff { - // Free the stack immediately if we're - // sweeping. - mheap_.freeStack(s) - } else { - // If the GC is running, we can't return a - // stack span to the heap because it could be - // reused as a heap span, and this state - // change would race with GC. Add it to the - // large stack cache instead. - log2npage := stacklog2(s.npages) - lock(&stackLarge.lock) - stackLarge.free[log2npage].insert(s) - unlock(&stackLarge.lock) - } - } -} - -var maxstacksize uintptr = 1 << 20 // enough until runtime.main sets it for real - -var ptrnames = []string{ - 0: "scalar", - 1: "ptr", -} - -// Stack frame layout -// -// (x86) -// +------------------+ -// | args from caller | -// +------------------+ <- frame->argp -// | return address | -// +------------------+ -// | caller's BP (*) | (*) if framepointer_enabled && varp < sp -// +------------------+ <- frame->varp -// | locals | -// +------------------+ -// | args to callee | -// +------------------+ <- frame->sp -// -// (arm) -// +------------------+ -// | args from caller | -// +------------------+ <- frame->argp -// | caller's retaddr | -// +------------------+ <- frame->varp -// | locals | -// +------------------+ -// | args to callee | -// +------------------+ -// | return address | -// +------------------+ <- frame->sp - -type adjustinfo struct { - old stack - delta uintptr // ptr distance from old to new stack (newbase - oldbase) - cache pcvalueCache - - // sghi is the highest sudog.elem on the stack. - sghi uintptr -} - -// Adjustpointer checks whether *vpp is in the old stack described by adjinfo. -// If so, it rewrites *vpp to point into the new stack. -func adjustpointer(adjinfo *adjustinfo, vpp unsafe.Pointer) { - pp := (*uintptr)(vpp) - p := *pp - if stackDebug >= 4 { - print(" ", pp, ":", hex(p), "\n") - } - if adjinfo.old.lo <= p && p < adjinfo.old.hi { - *pp = p + adjinfo.delta - if stackDebug >= 3 { - print(" adjust ptr ", pp, ":", hex(p), " -> ", hex(*pp), "\n") - } - } -} - -// Information from the compiler about the layout of stack frames. -type bitvector struct { - n int32 // # of bits - bytedata *uint8 -} - -type gobitvector struct { - n uintptr - bytedata []uint8 -} - -func gobv(bv bitvector) gobitvector { - return gobitvector{ - uintptr(bv.n), - (*[1 << 30]byte)(unsafe.Pointer(bv.bytedata))[:(bv.n+7)/8], - } -} - -func ptrbit(bv *gobitvector, i uintptr) uint8 { - return (bv.bytedata[i/8] >> (i % 8)) & 1 -} - -// bv describes the memory starting at address scanp. -// Adjust any pointers contained therein. -func adjustpointers(scanp unsafe.Pointer, cbv *bitvector, adjinfo *adjustinfo, f *_func) { - bv := gobv(*cbv) - minp := adjinfo.old.lo - maxp := adjinfo.old.hi - delta := adjinfo.delta - num := bv.n - // If this frame might contain channel receive slots, use CAS - // to adjust pointers. If the slot hasn't been received into - // yet, it may contain stack pointers and a concurrent send - // could race with adjusting those pointers. (The sent value - // itself can never contain stack pointers.) - useCAS := uintptr(scanp) < adjinfo.sghi - for i := uintptr(0); i < num; i++ { - if stackDebug >= 4 { - print(" ", add(scanp, i*sys.PtrSize), ":", ptrnames[ptrbit(&bv, i)], ":", hex(*(*uintptr)(add(scanp, i*sys.PtrSize))), " # ", i, " ", bv.bytedata[i/8], "\n") - } - if ptrbit(&bv, i) == 1 { - pp := (*uintptr)(add(scanp, i*sys.PtrSize)) - retry: - p := *pp - if f != nil && 0 < p && p < minLegalPointer && debug.invalidptr != 0 { - // Looks like a junk value in a pointer slot. - // Live analysis wrong? - getg().m.traceback = 2 - print("runtime: bad pointer in frame ", funcname(f), " at ", pp, ": ", hex(p), "\n") - throw("invalid pointer found on stack") - } - if minp <= p && p < maxp { - if stackDebug >= 3 { - print("adjust ptr ", hex(p), " ", funcname(f), "\n") - } - if useCAS { - ppu := (*unsafe.Pointer)(unsafe.Pointer(pp)) - if !atomic.Casp1(ppu, unsafe.Pointer(p), unsafe.Pointer(p+delta)) { - goto retry - } - } else { - *pp = p + delta - } - } - } - } -} - -// Note: the argument/return area is adjusted by the callee. -func adjustframe(frame *stkframe, arg unsafe.Pointer) bool { - adjinfo := (*adjustinfo)(arg) - targetpc := frame.continpc - if targetpc == 0 { - // Frame is dead. - return true - } - f := frame.fn - if stackDebug >= 2 { - print(" adjusting ", funcname(f), " frame=[", hex(frame.sp), ",", hex(frame.fp), "] pc=", hex(frame.pc), " continpc=", hex(frame.continpc), "\n") - } - if f.entry == systemstack_switchPC { - // A special routine at the bottom of stack of a goroutine that does an systemstack call. - // We will allow it to be copied even though we don't - // have full GC info for it (because it is written in asm). - return true - } - if targetpc != f.entry { - targetpc-- - } - pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, &adjinfo.cache) - if pcdata == -1 { - pcdata = 0 // in prologue - } - - // Adjust local variables if stack frame has been allocated. - size := frame.varp - frame.sp - var minsize uintptr - switch sys.ArchFamily { - case sys.ARM64: - minsize = sys.SpAlign - default: - minsize = sys.MinFrameSize - } - if size > minsize { - var bv bitvector - stackmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps)) - if stackmap == nil || stackmap.n <= 0 { - print("runtime: frame ", funcname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n") - throw("missing stackmap") - } - // Locals bitmap information, scan just the pointers in locals. - if pcdata < 0 || pcdata >= stackmap.n { - // don't know where we are - print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n") - throw("bad symbol table") - } - bv = stackmapdata(stackmap, pcdata) - size = uintptr(bv.n) * sys.PtrSize - if stackDebug >= 3 { - print(" locals ", pcdata, "/", stackmap.n, " ", size/sys.PtrSize, " words ", bv.bytedata, "\n") - } - adjustpointers(unsafe.Pointer(frame.varp-size), &bv, adjinfo, f) - } - - // Adjust saved base pointer if there is one. - if sys.ArchFamily == sys.AMD64 && frame.argp-frame.varp == 2*sys.RegSize { - if !framepointer_enabled { - print("runtime: found space for saved base pointer, but no framepointer experiment\n") - print("argp=", hex(frame.argp), " varp=", hex(frame.varp), "\n") - throw("bad frame layout") - } - if stackDebug >= 3 { - print(" saved bp\n") - } - if debugCheckBP { - // Frame pointers should always point to the next higher frame on - // the Go stack (or be nil, for the top frame on the stack). - bp := *(*uintptr)(unsafe.Pointer(frame.varp)) - if bp != 0 && (bp < adjinfo.old.lo || bp >= adjinfo.old.hi) { - println("runtime: found invalid frame pointer") - print("bp=", hex(bp), " min=", hex(adjinfo.old.lo), " max=", hex(adjinfo.old.hi), "\n") - throw("bad frame pointer") - } - } - adjustpointer(adjinfo, unsafe.Pointer(frame.varp)) - } - - // Adjust arguments. - if frame.arglen > 0 { - var bv bitvector - if frame.argmap != nil { - bv = *frame.argmap - } else { - stackmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps)) - if stackmap == nil || stackmap.n <= 0 { - print("runtime: frame ", funcname(f), " untyped args ", frame.argp, "+", frame.arglen, "\n") - throw("missing stackmap") - } - if pcdata < 0 || pcdata >= stackmap.n { - // don't know where we are - print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " args stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n") - throw("bad symbol table") - } - bv = stackmapdata(stackmap, pcdata) - } - if stackDebug >= 3 { - print(" args\n") - } - adjustpointers(unsafe.Pointer(frame.argp), &bv, adjinfo, nil) - } - return true -} - -func adjustctxt(gp *g, adjinfo *adjustinfo) { - adjustpointer(adjinfo, unsafe.Pointer(&gp.sched.ctxt)) - if !framepointer_enabled { - return - } - if debugCheckBP { - bp := gp.sched.bp - if bp != 0 && (bp < adjinfo.old.lo || bp >= adjinfo.old.hi) { - println("runtime: found invalid top frame pointer") - print("bp=", hex(bp), " min=", hex(adjinfo.old.lo), " max=", hex(adjinfo.old.hi), "\n") - throw("bad top frame pointer") - } - } - adjustpointer(adjinfo, unsafe.Pointer(&gp.sched.bp)) -} - -func adjustdefers(gp *g, adjinfo *adjustinfo) { - // Adjust defer argument blocks the same way we adjust active stack frames. - tracebackdefers(gp, adjustframe, noescape(unsafe.Pointer(adjinfo))) - - // Adjust pointers in the Defer structs. - // Defer structs themselves are never on the stack. - for d := gp._defer; d != nil; d = d.link { - adjustpointer(adjinfo, unsafe.Pointer(&d.fn)) - adjustpointer(adjinfo, unsafe.Pointer(&d.sp)) - adjustpointer(adjinfo, unsafe.Pointer(&d._panic)) - } -} - -func adjustpanics(gp *g, adjinfo *adjustinfo) { - // Panics are on stack and already adjusted. - // Update pointer to head of list in G. - adjustpointer(adjinfo, unsafe.Pointer(&gp._panic)) -} - -func adjustsudogs(gp *g, adjinfo *adjustinfo) { - // the data elements pointed to by a SudoG structure - // might be in the stack. - for s := gp.waiting; s != nil; s = s.waitlink { - adjustpointer(adjinfo, unsafe.Pointer(&s.elem)) - adjustpointer(adjinfo, unsafe.Pointer(&s.selectdone)) - } -} - -func adjuststkbar(gp *g, adjinfo *adjustinfo) { - for i := int(gp.stkbarPos); i < len(gp.stkbar); i++ { - adjustpointer(adjinfo, unsafe.Pointer(&gp.stkbar[i].savedLRPtr)) - } -} - -func fillstack(stk stack, b byte) { - for p := stk.lo; p < stk.hi; p++ { - *(*byte)(unsafe.Pointer(p)) = b - } -} - -func findsghi(gp *g, stk stack) uintptr { - var sghi uintptr - for sg := gp.waiting; sg != nil; sg = sg.waitlink { - p := uintptr(sg.elem) + uintptr(sg.c.elemsize) - if stk.lo <= p && p < stk.hi && p > sghi { - sghi = p - } - p = uintptr(unsafe.Pointer(sg.selectdone)) + unsafe.Sizeof(sg.selectdone) - if stk.lo <= p && p < stk.hi && p > sghi { - sghi = p - } - } - return sghi -} - -// syncadjustsudogs adjusts gp's sudogs and copies the part of gp's -// stack they refer to while synchronizing with concurrent channel -// operations. It returns the number of bytes of stack copied. -func syncadjustsudogs(gp *g, used uintptr, adjinfo *adjustinfo) uintptr { - if gp.waiting == nil { - return 0 - } - - // Lock channels to prevent concurrent send/receive. - // It's important that we *only* do this for async - // copystack; otherwise, gp may be in the middle of - // putting itself on wait queues and this would - // self-deadlock. - var lastc *hchan - for sg := gp.waiting; sg != nil; sg = sg.waitlink { - if sg.c != lastc { - lock(&sg.c.lock) - } - lastc = sg.c - } - - // Adjust sudogs. - adjustsudogs(gp, adjinfo) - - // Copy the part of the stack the sudogs point in to - // while holding the lock to prevent races on - // send/receive slots. - var sgsize uintptr - if adjinfo.sghi != 0 { - oldBot := adjinfo.old.hi - used - newBot := oldBot + adjinfo.delta - sgsize = adjinfo.sghi - oldBot - memmove(unsafe.Pointer(newBot), unsafe.Pointer(oldBot), sgsize) - } - - // Unlock channels. - lastc = nil - for sg := gp.waiting; sg != nil; sg = sg.waitlink { - if sg.c != lastc { - unlock(&sg.c.lock) - } - lastc = sg.c - } - - return sgsize -} - -// Copies gp's stack to a new stack of a different size. -// Caller must have changed gp status to Gcopystack. -// -// If sync is true, this is a self-triggered stack growth and, in -// particular, no other G may be writing to gp's stack (e.g., via a -// channel operation). If sync is false, copystack protects against -// concurrent channel operations. -func copystack(gp *g, newsize uintptr, sync bool) { - if gp.syscallsp != 0 { - throw("stack growth not allowed in system call") - } - old := gp.stack - if old.lo == 0 { - throw("nil stackbase") - } - used := old.hi - gp.sched.sp - - // allocate new stack - new, newstkbar := stackalloc(uint32(newsize)) - if stackPoisonCopy != 0 { - fillstack(new, 0xfd) - } - if stackDebug >= 1 { - print("copystack gp=", gp, " [", hex(old.lo), " ", hex(old.hi-used), " ", hex(old.hi), "]/", gp.stackAlloc, " -> [", hex(new.lo), " ", hex(new.hi-used), " ", hex(new.hi), "]/", newsize, "\n") - } - - // Compute adjustment. - var adjinfo adjustinfo - adjinfo.old = old - adjinfo.delta = new.hi - old.hi - - // Adjust sudogs, synchronizing with channel ops if necessary. - ncopy := used - if sync { - adjustsudogs(gp, &adjinfo) - } else { - // sudogs can point in to the stack. During concurrent - // shrinking, these areas may be written to. Find the - // highest such pointer so we can handle everything - // there and below carefully. (This shouldn't be far - // from the bottom of the stack, so there's little - // cost in handling everything below it carefully.) - adjinfo.sghi = findsghi(gp, old) - - // Synchronize with channel ops and copy the part of - // the stack they may interact with. - ncopy -= syncadjustsudogs(gp, used, &adjinfo) - } - - // Copy the stack (or the rest of it) to the new location - memmove(unsafe.Pointer(new.hi-ncopy), unsafe.Pointer(old.hi-ncopy), ncopy) - - // Disallow sigprof scans of this stack and block if there's - // one in progress. - gcLockStackBarriers(gp) - - // Adjust remaining structures that have pointers into stacks. - // We have to do most of these before we traceback the new - // stack because gentraceback uses them. - adjustctxt(gp, &adjinfo) - adjustdefers(gp, &adjinfo) - adjustpanics(gp, &adjinfo) - adjuststkbar(gp, &adjinfo) - if adjinfo.sghi != 0 { - adjinfo.sghi += adjinfo.delta - } - - // copy old stack barriers to new stack barrier array - newstkbar = newstkbar[:len(gp.stkbar)] - copy(newstkbar, gp.stkbar) - - // Swap out old stack for new one - gp.stack = new - gp.stackguard0 = new.lo + _StackGuard // NOTE: might clobber a preempt request - gp.sched.sp = new.hi - used - oldsize := gp.stackAlloc - gp.stackAlloc = newsize - gp.stkbar = newstkbar - gp.stktopsp += adjinfo.delta - - // Adjust pointers in the new stack. - gentraceback(^uintptr(0), ^uintptr(0), 0, gp, 0, nil, 0x7fffffff, adjustframe, noescape(unsafe.Pointer(&adjinfo)), 0) - - gcUnlockStackBarriers(gp) - - // free old stack - if stackPoisonCopy != 0 { - fillstack(old, 0xfc) - } - stackfree(old, oldsize) -} - -// round x up to a power of 2. -func round2(x int32) int32 { - s := uint(0) - for 1<<s < x { - s++ - } - return 1 << s -} - -// Called from runtime·morestack when more stack is needed. -// Allocate larger stack and relocate to new stack. -// Stack growth is multiplicative, for constant amortized cost. -// -// g->atomicstatus will be Grunning or Gscanrunning upon entry. -// If the GC is trying to stop this g then it will set preemptscan to true. -// -// ctxt is the value of the context register on morestack. newstack -// will write it to g.sched.ctxt. -func newstack(ctxt unsafe.Pointer) { - thisg := getg() - // TODO: double check all gp. shouldn't be getg(). - if thisg.m.morebuf.g.ptr().stackguard0 == stackFork { - throw("stack growth after fork") - } - if thisg.m.morebuf.g.ptr() != thisg.m.curg { - print("runtime: newstack called from g=", hex(thisg.m.morebuf.g), "\n"+"\tm=", thisg.m, " m->curg=", thisg.m.curg, " m->g0=", thisg.m.g0, " m->gsignal=", thisg.m.gsignal, "\n") - morebuf := thisg.m.morebuf - traceback(morebuf.pc, morebuf.sp, morebuf.lr, morebuf.g.ptr()) - throw("runtime: wrong goroutine in newstack") - } - - gp := thisg.m.curg - // Write ctxt to gp.sched. We do this here instead of in - // morestack so it has the necessary write barrier. - gp.sched.ctxt = ctxt - - if thisg.m.curg.throwsplit { - // Update syscallsp, syscallpc in case traceback uses them. - morebuf := thisg.m.morebuf - gp.syscallsp = morebuf.sp - gp.syscallpc = morebuf.pc - print("runtime: newstack sp=", hex(gp.sched.sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n", - "\tmorebuf={pc:", hex(morebuf.pc), " sp:", hex(morebuf.sp), " lr:", hex(morebuf.lr), "}\n", - "\tsched={pc:", hex(gp.sched.pc), " sp:", hex(gp.sched.sp), " lr:", hex(gp.sched.lr), " ctxt:", gp.sched.ctxt, "}\n") - - traceback(morebuf.pc, morebuf.sp, morebuf.lr, gp) - throw("runtime: stack split at bad time") - } - - morebuf := thisg.m.morebuf - thisg.m.morebuf.pc = 0 - thisg.m.morebuf.lr = 0 - thisg.m.morebuf.sp = 0 - thisg.m.morebuf.g = 0 - - // NOTE: stackguard0 may change underfoot, if another thread - // is about to try to preempt gp. Read it just once and use that same - // value now and below. - preempt := atomic.Loaduintptr(&gp.stackguard0) == stackPreempt - - // Be conservative about where we preempt. - // We are interested in preempting user Go code, not runtime code. - // If we're holding locks, mallocing, or preemption is disabled, don't - // preempt. - // This check is very early in newstack so that even the status change - // from Grunning to Gwaiting and back doesn't happen in this case. - // That status change by itself can be viewed as a small preemption, - // because the GC might change Gwaiting to Gscanwaiting, and then - // this goroutine has to wait for the GC to finish before continuing. - // If the GC is in some way dependent on this goroutine (for example, - // it needs a lock held by the goroutine), that small preemption turns - // into a real deadlock. - if preempt { - if thisg.m.locks != 0 || thisg.m.mallocing != 0 || thisg.m.preemptoff != "" || thisg.m.p.ptr().status != _Prunning { - // Let the goroutine keep running for now. - // gp->preempt is set, so it will be preempted next time. - gp.stackguard0 = gp.stack.lo + _StackGuard - gogo(&gp.sched) // never return - } - } - - if gp.stack.lo == 0 { - throw("missing stack in newstack") - } - sp := gp.sched.sp - if sys.ArchFamily == sys.AMD64 || sys.ArchFamily == sys.I386 { - // The call to morestack cost a word. - sp -= sys.PtrSize - } - if stackDebug >= 1 || sp < gp.stack.lo { - print("runtime: newstack sp=", hex(sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n", - "\tmorebuf={pc:", hex(morebuf.pc), " sp:", hex(morebuf.sp), " lr:", hex(morebuf.lr), "}\n", - "\tsched={pc:", hex(gp.sched.pc), " sp:", hex(gp.sched.sp), " lr:", hex(gp.sched.lr), " ctxt:", gp.sched.ctxt, "}\n") - } - if sp < gp.stack.lo { - print("runtime: gp=", gp, ", gp->status=", hex(readgstatus(gp)), "\n ") - print("runtime: split stack overflow: ", hex(sp), " < ", hex(gp.stack.lo), "\n") - throw("runtime: split stack overflow") - } - - if preempt { - if gp == thisg.m.g0 { - throw("runtime: preempt g0") - } - if thisg.m.p == 0 && thisg.m.locks == 0 { - throw("runtime: g is running but p is not") - } - // Synchronize with scang. - casgstatus(gp, _Grunning, _Gwaiting) - if gp.preemptscan { - for !castogscanstatus(gp, _Gwaiting, _Gscanwaiting) { - // Likely to be racing with the GC as - // it sees a _Gwaiting and does the - // stack scan. If so, gcworkdone will - // be set and gcphasework will simply - // return. - } - if !gp.gcscandone { - // gcw is safe because we're on the - // system stack. - gcw := &gp.m.p.ptr().gcw - scanstack(gp, gcw) - if gcBlackenPromptly { - gcw.dispose() - } - gp.gcscandone = true - } - gp.preemptscan = false - gp.preempt = false - casfrom_Gscanstatus(gp, _Gscanwaiting, _Gwaiting) - // This clears gcscanvalid. - casgstatus(gp, _Gwaiting, _Grunning) - gp.stackguard0 = gp.stack.lo + _StackGuard - gogo(&gp.sched) // never return - } - - // Act like goroutine called runtime.Gosched. - casgstatus(gp, _Gwaiting, _Grunning) - gopreempt_m(gp) // never return - } - - // Allocate a bigger segment and move the stack. - oldsize := int(gp.stackAlloc) - newsize := oldsize * 2 - if uintptr(newsize) > maxstacksize { - print("runtime: goroutine stack exceeds ", maxstacksize, "-byte limit\n") - throw("stack overflow") - } - - // The goroutine must be executing in order to call newstack, - // so it must be Grunning (or Gscanrunning). - casgstatus(gp, _Grunning, _Gcopystack) - - // The concurrent GC will not scan the stack while we are doing the copy since - // the gp is in a Gcopystack status. - copystack(gp, uintptr(newsize), true) - if stackDebug >= 1 { - print("stack grow done\n") - } - casgstatus(gp, _Gcopystack, _Grunning) - gogo(&gp.sched) -} - -//go:nosplit -func nilfunc() { - *(*uint8)(nil) = 0 -} - -// adjust Gobuf as if it executed a call to fn -// and then did an immediate gosave. -func gostartcallfn(gobuf *gobuf, fv *funcval) { - var fn unsafe.Pointer - if fv != nil { - fn = unsafe.Pointer(fv.fn) - } else { - fn = unsafe.Pointer(funcPC(nilfunc)) - } - gostartcall(gobuf, fn, unsafe.Pointer(fv)) -} - -// Maybe shrink the stack being used by gp. -// Called at garbage collection time. -// gp must be stopped, but the world need not be. -func shrinkstack(gp *g) { - gstatus := readgstatus(gp) - if gstatus&^_Gscan == _Gdead { - if gp.stack.lo != 0 { - // Free whole stack - it will get reallocated - // if G is used again. - stackfree(gp.stack, gp.stackAlloc) - gp.stack.lo = 0 - gp.stack.hi = 0 - gp.stkbar = nil - gp.stkbarPos = 0 - } - return - } - if gp.stack.lo == 0 { - throw("missing stack in shrinkstack") - } - if gstatus&_Gscan == 0 { - throw("bad status in shrinkstack") - } - - if debug.gcshrinkstackoff > 0 { - return - } - if gp.startpc == gcBgMarkWorkerPC { - // We're not allowed to shrink the gcBgMarkWorker - // stack (see gcBgMarkWorker for explanation). - return - } - - oldsize := gp.stackAlloc - newsize := oldsize / 2 - // Don't shrink the allocation below the minimum-sized stack - // allocation. - if newsize < _FixedStack { - return - } - // Compute how much of the stack is currently in use and only - // shrink the stack if gp is using less than a quarter of its - // current stack. The currently used stack includes everything - // down to the SP plus the stack guard space that ensures - // there's room for nosplit functions. - avail := gp.stack.hi - gp.stack.lo - if used := gp.stack.hi - gp.sched.sp + _StackLimit; used >= avail/4 { - return - } - - // We can't copy the stack if we're in a syscall. - // The syscall might have pointers into the stack. - if gp.syscallsp != 0 { - return - } - if sys.GoosWindows != 0 && gp.m != nil && gp.m.libcallsp != 0 { - return - } - - if stackDebug > 0 { - print("shrinking stack ", oldsize, "->", newsize, "\n") - } - - copystack(gp, newsize, false) -} - -// freeStackSpans frees unused stack spans at the end of GC. -func freeStackSpans() { - lock(&stackpoolmu) - - // Scan stack pools for empty stack spans. - for order := range stackpool { - list := &stackpool[order] - for s := list.first; s != nil; { - next := s.next - if s.allocCount == 0 { - list.remove(s) - s.stackfreelist = 0 - mheap_.freeStack(s) - } - s = next - } - } - - unlock(&stackpoolmu) - - // Free large stack spans. - lock(&stackLarge.lock) - for i := range stackLarge.free { - for s := stackLarge.free[i].first; s != nil; { - next := s.next - stackLarge.free[i].remove(s) - mheap_.freeStack(s) - s = next - } - } - unlock(&stackLarge.lock) -} - -//go:nosplit -func morestackc() { - systemstack(func() { - throw("attempt to execute C code on Go stack") - }) -} diff --git a/libgo/go/runtime/symtab.go b/libgo/go/runtime/symtab.go index 3d15fc8..12dc672 100644 --- a/libgo/go/runtime/symtab.go +++ b/libgo/go/runtime/symtab.go @@ -115,6 +115,35 @@ type Func struct { entry uintptr } +// A FuncID identifies particular functions that need to be treated +// specially by the runtime. +// Note that in some situations involving plugins, there may be multiple +// copies of a particular special runtime function. +// Note: this list must match the list in cmd/internal/objabi/funcid.go. +type funcID uint32 + +const ( + funcID_normal funcID = iota // not a special function + funcID_goexit + funcID_jmpdefer + funcID_mcall + funcID_morestack + funcID_mstart + funcID_rt0_go + funcID_asmcgocall + funcID_sigpanic + funcID_runfinq + funcID_bgsweep + funcID_forcegchelper + funcID_timerproc + funcID_gcBgMarkWorker + funcID_systemstack_switch + funcID_systemstack + funcID_cgocallback_gofunc + funcID_gogo + funcID_externalthreadhandler +) + // FuncForPC returns a *Func describing the function that contains the // given program counter address, or else nil. // diff --git a/libgo/go/runtime/unaligned2.go b/libgo/go/runtime/unaligned2.go index 891459e..9f52e8d 100644 --- a/libgo/go/runtime/unaligned2.go +++ b/libgo/go/runtime/unaligned2.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 arm mips mipsle mips64 mips64le armbe m68k sparc alpha ia64 mips64p32 mips64p32le sh shbe sparc64 +// +build alpha arm armbe ia64 m68k mips mipsle mips64 mips64le mips64p32 mips64p32le nios2 sh shbe sparc sparc64 package runtime diff --git a/libgo/go/syscall/endian_little.go b/libgo/go/syscall/endian_little.go index 4a73121..a5d32ae 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 amd64 amd64p32 arm arm64 ppc64le mips64le mipsle alpha ia64 mips64p32le sh riscv64 +// +build 386 alpha amd64 amd64p32 arm arm64 ia64 mips64le mipsle mips64p32le nios2 ppc64le riscv64 sh package syscall diff --git a/libgo/go/syscall/libcall_linux_ustat.go b/libgo/go/syscall/libcall_linux_ustat.go index 3aff344..f515fce 100644 --- a/libgo/go/syscall/libcall_linux_ustat.go +++ b/libgo/go/syscall/libcall_linux_ustat.go @@ -4,7 +4,7 @@ // GNU/Linux library ustat call. // This is not supported on some kernels, such as arm64. -// +build !arm64,!riscv64 +// +build !arm64,!nios2,!riscv64 package syscall diff --git a/libgo/goarch.sh b/libgo/goarch.sh index c63cbba..11bca7b 100755 --- a/libgo/goarch.sh +++ b/libgo/goarch.sh @@ -126,6 +126,13 @@ case $goarch in ;; esac ;; + nios2) + family=NIOS2 + cachelinesize=32 + minframesize=16 + pcquantum=4 + ptrsize=4 + ;; ppc) family=PPC bigendian=true diff --git a/libgo/gotool-packages.txt b/libgo/gotool-packages.txt new file mode 100644 index 0000000..012faf6 --- /dev/null +++ b/libgo/gotool-packages.txt @@ -0,0 +1,30 @@ +cmd/go/internal/base +cmd/go/internal/bug +cmd/go/internal/cache +cmd/go/internal/cfg +cmd/go/internal/clean +cmd/go/internal/cmdflag +cmd/go/internal/doc +cmd/go/internal/envcmd +cmd/go/internal/fix +cmd/go/internal/fmtcmd +cmd/go/internal/generate +cmd/go/internal/get +cmd/go/internal/help +cmd/go/internal/list +cmd/go/internal/load +cmd/go/internal/run +cmd/go/internal/str +cmd/go/internal/test +cmd/go/internal/tool +cmd/go/internal/version +cmd/go/internal/vet +cmd/go/internal/web +cmd/go/internal/work +cmd/internal/browser +cmd/internal/buildid +cmd/internal/edit +cmd/internal/objabi +cmd/internal/test2json +cmd/vet/internal/cfg +cmd/vet/internal/whitelist diff --git a/libgo/libgo-packages.txt b/libgo/libgo-packages.txt new file mode 100644 index 0000000..70c12ba --- /dev/null +++ b/libgo/libgo-packages.txt @@ -0,0 +1,177 @@ +archive/tar +archive/zip +bufio +bytes +compress/bzip2 +compress/flate +compress/gzip +compress/lzw +compress/zlib +container/heap +container/list +container/ring +context +crypto +crypto/aes +crypto/cipher +crypto/des +crypto/dsa +crypto/ecdsa +crypto/elliptic +crypto/hmac +crypto/internal/cipherhw +crypto/md5 +crypto/rand +crypto/rc4 +crypto/rsa +crypto/sha1 +crypto/sha256 +crypto/sha512 +crypto/subtle +crypto/tls +crypto/x509 +crypto/x509/pkix +database/sql +database/sql/driver +debug/dwarf +debug/elf +debug/gosym +debug/macho +debug/pe +debug/plan9obj +debug/xcoff +encoding +encoding/ascii85 +encoding/asn1 +encoding/base32 +encoding/base64 +encoding/binary +encoding/csv +encoding/gob +encoding/hex +encoding/json +encoding/pem +encoding/xml +errors +expvar +flag +fmt +go/ast +go/build +go/constant +go/doc +go/format +go/importer +go/internal/gccgoimporter +go/internal/gcimporter +go/internal/srcimporter +go/parser +go/printer +go/scanner +go/token +go/types +golang_org/x/crypto/chacha20poly1305 +golang_org/x/crypto/chacha20poly1305/internal/chacha20 +golang_org/x/crypto/cryptobyte +golang_org/x/crypto/cryptobyte/asn1 +golang_org/x/crypto/curve25519 +golang_org/x/crypto/poly1305 +golang_org/x/net/http2/hpack +golang_org/x/net/idna +golang_org/x/net/internal/nettest +golang_org/x/net/lex/httplex +golang_org/x/net/nettest +golang_org/x/net/proxy +golang_org/x/text/secure/bidirule +golang_org/x/text/transform +golang_org/x/text/unicode/bidi +golang_org/x/text/unicode/norm +golang_org/x/text/width +hash +hash/adler32 +hash/crc32 +hash/crc64 +hash/fnv +html +html/template +image +image/color +image/color/palette +image/draw +image/gif +image/internal/imageutil +image/jpeg +image/png +index/suffixarray +internal/nettrace +internal/poll +internal/race +internal/singleflight +internal/syscall/unix +internal/testenv +internal/testlog +internal/trace +io +io/ioutil +log +log/syslog +math +math/big +math/bits +math/cmplx +math/rand +mime +mime/multipart +mime/quotedprintable +net +net/http +net/http/cgi +net/http/cookiejar +net/http/fcgi +net/http/httptest +net/http/httptrace +net/http/httputil +net/http/internal +net/http/pprof +net/internal/socktest +net/mail +net/rpc +net/rpc/jsonrpc +net/smtp +net/textproto +net/url +os +os/exec +os/signal +os/signal/internal/pty +os/user +path +path/filepath +reflect +regexp +regexp/syntax +runtime +runtime/debug +runtime/internal/atomic +runtime/internal/sys +runtime/pprof +runtime/pprof/internal/profile +runtime/trace +sort +strconv +strings +sync +sync/atomic +syscall +testing +testing/internal/testdeps +testing/iotest +testing/quick +text/scanner +text/tabwriter +text/template +text/template/parse +time +unicode +unicode/utf16 +unicode/utf8 diff --git a/libgo/match.sh b/libgo/match.sh index 9247ec6..fb80013 100755 --- a/libgo/match.sh +++ b/libgo/match.sh @@ -116,7 +116,7 @@ for f in $gofiles; do aix | android | darwin | dragonfly | freebsd | linux | nacl | netbsd | openbsd | plan9 | solaris | windows) tag1=nonmatchingtag ;; - 386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | ppc64 | ppc64le | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | ppc | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64) + 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) tag1=nonmatchingtag ;; esac @@ -128,7 +128,7 @@ for f in $gofiles; do aix | android | darwin | dragonfly | freebsd | linux | nacl | netbsd | openbsd | plan9 | solaris | windows) tag2=nonmatchingtag ;; - 386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | ppc64 | ppc64le | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | ppc | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64) + 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) tag2=nonmatchingtag ;; esac diff --git a/libgo/misc/cgo/testplugin/src/issue24351/main.go b/libgo/misc/cgo/testplugin/src/issue24351/main.go new file mode 100644 index 0000000..4107adf --- /dev/null +++ b/libgo/misc/cgo/testplugin/src/issue24351/main.go @@ -0,0 +1,21 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "plugin" + +func main() { + p, err := plugin.Open("issue24351.so") + if err != nil { + panic(err) + } + f, err := p.Lookup("B") + if err != nil { + panic(err) + } + c := make(chan bool) + f.(func(chan bool))(c) + <-c +} diff --git a/libgo/misc/cgo/testplugin/src/issue24351/plugin.go b/libgo/misc/cgo/testplugin/src/issue24351/plugin.go new file mode 100644 index 0000000..db17e0a --- /dev/null +++ b/libgo/misc/cgo/testplugin/src/issue24351/plugin.go @@ -0,0 +1,14 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "fmt" + +func B(c chan bool) { + go func() { + fmt.Println(1.5) + c <- true + }() +} diff --git a/libgo/misc/cgo/testplugin/test.bash b/libgo/misc/cgo/testplugin/test.bash index 18e3803..df38204 100644 --- a/libgo/misc/cgo/testplugin/test.bash +++ b/libgo/misc/cgo/testplugin/test.bash @@ -85,3 +85,8 @@ GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue22175 src/issue22175/main. GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o issue.22295.so issue22295.pkg GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue22295 src/issue22295.pkg/main.go ./issue22295 + +# Test for issue 24351 +GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o issue24351.so src/issue24351/plugin.go +GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue24351 src/issue24351/main.go +./issue24351 diff --git a/libgo/misc/cgo/testshared/shared_test.go b/libgo/misc/cgo/testshared/shared_test.go index cf049ec..a296005 100644 --- a/libgo/misc/cgo/testshared/shared_test.go +++ b/libgo/misc/cgo/testshared/shared_test.go @@ -790,6 +790,7 @@ func TestRebuilding(t *testing.T) { // If the .a file is newer than the .so, the .so is rebuilt (but not the .a) t.Run("newarchive", func(t *testing.T) { resetFileStamps() + AssertNotRebuilt(t, "new .a file before build", filepath.Join(gopathInstallDir, "depBase.a")) goCmd(t, "list", "-linkshared", "-f={{.ImportPath}} {{.Stale}} {{.StaleReason}} {{.Target}}", "depBase") AssertNotRebuilt(t, "new .a file before build", filepath.Join(gopathInstallDir, "depBase.a")) cleanup := touch(t, filepath.Join(gopathInstallDir, "depBase.a")) diff --git a/libgo/mkruntimeinc.sh b/libgo/mkruntimeinc.sh new file mode 100755 index 0000000..cd95595 --- /dev/null +++ b/libgo/mkruntimeinc.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +# Copyright 2018 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. + +# Create tmp-runtime.inc from runtime.inc.raw. + +IN=runtime.inc.raw +OUT=tmp-runtime.inc + +rm -f runtime.inc.tmp2 runtime.inc.tmp3 + +# _Complex_lock and _Reader_lock are Go translations of some AIX system +# types and should not be exported back to C +# semt is a Go translation of the C type sem_t; it fails to convert on +# some systems and need not be exported back to C. +# sigset conflicts with system type sigset on AIX, so we need to rename it + +grep -v "#define _" ${IN} | grep -v "#define [cm][01234] " | grep -v "#define empty " | grep -v "#define \\$" > runtime.inc.tmp2 +for pattern in '_[GP][a-z]' _Max _Lock _Sig _Trace _MHeap _Num +do + grep "#define $pattern" ${IN} >> runtime.inc.tmp2 +done +TYPES="_Complex_lock _Reader_lock semt" +for TYPE in $TYPES +do + sed -e '/struct '${TYPE}' {/,/^}/s/^.*$//' runtime.inc.tmp2 > runtime.inc.tmp3; + mv runtime.inc.tmp3 runtime.inc.tmp2 +done +sed -e 's/sigset/sigset_go/' runtime.inc.tmp2 > ${OUT} +rm -f runtime.inc.tmp2 runtime.inc.tmp3 +exit 0 diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh index 6f7cba7..92ecb47 100755 --- a/libgo/mksysinfo.sh +++ b/libgo/mksysinfo.sh @@ -29,6 +29,7 @@ echo 'type _ unsafe.Pointer' >> ${OUT} # will all have a leading underscore. grep -v '^// ' gen-sysinfo.go | \ grep -v '^func' | \ + grep -v '^var' | \ grep -v '^type _timeval ' | \ grep -v '^type _timespec_t ' | \ grep -v '^type _timespec ' | \ @@ -1142,7 +1143,7 @@ grep '^const _RLIM_' gen-sysinfo.go | sed -e 's/^\(const \)_\(RLIM_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} if test "${rlimit}" = "_rlimit64" && grep '^const _RLIM64_INFINITY ' gen-sysinfo.go > /dev/null 2>&1; then echo 'const RLIM_INFINITY = _RLIM64_INFINITY' >> ${OUT} -elif grep '^const _RLIM_INFINITY ' gen-sysinfo-go; then +elif grep '^const _RLIM_INFINITY ' gen-sysinfo.go > /dev/null 2>&1; then echo 'const RLIM_INFINITY = _RLIM_INFINITY' >> ${OUT} fi diff --git a/libgo/runtime/go-unwind.c b/libgo/runtime/go-unwind.c index 4c9fb49..a059acb 100644 --- a/libgo/runtime/go-unwind.c +++ b/libgo/runtime/go-unwind.c @@ -10,11 +10,30 @@ #include <unistd.h> #include "unwind.h" -#define NO_SIZE_OF_ENCODED_VALUE -#include "unwind-pe.h" #include "runtime.h" +/* These constants are documented here: + https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/dwarfext.html + */ + +#define DW_EH_PE_omit 0xff +#define DW_EH_PE_absptr 0x00 +#define DW_EH_PE_uleb128 0x01 +#define DW_EH_PE_udata2 0x02 +#define DW_EH_PE_udata4 0x03 +#define DW_EH_PE_udata8 0x04 +#define DW_EH_PE_sleb128 0x09 +#define DW_EH_PE_sdata2 0x0A +#define DW_EH_PE_sdata4 0x0B +#define DW_EH_PE_sdata8 0x0C +#define DW_EH_PE_pcrel 0x10 +#define DW_EH_PE_textrel 0x20 +#define DW_EH_PE_datarel 0x30 +#define DW_EH_PE_funcrel 0x40 +#define DW_EH_PE_aligned 0x50 +#define DW_EH_PE_indirect 0x80 + /* The code for a Go exception. */ #ifdef __ARM_EABI_UNWINDER__ @@ -109,6 +128,182 @@ throwException () abort (); } +static inline _Unwind_Ptr +encoded_value_base (uint8_t encoding, struct _Unwind_Context *context) +{ + if (encoding == DW_EH_PE_omit) + return 0; + switch (encoding & 0x70) + { + case DW_EH_PE_absptr: + case DW_EH_PE_pcrel: + case DW_EH_PE_aligned: + return 0; + case DW_EH_PE_textrel: + return _Unwind_GetTextRelBase(context); + case DW_EH_PE_datarel: + return _Unwind_GetDataRelBase(context); + case DW_EH_PE_funcrel: + return _Unwind_GetRegionStart(context); + } + abort (); +} + +/* Read an unsigned leb128 value. */ + +static inline const uint8_t * +read_uleb128 (const uint8_t *p, _uleb128_t *val) +{ + unsigned int shift = 0; + _uleb128_t result = 0; + uint8_t byte; + + do + { + byte = *p++; + result |= ((_uleb128_t)byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + + *val = result; + return p; +} + +/* Similar, but read a signed leb128 value. */ + +static inline const uint8_t * +read_sleb128 (const uint8_t *p, _sleb128_t *val) +{ + unsigned int shift = 0; + _uleb128_t result = 0; + uint8_t byte; + + do + { + byte = *p++; + result |= ((_uleb128_t)byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + + /* sign extension */ + if (shift < (8 * sizeof(result)) && (byte & 0x40) != 0) + result |= (((_uleb128_t)~0) << shift); + + *val = (_sleb128_t)result; + return p; +} + +#define ROUND_UP_TO_PVB(x) (x + sizeof(void *) - 1) &- sizeof(void *) + +static inline const uint8_t * +read_encoded_value (struct _Unwind_Context *context, uint8_t encoding, + const uint8_t *p, _Unwind_Ptr *val) +{ + _Unwind_Ptr base = encoded_value_base (encoding, context); + _Unwind_Internal_Ptr decoded = 0; + const uint8_t *origp = p; + + if (encoding == DW_EH_PE_aligned) + { + _Unwind_Internal_Ptr uip = (_Unwind_Internal_Ptr)p; + uip = ROUND_UP_TO_PVB (uip); + decoded = *(_Unwind_Internal_Ptr *)uip; + p = (const uint8_t *)(uip + sizeof(void *)); + } + else + { + switch (encoding & 0x0f) + { + case DW_EH_PE_sdata2: + { + int16_t result; + __builtin_memcpy (&result, p, sizeof(int16_t)); + decoded = result; + p += sizeof(int16_t); + break; + } + case DW_EH_PE_udata2: + { + uint16_t result; + __builtin_memcpy (&result, p, sizeof(uint16_t)); + decoded = result; + p += sizeof(uint16_t); + break; + } + case DW_EH_PE_sdata4: + { + int32_t result; + __builtin_memcpy (&result, p, sizeof(int32_t)); + decoded = result; + p += sizeof(int32_t); + break; + } + case DW_EH_PE_udata4: + { + uint32_t result; + __builtin_memcpy (&result, p, sizeof(uint32_t)); + decoded = result; + p += sizeof(uint32_t); + break; + } + case DW_EH_PE_sdata8: + { + int64_t result; + __builtin_memcpy (&result, p, sizeof(int64_t)); + decoded = result; + p += sizeof(int64_t); + break; + } + case DW_EH_PE_udata8: + { + uint64_t result; + __builtin_memcpy (&result, p, sizeof(uint64_t)); + decoded = result; + p += sizeof(uint64_t); + break; + } + case DW_EH_PE_uleb128: + { + _uleb128_t value; + p = read_uleb128 (p, &value); + decoded = (_Unwind_Internal_Ptr)value; + break; + } + case DW_EH_PE_sleb128: + { + _sleb128_t value; + p = read_sleb128 (p, &value); + decoded = (_Unwind_Internal_Ptr)value; + break; + } + case DW_EH_PE_absptr: + __builtin_memcpy (&decoded, (const void *)p, sizeof(const void*)); + p += sizeof(void *); + break; + default: + abort (); + } + + if (decoded == 0) + { + *val = decoded; + return p; + } + + if ((encoding & 0x70) == DW_EH_PE_pcrel) + decoded += ((_Unwind_Internal_Ptr)origp); + else + decoded += base; + + if ((encoding & DW_EH_PE_indirect) != 0) + decoded = *(_Unwind_Internal_Ptr *)decoded; + } + *val = decoded; + return p; +} + /* The rest of this code is really similar to gcc/unwind-c.c and libjava/exception.cc. */ diff --git a/libgo/runtime/runtime_c.c b/libgo/runtime/runtime_c.c index 88f1adf..c65a7e0 100644 --- a/libgo/runtime/runtime_c.c +++ b/libgo/runtime/runtime_c.c @@ -33,13 +33,47 @@ runtime_atoi(const byte *p, intgo len) return n; } +#if defined(__i386__) || defined(__x86_64__) || defined (__s390__) || defined (__s390x__) + +// When cputicks is just asm instructions, skip the split stack +// prologue for speed. + +int64 runtime_cputicks(void) __attribute__((no_split_stack)); + +#endif + +// Whether the processor supports SSE2. +#if defined (__i386__) +static _Bool hasSSE2; + +// Force appropriate CPU level so that we can call the lfence/mfence +// builtins. + +#pragma GCC push_options +#pragma GCC target("sse2") + +#elif defined(__x86_64__) +#define hasSSE2 true +#endif + +#if defined(__i386__) || defined(__x86_64__) +// Whether to use lfence, as opposed to mfence. +// Set based on cpuid. +static _Bool lfenceBeforeRdtsc; +#endif // defined(__i386__) || defined(__x86_64__) + int64 runtime_cputicks(void) { -#if defined(__386__) || defined(__x86_64__) - uint32 low, high; - asm("rdtsc" : "=a" (low), "=d" (high)); - return (int64)(((uint64)high << 32) | (uint64)low); +#if defined(__i386__) || defined(__x86_64__) + if (hasSSE2) { + if (lfenceBeforeRdtsc) { + __builtin_ia32_lfence(); + } else { + __builtin_ia32_mfence(); + } + } + return __builtin_ia32_rdtsc(); #elif defined (__s390__) || defined (__s390x__) uint64 clock = 0; /* stckf may not write the return variable in case of a clock error, so make @@ -56,6 +90,10 @@ runtime_cputicks(void) #endif } +#if defined(__i386__) +#pragma GCC pop_options +#endif + void runtime_signalstack(byte *p, uintptr n) { @@ -146,8 +184,21 @@ runtime_cpuinit() #if defined(__i386__) || defined(__x86_64__) unsigned int eax, ebx, ecx, edx; + if (__get_cpuid(0, &eax, &ebx, &ecx, &edx)) { + if (eax != 0 + && ebx == 0x756E6547 // "Genu" + && edx == 0x49656E69 // "ineI" + && ecx == 0x6C65746E) { // "ntel" + lfenceBeforeRdtsc = true; + } + } if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) { setCpuidECX(ecx); +#if defined(__i386__) + if ((edx & bit_SSE2) != 0) { + hasSSE2 = true; + } +#endif } #if defined(HAVE_AS_X86_AES) diff --git a/libgo/sysinfo.c b/libgo/sysinfo.c index 884d017..fb11826 100644 --- a/libgo/sysinfo.c +++ b/libgo/sysinfo.c @@ -289,3 +289,212 @@ enum { epoll_data_offset = offsetof(struct epoll_event, data) }; #endif + +// The following section introduces explicit references to types and +// constants of interest to support bootstrapping libgo using a +// compiler that doesn't support -fdump-go-spec (e.g., clang), via +// DWARF-based tools. This process is made more difficult due to the +// fact that clang tries hard to omit types/constants from DWARF if it +// can't find explicit references to them, so here we make sure that +// key items are mentioned in ways that will force them into the +// generated DWARF. + +#if defined(__clang__) + +// Make a reference to a type +#define TREF(typ) typ typ ## ref + +// Make a reference to an opaque type +#define OTREF(typ) typ *typ ## ref + +// Make a reference to a struct tag +#define SREF(stag) struct stag stag ## ref + +// Make a reference to an enum literal +#define EREF(elit) unsigned elit ## fn(unsigned x) { return x == elit ? 1 : 0; } + +//...................................................................... + +// From dirent.h +SREF(dirent); +SREF(dirent64); +OTREF(DIR); + +// From fcntl.h +SREF(flock); +SREF(flock64); + +// From ffi headers +SREF(_ffi_type); +TREF(ffi_cif); +TREF(ffi_abi); +TREF(ffi_status); +EREF(FFI_OK); + +// From grp.h +SREF(group); + +#if defined(HAVE_LINUX_FILTER_H) +// From linux/filter.h +SREF(sock_filter); +SREF(sock_fprog); +#endif + +// From linux/if.h +EREF(IFF_UP); + +#if defined(HAVE_LINUX_IF_ADDR_H) +// From linux/if_addr.h +SREF(ifaddrmsg); +EREF(IFA_ADDRESS); +#endif + +#if defined(HAVE_LINUX_RTNETLINK_H) +// From linux/if_link.h +EREF(IFLA_ADDRESS); +#endif + +// From in.h, in6.h, icmp6.h +SREF(ip_mreq); +SREF(ip_mreqn); +SREF(ipv6_mreq); +SREF(ip6_mtuinfo); +SREF(icmp6_filter); +SREF(in_pktinfo); +EREF(IPPROTO_TCP); + +#if defined(HAVE_LINUX_RTNETLINK_H) +// From linux/rtnetlink.h +SREF(rtgenmsg); +SREF(rtmsg); +SREF(ifinfomsg); +SREF(rtattr); +SREF(rtnexthop); +EREF(RTM_BASE); +EREF(RTN_UNSPEC); +#endif + +// From netdb.h +SREF(addrinfo); + +// From netlink.h +SREF(nlattr); +SREF(nlmsgerr); + +// From pthread.h and related +TREF(pthread_attr_t); +TREF(pthread_t); +TREF(pthread_mutex_t); +TREF(pthread_mutexattr_t); + +// From pwd.h +SREF(passwd); + +// From signal.h and related +TREF(sigset_t); +TREF(siginfo_t); +TREF(stack_t); +SREF(sigaction); +SREF(sigstack); +EREF(SI_USER); +EREF(FPE_INTOVF); +EREF(BUS_ADRALN); +EREF(SS_ONSTACK); +EREF(SEGV_MAPERR); + +// From stat.h +SREF(stat64); + +// From statfs.h +SREF(statfs); +SREF(statfs64); + +// From sysinfo.h +SREF(sysinfo); + +// From <sys/epoll.h> +#if defined(HAVE_SYS_EPOLL_H) +SREF(epoll_event); +EREF(EPOLLIN); +EREF(epoll_data_offset); +#endif + +#if defined(HAVE_SYS_MOUNT_H) +// From sys/mount.h +EREF(MS_PRIVATE); +EREF(MNT_FORCE); +#endif + +#if defined(HAVE_SYS_PTRACE_H) +// From <sys/ptrace.h> +SREF(pt_regs); +EREF(PTRACE_PEEKTEXT); +#endif + +// From sys/resource.h +SREF(rusage); +SREF(rlimit64); +EREF(RLIMIT_NOFILE); +EREF(PRIO_USER); + +// From sys/select.h +TREF(fd_set); + +// From sys/socket.h +SREF(msghdr); +SREF(cmsghdr); +SREF(ucred); +EREF(MSG_OOB); +EREF(SCM_RIGHTS); +EREF(SOCK_RAW); +EREF(SHUT_RD); + +// From sys/time.h and sys/times.h +SREF(timespec); +SREF(timeval); +SREF(itimerval); +SREF(tms); +EREF(ITIMER_PROF); + +#if defined(HAVE_SYS_TIMEX_H) +// From sys/timex.h +SREF(timex); +#endif + +// From sys/types.h +TREF(pid_t); +TREF(off_t); +TREF(loff_t); +TREF(size_t); +TREF(ssize_t); +TREF(mode_t); +TREF(dev_t); +TREF(time_t); + +// From sys/ucontext.h +TREF(ucontext_t); + +#if defined(HAVE_SYS_USER_H) +// From sys/user.h +SREF(user_regs_struct); +#endif + +#if defined(HAVE_SYS_UTSNAME_H) +// From sys/utsname.h +SREF(utsname); +#endif + +// From termios.h +SREF(termios); + +// From uio.h +SREF(iovec); + +// From utime.h +SREF(utimbuf); + +// From unistd.h +EREF(_PC_NAME_MAX); +EREF(_SC_GETPW_R_SIZE_MAX); + +#endif // clang diff --git a/libgo/testsuite/gotest b/libgo/testsuite/gotest index 06848fd..d9353d1 100755 --- a/libgo/testsuite/gotest +++ b/libgo/testsuite/gotest @@ -314,7 +314,7 @@ x) aix | android | darwin | dragonfly | freebsd | linux | nacl | netbsd | openbsd | plan9 | solaris | windows) tag1=nonmatchingtag ;; - 386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | ppc64 | ppc64le | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | ppc | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64) + 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) tag1=nonmatchingtag ;; esac @@ -326,7 +326,7 @@ x) aix | android | darwin | dragonfly | freebsd | linux | nacl | netbsd | openbsd | plan9 | solaris | windows) tag2=nonmatchingtag ;; - 386 | amd64 | amd64p32 | arm | armbe | arm64 | arm64be | alpha | ia64 | m68k | ppc64 | ppc64le | mips | mipsle | mips64 | mips64le | mips64p32 | mips64p32le | ppc | riscv64 | s390 | s390x | sh | shbe | sparc | sparc64) + 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) tag2=nonmatchingtag ;; esac @@ -506,9 +506,13 @@ localname() { { text="T" - case "$goarch" in - ppc64*) text="[TD]" ;; - esac + + # On systems using PPC64 ELF ABI v1 function symbols show up + # as descriptors in the data section. We assume that $goarch + # distinguishes v1 (ppc64) from v2 (ppc64le). + if test "$goos" != "aix" && test "$goarch" = "ppc64"; then + text="[TD]" + fi symtogo='sed -e s/_test\([^A-Za-z0-9]\)/XXXtest\1/ -e s/.*_\([^_]*\.\)/\1/ -e s/XXXtest/_test/' |