diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go
index 5e1647cbf063c1853ffe158f96f0a5877ef0de28..eb8729149cd93228e7ace409837c453f28041ce7 100644
--- a/src/cmd/dist/buildtool.go
+++ b/src/cmd/dist/buildtool.go
@@ -23,78 +23,35 @@ import (
 // compiled with a Go 1.4 toolchain to produce the bootstrapTargets.
 // All directories in this list are relative to and must be below $GOROOT/src.
 //
-// The list has have two kinds of entries: names beginning with cmd/ with
+// The list has two kinds of entries: names beginning with cmd/ with
 // no other slashes, which are commands, and other paths, which are packages
 // supporting the commands. Packages in the standard library can be listed
 // if a newer copy needs to be substituted for the Go 1.4 copy when used
-// by the command packages.
+// by the command packages. Paths ending with /... automatically
+// include all packages within subdirectories as well.
 // These will be imported during bootstrap as bootstrap/name, like bootstrap/math/big.
 var bootstrapDirs = []string{
 	"cmd/asm",
-	"cmd/asm/internal/arch",
-	"cmd/asm/internal/asm",
-	"cmd/asm/internal/flags",
-	"cmd/asm/internal/lex",
+	"cmd/asm/internal/...",
 	"cmd/cgo",
 	"cmd/compile",
-	"cmd/compile/internal/amd64",
-	"cmd/compile/internal/base",
-	"cmd/compile/internal/arm",
-	"cmd/compile/internal/arm64",
-	"cmd/compile/internal/gc",
-	"cmd/compile/internal/ir",
-	"cmd/compile/internal/logopt",
-	"cmd/compile/internal/mips",
-	"cmd/compile/internal/mips64",
-	"cmd/compile/internal/ppc64",
-	"cmd/compile/internal/riscv64",
-	"cmd/compile/internal/s390x",
-	"cmd/compile/internal/ssa",
-	"cmd/compile/internal/syntax",
-	"cmd/compile/internal/types",
-	"cmd/compile/internal/x86",
-	"cmd/compile/internal/wasm",
+	"cmd/compile/internal/...",
+	"cmd/internal/archive",
 	"cmd/internal/bio",
 	"cmd/internal/codesign",
-	"cmd/internal/gcprog",
 	"cmd/internal/dwarf",
 	"cmd/internal/edit",
+	"cmd/internal/gcprog",
 	"cmd/internal/goobj",
+	"cmd/internal/obj/...",
 	"cmd/internal/objabi",
-	"cmd/internal/obj",
-	"cmd/internal/obj/arm",
-	"cmd/internal/obj/arm64",
-	"cmd/internal/obj/mips",
-	"cmd/internal/obj/ppc64",
-	"cmd/internal/obj/riscv",
-	"cmd/internal/obj/s390x",
-	"cmd/internal/obj/x86",
-	"cmd/internal/obj/wasm",
 	"cmd/internal/pkgpath",
 	"cmd/internal/src",
 	"cmd/internal/sys",
 	"cmd/link",
-	"cmd/link/internal/amd64",
-	"cmd/compile/internal/base",
-	"cmd/link/internal/arm",
-	"cmd/link/internal/arm64",
-	"cmd/link/internal/benchmark",
-	"cmd/link/internal/ld",
-	"cmd/link/internal/loadelf",
-	"cmd/link/internal/loader",
-	"cmd/link/internal/loadmacho",
-	"cmd/link/internal/loadpe",
-	"cmd/link/internal/loadxcoff",
-	"cmd/link/internal/mips",
-	"cmd/link/internal/mips64",
-	"cmd/link/internal/ppc64",
-	"cmd/link/internal/riscv64",
-	"cmd/link/internal/s390x",
-	"cmd/link/internal/sym",
-	"cmd/link/internal/x86",
+	"cmd/link/internal/...",
 	"compress/flate",
 	"compress/zlib",
-	"cmd/link/internal/wasm",
 	"container/heap",
 	"debug/dwarf",
 	"debug/elf",
@@ -116,6 +73,7 @@ var bootstrapDirs = []string{
 var ignorePrefixes = []string{
 	".",
 	"_",
+	"#",
 }
 
 // File suffixes that use build tags introduced since Go 1.4.
@@ -129,6 +87,7 @@ var ignoreSuffixes = []string{
 	"_wasm.s",
 	"_wasm.go",
 	"_test.s",
+	"_test.go",
 }
 
 func bootstrapBuildTools() {
@@ -154,31 +113,47 @@ func bootstrapBuildTools() {
 	// Copy source code into $GOROOT/pkg/bootstrap and rewrite import paths.
 	writefile("module bootstrap\n", pathf("%s/%s", base, "go.mod"), 0)
 	for _, dir := range bootstrapDirs {
-		src := pathf("%s/src/%s", goroot, dir)
-		dst := pathf("%s/%s", base, dir)
-		xmkdirall(dst)
-		if dir == "cmd/cgo" {
-			// Write to src because we need the file both for bootstrap
-			// and for later in the main build.
-			mkzdefaultcc("", pathf("%s/zdefaultcc.go", src))
-		}
-	Dir:
-		for _, name := range xreaddirfiles(src) {
+		recurse := strings.HasSuffix(dir, "/...")
+		dir = strings.TrimSuffix(dir, "/...")
+		filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
+			if err != nil {
+				fatalf("walking bootstrap dirs failed: %v: %v", path, err)
+			}
+
+			name := filepath.Base(path)
+			src := pathf("%s/src/%s", goroot, path)
+			dst := pathf("%s/%s", base, path)
+
+			if info.IsDir() {
+				if !recurse && path != dir || name == "testdata" {
+					return filepath.SkipDir
+				}
+
+				xmkdirall(dst)
+				if path == "cmd/cgo" {
+					// Write to src because we need the file both for bootstrap
+					// and for later in the main build.
+					mkzdefaultcc("", pathf("%s/zdefaultcc.go", src))
+					mkzdefaultcc("", pathf("%s/zdefaultcc.go", dst))
+				}
+				return nil
+			}
+
 			for _, pre := range ignorePrefixes {
 				if strings.HasPrefix(name, pre) {
-					continue Dir
+					return nil
 				}
 			}
 			for _, suf := range ignoreSuffixes {
 				if strings.HasSuffix(name, suf) {
-					continue Dir
+					return nil
 				}
 			}
-			srcFile := pathf("%s/%s", src, name)
-			dstFile := pathf("%s/%s", dst, name)
-			text := bootstrapRewriteFile(srcFile)
-			writefile(text, dstFile, 0)
-		}
+
+			text := bootstrapRewriteFile(src)
+			writefile(text, dst, 0)
+			return nil
+		})
 	}
 
 	// Set up environment for invoking Go 1.4 go command.
diff --git a/src/cmd/internal/archive/archive.go b/src/cmd/internal/archive/archive.go
index c1661d7711ac901ef1ae73539e38cd2f64c83785..762e888a04d1124b4e7b19eea45340e76e114060 100644
--- a/src/cmd/internal/archive/archive.go
+++ b/src/cmd/internal/archive/archive.go
@@ -118,9 +118,9 @@ type objReader struct {
 
 func (r *objReader) init(f *os.File) {
 	r.a = &Archive{f, nil}
-	r.offset, _ = f.Seek(0, io.SeekCurrent)
-	r.limit, _ = f.Seek(0, io.SeekEnd)
-	f.Seek(r.offset, io.SeekStart)
+	r.offset, _ = f.Seek(0, os.SEEK_CUR)
+	r.limit, _ = f.Seek(0, os.SEEK_END)
+	f.Seek(r.offset, os.SEEK_SET)
 	r.b = bio.NewReader(f)
 }
 
@@ -221,7 +221,7 @@ func (r *objReader) skip(n int64) {
 		r.readFull(r.tmp[:n])
 	} else {
 		// Seek, giving up buffered data.
-		r.b.MustSeek(r.offset+n, io.SeekStart)
+		r.b.MustSeek(r.offset+n, os.SEEK_SET)
 		r.offset += n
 	}
 }
@@ -426,7 +426,7 @@ func (r *objReader) parseObject(o *GoObj, size int64) error {
 
 // AddEntry adds an entry to the end of a, with the content from r.
 func (a *Archive) AddEntry(typ EntryType, name string, mtime int64, uid, gid int, mode os.FileMode, size int64, r io.Reader) {
-	off, err := a.f.Seek(0, io.SeekEnd)
+	off, err := a.f.Seek(0, os.SEEK_END)
 	if err != nil {
 		log.Fatal(err)
 	}