diff mbox series

GCC 8 branch: update to Go 1.10.2, other fixes

Message ID CAOyqgcW9PMjHja_6Qu=M+jP6LvTOzGd1RMA4U6BTXSrSXo-xMw@mail.gmail.com
State New
Headers show
Series GCC 8 branch: update to Go 1.10.2, other fixes | expand

Commit Message

Ian Lance Taylor May 31, 2018, 10:47 p.m. UTC
I've committed this patch to update the GCC 8 branch to the Go 1.10.2
release, and also brought along a couple of other recent fixes.
Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

    cmd/go: support more Solaris assembler syntaxes

    Patch by Rainer Orth.

    For https://gcc.gnu.org/PR/85429.

    cmd/go: update to match recent changes to gc

    In https://golang.org/cl/111097 the gc version of cmd/go was updated
    to include some gofrontend-specific changes. The gofrontend code
    already has different versions of those changes; this CL makes the
    gofrontend match the upstream code.

    libgo: update to Go 1.10.2 release

    cmd/go, cmd/vet: make vet work with gccgo

    Backport https://golang.org/cl/113715 and https://golang.org/cl/113716:

    cmd/go: don't pass -compiler flag to vet

    Without this running go vet -compiler=gccgo causes vet to fail.
    The vet tool does need to know the compiler, but it is passed in
    vetConfig.Compiler.

    cmd/go, cmd/vet, go/internal/gccgoimport: make vet work with gccgo

    When using gccgo/GoLLVM, there is no package file for a standard
    library package. Since it is impossible for the go tool to rebuild the
    package, and since the package file exists only in the form of a .gox
    file, this seems like the best choice. Unfortunately it was confusing
    vet, which wanted to see a real file. This caused vet to report errors
    about missing package files for standard library packages. The
    gccgoimporter knows how to correctly handle this case. Fix this by

    1) telling vet which packages are standard;
    2) letting vet skip those packages;
    3) letting the gccgoimporter handle this case.

    As a separate required fix, gccgo/GoLLVM has no runtime/cgo package,
    so don't try to depend on it (as it happens, this fixes golang/go#25324).

    The result is that the cmd/go vet tests pass when using -compiler=gccgo.

    crypto/x509: specify path to AIX certificate file

    go/build, cmd/go: update to match recent changes to gc

    Several recent changes to the gc version of cmd/go improve the
    gofrontend support. These changes are partially copies of existing
    gofrontend differences, and partially new code. This CL makes the
    gofrontend match the upstream code.

    The changes included here come from:
        https://golang.org/cl/111575
        https://golang.org/cl/111595
        https://golang.org/cl/111635
        https://golang.org/cl/111636

    For the record, the following recent gc changes are based on code
    already present in the gofrontend repo:
        https://golang.org/cl/110915
        https://golang.org/cl/111615

    For the record, a gc change, partially based on earlier gofrontend
    work, also with new gc code, was already copied to gofrontend repo in
    CL 111099:

    https://golang.org/cl/111097

    This moves the generated list of standard library packages from
    cmd/go/internal/load to go/build.

Ian

gotools/ChangeLog:

Backport from mainline:
2018-05-09  Ian Lance Taylor  <iant@golang.org>
* Makefile.am (check-go-tool): Don't copy zstdpkglist.go.
* Makefile.in: Rebuild.
diff mbox series

Patch

Index: gotools/Makefile.am
===================================================================
--- gotools/Makefile.am	(revision 261041)
+++ gotools/Makefile.am	(working copy)
@@ -232,7 +232,6 @@  check-go-tool: go$(EXEEXT) $(noinst_PROG
 	$(MKDIR_P) check-go-dir/src/cmd/go
 	cp $(cmdsrcdir)/go/*.go check-go-dir/src/cmd/go/
 	cp -r $(cmdsrcdir)/go/internal check-go-dir/src/cmd/go/
-	cp $(libgodir)/zstdpkglist.go check-go-dir/src/cmd/go/internal/load/
 	cp $(libgodir)/zdefaultcc.go check-go-dir/src/cmd/go/internal/cfg/
 	cp -r $(cmdsrcdir)/go/testdata check-go-dir/src/cmd/go/
 	cp -r $(cmdsrcdir)/internal check-go-dir/src/cmd/
Index: libgo/MERGE
===================================================================
--- libgo/MERGE	(revision 261041)
+++ libgo/MERGE	(working copy)
@@ -1,4 +1,4 @@ 
-bf86aec25972f3a100c3aa58a6abcbcc35bdea49
+71bdbf431b79dff61944f22c25c7e085ccfc25d5
 
 The first line of this file holds the git revision number of the
 last merge done from the master library sources.
Index: libgo/Makefile.am
===================================================================
--- libgo/Makefile.am	(revision 261041)
+++ libgo/Makefile.am	(working copy)
@@ -614,13 +614,13 @@  s-runtime-inc: runtime.lo Makefile
 	rm -f runtime.inc.tmp2 runtime.inc.tmp3
 	$(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
@@ -1179,6 +1179,9 @@  runtime_pprof_check_GOCFLAGS = -static-l
 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)
 
@@ -1188,9 +1191,6 @@  cmd/internal/objabi.lo.dep: $(extra_go_f
 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
@@ -1420,6 +1420,7 @@  TEST_PACKAGES = \
 	net/http/httptrace/check \
 	net/http/httputil/check \
 	net/http/internal/check \
+	net/http/pprof/check \
 	net/internal/socktest/check \
 	net/mail/check \
 	net/rpc/check \
Index: libgo/VERSION
===================================================================
--- libgo/VERSION	(revision 261041)
+++ libgo/VERSION	(working copy)
@@ -1 +1 @@ 
-go1.10
+go1.10.2
Index: libgo/go/archive/zip/reader.go
===================================================================
--- libgo/go/archive/zip/reader.go	(revision 261041)
+++ libgo/go/archive/zip/reader.go	(working copy)
@@ -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
 			}
@@ -378,12 +378,6 @@  parseExtras:
 				continue 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)
 		}
 	}
Index: libgo/go/archive/zip/reader_test.go
===================================================================
--- libgo/go/archive/zip/reader_test.go	(revision 261041)
+++ libgo/go/archive/zip/reader_test.go	(working copy)
@@ -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,
 			},
 		},
Index: libgo/go/cmd/go/alldocs.go
===================================================================
--- libgo/go/cmd/go/alldocs.go	(revision 261041)
+++ libgo/go/cmd/go/alldocs.go	(working copy)
@@ -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
Index: libgo/go/cmd/go/go_test.go
===================================================================
--- libgo/go/cmd/go/go_test.go	(revision 261041)
+++ libgo/go/cmd/go/go_test.go	(working copy)
@@ -3271,6 +3271,20 @@  func TestGoVetWithOnlyTestFiles(t *testi
 	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 +5119,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 +5834,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 +6007,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)
+	}
+}
Index: libgo/go/cmd/go/internal/cfg/cfg.go
===================================================================
--- libgo/go/cmd/go/internal/cfg/cfg.go	(revision 261041)
+++ libgo/go/cmd/go/internal/cfg/cfg.go	(working copy)
@@ -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()
Index: libgo/go/cmd/go/internal/get/vcs.go
===================================================================
--- libgo/go/cmd/go/internal/get/vcs.go	(revision 261041)
+++ libgo/go/cmd/go/internal/get/vcs.go	(working copy)
@@ -809,8 +809,8 @@  func repoRootForImportDynamic(importPath
 		}
 	}
 
-	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
 	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
Index: libgo/go/cmd/go/internal/get/vcs_test.go
===================================================================
--- libgo/go/cmd/go/internal/get/vcs_test.go	(revision 261041)
+++ libgo/go/cmd/go/internal/get/vcs_test.go	(working copy)
@@ -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)
+		}
+	}
+}
Index: libgo/go/cmd/go/internal/help/helpdoc.go
===================================================================
--- libgo/go/cmd/go/internal/help/helpdoc.go	(revision 261041)
+++ libgo/go/cmd/go/internal/help/helpdoc.go	(working copy)
@@ -526,6 +526,9 @@  Architecture-specific environment variab
 
 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.
 	`,
 }
 
Index: libgo/go/cmd/go/internal/load/pkg.go
===================================================================
--- libgo/go/cmd/go/internal/load/pkg.go	(revision 261041)
+++ libgo/go/cmd/go/internal/load/pkg.go	(working copy)
@@ -13,7 +13,6 @@  import (
 	"os"
 	pathpkg "path"
 	"path/filepath"
-	"runtime"
 	"sort"
 	"strings"
 	"unicode"
@@ -224,9 +223,6 @@  func (p *Package) copyBuild(pp *build.Pa
 	// 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,
 			// 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,
 
 	// 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,
 
 	// 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,
 			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(),
@@ -1239,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.
@@ -1611,9 +1599,6 @@  func GetTestPackagesFor(p *Package, forc
 	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
 		}
@@ -1642,9 +1627,6 @@  func GetTestPackagesFor(p *Package, forc
 	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
 		}
Index: libgo/go/cmd/go/internal/test/test.go
===================================================================
--- libgo/go/cmd/go/internal/test/test.go	(revision 261041)
+++ libgo/go/cmd/go/internal/test/test.go	(working copy)
@@ -633,6 +633,8 @@  func runTest(cmd *base.Command, args []s
 		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 []s
 				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 *loa
 			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
 			}
Index: libgo/go/cmd/go/internal/vet/vet.go
===================================================================
--- libgo/go/cmd/go/internal/vet/vet.go	(revision 261041)
+++ libgo/go/cmd/go/internal/vet/vet.go	(working copy)
@@ -62,11 +62,11 @@  func runVet(cmd *base.Command, args []st
 			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 {
Index: libgo/go/cmd/go/internal/vet/vetflag.go
===================================================================
--- libgo/go/cmd/go/internal/vet/vetflag.go	(revision 261041)
+++ libgo/go/cmd/go/internal/vet/vetflag.go	(working copy)
@@ -90,7 +90,7 @@  func vetFlags(args []string) (passToVet,
 			}
 			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
Index: libgo/go/cmd/go/internal/work/buildid.go
===================================================================
--- libgo/go/cmd/go/internal/work/buildid.go	(revision 261041)
+++ libgo/go/cmd/go/internal/work/buildid.go	(working copy)
@@ -234,18 +234,9 @@  func (b *Builder) gccgoToolID(name, lang
 	// compile an empty file on standard input.
 	cmdline := str.StringList(cfg.BuildToolexec, name, "-###", "-x", language, "-c", "-")
 	cmd := exec.Command(cmdline[0], cmdline[1:]...)
-
-	// Strip any LANG or LC_ environment variables, and force
-	// LANG=C, so that we get the untranslated output.
-	var env []string
-	for _, e := range os.Environ() {
-		if !strings.HasPrefix(e, "LANG=") && !strings.HasPrefix(e, "LC_") {
-			env = append(env, e)
-		}
-	}
-	env = append(env, "LANG=C")
-
-	cmd.Env = base.EnvForDir(cmd.Dir, env)
+	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)
@@ -303,16 +294,35 @@  func (b *Builder) gccgoToolID(name, lang
 	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
-	if cfg.Goos != "solaris" {
+	if cfg.Goos != "solaris" || assemblerIsGas() {
 		fmt.Fprintf(&buf, "\t"+`.section .go.buildid,"e"`+"\n")
-	} else {
+	} 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++ {
@@ -451,15 +461,7 @@  func (b *Builder) useCache(a *Action, p
 	// 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
@@ -536,7 +538,10 @@  func (b *Builder) useCache(a *Action, p
 				}
 			}
 		}
-		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.
@@ -564,6 +569,10 @@  func (b *Builder) useCache(a *Action, p
 						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
 					}
 				}
@@ -574,6 +583,10 @@  func (b *Builder) useCache(a *Action, p
 		a.output = []byte{}
 	}
 
+	if b.ComputeStaleOnly {
+		return true
+	}
+
 	return false
 }
 
Index: libgo/go/cmd/go/internal/work/exec.go
===================================================================
--- libgo/go/cmd/go/internal/work/exec.go	(revision 261041)
+++ libgo/go/cmd/go/internal/work/exec.go	(working copy)
@@ -512,6 +512,7 @@  func (b *Builder) build(a *Action) (err
 			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
 
 	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,11 +956,19 @@  func splitPkgConfigOutput(out []byte) []
 
 // 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
-		for len(pkgs) > 0 && strings.HasPrefix(pkgs[0], "--") {
-			pcflags = append(pcflags, pkgs[0])
-			pkgs = pkgs[1:]
+		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) {
@@ -1095,7 +1115,7 @@  func BuildInstallFunc(b *Builder, a *Act
 		// 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)
 		}
@@ -1545,6 +1565,8 @@  func joinUnambiguously(a []string) strin
 			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 {
@@ -1585,13 +1607,17 @@  func (b *Builder) Mkdir(dir string) erro
 
 // 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)
 }
 
Index: libgo/go/cmd/go/internal/work/security.go
===================================================================
--- libgo/go/cmd/go/internal/work/security.go	(revision 261041)
+++ libgo/go/cmd/go/internal/work/security.go	(working copy)
@@ -46,12 +46,19 @@  var validCompilerFlags = []*regexp.Regex
 	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`),
@@ -62,27 +69,42 @@  var validCompilerFlags = []*regexp.Regex
 	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(`-?-stdlib=([^@\-].*)`),
+	re(`-w`),
 	re(`-x([^@\-].*)`),
 }
 
 var validCompilerFlagsWithNextArg = []string{
+	"-arch",
 	"-D",
 	"-I",
-	"-isystem",
 	"-framework",
+	"-isysroot",
+	"-isystem",
+	"--sysroot",
+	"-target",
 	"-x",
 }
 
@@ -90,43 +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,--(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,-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_/].*\.(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 {
Index: libgo/go/cmd/go/internal/work/security_test.go
===================================================================
--- libgo/go/cmd/go/internal/work/security_test.go	(revision 261041)
+++ libgo/go/cmd/go/internal/work/security_test.go	(working copy)
@@ -140,9 +140,6 @@  var goodLinkerFlags = [][]string{
 var badLinkerFlags = [][]string{
 	{"-DFOO"},
 	{"-Dfoo=bar"},
-	{"-O"},
-	{"-O2"},
-	{"-Osmall"},
 	{"-W"},
 	{"-Wall"},
 	{"-fobjc-arc"},
@@ -155,7 +152,6 @@  var badLinkerFlags = [][]string{
 	{"-fno-stack-xxx"},
 	{"-mstack-overflow"},
 	{"-mno-stack-overflow"},
-	{"-mmacosx-version"},
 	{"-mnop-fun-dllimport"},
 	{"-std=c99"},
 	{"-xc"},
Index: libgo/go/cmd/internal/objabi/funcid.go
===================================================================
--- libgo/go/cmd/internal/objabi/funcid.go	(nonexistent)
+++ libgo/go/cmd/internal/objabi/funcid.go	(working copy)
@@ -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
+)
Index: libgo/go/cmd/vet/main.go
===================================================================
--- libgo/go/cmd/vet/main.go	(revision 261041)
+++ libgo/go/cmd/vet/main.go	(working copy)
@@ -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)
 	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)
 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.
Index: libgo/go/crypto/x509/name_constraints_test.go
===================================================================
--- libgo/go/crypto/x509/name_constraints_test.go	(revision 261041)
+++ libgo/go/crypto/x509/name_constraints_test.go	(working copy)
@@ -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 = []nameConstra
 		},
 		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 c
 		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 leafSp
 		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 leafSp
 			}
 			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 *testin
 }
 
 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)
Index: libgo/go/crypto/x509/root_aix.go
===================================================================
--- libgo/go/crypto/x509/root_aix.go	(revision 261041)
+++ libgo/go/crypto/x509/root_aix.go	(working copy)
@@ -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",
+}
Index: libgo/go/crypto/x509/verify.go
===================================================================
--- libgo/go/crypto/x509/verify.go	(revision 261041)
+++ libgo/go/crypto/x509/verify.go	(working copy)
@@ -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) checkNameConstrain
 	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 ExtKeyU
 	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 i
 				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 i
 
 			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 i
 
 			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 i
 	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 Verify
 	}
 
 	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}
 		}
 	}
 
Index: libgo/go/crypto/x509/x509.go
===================================================================
--- libgo/go/crypto/x509/x509.go	(revision 261041)
+++ libgo/go/crypto/x509/x509.go	(working copy)
@@ -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) (dn
 	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) (dn
 			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 []
 
 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,
Index: libgo/go/encoding/json/decode.go
===================================================================
--- libgo/go/encoding/json/decode.go	(revision 261041)
+++ libgo/go/encoding/json/decode.go	(working copy)
@@ -443,10 +443,25 @@  func (d *decodeState) valueQuoted() inte
 // 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
 		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
 				}
 			}
 		}
-		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
 }
Index: libgo/go/encoding/json/decode_test.go
===================================================================
--- libgo/go/encoding/json/decode_test.go	(revision 261041)
+++ libgo/go/encoding/json/decode_test.go	(working copy)
@@ -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.
 	}
 }
 
-// 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 TestUnmarshalEmbeddedPointerUnexpor
 			*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 TestUnmarshalEmbeddedPointerUnexpor
 		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 {
Index: libgo/go/go/build/build.go
===================================================================
--- libgo/go/go/build/build.go	(revision 261041)
+++ libgo/go/go/build/build.go	(working copy)
@@ -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,
 		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,
 				// 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,
 				}
 				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,
 		// 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
Index: libgo/go/go/build/gc.go
===================================================================
--- libgo/go/go/build/gc.go	(nonexistent)
+++ libgo/go/go/build/gc.go	(working copy)
@@ -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
+}
Index: libgo/go/go/build/gccgo.go
===================================================================
--- libgo/go/go/build/gccgo.go	(nonexistent)
+++ libgo/go/go/build/gccgo.go	(working copy)
@@ -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]
+}
Index: libgo/go/go/internal/gccgoimporter/importer.go
===================================================================
--- libgo/go/go/internal/gccgoimporter/importer.go	(revision 261041)
+++ libgo/go/go/internal/gccgoimporter/importer.go	(working copy)
@@ -176,7 +176,7 @@  func GetImporter(searchpaths []string, i
 				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 {
Index: libgo/go/go/internal/srcimporter/srcimporter.go
===================================================================
--- libgo/go/go/internal/srcimporter/srcimporter.go	(revision 261041)
+++ libgo/go/go/internal/srcimporter/srcimporter.go	(working copy)
@@ -44,9 +44,9 @@  func New(ctxt *build.Context, fset *toke
 // 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, srcD
 		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, srcD
 		}
 	}()
 
-	// 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...)
Index: libgo/go/go/internal/srcimporter/srcimporter_test.go
===================================================================
--- libgo/go/go/internal/srcimporter/srcimporter_test.go	(revision 261041)
+++ libgo/go/go/internal/srcimporter/srcimporter_test.go	(working copy)
@@ -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")
+}
Index: libgo/go/go/internal/srcimporter/testdata/issue23092/issue23092.go
===================================================================
--- libgo/go/go/internal/srcimporter/testdata/issue23092/issue23092.go	(nonexistent)
+++ libgo/go/go/internal/srcimporter/testdata/issue23092/issue23092.go	(working copy)
@@ -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
Index: libgo/go/go/internal/srcimporter/testdata/issue24392/issue24392.go
===================================================================
--- libgo/go/go/internal/srcimporter/testdata/issue24392/issue24392.go	(nonexistent)
+++ libgo/go/go/internal/srcimporter/testdata/issue24392/issue24392.go	(working copy)
@@ -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
Index: libgo/go/internal/singleflight/singleflight.go
===================================================================
--- libgo/go/internal/singleflight/singleflight.go	(revision 261041)
+++ libgo/go/internal/singleflight/singleflight.go	(working copy)
@@ -103,11 +103,21 @@  func (g *Group) doCall(c *call, key stri
 	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
 }
Index: libgo/go/net/http/pprof/pprof.go
===================================================================
--- libgo/go/net/http/pprof/pprof.go	(revision 261041)
+++ libgo/go/net/http/pprof/pprof.go	(working copy)
@@ -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
 	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 *h
 // 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 *htt
 // 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)
 }
 
Index: libgo/go/net/http/pprof/pprof_test.go
===================================================================
--- libgo/go/net/http/pprof/pprof_test.go	(nonexistent)
+++ libgo/go/net/http/pprof/pprof_test.go	(working copy)
@@ -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)
+			}
+		})
+	}
+
+}
Index: libgo/go/net/lookup.go
===================================================================
--- libgo/go/net/lookup.go	(revision 261041)
+++ libgo/go/net/lookup.go	(working copy)
@@ -194,10 +194,16 @@  func (r *Resolver) LookupIPAddr(ctx cont
 		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 cont
 
 	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)
Index: libgo/go/net/lookup_test.go
===================================================================
--- libgo/go/net/lookup_test.go	(revision 261041)
+++ libgo/go/net/lookup_test.go	(working copy)
@@ -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)
+	}
+}
Index: libgo/go/net/tcpsock_unix_test.go
===================================================================
--- libgo/go/net/tcpsock_unix_test.go	(revision 261041)
+++ libgo/go/net/tcpsock_unix_test.go	(working copy)
@@ -87,6 +87,7 @@  func TestTCPSpuriousConnSetupCompletionW
 	if testenv.Builder() == "" {
 		testenv.MustHaveExternalNetwork(t)
 	}
+	defer dnsWaitGroup.Wait()
 	t.Parallel()
 	const tries = 10000
 	var wg sync.WaitGroup
Index: libgo/go/runtime/error.go
===================================================================
--- libgo/go/runtime/error.go	(revision 261041)
+++ libgo/go/runtime/error.go	(working copy)
@@ -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:
Index: libgo/go/runtime/panic.go
===================================================================
--- libgo/go/runtime/panic.go	(revision 261041)
+++ libgo/go/runtime/panic.go	(working copy)
@@ -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]")
Index: libgo/go/runtime/proc.go
===================================================================
--- libgo/go/runtime/proc.go	(revision 261041)
+++ libgo/go/runtime/proc.go	(working copy)
@@ -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
Index: libgo/go/runtime/symtab.go
===================================================================
--- libgo/go/runtime/symtab.go	(revision 261041)
+++ libgo/go/runtime/symtab.go	(working copy)
@@ -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.
 //
Index: libgo/misc/cgo/testplugin/src/issue24351/main.go
===================================================================
--- libgo/misc/cgo/testplugin/src/issue24351/main.go	(nonexistent)
+++ libgo/misc/cgo/testplugin/src/issue24351/main.go	(working copy)
@@ -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
+}
Index: libgo/misc/cgo/testplugin/src/issue24351/plugin.go
===================================================================
--- libgo/misc/cgo/testplugin/src/issue24351/plugin.go	(nonexistent)
+++ libgo/misc/cgo/testplugin/src/issue24351/plugin.go	(working copy)
@@ -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
+	}()
+}
Index: libgo/misc/cgo/testplugin/test.bash
===================================================================
--- libgo/misc/cgo/testplugin/test.bash	(revision 261041)
+++ libgo/misc/cgo/testplugin/test.bash	(working copy)
@@ -85,3 +85,8 @@  GOPATH=$(pwd) go build -gcflags "$GO_GCF
 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
Index: libgo/misc/cgo/testshared/shared_test.go
===================================================================
--- libgo/misc/cgo/testshared/shared_test.go	(revision 261041)
+++ libgo/misc/cgo/testshared/shared_test.go	(working copy)
@@ -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"))