[tools] Delete all tools.

They have been moved to fuchsia.git.

Bug: 10321
Change-Id: Iacc8f2ece7a5b070a5727ddb6e393b6cb8e45fcf
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index f821f1c..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright 2018 The Fuchsia Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-   * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-   * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/PATENTS b/PATENTS
deleted file mode 100644
index 2746e78..0000000
--- a/PATENTS
+++ /dev/null
@@ -1,22 +0,0 @@
-Additional IP Rights Grant (Patents)
-
-"This implementation" means the copyrightable works distributed by
-Google as part of the Fuchsia project.
-
-Google hereby grants to you a perpetual, worldwide, non-exclusive,
-no-charge, royalty-free, irrevocable (except as stated in this
-section) patent license to make, have made, use, offer to sell, sell,
-import, transfer, and otherwise run, modify and propagate the contents
-of this implementation of Fuchsia, where such license applies only to
-those patent claims, both currently owned by Google and acquired in
-the future, licensable by Google that are necessarily infringed by
-this implementation. This grant does not include claims that would be
-infringed only as a consequence of further modification of this
-implementation. If you or your agent or exclusive licensee institute
-or order or agree to the institution of patent litigation or any other
-patent enforcement activity against any entity (including a
-cross-claim or counterclaim in a lawsuit) alleging that this
-implementation of Fuchsia constitutes direct or contributory patent
-infringement, or inducement of patent infringement, then any patent
-rights granted to you under this License for this implementation of
-Fuchsia shall terminate as of the date such litigation is filed.
diff --git a/README.md b/README.md
index 1745a5c..5b3a962 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,3 @@
 # tools
 
-This repo contains tools used in Fuchsia build and development.
-
-Go packages from here are automatically built and uploaded to CIPD and Google
-Storage by bots using the [tools](https://fuchsia.googlesource.com/infra/recipes/+/master/recipes/tools.py) recipe.
+All tools have been moved to fuchsia.git at https://fuchsia.googlesource.com/fuchsia/+/refs/heads/master/tools.
diff --git a/botanist/boot.go b/botanist/boot.go
deleted file mode 100644
index 22f01e4..0000000
--- a/botanist/boot.go
+++ /dev/null
@@ -1,307 +0,0 @@
-// Copyright 2018 The Fuchsia 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 botanist
-
-import (
-	"bytes"
-	"context"
-	"errors"
-	"fmt"
-	"io"
-	"log"
-	"net"
-	"os"
-	"sort"
-	"strings"
-	"time"
-
-	"go.fuchsia.dev/tools/build/api"
-	"go.fuchsia.dev/tools/lib/retry"
-	"go.fuchsia.dev/tools/net/netboot"
-	"go.fuchsia.dev/tools/net/tftp"
-	"golang.org/x/crypto/ssh"
-)
-
-const (
-	// ModePave is a directive to pave when booting.
-	ModePave int = iota
-	// ModeNetboot is a directive to netboot when booting.
-	ModeNetboot
-)
-
-const (
-	// Special image names recognized by fuchsia's netsvc.
-	authorizedKeysNetsvcName = "<<image>>authorized_keys"
-	bootloaderNetsvcName     = "<<image>>bootloader.img"
-	cmdlineNetsvcName        = "<<netboot>>cmdline"
-	efiNetsvcName            = "<<image>>efi.img"
-	fvmNetsvcName            = "<<image>>sparse.fvm"
-	kerncNetsvcName          = "<<image>>kernc.img"
-	kernelNetsvcName         = "<<netboot>>kernel.bin"
-	vbmetaANetsvcName        = "<<image>>vbmetaa.img"
-	vbmetaBNetsvcName        = "<<image>>vbmetab.img"
-	zirconANetsvcName        = "<<image>>zircona.img"
-	zirconBNetsvcName        = "<<image>>zirconb.img"
-	zirconRNetsvcName        = "<<image>>zirconr.img"
-)
-
-// Maps bootserver argument to a corresponding netsvc name.
-var bootserverArgToName = map[string]string{
-	"--boot":       kernelNetsvcName,
-	"--bootloader": bootloaderNetsvcName,
-	"--efi":        efiNetsvcName,
-	"--fvm":        fvmNetsvcName,
-	"--kernc":      kerncNetsvcName,
-	"--vbmetaa":    vbmetaANetsvcName,
-	"--vbmetab":    vbmetaBNetsvcName,
-	"--zircona":    zirconANetsvcName,
-	"--zirconb":    zirconBNetsvcName,
-	"--zirconr":    zirconRNetsvcName,
-}
-
-// Maps netsvc name to the index at which the corresponding file should be transferred if
-// present. The indices correspond to the ordering given in
-// https://go.fuchsia.dev/zircon/+/master/system/host/bootserver/bootserver.c
-var transferOrder = map[string]int{
-	cmdlineNetsvcName:        1,
-	fvmNetsvcName:            2,
-	bootloaderNetsvcName:     3,
-	efiNetsvcName:            4,
-	kerncNetsvcName:          5,
-	zirconANetsvcName:        6,
-	zirconBNetsvcName:        7,
-	zirconRNetsvcName:        8,
-	vbmetaANetsvcName:        9,
-	vbmetaBNetsvcName:        10,
-	authorizedKeysNetsvcName: 11,
-	kernelNetsvcName:         12,
-}
-
-// Boot prepares and boots a device at the given IP address. Depending on bootMode, the
-// device will either be paved or netbooted with the provided images, command-line
-// arguments and a public SSH user key.
-func Boot(ctx context.Context, addr *net.UDPAddr, bootMode int, imgs []build.Image, cmdlineArgs []string, signers []ssh.Signer) error {
-	var bootArgs func(build.Image) []string
-	switch bootMode {
-	case ModePave:
-		bootArgs = func(img build.Image) []string { return img.PaveArgs }
-	case ModeNetboot:
-		bootArgs = func(img build.Image) []string { return img.NetbootArgs }
-	default:
-		return fmt.Errorf("invalid boot mode: %d", bootMode)
-	}
-
-	var files []*netsvcFile
-	if len(cmdlineArgs) > 0 {
-		var buf bytes.Buffer
-		for _, arg := range cmdlineArgs {
-			fmt.Fprintf(&buf, "%s\n", arg)
-		}
-		cmdlineFile, err := newNetsvcFile(cmdlineNetsvcName, buf.Bytes())
-		if err != nil {
-			return err
-		}
-		files = append(files, cmdlineFile)
-	}
-
-	for _, img := range imgs {
-		for _, arg := range bootArgs(img) {
-			name, ok := bootserverArgToName[arg]
-			if !ok {
-				return fmt.Errorf("unrecognized bootserver argument found: %s", arg)
-			}
-			imgFile, err := openNetsvcFile(name, img.Path)
-			if err != nil {
-				return err
-			}
-			defer imgFile.close()
-			files = append(files, imgFile)
-		}
-	}
-
-	if bootMode == ModePave && len(signers) > 0 {
-		var authorizedKeys []byte
-		for _, s := range signers {
-			authorizedKey := ssh.MarshalAuthorizedKey(s.PublicKey())
-			authorizedKeys = append(authorizedKeys, authorizedKey...)
-		}
-		authorizedKeysFile, err := newNetsvcFile(authorizedKeysNetsvcName, authorizedKeys)
-		if err != nil {
-			return err
-		}
-		files = append(files, authorizedKeysFile)
-	}
-
-	sort.Slice(files, func(i, j int) bool {
-		return files[i].index < files[j].index
-	})
-
-	if len(files) == 0 {
-		return errors.New("no files to transfer")
-	}
-	if err := transfer(ctx, addr, files); err != nil {
-		return err
-	}
-
-	// If we do not load a kernel into RAM, then we reboot back into the first kernel
-	// partition; else we boot directly from RAM.
-	// TODO(ZX-2069): Eventually, no such kernel should be present.
-	hasRAMKernel := files[len(files)-1].name == kernelNetsvcName
-	n := netboot.NewClient(time.Second)
-	if hasRAMKernel {
-		// Try to send the boot command a few times, as there's no ack, so it's
-		// not possible to tell if it's successfully booted or not.
-		for i := 0; i < 5; i++ {
-			n.Boot(addr)
-		}
-	}
-	return n.Reboot(addr)
-}
-
-// BootZedbootShim extracts the Zircon-R image that is intended to be paved to the device
-// and mexec()'s it, it is intended to be executed before calling Boot().
-// This function serves to emulate zero-state, and will eventually be superseded by an
-// infra implementation.
-func BootZedbootShim(ctx context.Context, addr *net.UDPAddr, imgs []build.Image) error {
-	netsvcName := kernelNetsvcName
-	zirconRImg := build.Image{}
-	for _, img := range imgs {
-		for _, arg := range img.PaveArgs {
-			// Find name by bootserver arg to ensure we are extracting the correct zircon-r.
-			// There may be more than one in images.json but only one should be passed to
-			// the bootserver for paving.
-			name, ok := bootserverArgToName[arg]
-			if !ok {
-				return fmt.Errorf("unrecognized bootserver argument found: %q", arg)
-			}
-			if name == zirconRNetsvcName {
-				zirconRImg = img
-				// Signed ZBIs cannot be mexec()'d, so pave them to A and boot instead.
-				if strings.HasSuffix(img.Name, ".signed") {
-					netsvcName = zirconANetsvcName
-				}
-				break
-			}
-		}
-		if zirconRImg.Name != "" {
-			break
-		}
-	}
-
-	if zirconRImg.Name != "" {
-		imgFile, err := openNetsvcFile(netsvcName, zirconRImg.Path)
-		if err != nil {
-			return err
-		}
-		defer imgFile.close()
-		if err := transfer(ctx, addr, []*netsvcFile{imgFile}); err != nil {
-			return err
-		}
-		n := netboot.NewClient(time.Second)
-		if netsvcName == kernelNetsvcName {
-			return n.Boot(addr)
-		}
-		return n.Reboot(addr)
-	}
-
-	return fmt.Errorf("no zircon-r image found in: %v", imgs)
-}
-
-// A file to send to netsvc.
-type netsvcFile struct {
-	name   string
-	reader io.Reader
-	size   int64
-	index  int
-}
-
-func (f netsvcFile) close() error {
-	closer, ok := (f.reader).(io.Closer)
-	if ok {
-		return closer.Close()
-	}
-	return nil
-}
-
-func openNetsvcFile(name, path string) (*netsvcFile, error) {
-	idx, ok := transferOrder[name]
-	if !ok {
-		return nil, fmt.Errorf("unrecognized name: %s", name)
-	}
-	fd, err := os.Open(path)
-	if err != nil {
-		fd.Close()
-		return nil, err
-	}
-	fi, err := fd.Stat()
-	if err != nil {
-		fd.Close()
-		return nil, err
-	}
-	return &netsvcFile{name: name, reader: fd, size: fi.Size(), index: idx}, nil
-}
-
-func newNetsvcFile(name string, buf []byte) (*netsvcFile, error) {
-	idx, ok := transferOrder[name]
-	if !ok {
-		return nil, fmt.Errorf("unrecognized name: %s", name)
-	}
-	return &netsvcFile{
-		reader: bytes.NewReader(buf),
-		size:   int64(len(buf)),
-		name:   name,
-		index:  idx,
-	}, nil
-}
-
-// Transfers files over TFTP to a node at a given address.
-func transfer(ctx context.Context, addr *net.UDPAddr, files []*netsvcFile) error {
-	t := tftp.NewClient()
-	tftpAddr := &net.UDPAddr{
-		IP:   addr.IP,
-		Port: tftp.ClientPort,
-		Zone: addr.Zone,
-	}
-
-	// Attempt the whole process of sending every file over and retry on failure of any file.
-	// This behavior more closely aligns with that of the bootserver.
-	return retry.Retry(ctx, retry.WithMaxRetries(retry.NewConstantBackoff(time.Second), 20), func() error {
-		for _, f := range files {
-			// Attempt to send a file. If the server tells us we need to wait, then try
-			// again as long as it keeps telling us this. ErrShouldWait implies the server
-			// is still responding and will eventually be able to handle our request.
-			for {
-				select {
-				case <-ctx.Done():
-					return nil
-				default:
-				}
-				log.Printf("attempting to send %s...\n", f.name)
-				reader, err := t.Send(tftpAddr, f.name, f.size)
-				switch {
-				case err == tftp.ErrShouldWait:
-					// The target is busy, so let's sleep for a bit before
-					// trying again, otherwise we'll be wasting cycles and
-					// printing too often.
-					log.Printf("target is busy, retrying in one second\n")
-					select {
-					case <-time.After(time.Second):
-						continue
-					}
-				case err != nil:
-					log.Printf("failed to send %s; starting from the top: %v\n", f.name, err)
-					return err
-				}
-				if _, err := reader.ReadFrom(f.reader); err != nil {
-					log.Printf("unable to read from %s; retrying: %v\n", f.name, err)
-					return err
-				}
-				break
-			}
-			log.Printf("done\n")
-		}
-		return nil
-	}, nil)
-}
diff --git a/botanist/cmd/main.go b/botanist/cmd/main.go
deleted file mode 100644
index e749d42..0000000
--- a/botanist/cmd/main.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2017 The Fuchsia 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 (
-	"context"
-	"flag"
-	"os"
-	"syscall"
-
-	"github.com/google/subcommands"
-
-	"go.fuchsia.dev/tools/lib/color"
-	"go.fuchsia.dev/tools/lib/command"
-	"go.fuchsia.dev/tools/lib/logger"
-)
-
-var (
-	colors color.EnableColor
-	level  logger.LogLevel
-)
-
-func init() {
-	colors = color.ColorAuto
-	level = logger.InfoLevel
-
-	flag.Var(&colors, "color", "use color in output, can be never, auto, always")
-	flag.Var(&level, "level", "output verbosity, can be fatal, error, warning, info, debug or trace")
-}
-
-func main() {
-	subcommands.Register(subcommands.HelpCommand(), "")
-	subcommands.Register(subcommands.CommandsCommand(), "")
-	subcommands.Register(subcommands.FlagsCommand(), "")
-	subcommands.Register(&ZedbootCommand{}, "")
-	subcommands.Register(&QEMUCommand{}, "")
-	subcommands.Register(&RunCommand{}, "")
-
-	flag.Parse()
-
-	log := logger.NewLogger(level, color.NewColor(colors), os.Stdout, os.Stderr, "botanist ")
-	ctx := logger.WithLogger(context.Background(), log)
-	ctx = command.CancelOnSignals(ctx, syscall.SIGTERM)
-	os.Exit(int(subcommands.Execute(ctx)))
-}
diff --git a/botanist/cmd/qemu.go b/botanist/cmd/qemu.go
deleted file mode 100644
index 9ef6850..0000000
--- a/botanist/cmd/qemu.go
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2018 The Fuchsia 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 (
-	"context"
-	"flag"
-	"fmt"
-
-	"github.com/google/subcommands"
-	"go.fuchsia.dev/tools/botanist/target"
-	"go.fuchsia.dev/tools/build/api"
-	"go.fuchsia.dev/tools/lib/logger"
-)
-
-// QEMUBinPrefix is the prefix of the QEMU binary name, which is of the form
-// qemu-system-<QEMU arch suffix>.
-const qemuBinPrefix = "qemu-system"
-
-// QEMUCommand is a Command implementation for running the testing workflow on an emulated
-// target within QEMU.
-type QEMUCommand struct {
-	// ImageManifest is the path an image manifest specifying a QEMU kernel, a zircon
-	// kernel, and block image to back QEMU storage.
-	imageManifest string
-
-	// QEMUBinDir is a path to a directory of QEMU binaries.
-	qemuBinDir string
-
-	// MinFSImage is a path to a minFS image to be mounted on target, and to where test
-	// results will be written.
-	minFSImage string
-
-	// MinFSBlkDevPCIAddr is a minFS block device PCI address.
-	minFSBlkDevPCIAddr string
-
-	// TargetArch is the target architecture to be emulated within QEMU
-	targetArch string
-
-	// EnableKVM dictates whether to enable KVM.
-	enableKVM bool
-
-	// CPU is the number of processors to emulate.
-	cpu int
-
-	// Memory is the amount of memory (in MB) to provide.
-	memory int
-}
-
-func (*QEMUCommand) Name() string {
-	return "qemu"
-}
-
-func (*QEMUCommand) Usage() string {
-	return "qemu [flags...] [kernel command-line arguments...]\n\nflags:\n"
-}
-
-func (*QEMUCommand) Synopsis() string {
-	return "boots a QEMU device with a MinFS image as a block device."
-}
-
-func (cmd *QEMUCommand) SetFlags(f *flag.FlagSet) {
-	f.StringVar(&cmd.imageManifest, "images", "", "path to an image manifest")
-	f.StringVar(&cmd.qemuBinDir, "qemu-dir", "", "")
-	f.StringVar(&cmd.minFSImage, "minfs", "", "path to minFS image")
-	f.StringVar(&cmd.minFSBlkDevPCIAddr, "pci-addr", "06.0", "minFS block device PCI address")
-	f.StringVar(&cmd.targetArch, "arch", "", "target architecture (x64 or arm64)")
-	f.BoolVar(&cmd.enableKVM, "use-kvm", false, "whether to enable KVM")
-	f.IntVar(&cmd.cpu, "cpu", 4, "number of processors to emulate")
-	f.IntVar(&cmd.memory, "memory", 4096, "amount of memory (in MB) to provide")
-}
-
-func (cmd *QEMUCommand) execute(ctx context.Context, cmdlineArgs []string) error {
-	if cmd.qemuBinDir == "" {
-		return fmt.Errorf("-qemu-dir must be set")
-	}
-
-	imgs, err := build.LoadImages(cmd.imageManifest)
-	if err != nil {
-		return err
-	}
-
-	// TODO: pass this directly from a file.
-	config := target.QEMUConfig{
-		CPU:            cmd.cpu,
-		Memory:         cmd.memory,
-		Path:           cmd.qemuBinDir,
-		Target:         cmd.targetArch,
-		KVM:            cmd.enableKVM,
-		UserNetworking: true,
-	}
-	if cmd.minFSImage != "" {
-		config.MinFS = &target.MinFS{
-			Image:      cmd.minFSImage,
-			PCIAddress: cmd.minFSBlkDevPCIAddr,
-		}
-	}
-
-	t := target.NewQEMUTarget(config, target.Options{})
-	if err := t.Start(ctx, imgs, cmdlineArgs); err != nil {
-		return err
-	}
-
-	return t.Wait(ctx)
-}
-
-func (cmd *QEMUCommand) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
-	if err := cmd.execute(ctx, f.Args()); err != nil {
-		logger.Errorf(ctx, "%v\n", err)
-		return subcommands.ExitFailure
-	}
-	return subcommands.ExitSuccess
-}
diff --git a/botanist/cmd/run.go b/botanist/cmd/run.go
deleted file mode 100644
index 7337f5b..0000000
--- a/botanist/cmd/run.go
+++ /dev/null
@@ -1,387 +0,0 @@
-// Copyright 2018 The Fuchsia 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 (
-	"context"
-	"encoding/json"
-	"flag"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"net"
-	"os"
-	"path/filepath"
-	"sync"
-	"time"
-
-	"go.fuchsia.dev/tools/botanist"
-	"go.fuchsia.dev/tools/botanist/target"
-	"go.fuchsia.dev/tools/build/api"
-	"go.fuchsia.dev/tools/lib/command"
-	"go.fuchsia.dev/tools/lib/logger"
-	"go.fuchsia.dev/tools/lib/runner"
-	"go.fuchsia.dev/tools/net/sshutil"
-
-	"github.com/google/subcommands"
-)
-
-const (
-	netstackTimeout time.Duration = 1 * time.Minute
-)
-
-// Target represents a fuchsia instance.
-type Target interface {
-	// Nodename returns the name of the target node.
-	Nodename() string
-
-	// IPv4Addr returns the IPv4 address of the target.
-	IPv4Addr() (net.IP, error)
-
-	// Serial returns the serial device associated with the target for serial i/o.
-	Serial() io.ReadWriteCloser
-
-	// SSHKey returns the private key corresponding an authorized SSH key of the target.
-	SSHKey() string
-
-	// Start starts the target.
-	Start(ctx context.Context, images build.Images, args []string) error
-
-	// Restart restarts the target.
-	Restart(ctx context.Context) error
-
-	// Stop stops the target.
-	Stop(ctx context.Context) error
-
-	// Wait waits for the target to finish running.
-	Wait(ctx context.Context) error
-}
-
-// RunCommand is a Command implementation for booting a device and running a
-// given command locally.
-type RunCommand struct {
-	// ConfigFile is the path to the target configurations.
-	configFile string
-
-	// ImageManifests is a list of paths to image manifests (e.g., images.json)
-	imageManifests command.StringsFlag
-
-	// Netboot tells botanist to netboot (and not to pave).
-	netboot bool
-
-	// ZirconArgs are kernel command-line arguments to pass on boot.
-	zirconArgs command.StringsFlag
-
-	// Timeout is the duration allowed for the command to finish execution.
-	timeout time.Duration
-
-	// CmdStdout is the file to which the command's stdout will be redirected.
-	cmdStdout string
-
-	// CmdStderr is the file to which the command's stderr will be redirected.
-	cmdStderr string
-
-	// SysloggerFile, if nonempty, is the file to where the system's logs will be written.
-	syslogFile string
-
-	// SshKey is the path to a private SSH user key.
-	sshKey string
-
-	// SerialLogFile, if nonempty, is the file where the system's serial logs will be written.
-	serialLogFile string
-}
-
-func (*RunCommand) Name() string {
-	return "run"
-}
-
-func (*RunCommand) Usage() string {
-	return `
-botanist run [flags...] [command...]
-
-flags:
-`
-}
-
-func (*RunCommand) Synopsis() string {
-	return "boots a device and runs a local command"
-}
-
-func (r *RunCommand) SetFlags(f *flag.FlagSet) {
-	f.StringVar(&r.configFile, "config", "", "path to file of device config")
-	f.Var(&r.imageManifests, "images", "paths to image manifests")
-	f.BoolVar(&r.netboot, "netboot", false, "if set, botanist will not pave; but will netboot instead")
-	f.Var(&r.zirconArgs, "zircon-args", "kernel command-line arguments")
-	f.DurationVar(&r.timeout, "timeout", 10*time.Minute, "duration allowed for the command to finish execution.")
-	f.StringVar(&r.cmdStdout, "stdout", "", "file to redirect the command's stdout into; if unspecified, it will be redirected to the process' stdout")
-	f.StringVar(&r.cmdStderr, "stderr", "", "file to redirect the command's stderr into; if unspecified, it will be redirected to the process' stderr")
-	f.StringVar(&r.syslogFile, "syslog", "", "file to write the systems logs to")
-	f.StringVar(&r.sshKey, "ssh", "", "file containing a private SSH user key; if not provided, a private key will be generated.")
-	f.StringVar(&r.serialLogFile, "serial-log", "", "file to write the serial logs to.")
-}
-
-func (r *RunCommand) runCmd(ctx context.Context, args []string, t Target) error {
-	nodename := t.Nodename()
-	ip, err := t.IPv4Addr()
-	if err == nil {
-		logger.Infof(ctx, "IPv4 address of %s found: %s", nodename, ip)
-	} else {
-		logger.Errorf(ctx, "could not resolve IPv4 address of %s: %v", nodename, err)
-	}
-
-	env := append(
-		os.Environ(),
-		fmt.Sprintf("FUCHSIA_NODENAME=%s", nodename),
-		fmt.Sprintf("FUCHSIA_IPV4_ADDR=%v", ip),
-		fmt.Sprintf("FUCHSIA_SSH_KEY=%s", t.SSHKey()),
-	)
-
-	ctx, cancel := context.WithTimeout(ctx, r.timeout)
-	defer cancel()
-
-	stdout := os.Stdout
-	if r.cmdStdout != "" {
-		f, err := os.Create(r.cmdStdout)
-		if err != nil {
-			return err
-		}
-		defer f.Close()
-		stdout = f
-	}
-	stderr := os.Stderr
-	if r.cmdStderr != "" {
-		f, err := os.Create(r.cmdStderr)
-		if err != nil {
-			return err
-		}
-		defer f.Close()
-		stderr = f
-	}
-
-	runner := runner.SubprocessRunner{
-		Env: env,
-	}
-	if err := runner.Run(ctx, args, stdout, stderr); err != nil {
-		if ctx.Err() != nil {
-			return fmt.Errorf("command timed out after %v", r.timeout)
-		}
-		return err
-	}
-	return nil
-}
-
-func getIndexedFilename(filename string, index int) string {
-	ext := filepath.Ext(filename)
-	name := filename[:len(filename)-len(ext)]
-	return fmt.Sprintf("%s-%d%s", name, index, ext)
-}
-
-func (r *RunCommand) execute(ctx context.Context, args []string) error {
-	imgs, err := build.LoadImages(r.imageManifests...)
-	if err != nil {
-		return fmt.Errorf("failed to load images: %v", err)
-	}
-
-	opts := target.Options{
-		Netboot: r.netboot,
-		SSHKey:  r.sshKey,
-	}
-
-	data, err := ioutil.ReadFile(r.configFile)
-	if err != nil {
-		return fmt.Errorf("could not open config file: %v", err)
-	}
-	var objs []json.RawMessage
-	if err := json.Unmarshal(data, &objs); err != nil {
-		return fmt.Errorf("could not unmarshal config file as a JSON list: %v", err)
-	}
-
-	var targets []Target
-	for _, obj := range objs {
-		t, err := DeriveTarget(ctx, obj, opts)
-		if err != nil {
-			return err
-		}
-		targets = append(targets, t)
-	}
-
-	ctx, cancel := context.WithCancel(ctx)
-	defer cancel()
-	errs := make(chan error)
-	var wg sync.WaitGroup
-
-	for i, t := range targets {
-		defer func() {
-			logger.Debugf(ctx, "stopping or rebooting the node %q\n", t.Nodename())
-			if err := t.Stop(ctx); err == target.ErrUnimplemented {
-				t.Restart(ctx)
-			}
-		}()
-
-		var syslogFile, serialLogFile string
-		if r.syslogFile != "" {
-			syslogFile = r.syslogFile
-			if len(targets) > 1 {
-				syslogFile = getIndexedFilename(r.syslogFile, i)
-			}
-		}
-		if r.serialLogFile != "" {
-			serialLogFile = r.serialLogFile
-			if len(targets) > 1 {
-				serialLogFile = getIndexedFilename(r.serialLogFile, i)
-			}
-		}
-
-		wg.Add(1)
-		go func(t Target, syslogFile string, serialLogFile string) {
-			defer wg.Done()
-			var syslog io.Writer
-			if syslogFile != "" {
-				syslog, err := os.Create(syslogFile)
-				if err != nil {
-					errs <- err
-					return
-				}
-				defer syslog.Close()
-			}
-
-			zirconArgs := r.zirconArgs
-			if t.Serial() != nil {
-				if serialLogFile != "" {
-					serialLog, err := os.Create(serialLogFile)
-					if err != nil {
-						errs <- err
-						return
-					}
-					defer serialLog.Close()
-
-					// Here we invoke the `dlog` command over serial to tail the existing log buffer into the
-					// output file.  This should give us everything since Zedboot boot, and new messages should
-					// be written to directly to the serial port without needing to tail with `dlog -f`.
-					if _, err = io.WriteString(t.Serial(), "\ndlog\n"); err != nil {
-						logger.Errorf(ctx, "failed to tail zedboot dlog: %v", err)
-					}
-
-					go func(t Target) {
-						for {
-							_, err := io.Copy(serialLog, t.Serial())
-							if err != nil && err != io.EOF {
-								logger.Errorf(ctx, "failed to write serial log: %v", err)
-								return
-							}
-						}
-					}(t)
-					zirconArgs = append(zirconArgs, "kernel.bypass-debuglog=true")
-				}
-				// Modify the zirconArgs passed to the kernel on boot to enable serial on x64.
-				// arm64 devices should already be enabling kernel.serial at compile time.
-				zirconArgs = append(zirconArgs, "kernel.serial=legacy")
-			}
-
-			if err := t.Start(ctx, imgs, zirconArgs); err != nil {
-				errs <- err
-				return
-			}
-			nodename := t.Nodename()
-			// If having paved, SSH in and stream syslogs back to a file sink.
-			if !r.netboot && syslog != nil {
-				p, err := ioutil.ReadFile(t.SSHKey())
-				if err != nil {
-					errs <- err
-					return
-				}
-				config, err := sshutil.DefaultSSHConfig(p)
-				if err != nil {
-					errs <- err
-					return
-				}
-				client, err := sshutil.ConnectToNode(ctx, nodename, config)
-				if err != nil {
-					errs <- err
-					return
-				}
-				syslogger, err := botanist.NewSyslogger(client)
-				if err != nil {
-					errs <- err
-					return
-				}
-				go func() {
-					syslogger.Stream(ctx, syslog)
-					syslogger.Close()
-				}()
-			}
-		}(t, syslogFile, serialLogFile)
-	}
-	// Wait for all targets to finish starting.
-	wg.Wait()
-	// We can close the channel on the receiver end since we wait for all target goroutines to finish.
-	close(errs)
-	err, ok := <-errs
-	if ok {
-		return err
-	}
-
-	// Since errs was closed, reset it to reuse it again.
-	errs = make(chan error)
-
-	go func() {
-		// Target doesn't matter for multi-device host tests. Just use first one.
-		errs <- r.runCmd(ctx, args, targets[0])
-	}()
-
-	for _, t := range targets {
-		go func(t Target) {
-			if err := t.Wait(ctx); err != nil && err != target.ErrUnimplemented {
-				errs <- err
-			}
-		}(t)
-	}
-
-	select {
-	case err := <-errs:
-		return err
-	case <-ctx.Done():
-	}
-	return nil
-}
-
-func (r *RunCommand) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
-	args := f.Args()
-	if len(args) == 0 {
-		return subcommands.ExitUsageError
-	}
-	if err := r.execute(ctx, args); err != nil {
-		logger.Errorf(ctx, "%v\n", err)
-		return subcommands.ExitFailure
-	}
-	return subcommands.ExitSuccess
-}
-
-func DeriveTarget(ctx context.Context, obj []byte, opts target.Options) (Target, error) {
-	type typed struct {
-		Type string `json:"type"`
-	}
-	var x typed
-
-	if err := json.Unmarshal(obj, &x); err != nil {
-		return nil, fmt.Errorf("object in list has no \"type\" field: %v", err)
-	}
-	switch x.Type {
-	case "qemu":
-		var cfg target.QEMUConfig
-		if err := json.Unmarshal(obj, &cfg); err != nil {
-			return nil, fmt.Errorf("invalid QEMU config found: %v", err)
-		}
-		return target.NewQEMUTarget(cfg, opts), nil
-	case "device":
-		var cfg target.DeviceConfig
-		if err := json.Unmarshal(obj, &cfg); err != nil {
-			return nil, fmt.Errorf("invalid device config found: %v", err)
-		}
-		t, err := target.NewDeviceTarget(ctx, cfg, opts)
-		return t, err
-	default:
-		return nil, fmt.Errorf("unknown type found: %q", x.Type)
-	}
-}
diff --git a/botanist/cmd/zedboot.go b/botanist/cmd/zedboot.go
deleted file mode 100644
index 2a8bcee..0000000
--- a/botanist/cmd/zedboot.go
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2018 The Fuchsia 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 (
-	"context"
-	"flag"
-	"fmt"
-	"io/ioutil"
-	"net"
-	"strings"
-	"time"
-
-	"go.fuchsia.dev/tools/botanist/target"
-	"go.fuchsia.dev/tools/build/api"
-	"go.fuchsia.dev/tools/lib/command"
-	"go.fuchsia.dev/tools/lib/logger"
-	"go.fuchsia.dev/tools/net/netutil"
-	"go.fuchsia.dev/tools/testing/runtests"
-
-	"github.com/google/subcommands"
-)
-
-// ZedbootCommand is a Command implementation for running the testing workflow on a device
-// that boots with Zedboot.
-type ZedbootCommand struct {
-	// ImageManifests is a list of paths to image manifests (e.g., images.json)
-	imageManifests command.StringsFlag
-
-	// Netboot tells botanist to netboot (and not to pave).
-	netboot bool
-
-	// ConfigFile is the path to a file containing the target config.
-	configFile string
-
-	// TestResultsDir is the directory on target to where test results will be written.
-	testResultsDir string
-
-	// SummaryFilename is the name of the test summary JSON file to be written to
-	// testResultsDir.
-	summaryFilename string
-
-	// FilePollInterval is the duration waited between checking for test summary file
-	// on the target to be written.
-	filePollInterval time.Duration
-
-	// OutputArchive is a path on host to where the tarball containing the test results
-	// will be output.
-	outputArchive string
-
-	// CmdlineFile is the path to a file of additional kernel command-line arguments.
-	cmdlineFile string
-}
-
-func (*ZedbootCommand) Name() string {
-	return "zedboot"
-}
-
-func (*ZedbootCommand) Usage() string {
-	return "zedboot [flags...] [kernel command-line arguments...]\n\nflags:\n"
-}
-
-func (*ZedbootCommand) Synopsis() string {
-	return "boots a Zedboot device and collects test results"
-}
-
-func (cmd *ZedbootCommand) SetFlags(f *flag.FlagSet) {
-	f.Var(&cmd.imageManifests, "images", "paths to image manifests")
-	f.BoolVar(&cmd.netboot, "netboot", false, "if set, botanist will not pave; but will netboot instead")
-	f.StringVar(&cmd.testResultsDir, "results-dir", "/test", "path on target to where test results will be written")
-	f.StringVar(&cmd.outputArchive, "out", "output.tar", "path on host to output tarball of test results")
-	f.StringVar(&cmd.summaryFilename, "summary-name", runtests.TestSummaryFilename, "name of the file in the test directory")
-	f.DurationVar(&cmd.filePollInterval, "poll-interval", 1*time.Minute, "time between checking for summary.json on the target")
-	f.StringVar(&cmd.configFile, "config", "", "path to file of device config")
-	f.StringVar(&cmd.cmdlineFile, "cmdline-file", "", "path to a file containing additional kernel command-line arguments")
-}
-
-func (cmd *ZedbootCommand) runTests(ctx context.Context, imgs build.Images, addr *net.UDPAddr, cmdlineArgs []string) error {
-	logger.Debugf(ctx, "waiting for %q\n", cmd.summaryFilename)
-	return runtests.PollForSummary(ctx, addr, cmd.summaryFilename, cmd.testResultsDir, cmd.outputArchive, cmd.filePollInterval)
-}
-
-func (cmd *ZedbootCommand) execute(ctx context.Context, cmdlineArgs []string) error {
-	configs, err := target.LoadDeviceConfigs(cmd.configFile)
-
-	if err != nil {
-		return fmt.Errorf("failed to load target config file %q", cmd.configFile)
-	}
-	opts := target.Options{
-		Netboot: cmd.netboot,
-	}
-
-	var devices []*target.DeviceTarget
-	for _, config := range configs {
-		device, err := target.NewDeviceTarget(ctx, config, opts)
-		if err != nil {
-			return err
-		}
-		devices = append(devices, device)
-	}
-
-	for _, device := range devices {
-		defer device.Restart(ctx)
-	}
-
-	imgs, err := build.LoadImages(cmd.imageManifests...)
-	if err != nil {
-		return err
-	}
-
-	ctx, cancel := context.WithCancel(ctx)
-	defer cancel()
-	errs := make(chan error)
-
-	for _, device := range devices {
-		go func(device *target.DeviceTarget) {
-			if err := device.Start(ctx, imgs, cmdlineArgs); err != nil {
-				errs <- err
-			}
-		}(device)
-	}
-	go func() {
-		addr, err := netutil.GetNodeAddress(ctx, devices[0].Nodename(), false)
-		if err != nil {
-			errs <- err
-			return
-		}
-		errs <- cmd.runTests(ctx, imgs, addr, cmdlineArgs)
-	}()
-
-	select {
-	case err := <-errs:
-		return err
-	case <-ctx.Done():
-	}
-
-	return nil
-}
-
-func (cmd *ZedbootCommand) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
-	configFlag := f.Lookup("config")
-	logger.Debugf(ctx, "config flag: %v\n", configFlag.Value)
-
-	// Aggregate command-line arguments.
-	cmdlineArgs := f.Args()
-	if cmd.cmdlineFile != "" {
-		args, err := ioutil.ReadFile(cmd.cmdlineFile)
-		if err != nil {
-			logger.Errorf(ctx, "failed to read command-line args file %q: %v\n", cmd.cmdlineFile, err)
-			return subcommands.ExitFailure
-		}
-		cmdlineArgs = append(cmdlineArgs, strings.Split(string(args), "\n")...)
-	}
-
-	if err := cmd.execute(ctx, cmdlineArgs); err != nil {
-		logger.Errorf(ctx, "%v\n", err)
-		return subcommands.ExitFailure
-	}
-
-	return subcommands.ExitSuccess
-}
diff --git a/botanist/fileutil.go b/botanist/fileutil.go
deleted file mode 100644
index 4950d4c..0000000
--- a/botanist/fileutil.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2018 The Fuchsia 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 botanist
-
-import (
-	"archive/tar"
-	"fmt"
-	"net"
-
-	"go.fuchsia.dev/tools/net/tftp"
-)
-
-// FetchAndArchiveFile fetches a remote file via TFTP from a given node, and
-// writes it an archive.
-func FetchAndArchiveFile(t *tftp.Client, addr *net.UDPAddr, tw *tar.Writer, path, name string) error {
-	receiver, err := t.Receive(addr, path)
-	if err != nil {
-		return fmt.Errorf("failed to receive file %s: %v\n", path, err)
-	}
-	hdr := &tar.Header{
-		Name: name,
-		Size: receiver.(tftp.Session).Size(),
-		Mode: 0666,
-	}
-	if err := tw.WriteHeader(hdr); err != nil {
-		return err
-	}
-	_, err = receiver.WriteTo(tw)
-	return err
-}
diff --git a/botanist/ip.go b/botanist/ip.go
deleted file mode 100644
index 30fcd46..0000000
--- a/botanist/ip.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2019 The Fuchsia 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 botanist
-
-import (
-	"context"
-	"fmt"
-	"net"
-	"time"
-
-	"go.fuchsia.dev/tools/lib/logger"
-	"go.fuchsia.dev/tools/lib/retry"
-	"go.fuchsia.dev/tools/net/mdns"
-)
-
-// Interval at which ResolveIP will wait for a response to a question packet.
-const mDNSTimeout time.Duration = 2 * time.Second
-
-func getLocalDomain(nodename string) string {
-	return nodename + ".local"
-}
-
-// ResolveIP returns the IPv4 address of a fuchsia node via mDNS.
-//
-// TODO(joshuaseaton): Refactor dev_finder to share 'resolve' logic with botanist.
-func ResolveIPv4(ctx context.Context, nodename string, timeout time.Duration) (net.IP, error) {
-	m := mdns.NewMDNS()
-	m.EnableIPv4()
-	out := make(chan net.IP)
-	domain := getLocalDomain(nodename)
-	m.AddHandler(func(iface net.Interface, addr net.Addr, packet mdns.Packet) {
-		for _, a := range packet.Answers {
-			if a.Class == mdns.IN && a.Type == mdns.A && a.Domain == domain {
-				out <- net.IP(a.Data)
-				return
-			}
-		}
-	})
-	m.AddWarningHandler(func(addr net.Addr, err error) {
-		logger.Infof(ctx, "from: %v; warn: %v", addr, err)
-	})
-	errs := make(chan error)
-	m.AddErrorHandler(func(err error) {
-		errs <- err
-	})
-
-	ctx, cancel := context.WithTimeout(ctx, timeout)
-	defer cancel()
-
-	if err := m.Start(ctx, mdns.DefaultPort); err != nil {
-		return nil, fmt.Errorf("could not start mDNS client: %v", err)
-	}
-
-	// Send question packets to the mDNS server at intervals of mDNSTimeout for a total of
-	// |timeout|; retry, as it takes time for the netstack and server to be brought up.
-	var ip net.IP
-	var err error
-	err = retry.Retry(ctx, &retry.ZeroBackoff{}, func() error {
-		m.Send(mdns.QuestionPacket(domain))
-		ctx, cancel := context.WithTimeout(context.Background(), mDNSTimeout)
-		defer cancel()
-
-		select {
-		case <-ctx.Done():
-			return fmt.Errorf("timeout")
-		case err = <-errs:
-			return err
-		case ip = <-out:
-			return nil
-		}
-	}, nil)
-
-	return ip, err
-}
diff --git a/botanist/power/amt/amt.go b/botanist/power/amt/amt.go
deleted file mode 100644
index fb20b5e..0000000
--- a/botanist/power/amt/amt.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2018 The Fuchsia 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 amt
-
-import (
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"net/url"
-	"strings"
-
-	"github.com/google/uuid"
-	"go.fuchsia.dev/tools/net/digest"
-)
-
-const (
-	// https://software.intel.com/en-us/node/645995
-	PowerStateOn             = 2
-	PowerStateLightSleep     = 3
-	PowerStateDeepSleep      = 4
-	PowerStatePowerCycleSoft = 5
-	PowerStateOffHard        = 6
-	PowerStateHibernate      = 7
-	PowerStateOffSoft        = 8
-	PowerStatePowerCycleHard = 9
-	PowerStateMasterBusReset = 10
-)
-
-// Printf string with placeholders for destination uri, message uuid
-const payloadTmpl = `
-<?xml version="1.0" encoding="UTF-8"?>
-<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsman="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:pms="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_PowerManagementService">
-<s:Header>
-  <wsa:Action s:mustUnderstand="true">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_PowerManagementService/RequestPowerStateChange</wsa:Action>
-  <wsa:To s:mustUnderstand="true">%s</wsa:To>
-  <wsman:ResourceURI s:mustUnderstand="true">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_PowerManagementService</wsman:ResourceURI>
-  <wsa:MessageID s:mustUnderstand="true">uuid:%s</wsa:MessageID>
-  <wsa:ReplyTo><wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address></wsa:ReplyTo>
-  <wsman:SelectorSet>
-    <wsman:Selector Name="Name">Intel(r) AMT Power Management Service</wsman:Selector>
-    <wsman:Selector Name="SystemName">Intel(r) AMT</wsman:Selector>
-    <wsman:Selector Name="CreationClassName">CIM_PowerManagementService</wsman:Selector>
-    <wsman:Selector Name="SystemCreationClassName">CIM_ComputerSystem</wsman:Selector>
-  </wsman:SelectorSet>
-</s:Header>
-<s:Body>
-  <pms:RequestPowerStateChange_INPUT>
-    <pms:PowerState>%d</pms:PowerState>
-    <pms:ManagedElement>
-      <wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
-      <wsa:ReferenceParameters>
-        <wsman:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ComputerSystem</wsman:ResourceURI>
-        <wsman:SelectorSet>
-          <wsman:Selector Name="Name">ManagedSystem</wsman:Selector>
-          <wsman:Selector Name="CreationClassName">CIM_ComputerSystem</wsman:Selector>
-        </wsman:SelectorSet>
-      </wsa:ReferenceParameters>
-    </pms:ManagedElement>
-  </pms:RequestPowerStateChange_INPUT>
-</s:Body>
-</s:Envelope>
-`
-
-// Reboot sends a Master Bus Reset to an AMT compatible device at host:port.
-func Reboot(host, username, password string) error {
-	// AMT over http always uses port 16992
-	uri, err := url.Parse(fmt.Sprintf("http://%s:16992/wsman", host))
-	if err != nil {
-		return err
-	}
-	// Generate MessageID
-	uuid := uuid.New()
-	payload := fmt.Sprintf(payloadTmpl, uri.String(), uuid, PowerStatePowerCycleSoft)
-
-	t := digest.NewTransport(username, password)
-	req, err := http.NewRequest("POST", uri.String(), strings.NewReader(payload))
-	if err != nil {
-		return err
-	}
-	res, err := t.RoundTrip(req)
-	if err != nil {
-		return err
-	}
-	defer res.Body.Close()
-
-	body, err := ioutil.ReadAll(res.Body)
-	if err != nil {
-		return err
-	}
-	returnValue := string(strings.Split(string(body), "ReturnValue>")[1][0])
-	if returnValue != "0" {
-		return fmt.Errorf("amt reboot ReturnValue=%s", returnValue)
-	}
-
-	return nil
-}
diff --git a/botanist/power/power.go b/botanist/power/power.go
deleted file mode 100644
index a8aa3bc..0000000
--- a/botanist/power/power.go
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2018 The Fuchsia 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 power
-
-import (
-	"context"
-	"io"
-
-	"go.fuchsia.dev/tools/botanist/power/amt"
-	"go.fuchsia.dev/tools/botanist/power/wol"
-	"go.fuchsia.dev/tools/lib/logger"
-	"go.fuchsia.dev/tools/net/sshutil"
-
-	"golang.org/x/crypto/ssh"
-)
-
-// TODO(IN-977) Clean this up per suggestions in go/fxr/251550
-
-const (
-	// Controller machines use 192.168.42.1/24 for swarming bots
-	// This will broadcast to that entire subnet.
-	botBroadcastAddr = "192.168.42.255:9"
-
-	// Controller machines have multiple interfaces, currently
-	// 'eno2' is used for swarming bots.
-	botInterface = "eno2"
-)
-
-// Client represents a power management configuration for a particular device.
-type Client struct {
-	// Type is the type of manager to use.
-	Type string `json:"type"`
-
-	// Host is the network hostname of the manager, e.g. fuchsia-tests-pdu-001.
-	Host string `json:"host"`
-
-	// HostHwAddr is the ethernet MAC address of the manager,  e.g. 10:10:10:10:10:10
-	HostMACAddr string `json:"host_mac_addr"`
-
-	// Username is the username used to log in to the manager.
-	Username string `json:"username"`
-
-	// Password is the password used to log in to the manager..
-	Password string `json:"password"`
-}
-
-type Rebooter interface {
-	reboot() error
-}
-
-type SshRebooter struct {
-	nodename string
-	signers  []ssh.Signer
-}
-
-type SerialRebooter struct {
-	serial io.ReadWriter
-}
-
-// RebootDevice attempts to reboot the specified device into recovery, and
-// additionally uses the given configuration to reboot the device if specified.
-func (c Client) RebootDevice(signers []ssh.Signer, nodename string, serial io.ReadWriter) error {
-	var rebooter Rebooter
-	if serial != nil {
-		rebooter = NewSerialRebooter(serial)
-	} else {
-		rebooter = NewSSHRebooter(nodename, signers)
-	}
-	// Always attempt to soft reboot the device to recovery.
-	err := rebooter.reboot()
-	if err != nil {
-		logger.Warningf(context.Background(), "soft reboot failed: %v", err)
-	}
-
-	// Hard reboot the device if specified in the config.
-	switch c.Type {
-	case "amt":
-		return amt.Reboot(c.Host, c.Username, c.Password)
-	case "wol":
-		return wol.Reboot(botBroadcastAddr, botInterface, c.HostMACAddr)
-	default:
-		return err
-	}
-}
-
-func NewSerialRebooter(serial io.ReadWriter) *SerialRebooter {
-	return &SerialRebooter{
-		serial: serial,
-	}
-}
-
-func NewSSHRebooter(nodename string, signers []ssh.Signer) *SshRebooter {
-	return &SshRebooter{
-		nodename: nodename,
-		signers:  signers,
-	}
-}
-
-func (s *SerialRebooter) reboot() error {
-	_, err := io.WriteString(s.serial, "\ndm reboot-recovery\n")
-	return err
-}
-
-func (s *SshRebooter) reboot() error {
-	config, err := sshutil.DefaultSSHConfigFromSigners(s.signers...)
-	if err != nil {
-		return err
-	}
-
-	ctx := context.Background()
-	client, err := sshutil.ConnectToNode(ctx, s.nodename, config)
-	if err != nil {
-		return err
-	}
-
-	defer client.Close()
-
-	session, err := client.NewSession()
-	if err != nil {
-		return err
-	}
-
-	defer session.Close()
-
-	// Invoke `dm reboot-recovery` with a 2 second delay in the background, then exit the SSH shell.
-	// This prevents the SSH connection from hanging waiting for `dm reboot-recovery` to return.
-	err = session.Start("{ sleep 2; dm reboot-recovery; } >/dev/null & exit")
-	if err != nil {
-		return err
-	}
-
-	done := make(chan error)
-	go func() {
-		done <- session.Wait()
-	}()
-
-	select {
-	case err := <-done:
-		return err
-	}
-}
diff --git a/botanist/power/wol/wol.go b/botanist/power/wol/wol.go
deleted file mode 100644
index f05d503..0000000
--- a/botanist/power/wol/wol.go
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2018 The Fuchsia 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 wol
-
-import (
-	"errors"
-	"fmt"
-	"net"
-	"regexp"
-	"time"
-)
-
-var (
-	macAddrRegex = regexp.MustCompile(`(?i)^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$`)
-	// Magic Packet header is 0xFF repeated 6 times.
-	magicPacketHeader = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
-)
-
-const (
-	magicPacketLength = 102
-)
-
-// Reboot sends a WakeOnLAN magic packet {magicPacketHeader + macAddr x 16}
-// using the specified network interface to the broadcast address
-func Reboot(broadcastAddr, interfaceName, macAddr string) error {
-	if !macAddrRegex.Match([]byte(macAddr)) {
-		return fmt.Errorf("Invalid MAC: %s", macAddr)
-	}
-
-	remoteHwAddr, err := net.ParseMAC(macAddr)
-	if err != nil {
-		return err
-	}
-
-	localAddr, err := getUDPAddrFromIFace(interfaceName)
-	if err != nil {
-		return err
-	}
-	remoteAddr, err := net.ResolveUDPAddr("udp", broadcastAddr)
-	if err != nil {
-		return err
-	}
-
-	return sendMagicPacket(localAddr, remoteAddr, remoteHwAddr)
-}
-
-func getUDPAddrFromIFace(ifaceName string) (*net.UDPAddr, error) {
-	iface, err := net.InterfaceByName(ifaceName)
-	if err != nil {
-		return nil, err
-	}
-
-	addrs, err := iface.Addrs()
-	if err != nil {
-		return nil, err
-	}
-
-	for _, addr := range addrs {
-		if ipAddr, ok := addr.(*net.IPNet); ok {
-			// Need an IPv4, non-loopback address to send on
-			if !ipAddr.IP.IsLoopback() && ipAddr.IP.To4() != nil {
-				return &net.UDPAddr{
-					IP: ipAddr.IP,
-				}, nil
-			}
-		}
-	}
-
-	return nil, errors.New("No UDPAddr found on interface")
-}
-
-func sendMagicPacket(localAddr, remoteAddr *net.UDPAddr, remoteHwAddr net.HardwareAddr) error {
-	packet := magicPacketHeader
-	for i := 0; i < 16; i++ {
-		packet = append(packet, remoteHwAddr...)
-	}
-
-	if len(packet) != magicPacketLength {
-		return fmt.Errorf("Wake-On-LAN packet incorrect length: %d", len(packet))
-	}
-
-	conn, err := net.DialUDP("udp", localAddr, remoteAddr)
-	if err != nil {
-		return err
-	}
-	defer conn.Close()
-
-	// Attempt to send the Magic Packet TEN times in a row.  The UDP packet sometimes
-	// does not make it to the DUT and this is the simplest way to increase the chance
-	// the device reboots.
-	for i := 0; i < 10; i++ {
-		n, err := conn.Write(packet)
-
-		if n != magicPacketLength {
-			return errors.New("Failed to send correct Wake-On-LAN packet length")
-		}
-
-		if err != nil {
-			return err
-		}
-		time.Sleep(1 * time.Second)
-	}
-
-	return nil
-}
diff --git a/botanist/syslog.go b/botanist/syslog.go
deleted file mode 100644
index 35916fe..0000000
--- a/botanist/syslog.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2019 The Fuchsia 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 botanist
-
-import (
-	"context"
-	"io"
-
-	"golang.org/x/crypto/ssh"
-
-	"go.fuchsia.dev/tools/lib/runner"
-)
-
-// The program on fuchsia used to stream system logs through a shell, not to be confused
-// with the zircon host tool "loglistener" (no underscore) used to zircon-level logs to host.
-const logListener = "bin/log_listener"
-
-// Syslogger represents an session with a Fuchsia instance through which system logs may be streamed.
-type Syslogger struct {
-	r *runner.SSHRunner
-}
-
-// NewSyslogger creates a new Syslogger, given an SSH session with a Fuchsia instance.
-func NewSyslogger(client *ssh.Client) (*Syslogger, error) {
-	session, err := client.NewSession()
-	if err != nil {
-		return nil, err
-	}
-	return &Syslogger{r: &runner.SSHRunner{Session: session}}, nil
-}
-
-// Stream writes system logs to a given writer; it blocks until the stream is
-// is terminated or a Done is signaled.
-func (s *Syslogger) Stream(ctx context.Context, output io.Writer) error {
-	// Note: Fuchsia's log_listener does not write to stderr.
-	return s.r.Run(ctx, []string{logListener}, output, nil)
-}
-
-// Close tidies up the system logging session with the corresponding fuchsia instance.
-func (s *Syslogger) Close() error {
-	s.r.Session.Signal(ssh.SIGKILL)
-	return s.r.Session.Close()
-}
diff --git a/botanist/target/device.go b/botanist/target/device.go
deleted file mode 100644
index 58a71d2..0000000
--- a/botanist/target/device.go
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright 2019 The Fuchsia 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 target
-
-import (
-	"context"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"net"
-	"time"
-
-	"go.fuchsia.dev/tools/botanist"
-	"go.fuchsia.dev/tools/botanist/power"
-	"go.fuchsia.dev/tools/build/api"
-	"go.fuchsia.dev/tools/lib/logger"
-	"go.fuchsia.dev/tools/net/netboot"
-	"go.fuchsia.dev/tools/net/netutil"
-	"go.fuchsia.dev/tools/net/serial"
-
-	"golang.org/x/crypto/ssh"
-)
-
-const (
-	// The duration we allow for the netstack to come up when booting.
-	netstackTimeout = 90 * time.Second
-)
-
-// DeviceConfig contains the static properties of a target device.
-type DeviceConfig struct {
-	// Network is the network properties of the target.
-	Network NetworkProperties `json:"network"`
-
-	// Power is the attached power management configuration.
-	Power *power.Client `json:"power,omitempty"`
-
-	// SSHKeys are the default system keys to be used with the device.
-	SSHKeys []string `json:"keys,omitempty"`
-
-	// Serial is the path to the device file for serial i/o.
-	Serial string `json:"serial,omitempty"`
-}
-
-// NetworkProperties are the static network properties of a target.
-type NetworkProperties struct {
-	// Nodename is the hostname of the device that we want to boot on.
-	Nodename string `json:"nodename"`
-
-	// IPv4Addr is the IPv4 address, if statically given. If not provided, it may be
-	// resolved via the netstack's MDNS server.
-	IPv4Addr string `json:"ipv4"`
-}
-
-// LoadDeviceConfigs unmarshalls a slice of device configs from a given file.
-func LoadDeviceConfigs(path string) ([]DeviceConfig, error) {
-	data, err := ioutil.ReadFile(path)
-	if err != nil {
-		return nil, fmt.Errorf("failed to read device properties file %q", path)
-	}
-
-	var configs []DeviceConfig
-	if err := json.Unmarshal(data, &configs); err != nil {
-		return nil, fmt.Errorf("failed to unmarshal configs: %v", err)
-	}
-	return configs, nil
-}
-
-// DeviceTarget represents a target device.
-type DeviceTarget struct {
-	config  DeviceConfig
-	opts    Options
-	signers []ssh.Signer
-	serial  io.ReadWriteCloser
-}
-
-// NewDeviceTarget returns a new device target with a given configuration.
-func NewDeviceTarget(ctx context.Context, config DeviceConfig, opts Options) (*DeviceTarget, error) {
-	// If an SSH key is specified in the options, prepend it the configs list so that it
-	// corresponds to the authorized key that would be paved.
-	if opts.SSHKey != "" {
-		config.SSHKeys = append([]string{opts.SSHKey}, config.SSHKeys...)
-	}
-	signers, err := parseOutSigners(config.SSHKeys)
-	if err != nil {
-		return nil, fmt.Errorf("could not parse out signers from private keys: %v", err)
-	}
-	var s io.ReadWriteCloser
-	if config.Serial != "" {
-		s, err = serial.Open(config.Serial)
-		if err != nil {
-			// TODO(IN-????): This should be returned as an error, but we don't want to fail any
-			// test runs for misconfigured serial until it is actually required to complete certain
-			// tasks.
-			logger.Errorf(ctx, "unable to open %s: %v", config.Serial, err)
-		}
-	}
-	return &DeviceTarget{
-		config:  config,
-		opts:    opts,
-		signers: signers,
-		serial:  s,
-	}, nil
-}
-
-// Nodename returns the name of the node.
-func (t *DeviceTarget) Nodename() string {
-	return t.config.Network.Nodename
-}
-
-// IPv4Addr returns the IPv4 address of the node. If not provided in the config, then it
-// will be resolved against the target-side MDNS server.
-func (t *DeviceTarget) IPv4Addr() (net.IP, error) {
-	if t.config.Network.IPv4Addr != "" {
-		return net.ParseIP(t.config.Network.IPv4Addr), nil
-	}
-	return botanist.ResolveIPv4(context.Background(), t.Nodename(), netstackTimeout)
-}
-
-// Serial returns the serial device associated with the target for serial i/o.
-func (t *DeviceTarget) Serial() io.ReadWriteCloser {
-	return t.serial
-}
-
-// SSHKey returns the private SSH key path associated with the authorized key to be paved.
-func (t *DeviceTarget) SSHKey() string {
-	return t.config.SSHKeys[0]
-}
-
-// Start starts the device target.
-func (t *DeviceTarget) Start(ctx context.Context, images build.Images, args []string) error {
-	// Set up log listener and dump kernel output to stdout.
-	l, err := netboot.NewLogListener(t.Nodename())
-	if err != nil {
-		return fmt.Errorf("cannot listen: %v", err)
-	}
-	go func() {
-		defer l.Close()
-		for {
-			data, err := l.Listen()
-			if err != nil {
-				continue
-			}
-			fmt.Print(data)
-			select {
-			case <-ctx.Done():
-				return
-			default:
-			}
-		}
-	}()
-
-	addr, err := netutil.GetNodeAddress(ctx, t.Nodename(), false)
-	if err != nil {
-		return err
-	}
-
-	// Mexec Zedboot
-	err = botanist.BootZedbootShim(ctx, addr, images)
-	if err != nil {
-		return err
-	}
-
-	// Boot Fuchsia.
-	var bootMode int
-	if t.opts.Netboot {
-		bootMode = botanist.ModeNetboot
-	} else {
-		bootMode = botanist.ModePave
-	}
-	return botanist.Boot(ctx, addr, bootMode, images, args, t.signers)
-}
-
-// Restart restarts the target.
-func (t *DeviceTarget) Restart(ctx context.Context) error {
-	if t.serial != nil {
-		defer t.serial.Close()
-	}
-	if t.config.Power != nil {
-		if err := t.config.Power.RebootDevice(t.signers, t.Nodename(), t.serial); err != nil {
-			return fmt.Errorf("failed to reboot the device: %v", err)
-		}
-	}
-	return nil
-}
-
-// Stop stops the device.
-func (t *DeviceTarget) Stop(ctx context.Context) error {
-	return ErrUnimplemented
-}
-
-// Wait waits for the device target to stop.
-func (t *DeviceTarget) Wait(ctx context.Context) error {
-	return ErrUnimplemented
-}
-
-func parseOutSigners(keyPaths []string) ([]ssh.Signer, error) {
-	if len(keyPaths) == 0 {
-		return nil, errors.New("must supply SSH keys in the config")
-	}
-	var keys [][]byte
-	for _, keyPath := range keyPaths {
-		p, err := ioutil.ReadFile(keyPath)
-		if err != nil {
-			return nil, fmt.Errorf("could not read SSH key file %q: %v", keyPath, err)
-		}
-		keys = append(keys, p)
-	}
-
-	var signers []ssh.Signer
-	for _, p := range keys {
-		signer, err := ssh.ParsePrivateKey(p)
-		if err != nil {
-			return nil, err
-		}
-		signers = append(signers, signer)
-	}
-	return signers, nil
-}
diff --git a/botanist/target/device_test.go b/botanist/target/device_test.go
deleted file mode 100644
index 30687ab..0000000
--- a/botanist/target/device_test.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2019 The Fuchsia 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 target
-
-import (
-	"io/ioutil"
-	"os"
-	"testing"
-)
-
-func TestLoadConfigs(t *testing.T) {
-	tests := []struct {
-		name        string
-		jsonStr     string
-		expectedLen int
-		expectErr   bool
-	}{
-		// Valid configs.
-		{"ValidConfig", `[{"nodename":"upper-drank-wick-creek"},{"nodename":"siren-swoop-wick-hasty"}]`, 2, false},
-		// Invalid configs.
-		{"InvalidConfig", `{{"nodename":"upper-drank-wick-creek"},{"nodename":"siren-swoop-wick-hasty"}}`, 0, true},
-	}
-	for _, test := range tests {
-		tmpfile, err := ioutil.TempFile(os.TempDir(), "common_test")
-		if err != nil {
-			t.Fatalf("Failed to create test device properties file: %s", err)
-		}
-		defer os.Remove(tmpfile.Name())
-
-		content := []byte(test.jsonStr)
-		if _, err := tmpfile.Write(content); err != nil {
-			t.Fatalf("Failed to write to test device properties file: %s", err)
-		}
-
-		configs, err := LoadDeviceConfigs(tmpfile.Name())
-
-		if test.expectErr && err == nil {
-			t.Errorf("Test%v: Exepected errors; no errors found", test.name)
-		}
-
-		if !test.expectErr && err != nil {
-			t.Errorf("Test%v: Exepected no errors; found error - %v", test.name, err)
-		}
-
-		if len(configs) != test.expectedLen {
-			t.Errorf("Test%v: Expected %d nodes; found %d", test.name, test.expectedLen, len(configs))
-		}
-
-		if err := tmpfile.Close(); err != nil {
-			t.Fatal(err)
-		}
-	}
-}
diff --git a/botanist/target/errors.go b/botanist/target/errors.go
deleted file mode 100644
index bdb49f7..0000000
--- a/botanist/target/errors.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2019 The Fuchsia 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 target
-
-import (
-	"errors"
-)
-
-var (
-	// ErrUnimplemented is an error for unimplemented methods.
-	ErrUnimplemented error = errors.New("method unimplemented")
-)
diff --git a/botanist/target/options.go b/botanist/target/options.go
deleted file mode 100644
index 8440c0d..0000000
--- a/botanist/target/options.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2019 The Fuchsia 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 target
-
-// Options represents lifecycle options for a target. The options will not necessarily make
-// sense for all target types.
-type Options struct {
-	// Netboot gives whether to netboot or pave. Netboot here is being used in the
-	// colloquial sense of only sending netsvc a kernel to mexec. If false, the target
-	// will be paved. Ignored for QEMUTarget.
-	Netboot bool
-
-	// SSHKey is a private SSH key file, corresponding to an authorized key to be paved or
-	// to one baked into a boot image.
-	SSHKey string
-}
diff --git a/botanist/target/qemu.go b/botanist/target/qemu.go
deleted file mode 100644
index 9a650df..0000000
--- a/botanist/target/qemu.go
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright 2019 The Fuchsia 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 target
-
-import (
-	"context"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"log"
-	"net"
-	"os"
-	"os/exec"
-	"path/filepath"
-
-	"go.fuchsia.dev/tools/build/api"
-	"go.fuchsia.dev/tools/qemu"
-)
-
-const (
-	// qemuSystemPrefix is the prefix of the QEMU binary name, which is of the
-	// form qemu-system-<QEMU arch suffix>.
-	qemuSystemPrefix = "qemu-system"
-
-	// DefaultInterfaceName is the name given to the emulated tap interface.
-	defaultInterfaceName = "qemu"
-
-	// DefaultMACAddr is the default MAC address given to a QEMU target.
-	defaultMACAddr = "52:54:00:63:5e:7a"
-
-	// DefaultNodename is the default nodename given to an target with the default QEMU MAC address.
-	defaultNodename = "step-atom-yard-juicy"
-)
-
-// qemuTargetMapping maps the Fuchsia target name to the name recognized by QEMU.
-var qemuTargetMapping = map[string]string{
-	"x64":   qemu.TargetX86_64,
-	"arm64": qemu.TargetAArch64,
-}
-
-// MinFS is the configuration for the MinFS filesystem image.
-type MinFS struct {
-	// Image is the path to the filesystem image.
-	Image string `json:"image"`
-
-	// PCIAddress is the PCI address to map the device at.
-	PCIAddress string `json:"pci_address"`
-}
-
-// QEMUConfig is a QEMU configuration.
-type QEMUConfig struct {
-	// Path is a path to a directory that contains QEMU system binary.
-	Path string `json:"path"`
-
-	// Target is the QEMU target to emulate.
-	Target string `json:"target"`
-
-	// CPU is the number of processors to emulate.
-	CPU int `json:"cpu"`
-
-	// Memory is the amount of memory (in MB) to provide.
-	Memory int `json:"memory"`
-
-	// KVM specifies whether to enable hardware virtualization acceleration.
-	KVM bool `json:"kvm"`
-
-	// Whether User networking is enabled; if false, a Tap interface will be used.
-	UserNetworking bool `json:"user_networking"`
-
-	// MinFS is the filesystem to mount as a device.
-	MinFS *MinFS `json:"minfs,omitempty"`
-}
-
-// QEMUTarget is a QEMU target.
-type QEMUTarget struct {
-	config QEMUConfig
-	opts   Options
-
-	c chan error
-
-	cmd    *exec.Cmd
-	status error
-}
-
-// NewQEMUTarget returns a new QEMU target with a given configuration.
-func NewQEMUTarget(config QEMUConfig, opts Options) *QEMUTarget {
-	return &QEMUTarget{
-		config: config,
-		opts:   opts,
-		c:      make(chan error),
-	}
-}
-
-// Nodename returns the name of the target node.
-func (t *QEMUTarget) Nodename() string {
-	return defaultNodename
-}
-
-// IPv4Addr returns a nil address, as DHCP is not currently configured.
-func (t *QEMUTarget) IPv4Addr() (net.IP, error) {
-	return nil, nil
-}
-
-// Serial returns the serial device associated with the target for serial i/o.
-func (t *QEMUTarget) Serial() io.ReadWriteCloser {
-	return nil
-}
-
-// SSHKey returns the private SSH key path associated with the authorized key to be pavet.
-func (t *QEMUTarget) SSHKey() string {
-	return t.opts.SSHKey
-}
-
-// Start starts the QEMU target.
-func (t *QEMUTarget) Start(ctx context.Context, images build.Images, args []string) error {
-	qemuTarget, ok := qemuTargetMapping[t.config.Target]
-	if !ok {
-		return fmt.Errorf("invalid target %q", t.config.Target)
-	}
-
-	if t.config.Path == "" {
-		return fmt.Errorf("directory must be set")
-	}
-	qemuSystem := filepath.Join(t.config.Path, fmt.Sprintf("%s-%s", qemuSystemPrefix, qemuTarget))
-	if _, err := os.Stat(qemuSystem); err != nil {
-		return fmt.Errorf("could not find qemu-system binary %q: %v", qemuSystem, err)
-	}
-
-	qemuKernel := images.Get("qemu-kernel")
-	if qemuKernel == nil {
-		return fmt.Errorf("could not find qemu-kernel")
-	}
-	zirconA := images.Get("zircon-a")
-	if zirconA == nil {
-		return fmt.Errorf("could not find zircon-a")
-	}
-
-	var drives []qemu.Drive
-	if storageFull := images.Get("storage-full"); storageFull != nil {
-		drives = append(drives, qemu.Drive{
-			ID:   "maindisk",
-			File: storageFull.Path,
-		})
-	}
-	if t.config.MinFS != nil {
-		if _, err := os.Stat(t.config.MinFS.Image); err != nil {
-			return fmt.Errorf("could not find minfs image %q: %v", t.config.MinFS.Image, err)
-		}
-		file, err := filepath.Abs(t.config.MinFS.Image)
-		if err != nil {
-			return err
-		}
-		// Swarming hard-links Isolate downloads with a cache and the very same
-		// cached minfs image will be used across multiple tasks. To ensure
-		// that it remains blank, we must break its link.
-		if err := overwriteFileWithCopy(file); err != nil {
-			return err
-		}
-		drives = append(drives, qemu.Drive{
-			ID:   "testdisk",
-			File: file,
-			Addr: t.config.MinFS.PCIAddress,
-		})
-	}
-
-	netdev := qemu.Netdev{
-		ID:  "net0",
-		MAC: defaultMACAddr,
-	}
-	if t.config.UserNetworking {
-		netdev.User = &qemu.NetdevUser{}
-	} else {
-		netdev.Tap = &qemu.NetdevTap{
-			Name: defaultInterfaceName,
-		}
-	}
-	networks := []qemu.Netdev{netdev}
-
-	config := qemu.Config{
-		Binary:   qemuSystem,
-		Target:   qemuTarget,
-		CPU:      t.config.CPU,
-		Memory:   t.config.Memory,
-		KVM:      t.config.KVM,
-		Kernel:   qemuKernel.Path,
-		Initrd:   zirconA.Path,
-		Drives:   drives,
-		Networks: networks,
-	}
-
-	// The system will halt on a kernel panic instead of rebooting.
-	args = append(args, "kernel.halt-on-panic=true")
-	// Print a message if `dm poweroff` times out.
-	args = append(args, "devmgr.suspend-timeout-debug=true")
-	// Do not print colors.
-	args = append(args, "TERM=dumb")
-	if t.config.Target == "x64" {
-		// Necessary to redirect to stdout.
-		args = append(args, "kernel.serial=legacy")
-	}
-
-	invocation, err := qemu.CreateInvocation(config, args)
-	if err != nil {
-		return err
-	}
-
-	// The QEMU command needs to be invoked within an empty directory, as QEMU
-	// will attempt to pick up files from its working directory, one notable
-	// culprit being multiboot.bin.  This can result in strange behavior.
-	workdir, err := ioutil.TempDir("", "qemu-working-dir")
-	if err != nil {
-		return err
-	}
-
-	t.cmd = &exec.Cmd{
-		Path:   invocation[0],
-		Args:   invocation,
-		Dir:    workdir,
-		Stdout: os.Stdout,
-		Stderr: os.Stderr,
-	}
-	log.Printf("QEMU invocation:\n%s", invocation)
-
-	if err := t.cmd.Start(); err != nil {
-		os.RemoveAll(workdir)
-		return fmt.Errorf("failed to start: %v", err)
-	}
-
-	// Ensure that the working directory when QEMU finishes whether the Wait
-	// method is invoked or not.
-	go func() {
-		defer os.RemoveAll(workdir)
-		t.c <- qemu.CheckExitCode(t.cmd.Wait())
-	}()
-
-	return nil
-}
-
-// Wait waits for the QEMU target to stop.
-func (t *QEMUTarget) Restart(ctx context.Context) error {
-	return ErrUnimplemented
-}
-
-// Stop stops the QEMU target.
-func (t *QEMUTarget) Stop(ctx context.Context) error {
-	return t.cmd.Process.Kill()
-}
-
-// Wait waits for the QEMU target to stop.
-func (t *QEMUTarget) Wait(ctx context.Context) error {
-	return <-t.c
-}
-
-func overwriteFileWithCopy(path string) error {
-	tmpfile, err := ioutil.TempFile(filepath.Dir(path), "botanist")
-	if err != nil {
-		return err
-	}
-	defer tmpfile.Close()
-	if err := copyFile(path, tmpfile.Name()); err != nil {
-		return err
-	}
-	return os.Rename(tmpfile.Name(), path)
-}
-
-func copyFile(src, dest string) error {
-	in, err := os.Open(src)
-	if err != nil {
-		return err
-	}
-	defer in.Close()
-	info, err := in.Stat()
-	if err != nil {
-		return err
-	}
-	out, err := os.OpenFile(dest, os.O_WRONLY|os.O_CREATE, info.Mode().Perm())
-	if err != nil {
-		return err
-	}
-	defer out.Close()
-	_, err = io.Copy(out, in)
-	return err
-}
diff --git a/build/api/build.go b/build/api/build.go
deleted file mode 100644
index bb19532..0000000
--- a/build/api/build.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2018 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file includes build-specific concepts.
-
-package build
-
-const (
-	// TestSpecManifestName is the name of the manifest of test specs produced by the build.
-	TestSpecManifestName = "tests.json"
-
-	// PlatformManifestName is the name of the manifest of available test
-	// platforms.
-	PlatformManifestName = "platforms.json"
-)
diff --git a/build/api/images.go b/build/api/images.go
deleted file mode 100644
index 94b55b5..0000000
--- a/build/api/images.go
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2018 The Fuchsia 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 build
-
-import (
-	"encoding/json"
-	"fmt"
-	"os"
-	"path/filepath"
-)
-
-// Image represents an entry in an image manifest.
-type Image struct {
-	// Name is the canonical name of the image.
-	Name string `json:"name"`
-
-	// Path is the absolute path to the image.
-	// Note: when unmarshalled from a manifest this entry actually gives the relative
-	// location from the manifest's directory; we prepend that directory when loading. See
-	// LoadImages() below.
-	Path string `json:"path"`
-
-	// Type is the shorthand for the type of the image (e.g., "zbi" or "blk").
-	Type string `json:"type"`
-
-	// PaveArgs is the list of associated arguments to pass to the bootserver
-	// when paving.
-	PaveArgs []string `json:"bootserver_pave"`
-
-	// NetbootArgs is the list of associated arguments to pass to the bootserver
-	// when netbooting.
-	NetbootArgs []string `json:"bootserver_netboot"`
-}
-
-// Images is list of images produced by the build, as may be read in from an image manifest.
-type Images []Image
-
-// Get returns the first image in a list with the given name, or nil if no such image exists.
-func (imgs Images) Get(name string) *Image {
-	for _, img := range imgs {
-		if img.Name == name {
-			return &img
-		}
-	}
-	return nil
-}
-
-// LoadImages reads in the entries indexed in the given image manifests.
-func LoadImages(imageManifests ...string) (Images, error) {
-	decodeImages := func(manifest string) (Images, error) {
-		f, err := os.Open(manifest)
-		if err != nil {
-			return nil, fmt.Errorf("failed to open %s: %v", manifest, err)
-		}
-		defer f.Close()
-		var imgs Images
-		if err := json.NewDecoder(f).Decode(&imgs); err != nil {
-			return nil, fmt.Errorf("failed to decode %s: %v", manifest, err)
-		}
-		manifestDir, err := filepath.Abs(filepath.Dir(manifest))
-		if err != nil {
-			return nil, err
-		}
-		for i, _ := range imgs {
-			imgs[i].Path = filepath.Join(manifestDir, imgs[i].Path)
-		}
-		return imgs, nil
-	}
-
-	var imgs Images
-	for _, manifest := range imageManifests {
-		decoded, err := decodeImages(manifest)
-		if err != nil {
-			return nil, err
-		}
-		imgs = append(imgs, decoded...)
-	}
-	return imgs, nil
-}
diff --git a/build/gndoc/argmap.go b/build/gndoc/argmap.go
deleted file mode 100644
index 24888a6..0000000
--- a/build/gndoc/argmap.go
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2018 The Fuchsia 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 gndoc
-
-import (
-	"fmt"
-	"io"
-	"sort"
-	"strings"
-)
-
-type ArgMap struct {
-	argLookup map[string][]string // map of arg names to keys for lookup
-	args      map[string][]Arg    // map of key names to relevant args
-	sources   *SourceMap          // map of existing source locations for linkifying
-}
-
-// NewArgMap returns a pointer to an
-func NewArgMap(sources *SourceMap) *ArgMap {
-	return &ArgMap{
-		argLookup: make(map[string][]string),
-		args:      make(map[string][]Arg),
-		sources:   sources,
-	}
-}
-
-// AddArgs creates args from GNArgs and adds them to the maps
-func (a *ArgMap) AddArgs(gnArgs <-chan Arg) {
-	for gnArg := range gnArgs {
-		a.AddArg(gnArg)
-	}
-}
-
-// AddArg adds Arg to the maps
-func (a *ArgMap) AddArg(gnArg Arg) {
-	a.args[gnArg.Key] = append(a.args[gnArg.Key], gnArg)
-	a.argLookup[gnArg.Name] = append(a.argLookup[gnArg.Name], gnArg.Key)
-}
-
-// EmitMarkdown emits Markdown text for the map of arguments.
-func (a *ArgMap) EmitMarkdown(out io.Writer) {
-	type mappedArgs struct {
-		m map[string][]Arg
-		k []string
-	}
-	sortedArgs := struct {
-		m map[string]*mappedArgs
-		k []string
-	}{
-		m: make(map[string]*mappedArgs),
-		k: make([]string, 0),
-	}
-
-	numKeys := len(a.args)
-	for _, gnArgs := range a.args {
-		for _, gnArg := range gnArgs {
-			// Lookup the keys associated with this arg & sort & stringify.
-			keys, _ := a.argLookup[gnArg.Name]
-			if len(keys) == numKeys {
-				// Incoming keys will always have an `=`, and so  this is an
-				// okay value.
-				keys = []string{"all"}
-			}
-			sort.Strings(keys)
-			key := strings.Join(keys, ", ")
-			if _, ok := sortedArgs.m[key]; !ok {
-				sortedArgs.m[key] = &mappedArgs{
-					m: make(map[string][]Arg),
-					k: make([]string, 0)}
-			}
-			sortedArgs.m[key].m[gnArg.Name] = append(sortedArgs.m[key].m[gnArg.Name], gnArg)
-		}
-	}
-	for k := range sortedArgs.m {
-		for argName := range sortedArgs.m[k].m {
-			sort.Slice(sortedArgs.m[k].m[argName], func(i, j int) bool {
-				return sortedArgs.m[k].m[argName][i].Key < sortedArgs.m[k].m[argName][j].Key
-			})
-			sortedArgs.m[k].k = append(sortedArgs.m[k].k, argName)
-		}
-		sort.Strings(sortedArgs.m[k].k)
-		sortedArgs.k = append(sortedArgs.k, k)
-	}
-	sort.Strings(sortedArgs.k)
-	// Emit a header.
-	fmt.Fprintf(out, "# %s\n\n", pageTitle)
-	for _, name := range sortedArgs.k {
-		if name == "all" {
-			fmt.Fprintf(out, "## All builds\n\n")
-		} else {
-			fmt.Fprintf(out, "## `%s`\n\n", name)
-		}
-		for _, argsKey := range sortedArgs.m[name].k {
-			gnArgs := sortedArgs.m[name].m[argsKey]
-			writeArgs(gnArgs, out, a.sources)
-		}
-	}
-}
diff --git a/build/gndoc/argmap_test.go b/build/gndoc/argmap_test.go
deleted file mode 100644
index 005c97b..0000000
--- a/build/gndoc/argmap_test.go
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2019 The Fuchsia 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 gndoc
-
-import (
-	"bytes"
-	"math/rand"
-	"testing"
-	"time"
-)
-
-func genArgMapInRandomOrder() *ArgMap {
-	testArgMap := NewArgMap(Sources())
-	gnArgs := []Arg{
-		defaultx64Arg,
-		defaultarm64Arg,
-		defaultarm64ArgWithCurrent,
-		defaultx64ArgWithCurrent,
-		x64Arg,
-		arm64Arg,
-		twoKeyarm64TestArg,
-		twoKeyx64TestArg,
-		twoKeyarm64OtherArg,
-		twoKeyx64OtherArg,
-		newLineValueArg,
-	}
-	// Shuffle the gnArgs.
-	r := rand.New(rand.NewSource(time.Now().Unix()))
-	shuffledGnArgs := make([]Arg, 0)
-	for _, j := range r.Perm(len(gnArgs)) {
-		shuffledGnArgs = append(shuffledGnArgs, gnArgs[j])
-	}
-	for _, arg := range shuffledGnArgs {
-		testArgMap.AddArg(arg)
-	}
-	return testArgMap
-}
-
-func TestArgMapEmitMarkdown(t *testing.T) {
-	expectedOutput := `# GN Build Arguments
-
-## ` + "`target_cpu = arm64, package='other/package/default'`" + `
-
-### arm64Other
-Description of arm64 arg.
-
-**Current value for ` + "`target_cpu = arm64, package='other/package/default'`:** `arg`" + `
-
-**Overridden from the default:** ` + "`value`" + `
-
-## ` + "`target_cpu = arm64, target_cpu = arm64, package='test/package/default'`" + `
-
-### arm64
-Description of arm64 arg.
-
-**Current value for ` + "`target_cpu = arm64`:** `arg`" + `
-
-**Overridden from the default:** ` + "`value`" + `
-
-**Current value for ` + "`target_cpu = arm64, package='test/package/default'`:** `arg`" + `
-
-**Overridden from the default:** ` + "`value`" + `
-
-## ` + "`target_cpu = arm64, target_cpu = x64`" + `
-
-### default
-Description of default arg.
-
-**Current value (from the default):** ` + "`false`" + `
-
-From //test/BUILD.gn:2
-
-### default_current
-Description of default_current arg.
-
-**Current value for ` + "`target_cpu = arm64`:** `[1, 2]`" + `
-
-From [//build/BUILD.gn:24](http://fuchsia.com/build/BUILD.gn#24)
-
-**Overridden from the default:** ` + "`[3, 4]`" + `
-
-From [//base/BUILD.gn:4](http://fuchsia.com/base/BUILD.gn#4)
-
-**Current value for ` + "`target_cpu = x64`:** `3`" + `
-
-From [//build/BUILD.gn:24](http://fuchsia.com/build/BUILD.gn#24)
-
-**Overridden from the default:** ` + "`4`" + `
-
-From [//base/BUILD.gn:2](http://fuchsia.com/base/BUILD.gn#2)
-
-## ` + "`target_cpu = x64, package='other/package/default'`" + `
-
-### NewLine
-Description of newline arg.
-
-**Current value (from the default):**
-` + "```" + `
-{
-  base = "//build/toolchain/fuchsia:x64"
-}
-` + "```" + `
-
-### x64Other
-Description of x64 arg.
-
-**Current value for ` + "`target_cpu = x64, package='other/package/default'`:** `arg`" + `
-
-**Overridden from the default:** ` + "`value`" + `
-
-## ` + "`target_cpu = x64, target_cpu = x64, package='test/package/default'`" + `
-
-### x64
-Description of x64 arg that references [//build/path.py](http://fuchsia.com/build/path.py), //sources, and [//base](http://fuchsia.com/base).
-
-**Current value for ` + "`target_cpu = x64`:** `1`" + `
-
-**Overridden from the default:** ` + "`2`" + `
-
-**Current value for ` + "`target_cpu = x64, package='test/package/default'`:** `arg`" + `
-
-**Overridden from the default:** ` + "`value`" + `
-
-`
-	for i := 0; i < 10; i++ {
-		testArgMap := genArgMapInRandomOrder()
-		var testOutput bytes.Buffer
-		testArgMap.EmitMarkdown(&testOutput)
-		if expectedOutput != testOutput.String() {
-			t.Errorf("expecting output:\n%s\n, got:\n%s\n", expectedOutput, testOutput.String())
-			break
-		}
-	}
-}
diff --git a/build/gndoc/argparser.go b/build/gndoc/argparser.go
deleted file mode 100644
index a21ad0e..0000000
--- a/build/gndoc/argparser.go
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2018 The Fuchsia 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 gndoc
-
-import (
-	"context"
-	"encoding/json"
-	"fmt"
-	"os"
-	"strings"
-)
-
-// Arg holds the information directly parsed from the json output of `gn args <build> --list --json`.
-type Arg struct {
-	Name       string   `json:"name"`
-	CurrentVal argValue `json:"current"`
-	DefaultVal argValue `json:"default"`
-	Comment    string   `json:"comment"`
-	Key        string   `json: "-"`
-}
-
-// ArgValue holds a value, its filepath and line number, and the build associated with the value.
-type argValue struct {
-	Val  string `json:"value"`
-	File string `json:"file"`
-	Line int    `json:"line"`
-}
-
-// ParseGNArgs runs the necessary gn commands and decodes the json output into a channel of GNArgs.
-func ParseGNArgs(ctx context.Context, inputFiles []string, keyArgs []string) (<-chan Arg, <-chan error) {
-	args := make(chan Arg)
-	errs := make(chan error, 1)
-	go func() {
-		defer func() {
-			close(args)
-			close(errs)
-		}()
-		for _, input := range inputFiles {
-			select {
-			case <-ctx.Done():
-				return
-			default:
-				err := parseJson(input, keyArgs, args)
-				if err != nil {
-					errs <- err
-					return
-				}
-			}
-		}
-	}()
-	return args, errs
-}
-
-func parseJson(input string, keyArgs []string, out chan<- Arg) error {
-	// Open the json file.
-	file, err := os.Open(input)
-	if err != nil {
-		return err
-	}
-	defer file.Close()
-
-	// Decode the json into GNArgs.
-	var gnArgs []Arg
-	decoder := json.NewDecoder(file)
-	if err := decoder.Decode(&gnArgs); err != nil {
-		return err
-	}
-
-	// Mark the args with the relevant key and send to channel.
-	key := getKey(gnArgs, keyArgs)
-	for _, arg := range gnArgs {
-		arg.Key = key
-		out <- arg
-	}
-
-	return nil
-}
-
-// TODO: make sure this is sorted before stringifying
-// getKey searches the decoded json for the flagged keys and builds the marker string.
-func getKey(args []Arg, keys []string) string {
-	keyVals := make([]string, len(keys))
-	for _, arg := range args {
-		for idx, key := range keys {
-			if arg.Name == key {
-				keyVals[idx] = fmt.Sprintf("%s = %v", key, arg.CurrentVal.Val)
-			}
-		}
-	}
-	return strings.Join(keyVals, ", ")
-}
diff --git a/build/gndoc/cmd/main.go b/build/gndoc/cmd/main.go
deleted file mode 100644
index 06aedc1..0000000
--- a/build/gndoc/cmd/main.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2018 The Fuchsia 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 (
-	"context"
-	"flag"
-	"io"
-	"log"
-	"os"
-	"path/filepath"
-	"strings"
-
-	"go.fuchsia.dev/tools/build/gndoc"
-)
-
-type stringsFlag []string
-
-func (s *stringsFlag) String() string {
-	return strings.Join(*s, ", ")
-}
-
-func (s *stringsFlag) Set(value string) error {
-	*s = append(*s, value)
-	return nil
-}
-
-var (
-	keyArgs     stringsFlag
-	inputFiles  stringsFlag
-	outFile     string
-	sourcesFile string
-)
-
-func init() {
-	flag.Var(&keyArgs, "key", "a label for output")
-	flag.Var(&inputFiles, "in", "path to an input file")
-	flag.StringVar(&outFile, "out", "", "path to output file (default stdout)")
-	flag.StringVar(&sourcesFile, "s", "", "path to json file generated by Jiri projects")
-}
-
-func main() {
-	flag.Parse()
-	if flag.NArg() != 0 {
-		flag.PrintDefaults()
-	}
-
-	if sourcesFile == "" {
-		log.Fatalf("Error: no Jiri project reference file specified.\nTo generate, use jiri project -json-output=<file>.\n")
-	}
-
-	// Open the json file.
-	sources, err := os.Open(sourcesFile)
-	if err != nil {
-		log.Fatalf("Error: unable to open %s", sourcesFile)
-	}
-	defer sources.Close()
-
-	ctx := context.Background()
-	sourceMap, err := gndoc.NewSourceMap(sources)
-	if err != nil {
-		log.Fatalf("Error: %s", err)
-	}
-	argMap := gndoc.NewArgMap(sourceMap)
-
-	args, errs := gndoc.ParseGNArgs(ctx, inputFiles, keyArgs)
-	argMap.AddArgs(args)
-	if err := <-errs; err != nil {
-		log.Fatalf("Error: %s\n", err)
-	}
-
-	var out io.Writer
-	if outFile != "" {
-		var err error
-		if dirErr := os.MkdirAll(filepath.Dir(outFile), os.ModePerm); dirErr != nil {
-			log.Fatalf("Error creating directories: %s", dirErr)
-		}
-		out, err = os.Create(outFile)
-		if err != nil {
-			log.Fatalf("Error opening file: %s", err)
-		}
-	} else {
-		out = os.Stdout
-	}
-
-	argMap.EmitMarkdown(out)
-}
diff --git a/build/gndoc/formatter.go b/build/gndoc/formatter.go
deleted file mode 100644
index 15119f0..0000000
--- a/build/gndoc/formatter.go
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2018 The Fuchsia 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 gndoc
-
-import (
-	"fmt"
-	"io"
-	"regexp"
-	"sort"
-	"strings"
-)
-
-const (
-	pageTitle = "GN Build Arguments"
-	nameDepth = 3
-)
-
-var (
-	linkRegexp = regexp.MustCompile("//([/A-Za-z-_]+)([.][/A-Za-z-_]+)?")
-)
-
-// writeArg emits the name, comment description, and value(s) of the argument in Markdown.
-func writeArgs(args []Arg, out io.Writer, sources *SourceMap) {
-	if len(args) == 0 {
-		return
-	}
-	sort.Slice(args, func(i, j int) bool {
-		return args[i].Name < args[j].Name
-	})
-
-	fmt.Fprintf(out, "%s %s\n", strings.Repeat("#", nameDepth), args[0].Name)
-	// TODO (juliehockett): Make sure that *all* comments get emitted.
-	writeLinkifiedComment(&args[0], out, sources)
-	writeAllValues(args, out, sources)
-}
-
-// writeValue emits the value of a given argument value, along with the associated Markdown link to its declaration and build (if present).
-func writeValue(a *argValue, out io.Writer, sources *SourceMap) {
-	var value string
-	if strings.Contains(a.Val, "\n") {
-		value = fmt.Sprintf("\n```\n%s\n```", a.Val)
-	} else {
-		value = fmt.Sprintf(" `%s`", a.Val)
-	}
-
-	if a.File == "" {
-		// If there is no declaration file, emit just the value.
-		fmt.Fprintf(out, "%s\n\n", value)
-	} else {
-		// Otherwise, emit the value with a link to the declaration.
-		link := sources.GetSourceLink(a.File, a.Line)
-		if link == "" {
-			fmt.Fprintf(out, "%s\n\nFrom %s:%d\n\n", value, a.File, a.Line)
-			return
-		}
-		fmt.Fprintf(out, "%s\n\nFrom [%s:%d](%s)\n\n", value, a.File, a.Line, link)
-	}
-}
-
-func writeLinkifiedComment(a *Arg, out io.Writer, sources *SourceMap) {
-	replFunc := func(str string) string {
-		if link := sources.GetSourceLink(str, 0); link != "" {
-			return fmt.Sprintf("[%s](%s)", str, link)
-		}
-		return str
-	}
-	fmt.Fprintf(out, "%s\n", linkRegexp.ReplaceAllStringFunc(a.Comment, replFunc))
-}
-
-func writeAllValues(args []Arg, out io.Writer, sources *SourceMap) {
-	emptyArgValue := argValue{}
-	for _, a := range args {
-		if a.CurrentVal == emptyArgValue || a.CurrentVal == a.DefaultVal {
-			fmt.Fprintf(out, "**Current value (from the default):**")
-			writeValue(&a.DefaultVal, out, sources)
-			return
-		}
-		fmt.Fprintf(out, "**Current value for `%s`:**", a.Key)
-		writeValue(&a.CurrentVal, out, sources)
-		fmt.Fprintf(out, "**Overridden from the default:**")
-		writeValue(&a.DefaultVal, out, sources)
-	}
-}
diff --git a/build/gndoc/formatter_test.go b/build/gndoc/formatter_test.go
deleted file mode 100644
index a72757c..0000000
--- a/build/gndoc/formatter_test.go
+++ /dev/null
@@ -1,360 +0,0 @@
-// Copyright 2018 The Fuchsia 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 gndoc
-
-import (
-	"bytes"
-	"testing"
-)
-
-const (
-	numKeys = 2
-)
-
-var (
-	defaultx64Arg = Arg{
-		Name: "default",
-		DefaultVal: argValue{
-			Val:  "false",
-			File: "//test/BUILD.gn",
-			Line: 2,
-		},
-		Comment: "Description of default arg.\n",
-		Key:     "target_cpu = x64",
-	}
-
-	defaultarm64Arg = Arg{
-		Name: "default",
-		DefaultVal: argValue{
-			Val:  "false",
-			File: "//test/BUILD.gn",
-			Line: 2,
-		},
-		Comment: "Description of default arg.\n",
-		Key:     "target_cpu = arm64",
-	}
-
-	defaultarm64ArgWithCurrent = Arg{
-		Name: "default_current",
-		CurrentVal: argValue{
-			Val:  "[1, 2]",
-			File: "//build/BUILD.gn",
-			Line: 24,
-		},
-		DefaultVal: argValue{
-			Val:  "[3, 4]",
-			File: "//base/BUILD.gn",
-			Line: 4,
-		},
-		Comment: "Description of default_current arg.\n",
-		Key:     "target_cpu = arm64",
-	}
-
-	defaultx64ArgWithCurrent = Arg{
-		Name: "default_current",
-		CurrentVal: argValue{
-			Val:  "3",
-			File: "//build/BUILD.gn",
-			Line: 24,
-		},
-		DefaultVal: argValue{
-			Val:  "4",
-			File: "//base/BUILD.gn",
-			Line: 2,
-		},
-		Comment: "Description of default_current arg.\n",
-		Key:     "target_cpu = x64",
-	}
-
-	x64Arg = Arg{
-		Name: "x64",
-		CurrentVal: argValue{
-			Val: "1",
-		},
-		DefaultVal: argValue{
-			Val: "2",
-		},
-		Comment: "Description of x64 arg that references //build/path.py, //sources, and //base.\n",
-		Key:     "target_cpu = x64",
-	}
-
-	arm64Arg = Arg{
-		Name: "arm64",
-		CurrentVal: argValue{
-			Val: "arg",
-		},
-		DefaultVal: argValue{
-			Val: "value",
-		},
-		Comment: "Description of arm64 arg.\n",
-		Key:     "target_cpu = arm64",
-	}
-
-	twoKeyarm64TestArg = Arg{
-		Name: "arm64",
-		CurrentVal: argValue{
-			Val: "arg",
-		},
-		DefaultVal: argValue{
-			Val: "value",
-		},
-		Comment: "Description of arm64 arg.\n",
-		Key:     "target_cpu = arm64, package='test/package/default'",
-	}
-
-	twoKeyx64TestArg = Arg{
-		Name: "x64",
-		CurrentVal: argValue{
-			Val: "arg",
-		},
-		DefaultVal: argValue{
-			Val: "value",
-		},
-		Comment: "Description of x64 arg.\n",
-		Key:     "target_cpu = x64, package='test/package/default'",
-	}
-
-	twoKeyarm64OtherArg = Arg{
-		Name: "arm64Other",
-		CurrentVal: argValue{
-			Val: "arg",
-		},
-		DefaultVal: argValue{
-			Val: "value",
-		},
-		Comment: "Description of arm64 arg.\n",
-		Key:     "target_cpu = arm64, package='other/package/default'",
-	}
-
-	twoKeyx64OtherArg = Arg{
-		Name: "x64Other",
-		CurrentVal: argValue{
-			Val: "arg",
-		},
-		DefaultVal: argValue{
-			Val: "value",
-		},
-		Comment: "Description of x64 arg.\n",
-		Key:     "target_cpu = x64, package='other/package/default'",
-	}
-
-	newLineValueArg = Arg{
-		Name: "NewLine",
-		DefaultVal: argValue{
-			Val: "{\n  base = \"//build/toolchain/fuchsia:x64\"\n}",
-		},
-		Comment: "Description of newline arg.\n",
-		Key:     "target_cpu = x64, package='other/package/default'",
-	}
-)
-
-func Sources() *SourceMap {
-	s := SourceMap(make(map[string]string))
-	s["base"] = "http://fuchsia.com/base"
-	s["build"] = "http://fuchsia.com/build"
-	return &s
-}
-
-func TestDefault(t *testing.T) {
-
-	gnArgs := []Arg{defaultx64Arg, defaultarm64Arg}
-	argMap := NewArgMap(Sources())
-	for _, arg := range gnArgs {
-		argMap.AddArg(arg)
-	}
-
-	// No file name emits to stdout.
-	var buffer bytes.Buffer
-	argMap.EmitMarkdown(&buffer)
-
-	actual := buffer.String()
-	expected := `# GN Build Arguments
-
-## All builds
-
-### default
-Description of default arg.
-
-**Current value (from the default):** ` + "`false`" + `
-
-From //test/BUILD.gn:2
-
-`
-	if expected != actual {
-		t.Fatalf("In TestDefault, expected \n%s but got \n%s", expected, actual)
-	}
-}
-
-func TestDefaultWithCurrent(t *testing.T) {
-
-	gnArgs := []Arg{defaultx64ArgWithCurrent, defaultarm64ArgWithCurrent}
-	argMap := NewArgMap(Sources())
-	for _, arg := range gnArgs {
-		argMap.AddArg(arg)
-	}
-
-	// No file name emits to stdout.
-	var buffer bytes.Buffer
-	argMap.EmitMarkdown(&buffer)
-
-	actual := buffer.String()
-	expected := `# GN Build Arguments
-
-## All builds
-
-### default_current
-Description of default_current arg.
-
-**Current value for ` + "`target_cpu = arm64`:** `[1, 2]`" + `
-
-From [//build/BUILD.gn:24](http://fuchsia.com/build/BUILD.gn#24)
-
-**Overridden from the default:** ` + "`[3, 4]`" + `
-
-From [//base/BUILD.gn:4](http://fuchsia.com/base/BUILD.gn#4)
-
-**Current value for ` + "`target_cpu = x64`:** `3`" + `
-
-From [//build/BUILD.gn:24](http://fuchsia.com/build/BUILD.gn#24)
-
-**Overridden from the default:**` + " `4`" + `
-
-From [//base/BUILD.gn:2](http://fuchsia.com/base/BUILD.gn#2)
-
-`
-
-	if expected != actual {
-		t.Fatalf("In TestDefaultWithCurrent, expected \n%s but got \n%s", expected, actual)
-	}
-}
-
-func TestUnique(t *testing.T) {
-
-	gnArgs := []Arg{x64Arg, arm64Arg}
-	argMap := NewArgMap(Sources())
-	for _, arg := range gnArgs {
-		argMap.AddArg(arg)
-	}
-
-	// No file name emits to stdout.
-	var buffer bytes.Buffer
-	argMap.EmitMarkdown(&buffer)
-
-	actual := buffer.String()
-	expected := `# GN Build Arguments
-
-## ` + "`target_cpu = arm64`" + `
-
-### arm64
-Description of arm64 arg.
-
-**Current value for ` + "`target_cpu = arm64`:** `arg`" + `
-
-**Overridden from the default:** ` + "`value`" + `
-
-## ` + "`target_cpu = x64`" + `
-
-### x64
-Description of x64 arg that references [//build/path.py](http://fuchsia.com/build/path.py), //sources, and [//base](http://fuchsia.com/base).
-
-**Current value for ` + "`target_cpu = x64`:** `1`" + `
-
-**Overridden from the default:** ` + "`2`" + `
-
-`
-	if expected != actual {
-		t.Fatalf("In TestUnique, expected \n%s but got \n%s", expected, actual)
-	}
-}
-
-func TestTwoKeys(t *testing.T) {
-
-	gnArgs := []Arg{twoKeyarm64TestArg, twoKeyx64TestArg, twoKeyarm64OtherArg, twoKeyx64OtherArg}
-	argMap := NewArgMap(Sources())
-	for _, arg := range gnArgs {
-		argMap.AddArg(arg)
-	}
-
-	// No file name emits to stdout.
-	var buffer bytes.Buffer
-	argMap.EmitMarkdown(&buffer)
-
-	actual := buffer.String()
-	expected := `# GN Build Arguments
-
-## ` + "`target_cpu = arm64, package='other/package/default'`" + `
-
-### arm64Other
-Description of arm64 arg.
-
-**Current value for ` + "`target_cpu = arm64, package='other/package/default'`:** `arg`" + `
-
-**Overridden from the default:** ` + "`value`" + `
-
-## ` + "`target_cpu = arm64, package='test/package/default'`" + `
-
-### arm64
-Description of arm64 arg.
-
-**Current value for ` + "`target_cpu = arm64, package='test/package/default'`:** `arg`" + `
-
-**Overridden from the default:** ` + "`value`" + `
-
-## ` + "`target_cpu = x64, package='other/package/default'`" + `
-
-### x64Other
-Description of x64 arg.
-
-**Current value for ` + "`target_cpu = x64, package='other/package/default'`:** `arg`" + `
-
-**Overridden from the default:** ` + "`value`" + `
-
-## ` + "`target_cpu = x64, package='test/package/default'`" + `
-
-### x64
-Description of x64 arg.
-
-**Current value for ` + "`target_cpu = x64, package='test/package/default'`:** `arg`" + `
-
-**Overridden from the default:** ` + "`value`" + `
-
-`
-	if expected != actual {
-		t.Fatalf("In TestUnique, expected \n%s but got \n%s", expected, actual)
-	}
-}
-
-func TestValueNewLine(t *testing.T) {
-
-	gnArgs := []Arg{newLineValueArg}
-	argMap := NewArgMap(Sources())
-	for _, arg := range gnArgs {
-		argMap.AddArg(arg)
-	}
-
-	// No file name emits to stdout.
-	var buffer bytes.Buffer
-	argMap.EmitMarkdown(&buffer)
-
-	actual := buffer.String()
-	expected := `# GN Build Arguments
-
-## All builds
-
-### NewLine
-Description of newline arg.
-
-**Current value (from the default):**
-` + "```" + `
-{
-  base = "//build/toolchain/fuchsia:x64"
-}
-` + "```" + `
-
-`
-	if expected != actual {
-		t.Fatalf("In TestDefault, expected \n%s but got \n%s", expected, actual)
-	}
-}
diff --git a/build/gndoc/sourceparser.go b/build/gndoc/sourceparser.go
deleted file mode 100644
index 02c8611..0000000
--- a/build/gndoc/sourceparser.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2018 The Fuchsia 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 gndoc
-
-import (
-	"encoding/json"
-	"fmt"
-	"io"
-	"path/filepath"
-	"strings"
-)
-
-type SourceMap map[string]string
-
-func NewSourceMap(input io.Reader) (*SourceMap, error) {
-	s := SourceMap(make(map[string]string))
-	err := s.parseJson(input)
-	if err != nil {
-		return nil, err
-	}
-	return &s, nil
-}
-
-// parseJson extracts the source project information into the map.
-func (s SourceMap) parseJson(input io.Reader) error {
-	// Decode the json into the map.
-	var sources []map[string]interface{}
-	decoder := json.NewDecoder(input)
-	if err := decoder.Decode(&sources); err != nil {
-		return err
-	}
-
-	for _, source := range sources {
-		if revision, ok := source["revision"]; ok {
-			s[source["name"].(string)] = fmt.Sprintf("%v/+/%s", source["remote"], revision)
-		} else {
-			s[source["name"].(string)] = fmt.Sprintf("%v/+/master", source["remote"])
-		}
-	}
-
-	return nil
-}
-
-// GetSourceLink returns a URL based on a file and a line number.
-func (s SourceMap) GetSourceLink(file string, line int) string {
-	// We need to trim off first slashes in the filename.
-	file = strings.TrimPrefix(file, "//")
-	project := file
-	for {
-		if _, exists := s[project]; exists {
-			break
-		}
-		project = filepath.Dir(project)
-		if project == "." {
-			return ""
-		}
-	}
-	if line == 0 {
-		return fmt.Sprintf("%s%s", s[project], file[len(project):])
-	}
-	return fmt.Sprintf("%s%s#%d", s[project], file[len(project):], line)
-}
diff --git a/build/gndoc/sourceparser_test.go b/build/gndoc/sourceparser_test.go
deleted file mode 100644
index e5db803..0000000
--- a/build/gndoc/sourceparser_test.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2018 The Fuchsia 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 gndoc
-
-import (
-	"strings"
-	"testing"
-)
-
-func TestNewSourceMap(t *testing.T) {
-	sources := `[
-  {
-    "name": "build",
-    "path": "/path/to/fuchsia/build",
-    "relativePath": "build",
-    "remote": "https://fuchsia.googlesource.com/build",
-    "revision": "43d2b55675d428d460fe6f91092bbf3c39552caf",
-    "branches": [
-      "mybranch",
-      "master"
-    ]
-  },
-  {
-    "name": "buildtools",
-    "path": "/path/to/fuchsia/buildtools",
-    "relativePath": "buildtools",
-    "remote": "https://fuchsia.googlesource.com/buildtools"
-  }
-]
-`
-	actual, err := NewSourceMap(strings.NewReader(sources))
-	if err != nil {
-		t.Fatalf("In TestNewSourceMap, unable to create source map: %s", err)
-	}
-
-	expected := SourceMap(make(map[string]string))
-	expected["build"] = "https://fuchsia.googlesource.com/build/+/43d2b55675d428d460fe6f91092bbf3c39552caf"
-	expected["buildtools"] = "https://fuchsia.googlesource.com/buildtools/+/master"
-
-	if len(expected) != len(*actual) {
-		t.Fatalf("In TestNewSourceMap, expected \n%d but got \n%d", len(expected), len(*actual))
-	}
-
-	if expected["build"] != (*actual)["build"] {
-		t.Fatalf("In TestNewSourceMap, expected \n%s but got \n%s", expected["build"], (*actual)["build"])
-	}
-
-	if expected["buildtools"] != (*actual)["buildtools"] {
-		t.Fatalf("In TestNewSourceMap, expected \n%s but got \n%s", expected["buildtools"], (*actual)["buildtools"])
-	}
-}
-
-func TestGetSourceLink(t *testing.T) {
-	sourceMap := SourceMap(make(map[string]string))
-	sourceMap["build"] = "https://fuchsia.googlesource.com/build/+/43d2b55675d428d460fe6f91092bbf3c39552caf"
-	sourceMap["buildtools"] = "https://fuchsia.googlesource.com/buildtools/+/master"
-
-	expected := "https://fuchsia.googlesource.com/build/+/43d2b55675d428d460fe6f91092bbf3c39552caf/BUILD.gn#27"
-	actual := sourceMap.GetSourceLink("//build/BUILD.gn", 27)
-	if expected != actual {
-		t.Fatalf("In TestNewSourceMap, expected \n%s but got \n%s", expected, actual)
-	}
-
-	expected = "https://fuchsia.googlesource.com/build/+/43d2b55675d428d460fe6f91092bbf3c39552caf/BUILD.gn"
-	actual = sourceMap.GetSourceLink("//build/BUILD.gn", 0)
-	if expected != actual {
-		t.Fatalf("In TestNewSourceMap, expected \n%s but got \n%s", expected, actual)
-	}
-
-	expected = ""
-	actual = sourceMap.GetSourceLink("//base/BUILD.gn", 0)
-	if expected != actual {
-		t.Fatalf("In TestNewSourceMap, expected \n%s but got \n%s", expected, actual)
-	}
-}
diff --git a/build/godepfile/cmd/godepfile.go b/build/godepfile/cmd/godepfile.go
deleted file mode 100644
index 0793697..0000000
--- a/build/godepfile/cmd/godepfile.go
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright 2016 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Generates a depfile for a Go package that can be consumed by Ninja.
-package main
-
-import (
-	"flag"
-	"fmt"
-	"go/build"
-	"log"
-	"os"
-	"runtime"
-	"sort"
-	"strings"
-	"sync"
-)
-
-type stringsFlag []string
-
-func (v *stringsFlag) String() string { return strings.Join(*v, " ") }
-
-func (v *stringsFlag) Set(s string) error {
-	*v = strings.Split(s, " ")
-	if *v == nil {
-		*v = []string{}
-	}
-	return nil
-}
-
-var (
-	ctx    = build.Default
-	output string
-	test   bool
-)
-
-func init() {
-	flag.Var((*stringsFlag)(&ctx.BuildTags), "tags", "build tags")
-	flag.StringVar(&output, "o", "", "name of the resulting executable")
-	flag.BoolVar(&test, "test", false, "whether this is a test target")
-
-	flag.Usage = func() {
-		fmt.Fprintf(os.Stderr, "usage: godepfile [packages]\n")
-		flag.PrintDefaults()
-	}
-}
-
-func main() {
-	flag.Parse()
-
-	if len(flag.Args()) == 0 {
-		flag.Usage()
-		os.Exit(1)
-	}
-
-	var mu sync.Mutex
-	deps := make(map[string]bool)
-	paths := make(map[string]bool)
-
-	fdlimit := make(chan struct{}, 128)
-	var wg sync.WaitGroup
-	var scan func(path, srcDir string)
-	scan = func(path, srcDir string) {
-		defer wg.Done()
-
-		mu.Lock()
-		_, done := paths[path]
-		if !done {
-			paths[path] = true
-		}
-		mu.Unlock()
-
-		if done {
-			return
-		}
-
-		if path == "C" {
-			return
-		}
-
-		fdlimit <- struct{}{}
-		defer func() { <-fdlimit }()
-
-		pkg, err := ctx.Import(path, srcDir, 0)
-		if err != nil {
-			log.Fatalf("%s: %v", path, err)
-		}
-
-		var files []string
-		srcdir := pkg.Dir + "/"
-		files = appendAndPrefix(files, srcdir, pkg.GoFiles)
-		files = appendAndPrefix(files, srcdir, pkg.CgoFiles)
-		files = appendAndPrefix(files, srcdir, pkg.CFiles)
-		files = appendAndPrefix(files, srcdir, pkg.CXXFiles)
-		files = appendAndPrefix(files, srcdir, pkg.HFiles)
-		files = appendAndPrefix(files, srcdir, pkg.SFiles)
-		files = appendAndPrefix(files, srcdir, pkg.SwigFiles)
-		files = appendAndPrefix(files, srcdir, pkg.SwigCXXFiles)
-
-		if test {
-			files = appendAndPrefix(files, srcdir, pkg.TestGoFiles)
-			files = appendAndPrefix(files, srcdir, pkg.XTestGoFiles)
-		}
-
-		mu.Lock()
-		for _, file := range files {
-			deps[file] = true
-		}
-		mu.Unlock()
-
-		if pkg.Name == "main" && output == "" {
-			bindir := os.Getenv("GOBIN")
-			if bindir == "" {
-				bindir = pkg.BinDir
-			}
-			if ctx.GOOS == runtime.GOOS && ctx.GOARCH == runtime.GOARCH {
-				output = ctx.JoinPath(bindir, path)
-			} else {
-				output = ctx.JoinPath(bindir, ctx.GOOS+"_"+ctx.GOARCH, path)
-			}
-		}
-
-		for _, imp := range pkg.Imports {
-			wg.Add(1)
-			go scan(imp, pkg.Dir)
-		}
-	}
-
-	for _, root := range flag.Args() {
-		wg.Add(1)
-		go scan(root, "")
-	}
-	wg.Wait()
-
-	fmt.Printf("%s:", output)
-	var depnames []string
-	for path := range deps {
-		depnames = append(depnames, path)
-	}
-	sort.Strings(depnames)
-	for path := range deps {
-		fmt.Printf(" %s", path)
-	}
-	fmt.Printf("\n")
-}
-
-func appendAndPrefix(slice []string, prefix string, src []string) []string {
-	for _, s := range src {
-		slice = append(slice, prefix+s)
-	}
-	return slice
-}
diff --git a/build/ninjalog/doc.go b/build/ninjalog/doc.go
deleted file mode 100644
index 4c2b075..0000000
--- a/build/ninjalog/doc.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 The Chromium 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 ninjalog provides ninja_log parser
-
-It support ninja log v5.
-
- # ninja log v5
- <start>	<end>	<restat>	<target>	<cmdhash>
-
-where
- <start> = start time since ninja starts in msec.
- <end>   = end time since ninja starts in msec.
- <restat> = restat time in epoch.
- <target> = target (output) filename
- <cmdhash> = hash of command line (?)
-
-It assumes steps in the last build will be ascendent order of <end>.
-
-It also supports metadata added by chromium's buildbot compile.py.
-metadata is added after
-
- # end of ninja log
-
-and written in json format.
-
-*/
-package ninjalog
diff --git a/build/ninjalog/ninjalog.go b/build/ninjalog/ninjalog.go
deleted file mode 100644
index 09261ac..0000000
--- a/build/ninjalog/ninjalog.go
+++ /dev/null
@@ -1,449 +0,0 @@
-// Copyright 2014 The Fuchsia 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 ninjalog
-
-import (
-	"bufio"
-	"encoding/json"
-	"fmt"
-	"io"
-	"sort"
-	"strconv"
-	"strings"
-	"time"
-)
-
-// Step is one step in ninja_log file.
-// time is measured from ninja start time.
-type Step struct {
-	Start time.Duration
-	End   time.Duration
-	// modification time, but not convertable to absolute real time.
-	// on POSIX, time_t is used, but on Windows different type is used.
-	// htts://github.com/martine/ninja/blob/master/src/timestamp.h
-	Restat  int
-	Out     string
-	CmdHash string
-
-	// other outs for the same CmdHash if dedup'ed.
-	Outs []string
-}
-
-// Duration reports step's duration.
-func (s Step) Duration() time.Duration {
-	return s.End - s.Start
-}
-
-// Steps is a list of Step.
-// It could be used to sort by start time.
-type Steps []Step
-
-func (s Steps) Len() int      { return len(s) }
-func (s Steps) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-func (s Steps) Less(i, j int) bool {
-	if s[i].Start != s[j].Start {
-		return s[i].Start < s[j].Start
-	}
-	if s[i].End != s[j].End {
-		return s[i].End < s[j].End
-	}
-	return s[i].Out < s[j].Out
-}
-
-// Reverse reverses steps.
-// It would be more efficient if steps is already sorted than using sort.Reverse.
-func (s Steps) Reverse() {
-	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
-		s[i], s[j] = s[j], s[i]
-	}
-}
-
-// ByEnd is used to sort by end time.
-type ByEnd struct{ Steps }
-
-func (s ByEnd) Less(i, j int) bool { return s.Steps[i].End < s.Steps[j].End }
-
-// ByDuration is used to sort by duration.
-type ByDuration struct{ Steps }
-
-func (s ByDuration) Less(i, j int) bool { return s.Steps[i].Duration() < s.Steps[j].Duration() }
-
-// ByWeightedTime is used to sort by weighted time.
-type ByWeightedTime struct {
-	Weighted map[string]time.Duration
-	Steps
-}
-
-func (s ByWeightedTime) Less(i, j int) bool {
-	return s.Weighted[s.Steps[i].Out] < s.Weighted[s.Steps[j].Out]
-}
-
-// Metadata is data added by compile.py.
-type Metadata struct {
-	// Platform is platform of buildbot.
-	Platform string `json:"platform"`
-
-	// Argv is argv of compile.py
-	Argv []string `json:"argv"`
-
-	// Cwd is current working directory of compile.py
-	Cwd string `json:"cwd"`
-
-	// Compiler is compiler used.
-	Compiler string `json:"compiler"`
-
-	// Cmdline is command line of ninja.
-	Cmdline []string `json:"cmdline"`
-
-	// Exit is exit status of ninja.
-	Exit int `json:"exit"`
-
-	// Env is environment variables.
-	Env map[string]string `json:"env"`
-
-	// CompilerProxyInfo is a path name of associated compiler_proxy.INFO log.
-	CompilerProxyInfo string `json:"compiler_proxy_info"`
-
-	// Raw is raw string for metadata.
-	Raw string
-	// Error is error message of parsing metadata.
-	Error string
-}
-
-// NinjaLog is parsed data of ninja_log file.
-type NinjaLog struct {
-	// Filename is a filename of ninja_log.
-	Filename string
-
-	// Start is start line of the last build in ninja_log file.
-	Start int
-
-	// Steps contains steps in the last build in ninja_log file.
-	Steps []Step
-
-	// Metadata is additional data found in ninja_log file.
-	Metadata Metadata
-}
-
-// Parse parses .ninja_log file, with chromium's compile.py metadata.
-func Parse(fname string, r io.Reader) (*NinjaLog, error) {
-	b := bufio.NewReader(r)
-	scanner := bufio.NewScanner(b)
-	nlog := &NinjaLog{Filename: fname}
-	lineno := 0
-	if !scanner.Scan() {
-		if err := scanner.Err(); err != nil {
-			return nil, err
-		}
-		return nil, fmt.Errorf("empty file?")
-	}
-	lineno++
-	line := scanner.Text()
-	if line != "# ninja log v5" {
-		return nil, fmt.Errorf("unexpected format: %s", line)
-	}
-	nlog.Start = lineno
-	var lastStep Step
-	for scanner.Scan() {
-		line := scanner.Text()
-		if line == "# end of ninja log" {
-			break
-		}
-		if line == "" {
-			continue
-		}
-		step, err := lineToStep(line)
-		if err != nil {
-			return nil, fmt.Errorf("error at %d: %v", lineno, err)
-		}
-		if step.End < lastStep.End {
-			nlog.Start = lineno
-			nlog.Steps = nil
-		}
-		nlog.Steps = append(nlog.Steps, step)
-		lastStep = step
-		lineno++
-	}
-	if err := scanner.Err(); err != nil {
-		return nil, fmt.Errorf("error at %d: %v", lineno, err)
-	}
-	if !scanner.Scan() {
-		if err := scanner.Err(); err != nil {
-			return nil, fmt.Errorf("error at %d: %v", lineno, err)
-		}
-		// missing metadata?
-		return nlog, nil
-	}
-	lineno++
-	nlog.Metadata.Raw = scanner.Text()
-	if err := parseMetadata([]byte(nlog.Metadata.Raw), &nlog.Metadata); err != nil {
-		nlog.Metadata.Error = fmt.Sprintf("error at %d: %v", lineno, err)
-	}
-	return nlog, nil
-}
-
-func lineToStep(line string) (Step, error) {
-	var step Step
-
-	// Due to slowness of strings.Split in App Engine Go,
-	// we use more faster implementation.
-	fields := make([]string, 0, 5)
-	for i := 0; i < 5; i += 1 {
-		m := strings.IndexByte(line, '\t')
-		if m < 0 {
-			m = len(line)
-		}
-		fields = append(fields, line[:m])
-		if m < len(line) {
-			line = line[m+1:]
-		}
-	}
-
-	if len(fields) < 5 {
-		return step, fmt.Errorf("few fields:%d", len(fields))
-	}
-	s, err := strconv.ParseUint(fields[0], 10, 0)
-	if err != nil {
-		return step, fmt.Errorf("bad start %s:%v", fields[0], err)
-	}
-	e, err := strconv.ParseUint(fields[1], 10, 0)
-	if err != nil {
-		return step, fmt.Errorf("bad end %s:%v", fields[1], err)
-	}
-	rs, err := strconv.ParseUint(fields[2], 10, 0)
-	if err != nil {
-		return step, fmt.Errorf("bad restat %s:%v", fields[2], err)
-	}
-	step.Start = time.Duration(s) * time.Millisecond
-	step.End = time.Duration(e) * time.Millisecond
-	step.Restat = int(rs)
-	step.Out = fields[3]
-	step.CmdHash = fields[4]
-	return step, nil
-}
-
-func stepToLine(s Step) string {
-	return fmt.Sprintf("%d\t%d\t%d\t%s\t%s",
-		s.Start.Nanoseconds()/int64(time.Millisecond),
-		s.End.Nanoseconds()/int64(time.Millisecond),
-		s.Restat,
-		s.Out,
-		s.CmdHash)
-}
-
-func parseMetadata(buf []byte, metadata *Metadata) error {
-	return json.Unmarshal(buf, metadata)
-}
-
-// Dump dumps steps as ninja log v5 format in w.
-func Dump(w io.Writer, steps []Step) error {
-	_, err := fmt.Fprintf(w, "# ninja log v5\n")
-	if err != nil {
-		return err
-	}
-	for _, s := range steps {
-		_, err = fmt.Fprintln(w, stepToLine(s))
-		if err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// Dedup dedupes steps. step may have the same cmd hash.
-// Dedup only returns the first step for these steps.
-// steps will be sorted by start time.
-func Dedup(steps []Step) []Step {
-	m := make(map[string]*Step)
-	sort.Sort(Steps(steps))
-	var dedup []Step
-	for _, s := range steps {
-		if os := m[s.CmdHash]; os != nil {
-			os.Outs = append(os.Outs, s.Out)
-			continue
-		}
-		dedup = append(dedup, s)
-		m[s.CmdHash] = &dedup[len(dedup)-1]
-	}
-	return dedup
-}
-
-// TotalTime returns startup time and end time of ninja, and accumulated time
-// of all tasks.
-func TotalTime(steps []Step) (startupTime, endTime, cpuTime time.Duration) {
-	if len(steps) == 0 {
-		return 0, 0, 0
-	}
-	steps = Dedup(steps)
-	startup := steps[0].Start
-	var end time.Duration
-	for _, s := range steps {
-		if s.Start < startup {
-			startup = s.Start
-		}
-		if s.End > end {
-			end = s.End
-		}
-		cpuTime += s.Duration()
-	}
-	return startup, end, cpuTime
-}
-
-// Flow returns concurrent steps by time.
-// steps in every []Step will not have time overlap.
-// steps will be sorted by start time.
-func Flow(steps []Step) [][]Step {
-	sort.Sort(Steps(steps))
-	var threads [][]Step
-
-	for _, s := range steps {
-		tid := -1
-		for i, th := range threads {
-			if len(th) == 0 {
-				panic(fmt.Errorf("thread %d has no entry", i))
-			}
-			if th[len(th)-1].End <= s.Start {
-				tid = i
-				break
-			}
-		}
-		if tid == -1 {
-			threads = append(threads, nil)
-			tid = len(threads) - 1
-		}
-		threads[tid] = append(threads[tid], s)
-	}
-	return threads
-}
-
-// action represents an event's action. "start" or "end".
-type action string
-
-const (
-	unknownAction action = ""
-	startAction   action = "start"
-	stopAction    action = "stop"
-)
-
-// event is an event of steps.
-type event struct {
-	time   time.Duration
-	action action
-	target string
-}
-
-// toEvent converts steps into events.
-// events are sorted by its time.
-func toEvent(steps []Step) []event {
-	var events []event
-	for _, s := range steps {
-		events = append(events,
-			event{
-				time:   s.Start,
-				action: startAction,
-				target: s.Out,
-			},
-			event{
-				time:   s.End,
-				action: stopAction,
-				target: s.Out,
-			},
-		)
-	}
-	sort.Slice(events, func(i, j int) bool {
-		if events[i].time == events[j].time {
-			// If a task starts and stops on the same time stamp
-			// then the start will come first.
-			return events[i].action < events[j].action
-		}
-		return events[i].time < events[j].time
-	})
-	return events
-}
-
-// WeightedTime calculates weighted time, which is elapsed time with
-// each segment divided by the number of tasks that were running in paralle.
-// This makes it a much better approximation of how "important" a slow step was.
-// For example, A link that is entirely or mostly serialized will have a
-// weighted time that is the same or similar to its elapsed time.
-// A compile that runs in parallel with 999 other compiles will have a weighted
-// time that is tiny.
-func WeightedTime(steps []Step) map[string]time.Duration {
-	if len(steps) == 0 {
-		return nil
-	}
-	steps = Dedup(steps)
-	events := toEvent(steps)
-	weightedDuration := make(map[string]time.Duration)
-
-	// Track the tasks which are currently running.
-	runningTasks := make(map[string]time.Duration)
-
-	// Record the time we have processed up to so we know how to calculate
-	// time deltas.
-	lastTime := events[0].time
-
-	// Track the accumulated weighted time so that it can efficiently be
-	// added to individual tasks.
-	var lastWeightedTime time.Duration
-
-	for _, event := range events {
-		numRunning := len(runningTasks)
-		if numRunning > 0 {
-			// Update the total weighted time up to this moment.
-			lastWeightedTime += (event.time - lastTime) / time.Duration(numRunning)
-		}
-		switch event.action {
-		case startAction:
-			// Record the total weighted task time when this task starts.
-			runningTasks[event.target] = lastWeightedTime
-		case stopAction:
-			// Record the change in the total weighted task time while this task ran.
-			weightedDuration[event.target] = lastWeightedTime - runningTasks[event.target]
-			delete(runningTasks, event.target)
-		}
-		lastTime = event.time
-	}
-	return weightedDuration
-}
-
-// Stat represents statistics for build step.
-type Stat struct {
-	Type     string
-	Count    int
-	Time     time.Duration
-	Weighted time.Duration
-}
-
-// StatsByType summarizes build step statistics with weighted and typeOf.
-// Stats is sorted by Weighted, longer first.
-func StatsByType(steps []Step, weighted map[string]time.Duration, typeOf func(Step) string) []Stat {
-	if len(steps) == 0 {
-		return nil
-	}
-	steps = Dedup(steps)
-	m := make(map[string]int) // type to index of stats.
-	var stats []Stat
-	for _, step := range steps {
-		t := typeOf(step)
-		if i, ok := m[t]; ok {
-			stats[i].Count++
-			stats[i].Time += step.Duration()
-			stats[i].Weighted += weighted[step.Out]
-			continue
-		}
-		stats = append(stats, Stat{
-			Type:     t,
-			Count:    1,
-			Time:     step.Duration(),
-			Weighted: weighted[step.Out],
-		})
-		m[t] = len(stats) - 1
-	}
-	sort.Slice(stats, func(i, j int) bool {
-		return stats[i].Weighted > stats[j].Weighted
-	})
-	return stats
-}
diff --git a/build/ninjalog/ninjalog_test.go b/build/ninjalog/ninjalog_test.go
deleted file mode 100644
index bc5306d..0000000
--- a/build/ninjalog/ninjalog_test.go
+++ /dev/null
@@ -1,553 +0,0 @@
-// Copyright 2014 The Fuchsia 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 ninjalog
-
-import (
-	"bytes"
-	"io/ioutil"
-	"reflect"
-	"sort"
-	"strings"
-	"testing"
-	"time"
-)
-
-var (
-	logTestCase = `# ninja log v5
-76	187	0	resources/inspector/devtools_extension_api.js	75430546595be7c2
-80	284	0	gen/autofill_regex_constants.cc	fa33c8d7ce1d8791
-78	286	0	gen/angle/commit_id.py	4ede38e2c1617d8c
-79	287	0	gen/angle/copy_compiler_dll.bat	9fb635ad5d2c1109
-141	287	0	PepperFlash/manifest.json	324f0a0b77c37ef
-142	288	0	PepperFlash/libpepflashplayer.so	1e2c2b7845a4d4fe
-287	290	0	obj/third_party/angle/src/copy_scripts.actions_rules_copies.stamp	b211d373de72f455
-`
-
-	stepsTestCase = []Step{
-		Step{
-			Start:   76 * time.Millisecond,
-			End:     187 * time.Millisecond,
-			Out:     "resources/inspector/devtools_extension_api.js",
-			CmdHash: "75430546595be7c2",
-		},
-		Step{
-			Start:   80 * time.Millisecond,
-			End:     284 * time.Millisecond,
-			Out:     "gen/autofill_regex_constants.cc",
-			CmdHash: "fa33c8d7ce1d8791",
-		},
-		Step{
-			Start:   78 * time.Millisecond,
-			End:     286 * time.Millisecond,
-			Out:     "gen/angle/commit_id.py",
-			CmdHash: "4ede38e2c1617d8c",
-		},
-		Step{
-			Start:   79 * time.Millisecond,
-			End:     287 * time.Millisecond,
-			Out:     "gen/angle/copy_compiler_dll.bat",
-			CmdHash: "9fb635ad5d2c1109",
-		},
-		Step{
-			Start:   141 * time.Millisecond,
-			End:     287 * time.Millisecond,
-			Out:     "PepperFlash/manifest.json",
-			CmdHash: "324f0a0b77c37ef",
-		},
-		Step{
-			Start:   142 * time.Millisecond,
-			End:     288 * time.Millisecond,
-			Out:     "PepperFlash/libpepflashplayer.so",
-			CmdHash: "1e2c2b7845a4d4fe",
-		},
-		Step{
-			Start:   287 * time.Millisecond,
-			End:     290 * time.Millisecond,
-			Out:     "obj/third_party/angle/src/copy_scripts.actions_rules_copies.stamp",
-			CmdHash: "b211d373de72f455",
-		},
-	}
-
-	stepsSorted = []Step{
-		Step{
-			Start:   76 * time.Millisecond,
-			End:     187 * time.Millisecond,
-			Out:     "resources/inspector/devtools_extension_api.js",
-			CmdHash: "75430546595be7c2",
-		},
-		Step{
-			Start:   78 * time.Millisecond,
-			End:     286 * time.Millisecond,
-			Out:     "gen/angle/commit_id.py",
-			CmdHash: "4ede38e2c1617d8c",
-		},
-		Step{
-			Start:   79 * time.Millisecond,
-			End:     287 * time.Millisecond,
-			Out:     "gen/angle/copy_compiler_dll.bat",
-			CmdHash: "9fb635ad5d2c1109",
-		},
-		Step{
-			Start:   80 * time.Millisecond,
-			End:     284 * time.Millisecond,
-			Out:     "gen/autofill_regex_constants.cc",
-			CmdHash: "fa33c8d7ce1d8791",
-		},
-		Step{
-			Start:   141 * time.Millisecond,
-			End:     287 * time.Millisecond,
-			Out:     "PepperFlash/manifest.json",
-			CmdHash: "324f0a0b77c37ef",
-		},
-		Step{
-			Start:   142 * time.Millisecond,
-			End:     288 * time.Millisecond,
-			Out:     "PepperFlash/libpepflashplayer.so",
-			CmdHash: "1e2c2b7845a4d4fe",
-		},
-		Step{
-			Start:   287 * time.Millisecond,
-			End:     290 * time.Millisecond,
-			Out:     "obj/third_party/angle/src/copy_scripts.actions_rules_copies.stamp",
-			CmdHash: "b211d373de72f455",
-		},
-	}
-
-	metadataTestCase = Metadata{
-		Platform: "linux",
-		Argv:     []string{"../../../scripts/slave/compile.py", "--target", "Release", "--clobber", "--compiler=goma", "--", "all"},
-		Cwd:      "/b/build/slave/Linux_x64/build/src",
-		Compiler: "goma",
-		Cmdline:  []string{"ninja", "-C", "/b/build/slave/Linux_x64/build/src/out/Release", "all", "-j50"},
-		Exit:     0,
-		Env: map[string]string{
-			"LANG":    "en_US.UTF-8",
-			"SHELL":   "/bin/bash",
-			"HOME":    "/home/chrome-bot",
-			"PWD":     "/b/build/slave/Linux_x64/build",
-			"LOGNAME": "chrome-bot",
-			"USER":    "chrome-bot",
-			"PATH":    "/home/chrome-bot/slavebin:/b/depot_tools:/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin",
-		},
-		CompilerProxyInfo: "/tmp/compiler_proxy.build48-m1.chrome-bot.log.INFO.20140907-203827.14676",
-	}
-)
-
-func TestStepsSort(t *testing.T) {
-	steps := append([]Step{}, stepsTestCase...)
-	sort.Sort(Steps(steps))
-	if !reflect.DeepEqual(steps, stepsSorted) {
-		t.Errorf("sort Steps=%v; want=%v", steps, stepsSorted)
-	}
-}
-
-func TestStepsReverse(t *testing.T) {
-	steps := []Step{
-		Step{Out: "0"},
-		Step{Out: "1"},
-		Step{Out: "2"},
-		Step{Out: "3"},
-	}
-	Steps(steps).Reverse()
-	want := []Step{
-		Step{Out: "3"},
-		Step{Out: "2"},
-		Step{Out: "1"},
-		Step{Out: "0"},
-	}
-	if !reflect.DeepEqual(steps, want) {
-		t.Errorf("steps.Reverse=%v; want=%v", steps, want)
-	}
-}
-
-func TestParseBadVersion(t *testing.T) {
-	_, err := Parse(".ninja_log", strings.NewReader(`# ninja log v4
-0	1	0	foo	touch foo
-`))
-	if err == nil {
-		t.Error("Parse()=_, <nil>; want=_, error")
-	}
-}
-
-func TestParseSimple(t *testing.T) {
-	njl, err := Parse(".ninja_log", strings.NewReader(logTestCase))
-	if err != nil {
-		t.Errorf(`Parse()=_, %v; want=_, <nil>`, err)
-	}
-
-	want := &NinjaLog{
-		Filename: ".ninja_log",
-		Start:    1,
-		Steps:    stepsTestCase,
-	}
-	if !reflect.DeepEqual(njl, want) {
-		t.Errorf("Parse()=%v; want=%v", njl, want)
-	}
-}
-
-func TestParseEmptyLine(t *testing.T) {
-	njl, err := Parse(".ninja_log", strings.NewReader(logTestCase+"\n"))
-	if err != nil {
-		t.Errorf(`Parse()=_, %v; want=_, <nil>`, err)
-	}
-	want := &NinjaLog{
-		Filename: ".ninja_log",
-		Start:    1,
-		Steps:    stepsTestCase,
-	}
-	if !reflect.DeepEqual(njl, want) {
-		t.Errorf("Parse()=%v; want=%v", njl, want)
-	}
-}
-
-func TestParseLast(t *testing.T) {
-	njl, err := Parse(".ninja_log", strings.NewReader(`# ninja log v5
-1020807	1020916	0	chrome.1	e101fd46be020cfc
-84	9489	0	gen/libraries.cc	9001f3182fa8210e
-1024369	1041522	0	chrome	aee9d497d56c9637
-76	187	0	resources/inspector/devtools_extension_api.js	75430546595be7c2
-80	284	0	gen/autofill_regex_constants.cc	fa33c8d7ce1d8791
-78	286	0	gen/angle/commit_id.py	4ede38e2c1617d8c
-79	287	0	gen/angle/copy_compiler_dll.bat	9fb635ad5d2c1109
-141	287	0	PepperFlash/manifest.json	324f0a0b77c37ef
-142	288	0	PepperFlash/libpepflashplayer.so	1e2c2b7845a4d4fe
-287	290	0	obj/third_party/angle/src/copy_scripts.actions_rules_copies.stamp	b211d373de72f455
-`))
-	if err != nil {
-		t.Errorf(`Parse()=_, %v; want=_, <nil>`, err)
-	}
-
-	want := &NinjaLog{
-		Filename: ".ninja_log",
-		Start:    4,
-		Steps:    stepsTestCase,
-	}
-	if !reflect.DeepEqual(njl, want) {
-		t.Errorf("Parse()=%v; want=%v", njl, want)
-	}
-}
-
-func TestParseMetadata(t *testing.T) {
-	njl, err := Parse(".ninja_log", strings.NewReader(`# ninja log v5
-1020807	1020916	0	chrome.1	e101fd46be020cfc
-84	9489	0	gen/libraries.cc	9001f3182fa8210e
-1024369	1041522	0	chrome	aee9d497d56c9637
-76	187	0	resources/inspector/devtools_extension_api.js	75430546595be7c2
-80	284	0	gen/autofill_regex_constants.cc	fa33c8d7ce1d8791
-78	286	0	gen/angle/commit_id.py	4ede38e2c1617d8c
-79	287	0	gen/angle/copy_compiler_dll.bat	9fb635ad5d2c1109
-141	287	0	PepperFlash/manifest.json	324f0a0b77c37ef
-142	288	0	PepperFlash/libpepflashplayer.so	1e2c2b7845a4d4fe
-287	290	0	obj/third_party/angle/src/copy_scripts.actions_rules_copies.stamp	b211d373de72f455
-
-# end of ninja log
-{"platform": "linux", "argv": ["../../../scripts/slave/compile.py", "--target", "Release", "--clobber", "--compiler=goma", "--", "all"], "cmdline": ["ninja", "-C", "/b/build/slave/Linux_x64/build/src/out/Release", "all", "-j50"], "exit": 0, "env": {"LANG": "en_US.UTF-8", "SHELL": "/bin/bash", "HOME": "/home/chrome-bot", "PWD": "/b/build/slave/Linux_x64/build", "LOGNAME": "chrome-bot", "USER": "chrome-bot", "PATH": "/home/chrome-bot/slavebin:/b/depot_tools:/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin" }, "compiler_proxy_info": "/tmp/compiler_proxy.build48-m1.chrome-bot.log.INFO.20140907-203827.14676", "cwd": "/b/build/slave/Linux_x64/build/src", "compiler": "goma"}
-`))
-	if err != nil {
-		t.Errorf(`Parse()=_, %#v; want=_, <nil>`, err)
-	}
-
-	want := &NinjaLog{
-		Filename: ".ninja_log",
-		Start:    4,
-		Steps:    stepsTestCase,
-		Metadata: metadataTestCase,
-	}
-	njl.Metadata.Raw = ""
-	if !reflect.DeepEqual(njl, want) {
-		t.Errorf("Parse()=%#v; want=%#v", njl, want)
-	}
-}
-
-func TestParseBadMetadata(t *testing.T) {
-	// https://bugs.chromium.org/p/chromium/issues/detail?id=667571
-	njl, err := Parse(".ninja_log", strings.NewReader(`# ninja log v5
-1020807	1020916	0	chrome.1	e101fd46be020cfc
-84	9489	0	gen/libraries.cc	9001f3182fa8210e
-1024369	1041522	0	chrome	aee9d497d56c9637
-76	187	0	resources/inspector/devtools_extension_api.js	75430546595be7c2
-80	284	0	gen/autofill_regex_constants.cc	fa33c8d7ce1d8791
-78	286	0	gen/angle/commit_id.py	4ede38e2c1617d8c
-79	287	0	gen/angle/copy_compiler_dll.bat	9fb635ad5d2c1109
-141	287	0	PepperFlash/manifest.json	324f0a0b77c37ef
-142	288	0	PepperFlash/libpepflashplayer.so	1e2c2b7845a4d4fe
-287	290	0	obj/third_party/angle/src/copy_scripts.actions_rules_copies.stamp	b211d373de72f455
-# end of ninja log
-{"platform": "linux", "argv": ["/b/build/scripts/slave/upload_goma_logs.py", "--upload-compiler-proxy-info", "--json-status", "/b/build/slave/cache/cipd/goma/jsonstatus", "--ninja-log-outdir", "/b/build/slave/pdfium/build/pdfium/out/debug_xfa_v8", "--ninja-log-compiler", "unknown", "--ninja-log-command", "['ninja', '-C', Path('checkout', 'out','debug_xfa_v8'), '-j', 80]", "--ninja-log-exit-status", "0", "--goma-stats-file", "/b/build/slave/pdfium/.recipe_runtime/tmpOgwx97/build_data/goma_stats_proto", "--goma-crash-report-id-file", "/b/build/slave/pdfium/.recipe_runtime/tmpOgwx97/build_data/crash_report_id_file", "--build-data-dir", "/b/build/slave/pdfium/.recipe_runtime/tmpOgwx97/build_data", "--buildbot-buildername", "linux_xfa", "--buildbot-mastername", "tryserver.client.pdfium", "--buildbot-slavename", "slave1386-c4"], "cmdline": "['ninja', '-C', Path('checkout','out','debug_xfa_v8'), '-j', 80]", "exit": 0, "env": {"GOMA_SERVICE_ACCOUNT_JSON_FILE": "/creds/service_accounts/service-account-goma-client.json", "BUILDBOT_BUILDERNAME": "linux_xfa", "USER": "chrome-bot", "HOME": "/home/chrome-bot", "BOTO_CONFIG": "/b/build/scripts/slave/../../site_config/.boto", "PATH": "/home/chrome-bot/slavebin:/b/depot_tools:/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin", "PYTHONUNBUFFERED": "1", "BUILDBOT_BUILDBOTURL": "https://build.chromium.org/p/tryserver.client.pdfium/", "DISPLAY": ":0.0", "LANG": "en_US.UTF-8", "BUILDBOT_BLAMELIST": "[u'dsinclair@chromium.org']", "BUILDBOT_MASTERNAME": "tryserver.client.pdfium", "GOMACTL_CRASH_REPORT_ID_FILE": "/b/build/slave/pdfium/.recipe_runtime/tmpOgwx97/build_data/crash_report_id_file", "USERNAME": "chrome-bot", "BUILDBOT_GOT_REVISION": "None", "PYTHONPATH": "/b/build/site_config:/b/build/scripts:/b/build/scripts/release:/b/build/third_party:/b/build/third_party/requests_2_10_0:/b/build_internal/site_config:/b/build_internal/symsrc:/b/build/slave:/b/build/third_party/buildbot_slave_8_4:/b/build/third_party/twisted_10_2:", "BUILDBOT_SCHEDULER": "None", "BUILDBOT_REVISION": "", "AWS_CREDENTIAL_FILE": "/b/build/scripts/slave/../../site_config/.boto", "CHROME_HEADLESS": "1", "BUILDBOT_BRANCH": "", "GIT_USER_AGENT": "linux2 git/2.10.2 slave1386-c4.c.chromecompute.google.com.internal", "TESTING_SLAVENAME": "slave1386-c4", "GOMA_DUMP_STATS_FILE": "/b/build/slave/pdfium/.recipe_runtime/tmpOgwx97/build_data/goma_stats_proto", "BUILDBOT_BUILDNUMBER": "2937", "PWD": "/b/build/slave/pdfium/build", "BUILDBOT_SLAVENAME": "slave1386-c4", "BUILDBOT_CLOBBER": "", "PAGER": "cat"}, "compiler_proxy_info": "/tmp/compiler_proxy.slave1386-c4.chrome-bot.log.INFO.20161121-165459.5790", "cwd": "/b/build/slave/pdfium/build", "compiler": "unknown"}
-`))
-	if err != nil {
-		t.Errorf(`Parse()=_, %#v; want=_, <nil>`, err)
-	}
-
-	if njl.Metadata.Error == "" {
-		t.Errorf("Parse().Metadata.Error='', want some error")
-	}
-	njl.Metadata = Metadata{}
-
-	want := &NinjaLog{
-		Filename: ".ninja_log",
-		Start:    4,
-		Steps:    stepsTestCase,
-	}
-	if !reflect.DeepEqual(njl, want) {
-		t.Errorf("Parse()=%#v; want=%#v", njl, want)
-	}
-}
-
-func TestDump(t *testing.T) {
-	var b bytes.Buffer
-	err := Dump(&b, stepsTestCase)
-	if err != nil {
-		t.Errorf("Dump()=%v; want=<nil>", err)
-	}
-	if b.String() != logTestCase {
-		t.Errorf("Dump %q; want %q", b.String(), logTestCase)
-	}
-}
-
-func TestDedup(t *testing.T) {
-	steps := append([]Step{}, stepsTestCase...)
-	for _, out := range []string{
-		"gen/ui/keyboard/webui/keyboard.mojom.cc",
-		"gen/ui/keyboard/webui/keyboard.mojom.h",
-		"gen/ui/keyboard/webui/keyboard.mojom.js",
-		"gen/ui/keyboard/webui/keyboard.mojom-internal.h",
-	} {
-		steps = append(steps, Step{
-			Start:   302 * time.Millisecond,
-			End:     5764 * time.Millisecond,
-			Out:     out,
-			CmdHash: "a551cc46f8c21e5a",
-		})
-	}
-	got := Dedup(steps)
-	want := append([]Step{}, stepsSorted...)
-	want = append(want, Step{
-		Start: 302 * time.Millisecond,
-		End:   5764 * time.Millisecond,
-		Out:   "gen/ui/keyboard/webui/keyboard.mojom-internal.h",
-		Outs: []string{
-			"gen/ui/keyboard/webui/keyboard.mojom.cc",
-			"gen/ui/keyboard/webui/keyboard.mojom.h",
-			"gen/ui/keyboard/webui/keyboard.mojom.js",
-		},
-		CmdHash: "a551cc46f8c21e5a",
-	})
-	if !reflect.DeepEqual(got, want) {
-		t.Errorf("Dedup=%v; want=%v", got, want)
-	}
-}
-
-func TestFlow(t *testing.T) {
-	steps := append([]Step{}, stepsTestCase...)
-	steps = append(steps, Step{
-		Start:   187 * time.Millisecond,
-		End:     21304 * time.Millisecond,
-		Out:     "obj/third_party/pdfium/core/src/fpdfdoc/fpdfdoc.doc_formfield.o",
-		CmdHash: "2ac7111aa1ae86af",
-	})
-
-	flow := Flow(steps)
-
-	want := [][]Step{
-		[]Step{
-			Step{
-				Start:   76 * time.Millisecond,
-				End:     187 * time.Millisecond,
-				Out:     "resources/inspector/devtools_extension_api.js",
-				CmdHash: "75430546595be7c2",
-			},
-			Step{
-				Start:   187 * time.Millisecond,
-				End:     21304 * time.Millisecond,
-				Out:     "obj/third_party/pdfium/core/src/fpdfdoc/fpdfdoc.doc_formfield.o",
-				CmdHash: "2ac7111aa1ae86af",
-			},
-		},
-		[]Step{
-			Step{
-				Start:   78 * time.Millisecond,
-				End:     286 * time.Millisecond,
-				Out:     "gen/angle/commit_id.py",
-				CmdHash: "4ede38e2c1617d8c",
-			},
-			Step{
-				Start:   287 * time.Millisecond,
-				End:     290 * time.Millisecond,
-				Out:     "obj/third_party/angle/src/copy_scripts.actions_rules_copies.stamp",
-				CmdHash: "b211d373de72f455",
-			},
-		},
-		[]Step{
-			Step{
-				Start:   79 * time.Millisecond,
-				End:     287 * time.Millisecond,
-				Out:     "gen/angle/copy_compiler_dll.bat",
-				CmdHash: "9fb635ad5d2c1109",
-			},
-		},
-		[]Step{
-			Step{
-				Start:   80 * time.Millisecond,
-				End:     284 * time.Millisecond,
-				Out:     "gen/autofill_regex_constants.cc",
-				CmdHash: "fa33c8d7ce1d8791",
-			},
-		},
-		[]Step{
-			Step{
-				Start:   141 * time.Millisecond,
-				End:     287 * time.Millisecond,
-				Out:     "PepperFlash/manifest.json",
-				CmdHash: "324f0a0b77c37ef",
-			},
-		},
-		[]Step{
-			Step{
-				Start:   142 * time.Millisecond,
-				End:     288 * time.Millisecond,
-				Out:     "PepperFlash/libpepflashplayer.so",
-				CmdHash: "1e2c2b7845a4d4fe",
-			},
-		},
-	}
-
-	if !reflect.DeepEqual(flow, want) {
-		t.Errorf("Flow()=%v; want=%v", flow, want)
-	}
-}
-
-func TestWeightedTime(t *testing.T) {
-	steps := []Step{
-		Step{
-			Start:   0 * time.Millisecond,
-			End:     3 * time.Millisecond,
-			Out:     "target-a",
-			CmdHash: "hash-target-a",
-		},
-		Step{
-			Start:   2 * time.Millisecond,
-			End:     5 * time.Millisecond,
-			Out:     "target-b",
-			CmdHash: "hash-target-b",
-		},
-		Step{
-			Start:   2 * time.Millisecond,
-			End:     8 * time.Millisecond,
-			Out:     "target-c",
-			CmdHash: "hash-target-c",
-		},
-		Step{
-			Start:   2 * time.Millisecond,
-			End:     3 * time.Millisecond,
-			Out:     "target-d",
-			CmdHash: "hash-target-d",
-		},
-	}
-
-	// 0 1 2 3 4 5 6 7 8
-	// +-+-+-+-+-+-+-+-+
-	// <--A-->
-	//     <--B-->
-	//     <------C---->
-	//     <D>
-	got := WeightedTime(steps)
-	want := map[string]time.Duration{
-		"target-a": 2*time.Millisecond + 1*time.Millisecond/4,
-		"target-b": 1*time.Millisecond/4 + 2*time.Millisecond/2,
-		"target-c": 1*time.Millisecond/4 + 2*time.Millisecond/2 + 3*time.Millisecond,
-		"target-d": 1 * time.Millisecond / 4,
-	}
-	if !reflect.DeepEqual(got, want) {
-		t.Errorf("WeightedTime(%v)=%v; want=%v", steps, got, want)
-	}
-}
-
-func BenchmarkParse(b *testing.B) {
-	data, err := ioutil.ReadFile("testdata/ninja_log")
-	if err != nil {
-		b.Errorf(`ReadFile("testdata/ninja_log")=_, %v; want_, <nil>`, err)
-	}
-
-	for i := 0; i < b.N; i++ {
-		_, err := Parse(".ninja_log", bytes.NewReader(data))
-		if err != nil {
-			b.Errorf(`Parse()=_, %v; want=_, <nil>`, err)
-		}
-	}
-}
-
-func BenchmarkDedup(b *testing.B) {
-	data, err := ioutil.ReadFile("testdata/ninja_log")
-	if err != nil {
-		b.Errorf(`ReadFile("testdata/ninja_log")=_, %v; want_, <nil>`, err)
-	}
-
-	njl, err := Parse(".ninja_log", bytes.NewReader(data))
-	if err != nil {
-		b.Errorf(`Parse()=_, %v; want=_, <nil>`, err)
-	}
-	b.ResetTimer()
-	for i := 0; i < b.N; i++ {
-		steps := make([]Step, len(njl.Steps))
-		copy(steps, njl.Steps)
-		Dedup(steps)
-	}
-}
-
-func BenchmarkFlow(b *testing.B) {
-	data, err := ioutil.ReadFile("testdata/ninja_log")
-	if err != nil {
-		b.Errorf(`ReadFile("testdata/ninja_log")=_, %v; want_, <nil>`, err)
-	}
-
-	njl, err := Parse(".ninja_log", bytes.NewReader(data))
-	if err != nil {
-		b.Errorf(`Parse()=_, %v; want=_, <nil>`, err)
-	}
-	steps := Dedup(njl.Steps)
-	b.ResetTimer()
-	for i := 0; i < b.N; i++ {
-		flowInput := make([]Step, len(steps))
-		copy(flowInput, steps)
-		Flow(flowInput)
-	}
-}
-
-func BenchmarkToTraces(b *testing.B) {
-	data, err := ioutil.ReadFile("testdata/ninja_log")
-	if err != nil {
-		b.Errorf(`ReadFile("testdata/ninja_log")=_, %v; want_, <nil>`, err)
-	}
-
-	njl, err := Parse(".ninja_log", bytes.NewReader(data))
-	if err != nil {
-		b.Errorf(`Parse()=_, %v; want=_, <nil>`, err)
-	}
-	steps := Dedup(njl.Steps)
-	flow := Flow(steps)
-	b.ResetTimer()
-	for i := 0; i < b.N; i++ {
-		ToTraces(flow, 1)
-	}
-}
-
-func BenchmarkDedupFlowToTraces(b *testing.B) {
-	data, err := ioutil.ReadFile("testdata/ninja_log")
-	if err != nil {
-		b.Errorf(`ReadFile("testdata/ninja_log")=_, %v; want_, <nil>`, err)
-	}
-
-	for i := 0; i < b.N; i++ {
-		njl, err := Parse(".ninja_log", bytes.NewReader(data))
-		if err != nil {
-			b.Errorf(`Parse()=_, %v; want=_, <nil>`, err)
-		}
-
-		steps := Dedup(njl.Steps)
-		flow := Flow(steps)
-		ToTraces(flow, 1)
-	}
-}
diff --git a/build/ninjalog/testdata/ninja_log b/build/ninjalog/testdata/ninja_log
deleted file mode 100644
index ac90cab..0000000
--- a/build/ninjalog/testdata/ninja_log
+++ /dev/null
@@ -1,326 +0,0 @@
-# ninja log v5
-932	1887	0	obj/aura_builder.stamp	7f299500e7cc72e4
-933	1887	0	obj/chromium_builder_tests.stamp	3b269cc5e106d1cb
-935	1889	0	obj/chromium_swarm_tests.stamp	228817dbc2838ed
-935	1889	0	obj/breakpad/stackwalk_common/ia32_operand.o	e910d286882099db
-936	1890	0	obj/breakpad/stackwalk_common/ia32_implicit.o	5f70baee81295512
-936	1891	0	obj/breakpad/stackwalk_common/ia32_insn.o	f5a4396053248fe2
-940	1892	0	obj/breakpad/stackwalk_common/ia32_settings.o	defcb1700387b35b
-941	1900	0	obj/breakpad/stackwalk_common/x86_imm.o	a9d30af1b7950290
-944	1901	0	obj/build/config/posix/posix.stamp	6d0ca2a0eaf18f67
-944	1902	0	obj/build/config/nacl/nacl_base.stamp	ef27934affc9c112
-945	1903	0	obj/build/config/sanitizers/deps_no_options.stamp	5a49d397d6442ac3
-947	1903	0	obj/build/config/linux/linux.stamp	f77230b5eb5afaf2
-947	1910	0	obj/build/config/linux/gtk3/gtk3.stamp	9b784fd2e50164d4
-947	1910	0	obj/build/config/linux/gtk3/gtkprint3.stamp	630941a61f5a6923
-948	1914	0	obj/base/base_static/switches.o	b013922ef6f8aaab
-948	1915	0	gen/base/histogram_unittest_nc.cc	dd29c0c48a525644
-949	1915	0	gen/base/callback_unittest_nc.cc	475066177ce401ff
-949	1916	0	gen/base/callback_list_unittest_nc.cc	16824df464b694f
-953	1920	0	obj/base/test/native_library_test_utils/native_library_test_utils.o	c33b12415d139603
-953	1920	0	obj/base/allocator/tcmalloc/low_level_alloc.o	1fc5cc88e3e16e23
-957	1921	0	obj/base/allocator/tcmalloc/sysinfo.o	45a91a4d87d1aa9e
-957	1922	0	obj/base/allocator/tcmalloc/vdso_support.o	3e46bc0f32a5f33c
-962	1922	0	obj/base/allocator/tcmalloc/common.o	13a060d08e39d509
-962	1923	0	obj/base/allocator/tcmalloc/free_list.o	4e42356197e89a16
-965	1925	0	obj/base/allocator/tcmalloc/malloc_extension.o	76679f18029232e7
-965	1925	0	obj/base/allocator/tcmalloc/malloc_hook.o	c627b7675ebfb1b0
-968	1925	0	obj/base/allocator/tcmalloc/page_heap.o	d94de6badd6f30e6
-968	1926	0	obj/base/allocator/tcmalloc/raw_printer.o	9a2e6e0c1a365182
-968	1927	0	obj/base/allocator/tcmalloc/sampler.o	ab3fb9ade346e5bc
-969	1927	0	obj/base/allocator/tcmalloc/stacktrace.o	7ac392099df854df
-969	1928	0	obj/base/allocator/tcmalloc/static_vars.o	5a7c9b34e682f72f
-973	1929	0	obj/base/allocator/tcmalloc/system-alloc.o	f7e40e31b72b4fed
-977	1929	0	gen/base/debug/debugging_flags.h	9596e291177bcaa7
-977	1932	0	obj/base/base_unittests_bundle_data.stamp	ccc2010a4884995f
-980	1932	0	obj/base/build_date.inputdeps.stamp	44b53a9dd8e06c36
-980	1932	0	gen/base/allocator/features.h	f9894386c01c41c2
-980	1935	0	obj/base/allocator/tcmalloc/spinlock_internal.o	52eb3163ecfc72c
-980	1935	0	obj/base/allocator/tcmalloc/abort.o	318d8d2c8df20f6c
-987	1935	0	obj/base/allocator/tcmalloc/atomicops-internals-x86.o	3d3c2a4b6e9e91fa
-1005	1936	0	obj/base/allocator/tcmalloc/logging.o	861b3c21231da430
-1023	1937	0	obj/base/third_party/xdg_mime/xdg_mime/xdgmimeicon.o	64baf98d444024dd
-1029	1937	0	obj/base/third_party/libevent/libevent/strlcpy.o	be9686387d30188e
-1171	1938	0	minidump_fuzzer.dict	2f759dc54b10c5a5
-1195	1939	0	minidump_fuzzer.options	12fb1704c79cd108
-1204	1940	0	gen/library_loaders/libgio.h	3f42a994f91c90ad
-1204	1940	0	gen/library_loaders/libgio_loader.cc	3f42a994f91c90ad
-1220	1944	0	obj/breakpad/stackwalk_common/dump_object.o	e6678006ee215cf6
-1253	1944	0	obj/breakpad/stackwalk_common/stackwalker_sparc.o	634f5cec2de7ad50
-1253	1944	0	chrome.VisualElementsManifest.xml	11019a3b23390133
-1258	1944	0	gen/library_loaders/libudev0.h	6e9ea2f9a6d08cc5
-1258	1944	0	gen/library_loaders/libudev0_loader.cc	6e9ea2f9a6d08cc5
-1259	1945	0	gen/library_loaders/libudev1.h	5cff2c8da0269aa3
-1259	1945	0	gen/library_loaders/libudev1_loader.cc	5cff2c8da0269aa3
-1259	1945	0	obj/build/util/chrome_version_json.inputdeps.stamp	4a98b379bd3a95e1
-1259	1945	0	obj/build/util/webkit_version.inputdeps.stamp	b4f2c6e2e759ee6d
-1259	1945	0	obj/build/win/default_exe_manifest.stamp	5749e6404e11fdd6
-1259	1947	0	obj/cc/ipc/interfaces__is_mojom.stamp	4f4afff0f6093dda
-1259	1948	0	obj/chrome/browser/preferences_manifest.inputdeps.stamp	373d9f2344667069
-1261	1948	0	obj/cc/ipc/test_interfaces__is_mojom.stamp	11f28ad8101031f9
-1268	1948	0	product_logo_48.png	b4486b27ac8de19e
-1269	1950	0	chrome-wrapper	c30fdbd2f2925001
-1270	1951	0	obj/chrome/manpage.inputdeps.stamp	307252fd80755cae
-1271	1951	0	xdg-mime	472f1619df53cd2b
-1272	1951	0	xdg-settings	325658a140ad44c1
-1272	1952	0	obj/chrome/app/chrome_content_gpu_manifest__is_service_manifest.stamp	bc54c4907b6aae93
-1273	1952	0	obj/chrome/app/chrome_content_browser_manifest_overlay__is_service_manifest.stamp	f6b6ad1752883df7
-1273	1952	0	obj/chrome/app/chrome_content_browser_manifest__is_service_manifest.stamp	679b1f0fffefa65f
-1273	1954	0	obj/chrome/app/chrome_content_gpu_manifest_overlay.inputdeps.stamp	87835f17ee6d9ad8
-1273	1954	0	obj/chrome/app/chrome_content_gpu_manifest_overlay__is_service_manifest.stamp	b8219a49d409a88e
-1274	1955	0	obj/chrome/app/chrome_content_packaged_services_manifest__is_service_manifest.stamp	162af6abc2708239
-1274	1956	0	obj/chrome/app/chrome_content_packaged_services_manifest_for_mash__is_service_manifest.stamp	b1395a7bf61f2e1a
-1274	1956	0	obj/chrome/app/chrome_content_packaged_services_manifest_overlay__is_service_manifest.stamp	da61f69dd6c92351
-1274	1956	0	obj/chrome/app/chrome_content_packaged_services_manifest_overlay_for_mash__is_service_manifest.stamp	2a19ea80ead0568a
-1275	1957	0	obj/chrome/app/chrome_content_plugin_manifest_overlay.inputdeps.stamp	a6733dbc50dc0b4
-1275	1957	0	obj/chrome/app/chrome_content_plugin_manifest__is_service_manifest.stamp	df4185965232a7e6
-1275	1957	0	obj/chrome/app/chrome_content_plugin_manifest_overlay__is_service_manifest.stamp	bd0fb97237c5074d
-1275	1957	0	obj/chrome/app/chrome_content_renderer_manifest_overlay.inputdeps.stamp	1605b840beae701c
-1275	1958	0	obj/chrome/app/chrome_content_renderer_manifest__is_service_manifest.stamp	5173642d314f2d18
-1276	1959	0	obj/chrome/app/chrome_content_renderer_manifest_overlay__is_service_manifest.stamp	dab5a7d3eaadd85a
-1276	1960	0	obj/chrome/app/chrome_content_utility_manifest_overlay.inputdeps.stamp	bb61a6eae7e90d98
-1276	1962	0	obj/chrome/app/chrome_content_utility_manifest__is_service_manifest.stamp	d102efc7228156fc
-1276	1962	0	obj/chrome/app/chrome_content_utility_manifest_overlay__is_service_manifest.stamp	e7c510cfbe2d9088
-1277	1962	0	obj/chrome/app/chrome_dll_resources.stamp	608c7174590ae48c
-1280	1963	0	obj/chrome/app/chrome_manifest.inputdeps.stamp	26a230f094ee6e25
-1281	1964	0	obj/chrome/app/chrome_manifest__is_service_manifest.stamp	392035a75b781481
-1281	1965	0	obj/chrome/app/command_ids.stamp	a2bf13bf4ee69ea3
-1282	1966	0	obj/chrome/browser/ui/webui/omnibox/mojo_bindings__check_deps_are_all_mojom.stamp	bd7ff06038f3ec7f
-1282	1966	0	obj/chrome/app/vector_icons/chrome_vector_icons.inputdeps.stamp	f47ee6fec73e05b0
-1282	1967	0	cast_remoting_connector_fuzzer.options	930134b769ba9f73
-1282	1967	0	obj/chrome/browser/media/router/mojo_bindings__is_mojom.stamp	466fc9a439fbb2ec
-1283	1970	0	obj/chrome/browser/media/router/mojo_bindings_common__is_mojom.stamp	8b490270cdafecf
-1283	1971	0	obj/chrome/browser/media/router/mojo_test_interfaces__is_mojom.stamp	4c893ba3099cdaf7
-1283	1971	0	obj/chrome/browser/resources/md_downloads/vulcanize.inputdeps.stamp	b463bc7f9833e4eb
-1283	1973	0	obj/chrome/browser/resources/md_history/vulcanize_app.inputdeps.stamp	5da5a62ad1dcb31f
-1283	1975	0	obj/chrome/browser/resources/md_history/vulcanize_lazy_load.inputdeps.stamp	3962d76366774295
-1284	1976	0	obj/components/domain_reliability/bake_in_configs.inputdeps.stamp	7fb2b7da8b55926b
-1284	1976	0	obj/chrome/browser/chrome_internal_resources_gen.stamp	1eae97aecd17386c
-1284	1976	0	obj/chrome/browser/preferences_manifest__is_service_manifest.stamp	33d9abfb726981c4
-1284	1978	0	obj/chrome/browser/theme_properties.stamp	6aa373278541af71
-1288	1978	0	gen/chrome/common/features.h	1380d988824bf2ae
-1289	1982	0	obj/chrome/common/mojo_bindings__is_mojom.stamp	58677facfc55a6c3
-1289	1983	0	obj/chrome/common/instant_mojom__is_mojom.stamp	eca52cd264c479c6
-1289	1983	0	obj/chrome/browser/ui/webui/engagement/mojo_bindings__is_mojom.stamp	9f26b0e2b5750aa6
-1289	1984	0	obj/chrome/browser/ui/webui/omnibox/mojo_bindings__type_mappings.inputdeps.stamp	a92cfc87812fc28e
-1289	1984	0	obj/chrome/browser/ui/webui/omnibox/mojo_bindings__is_mojom.stamp	1f292b08a229fcff
-1289	1984	0	obj/chrome/browser/ui/webui/omnibox/mojo_bindings_blink__type_mappings.inputdeps.stamp	a7ef1a514c41174f
-1289	1985	0	obj/chrome/browser/ui/webui/usb_internals/mojo_bindings__is_mojom.stamp	9f2140f824793e44
-1290	1986	0	obj/chrome/common/extensions/mojo_bindings__is_mojom.stamp	697cc1f72aa3c9e9
-1290	1987	0	obj/chrome/common/version_header_action.inputdeps.stamp	6b9baa8063a6a905
-1291	1987	0	obj/chrome/common/extensions/api/api_bundle_generator_schema.inputdeps.stamp	417a733a1b1dc1b8
-1291	1988	0	obj/chrome/common/extensions/api/api_schema_generator.inputdeps.stamp	c78d2148e660f04b
-1291	1990	0	obj/chrome/common/extensions/api/api_registration_bundle_generator_registration.inputdeps.stamp	d87a40660f2526e8
-1292	1990	0	obj/chrome/common/importer/interfaces__is_mojom.stamp	fbba48a63930fad8
-1292	1991	0	obj/components/password_manager/core/browser/unit_tests_bundle_data.stamp	a1221f6a41bbc716
-1292	1993	0	obj/components/visitedlink/common/interfaces__is_mojom.stamp	2c49363bec81305d
-1292	1994	0	obj/components/visitedlink/common/interfaces__type_mappings.inputdeps.stamp	a0d0f67f50be78ae
-1294	1994	0	obj/chrome/installer/installer.stamp	fdbc934e2b94627c
-1294	1996	0	obj/chrome/installer/util/generate_strings.inputdeps.stamp	c21387fd9dd578b7
-1294	1996	0	obj/components/payments/content/payment_app__is_mojom.stamp	a8f1f182179a2e4a
-1294	1996	0	obj/components/autofill/core/browser/unit_tests_bundle_data.stamp	76813fb9ac300ccd
-1295	1997	0	obj/components/dom_distiller/core/unit_tests_bundle_data.stamp	6a0f970508ef2822
-1295	1998	0	obj/mash/public/interfaces/interfaces__type_mappings.inputdeps.stamp	8fc53baa86393f2c
-1295	1999	0	obj/components/dom_distiller/content/common/mojo_bindings__type_mappings.inputdeps.stamp	7cf1b8d92cfbe99d
-1295	2002	0	obj/chrome/test/test.stamp	740bf2e94b308511
-1295	2005	0	obj/extensions/browser/api/api_registration_bundle_generator_registration.inputdeps.stamp	16ba782e33efde8a
-1295	2009	0	obj/components/autofill/content/common/mojo_interfaces__is_mojom.stamp	9e5b625f65094c9f
-1295	2009	0	obj/components/autofill/content/common/mojo_types__is_mojom.stamp	dcb5dbec6d55a6a7
-1296	2011	0	obj/components/autofill/content/common/mojo_test_types__is_mojom.stamp	d9c798289ba46425
-1297	2011	0	obj/components/password_manager/content/common/mojo_interfaces__is_mojom.stamp	626b36fa82d1da58
-1298	2012	0	obj/components/bookmarks/browser/unit_tests_bundle_data.stamp	597321f908035e7b
-1298	2029	0	test_data/chrome/browser/resources/print_preview/print_preview_utils.js	3da6f440b12423f5
-1298	2045	0	test_data/chrome/browser/resources/print_preview/data/measurement_system.js	276da1cf0e264513
-1298	2061	0	test_data/chrome/browser/resources/md_downloads/action_service.js	ab7d4417cd0ee295
-1298	2097	0	test_data/chrome/renderer/resources/extensions/notifications_custom_bindings.js	a6480bafe57a2747
-1299	2097	0	test_data/chrome/renderer/resources/extensions/notifications_test_util.js	21534713a862f9f0
-1300	2106	0	media_router/browser_test_resources/no_provider.json	3966753c5d416bb
-1300	2120	0	media_router/browser_test_resources/no_sinks.json	8a565aa71679478b
-1300	2121	0	media_router/test_extension/manifest.json	8f65bc8b627dcc57
-1300	2126	0	media_router/test_extension/script.js	107afb97bad014f
-1300	2127	0	media_router/browser_test_resources/close_route_with_error_on_send.json	b9facf84d2e8c445
-1301	2129	0	media_router/browser_test_resources/basic_test.html	f95507df99df541
-1301	2134	0	media_router/browser_test_resources/common.js	d07c9ad75bf70cf5
-1301	2137	0	media_router/browser_test_resources/route_creation_timed_out.json	e5dc7c74ac436fe5
-1302	2141	0	media_router/browser_test_resources/fail_create_route.json	f41da6c16c17fcce
-1302	2157	0	media_router/browser_test_resources/fail_reconnect_session.json	581f4aec17f01054
-1302	2177	0	media_router/browser_test_resources/no_supported_sinks.json	9a1378949ae8c576
-1303	2181	0	media_router/browser_test_resources/fail_reconnect_session.html	63cebfae6ed2384e
-1303	2181	0	obj/content/test/content_test_mojo_bindings__check_deps_are_all_mojom.stamp	ffff60eb9ffb675
-1303	2183	0	test_data/ui/webui/resources/js/cr.js	b6fec657a251987d
-1303	2184	0	obj/chrome/test/chromedriver/embed_js_in_cpp.inputdeps.stamp	decaaac784c17e4a
-1303	2184	0	obj/chrome/test/chromedriver/embed_user_data_dir_in_cpp.inputdeps.stamp	e92600aa087bbb93
-1304	2185	0	obj/chrome/test/chromedriver/embed_version_in_cpp.inputdeps.stamp	3972b73cb5c02713
-1304	2186	0	obj/chrome/test/chromedriver/embed_extension_in_cpp.inputdeps.stamp	b9ccb10c5ebe688b
-1304	2189	0	obj/components/content_settings/core/common/mojo_bindings__check_deps_are_all_mojom.stamp	da375d2ecca40368
-1305	2201	0	obj/components/history/core/browser/unit_tests_bundle_data.stamp	a3b912d12f688623
-1305	2201	0	obj/components/contextual_search/mojo_bindings__check_deps_are_all_mojom.stamp	18fd737f0687941e
-1305	2201	0	obj/components/contextual_search/mojo_bindings__is_mojom.stamp	d187e414f8925477
-1308	2205	0	obj/components/contextual_search/mojo_bindings__type_mappings.inputdeps.stamp	1af9b91fb39cf2c
-1309	2221	0	hid_report_descriptor_fuzzer.options	580f064a68005230
-1309	2224	0	obj/components/content_settings/core/common/mojo_bindings__type_mappings.inputdeps.stamp	5d22a3eb8a588726
-1309	2249	0	obj/components/content_settings/core/common/mojo_bindings__is_mojom.stamp	7750f7c67582c124
-1309	2258	0	obj/components/content_settings/core/common/mojo_bindings_blink__type_mappings.inputdeps.stamp	2431763c76fe6e5a
-1309	2265	0	obj/components/contextual_search/mojo_bindings_blink__type_mappings.inputdeps.stamp	e7473d8c2e1dcae2
-1311	2265	0	obj/components/data_reduction_proxy/core/common/version_header_action.inputdeps.stamp	def55c35f16728c2
-1311	2277	0	obj/components/data_reduction_proxy/core/browser/unit_tests_bundle_data.stamp	7cb412d497616df3
-1311	2297	0	obj/components/discardable_memory/public/interfaces/interfaces__type_mappings.inputdeps.stamp	dca59ab4f91c2ee8
-1311	2309	0	obj/components/discardable_memory/public/interfaces/interfaces__is_mojom.stamp	9f0a161334664221
-1311	2333	0	obj/components/discardable_memory/public/interfaces/interfaces_blink__type_mappings.inputdeps.stamp	6e36ef3a17f3de02
-1312	2345	0	obj/components/discardable_memory/public/interfaces/interfaces__check_deps_are_all_mojom.stamp	ec112dbb3de63c54
-1312	2345	0	obj/components/dom_distiller/content/common/mojo_bindings__is_mojom.stamp	e9cb079e59ba260e
-1312	2348	0	obj/components/dom_distiller/content/common/mojo_bindings__check_deps_are_all_mojom.stamp	dbece267a76395df
-1314	2353	0	obj/ui/base/ime/text_input_types.stamp	7a2d9dbcc77cfda6
-1314	2359	0	obj/components/dom_distiller/content/common/mojo_bindings_blink__type_mappings.inputdeps.stamp	1e36ef36dd3398c9
-1315	2360	0	obj/components/filesystem/test_manifest__is_service_manifest.stamp	49dd9970c19ba5e
-1315	2369	0	obj/components/filesystem/manifest__is_service_manifest.stamp	95c95da367c72984
-1315	2369	0	obj/components/filesystem/test_manifest.inputdeps.stamp	ff8428f5f54eeb48
-1315	2393	0	obj/components/filesystem/manifest.inputdeps.stamp	43bef0c83d0b0886
-1315	2393	0	obj/components/filesystem/public/interfaces/interfaces__is_mojom.stamp	4c28486b416c7fd2
-1316	2394	0	obj/components/font_service/manifest.inputdeps.stamp	d8a2303746c6b516
-1317	2395	0	obj/components/font_service/manifest__is_service_manifest.stamp	1fc5b5ae92a492b7
-1317	2396	0	obj/components/font_service/public/interfaces/interfaces__is_mojom.stamp	2f17d19bcb97eb84
-1318	2404	0	obj/components/handoff/handoff.stamp	a1ecd0e1f95f0461
-1318	2409	0	obj/components/visitedlink/common/interfaces_blink__type_mappings.inputdeps.stamp	22bdb1b353356929
-1318	2425	0	obj/components/json_schema/unit_tests_bundle_data.stamp	55e44fc60b39fe05
-1318	2427	0	obj/components/leveldb/public/interfaces/interfaces__is_mojom.stamp	a4c4f4afa51e0970
-1319	2427	0	obj/components/leveldb/test_manifest__is_service_manifest.stamp	a5060450ad053f48
-1319	2429	0	obj/components/leveldb/manifest__is_service_manifest.stamp	98ae837e0acd335
-1319	2429	0	obj/components/leveldb/test_manifest.inputdeps.stamp	68a6f2adcbd52597
-1319	2433	0	obj/components/leveldb/manifest.inputdeps.stamp	ab10e912a19cf2df
-1320	2433	0	obj/content/public/common/service_names__type_mappings.inputdeps.stamp	373bbbad6ead5f34
-1321	2453	0	obj/content/public/common/service_names__is_mojom.stamp	8357cc3b4f2c0123
-1323	2461	0	obj/content/renderer/for_content_tests.stamp	700a6a50f029f439
-1323	2461	0	obj/components/metrics/call_stack_profile_params/call_stack_profile_params.o	d0898cd3269c4685
-1324	2461	0	obj/components/metrics/public/interfaces/call_stack_mojo_bindings__is_mojom.stamp	d71fb0ea06f4ff50
-1324	2463	0	obj/components/metrics/public/interfaces/call_stack_mojo_test_bindings__is_mojom.stamp	f343bc355006eda9
-1324	2465	0	obj/content/test/content_test_mojo_bindings__is_mojom.stamp	dca0e4ba7b52130d
-1325	2466	0	obj/content/test/content_test_mojo_bindings__type_mappings.inputdeps.stamp	1b21e422740b76bd
-1325	2466	0	obj/device/bluetooth/public/interfaces/interfaces__type_mappings.inputdeps.stamp	bb0aa06fc65ada2
-1325	2486	0	obj/device/bluetooth/public/interfaces/interfaces__is_mojom.stamp	5e31bc7b9644b45e
-1325	2486	0	obj/components/omnibox/browser/unit_tests_bundle_data.stamp	e6f22eb311c939d0
-1326	2489	0	obj/components/omnibox/common/common.stamp	c3620bb786809ce6
-1326	2489	0	obj/components/omnibox/browser/omnibox_vector_icons.inputdeps.stamp	fc4caa96333b1f49
-1328	2525	0	obj/components/payments/content/payment_request__type_mappings.inputdeps.stamp	4138c73edd8d9967
-1329	2525	0	obj/components/payments/content/payment_request__is_mojom.stamp	4dbc6bdd61021ca0
-1330	2537	0	obj/components/payments/content/payment_request__check_deps_are_all_mojom.stamp	d922943f5977c2dd
-1330	2541	0	obj/components/payments/content/payment_request_blink__type_mappings.inputdeps.stamp	43997c6ac87963a4
-1330	2541	0	obj/components/policy/full_runtime_code_generate.inputdeps.stamp	8207acd4fc2c0e50
-1331	2542	0	obj/device/wake_lock/public/interfaces/interfaces_blink__type_mappings.inputdeps.stamp	6b4c989d4e204ee3
-1332	2545	0	obj/components/policy/cloud_policy_code_generate.inputdeps.stamp	80d997b008445f27
-1332	2559	0	obj/components/rappor/public/interfaces/interfaces__is_mojom.stamp	f74ddb5b30de7283
-1332	2585	0	gen/components/reading_list/core/reading_list_enable_flags.h	f18d0b5d02cf9f78
-1334	2586	0	obj/headless/version_header_action.inputdeps.stamp	c1023777f5460270
-1334	2587	0	obj/components/resources/about_credits.inputdeps.stamp	a42c859c1e84aafc
-1334	2587	0	obj/gpu/ipc/common/test_interfaces__is_mojom.stamp	6c211a01634aee8e
-1335	2587	0	obj/components/search_engines/prepopulated_engines_action.inputdeps.stamp	563322a485255768
-1335	2588	0	obj/components/safe_json/public/interfaces/interfaces__is_mojom.stamp	b1c4ffd92ad2d62
-1337	2593	0	gpu_fuzzer.options	357a45b5220e5ae6
-1337	2593	0	gen/components/spellcheck/spellcheck_build_features.h	ffbfeb2acac5fefb
-1338	2594	0	net_url_request_ftp_fuzzer.dict	d2a573f9850594ae
-1338	2594	0	net_url_request_ftp_fuzzer.options	ebf89f03483d7889
-1338	2596	0	obj/components/startup_metric_utils/common/interfaces__is_mojom.stamp	402b01730c095796
-1339	2597	0	obj/services/image_decoder/public/interfaces/constants__check_deps_are_all_mojom.stamp	79541de2b563448d
-1339	2598	0	remoting/chrome-remote-desktop-host	645e67669422d2f4
-1339	2598	0	obj/services/ui/ws/mus_ws_unittests_app_manifest.inputdeps.stamp	387fe8854b2e7630
-1339	2599	0	obj/skia/public/interfaces/test_interfaces__is_mojom.stamp	8e9419d22031d89a
-1340	2606	0	obj/services/shape_detection/manifest.inputdeps.stamp	2245ddb863b954c
-1341	2621	0	colorenhancer/src/cvd.js	bfff4c53b86e67fa
-1342	2621	0	colorenhancer/src/common.js	273a0f544599a6f
-1343	2633	0	colorenhancer/src/background.js	8b6bc1aa16c16bc8
-1343	2633	0	obj/ui/base/mojo/mojo_bindings_blink__type_mappings.inputdeps.stamp	565a2b79604e9caa
-1344	2633	0	obj/services/service_manager/manifest.inputdeps.stamp	89d35163db05eef
-1344	2634	0	obj/services/service_manager/manifest__is_service_manifest.stamp	1cbc8d6f5f4b48ff
-1350	2634	0	obj/services/service_manager/background/tests/test_manifest__is_service_manifest.stamp	d6300a614424bac5
-1351	2636	0	obj/services/service_manager/background/tests/test_service_interfaces__check_deps_are_all_mojom.stamp	17f819c51d0bbcba
-1351	2636	0	obj/services/service_manager/background/tests/test_manifest.inputdeps.stamp	ac6756d58fa02be5
-1351	2636	0	obj/services/service_manager/background/tests/test_service_interfaces__is_mojom.stamp	d9304a27f20ef777
-1351	2636	0	obj/services/service_manager/background/tests/test_service_interfaces__type_mappings.inputdeps.stamp	99a4b65a446a96c6
-1352	2637	0	obj/services/service_manager/background/tests/test_service_interfaces_blink__type_mappings.inputdeps.stamp	fc8744ed09af87be
-1352	2637	0	obj/services/service_manager/background/tests/test_service_manifest.inputdeps.stamp	c24cd0627664d8f
-1352	2637	0	obj/services/service_manager/background/tests/test_service_manifest__is_service_manifest.stamp	b5e86b588a28fb5c
-1353	2641	0	obj/services/service_manager/public/interfaces/constants__is_mojom.stamp	e062038719022d9a
-1354	2642	0	obj/services/service_manager/public/interfaces/constants__check_deps_are_all_mojom.stamp	419f0ddba4c080d6
-1356	2643	0	obj/services/service_manager/public/interfaces/constants__type_mappings.inputdeps.stamp	d69a5fd3bc55a6fa
-1357	2643	0	obj/services/service_manager/public/interfaces/constants_blink__type_mappings.inputdeps.stamp	e5d64366e8ff03ac
-1358	2645	0	obj/services/service_manager/public/interfaces/interfaces__is_mojom.stamp	8008271190de7995
-1358	2649	0	obj/services/service_manager/tests/interfaces__type_mappings.inputdeps.stamp	3b926ed55307693f
-1359	2650	0	obj/services/service_manager/tests/interfaces__is_mojom.stamp	bbf5a998c440e482
-1359	2652	0	obj/services/service_manager/runner/host/host_test_service_manifest__is_service_manifest.stamp	b3629c78e87569ea
-1360	2652	0	obj/services/service_manager/runner/host/host_test_service_manifest.inputdeps.stamp	881ed42edc54279
-1360	2654	0	obj/services/service_manager/tests/interfaces__check_deps_are_all_mojom.stamp	3e745013b5c3a7d4
-1361	2654	0	obj/ui/keyboard/mojom__is_mojom.stamp	ac83212aef984ca6
-1362	2655	0	obj/components/toolbar/toolbar_vector_icons.inputdeps.stamp	999190b061be2b18
-1363	2656	0	obj/components/translate/content/common/common__is_mojom.stamp	e77a47adf41e78ca
-1363	2658	0	obj/components/ui_devtools/protocol_compatibility.inputdeps.stamp	a262a48d447d407c
-1364	2660	0	obj/components/update_client/unit_tests_bundle_data.stamp	e34a9f29a7ddf9da
-1364	2660	0	obj/components/variations/field_trial_config/field_trial_testing_config_action.inputdeps.stamp	434946957497ef1e
-1364	2660	0	obj/testing/buildbot/filters/browser_tests_filters.stamp	3b9fd46dc80e103
-1365	2660	0	obj/components/version_info/generate_version_info_action.inputdeps.stamp	e320dedf7f041bb8
-1365	2662	0	obj/components/web_cache/public/interfaces/interfaces__type_mappings.inputdeps.stamp	1d8798130ad180c8
-1365	2662	0	obj/components/web_cache/public/interfaces/interfaces__is_mojom.stamp	5173eb112c5d56f1
-1366	2669	0	obj/mash/public/interfaces/interfaces__is_mojom.stamp	6dd113bd4ce0134a
-1366	2669	0	obj/components/web_cache/public/interfaces/interfaces_blink__type_mappings.inputdeps.stamp	defee36e55d65320
-1367	2669	0	obj/components/visitedlink/common/interfaces__check_deps_are_all_mojom.stamp	12c5f8f404f07144
-1367	2669	0	obj/components/web_cache/public/interfaces/interfaces__check_deps_are_all_mojom.stamp	4d22832bbd44e332
-1368	2673	0	obj/content/sandbox_helper_win.stamp	53556bd1952574d0
-1369	2681	0	obj/services/ui/demo/manifest.inputdeps.stamp	d261cb8b5832ad36
-1370	2681	0	obj/components/webdata/common/unit_tests_bundle_data.stamp	bea6c98642e32d4e
-1370	2681	0	obj/content/app/both_for_content_tests.stamp	61ebf49fd98b90cc
-1370	2681	0	obj/content/export.stamp	4a060d841250382b
-1370	2681	0	obj/content/common/mojo_bindings__is_mojom.stamp	41eea74b73e02dfb
-1371	2682	0	obj/content/child/for_content_tests.stamp	44aaf3e748abc1ea
-1371	2682	0	gen/content/public/common/features.h	f5ec1a1276c73150
-1372	2683	0	obj/content/common/for_content_tests.stamp	b3f0afc35633fbca
-1373	2684	0	gen/content/common/features.h	f14dec80fcf32baa
-1373	2685	0	obj/services/ui/demo/test_manifest.inputdeps.stamp	76824c99aa6bf355
-1373	2685	0	obj/content/public/app/renderer_manifest__is_service_manifest.stamp	fd7f4a85ccacf1b7
-1374	2686	0	obj/content/public/app/renderer_manifest.inputdeps.stamp	48032c8ab25a6aec
-1374	2688	0	obj/content/public/app/plugin_manifest__is_service_manifest.stamp	99d43b55bb330fae
-1374	2690	0	obj/content/public/app/plugin_manifest.inputdeps.stamp	fd40843720182461
-1374	2690	0	obj/content/public/app/packaged_services_manifest__is_service_manifest.stamp	4813dd4c7cfe0dd4
-1375	2691	0	obj/content/public/app/gpu_manifest__is_service_manifest.stamp	ae2b882bbd8bb292
-1375	2692	0	obj/content/public/app/gpu_manifest.inputdeps.stamp	d316339c888e8cbf
-1375	2692	0	obj/content/public/app/browser_manifest__is_service_manifest.stamp	83671be596ae3bf9
-1377	2692	0	obj/content/public/app/utility_manifest__is_service_manifest.stamp	c875df2d90c2c80
-1378	2693	0	obj/content/public/app/utility_manifest.inputdeps.stamp	88bb6e963b00b0c1
-1378	2694	0	obj/content/public/common/service_names_blink__type_mappings.inputdeps.stamp	1b2338947af3a1b
-1378	2694	0	obj/content/public/common/interfaces__check_deps_are_all_mojom.stamp	97afcae8baadc77a
-1379	2694	0	obj/content/public/common/result_codes.stamp	7e3d25132dcedc3b
-1380	2694	0	obj/content/public/common/service_names__check_deps_are_all_mojom.stamp	1b497d9c4f1d8650
-1380	2695	0	obj/content/public/common/interfaces__type_mappings.inputdeps.stamp	359a82b755d6dfbc
-1380	2696	0	obj/content/public/common/interfaces__is_mojom.stamp	4a4e8a0c32c5f938
-1381	2696	0	obj/content/public/common/interfaces_blink__type_mappings.inputdeps.stamp	ee602eacc9b045e9
-1381	2697	0	GardinerModCat.ttf	3ce72a7c357259c0
-1381	2699	0	GardinerModBug.ttf	69f4c57ee21e3d45
-1382	2699	0	fonts.conf	903c92c674848f27
-1383	2699	0	AHEM____.TTF	d9be98d3534e71be
-1384	2699	0	obj/content/shell/mojo_bindings__is_mojom.stamp	41a503d4088b8a6d
-1384	2700	0	obj/content/test/content_test_mojo_bindings_blink__type_mappings.inputdeps.stamp	cdbad946535f7511
-1385	2701	0	obj/content/test/content_unittests_manifest__is_service_manifest.stamp	f72e2413607b90b6
-1385	2701	0	obj/content/utility/for_content_tests.stamp	144e86637a119ab7
-1385	2701	0	obj/content/test/web_ui_test_mojo_bindings__check_deps_are_all_mojom.stamp	70bf70f78a81f092
-1386	2703	0	obj/third_party/webrtc/base/gtest_prod.stamp	c7ba3618f71670fe
-1387	2713	0	obj/device/battery/mojo_bindings__is_mojom.stamp	d1000202725cdd3a
-1387	2713	0	obj/device/battery/mojo_bindings_blink__type_mappings.inputdeps.stamp	b5a2ba69c2ffe9f1
-1388	2714	0	obj/device/battery/mojo_bindings__check_deps_are_all_mojom.stamp	ec7d3f5902ab03b8
-1388	2715	0	obj/device/battery/mojo_bindings__type_mappings.inputdeps.stamp	8f755a1226416498
-1388	2716	0	obj/content/test/web_ui_test_mojo_bindings_blink__type_mappings.inputdeps.stamp	491d4795773c54c8
-1388	2716	0	obj/content/test/web_ui_test_mojo_bindings__type_mappings.inputdeps.stamp	de7637397f63b2ec
-1389	2716	0	obj/content/test/web_ui_test_mojo_bindings__is_mojom.stamp	1e0ab0348c2e1ee0
-1390	2717	0	obj/content/test/fuzzer/fuzzer.stamp	bbc6f5317d29aa65
-1390	2718	0	obj/device/bluetooth/public/interfaces/experimental_interfaces__is_mojom.stamp	1c79665bed98ab04
-1390	2719	0	obj/device/bluetooth/public/interfaces/interfaces__check_deps_are_all_mojom.stamp	89c2f14913b32f85
-1391	2719	0	obj/device/bluetooth/public/interfaces/interfaces_blink__type_mappings.inputdeps.stamp	2b05f29f4adaa33
-1392	2720	0	obj/device/gamepad/public/interfaces/gamepad_struct_traits_test__is_mojom.stamp	33daf38dd323965b
-1393	2721	0	obj/device/gamepad/public/interfaces/interfaces__check_deps_are_all_mojom.stamp	35111b8a42281362
-1393	2721	0	obj/device/gamepad/public/interfaces/interfaces__is_mojom.stamp	60c295fb5928248a
-1394	2722	0	obj/device/gamepad/public/interfaces/interfaces__type_mappings.inputdeps.stamp	3b2c48390830aa2b
-1395	2725	0	obj/device/gamepad/public/interfaces/interfaces_blink__type_mappings.inputdeps.stamp	1e19f40cc0de3a70
-1395	2733	0	obj/device/generic_sensor/public/interfaces/interfaces__check_deps_are_all_mojom.stamp	4314a13b8c276e18
-1395	2733	0	obj/device/generic_sensor/public/interfaces/interfaces__is_mojom.stamp	69989e0cd8e35ad4
-1396	2735	0	obj/device/generic_sensor/public/interfaces/interfaces__type_mappings.inputdeps.stamp	5ddddfa704d022e6
-1396	2735	0	obj/device/generic_sensor/public/interfaces/interfaces_blink__type_mappings.inputdeps.stamp	e1fa941c54fc56cc
-1397	2735	0	obj/device/geolocation/public/interfaces/interfaces__is_mojom.stamp	1c29a8f30eb15f9d
-1397	2736	0	obj/device/geolocation/public/interfaces/interfaces__type_mappings.inputdeps.stamp	286d95a305d8b211
-1398	2737	0	obj/device/geolocation/public/interfaces/interfaces__check_deps_are_all_mojom.stamp	a9256d80d904d268
diff --git a/build/ninjalog/trace.go b/build/ninjalog/trace.go
deleted file mode 100644
index 0313d4c..0000000
--- a/build/ninjalog/trace.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2014 The Fuchsia 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 ninjalog
-
-import (
-	"sort"
-)
-
-// Trace is an entry of trace format.
-// https://code.google.com/p/trace-viewer/
-type Trace struct {
-	Name      string                 `json:"name"`
-	Category  string                 `json:"cat"`
-	EventType string                 `json:"ph"`
-	Timestamp int                    `json:"ts"`  // microsecond
-	Duration  int                    `json:"dur"` // microsecond
-	ProcessID int                    `json:"pid"`
-	ThreadID  int                    `json:"tid"`
-	Args      map[string]interface{} `json:"args"`
-}
-
-type traceByStart []Trace
-
-func (t traceByStart) Len() int           { return len(t) }
-func (t traceByStart) Swap(i, j int)      { t[i], t[j] = t[j], t[i] }
-func (t traceByStart) Less(i, j int) bool { return t[i].Timestamp < t[j].Timestamp }
-
-func toTrace(step Step, pid int, tid int) Trace {
-	return Trace{
-		Name:      step.Out,
-		Category:  "target",
-		EventType: "X",
-		Timestamp: int(step.Start.Nanoseconds() / 1000),
-		Duration:  int(step.Duration().Nanoseconds() / 1000),
-		ProcessID: pid,
-		ThreadID:  tid,
-		Args:      make(map[string]interface{}),
-	}
-}
-
-// ToTraces converts Flow outputs into trace log.
-func ToTraces(steps [][]Step, pid int) []Trace {
-	traceNum := 0
-	for _, thread := range steps {
-		traceNum += len(thread)
-	}
-
-	traces := make([]Trace, 0, traceNum)
-	for tid, thread := range steps {
-		for _, step := range thread {
-			traces = append(traces, toTrace(step, pid, tid))
-		}
-	}
-	sort.Sort(traceByStart(traces))
-	return traces
-}
diff --git a/build/ninjalog/trace_test.go b/build/ninjalog/trace_test.go
deleted file mode 100644
index 9417587..0000000
--- a/build/ninjalog/trace_test.go
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2014 The Fuchsia 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 ninjalog
-
-import (
-	"reflect"
-	"testing"
-	"time"
-)
-
-func TestTrace(t *testing.T) {
-	flow := [][]Step{
-		[]Step{
-			Step{
-				Start:   76 * time.Millisecond,
-				End:     187 * time.Millisecond,
-				Out:     "resources/inspector/devtools_extension_api.js",
-				CmdHash: "75430546595be7c2",
-			},
-			Step{
-				Start:   187 * time.Millisecond,
-				End:     21304 * time.Millisecond,
-				Out:     "obj/third_party/pdfium/core/src/fpdfdoc/fpdfdoc.doc_formfield.o",
-				CmdHash: "2ac7111aa1ae86af",
-			},
-		},
-		[]Step{
-			Step{
-				Start:   78 * time.Millisecond,
-				End:     286 * time.Millisecond,
-				Out:     "gen/angle/commit_id.py",
-				CmdHash: "4ede38e2c1617d8c",
-			},
-			Step{
-				Start:   287 * time.Millisecond,
-				End:     290 * time.Millisecond,
-				Out:     "obj/third_party/angle/src/copy_scripts.actions_rules_copies.stamp",
-				CmdHash: "b211d373de72f455",
-			},
-		},
-		[]Step{
-			Step{
-				Start:   79 * time.Millisecond,
-				End:     287 * time.Millisecond,
-				Out:     "gen/angle/copy_compiler_dll.bat",
-				CmdHash: "9fb635ad5d2c1109",
-			},
-		},
-		[]Step{
-			Step{
-				Start:   80 * time.Millisecond,
-				End:     284 * time.Millisecond,
-				Out:     "gen/autofill_regex_constants.cc",
-				CmdHash: "fa33c8d7ce1d8791",
-			},
-		},
-		[]Step{
-			Step{
-				Start:   141 * time.Millisecond,
-				End:     287 * time.Millisecond,
-				Out:     "PepperFlash/manifest.json",
-				CmdHash: "324f0a0b77c37ef",
-			},
-		},
-		[]Step{
-			Step{
-				Start:   142 * time.Millisecond,
-				End:     288 * time.Millisecond,
-				Out:     "PepperFlash/libpepflashplayer.so",
-				CmdHash: "1e2c2b7845a4d4fe",
-			},
-		},
-	}
-
-	traces := ToTraces(flow, 1)
-	want := []Trace{
-		Trace{
-			Name:      "resources/inspector/devtools_extension_api.js",
-			Category:  "target",
-			EventType: "X",
-			Timestamp: 76 * 1000,
-			Duration:  (187 - 76) * 1000,
-			ProcessID: 1,
-			ThreadID:  0,
-			Args:      map[string]interface{}{},
-		},
-		Trace{
-			Name:      "gen/angle/commit_id.py",
-			Category:  "target",
-			EventType: "X",
-			Timestamp: 78 * 1000,
-			Duration:  (286 - 78) * 1000,
-			ProcessID: 1,
-			ThreadID:  1,
-			Args:      map[string]interface{}{},
-		},
-		Trace{
-			Name:      "gen/angle/copy_compiler_dll.bat",
-			Category:  "target",
-			EventType: "X",
-			Timestamp: 79 * 1000,
-			Duration:  (287 - 79) * 1000,
-			ProcessID: 1,
-			ThreadID:  2,
-			Args:      map[string]interface{}{},
-		},
-		Trace{
-			Name:      "gen/autofill_regex_constants.cc",
-			Category:  "target",
-			EventType: "X",
-			Timestamp: 80 * 1000,
-			Duration:  (284 - 80) * 1000,
-			ProcessID: 1,
-			ThreadID:  3,
-			Args:      map[string]interface{}{},
-		},
-		Trace{
-			Name:      "PepperFlash/manifest.json",
-			Category:  "target",
-			EventType: "X",
-			Timestamp: 141 * 1000,
-			Duration:  (287 - 141) * 1000,
-			ProcessID: 1,
-			ThreadID:  4,
-			Args:      map[string]interface{}{},
-		},
-		Trace{
-			Name:      "PepperFlash/libpepflashplayer.so",
-			Category:  "target",
-			EventType: "X",
-			Timestamp: 142 * 1000,
-			Duration:  (288 - 142) * 1000,
-			ProcessID: 1,
-			ThreadID:  5,
-			Args:      map[string]interface{}{},
-		},
-		Trace{
-			Name:      "obj/third_party/pdfium/core/src/fpdfdoc/fpdfdoc.doc_formfield.o",
-			Category:  "target",
-			EventType: "X",
-			Timestamp: 187 * 1000,
-			Duration:  (21304 - 187) * 1000,
-			ProcessID: 1,
-			ThreadID:  0,
-			Args:      map[string]interface{}{},
-		},
-		Trace{
-			Name:      "obj/third_party/angle/src/copy_scripts.actions_rules_copies.stamp",
-			Category:  "target",
-			EventType: "X",
-			Timestamp: 287 * 1000,
-			Duration:  (290 - 287) * 1000,
-			ProcessID: 1,
-			ThreadID:  1,
-			Args:      map[string]interface{}{},
-		},
-	}
-
-	if !reflect.DeepEqual(traces, want) {
-		t.Errorf("ToTrace()=%v; want=%v", traces, want)
-	}
-}
diff --git a/build/ninjatrace/cmd/ninjatrace.go b/build/ninjatrace/cmd/ninjatrace.go
deleted file mode 100644
index 633d44a..0000000
--- a/build/ninjatrace/cmd/ninjatrace.go
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2014 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// ninjatrace converts .ninja_log into trace-viewer formats.
-//
-// usage:
-//  $ go run ninjatrace.go --filename out/debug-x64/.ninja_log
-//
-package main
-
-import (
-	"bufio"
-	"compress/gzip"
-	"encoding/json"
-	"flag"
-	"io"
-	"log"
-	"os"
-	"path/filepath"
-	"runtime/pprof"
-
-	"go.fuchsia.dev/tools/build/ninjalog"
-)
-
-var (
-	filename   = flag.String("filename", ".ninja_log", "filename of .ninja_log")
-	traceJSON  = flag.String("trace-json", "trace.json", "output filename of trace.json")
-	cpuprofile = flag.String("cpuprofile", "", "file to write cpu profile")
-)
-
-func reader(fname string, rd io.Reader) (io.Reader, error) {
-	if filepath.Ext(fname) != ".gz" {
-		return bufio.NewReaderSize(rd, 512*1024), nil
-	}
-	return gzip.NewReader(bufio.NewReaderSize(rd, 512*1024))
-}
-
-func convert(fname string) ([]ninjalog.Trace, error) {
-	f, err := os.Open(fname)
-	if err != nil {
-		return nil, err
-	}
-	defer f.Close()
-	rd, err := reader(fname, f)
-	if err != nil {
-		return nil, err
-	}
-
-	njl, err := ninjalog.Parse(fname, rd)
-	if err != nil {
-		return nil, err
-	}
-	steps := ninjalog.Dedup(njl.Steps)
-	flow := ninjalog.Flow(steps)
-	return ninjalog.ToTraces(flow, 1), nil
-}
-
-func output(fname string, traces []ninjalog.Trace) (err error) {
-	f, err := os.Create(fname)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		cerr := f.Close()
-		if err == nil {
-			err = cerr
-		}
-	}()
-	js, err := json.Marshal(traces)
-	if err != nil {
-		return err
-	}
-	_, err = f.Write(js)
-	return err
-}
-
-func main() {
-	flag.Parse()
-
-	if *cpuprofile != "" {
-		f, err := os.Create(*cpuprofile)
-		if err != nil {
-			log.Fatal(err)
-		}
-		pprof.StartCPUProfile(f)
-		defer pprof.StopCPUProfile()
-	}
-
-	traces, err := convert(*filename)
-	if err != nil {
-		log.Fatal(err)
-	}
-	if *traceJSON != "" {
-		err = output(*traceJSON, traces)
-		if err != nil {
-			log.Fatal(err)
-		}
-	}
-}
diff --git a/debroot/cmd/debian-archive-keyring.gpg b/debroot/cmd/debian-archive-keyring.gpg
deleted file mode 100644
index b13cf79..0000000
--- a/debroot/cmd/debian-archive-keyring.gpg
+++ /dev/null
Binary files differ
diff --git a/debroot/cmd/main.go b/debroot/cmd/main.go
deleted file mode 100644
index d8d1552..0000000
--- a/debroot/cmd/main.go
+++ /dev/null
@@ -1,727 +0,0 @@
-// Copyright 2017 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Generates a Debian based sysroot.
-package main
-
-import (
-	"bufio"
-	"bytes"
-	"compress/gzip"
-	"context"
-	"crypto/sha256"
-	"encoding/hex"
-	"flag"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"net/http"
-	"net/url"
-	"os"
-	"os/exec"
-	"path"
-	"path/filepath"
-	"regexp"
-	"sort"
-	"strings"
-	"time"
-
-	"github.com/google/subcommands"
-	"golang.org/x/crypto/openpgp"
-	"gopkg.in/yaml.v2"
-)
-
-// gpg keyring file generated using:
-//   export KEYS="46925553 2B90D010 518E17E1 1A7B6500"
-//   gpg --keyserver keys.gnupg.net --recv-keys $KEYS
-//   gpg --output ./debian-archive-stretch-stable.gpg --export $KEYS
-
-const (
-	// http://http.us.debian.org/debian no longer contains arm64 packages
-	// for jessie so we instead use the last snapshot that still has them.
-	aptRepo = "https://snapshot.debian.org/archive/debian/20190324T093412Z"
-)
-
-type stringsValue []string
-
-func (i *stringsValue) String() string {
-	return strings.Join(*i, ",")
-}
-
-func (i *stringsValue) Set(value string) error {
-	*i = strings.Split(value, ",")
-	return nil
-}
-
-type Config struct {
-	Dists         []string  `yaml:"dists"`
-	Components    []string  `yaml:"components"`
-	Keyring       string    `yaml:"keyring"`
-	Architectures []string  `yaml:"architectures"`
-	Packages      []Package `yaml:"packages"`
-}
-
-type Package struct {
-	Name          string   `yaml:"package"`
-	Architectures []string `yaml:"architectures,omitempty"`
-}
-
-type Lockfile struct {
-	Hash     string    `yaml:"hash"`
-	Updated  time.Time `yaml:"updated"`
-	Packages []Lock    `yaml:"packages"`
-}
-
-type Lock struct {
-	Name     string `yaml:"package"`
-	Version  string `yaml:"version"`
-	Filename string `yaml:"filename"`
-	Hash     string `yaml:"hash"`
-}
-
-type Locks []Lock
-
-func (l Locks) Len() int {
-	return len(l)
-}
-
-func (l Locks) Swap(i, j int) {
-	l[i], l[j] = l[j], l[i]
-}
-
-func (l Locks) Less(i, j int) bool {
-	if l[i].Name == l[j].Name {
-		return l[i].Filename < l[j].Filename
-	}
-	return l[i].Name < l[j].Name
-}
-
-// Descriptor represents a Debian package description.
-type Descriptor map[string]string
-
-// parsePackages parses Debian's control file which described packages.
-//
-// See chapter 5.1 (Syntax of control files) of the Debian Policy Manual:
-// http://www.debian.org/doc/debian-policy/ch-controlfields.html
-func parsePackages(r io.Reader) ([]Descriptor, error) {
-	// Packages are separated by double newline, use scanner to split them.
-	scanner := bufio.NewScanner(r)
-	scanner.Split(func(data []byte, atEOF bool) (int, []byte, error) {
-		const separator = "\n\n"
-		if i := bytes.Index(data, []byte(separator)); i != -1 {
-			return i + len(separator), data[:i], nil
-		}
-		return 0, nil, nil
-	})
-	exp := regexp.MustCompile(`(?m)^(?P<key>\S+): (?P<value>(.*)(?:$\s^ .*)*)$`)
-	var descriptors []Descriptor
-	for scanner.Scan() {
-		descriptor := make(Descriptor)
-		for _, m := range exp.FindAllStringSubmatch(scanner.Text(), -1) {
-			descriptor[m[1]] = m[2]
-		}
-		descriptors = append(descriptors, descriptor)
-	}
-	if err := scanner.Err(); err != nil {
-		return nil, err
-	}
-	return descriptors, nil
-}
-
-func downloadPackageList(config *Config, depends bool) ([]Lock, error) {
-	descriptors := map[string]map[string]Descriptor{}
-
-	file, err := os.Open(config.Keyring)
-	if err != nil {
-		return nil, err
-	}
-	defer file.Close()
-	keyring, err := openpgp.ReadKeyRing(file)
-	if err != nil {
-		return nil, err
-	}
-
-	for _, dist := range config.Dists {
-		u, err := url.Parse(aptRepo)
-		u.Path = path.Join(u.Path, "dists", dist, "Release")
-		r, err := http.Get(u.String())
-		if err != nil {
-			return nil, err
-		}
-		defer r.Body.Close()
-
-		b, err := ioutil.ReadAll(r.Body)
-		if err != nil {
-			return nil, err
-		}
-		var lines []string
-		sha256section := false
-		for _, l := range strings.Split(string(b), "\n") {
-			if sha256section {
-				if strings.HasPrefix(l, " ") {
-					lines = append(lines, l[1:])
-				} else {
-					sha256section = false
-				}
-			} else if strings.HasPrefix(l, "SHA256:") {
-				sha256section = true
-			}
-		}
-
-		u, err = url.Parse(aptRepo)
-		u.Path = path.Join(u.Path, "dists", dist, "Release.gpg")
-		r, err = http.Get(u.String())
-		if err != nil {
-			return nil, err
-		}
-		defer r.Body.Close()
-
-		_, err = openpgp.CheckArmoredDetachedSignature(keyring, bytes.NewReader(b), r.Body)
-		if err != nil {
-			return nil, err
-		}
-
-		for _, a := range config.Architectures {
-			for _, c := range config.Components {
-				u, err := url.Parse(aptRepo)
-				u.Path = path.Join(u.Path, "dists", dist, c, "binary-"+a, "Packages.gz")
-				r, err := http.Get(u.String())
-				if err != nil {
-					return nil, err
-				}
-				defer r.Body.Close()
-
-				buf, err := ioutil.ReadAll(r.Body)
-				if err != nil {
-					return nil, err
-				}
-
-				var checksum string
-				f := path.Join(c, "binary-"+a, "Packages.gz")
-				for _, l := range lines {
-					if strings.HasSuffix(l, f) {
-						checksum = strings.Fields(l)[0]
-						break
-					}
-				}
-				if checksum == "" {
-					return nil, fmt.Errorf("%s: checksum missing", f)
-				}
-
-				sum := sha256.Sum256(buf)
-				if checksum != hex.EncodeToString(sum[:]) {
-					return nil, fmt.Errorf("%s: checksum doesn't match", f)
-				}
-
-				g, err := gzip.NewReader(bytes.NewReader(buf))
-				if err != nil {
-					return nil, err
-				}
-
-				ps, err := parsePackages(g)
-				if err != nil {
-					return nil, err
-				}
-
-				// We only want development libraries, filter out everything else.
-				for _, p := range ps {
-					// Use sections as a coarse grained filter.
-					var section bool
-					switch p["Section"] {
-					case "libs", "libdevel", "devel", "x11":
-						section = true
-					}
-					// Use tags as a more fine-grained filter.
-					var tag bool
-					for _, n := range strings.Split(p["Tag"], ", ") {
-						t := strings.Split(strings.TrimSpace(n), " ")[0]
-						switch t {
-						case "devel::library", "x11::library", "role::devel-lib", "role::shared-lib":
-							tag = true
-						}
-					}
-					// Skip everything that doesn't match.
-					if section && tag {
-						n := p["Package"]
-						if _, ok := descriptors[n]; !ok {
-							descriptors[n] = map[string]Descriptor{}
-						}
-						descriptors[n][a] = p
-					}
-				}
-			}
-		}
-	}
-
-	type dependency struct {
-		name         string
-		architecture string
-	}
-
-	// Place the initial set of packages into queue.
-	var queue []dependency
-	for _, p := range config.Packages {
-		if len(p.Architectures) > 0 {
-			for _, a := range p.Architectures {
-				queue = append(queue, dependency{
-					name:         p.Name,
-					architecture: a,
-				})
-			}
-		} else {
-			for _, a := range config.Architectures {
-				queue = append(queue, dependency{
-					name:         p.Name,
-					architecture: a,
-				})
-			}
-		}
-	}
-
-	// Process all dependencies until we drain the queue.
-	locks := map[string]map[string]Lock{}
-	for len(queue) > 0 {
-		p := queue[0]
-		queue = queue[1:]
-		if lock, ok := locks[p.name]; ok {
-			if _, ok := lock[p.architecture]; ok {
-				continue
-			}
-		}
-		if ds, ok := descriptors[p.name]; ok {
-			if _, ok := locks[p.name]; !ok {
-				locks[p.name] = map[string]Lock{}
-			}
-			if pkg, ok := ds[p.architecture]; ok {
-				locks[p.name][p.architecture] = Lock{
-					Name:     pkg["Package"],
-					Version:  pkg["Version"],
-					Filename: pkg["Filename"],
-					Hash:     pkg["SHA256"],
-				}
-				if depends {
-					for _, n := range strings.Split(pkg["Depends"], ", ") {
-						d := strings.Split(strings.TrimSpace(n), " ")[0]
-						queue = append(queue, dependency{
-							name:         d,
-							architecture: p.architecture,
-						})
-					}
-				}
-			} else {
-				return nil, fmt.Errorf("package %q not found for architecture %q", p.name, p.architecture)
-			}
-		} else {
-			return nil, fmt.Errorf("package %q not found", p.name)
-		}
-	}
-
-	// Eliminate all duplicates.
-	hashes := map[string]Lock{}
-	for _, l := range locks {
-		for _, p := range l {
-			hashes[p.Hash] = p
-		}
-	}
-
-	// Flatten into a list.
-	var list []Lock
-	for _, p := range hashes {
-		list = append(list, p)
-	}
-
-	return list, nil
-}
-
-func relativize(link, target, dir string, patterns []string) error {
-	for _, p := range patterns {
-		matches, err := filepath.Glob(filepath.Join(dir, p))
-		if err != nil {
-			return err
-		}
-		for _, m := range matches {
-			if link == m {
-				if err := os.Remove(link); err != nil {
-					return err
-				}
-				relDir := ".." + strings.Repeat("/..", strings.Count(p, "/")-1)
-				if err := os.Symlink(relDir+target, link); err != nil {
-					return err
-				}
-				return nil
-			}
-		}
-	}
-	return nil
-}
-
-func installSysroot(list []Lock, installDir, debsCache string) error {
-	if err := os.MkdirAll(debsCache, 0777); err != nil {
-		return err
-	}
-
-	if err := os.RemoveAll(installDir); err != nil {
-		return err
-	}
-
-	// This is only needed when running dpkg-shlibdeps.
-	if err := os.MkdirAll(filepath.Join(installDir, "debian"), 0777); err != nil {
-		return err
-	}
-
-	// An empty control file is necessary to run dpkg-shlibdeps.
-	if file, err := os.OpenFile(filepath.Join(installDir, "debian", "control"), os.O_RDONLY|os.O_CREATE, 0644); err != nil {
-		return err
-	} else {
-		file.Close()
-	}
-
-	for _, pkg := range list {
-		filename := filepath.Base(pkg.Filename)
-		deb := filepath.Join(debsCache, filename)
-		if _, err := os.Stat(deb); os.IsNotExist(err) {
-			fmt.Printf("Downloading %s...\n", filename)
-
-			u, err := url.Parse(aptRepo)
-			u.Path = path.Join(u.Path, pkg.Filename)
-			r, err := http.Get(u.String())
-			if err != nil {
-				return err
-			}
-			defer r.Body.Close()
-
-			buf, err := ioutil.ReadAll(r.Body)
-			if err != nil {
-				return err
-			}
-
-			sum := sha256.Sum256(buf)
-			if pkg.Hash != hex.EncodeToString(sum[:]) {
-				return fmt.Errorf("%s: checksum doesn't match", filename)
-			}
-
-			if err := ioutil.WriteFile(deb, buf, 0644); err != nil {
-				return err
-			}
-		}
-
-		fmt.Printf("Installing %s...\n", filename)
-		// Extract the content of the package into the install directory.
-		err := exec.Command("dpkg-deb", "-x", deb, installDir).Run()
-		if err != nil {
-			return err
-		}
-		// Get the package name.
-		cmd := exec.Command("dpkg-deb", "--field", deb, "Package")
-		stdout, err := cmd.StdoutPipe()
-		if err != nil {
-			return err
-		}
-		if err := cmd.Start(); err != nil {
-			return err
-		}
-		r := bufio.NewReader(stdout)
-		baseDir, _, err := r.ReadLine()
-		if err != nil {
-			return err
-		}
-		if err := cmd.Wait(); err != nil {
-			return err
-		}
-		// Construct the path which contains the control information files.
-		controlDir := filepath.Join(installDir, "debian", string(baseDir), "DEBIAN")
-		if err := os.MkdirAll(controlDir, 0777); err != nil {
-			return err
-		}
-		// Extract the control information files.
-		err = exec.Command("dpkg-deb", "-e", deb, controlDir).Run()
-		if err != nil {
-			return err
-		}
-	}
-
-	// Prune /usr/share, leave only pkgconfig files.
-	files, err := ioutil.ReadDir(filepath.Join(installDir, "usr", "share"))
-	if err != nil {
-		return err
-	}
-	for _, file := range files {
-		if file.Name() != "pkgconfig" {
-			if err := os.RemoveAll(filepath.Join(installDir, "usr", "share", file.Name())); err != nil {
-				return err
-			}
-		}
-	}
-
-	// Ensure that we don't have duplicate file names that only differ in case.
-	type rename struct{ oldpath, newpath string }
-	renames := []rename{}
-
-	for _, d := range []string{"usr/include/linux"} {
-		p := filepath.Join(installDir, d)
-		if _, err := os.Stat(p); os.IsNotExist(err) {
-			continue
-		}
-		paths := make(map[string][]string)
-		if err := filepath.Walk(p, func(path string, info os.FileInfo, err error) error {
-			if err != nil {
-				return err
-			}
-			if info.Mode().IsRegular() && filepath.Ext(path) == ".h" {
-				name := strings.ToLower(path)
-				if _, ok := paths[name]; !ok {
-					paths[name] = []string{}
-				}
-				paths[name] = append(paths[name], path)
-			}
-			return nil
-		}); err != nil {
-			return err
-		}
-
-		for _, ps := range paths {
-			if len(ps) > 1 {
-				sort.Sort(sort.Reverse(sort.StringSlice(ps)))
-				for i, p := range ps {
-					if i > 0 {
-						ext := filepath.Ext(p)
-						renames = append(renames, rename{p, p[:len(p)-len(ext)] + strings.Repeat("_", i) + ext})
-					}
-				}
-			}
-		}
-	}
-
-	for _, r := range renames {
-		fmt.Printf("Renaming %s to %s\n", r.oldpath, r.newpath)
-		if err := os.Rename(r.oldpath, r.newpath); err != nil {
-			return err
-		}
-	}
-
-	for _, d := range []string{"usr/include/linux"} {
-		p := filepath.Join(installDir, d)
-		if _, err := os.Stat(p); os.IsNotExist(err) {
-			continue
-		}
-		if err := filepath.Walk(p, func(path string, info os.FileInfo, err error) error {
-			if err != nil {
-				return err
-			}
-			update := false
-			if info.Mode().IsRegular() && filepath.Ext(path) == ".h" {
-				content, err := ioutil.ReadFile(path)
-				if err != nil {
-					return err
-				}
-				for _, r := range renames {
-					oldbase := filepath.Base(r.oldpath)
-					newbase := filepath.Base(r.newpath)
-					if strings.Contains(string(content), oldbase) {
-						content = bytes.Replace(content, []byte(oldbase), []byte(newbase), 1)
-						update = true
-					}
-				}
-				if update {
-					fmt.Printf("Updating %s...\n", path)
-					if err := ioutil.WriteFile(path, content, info.Mode()); err != nil {
-						return err
-					}
-				}
-			}
-			return nil
-		}); err != nil {
-			return err
-		}
-	}
-
-	// Relativize all symlinks within the sysroot.
-	for _, d := range []string{"usr/lib", "lib64", "lib"} {
-		p := filepath.Join(installDir, d)
-		if _, err := os.Stat(p); os.IsNotExist(err) {
-			continue
-		}
-		if err := filepath.Walk(p, func(path string, info os.FileInfo, err error) error {
-			if err != nil {
-				return err
-			}
-			if info.Mode()&os.ModeSymlink == os.ModeSymlink {
-				target, err := os.Readlink(path)
-				if err != nil {
-					return err
-				}
-				if !filepath.IsAbs(target) {
-					return nil
-				}
-				patterns := []string{
-					"usr/lib/gcc/*-linux-gnu*/*/*",
-					"usr/lib/*-linux-gnu*/*",
-					"usr/lib/*",
-					"lib64/*",
-					"lib/*",
-				}
-				if err := relativize(path, target, installDir, patterns); err != nil {
-					return err
-				}
-				if _, err := os.Stat(path); os.IsNotExist(err) {
-					return fmt.Errorf("%s: broken link", path)
-				}
-			}
-			return nil
-		}); err != nil {
-			return err
-		}
-	}
-
-	// Rewrite and relativize all linkerscripts.
-	linkerscripts := []string{
-		"usr/lib/*-linux-gnu*/libpthread.so",
-		"usr/lib/*-linux-gnu*/libc.so",
-	}
-	for _, l := range linkerscripts {
-		matches, err := filepath.Glob(filepath.Join(installDir, l))
-		if err != nil {
-			return err
-		}
-		for _, path := range matches {
-			read, err := ioutil.ReadFile(path)
-			if err != nil {
-				return err
-			}
-			sub := regexp.MustCompile(`(/usr)?/lib/[a-z0-9_]+-linux-gnu[a-z0-9]*/`)
-			contents := sub.ReplaceAllString(string(read), "")
-			if err := ioutil.WriteFile(path, []byte(contents), 0644); err != nil {
-				return err
-			}
-		}
-	}
-
-	if err := os.RemoveAll(filepath.Join(installDir, "debian")); err != nil {
-		return err
-	}
-
-	return nil
-}
-
-type updateCmd struct {
-	config   string
-	lockfile string
-	depends  bool
-}
-
-func (*updateCmd) Name() string     { return "update" }
-func (*updateCmd) Synopsis() string { return "Update the lock file." }
-func (*updateCmd) Usage() string {
-	return `update [-config] [-lock] [-depends]:
-	Update the lock file to include specific package versions.
-`
-}
-
-func (c *updateCmd) SetFlags(f *flag.FlagSet) {
-	f.StringVar(&c.config, "config", "packages.yml", "Package configuration")
-	f.StringVar(&c.lockfile, "lock", "packages.lock", "Lockfile filename")
-	f.BoolVar(&c.depends, "depends", false, "Transitively include dependencies")
-}
-
-func (c *updateCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
-	d, err := ioutil.ReadFile(c.config)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "failed to read config: %v\n", err)
-		return subcommands.ExitFailure
-	}
-	config := &Config{}
-	if err := yaml.Unmarshal(d, &config); err != nil {
-		fmt.Fprintf(os.Stderr, "failed to unmarshal config: %v\n", err)
-		return subcommands.ExitFailure
-	}
-
-	if _, err := os.Stat(config.Keyring); os.IsNotExist(err) {
-		fmt.Fprintf(os.Stderr, "keyring file '%s' missing\n", config.Keyring)
-		return subcommands.ExitUsageError
-	}
-
-	list, err := downloadPackageList(config, c.depends)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "failed to download package list: %v\n", err)
-		return subcommands.ExitFailure
-	}
-	sort.Sort(Locks(list))
-
-	hash := sha256.New()
-	hash.Write(d)
-
-	lockfile := Lockfile{
-		Updated:  time.Now(),
-		Hash:     fmt.Sprintf("%x", hash.Sum(nil)),
-		Packages: list,
-	}
-
-	l, err := yaml.Marshal(&lockfile)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "failed to marshal lockfile: %v\n", err)
-		return subcommands.ExitFailure
-	}
-
-	if err := ioutil.WriteFile(c.lockfile, l, 0666); err != nil {
-		fmt.Fprintf(os.Stderr, "failed to write lockfile: %v\n", err)
-		return subcommands.ExitFailure
-	}
-
-	return subcommands.ExitSuccess
-}
-
-type installCmd struct {
-	outDir    string
-	debsCache string
-}
-
-func (*installCmd) Name() string     { return "install" }
-func (*installCmd) Synopsis() string { return "Install packages" }
-func (*installCmd) Usage() string {
-	return `install [-out] [-cache] <lockfile>:
-  Install the specific versions from the lock file.
-`
-}
-
-func (c *installCmd) SetFlags(f *flag.FlagSet) {
-	f.StringVar(&c.outDir, "out", "sysroot", "Output directory")
-	f.StringVar(&c.debsCache, "cache", "debs", "Cache for .deb files")
-}
-
-func (c *installCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
-	if len(f.Args()) != 1 {
-		fmt.Fprintln(os.Stderr, "missing lockfile argument")
-		return subcommands.ExitUsageError
-	}
-	lockfile := f.Args()[0]
-
-	d, err := ioutil.ReadFile(lockfile)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "failed to read lockfile: %v\n", err)
-		return subcommands.ExitFailure
-	}
-	var lock Lockfile
-	if err := yaml.Unmarshal(d, &lock); err != nil {
-		fmt.Fprintf(os.Stderr, "failed to unmarshal lockfile: %v\n", err)
-		return subcommands.ExitFailure
-	}
-
-	if err := installSysroot(lock.Packages, c.outDir, c.debsCache); err != nil {
-		fmt.Fprintf(os.Stderr, "failed to install sysroot: %v\n", err)
-		return subcommands.ExitFailure
-	}
-	return subcommands.ExitSuccess
-}
-
-func main() {
-	subcommands.Register(subcommands.HelpCommand(), "")
-	subcommands.Register(subcommands.FlagsCommand(), "")
-	subcommands.Register(subcommands.CommandsCommand(), "")
-	subcommands.Register(&updateCmd{}, "")
-	subcommands.Register(&installCmd{}, "")
-
-	flag.Parse()
-	ctx := context.Background()
-	os.Exit(int(subcommands.Execute(ctx)))
-}
diff --git a/debroot/cmd/packages.lock b/debroot/cmd/packages.lock
deleted file mode 100644
index bd08182..0000000
--- a/debroot/cmd/packages.lock
+++ /dev/null
@@ -1,403 +0,0 @@
-hash: 8727abfc278cd94cc0b6d4285f92eca18f7495bf7650a26e416ad585c9b3f65a
-updated: 2019-08-14T21:38:48.608392147-07:00
-packages:
-- package: libc6
-  version: 2.19-18+deb8u10
-  filename: pool/main/g/glibc/libc6_2.19-18+deb8u10_amd64.deb
-  hash: 0a95ee1c5bff7f73c1279b2b78f32d40da9025a76f93cb67c03f2867a7133e61
-- package: libc6
-  version: 2.19-18+deb8u10
-  filename: pool/main/g/glibc/libc6_2.19-18+deb8u10_arm64.deb
-  hash: b52eab4f1beeb020e20fb44bc2dc02a9ccf12fc70213d6a56921e08308bc3e9c
-- package: libc6
-  version: 2.19-18+deb8u10
-  filename: pool/main/g/glibc/libc6_2.19-18+deb8u10_armhf.deb
-  hash: ccfc4a10a1654454ad07ac381d55dc1bfe0787ebbcd87b42ac05402777ce41b5
-- package: libc6
-  version: 2.19-18+deb8u10
-  filename: pool/main/g/glibc/libc6_2.19-18+deb8u10_i386.deb
-  hash: 1d1f82f905386ff6a1dab08ec69b3b1d8bddbfd7c41b68e295e0a204232ad1ae
-- package: libc6-dev
-  version: 2.19-18+deb8u10
-  filename: pool/main/g/glibc/libc6-dev_2.19-18+deb8u10_amd64.deb
-  hash: 00ba98ce8879bdfde13eac699da718d3aaba904ea6a88d5e21e77d1e298d65eb
-- package: libc6-dev
-  version: 2.19-18+deb8u10
-  filename: pool/main/g/glibc/libc6-dev_2.19-18+deb8u10_arm64.deb
-  hash: 9cf8ae92bb508873e19b43975b5841166fc2476664d9de52eb62ae3a1a50abb3
-- package: libc6-dev
-  version: 2.19-18+deb8u10
-  filename: pool/main/g/glibc/libc6-dev_2.19-18+deb8u10_armhf.deb
-  hash: b5af7102716127343a82dfdb42e5b9cd9dc28e28fc14653e0db8f9efdd1fe0a9
-- package: libc6-dev
-  version: 2.19-18+deb8u10
-  filename: pool/main/g/glibc/libc6-dev_2.19-18+deb8u10_i386.deb
-  hash: 287ea40a96c4eafb94843169f6bf802335182b68f78a1b4bab95851c3385866d
-- package: libgl1-mesa-dev
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/libgl1-mesa-dev_10.3.2-1+deb8u1_amd64.deb
-  hash: b790d56135725193fc38216d4c6017003209d23e4250147882f075b5622e5e06
-- package: libgl1-mesa-dev
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/libgl1-mesa-dev_10.3.2-1+deb8u1_arm64.deb
-  hash: b363bbe43937a7f23a868e64b278e29f3f45b7608cdc41f295f6088b566b045c
-- package: libgl1-mesa-dev
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/libgl1-mesa-dev_10.3.2-1+deb8u1_armhf.deb
-  hash: 81f7f98b50e513b5b21f0265542a5544b2c97a2e8f059c79b4e6208dc5d5e656
-- package: libgl1-mesa-dev
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/libgl1-mesa-dev_10.3.2-1+deb8u1_i386.deb
-  hash: 754a9968ea861842a289fa34ca68123723170eb308bd5c64cc7cdb69a939fdbd
-- package: libgl1-mesa-glx
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/libgl1-mesa-glx_10.3.2-1+deb8u1_amd64.deb
-  hash: de91fad0ffb35ba497ec146ccfa261df79dced33ffc6f9e229435dadeac49e64
-- package: libgl1-mesa-glx
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/libgl1-mesa-glx_10.3.2-1+deb8u1_arm64.deb
-  hash: e22ec22e5a46920c6340ea3224a43ec677f728d368fe34421d51d304046a62a0
-- package: libgl1-mesa-glx
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/libgl1-mesa-glx_10.3.2-1+deb8u1_armhf.deb
-  hash: f62a51c6968c9b7b0312081816c538cc4ff49c3a799722f06e492bf0e13ca259
-- package: libgl1-mesa-glx
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/libgl1-mesa-glx_10.3.2-1+deb8u1_i386.deb
-  hash: 11aee5275de4a92d297a785f79ffc1696db99e2761af63355aa7ebe34139ecaa
-- package: libglapi-mesa
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/libglapi-mesa_10.3.2-1+deb8u1_amd64.deb
-  hash: 8f77452524501072c09676bd1acf4b71d864d7d2a18fa8158aa5a5cb0bc3ade3
-- package: libglapi-mesa
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/libglapi-mesa_10.3.2-1+deb8u1_arm64.deb
-  hash: 24007141988b34aab55abf03a606ea590ac71d62e6cd0aac015427cfab6c0df4
-- package: libglapi-mesa
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/libglapi-mesa_10.3.2-1+deb8u1_armhf.deb
-  hash: 7098825f957f7bcf216f65fbb8e1c3efe6365041103f77a412f0c8c1145de17f
-- package: libglapi-mesa
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/libglapi-mesa_10.3.2-1+deb8u1_i386.deb
-  hash: 3b39319fbb66afcf17ba1e6bef9c5583eb873cbd14621821143babb0f855529e
-- package: libx11-6
-  version: 2:1.6.2-3+deb8u1
-  filename: pool/main/libx/libx11/libx11-6_1.6.2-3+deb8u1_amd64.deb
-  hash: 380aa38372e949f74b57e962146626aae847850ed4f1fcb83784086f239d50c3
-- package: libx11-6
-  version: 2:1.6.2-3+deb8u1
-  filename: pool/main/libx/libx11/libx11-6_1.6.2-3+deb8u1_arm64.deb
-  hash: 20ce433137bd35b1f131dadf8dd0f4bedfeac804ae875d495d572b52b9f238cd
-- package: libx11-6
-  version: 2:1.6.2-3+deb8u1
-  filename: pool/main/libx/libx11/libx11-6_1.6.2-3+deb8u1_armhf.deb
-  hash: 29b2da94d351278e0682f86b290724998b6aace8dd730a23930feb5ad11662e7
-- package: libx11-6
-  version: 2:1.6.2-3+deb8u1
-  filename: pool/main/libx/libx11/libx11-6_1.6.2-3+deb8u1_i386.deb
-  hash: 7f55cb1a60fdd6a02bda2c00d6a438f836404681d0e7a8ce7c93cee1545ef7ca
-- package: libx11-dev
-  version: 2:1.6.2-3+deb8u1
-  filename: pool/main/libx/libx11/libx11-dev_1.6.2-3+deb8u1_amd64.deb
-  hash: cd141e5c95d7b5f05df08a8e66abbbdb9a2a7213f9f4354b862925fac6106334
-- package: libx11-dev
-  version: 2:1.6.2-3+deb8u1
-  filename: pool/main/libx/libx11/libx11-dev_1.6.2-3+deb8u1_arm64.deb
-  hash: fb9e44a7520dd7cc9ec911954fc4896c31aff683c56a8fbf64867b1e184dd7f2
-- package: libx11-dev
-  version: 2:1.6.2-3+deb8u1
-  filename: pool/main/libx/libx11/libx11-dev_1.6.2-3+deb8u1_armhf.deb
-  hash: d5b0c2b3e8939e896da089757151a9f1f202b0e65134ed453b37d465566acd25
-- package: libx11-dev
-  version: 2:1.6.2-3+deb8u1
-  filename: pool/main/libx/libx11/libx11-dev_1.6.2-3+deb8u1_i386.deb
-  hash: 82fd52f4db77855cbf76f274550ff07d2a4bfe62a9c9d10e0345e7c8dece4188
-- package: libxcursor-dev
-  version: 1:1.1.14-1+deb8u1
-  filename: pool/main/libx/libxcursor/libxcursor-dev_1.1.14-1+deb8u1_amd64.deb
-  hash: 101d83f1368cef54594100b849843df0d1952b0155b707f2256914d4e2d9debc
-- package: libxcursor-dev
-  version: 1:1.1.14-1+deb8u1
-  filename: pool/main/libx/libxcursor/libxcursor-dev_1.1.14-1+deb8u1_arm64.deb
-  hash: 5c5125291e5258deac4442fe363c7da162329125e46e9d18add6efee5a6a7ba3
-- package: libxcursor-dev
-  version: 1:1.1.14-1+deb8u1
-  filename: pool/main/libx/libxcursor/libxcursor-dev_1.1.14-1+deb8u1_armhf.deb
-  hash: 3836920c14f8e9ecd3aabe31b4b3526e135125f3712cba4b4a030a218be1699b
-- package: libxcursor-dev
-  version: 1:1.1.14-1+deb8u1
-  filename: pool/main/libx/libxcursor/libxcursor-dev_1.1.14-1+deb8u1_i386.deb
-  hash: 61a4618472acb9cd464c1f42b304d5250cf0fe71212682453031f7fde172d799
-- package: libxcursor1
-  version: 1:1.1.14-1+deb8u1
-  filename: pool/main/libx/libxcursor/libxcursor1_1.1.14-1+deb8u1_amd64.deb
-  hash: 31c05ccd419d5c255643e3d21c871204e154a06af25300c2bd2b721989d038f0
-- package: libxcursor1
-  version: 1:1.1.14-1+deb8u1
-  filename: pool/main/libx/libxcursor/libxcursor1_1.1.14-1+deb8u1_arm64.deb
-  hash: ce62dcf433498d25f2534213f48184e08ca72abe11454041cf96d845bc32d062
-- package: libxcursor1
-  version: 1:1.1.14-1+deb8u1
-  filename: pool/main/libx/libxcursor/libxcursor1_1.1.14-1+deb8u1_armhf.deb
-  hash: 87a99212079783b499b402426796d2ceb07e14f1b972e4e73f7e25ec3046fa9a
-- package: libxcursor1
-  version: 1:1.1.14-1+deb8u1
-  filename: pool/main/libx/libxcursor/libxcursor1_1.1.14-1+deb8u1_i386.deb
-  hash: 771530e98891da87de8c15156d2a2d06ab293086a35f5167f9116548f41900c4
-- package: libxext-dev
-  version: 2:1.3.3-1
-  filename: pool/main/libx/libxext/libxext-dev_1.3.3-1_amd64.deb
-  hash: 35d62e8b6c72ea9ae67488f06360224a918f6d87ceb27575f49a9e712bf8b70a
-- package: libxext-dev
-  version: 2:1.3.3-1
-  filename: pool/main/libx/libxext/libxext-dev_1.3.3-1_arm64.deb
-  hash: c8abe305d5b35eb2f6b342f72e6fd2294748eb6254b21fb3d68e288c864a70e9
-- package: libxext-dev
-  version: 2:1.3.3-1
-  filename: pool/main/libx/libxext/libxext-dev_1.3.3-1_armhf.deb
-  hash: 0a23e3dd6f6fcb51219b75654bac5df8ff92ef029d8203e6efebcf0c9047501c
-- package: libxext-dev
-  version: 2:1.3.3-1
-  filename: pool/main/libx/libxext/libxext-dev_1.3.3-1_i386.deb
-  hash: 5f1e821fcc241d642e15c0a966536e12320aaf319dbd9738a7715108f3ad22ab
-- package: libxext6
-  version: 2:1.3.3-1
-  filename: pool/main/libx/libxext/libxext6_1.3.3-1_amd64.deb
-  hash: 5105f77289a7e08faaf3bb4c16c6945cafca65b9bdb4792fef820045ab43e568
-- package: libxext6
-  version: 2:1.3.3-1
-  filename: pool/main/libx/libxext/libxext6_1.3.3-1_arm64.deb
-  hash: 2d9b203682b2ac5e3cb3e585e6a51e59bd7ac32486827586a4ca121e84c8d794
-- package: libxext6
-  version: 2:1.3.3-1
-  filename: pool/main/libx/libxext/libxext6_1.3.3-1_armhf.deb
-  hash: c98094a2dcc1965bb04ed8929fca6899e1cad3ad1e0f29a5c20a79338dacb702
-- package: libxext6
-  version: 2:1.3.3-1
-  filename: pool/main/libx/libxext/libxext6_1.3.3-1_i386.deb
-  hash: d9025901af98bcda89028753583e146989f6f25eacbb7b073f2bfe4619a0fb79
-- package: libxfixes-dev
-  version: 1:5.0.1-2+deb8u1
-  filename: pool/main/libx/libxfixes/libxfixes-dev_5.0.1-2+deb8u1_amd64.deb
-  hash: 4dc7467a9dbc531d95884217437e2e8e856c8f211fe3fcebb2297998f72901b3
-- package: libxfixes-dev
-  version: 1:5.0.1-2+deb8u1
-  filename: pool/main/libx/libxfixes/libxfixes-dev_5.0.1-2+deb8u1_arm64.deb
-  hash: 3ce4c58fd7a97cf3217a4ac35c495e444d944dedb22b3893cffeecd475fe8f60
-- package: libxfixes-dev
-  version: 1:5.0.1-2+deb8u1
-  filename: pool/main/libx/libxfixes/libxfixes-dev_5.0.1-2+deb8u1_armhf.deb
-  hash: 7c0fecdc8973056fb32aa9255b58536236bfde0b2fe0bfdbfbad8beff79b2216
-- package: libxfixes-dev
-  version: 1:5.0.1-2+deb8u1
-  filename: pool/main/libx/libxfixes/libxfixes-dev_5.0.1-2+deb8u1_i386.deb
-  hash: ae0692bbc186ec19d610b5bc5a027bdd33563887f19d780b1b2024c3702802aa
-- package: libxfixes3
-  version: 1:5.0.1-2+deb8u1
-  filename: pool/main/libx/libxfixes/libxfixes3_5.0.1-2+deb8u1_amd64.deb
-  hash: bc30bf139964c7505776374c7ba8a7f9bd7c6bd101823f3d6a1f3b0bf11e41ee
-- package: libxfixes3
-  version: 1:5.0.1-2+deb8u1
-  filename: pool/main/libx/libxfixes/libxfixes3_5.0.1-2+deb8u1_arm64.deb
-  hash: 8e9d0fbc96e12fa7a3400901b7deb755ca46b21e52c2c4852c59e28c95b20c04
-- package: libxfixes3
-  version: 1:5.0.1-2+deb8u1
-  filename: pool/main/libx/libxfixes/libxfixes3_5.0.1-2+deb8u1_armhf.deb
-  hash: fda5f4b0cd09388acab581e59c2064e0398e23f3677c06ab82477ac615759016
-- package: libxfixes3
-  version: 1:5.0.1-2+deb8u1
-  filename: pool/main/libx/libxfixes/libxfixes3_5.0.1-2+deb8u1_i386.deb
-  hash: 44f2d8cb572ff8e2a5c6dcd9d0aa42eda7a0eed0c50a403cc9239d6d3a2bf308
-- package: libxi-dev
-  version: 2:1.7.4-1+deb8u1
-  filename: pool/main/libx/libxi/libxi-dev_1.7.4-1+deb8u1_amd64.deb
-  hash: 77dd8c34c69d86dec841028c0fca646544cea079ee95643db3fdc15cbdf9d8bf
-- package: libxi-dev
-  version: 2:1.7.4-1+deb8u1
-  filename: pool/main/libx/libxi/libxi-dev_1.7.4-1+deb8u1_arm64.deb
-  hash: 5aee0969b1792e41ab7e3b4dfe0bd1e2657cb32fe3e880a25bf87a3a645f9cdc
-- package: libxi-dev
-  version: 2:1.7.4-1+deb8u1
-  filename: pool/main/libx/libxi/libxi-dev_1.7.4-1+deb8u1_armhf.deb
-  hash: de4bb8afb8f2fc3e083cc89e39aa839b7af3c40ab312bb1ac7342bdfb2f605f2
-- package: libxi-dev
-  version: 2:1.7.4-1+deb8u1
-  filename: pool/main/libx/libxi/libxi-dev_1.7.4-1+deb8u1_i386.deb
-  hash: 4ed707f9a73f7381fe7e16c4f4099f47b025700465dfada8aa7c8678f4e8a657
-- package: libxi6
-  version: 2:1.7.4-1+deb8u1
-  filename: pool/main/libx/libxi/libxi6_1.7.4-1+deb8u1_amd64.deb
-  hash: a99de627a07f54bc40e5dc77e3ca7e9d9b5619e068f1bb303f86edd138d6d037
-- package: libxi6
-  version: 2:1.7.4-1+deb8u1
-  filename: pool/main/libx/libxi/libxi6_1.7.4-1+deb8u1_arm64.deb
-  hash: fddbfdce740bd5a74cb34d69d10d0e42a9abff78cd89e7119cdf21a8e3dd5d3a
-- package: libxi6
-  version: 2:1.7.4-1+deb8u1
-  filename: pool/main/libx/libxi/libxi6_1.7.4-1+deb8u1_armhf.deb
-  hash: 79c53ea34b9a7c239a75aac28386ca2614f7add0be3578ca4710705ba3e0bd66
-- package: libxi6
-  version: 2:1.7.4-1+deb8u1
-  filename: pool/main/libx/libxi/libxi6_1.7.4-1+deb8u1_i386.deb
-  hash: d6f5e16a2ea39f045273b8ab1ac64436ce6df0b21fb77f3839d298ebdac297e5
-- package: libxinerama-dev
-  version: 2:1.1.3-1+b1
-  filename: pool/main/libx/libxinerama/libxinerama-dev_1.1.3-1+b1_amd64.deb
-  hash: 0e2504bbe3501aae376691e2519336533309c8a97715f8a2b060cdcd6abce15f
-- package: libxinerama-dev
-  version: 2:1.1.3-1+b1
-  filename: pool/main/libx/libxinerama/libxinerama-dev_1.1.3-1+b1_arm64.deb
-  hash: 9094a4298c357455ea4a4094ecdf93a85a1ab404630e35da1dedad5b08e30f27
-- package: libxinerama-dev
-  version: 2:1.1.3-1+b1
-  filename: pool/main/libx/libxinerama/libxinerama-dev_1.1.3-1+b1_armhf.deb
-  hash: 49d378db7c271db6b3befc7cc73448177b4515424d17e400b053f199df4b2a77
-- package: libxinerama-dev
-  version: 2:1.1.3-1+b1
-  filename: pool/main/libx/libxinerama/libxinerama-dev_1.1.3-1+b1_i386.deb
-  hash: 490439d9ebff2e4bc324e5d418d4d9a245a223b5d211de3189cabd78ff7b47d7
-- package: libxinerama1
-  version: 2:1.1.3-1+b1
-  filename: pool/main/libx/libxinerama/libxinerama1_1.1.3-1+b1_amd64.deb
-  hash: 3668c1178ac649879338192759e79879e0f5797764b448dcac6aed4b24ef495b
-- package: libxinerama1
-  version: 2:1.1.3-1+b1
-  filename: pool/main/libx/libxinerama/libxinerama1_1.1.3-1+b1_arm64.deb
-  hash: e573c84cb609a8799db03b19f1529153048d9e04307e8721fa4f0b516cb47171
-- package: libxinerama1
-  version: 2:1.1.3-1+b1
-  filename: pool/main/libx/libxinerama/libxinerama1_1.1.3-1+b1_armhf.deb
-  hash: 9fcc2234beb0eb4e0ca3a38d93d38655a433551c04b3d73aa06ca020121d5d2f
-- package: libxinerama1
-  version: 2:1.1.3-1+b1
-  filename: pool/main/libx/libxinerama/libxinerama1_1.1.3-1+b1_i386.deb
-  hash: a1f29a26a81405df89d2ddf64990d9e32d7b642130334db66f063d78c5574633
-- package: libxrandr-dev
-  version: 2:1.4.2-1+deb8u1
-  filename: pool/main/libx/libxrandr/libxrandr-dev_1.4.2-1+deb8u1_amd64.deb
-  hash: d64ac2abe410fe6e25c6de2b90fd2a65dbfdf027c117a574714a0a60c019738f
-- package: libxrandr-dev
-  version: 2:1.4.2-1+deb8u1
-  filename: pool/main/libx/libxrandr/libxrandr-dev_1.4.2-1+deb8u1_arm64.deb
-  hash: d1c1c132da1d809acc8e3b11f173c5a28ba28e76d70dd81123cbf41c6fbb90eb
-- package: libxrandr-dev
-  version: 2:1.4.2-1+deb8u1
-  filename: pool/main/libx/libxrandr/libxrandr-dev_1.4.2-1+deb8u1_armhf.deb
-  hash: 712357a9065f49f4174e04ddb49e2e1eac63a168c27ae9737f04a463e309757d
-- package: libxrandr-dev
-  version: 2:1.4.2-1+deb8u1
-  filename: pool/main/libx/libxrandr/libxrandr-dev_1.4.2-1+deb8u1_i386.deb
-  hash: 727435c3854fec93401eb2421842a5749cc113797799dccfa246d6f9b2f22f84
-- package: libxrandr2
-  version: 2:1.4.2-1+deb8u1
-  filename: pool/main/libx/libxrandr/libxrandr2_1.4.2-1+deb8u1_amd64.deb
-  hash: e59996ac0e993331799aa7bc768f7edd7b0baec0fafdbeebeef658834ba96b63
-- package: libxrandr2
-  version: 2:1.4.2-1+deb8u1
-  filename: pool/main/libx/libxrandr/libxrandr2_1.4.2-1+deb8u1_arm64.deb
-  hash: 713b2b8a05bc05dc61fa158b2fb4f665272d2f60a86f4bcb15722aec3a02c9fd
-- package: libxrandr2
-  version: 2:1.4.2-1+deb8u1
-  filename: pool/main/libx/libxrandr/libxrandr2_1.4.2-1+deb8u1_armhf.deb
-  hash: 9c379b71846de6d3cb35191962caa5f15d0964fdfd277c3f39b56275dbd1566e
-- package: libxrandr2
-  version: 2:1.4.2-1+deb8u1
-  filename: pool/main/libx/libxrandr/libxrandr2_1.4.2-1+deb8u1_i386.deb
-  hash: c14134e213a1020e4848f927612377bce319a6a4640b5d572009cb8929b0142a
-- package: libxrender-dev
-  version: 1:0.9.8-1+b1
-  filename: pool/main/libx/libxrender/libxrender-dev_0.9.8-1+b1_amd64.deb
-  hash: d17bd9a32eaecdd75d465d38bfc6318aa00e92fa5289ed36a8853f94feb18cbe
-- package: libxrender-dev
-  version: 1:0.9.8-1+b1
-  filename: pool/main/libx/libxrender/libxrender-dev_0.9.8-1+b1_arm64.deb
-  hash: 7149bd62f79f8f0d5ef8981722e3f1e7d3090b037bf850a607c2ca69f66cf2ad
-- package: libxrender-dev
-  version: 1:0.9.8-1+b1
-  filename: pool/main/libx/libxrender/libxrender-dev_0.9.8-1+b1_armhf.deb
-  hash: 031a2ebffde76e4c201f43c1b66a62a1af7c488877e541623fa5ab6b790abb07
-- package: libxrender-dev
-  version: 1:0.9.8-1+b1
-  filename: pool/main/libx/libxrender/libxrender-dev_0.9.8-1+b1_i386.deb
-  hash: e399b94ab1c07f7f1d8e72a43630f9e83ae439a279d81a51c9cd82848b986355
-- package: libxrender1
-  version: 1:0.9.8-1+b1
-  filename: pool/main/libx/libxrender/libxrender1_0.9.8-1+b1_amd64.deb
-  hash: 8980934c84c0ebbca4158023d91ced3ddbfa028a2be25959ff4566b37eceb8f4
-- package: libxrender1
-  version: 1:0.9.8-1+b1
-  filename: pool/main/libx/libxrender/libxrender1_0.9.8-1+b1_arm64.deb
-  hash: c2607cd67ff2eb60f88b2532e6999d1a3d31c55afa20ac9be431148a76374908
-- package: libxrender1
-  version: 1:0.9.8-1+b1
-  filename: pool/main/libx/libxrender/libxrender1_0.9.8-1+b1_armhf.deb
-  hash: 8bb5f345e6603bbdd151619e045637512e9c3dad27bd670983a50c15b4d98fb0
-- package: libxrender1
-  version: 1:0.9.8-1+b1
-  filename: pool/main/libx/libxrender/libxrender1_0.9.8-1+b1_i386.deb
-  hash: df3f4d61be300203ffde82c829e2bb0a72eceb4991161f419dc5a7ec061d92f9
-- package: linux-libc-dev
-  version: 3.16.51-3
-  filename: pool/main/l/linux/linux-libc-dev_3.16.51-3_amd64.deb
-  hash: 8cdc63378b6dfe8995f40cd6f04701e89dbca588e9a9c6fbbe524d1db4cb4f08
-- package: linux-libc-dev
-  version: 3.16.51-3
-  filename: pool/main/l/linux/linux-libc-dev_3.16.51-3_arm64.deb
-  hash: f2e7ab5f0cc3dd03cd7278e5574dc25b744a399f75cb2890c346a064954779dd
-- package: linux-libc-dev
-  version: 3.16.51-3
-  filename: pool/main/l/linux/linux-libc-dev_3.16.51-3_armhf.deb
-  hash: 14bfef400b83e2f3a587dc564b7d13bf72f27f739d6a74d77a9326f83b3d9460
-- package: linux-libc-dev
-  version: 3.16.51-3
-  filename: pool/main/l/linux/linux-libc-dev_3.16.51-3_i386.deb
-  hash: 35def1939fccfd26335d000528a0053e6092a488abce9bbb47d94eb161115d1b
-- package: mesa-common-dev
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/mesa-common-dev_10.3.2-1+deb8u1_amd64.deb
-  hash: 6e617bfdbe9b87a82981b33d2be0963d3cba28160565658420859d84d07ef7a0
-- package: mesa-common-dev
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/mesa-common-dev_10.3.2-1+deb8u1_arm64.deb
-  hash: f22b5fa98c4e367d1753a18b2feabb9a1c8185abc727357a783567fe523d1e96
-- package: mesa-common-dev
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/mesa-common-dev_10.3.2-1+deb8u1_armhf.deb
-  hash: 19d7b6756d27ddca44356cb4cb3fcaee19dd8166cf64e52d0dfe51302ea39a21
-- package: mesa-common-dev
-  version: 10.3.2-1+deb8u1
-  filename: pool/main/m/mesa/mesa-common-dev_10.3.2-1+deb8u1_i386.deb
-  hash: 9d2de0e90cca097d380da9e5bd1fdfc34f15b71ba8da5de1289a930b79de5ac9
-- package: x11proto-core-dev
-  version: 7.0.26-1
-  filename: pool/main/x/x11proto-core/x11proto-core-dev_7.0.26-1_all.deb
-  hash: 9d60c962746bf2d1b1eb69e872a57eb21e13b341329ca592fd8eca527bab1df6
-- package: x11proto-fixes-dev
-  version: 1:5.0-2
-  filename: pool/main/x/x11proto-fixes/x11proto-fixes-dev_5.0-2_all.deb
-  hash: e08e0aa9b58ffccc7685c6715df77a9c00781575a6229b4497b06b32bd61336c
-- package: x11proto-gl-dev
-  version: 1.4.17-1
-  filename: pool/main/x/x11proto-gl/x11proto-gl-dev_1.4.17-1_all.deb
-  hash: 6ce92444e2fda684d5071667adb776152291f940696e547d73022d5ed66d3f10
-- package: x11proto-input-dev
-  version: 2.3.1-1
-  filename: pool/main/x/x11proto-input/x11proto-input-dev_2.3.1-1_all.deb
-  hash: a61a10b34cb0ffac6a2603971be1afd4908ed2830b6a1c554e74ac3321bb1e35
-- package: x11proto-kb-dev
-  version: 1.0.6-2
-  filename: pool/main/x/x11proto-kb/x11proto-kb-dev_1.0.6-2_all.deb
-  hash: b7ff8eceb9f05eb470700807c73fdae88f5f9f8b8fbef869029882264dbebd81
-- package: x11proto-randr-dev
-  version: 1.4.0-2
-  filename: pool/main/x/x11proto-randr/x11proto-randr-dev_1.4.0-2_all.deb
-  hash: 3d49d2e205da5d2ca4cdca8d5782e47da5c11ad762c046ffb6173beb5f0d837e
-- package: x11proto-render-dev
-  version: 2:0.11.1-2
-  filename: pool/main/x/x11proto-render/x11proto-render-dev_0.11.1-2_all.deb
-  hash: 606d63fab57421afe305e4866edb1948e4f9090409d6f63199838ac269d8cfba
-- package: x11proto-xext-dev
-  version: 7.3.0-1
-  filename: pool/main/x/x11proto-xext/x11proto-xext-dev_7.3.0-1_all.deb
-  hash: bb505470525281ad330093a9d9d23f4a36b00d0b8502dcbc05e44781375abdf0
diff --git a/debroot/cmd/packages.yml b/debroot/cmd/packages.yml
deleted file mode 100644
index b84421c..0000000
--- a/debroot/cmd/packages.yml
+++ /dev/null
@@ -1,43 +0,0 @@
-dists:
-  - jessie
-  - jessie-updates
-architectures:
-  - amd64
-  - arm64
-  - armhf
-  - i386
-components:
-  - main
-keyring: debian-archive-keyring.gpg
-packages:
-  - package: libc6
-  - package: libc6-dev
-  - package: libgl1-mesa-dev
-  - package: libgl1-mesa-glx
-  - package: libglapi-mesa
-  - package: libx11-6
-  - package: libx11-dev
-  - package: libxcursor1
-  - package: libxcursor-dev
-  - package: libxext6
-  - package: libxext-dev
-  - package: libxfixes3
-  - package: libxfixes-dev
-  - package: libxi6
-  - package: libxi-dev
-  - package: libxrandr2
-  - package: libxrandr-dev
-  - package: libxrender1
-  - package: libxrender-dev
-  - package: libxinerama1
-  - package: libxinerama-dev
-  - package: linux-libc-dev
-  - package: mesa-common-dev
-  - package: x11proto-core-dev
-  - package: x11proto-gl-dev
-  - package: x11proto-input-dev
-  - package: x11proto-kb-dev
-  - package: x11proto-randr-dev
-  - package: x11proto-render-dev
-  - package: x11proto-xext-dev
-  - package: x11proto-fixes-dev
diff --git a/debug/bloatalyzer/cmd/main.go b/debug/bloatalyzer/cmd/main.go
deleted file mode 100644
index fb161e8..0000000
--- a/debug/bloatalyzer/cmd/main.go
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2018 The Fuchsia 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 (
-	"context"
-	"encoding/json"
-	"flag"
-	"fmt"
-	"io"
-	"os"
-	"runtime"
-	"strings"
-
-	"go.fuchsia.dev/tools/debug/bloaty"
-	"go.fuchsia.dev/tools/lib/logger"
-)
-
-type Format int
-
-const (
-	FormatJSON Format = iota
-	FormatHTML
-)
-
-func (f *Format) Set(value string) error {
-	switch strings.ToLower(value) {
-	case "json":
-		*f = FormatJSON
-	case "html":
-		*f = FormatHTML
-	default:
-		return fmt.Errorf("Unknown format type.")
-	}
-	return nil
-}
-
-func (f *Format) String() string {
-	switch *f {
-	case FormatJSON:
-		return "json"
-	case FormatHTML:
-		return "html"
-	default:
-		return "unknown"
-	}
-}
-
-var (
-	bloatyPath string
-	idsPath    string
-	output     string
-	format     Format
-	title      string
-	topFiles   uint64
-	topSyms    uint64
-	jobs       int
-)
-
-func init() {
-	flag.StringVar(&bloatyPath, "bloaty", "", "path to bloaty executable")
-	flag.StringVar(&idsPath, "input", "", "path to ids.txt")
-	flag.StringVar(&output, "output", "", "output path")
-	flag.Var(&format, "format", "output format (options: json, html)")
-	flag.StringVar(&title, "title", "Bloaty Analysis", "title for html page")
-	flag.Uint64Var(&topFiles, "top-files", 0, "max number of files to keep")
-	flag.Uint64Var(&topSyms, "top-syms", 0, "max number of symbols to keep per file")
-	flag.IntVar(&jobs, "jobs", runtime.NumCPU(), "max number of concurrent bloaty runs")
-}
-
-func main() {
-	flag.Parse()
-	if flag.NArg() != 0 {
-		flag.PrintDefaults()
-	}
-
-	ctx := context.Background()
-
-	if bloatyPath == "" {
-		logger.Fatalf(ctx, "%s", "must provide path to bloaty executable.")
-	}
-
-	if idsPath == "" {
-		logger.Fatalf(ctx, "%s", "must provide path to ids.txt file.")
-	}
-
-	if jobs <= 0 {
-		logger.Fatalf(ctx, "%s", "jobs (j) must be greater than 0.")
-	}
-
-	data, err := bloaty.RunBloaty(bloatyPath, idsPath, topFiles, topSyms, jobs)
-	if err != nil {
-		logger.Fatalf(ctx, "%v", err)
-	}
-
-	var out io.Writer
-	if output != "" {
-		var err error
-		f, err := os.Create(output)
-		if err != nil {
-			logger.Fatalf(ctx, "uanble to open file: %v", err)
-		}
-		defer f.Close()
-		out = f
-	} else {
-		out = os.Stdout
-	}
-
-	switch format {
-	case FormatHTML:
-		logger.Debugf(ctx, "Writing HTML...")
-		err = bloaty.Chart(data, title, out)
-		if err != nil {
-			logger.Fatalf(ctx, "%v", err)
-		}
-	case FormatJSON:
-		logger.Debugf(ctx, "Marshalling JSON...")
-		enc := json.NewEncoder(out)
-		err := enc.Encode(data)
-		if err != nil {
-			logger.Fatalf(ctx, "%v", err)
-		}
-	default:
-		logger.Fatalf(ctx, "Unknown format.")
-	}
-}
diff --git a/debug/bloaty/bloaty.go b/debug/bloaty/bloaty.go
deleted file mode 100644
index 27d0354..0000000
--- a/debug/bloaty/bloaty.go
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright 2018 The Fuchsia 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 bloaty
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"os"
-	"os/exec"
-	"sort"
-	"strings"
-	"sync"
-)
-
-type bloatyOutput struct {
-	data row
-	file string
-	err  error
-}
-
-// TODO(jakehehrlich): Add reading ids.txt to elflib, since there are now three
-// different tools that each need to read it for mostly unrelated reasons
-func getFiles(idsPath string) ([]string, error) {
-	out := []string{}
-	idsFile, err := os.Open(idsPath)
-	if err != nil {
-		return nil, err
-	}
-	defer idsFile.Close()
-	scanner := bufio.NewScanner(idsFile)
-	for line := 1; scanner.Scan(); line++ {
-		parts := strings.SplitN(scanner.Text(), " ", 2)
-		if len(parts) != 2 {
-			return nil, fmt.Errorf("invalid ids.txt: error on line %d", line)
-		}
-		out = append(out, parts[1])
-	}
-	return out, nil
-}
-
-func run(bloatyPath, file string, out chan<- bloatyOutput) {
-	args := []string{
-		"-d", "segments,compileunits,symbols",
-		"-s", "file",
-		"--tsv",
-		"-n", "0",
-		file,
-	}
-	cmd := exec.Command(bloatyPath, args...)
-	fmt.Printf("running: %s\n", file)
-	stdout, err := cmd.StdoutPipe()
-	if err != nil {
-		out <- bloatyOutput{err: fmt.Errorf("pipe: %s: %s", file, err)}
-		return
-	}
-
-	var stderr bytes.Buffer
-	cmd.Stderr = &stderr
-
-	if err := cmd.Start(); err != nil {
-		out <- bloatyOutput{err: fmt.Errorf("start (%s): %s: %s\n", err, file, cmd.Stderr)}
-		stdout.Close()
-		return
-	}
-
-	err = ReadCSV(stdout, out, file)
-	if err != nil {
-		out <- bloatyOutput{err: fmt.Errorf("csv: %s: %s", file, err)}
-		stdout.Close()
-		return
-	}
-
-	if err := cmd.Wait(); err != nil {
-		out <- bloatyOutput{err: fmt.Errorf("wait (%s): %s: %s\n", err, file, cmd.Stderr)}
-		return
-	}
-}
-
-func updateSymbol(newSym *row, file string, sym *Symbol) {
-	sym.Name = newSym.Symbol
-	sym.Vmsz += newSym.Vmsz
-	sym.Filesz += newSym.Filesz
-	sym.Binaries = append(sym.Binaries, file)
-}
-
-func addRowToOutput(r *row, file string, output map[string]*Segment) {
-	if _, ok := output[r.Seg]; !ok {
-		output[r.Seg] = &Segment{make(map[string]*File)}
-	}
-	seg := output[r.Seg]
-
-	if _, ok := seg.Files[r.File]; !ok {
-		seg.Files[r.File] = &File{Symbols: make(map[string]*Symbol)}
-	}
-	f := seg.Files[r.File]
-
-	if _, ok := f.Symbols[r.Symbol]; !ok {
-		f.Symbols[r.Symbol] = &Symbol{}
-	}
-	updateSymbol(r, file, f.Symbols[r.Symbol])
-	seg.Files[r.File] = f
-	output[r.Seg] = seg
-}
-
-func getTopN(fileSizes map[string]uint64, topFiles, topSyms uint64, output *map[string]*Segment) {
-	// If both topFiles and topSyms are 0, bail early because we're returning everything.
-	if topFiles == 0 && topSyms == 0 {
-		return
-	}
-	type sortedFile struct {
-		name string
-		size uint64
-	}
-
-	smallFiles := make(map[string]uint64)
-	if topFiles > 0 && topFiles < uint64(len(fileSizes)) {
-		var all []struct {
-			name string
-			size uint64
-		}
-		for name, size := range fileSizes {
-			all = append(all, sortedFile{name, size})
-		}
-		sort.Slice(all, func(i, j int) bool {
-			return all[i].size < all[j].size
-		})
-
-		for _, d := range all[:uint64(len(all))-topFiles] {
-			smallFiles[d.name] = d.size
-		}
-	}
-
-	for _, segData := range *output {
-		smallFilesSize := uint64(0)
-		for file, fileData := range segData.Files {
-			smallSyms := Symbol{Name: "all small syms"}
-			// If the file labeled a small file, add to small files size and delete the sym data.
-			if size, exists := smallFiles[file]; exists {
-				smallFilesSize += size
-				delete(segData.Files, file)
-			} else if topSyms > 0 && topSyms < uint64(len(fileData.Symbols)) {
-				var all []*Symbol
-				for _, sym := range fileData.Symbols {
-					all = append(all, sym)
-				}
-				sort.Slice(all, func(i, j int) bool {
-					return all[i].Filesz < all[j].Filesz
-				})
-
-				for _, d := range all[:uint64(len(all))-topSyms] {
-					if sym, exists := fileData.Symbols[d.Name]; exists {
-						smallSyms.Vmsz += sym.Vmsz
-						smallSyms.Filesz += sym.Filesz
-						delete(fileData.Symbols, d.Name)
-					}
-				}
-			}
-
-			if topSyms > 0 {
-				fileData.Symbols["all small syms"] = &smallSyms
-			}
-		}
-
-		if topFiles > 0 {
-			segData.Files["all small files"] = &File{TotalFilesz: smallFilesSize}
-		}
-	}
-}
-
-// RunBloaty runs bloaty on all files in ids.txt, and returns a mapping of the
-// symbols and files by segment.
-func RunBloaty(bloatyPath, idsPath string, topFiles, topSyms uint64, jobs int) (map[string]*Segment, error) {
-	files, err := getFiles(idsPath)
-	if err != nil {
-		return nil, err
-	}
-
-	var wg sync.WaitGroup
-	data := make(chan bloatyOutput)
-	output := make(map[string]*Segment)
-	fileSizes := make(map[string]uint64)
-
-	// Start up the data collection process.
-	dataComplete := make(chan struct{}, 1)
-	go func() {
-		for d := range data {
-			if d.err != nil {
-				fmt.Printf("%v", d.err)
-				continue
-			}
-			addRowToOutput(&d.data, d.file, output)
-			fileSizes[d.data.File] += d.data.Filesz
-		}
-		dataComplete <- struct{}{}
-	}()
-
-	// Only allow up to max jobs concurrent executions.
-	sem := make(chan struct{}, jobs)
-
-	// Start a bloaty run on each file.
-	for _, file := range files {
-		wg.Add(1)
-		sem <- struct{}{}
-		go func(file string) {
-			defer wg.Done()
-			run(bloatyPath, file, data)
-			<-sem
-		}(file)
-	}
-
-	wg.Wait()
-	close(data)
-	<-dataComplete
-
-	getTopN(fileSizes, topFiles, topSyms, &output)
-	return output, nil
-}
diff --git a/debug/bloaty/bloaty_test.go b/debug/bloaty/bloaty_test.go
deleted file mode 100644
index 2acf8cd..0000000
--- a/debug/bloaty/bloaty_test.go
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright 2018 The Fuchsia 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 bloaty
-
-import (
-	"fmt"
-	"io/ioutil"
-	"testing"
-)
-
-const (
-	ids = `0071116f87e52dab0c21bd1cabc590fab5b06348 /out/libc.so
-01885627175ee9996b08af6c64c95a6e30787269 /out/libpc-ps2.so
-`
-)
-
-func WriteTempIdsTxt() (string, error) {
-	idsPath, err := ioutil.TempFile("", "ids")
-	if err != nil {
-		return "", err
-	}
-	fmt.Fprintf(idsPath, ids)
-	idsPath.Close()
-	return idsPath.Name(), nil
-}
-
-func TestGetFiles(t *testing.T) {
-	idsPath, errIds := WriteTempIdsTxt()
-	if errIds != nil {
-		t.Fatal(errIds)
-	}
-
-	actual, errConfig := getFiles(idsPath)
-	if errConfig != nil {
-		t.Fatal(errConfig)
-	}
-
-	expected := []string{"/out/libc.so", "/out/libpc-ps2.so"}
-
-	if len(actual) != len(expected) {
-		t.Fatalf("In TestGenConfig, expected \n%s but got \n%s", expected, actual)
-	}
-
-	for i, val := range expected {
-		if actual[i] != val {
-			t.Fatalf("In TestGenConfig, expected \n%s but got \n%s", expected, actual)
-		}
-	}
-}
-
-func TestGetTopNFiles(t *testing.T) {
-	input := map[string]*Segment{
-		"LOAD [R]": {
-			Files: map[string]*File{
-				"file.c": {
-					TotalFilesz: 14,
-					Symbols: map[string]*Symbol{
-						"ecm_bind": {
-							Name:     "ecm_bind",
-							Vmsz:     14,
-							Filesz:   14,
-							Binaries: []string{"lib.so"},
-						},
-					},
-				},
-				"different.c": {
-					TotalFilesz: 5,
-					Symbols: map[string]*Symbol{
-						"ecm_bind": {
-							Name:     "ecm_bind",
-							Vmsz:     23,
-							Filesz:   5,
-							Binaries: []string{"lib.so"},
-						},
-					},
-				},
-			},
-		},
-		"LOAD [RX]": {
-			Files: map[string]*File{
-				"other.c": {
-					TotalFilesz: 1,
-					Symbols: map[string]*Symbol{
-						"ecm_bind": {
-							Name:     "ecm_bind",
-							Vmsz:     1,
-							Filesz:   1,
-							Binaries: []string{"lib.so"},
-						},
-					},
-				},
-				"test.c": {
-					TotalFilesz: 4,
-					Symbols: map[string]*Symbol{
-						"test": {
-							Name:     "test",
-							Vmsz:     4,
-							Filesz:   4,
-							Binaries: []string{"lib.so"},
-						},
-					},
-				},
-			},
-		},
-	}
-
-	fileSizes := map[string]uint64{
-		"file.c":      14,
-		"different.c": 5,
-		"other.c":     1,
-		"test.c":      4,
-	}
-
-	getTopN(fileSizes, 1, 0, &input)
-	if len(input) != 2 {
-		t.Fatalf("In TestGetTopN, len is wrong: \n%+v", input)
-	}
-
-	if _, ok := input["LOAD [R]"]; !ok {
-		t.Fatalf("In TestGetTopN, missing LOAD [R]: \n%+v", input)
-	}
-
-	if len(input["LOAD [R]"].Files) != 2 {
-		t.Fatalf("In TestGetTopN, len is wrong: \n%+v", input["LOAD [R]"].Files)
-	}
-
-	if val, ok := input["LOAD [R]"].Files["file.c"]; !ok {
-		t.Fatalf("In TestGetTopN, missing file.c: \n%+v", input["LOAD [R]"].Files)
-	} else if val.TotalFilesz != 14 {
-		t.Fatalf("In TestGetTopN, filesz is wrong: \n%+v", val)
-	}
-
-	if val, ok := input["LOAD [R]"].Files["all small files"]; !ok {
-		t.Fatalf("In TestGetTopN, missing all small files: \n%+v", input["LOAD [R]"].Files)
-	} else if val.TotalFilesz != 5 {
-		t.Fatalf("In TestGetTopN, filesz is wrong: \n%+v", val)
-	}
-
-	if _, ok := input["LOAD [RX]"]; !ok {
-		t.Fatalf("In TestGetTopN, missing LOAD [RX]: \n%+v", input)
-	}
-
-	if len(input["LOAD [RX]"].Files) != 1 {
-		t.Fatalf("In TestGetTopN, len is wrong: \n%+v", input["LOAD [R]"].Files)
-	}
-
-	if val, ok := input["LOAD [RX]"].Files["all small files"]; !ok {
-		t.Fatalf("In TestGetTopN, missing all small files: \n%+v", input["LOAD [R]"].Files)
-	} else if val.TotalFilesz != 5 {
-		t.Fatalf("In TestGetTopN, filesz is wrong: \n%+v", val)
-	}
-}
-
-func TestGetTopNSymbols(t *testing.T) {
-	input := map[string]*Segment{
-		"LOAD [R]": {
-			Files: map[string]*File{
-				"file.c": {
-					TotalFilesz: 14,
-					Symbols: map[string]*Symbol{
-						"ecm_bind": {
-							Name:     "ecm_bind",
-							Vmsz:     14,
-							Filesz:   14,
-							Binaries: []string{"lib.so"},
-						},
-						"test": {
-							Name:     "test",
-							Vmsz:     23,
-							Filesz:   5,
-							Binaries: []string{"lib.so"},
-						},
-						"other": {
-							Name:     "other",
-							Vmsz:     5,
-							Filesz:   5,
-							Binaries: []string{"lib.so"},
-						},
-					},
-				},
-			},
-		},
-	}
-
-	fileSizes := map[string]uint64{
-		"file.c":      14,
-		"different.c": 5,
-		"other.c":     1,
-		"test.c":      4,
-	}
-
-	getTopN(fileSizes, 0, 1, &input)
-	if len(input) != 1 {
-		t.Fatalf("In TestGetTopNSymbols, len is wrong: \n%+v", input)
-	}
-
-	if _, ok := input["LOAD [R]"]; !ok {
-		t.Fatalf("In TestGetTopNSymbols, missing LOAD [R]: \n%+v", input)
-	}
-
-	if len(input["LOAD [R]"].Files) != 1 {
-		t.Fatalf("In TestGetTopNSymbols, len is wrong: \n%+v", input["LOAD [R]"].Files)
-	}
-
-	if val, ok := input["LOAD [R]"].Files["file.c"]; !ok {
-		t.Fatalf("In TestGetTopNSymbols, missing file.c: \n%+v", input["LOAD [R]"].Files)
-	} else if val.TotalFilesz != 14 {
-		t.Fatalf("In TestGetTopNSymbols, filesz is wrong: \n%+v", val)
-	}
-
-	if len(input["LOAD [R]"].Files["file.c"].Symbols) != 2 {
-		t.Fatalf("In TestGetTopNSymbols, len is wrong: \n%+v", input["LOAD [R]"].Files["file.c"].Symbols)
-	}
-
-	if val, ok := input["LOAD [R]"].Files["file.c"].Symbols["ecm_bind"]; !ok {
-		t.Fatalf("In TestGetTopNSymbols, missing ecm_bind: \n%+v", input["LOAD [R]"].Files)
-	} else if val.Filesz != 14 {
-		t.Fatalf("In TestGetTopNSymbols, filesz is wrong: \n%+v", val)
-	}
-
-	if val, ok := input["LOAD [R]"].Files["file.c"].Symbols["all small syms"]; !ok {
-		t.Fatalf("In TestGetTopNSymbols, missing ecm_bind: \n%+v", input["LOAD [R]"].Files["file.c"].Symbols["all small syms"])
-	} else if val.Filesz != 10 {
-		t.Fatalf("In TestGetTopNSymbols, filesz is wrong: \n%+v", val)
-	}
-}
-
-func TestAddRowToOutput(t *testing.T) {
-	rows := []row{
-		{"ecm_bind", "other.c", "LOAD [RX]", 7, 7},
-		{"test", "other.c", "LOAD [RX]", 12, 2},
-		{"ecm_bind", "other.c", "LOAD [R]", 23, 5},
-		{"ecm_bind", "file.c", "LOAD [R]", 3, 3},
-	}
-
-	actual := make(map[string]*Segment)
-	for _, row := range rows {
-		addRowToOutput(&row, row.File, actual)
-	}
-
-	// {"ecm_bind", "other.c", "LOAD [RX]", 7, 7},
-	if _, ok := actual["LOAD [RX]"]; !ok {
-		t.Fatalf("In TestAddRowToOutput, got \n%+v", actual)
-	}
-	if _, ok := actual["LOAD [RX]"].Files["other.c"]; !ok {
-		t.Fatalf("In TestAddRowToOutput, missing LOAD[RX] other.c")
-	}
-	if val, ok := actual["LOAD [RX]"].Files["other.c"].Symbols["ecm_bind"]; !ok {
-		t.Fatalf("In TestAddRowToOutput, missing LOAD[RX] other.c ecm_bind")
-	} else if val.Name != "ecm_bind" || val.Vmsz != 7 || val.Filesz != 7 {
-		t.Fatalf("In TestAddRowToOutput, got \n%+v", val)
-	}
-
-	// {"test", "other.c", "LOAD [RX]", 12, 2},
-	if val, ok := actual["LOAD [RX]"].Files["other.c"].Symbols["test"]; !ok {
-		t.Fatalf("In TestAddRowToOutput, missing LOAD[RX] other.c test")
-	} else if val.Name != "test" || val.Vmsz != 12 || val.Filesz != 2 {
-		t.Fatalf("In TestAddRowToOutput, got \n%+v", val)
-	}
-
-	// {"ecm_bind", "other.c", "LOAD [R]", 23, 5},
-	if _, ok := actual["LOAD [R]"]; !ok {
-		t.Fatalf("In TestAddRowToOutput, missing LOAD[R]")
-	}
-	if _, ok := actual["LOAD [R]"].Files["other.c"]; !ok {
-		t.Fatalf("In TestAddRowToOutput, missing LOAD[R]:other.c")
-	}
-	if val, ok := actual["LOAD [R]"].Files["other.c"].Symbols["ecm_bind"]; !ok {
-		t.Fatalf("In TestAddRowToOutput, missing LOAD[R] other.c ecm_bind")
-	} else if val.Name != "ecm_bind" || val.Vmsz != 23 || val.Filesz != 5 {
-		t.Fatalf("In TestAddRowToOutput, got \n%+v", val)
-	}
-
-	// {"ecm_bind", "file.c", "LOAD [R]", 3, 3},
-	if _, ok := actual["LOAD [R]"].Files["file.c"]; !ok {
-		t.Fatalf("In TestAddRowToOutput, missing LOAD[R] file.c")
-	}
-	if val, ok := actual["LOAD [R]"].Files["file.c"].Symbols["ecm_bind"]; !ok {
-		t.Fatalf("In TestAddRowToOutput, missing LOAD[R] file.c ecm_bind")
-	} else if val.Name != "ecm_bind" || val.Vmsz != 3 || val.Filesz != 3 {
-		t.Fatalf("In TestAddRowToOutput, got \n%+v", val)
-	}
-}
diff --git a/debug/bloaty/chart.go b/debug/bloaty/chart.go
deleted file mode 100644
index 242b436..0000000
--- a/debug/bloaty/chart.go
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2018 The Fuchsia 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 bloaty
-
-import (
-	"fmt"
-	"html/template"
-	"io"
-)
-
-const gchart = `
-<html>
-  <head>
-    <title>{{.Title}}</title>
-    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
-    <script type="text/javascript">
-      google.charts.load('current', {'packages':['treemap']});
-      google.charts.setOnLoadCallback(drawChart);
-      function drawChart() {
-        var data = google.visualization.arrayToDataTable({{.Data}});
-
-        tree = new google.visualization.TreeMap(document.getElementById('chart_div'));
-
-        var options = {
-          highlightOnMouseOver: true,
-          maxDepth: 0,
-          maxPostDepth: 0,
-          minHighlightColor: '#8c6bb1',
-          midHighlightColor: '#9ebcda',
-          maxHighlightColor: '#edf8fb',
-          minColor: '#009688',
-          midColor: '#f7f7f7',
-          maxColor: '#ee8100',
-          headerHeight: 15,
-          showScale: true,
-          useWeightedAverageForAggregation: true
-        };
-
-        tree.draw(data, options);
-      }
-    </script>
-  </head>
-  <body>
-    <div id="chart_div" style="width: 100%; height: 100%;"></div>
-  </body>
-</html>`
-
-type htmlData struct {
-	Data  *[][]interface{}
-	Title string
-}
-
-// Data format:
-// Column 0 - [string] An ID for this node. It can be any valid JavaScript string,
-//    including spaces, and any length that a string can hold. This value is
-//    displayed as the node header.
-// Column 1 - [string] - The ID of the parent node. If this is a root node,
-//    leave this blank. Only one root is allowed per treemap.
-// Column 2 - [number] - The size of the node. Any positive value is allowed.
-//    This value determines the size of the node, computed relative to all other
-//    nodes currently shown. For non-leaf nodes, this value is ignored and
-//    calculated from the size of all its children.
-func toTable(bloatyData map[string]*Segment) *[][]interface{} {
-	var data [][]interface{}
-	data = append(data, []interface{}{"ID", "Parent", "File Size", "Color"})
-	data = append(data, []interface{}{"Build", nil, uint64(0), 0})
-
-	for seg, segData := range bloatyData {
-		data = append(data, []interface{}{seg, "Build", uint64(0), 0})
-		for file, fileData := range segData.Files {
-			data = append(data, []interface{}{fmt.Sprintf("%s (%s)", file, seg), seg, fileData.TotalFilesz, 0})
-			for sym, symData := range fileData.Symbols {
-				data = append(data, []interface{}{
-					fmt.Sprintf("%s:%s (%s)", file, sym, seg),
-					fmt.Sprintf("%s (%s)", file, seg),
-					symData.Filesz,
-					len(symData.Binaries),
-				})
-			}
-		}
-	}
-	return &data
-}
-
-// Chart converts the map of symbols to the format expected by GChart, and then
-// generates an HTML page from that data.
-func Chart(bloatyData map[string]*Segment, title string, out io.Writer) error {
-	temp, err := template.New("T").Parse(gchart)
-	if err != nil {
-		return err
-	}
-	err = temp.Execute(out, htmlData{toTable(bloatyData), title})
-	if err != nil {
-		return err
-	}
-	return nil
-}
diff --git a/debug/bloaty/chart_test.go b/debug/bloaty/chart_test.go
deleted file mode 100644
index f38a84c..0000000
--- a/debug/bloaty/chart_test.go
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2018 The Fuchsia 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 bloaty
-
-import (
-	"testing"
-)
-
-func checkRow(t *testing.T, row []interface{}, expected []interface{}) {
-	if len(expected) != 4 {
-		t.Fatalf("In TestToChart, len is wrong. expected: \n%+v\n but got: \n%+v", expected, row)
-	}
-	if row[0] != expected[0] {
-		t.Fatalf("In TestToChart, len is wrong. expected: \n%+v\n but got: \n%+v", expected, row)
-	}
-	if len(row) != 4 {
-		t.Fatalf("In TestToChart, id is wrong. expected: \n%+v\n but got: \n%+v", expected, row)
-	}
-	if row[1] != expected[1] {
-		t.Fatalf("In TestToChart, parent is wrong. expected: \n%+v\n but got: \n%+v", expected, row)
-	}
-	if row[2] != expected[2] {
-		t.Fatalf("In TestToChart, size is wrong. expected: \n%+v\n but got: \n%+v", expected, row)
-	}
-	if row[3] != expected[3] {
-		t.Fatalf("In TestToChart, color is wrong. expected: \n%+v\n but got: \n%+v", expected, row)
-	}
-}
-
-func TestToChart(t *testing.T) {
-	input := map[string]*Segment{
-		"LOAD [R]": {
-			Files: map[string]*File{
-				"file.c": {
-					TotalFilesz: 3,
-					Symbols: map[string]*Symbol{
-						"ecm_bind": {
-							Name:     "ecm_bind",
-							Vmsz:     3,
-							Filesz:   3,
-							Binaries: []string{"lib.so"},
-						},
-					},
-				},
-				"other.c": {
-					TotalFilesz: 5,
-					Symbols: map[string]*Symbol{
-						"ecm_bind": {
-							Name:     "ecm_bind",
-							Vmsz:     23,
-							Filesz:   5,
-							Binaries: []string{"lib.so", "other.so"},
-						},
-					},
-				},
-			},
-		},
-		"LOAD [RX]": {
-			Files: map[string]*File{
-				"other.c": {
-					TotalFilesz: 14,
-					Symbols: map[string]*Symbol{
-						"ecm_bind": {
-							Name:     "ecm_bind",
-							Vmsz:     7,
-							Filesz:   7,
-							Binaries: []string{"lib.so"},
-						},
-						"test": {
-							Name:     "test",
-							Vmsz:     12,
-							Filesz:   7,
-							Binaries: []string{"lib.so", "other.so"},
-						},
-					},
-				},
-			},
-		},
-	}
-
-	actual := *toTable(input)
-
-	ids_to_expected_rows := map[string][]interface{}{
-		"ID":                           {"ID", "Parent", "File Size", "Color"},
-		"Build":                        {"Build", nil, uint64(0), 0},
-		"LOAD [R]":                     {"LOAD [R]", "Build", uint64(0), 0},
-		"LOAD [RX]":                    {"LOAD [RX]", "Build", uint64(0), 0},
-		"file.c (LOAD [R])":            {"file.c (LOAD [R])", "LOAD [R]", uint64(3), 0},
-		"other.c (LOAD [R])":           {"other.c (LOAD [R])", "LOAD [R]", uint64(5), 0},
-		"other.c (LOAD [RX])":          {"other.c (LOAD [RX])", "LOAD [RX]", uint64(14), 0},
-		"file.c:ecm_bind (LOAD [R])":   {"file.c:ecm_bind (LOAD [R])", "file.c (LOAD [R])", uint64(3), 1},
-		"other.c:ecm_bind (LOAD [R])":  {"other.c:ecm_bind (LOAD [R])", "other.c (LOAD [R])", uint64(5), 2},
-		"other.c:ecm_bind (LOAD [RX])": {"other.c:ecm_bind (LOAD [RX])", "other.c (LOAD [RX])", uint64(7), 1},
-		"other.c:test (LOAD [RX])":     {"other.c:test (LOAD [RX])", "other.c (LOAD [RX])", uint64(7), 2},
-	}
-
-	if len(actual) != 11 {
-		t.Fatalf("In TestToChart, len is wrong: \n%+v", actual)
-	}
-	for _, row := range actual {
-		if len(row) != 4 {
-			t.Fatalf("In TestToChart, len is wrong: \n%+v", row)
-		}
-		checkRow(t, row, ids_to_expected_rows[row[0].(string)])
-	}
-}
diff --git a/debug/bloaty/symbols.go b/debug/bloaty/symbols.go
deleted file mode 100644
index 8d61094..0000000
--- a/debug/bloaty/symbols.go
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2018 The Fuchsia 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 bloaty
-
-import (
-	"encoding/csv"
-	"fmt"
-	"io"
-	"strconv"
-)
-
-type row struct {
-	Symbol string
-	File   string
-	Seg    string
-	Vmsz   uint64
-	Filesz uint64
-}
-
-// Symbol represents data about one symbol in the produced Bloaty output.
-type Symbol struct {
-	Name     string   `json:"Name"`
-	Vmsz     uint64   `json:"Vmsz"`
-	Filesz   uint64   `json:"Filesz"`
-	Binaries []string `json:"Binaries"`
-}
-
-// File represents all data about one file in the produced Bloaty output
-type File struct {
-	Symbols     map[string]*Symbol `json:"Symbols"`
-	TotalFilesz uint64             `json:"TotalFilesz"`
-}
-
-// Segment represents all data about one segment in the produced Bloaty output
-type Segment struct {
-	Files map[string]*File
-}
-
-func parseRow(rawRow []string) (row, bool, error) {
-	var out row
-	if len(rawRow) != 5 {
-		return out, false, fmt.Errorf("row did not match format")
-	}
-
-	if rawRow[0] == "segments" {
-		return out, true, nil
-	}
-
-	out.Seg = rawRow[0]
-	out.File = rawRow[1]
-	out.Symbol = rawRow[2]
-
-	var err error
-	out.Vmsz, err = strconv.ParseUint(rawRow[3], 0, 64)
-	if err != nil {
-		return out, false, err
-	}
-
-	out.Filesz, err = strconv.ParseUint(rawRow[4], 0, 64)
-	if err != nil {
-		return out, false, err
-	}
-
-	return out, false, nil
-}
-
-func filterRow(r row) bool {
-	// These rows mean nothing to us
-	if r.Vmsz == 0 || r.Filesz == 0 {
-		return false
-	}
-	// These are things that get stripped away
-	if r.Seg == "[Unmapped]" {
-		return false
-	}
-	return true
-}
-
-func ReadCSV(data io.Reader, out chan<- bloatyOutput, file string) error {
-	reader := csv.NewReader(data)
-	reader.Comma = '\t'
-
-	var line int
-	for {
-		r, err := reader.Read()
-		if err == io.EOF {
-			return nil
-		}
-		if err != nil {
-			return fmt.Errorf("%v\n", err)
-		}
-
-		// If it's empty, ignore it
-		if len(r) == 0 {
-			line += 1
-			continue
-		}
-
-		properRow, isHeader, err := parseRow(r)
-		if !isHeader {
-			if err != nil {
-				return fmt.Errorf("unable to decode line %d:%v %v\n", line, r, err)
-			}
-			if filterRow(properRow) {
-				out <- bloatyOutput{
-					data: properRow,
-					file: file,
-				}
-			}
-		}
-		line += 1
-	}
-}
diff --git a/debug/bloaty/symbols_test.go b/debug/bloaty/symbols_test.go
deleted file mode 100644
index edb83af..0000000
--- a/debug/bloaty/symbols_test.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2018 The Fuchsia 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 bloaty
-
-import (
-	"bytes"
-	"testing"
-)
-
-const (
-	tsv = `segments	compileunits	symbols	vmsize	filesize
-[Unmapped]	file.c	[section .debug_info]	0	15550
-LOAD [RX]	other.c	ecm_bind	4142	4142
-[ELF Headers]			0	1920
-LOAD [RX]	[LOAD [RX]]		530	0`
-)
-
-func TestReadCSV(t *testing.T) {
-	reader := bytes.NewReader([]byte(tsv))
-
-	out := make(chan bloatyOutput)
-	go func() {
-		err := ReadCSV(reader, out, "file.c")
-		if err != nil {
-			t.Fatal(err)
-		}
-		close(out)
-	}()
-
-	actual := []row{}
-	for o := range out {
-		actual = append(actual, o.data)
-	}
-
-	expected := []row{
-		{"ecm_bind", "other.c", "LOAD [RX]", 4142, 4142},
-	}
-
-	if len(actual) != len(expected) {
-		t.Fatalf("In TestReadCSV, expected \n%v but got \n%v", expected, actual)
-	}
-
-	for i, val := range expected {
-		if actual[i] != val {
-			t.Fatalf("In TestReadCSV, expected \n%v but got \n%v", expected, actual)
-		}
-	}
-}
-
-func TestFilterRow(t *testing.T) {
-	goodRow := row{"ecm_bind", "other.c", "LOAD [RX]", 4142, 4142}
-	badRow := row{"[section .debug_info]", "file.c", "[Unmapped]", 0, 15550}
-
-	actual := filterRow(goodRow)
-	expected := true
-
-	if actual != expected {
-		t.Fatalf("In TestFilterRows, expected \n%v but got \n%v", expected, actual)
-	}
-
-	actual = filterRow(badRow)
-	expected = false
-
-	if actual != expected {
-		t.Fatalf("In TestFilterRows, expected \n%v but got \n%v", expected, actual)
-	}
-}
diff --git a/debug/breakpad/generator/generator.go b/debug/breakpad/generator/generator.go
deleted file mode 100644
index 84f9b44..0000000
--- a/debug/breakpad/generator/generator.go
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2019 The Fuchsia 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 generator
-
-import (
-	"bytes"
-	"fmt"
-	"io/ioutil"
-	"log"
-	"os"
-	"os/exec"
-	"path/filepath"
-	"sync"
-
-	"go.fuchsia.dev/tools/debug/breakpad"
-	"go.fuchsia.dev/tools/debug/elflib"
-)
-
-// The default module name for modules that don't have a soname, e.g., executables and
-// loadable modules. This allows us to use the same module name at runtime as sonames are
-// the only names that are guaranteed to be available at build and run times. This value
-// must be kept in sync with what Crashpad uses at run time for symbol resolution to work
-// properly.
-const defaultModuleName = "<_>"
-
-// The module OS used to overwrite existing OS values in generated symbol files, even if
-// they're already set to something else.
-const replacementModuleOS = "Fuchsia"
-
-// Generate generates breakpad symbol data for each of the input elflib.BinaryFileRefs.
-// Returns the path to a directory containing the generated files, or the empty string if
-// an error occurred.
-func Generate(bfrs []elflib.BinaryFileRef, dumpSymsPath string) (path string, err error) {
-	outc := make(chan string)
-	errc := make(chan error)
-	defer close(outc)
-	defer close(errc)
-
-	g := &generator{
-		dumpSymsPath: dumpSymsPath,
-		visited:      make(map[string]bool),
-		visitedMutex: &sync.Mutex{},
-	}
-
-	jobs := make(chan elflib.BinaryFileRef)
-	go g.run(jobs, outc, errc)
-	for _, bfr := range bfrs {
-		jobs <- bfr
-	}
-	close(jobs)
-
-	select {
-	case err = <-errc:
-		return "", err
-	case path = <-outc:
-		return path, nil
-	}
-}
-
-// Generator is a helper class for executing Breakpad's dump_syms tool.
-//
-// The run method is meant to be executed as a go-routine. It will manage its own working
-// directory, and publish the path to that directory only on success.
-//
-// The run method is threadsafe, and will skip files that have already been processed.
-type generator struct {
-	// The path to the Breakpad dump_syms executable.
-	dumpSymsPath string
-
-	// Filepaths that have already been processed by this generator.
-	visited      map[string]bool
-	visitedMutex *sync.Mutex
-}
-
-// Run executes this generator on the given channel of elflib.BinarFileRefs.
-//
-// A temp directory is created to store generated files. On success, the directory is
-// emitted on out. On the first encountered error, the generator will emit the error on
-// errs, delete the output directory, and exit.
-func (g *generator) run(in <-chan elflib.BinaryFileRef, out chan<- string, errs chan<- error) {
-	outdir, err := ioutil.TempDir("", "breakpad")
-	if err != nil {
-		errs <- err
-		return
-	}
-	if err := g.generate(in, outdir); err != nil {
-		errs <- err
-		os.RemoveAll(outdir)
-		return
-	}
-	out <- outdir
-}
-
-func (g *generator) generate(in <-chan elflib.BinaryFileRef, outdir string) error {
-	for bfr := range in {
-		if !g.markVisited(bfr.Filepath) {
-			continue
-		}
-		sf, err := g.genFromBinaryFileRef(bfr)
-		if err != nil {
-			return err
-		}
-		fd, err := os.Create(filepath.Join(outdir, sf.ModuleSection.BuildID))
-		if err != nil {
-			return err
-		}
-		defer fd.Close()
-		if _, err := sf.WriteTo(fd); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func (g *generator) genFromBinaryFileRef(bfr elflib.BinaryFileRef) (*breakpad.SymbolFile, error) {
-	log.Printf("generating symbols for %q", bfr.Filepath)
-	sf, err := g.genSymbolFile(bfr)
-	if err != nil {
-		return nil, err
-	}
-	sf.ModuleSection.OS = replacementModuleOS
-	sf.ModuleSection.ModuleName = defaultModuleName
-	soname, err := g.readSoName(bfr.Filepath)
-	if err == nil && soname != "" {
-		sf.ModuleSection.ModuleName = soname
-	}
-	return sf, nil
-}
-
-func (g *generator) genSymbolFile(bfr elflib.BinaryFileRef) (*breakpad.SymbolFile, error) {
-	var stdout bytes.Buffer
-	cmd := exec.Cmd{
-		Path:   g.dumpSymsPath,
-		Args:   []string{g.dumpSymsPath, bfr.Filepath},
-		Stdout: &stdout,
-	}
-	if err := cmd.Run(); err != nil {
-		return nil, fmt.Errorf("command failed %v: %v", cmd.Args, err)
-	}
-	return breakpad.ParseSymbolFile(&stdout)
-}
-
-func (g *generator) readSoName(path string) (string, error) {
-	fd, err := os.Open(path)
-	if err != nil {
-		return "", fmt.Errorf("open failed %q: %v", path, err)
-	}
-	defer fd.Close()
-	return elflib.GetSoName(path, fd)
-}
-
-// Marks that path has been visited and returs true iff this generator has not alread
-// visited path. Otherwise returns false.
-func (g *generator) markVisited(path string) (succeeded bool) {
-	g.visitedMutex.Lock()
-	defer g.visitedMutex.Unlock()
-	if g.visited[path] {
-		return false
-	}
-	g.visited[path] = true
-	return true
-}
diff --git a/debug/breakpad/symbol_file.go b/debug/breakpad/symbol_file.go
deleted file mode 100644
index 495ab66..0000000
--- a/debug/breakpad/symbol_file.go
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2019 The Fuchsia 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 breakpad
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"strings"
-)
-
-// ParseSymbolFile reads a breakpad symbol file.
-func ParseSymbolFile(r io.Reader) (*SymbolFile, error) {
-	bytes, err := ioutil.ReadAll(r)
-	if err != nil {
-		return nil, fmt.Errorf("failed to read symbol file: %v", err)
-	}
-	lines := strings.SplitN(string(bytes), "\n", 2)
-	if len(lines) != 2 {
-		return nil, fmt.Errorf("got < 2 lines in symbol file")
-	}
-	moduleSection := strings.TrimSpace(lines[0])
-	if moduleSection == "" {
-		return nil, fmt.Errorf("unexpected blank first line in symbol file")
-	}
-	module, err := parseModuleLine(moduleSection)
-	if err != nil {
-		return nil, fmt.Errorf("failed to parse module section: %v", err)
-	}
-	return &SymbolFile{
-		ModuleSection: module,
-		remainder:     lines[1],
-	}, nil
-}
-
-// SymbolFile represents a Breakpad symbol file, typically produced by the dump_syms tool.
-// This is only a partial implementation; the ModuleSection is all that is parsed. Add fields
-// as needed.
-type SymbolFile struct {
-	ModuleSection *ModuleSection
-
-	// Unparsed contents from the input file excluding the ModuleSection.
-	remainder string
-}
-
-func (f SymbolFile) WriteTo(w io.Writer) (int64, error) {
-	return io.Copy(w, f.Reader())
-}
-
-// Reader returns an io.Reader for this SymbolFile data as it would be written to a file.
-func (f SymbolFile) Reader() io.Reader {
-	var buf bytes.Buffer
-	buf.WriteString(f.ModuleSection.String())
-	buf.WriteString("\n")
-	buf.WriteString(f.remainder)
-	return &buf
-}
-
-// ModuleSection represents the first section/line of a symbol file.
-type ModuleSection struct {
-	OS         string
-	Arch       string
-	BuildID    string
-	ModuleName string
-}
-
-// String formats this ModuleSection as it would be written to a file.
-func (mod *ModuleSection) String() string {
-	content := fmt.Sprintf("MODULE %s %s %s %s", mod.OS, mod.Arch, mod.BuildID, mod.ModuleName)
-	return strings.TrimSpace(content)
-}
-
-func parseModuleLine(source string) (*ModuleSection, error) {
-	format := "MODULE $OS $ARCH $BUILD_ID $MODULE_NAME"
-	parts := strings.Split(source, " ")
-	if len(parts) != 5 {
-		return nil, fmt.Errorf("wanted line 1 with format %q but got %q", format, source)
-	}
-	return &ModuleSection{
-		OS:         parts[1],
-		Arch:       parts[2],
-		BuildID:    parts[3],
-		ModuleName: parts[4],
-	}, nil
-}
diff --git a/debug/breakpad/symbol_file_test.go b/debug/breakpad/symbol_file_test.go
deleted file mode 100644
index 5ea195f..0000000
--- a/debug/breakpad/symbol_file_test.go
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright 2019 The Fuchsia 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 breakpad
-
-import (
-	"bytes"
-	"reflect"
-	"strings"
-	"testing"
-)
-
-func TestParseSymbolFile(t *testing.T) {
-	tests := []struct {
-		name      string
-		input     string
-		output    *SymbolFile
-		expectErr bool
-	}{
-		{
-			name: "should parse when the module section has all values",
-			input: strings.Join([]string{
-				"MODULE os arch buildid modulename",
-				"garbage1",
-			}, "\n"),
-			output: &SymbolFile{
-				ModuleSection: &ModuleSection{
-					OS:         "os",
-					Arch:       "arch",
-					BuildID:    "buildid",
-					ModuleName: "modulename",
-				},
-				remainder: "garbage1",
-			},
-		},
-		{
-			name: "should fail to parse a file with less than two lines",
-			input: strings.Join([]string{
-				"MODULE os arch buildid modulename",
-			}, "\n"),
-			expectErr: true,
-		},
-		{
-			name: "should fail to parse a file with a leading blank line",
-			input: strings.Join([]string{
-				"",
-				"MODULE os arch buildid modulename",
-			}, "\n"),
-			expectErr: true,
-		},
-		{
-			name: "should fail to parse when the module section is missing one value",
-			input: strings.Join([]string{
-				"MODULE os arch buildid",
-				"INFO CODE_ID ACBDEF",
-				"FILE 9 /tmp/test/out/source.cpp",
-			}, "\n"),
-			expectErr: true,
-		},
-		{
-			name: "should fail to parse when the module section is missing two values",
-			input: strings.Join([]string{
-				"MODULE os arch",
-				"INFO CODE_ID ACBDEF",
-				"FILE 9 /tmp/test/out/source.cpp",
-			}, "\n"),
-			expectErr: true,
-		},
-		{
-			name: "should fail to parse when the module section is missing three values",
-			input: strings.Join([]string{
-				"MODULE os",
-				"INFO CODE_ID ACBDEF",
-				"FILE 9 /tmp/test/out/source.cpp",
-			}, "\n"),
-			expectErr: true,
-		},
-		{
-			name: "should fail to parse when the module section is missing all values",
-			input: strings.Join([]string{
-				"MODULE",
-				"INFO CODE_ID ACBDEF",
-				"FILE 9 /tmp/test/out/source.cpp",
-			}, "\n"),
-			expectErr: true,
-		},
-		{
-			name: "should fail to parse when the module section is missing",
-			input: strings.Join([]string{
-				"INFO CODE_ID ACBDEF",
-				"FILE 9 /tmp/test/out/source.cpp",
-			}, "\n"),
-			expectErr: true,
-		},
-		{
-			name: "should fail to parse when the module section has extra values",
-			input: strings.Join([]string{
-				"MODULE os arch buildid modulename whatisthis",
-				"INFO CODE_ID ACBDEF",
-				"FILE 9 /tmp/test/out/source.cpp",
-			}, "\n"),
-			expectErr: true,
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			output, err := ParseSymbolFile(strings.NewReader(tt.input))
-			if err != nil && !tt.expectErr {
-				t.Errorf("unexpected parse error: %v", err)
-				return
-			} else if err == nil && tt.expectErr {
-				t.Errorf("exected error but got nil with output: %v", output)
-				return
-			}
-			if tt.expectErr {
-				return
-			}
-			expected := tt.output
-			actual := output
-			if !reflect.DeepEqual(expected.ModuleSection, actual.ModuleSection) {
-				t.Errorf("wanted module section:\n\n%v\n\ngot:\n\n%v\n\n", expected.ModuleSection, actual.ModuleSection)
-			}
-			if expected.remainder != actual.remainder {
-				t.Errorf("wanted remainder file contents:\n\n%v\n\ngot:\n\n%v\n\n", expected.remainder, actual.remainder)
-			}
-		})
-	}
-}
-
-func TestSymbolFileWriteTo(t *testing.T) {
-	tests := []struct {
-		name   string
-		input  SymbolFile
-		output string
-	}{
-		{
-			name: "when module section has all fields",
-			input: SymbolFile{
-				ModuleSection: &ModuleSection{
-					OS:         "os",
-					Arch:       "arch",
-					BuildID:    "buildid",
-					ModuleName: "modulename",
-				},
-				remainder: strings.Join([]string{
-					"remainder line 1",
-					"remainder line 2",
-				}, "\n"),
-			},
-			output: strings.Join([]string{
-				"MODULE os arch buildid modulename",
-				"remainder line 1",
-				"remainder line 2",
-			}, "\n"),
-		},
-		{
-			// This is not a valid module section, but we still want to verify that it
-			// writes the exected data.
-			name: "when module section is missing some fields",
-			input: SymbolFile{
-				ModuleSection: &ModuleSection{
-					OS:      "os",
-					Arch:    "arch",
-					BuildID: "buildid",
-				},
-				remainder: strings.Join([]string{
-					"remainder line 1",
-				}, "\n"),
-			},
-			output: strings.Join([]string{
-				"MODULE os arch buildid",
-				"remainder line 1",
-			}, "\n"),
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			var output bytes.Buffer
-			if _, err := tt.input.WriteTo(&output); err != nil {
-				t.Errorf("unexpected error: %v. input: %v", err, tt.input)
-			}
-			expected := tt.output
-			actual := output.String()
-			if expected != actual {
-				t.Errorf("wanted:\n\n%v\n\ngot:\n\n%v\n\n", expected, actual)
-			}
-		})
-	}
-}
diff --git a/debug/buildidtool/cmd/main.go b/debug/buildidtool/cmd/main.go
deleted file mode 100644
index fbb5584..0000000
--- a/debug/buildidtool/cmd/main.go
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2018 The Fuchsia 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 (
-	"crypto/rand"
-	"encoding/hex"
-	"flag"
-	"fmt"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"strings"
-
-	"go.fuchsia.dev/tools/debug/elflib"
-	"go.fuchsia.dev/tools/lib/color"
-	"go.fuchsia.dev/tools/lib/logger"
-)
-
-type entry struct {
-	suffix string
-	file   string
-}
-
-type entryList []entry
-
-func (a *entryList) String() string {
-	return fmt.Sprintf("%v", []entry(*a))
-}
-
-func (a *entryList) Set(value string) error {
-	args := strings.SplitN(value, "=", 2)
-	if len(args) != 2 {
-		return fmt.Errorf("'%s' is not a valid entry. Must be in format <suffix>=<file>", value)
-	}
-	*a = append(*a, entry{args[0], args[1]})
-	return nil
-}
-
-var (
-	buildIDDir string
-	stamp      string
-	entries    entryList
-	colors     color.EnableColor
-	level      logger.LogLevel
-)
-
-func init() {
-	colors = color.ColorAuto
-	level = logger.FatalLevel
-
-	flag.StringVar(&buildIDDir, "build-id-dir", "", "path to .build-id dirctory")
-	flag.StringVar(&stamp, "stamp", "", "path to stamp file which acts as a stand in for the .build-id file")
-	flag.Var(&entries, "entry", "supply <suffix>=<file> to link <file> into .build-id with the given suffix")
-	flag.Var(&colors, "color", "use color in output, can be never, auto, always")
-	flag.Var(&level, "level", "output verbosity, can be fatal, error, warning, info, debug or trace")
-}
-
-func getTmpFile(path string, name string) (string, error) {
-	out := make([]byte, 16)
-	if _, err := rand.Read(out); err != nil {
-		return "", nil
-	}
-	return filepath.Join(path, name+"-"+hex.EncodeToString(out)) + ".tmp", nil
-}
-
-func atomicLink(from, to string) error {
-	// First make sure the directory already exists
-	if err := os.MkdirAll(filepath.Dir(to), 0700); err != nil {
-		return err
-	}
-	// Make a tmpFile in the same directory as 'from'
-	dir, file := filepath.Split(from)
-	tmpFile, err := getTmpFile(dir, file)
-	if err != nil {
-		return err
-	}
-	if err := os.Link(from, tmpFile); err != nil {
-		return err
-	}
-	if err := os.Rename(tmpFile, to); err != nil {
-		return err
-	}
-	// If "tmpFile" and "to" are already links to the same inode Rename does not remove tmpFile.
-	if err := os.Remove(tmpFile); !os.IsNotExist(err) {
-		return err
-	}
-	return nil
-}
-
-func atomicWrite(file, fmtStr string, args ...interface{}) error {
-	dir, base := filepath.Split(file)
-	tmpFile, err := getTmpFile(dir, base)
-	if err != nil {
-		return err
-	}
-	f, err := os.Create(tmpFile)
-	if err != nil {
-		return err
-	}
-	defer f.Close()
-	_, err = fmt.Fprintf(f, fmtStr, args...)
-	if err != nil {
-		return err
-	}
-	return os.Rename(tmpFile, file)
-}
-
-func removeOldFile(newBuildID, suffix string) error {
-	data, err := ioutil.ReadFile(stamp)
-	if err != nil {
-		if !os.IsNotExist(err) {
-			return err
-		}
-		return nil
-	}
-	oldBuildID := string(data)
-	// We don't want to remove what we just added!
-	if newBuildID == oldBuildID {
-		return nil
-	}
-	oldPath := filepath.Join(buildIDDir, oldBuildID[:2], oldBuildID[2:]) + suffix
-	// If the file has already been removed (perhaps by another process) then
-	// just keep going.
-	if err := os.Remove(oldPath); !os.IsNotExist(err) {
-		return err
-	}
-	return nil
-}
-
-type entryInfo struct {
-	ref    elflib.BinaryFileRef
-	suffix string
-}
-
-func getEntriesInfo() ([]entryInfo, error) {
-	var outs []entryInfo
-	for _, entry := range entries {
-		f, err := os.Open(entry.file)
-		if err != nil {
-			return nil, fmt.Errorf("opening %s to read build ID: %v", entry.file, err)
-		}
-		defer f.Close()
-		buildIDs, err := elflib.GetBuildIDs(entry.file, f)
-		if err != nil {
-			return nil, fmt.Errorf("reading build ID from %s: %v", entry.file, err)
-		}
-		// Ignore entries where the binary doesn't have a build ID.
-		if len(buildIDs) == 0 {
-			continue
-		}
-		if len(buildIDs) != 1 {
-			return nil, fmt.Errorf("unexpected number of build IDs in %s. Expected 1 but found %v", entry.file, buildIDs)
-		}
-		if len(buildIDs[0]) < 2 {
-			return nil, fmt.Errorf("build ID (%s) is too short in %s", buildIDs[0], entry.file)
-		}
-		buildID := hex.EncodeToString(buildIDs[0])
-		outs = append(outs, entryInfo{elflib.BinaryFileRef{BuildID: buildID, Filepath: entry.file}, entry.suffix})
-	}
-	return outs, nil
-}
-
-func main() {
-	l := logger.NewLogger(level, color.NewColor(colors), os.Stderr, os.Stderr, "")
-	// Parse flags and check for errors.
-	flag.Parse()
-	if buildIDDir == "" {
-		l.Fatalf("-build-id-dir is required.")
-	}
-	if stamp == "" {
-		l.Fatalf("-stamp file is required.")
-	}
-	if len(entries) == 0 {
-		l.Fatalf("Need at least one -entry arg")
-	}
-	// Get the build IDs
-	infos, err := getEntriesInfo()
-	if err != nil {
-		l.Fatalf("Parsing entries: %v", err)
-	}
-	if len(infos) != 0 {
-		// It could occur that we have ignored all files and need to return.
-		return
-	}
-	buildID := infos[0].ref.BuildID
-	for _, info := range infos {
-		if buildID != info.ref.BuildID {
-			l.Fatalf("%s and %s do not have the same build ID", info.ref.Filepath, infos[0].ref.Filepath)
-		}
-		if err := info.ref.Verify(); err != nil {
-			l.Fatalf("Could not verify build ID of %s: %v", info.ref.Filepath, err)
-		}
-	}
-	// Now that we know all the build IDs are in order perform operations.
-	// Make sure to not output the stamp file until all of these operations are
-	// performed to ensure that this tool is re-run if it fails mid-run.
-	buildIDRunes := []rune(buildID)
-	buildIDPathPrefix := filepath.Join(buildIDDir, string(buildIDRunes[:2]), string(buildIDRunes[2:]))
-	for _, info := range infos {
-		buildIDPath := buildIDPathPrefix + info.suffix
-		if err = atomicLink(info.ref.Filepath, buildIDPath); err != nil {
-			l.Fatalf("atomically linking %s to %s: %v", info.ref.Filepath, buildIDPath, err)
-		}
-		if err = removeOldFile(buildID, info.suffix); err != nil {
-			l.Fatalf("removing old file referenced by %s: %v", stamp, err)
-		}
-	}
-	// Update the stamp last atomically to commit all the above operations.
-	if err = atomicWrite(stamp, buildID); err != nil {
-		l.Fatalf("emitting final stamp %s: %v", stamp, err)
-	}
-}
diff --git a/debug/covargs/cmd/main.go b/debug/covargs/cmd/main.go
deleted file mode 100644
index 30ff15e..0000000
--- a/debug/covargs/cmd/main.go
+++ /dev/null
@@ -1,363 +0,0 @@
-// Copyright 2018 The Fuchsia 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 (
-	"bytes"
-	"context"
-	"debug/elf"
-	"encoding/json"
-	"flag"
-	"fmt"
-	"io/ioutil"
-	"os"
-	"os/exec"
-	"path/filepath"
-
-	"go.fuchsia.dev/tools/debug/elflib"
-	"go.fuchsia.dev/tools/debug/symbolize"
-	"go.fuchsia.dev/tools/lib/color"
-	"go.fuchsia.dev/tools/lib/command"
-	"go.fuchsia.dev/tools/lib/logger"
-	"go.fuchsia.dev/tools/testing/runtests"
-)
-
-var (
-	colors            color.EnableColor
-	level             logger.LogLevel
-	summaryFile       command.StringsFlag
-	idsFile           string
-	symbolizeDumpFile command.StringsFlag
-	dryRun            bool
-	outputDir         string
-	llvmCov           string
-	llvmProfdata      string
-	outputFormat      string
-	jsonOutput        string
-)
-
-func init() {
-	colors = color.ColorAuto
-	level = logger.InfoLevel
-
-	flag.Var(&colors, "color", "can be never, auto, always")
-	flag.Var(&level, "level", "can be fatal, error, warning, info, debug or trace")
-	flag.Var(&summaryFile, "summary", "path to summary.json file")
-	flag.StringVar(&idsFile, "ids", "", "path to ids.txt")
-	flag.Var(&symbolizeDumpFile, "symbolize-dump", "path to the json emited from the symbolizer")
-	flag.BoolVar(&dryRun, "dry-run", false, "if set the system prints out commands that would be run instead of running them")
-	flag.StringVar(&outputDir, "output-dir", "", "the directory to output results to")
-	flag.StringVar(&llvmProfdata, "llvm-profdata", "llvm-profdata", "the location of llvm-profdata")
-	flag.StringVar(&llvmCov, "llvm-cov", "llvm-cov", "the location of llvm-cov")
-	flag.StringVar(&outputFormat, "format", "html", "the output format used for llvm-cov")
-	flag.StringVar(&jsonOutput, "json-output", "", "outputs profile information to the specified file")
-}
-
-const llvmProfileSinkType = "llvm-profile"
-
-// Output is indexed by dump name
-func readSummary(summaryFiles []string) (map[string][]runtests.DataSink, error) {
-	sinks := make(map[string][]runtests.DataSink)
-
-	for _, summaryFile := range summaryFiles {
-		// TODO(phosek): process these in parallel using goroutines.
-		file, err := os.Open(summaryFile)
-		if err != nil {
-			return nil, fmt.Errorf("cannot open %q: %v", summaryFile, err)
-		}
-		defer file.Close()
-
-		var summary runtests.TestSummary
-		if err := json.NewDecoder(file).Decode(&summary); err != nil {
-			return nil, fmt.Errorf("cannot decode %q: %v", summaryFile, err)
-		}
-
-		dir := filepath.Dir(summaryFile)
-		for _, detail := range summary.Tests {
-			for name, data := range detail.DataSinks {
-				for _, sink := range data {
-					sinks[name] = append(sinks[name], runtests.DataSink{
-						Name: sink.Name,
-						File: filepath.Join(dir, sink.File),
-					})
-				}
-			}
-		}
-	}
-
-	return sinks, nil
-}
-
-type SymbolizerDump struct {
-	Modules  []symbolize.Module `json:"modules"`
-	SinkType string             `json:"type"`
-	DumpName string             `json:"name"`
-}
-
-type SymbolizerOutput []SymbolizerDump
-
-func readSymbolizerOutput(outputFiles []string) (map[string]SymbolizerDump, error) {
-	dumps := make(map[string]SymbolizerDump)
-
-	for _, outputFile := range outputFiles {
-		// TODO(phosek): process these in parallel using goroutines.
-		file, err := os.Open(outputFile)
-		if err != nil {
-			return nil, fmt.Errorf("cannot open %q: %v", outputFile, err)
-		}
-		defer file.Close()
-		var output SymbolizerOutput
-		if err := json.NewDecoder(file).Decode(&output); err != nil {
-			return nil, fmt.Errorf("cannot decode %q: %v", outputFile, err)
-		}
-
-		for _, dump := range output {
-			dumps[dump.DumpName] = dump
-		}
-	}
-
-	return dumps, nil
-}
-
-// Output is indexed by build id
-func readIDsTxt(idsFile string) (map[string]elflib.BinaryFileRef, error) {
-	file, err := os.Open(idsFile)
-	if err != nil {
-		return nil, fmt.Errorf("cannot open %q: %s", idsFile, err)
-	}
-	defer file.Close()
-	refs, err := elflib.ReadIDsFile(file)
-	if err != nil {
-		return nil, fmt.Errorf("cannot read %q: %v", idsFile, err)
-	}
-	out := make(map[string]elflib.BinaryFileRef)
-	for _, ref := range refs {
-		out[ref.BuildID] = ref
-	}
-	return out, nil
-}
-
-type indexedInfo struct {
-	dumps   map[string]SymbolizerDump
-	summary map[string][]runtests.DataSink
-	ids     map[string]elflib.BinaryFileRef
-}
-
-type ProfileEntry struct {
-	ProfileData string   `json:"profile"`
-	ModuleFiles []string `json:"modules"`
-}
-
-func readInfo(dumpFiles, summaryFiles []string, idsFile string) (*indexedInfo, error) {
-	summary, err := readSummary(summaryFile)
-	if err != nil {
-		return nil, err
-	}
-	dumps, err := readSymbolizerOutput(symbolizeDumpFile)
-	if err != nil {
-		return nil, err
-	}
-	ids, err := readIDsTxt(idsFile)
-	if err != nil {
-		return nil, err
-	}
-	return &indexedInfo{
-		dumps:   dumps,
-		summary: summary,
-		ids:     ids,
-	}, nil
-}
-
-func mergeInfo(ctx context.Context, info *indexedInfo) ([]ProfileEntry, error) {
-	entries := []ProfileEntry{}
-
-	for _, sink := range info.summary[llvmProfileSinkType] {
-		dump, ok := info.dumps[sink.Name]
-		if !ok {
-			logger.Warningf(ctx, "%s not found in summary file\n", sink.Name)
-			continue
-		}
-
-		// This is going to go in a covDataEntry as the list of paths to the modules for the data
-		moduleFiles := []string{}
-		for _, mod := range dump.Modules {
-			if ref, ok := info.ids[mod.Build]; ok {
-				moduleFiles = append(moduleFiles, ref.Filepath)
-			} else {
-				logger.Warningf(ctx, "module with build id %s not found in ids.txt file\n", mod.Build)
-				continue
-			}
-		}
-
-		// Finally we can add all the data
-		entries = append(entries, ProfileEntry{
-			ModuleFiles: moduleFiles,
-			ProfileData: sink.File,
-		})
-	}
-
-	return entries, nil
-}
-
-type Action struct {
-	Path string   `json:"cmd"`
-	Args []string `json:"args"`
-}
-
-func (a Action) Run(ctx context.Context) ([]byte, error) {
-	logger.Debugf(ctx, "%s\n", a.String())
-	if !dryRun {
-		return exec.Command(a.Path, a.Args...).CombinedOutput()
-	}
-	return nil, nil
-}
-
-func (a Action) String() string {
-	var buf bytes.Buffer
-	fmt.Fprint(&buf, a.Path)
-	for _, arg := range a.Args {
-		fmt.Fprintf(&buf, " %s", arg)
-	}
-	return buf.String()
-}
-
-func isInstrumented(filepath string) bool {
-	sections := []string{"__llvm_covmap", "__llvm_prf_names"}
-	file, err := os.Open(filepath)
-	if err != nil {
-		return false
-	}
-	defer file.Close()
-	elfFile, err := elf.NewFile(file)
-	if err != nil {
-		return false
-	}
-	for _, section := range sections {
-		if sec := elfFile.Section(section); sec == nil {
-			return false
-		}
-	}
-	return true
-}
-
-func process(ctx context.Context) error {
-	// Make the output directory
-	err := os.MkdirAll(outputDir, os.ModePerm)
-	if err != nil {
-		return fmt.Errorf("creating output dir %s: %v", outputDir, err)
-	}
-
-	// Read in all the data
-	info, err := readInfo(symbolizeDumpFile, summaryFile, idsFile)
-	if err != nil {
-		return fmt.Errorf("parsing info: %v", err)
-	}
-
-	// Merge all the information
-	entries, err := mergeInfo(ctx, info)
-	if err != nil {
-		return fmt.Errorf("merging info: %v", err)
-	}
-
-	if jsonOutput != "" {
-		file, err := os.Create(jsonOutput)
-		if err != nil {
-			return fmt.Errorf("creating profile output file: %v", err)
-		}
-		defer file.Close()
-		if err := json.NewEncoder(file).Encode(entries); err != nil {
-			return fmt.Errorf("writing profile information: %v", err)
-		}
-	}
-
-	// Gather the set of modules and coverage files
-	modSet := make(map[string]struct{})
-	var mods []string
-	var covFiles []string
-	for _, entry := range entries {
-		for _, mod := range entry.ModuleFiles {
-			if _, ok := modSet[mod]; !ok && isInstrumented(mod) {
-				mods = append(mods, mod)
-				modSet[mod] = struct{}{}
-			}
-		}
-		// TODO(https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=34796): ideally this would
-		// be handled by llvm-profdata tool itself.
-		cmd := exec.Command(llvmProfdata, "show", entry.ProfileData)
-		if err := cmd.Run(); err != nil {
-			if _, ok := err.(*exec.ExitError); ok {
-				logger.Warningf(ctx, "profile %q is corrupted\n", entry.ProfileData)
-				continue
-			} else {
-				return fmt.Errorf("llvm-profdata show %s failed: %v", entry.ProfileData, err)
-			}
-		}
-		covFiles = append(covFiles, entry.ProfileData)
-	}
-
-	dir, err := ioutil.TempDir("", "covargs")
-	if err != nil {
-		return fmt.Errorf("cannot create temporary dir: %v", err)
-	}
-	defer os.RemoveAll(dir)
-
-	// Make the llvm-profdata response file
-	profdataFile, err := os.Create(filepath.Join(dir, "llvm-profdata.rsp"))
-	if err != nil {
-		return fmt.Errorf("creating llvm-profdata.rsp file: %v", err)
-	}
-	for _, covFile := range covFiles {
-		fmt.Fprintf(profdataFile, "%s\n", covFile)
-	}
-	profdataFile.Close()
-
-	// Merge everything
-	mergedFile := filepath.Join(dir, "merged.profdata")
-	mergeCmd := Action{Path: llvmProfdata, Args: []string{
-		"merge",
-		"-o", mergedFile,
-		"@" + profdataFile.Name(),
-	}}
-	data, err := mergeCmd.Run(ctx)
-	if err != nil {
-		return fmt.Errorf("%v:\n%s", err, string(data))
-	}
-
-	// Make the llvm-cov response file
-	covFile, err := os.Create(filepath.Join(dir, "llvm-cov.rsp"))
-	if err != nil {
-		return fmt.Errorf("creating llvm-cov.rsp file: %v", err)
-	}
-	for _, mod := range mods {
-		fmt.Fprintf(covFile, "-object %s\n", mod)
-	}
-	covFile.Close()
-
-	// Produce output
-	showCmd := Action{Path: llvmCov, Args: []string{
-		"show",
-		"-format", outputFormat,
-		"-instr-profile", mergedFile,
-		"-output-dir", outputDir,
-		"@" + covFile.Name(),
-	}}
-	data, err = showCmd.Run(ctx)
-	if err != nil {
-		return fmt.Errorf("%v:\n%s", err, string(data))
-	}
-	return nil
-}
-
-func main() {
-	flag.Parse()
-
-	log := logger.NewLogger(level, color.NewColor(colors), os.Stdout, os.Stderr, "")
-	ctx := logger.WithLogger(context.Background(), log)
-
-	if err := process(ctx); err != nil {
-		log.Errorf("%v\n", err)
-		os.Exit(1)
-	}
-}
diff --git a/debug/covargs/cmd/testdata/build/dl.c b/debug/covargs/cmd/testdata/build/dl.c
deleted file mode 100644
index 77b2aae..0000000
--- a/debug/covargs/cmd/testdata/build/dl.c
+++ /dev/null
@@ -1,7 +0,0 @@
-int main() {
-  if (0) {
-    return 1;
-  } else {
-    return 0;
-  }
-}
diff --git a/debug/covargs/cmd/testdata/build/dl.profraw b/debug/covargs/cmd/testdata/build/dl.profraw
deleted file mode 100644
index 3100c8d..0000000
--- a/debug/covargs/cmd/testdata/build/dl.profraw
+++ /dev/null
Binary files differ
diff --git a/debug/covargs/cmd/testdata/build/fbl.c b/debug/covargs/cmd/testdata/build/fbl.c
deleted file mode 100644
index 807d0f5..0000000
--- a/debug/covargs/cmd/testdata/build/fbl.c
+++ /dev/null
@@ -1,6 +0,0 @@
-void puts(const char*);
-
-int main() {
-  puts("Hello, World!");
-  return 0;
-}
diff --git a/debug/covargs/cmd/testdata/build/fbl.profraw b/debug/covargs/cmd/testdata/build/fbl.profraw
deleted file mode 100644
index ed0bc96..0000000
--- a/debug/covargs/cmd/testdata/build/fbl.profraw
+++ /dev/null
Binary files differ
diff --git a/debug/covargs/cmd/testdata/build/foo.c b/debug/covargs/cmd/testdata/build/foo.c
deleted file mode 100644
index 79c88fd..0000000
--- a/debug/covargs/cmd/testdata/build/foo.c
+++ /dev/null
@@ -1,7 +0,0 @@
-int foo() {
-  return 42;
-}
-
-int main() {
-  return foo();
-}
diff --git a/debug/covargs/cmd/testdata/build/foo.profraw b/debug/covargs/cmd/testdata/build/foo.profraw
deleted file mode 100644
index 1d491e9..0000000
--- a/debug/covargs/cmd/testdata/build/foo.profraw
+++ /dev/null
Binary files differ
diff --git a/debug/covargs/cmd/testdata/build/libc.c b/debug/covargs/cmd/testdata/build/libc.c
deleted file mode 100644
index 33ab303..0000000
--- a/debug/covargs/cmd/testdata/build/libc.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <stdio.h>
-
-int main() {
-  if (printf("this is a test")) {
-    return 0;
-  } else {
-    return 1;
-  }
-}
diff --git a/debug/covargs/cmd/testdata/build/libc.profraw b/debug/covargs/cmd/testdata/build/libc.profraw
deleted file mode 100644
index 9825399..0000000
--- a/debug/covargs/cmd/testdata/build/libc.profraw
+++ /dev/null
Binary files differ
diff --git a/debug/covargs/cmd/testdata/dump.json b/debug/covargs/cmd/testdata/dump.json
deleted file mode 100644
index 475b589..0000000
--- a/debug/covargs/cmd/testdata/dump.json
+++ /dev/null
@@ -1,12 +0,0 @@
-[
-  {"modules":[
-    {"name": "fbl.so", "build":"deadbeef", "id":0},
-    {"name": "a.out", "build":"deadcafe", "id":2}],
-    "segments":[], "type":"llvm-profile", "name": "llvm-profile.3190"},
-  {"modules":[
-    {"name": "dl.so", "build":"89abcdef", "id":3}],
-    "segments":[], "type":"llvm-profile", "name": "llvm-profile.1234"},
-  {"modules":[
-    {"name": "foo.so", "build":"ffffffff", "id":1}],
-    "segments":[], "type":"llvm-profile", "name": "llvm-profile.4567"}
-]
diff --git a/debug/covargs/cmd/testdata/ids.txt b/debug/covargs/cmd/testdata/ids.txt
deleted file mode 100644
index 5dc3a0d..0000000
--- a/debug/covargs/cmd/testdata/ids.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-deadbeef build/fbl.so
-12345678 build/libc.so
-ffffffff build/foo.so
-89abcdef build/dl.so
-deadcafe build/a.out
diff --git a/debug/covargs/cmd/testdata/summary.json b/debug/covargs/cmd/testdata/summary.json
deleted file mode 100644
index 7e91d53..0000000
--- a/debug/covargs/cmd/testdata/summary.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{"tests": [
-  {"name": "fbl-test",
-   "output_file": "stdout-and-stderr.txt",
-   "result": "PASS",
-   "data_sinks": {"llvm-profile": [
-     {"name": "llvm-profile.3190", "file": "build/fbl.profraw"}
-  ]}},
-  {"name": "foo-test",
-   "output_file": "stdout-and-stderr.txt",
-   "result": "PASS",
-   "data_sinks": {"llvm-profile": [
-     {"name": "llvm-profile.4567", "file": "build/foo.profraw"}
-  ]}},
-  {"name": "all-test",
-   "output_file": "stdout-and-stderr.txt",
-   "result": "PASS",
-   "data_sinks": {"llvm-profile": [
-     {"name": "llvm-profile.1234", "file": "build/dl.profraw"}
-   ]}}
- ],
- "outputs": {"syslog_file": "syslog.txt"}}
diff --git a/debug/dump_breakpad_symbols/cmd/depfile.go b/debug/dump_breakpad_symbols/cmd/depfile.go
deleted file mode 100644
index ee2dfb7..0000000
--- a/debug/dump_breakpad_symbols/cmd/depfile.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2019 The Fuchsia 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 (
-	"errors"
-	"fmt"
-	"io"
-	"strings"
-)
-
-// depfile writes Ninja dep files.
-type depfile struct {
-	// outputPath is the path to some new filesystem entity.
-	outputPath string
-
-	// inputPaths are the sources that were used to generate outputPath.
-	inputPaths []string
-}
-
-// WriteTo writes this depfile to the given io.Writer. Returns an error if the output is
-// empty, there are no input paths, or any of the inputs is empty.
-func (df *depfile) WriteTo(w io.Writer) (int64, error) {
-	if df.outputPath == "" {
-		return 0, errors.New("depfile is missing output")
-	}
-	if len(df.inputPaths) == 0 {
-		return 0, errors.New("depfile is missing inputs")
-	}
-	for _, input := range df.inputPaths {
-		if input == "" {
-			return 0, fmt.Errorf("got empty dep file input path: %v", df.inputPaths)
-		}
-	}
-
-	contents := fmt.Sprintf("%s: %s\n", df.outputPath, strings.Join(df.inputPaths, " "))
-	n, err := w.Write([]byte(contents))
-	return int64(n), err
-}
diff --git a/debug/dump_breakpad_symbols/cmd/depfile_test.go b/debug/dump_breakpad_symbols/cmd/depfile_test.go
deleted file mode 100644
index e7296e2..0000000
--- a/debug/dump_breakpad_symbols/cmd/depfile_test.go
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2019 The Fuchsia 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 (
-	"bytes"
-	"reflect"
-	"testing"
-)
-
-func TestDepfile(t *testing.T) {
-	tests := []struct {
-		// A name for this test case
-		name string
-
-		// The input depfile.
-		depfile *depfile
-
-		// The expected contents of the file produced by WriteTo.
-		output string
-
-		// Whether to expect an error when creating the dep file.
-		expectErr bool
-	}{
-		{
-			name: "should create a dep file with a single input",
-			depfile: &depfile{
-				outputPath: "a",
-				inputPaths: []string{"b"},
-			},
-			output: "a: b\n",
-		},
-		{
-			name: "should create a dep file with multiple inputs",
-			depfile: &depfile{
-				outputPath: "a",
-				inputPaths: []string{"b", "c"},
-			},
-			output: "a: b c\n",
-		},
-		{
-			name: "should err if the output path is missing",
-			depfile: &depfile{
-				inputPaths: []string{"b"},
-			},
-			expectErr: true,
-		},
-		{
-			name: "should err if the input paths are missing",
-			depfile: &depfile{
-				outputPath: "a",
-			},
-			expectErr: true,
-		},
-		{
-			name: "should err if any of the input paths is empty (first)",
-			depfile: &depfile{
-				outputPath: "a",
-				inputPaths: []string{"", "b"},
-			},
-			expectErr: true,
-		},
-		{
-			name: "should err if any of the input paths is empty (last)",
-			depfile: &depfile{
-				outputPath: "a",
-				inputPaths: []string{"b", ""},
-			},
-			expectErr: true,
-		},
-		{
-			name: "should err if any of the input paths is empty (nth)",
-			depfile: &depfile{
-				outputPath: "a",
-				inputPaths: []string{"b", "c", "", "e"},
-			},
-			expectErr: true,
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			var buf bytes.Buffer
-			_, err := tt.depfile.WriteTo(&buf)
-			if tt.expectErr && err == nil {
-				t.Errorf("wanted an error but got nil")
-				return
-			}
-			if !tt.expectErr && err != nil {
-				t.Errorf("got an unexpected error: %v", err)
-			}
-			actual := buf.String()
-			expected := tt.output
-			if !reflect.DeepEqual(actual, expected) {
-				t.Errorf("got:\n\n%v\n\nwanted:\n\n%v\n\n", actual, expected)
-			}
-		})
-	}
-}
diff --git a/debug/dump_breakpad_symbols/cmd/main.go b/debug/dump_breakpad_symbols/cmd/main.go
deleted file mode 100755
index 1ed0a42..0000000
--- a/debug/dump_breakpad_symbols/cmd/main.go
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2018 The Fuchsia 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 (
-	// TODO(kjharland): change crypto/sha1 to a safer hash algorithm. sha256 or sha2, etc.
-	"archive/tar"
-	"compress/gzip"
-	"context"
-	"flag"
-	"fmt"
-	"log"
-	"os"
-
-	"go.fuchsia.dev/tools/debug/breakpad/generator"
-	"go.fuchsia.dev/tools/debug/elflib"
-	"go.fuchsia.dev/tools/lib/tarutil"
-)
-
-const usage = `usage: dump_breakpad_symbols [options] paths...
-
-Generates breakpad symbol files by running dump_syms on a collection of binaries. Produces
-a tar archive containing all generated files. Expects a list of paths to .build-id dirs as
-input.
-
-Example invocation:
-
-$ dump_breakpad_symbols -dump-syms-path=dump_syms -tar-file=out.tar.gz -depfile=dep.out ./.build-ids
-`
-
-// Command line flag values
-var (
-	depFilepath  string
-	dumpSymsPath string
-	tarFilepath  string
-
-	// Flag to switch to using .build-id directory paths as input instead of ids.txt
-	// files.
-	//
-	// TODO(1068): Make this the default and delete support for ids.txt.
-	useBuildIDInput bool
-)
-
-func init() {
-	flag.Usage = func() {
-		fmt.Fprint(os.Stderr, usage)
-		flag.PrintDefaults()
-		os.Exit(0)
-	}
-
-	var unused string
-	flag.StringVar(&unused, "out-dir", "", "DEPRECATED. This is not used")
-	flag.StringVar(&dumpSymsPath, "dump-syms-path", "", "Path to the breakpad tools `dump_syms` executable")
-	flag.StringVar(&depFilepath, "depfile", "", "Path to the ninja depfile to generate")
-	flag.StringVar(&tarFilepath, "tar-file", "", "Path where the tar archive containing symbol files is written")
-	flag.BoolVar(&useBuildIDInput, "use-build-id", false, "Use .build-id dir inputs instead of ids.txt")
-}
-
-func main() {
-	flag.Parse()
-	if err := execute(context.Background(), flag.Args()...); err != nil {
-		log.Fatal(err)
-	}
-}
-
-func execute(ctx context.Context, paths ...string) error {
-	// Collect all binary file refs from each directory
-	var bfrs []elflib.BinaryFileRef
-	var err error
-	if useBuildIDInput {
-		bfrs, err = bfrsFromBuildIDs(paths...)
-	} else {
-		bfrs, err = bfrsFromIdsTxt(paths...)
-	}
-	if err != nil {
-		return err
-	}
-
-	// Skip files without .debug_info header.
-	bfrs = filterEmptyDebugSymbolFiles(bfrs)
-	// Generate all symbol files.
-	path, err := generator.Generate(bfrs, dumpSymsPath)
-	if err != nil {
-		return fmt.Errorf("failed to generate symbols: %v", err)
-	}
-
-	// Write all files to the specified tar archive.
-	tarfd, err := os.Create(tarFilepath)
-	if err != nil {
-		return fmt.Errorf("failed to create %q: %v", tarFilepath, err)
-	}
-	gzw := gzip.NewWriter(tarfd)
-	defer gzw.Close()
-	tw := tar.NewWriter(gzw)
-	defer tw.Close()
-
-	log.Printf("archiving %q to %q", path, tarFilepath)
-	if err := tarutil.TarDirectory(tw, path); err != nil {
-		return fmt.Errorf("failed to write %q: %v", tarFilepath, err)
-	}
-
-	// Write the Ninja dep file.
-	depfile := depfile{outputPath: tarFilepath, inputPaths: paths}
-	depfd, err := os.Create(depFilepath)
-	if err != nil {
-		return fmt.Errorf("failed to create %q: %v", depFilepath, err)
-	}
-	n, err := depfile.WriteTo(depfd)
-	if err != nil {
-		return fmt.Errorf("failed to write %q: %v", depFilepath, err)
-	}
-	if n == 0 {
-		return fmt.Errorf("wrote 0 bytes to %q", depFilepath)
-	}
-	return nil
-}
-
-// TODO(1068): Delete this after updating the build to use .build-id directories.
-func bfrsFromIdsTxt(paths ...string) ([]elflib.BinaryFileRef, error) {
-	var bfrs []elflib.BinaryFileRef
-	for _, path := range paths {
-		fd, err := os.Open(path)
-		if err != nil {
-			return nil, fmt.Errorf("failed to open %q: %v", path, err)
-		}
-		defer fd.Close()
-		newbfrs, err := elflib.ReadIDsFile(fd)
-		if err != nil {
-			return nil, fmt.Errorf("failed to read %q: %v", path, err)
-		}
-		bfrs = append(bfrs, newbfrs...)
-	}
-	return bfrs, nil
-}
-
-func bfrsFromBuildIDs(dirs ...string) ([]elflib.BinaryFileRef, error) {
-	var bfrs []elflib.BinaryFileRef
-	for _, dir := range dirs {
-		newbfrs, err := elflib.WalkBuildIDDir(dir)
-		if err != nil {
-			return nil, err
-		}
-		bfrs = append(bfrs, newbfrs...)
-	}
-	return bfrs, nil
-}
-
-// Returns filtered input of BinaryFileRefs, skipping files without .debug_info header.
-func filterEmptyDebugSymbolFiles(bfrs []elflib.BinaryFileRef) []elflib.BinaryFileRef {
-	var filteredBfrs []elflib.BinaryFileRef
-	for _, bfr := range bfrs {
-		hasDebugInfo, err := bfr.HasDebugInfo()
-		if err != nil {
-			log.Printf("WARNING: cannot read file %s: %v, skipping\n", bfr.Filepath, err)
-		} else if !hasDebugInfo {
-			log.Printf("WARNING: file %s missing .debug_info section, skipping\n", bfr.Filepath)
-		} else {
-			filteredBfrs = append(filteredBfrs, bfr)
-		}
-	}
-	return filteredBfrs
-}
diff --git a/debug/elflib/elflib.go b/debug/elflib/elflib.go
deleted file mode 100644
index bfb3a67..0000000
--- a/debug/elflib/elflib.go
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright 2018 The Fuchsia 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 elflib provides methods for handling ELF files.
-package elflib
-
-import (
-	"bufio"
-	"bytes"
-	"debug/elf"
-	"encoding/binary"
-	"encoding/hex"
-	"fmt"
-	"io"
-	"os"
-	"path/filepath"
-	"strings"
-)
-
-const NT_GNU_BUILD_ID uint32 = 3
-
-// DebugFileSuffix is the file suffix used by unstripped debug binaries.
-const DebugFileSuffix = ".debug"
-
-// BinaryFileRef represents a reference to an ELF file. The build id
-// and filepath are stored here. BinaryFileRefs can verify that their
-// build id matches their contents.
-type BinaryFileRef struct {
-	BuildID  string
-	Filepath string
-}
-
-// NewBinaryFileRef returns a BinaryFileRef with the given build id and filepath.
-func NewBinaryFileRef(filepath, build string) BinaryFileRef {
-	return BinaryFileRef{BuildID: build, Filepath: filepath}
-}
-
-type buildIDError struct {
-	err      error
-	filename string
-}
-
-func newBuildIDError(err error, filename string) *buildIDError {
-	return &buildIDError{err: err, filename: filename}
-}
-
-func (b buildIDError) Error() string {
-	return fmt.Sprintf("error reading %s: %v", b.filename, b.err)
-}
-
-// Verify verifies that the build id of b matches the build id found in the file.
-func (b BinaryFileRef) Verify() error {
-	file, err := os.Open(b.Filepath)
-	if err != nil {
-		return newBuildIDError(err, b.Filepath)
-	}
-	defer file.Close()
-	buildIDs, err := GetBuildIDs(b.Filepath, file)
-	if err != nil {
-		return newBuildIDError(err, b.Filepath)
-	}
-	binBuild, err := hex.DecodeString(b.BuildID)
-	if err != nil {
-		return newBuildIDError(fmt.Errorf("build ID `%s` is not a hex string: %v", b.BuildID, err), b.Filepath)
-	}
-	for _, buildID := range buildIDs {
-		if bytes.Equal(buildID, binBuild) {
-			return nil
-		}
-	}
-	return newBuildIDError(fmt.Errorf("build ID `%s` could not be found", b.BuildID), b.Filepath)
-}
-
-// HasDebugInfo checks if file contains debug_info section.
-func (b BinaryFileRef) HasDebugInfo() (bool, error) {
-	elfFile, err := elf.Open(b.Filepath)
-	if err != nil {
-		return false, err
-	}
-	defer elfFile.Close()
-	for _, section := range elfFile.Sections {
-		if section != nil && section.Name == ".debug_info" {
-			return true, nil
-		}
-	}
-	return false, nil
-}
-
-// rounds 'x' up to the next 'to' aligned value
-func alignTo(x, to uint32) uint32 {
-	return (x + to - 1) & -to
-}
-
-type noteEntry struct {
-	noteType uint32
-	name     string
-	desc     []byte
-}
-
-func forEachNote(note []byte, endian binary.ByteOrder, entryFn func(noteEntry)) error {
-	for {
-		var out noteEntry
-		// If there isn't enough to parse set n to nil.
-		if len(note) < 12 {
-			return nil
-		}
-		namesz := endian.Uint32(note[0:4])
-		descsz := endian.Uint32(note[4:8])
-		out.noteType = endian.Uint32(note[8:12])
-		if namesz+12 > uint32(len(note)) {
-			return fmt.Errorf("invalid name length in note entry")
-		}
-		out.name = string(note[12 : 12+namesz])
-		// We need to account for padding at the end.
-		descoff := alignTo(12+namesz, 4)
-		if descoff+descsz > uint32(len(note)) {
-			return fmt.Errorf("invalid desc length in note entry")
-		}
-		out.desc = note[descoff : descoff+descsz]
-		next := alignTo(descoff+descsz, 4)
-		// If the final padding isn't in the entry, don't throw error.
-		if next >= uint32(len(note)) {
-			note = note[len(note):]
-		} else {
-			note = note[next:]
-		}
-		entryFn(out)
-	}
-}
-
-func getBuildIDs(filename string, endian binary.ByteOrder, data io.ReaderAt, size uint64) ([][]byte, error) {
-	noteBytes := make([]byte, size)
-	_, err := data.ReadAt(noteBytes, 0)
-	if err != nil {
-		return nil, fmt.Errorf("error parsing section header in %s: %v", filename, err)
-	}
-	out := [][]byte{}
-	err = forEachNote(noteBytes, endian, func(entry noteEntry) {
-		if entry.noteType != NT_GNU_BUILD_ID || entry.name != "GNU\000" {
-			return
-		}
-		out = append(out, entry.desc)
-	})
-	return out, err
-}
-
-// GetBuildIDs parses and returns all the build ids from file's section/program headers.
-func GetBuildIDs(filename string, file io.ReaderAt) ([][]byte, error) {
-	elfFile, err := elf.NewFile(file)
-	if err != nil {
-		return nil, fmt.Errorf("could not parse ELF file %s: %v", filename, err)
-	}
-	if len(elfFile.Progs) == 0 && len(elfFile.Sections) == 0 {
-		return nil, fmt.Errorf("no program headers or sections in %s", filename)
-	}
-	var endian binary.ByteOrder
-	if elfFile.Data == elf.ELFDATA2LSB {
-		endian = binary.LittleEndian
-	} else {
-		endian = binary.BigEndian
-	}
-	out := [][]byte{}
-	// Check every SHT_NOTE section.
-	for _, section := range elfFile.Sections {
-		if section == nil || section.Type != elf.SHT_NOTE {
-			continue
-		}
-		buildIDs, err := getBuildIDs(filename, endian, section, section.Size)
-		if err != nil {
-			return out, err
-		}
-		out = append(out, buildIDs...)
-	}
-	// If we found what we were looking for with sections, don't reparse the program
-	// headers.
-	if len(out) > 0 {
-		return out, nil
-	}
-	// Check every PT_NOTE segment.
-	for _, prog := range elfFile.Progs {
-		if prog == nil || prog.Type != elf.PT_NOTE {
-			continue
-		}
-		buildIDs, err := getBuildIDs(filename, endian, prog, prog.Filesz)
-		if err != nil {
-			return out, err
-		}
-		out = append(out, buildIDs...)
-	}
-	return out, nil
-}
-
-// GetSoName returns the soname of the ELF file.
-func GetSoName(filename string, file io.ReaderAt) (string, error) {
-	elfFile, err := elf.NewFile(file)
-	if err != nil {
-		return "", fmt.Errorf("could not parse ELF file %s: %v", filename, err)
-	}
-	strings, err := elfFile.DynString(elf.DT_SONAME)
-	if err != nil {
-		return "", fmt.Errorf("when parsing .dynamic from %s: %v", filename, err)
-	}
-	if len(strings) > 1 {
-		return "", fmt.Errorf("expected at most one DT_SONAME entry in %s", filename)
-	}
-	if len(strings) == 0 {
-		return "", nil
-	}
-	return strings[0], nil
-}
-
-// ReadIDsFile reads a list of build ids and corresponding filenames from an ids file
-// and returns a list of BinaryFileRefs.
-func ReadIDsFile(file io.Reader) ([]BinaryFileRef, error) {
-	scanner := bufio.NewScanner(file)
-	out := []BinaryFileRef{}
-	for line := 1; scanner.Scan(); line++ {
-		text := scanner.Text()
-		parts := strings.SplitN(text, " ", 2)
-		if len(parts) != 2 {
-			return nil, fmt.Errorf("error parsing on line %d: found `%s`", line, text)
-		}
-		build := strings.TrimSpace(parts[0])
-		filename := strings.TrimSpace(parts[1])
-		out = append(out, BinaryFileRef{Filepath: filename, BuildID: build})
-	}
-	return out, nil
-}
-
-// WalkBuildIDDir walks the directory containing symbol files at dirpath and creates a
-// BinaryFileRef for each symbol file it finds. Files without a ".debug" suffix are
-// skipped. Each output BinaryFileRef's BuildID is formed by concatenating the file's
-// basename with its parent directory's basename. For example:
-//
-// Input directory:
-//
-//   de/
-//     adbeef.debug
-//     admeat.debug
-//
-// Output BuildIDs:
-//
-//   deadbeef.debug
-//   deadmeat.debug
-func WalkBuildIDDir(dirpath string) ([]BinaryFileRef, error) {
-	info, err := os.Stat(dirpath)
-	if err != nil {
-		return nil, fmt.Errorf("failed to stat %q: %v", dirpath, err)
-	}
-	if !info.IsDir() {
-		return nil, fmt.Errorf("%q is not a directory", dirpath)
-	}
-	var refs []BinaryFileRef
-	if err := filepath.Walk(dirpath, func(path string, info os.FileInfo, err error) error {
-		if err != nil {
-			return fmt.Errorf("%q: %v", path, err)
-		}
-		if info.IsDir() {
-			return nil
-		}
-		if !strings.HasSuffix(path, DebugFileSuffix) {
-			return nil
-		}
-		dir, basename := filepath.Split(path)
-		buildID := filepath.Base(dir) + strings.TrimSuffix(basename, DebugFileSuffix)
-		refs = append(refs, BinaryFileRef{
-			Filepath: path,
-			BuildID:  buildID,
-		})
-		return nil
-	}); err != nil {
-		return nil, err
-	}
-	return refs, nil
-}
diff --git a/debug/elflib/elflib_test.go b/debug/elflib/elflib_test.go
deleted file mode 100644
index 8c01747..0000000
--- a/debug/elflib/elflib_test.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2018 The Fuchsia 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 elflib
-
-import (
-	"encoding/hex"
-	"os"
-	"testing"
-)
-
-func TestBuildIDs(t *testing.T) {
-	f, err := os.Open("testdata/libc.elf.section-only")
-	if err != nil {
-		t.Fatal("from os.Open: ", err)
-	}
-	buildIDs, err := GetBuildIDs("testdata/libc.elf.section-only", f)
-	if err != nil {
-		t.Fatal("from GetBuildIDs: ", err)
-	}
-	if len(buildIDs) != 1 {
-		t.Fatal("expected one build ID but got ", buildIDs)
-	}
-	expected := "4fcb712aa6387724a9f465a32cd8c14b"
-	if hex.EncodeToString(buildIDs[0]) != expected {
-		t.Fatal("expected ", expected, " but got ", buildIDs[0])
-	}
-}
-
-func TestStrippedBuildIDs(t *testing.T) {
-	f, err := os.Open("testdata/libc.elf.stripped")
-	if err != nil {
-		t.Fatal("from os.Open: ", err)
-	}
-	buildIDs, err := GetBuildIDs("testdata/libc.elf.stripped", f)
-	if err != nil {
-		t.Fatal("from GetBuildIDs: ", err)
-	}
-	if len(buildIDs) != 1 {
-		t.Fatal("expected one build ID but got ", buildIDs)
-	}
-	expected := "4fcb712aa6387724a9f465a32cd8c14b"
-	if hex.EncodeToString(buildIDs[0]) != expected {
-		t.Fatal("expected ", expected, " but got ", buildIDs[0])
-	}
-}
diff --git a/debug/elflib/testdata/libc.elf.section-only b/debug/elflib/testdata/libc.elf.section-only
deleted file mode 100644
index cbced7c..0000000
--- a/debug/elflib/testdata/libc.elf.section-only
+++ /dev/null
Binary files differ
diff --git a/debug/elflib/testdata/libc.elf.stripped b/debug/elflib/testdata/libc.elf.stripped
deleted file mode 100755
index 0071813..0000000
--- a/debug/elflib/testdata/libc.elf.stripped
+++ /dev/null
Binary files differ
diff --git a/debug/elflib/testdata/libc.yaml b/debug/elflib/testdata/libc.yaml
deleted file mode 100644
index e33cfd0..0000000
--- a/debug/elflib/testdata/libc.yaml
+++ /dev/null
@@ -1,45 +0,0 @@
---- !ELF
-FileHeader:
-  Class:           ELFCLASS64
-  Data:            ELFDATA2LSB
-  Type:            ET_EXEC
-  Machine:         EM_X86_64
-Sections:
-  - Name:            .text
-    Type:            SHT_PROGBITS
-    Flags:           [ SHF_ALLOC ]
-  - Name:            .dynsym
-    Type:            SHT_DYNSYM
-  - Name:            .dynstr
-    Type:            SHT_STRTAB
-  - Name:            .note.gnu.build-id
-    Type:            SHT_NOTE
-    Flags:           [ SHF_ALLOC ]
-    AddressAlign:    0x0000000000000004
-    Content:         040000001000000003000000474E55004FCB712AA6387724A9F465A32CD8C14B
-DynamicSymbols:
-  Global:
-    - Name: atan2
-      Type: STT_FUNC
-      Section: .text
-    - Name: pow
-      Type: STT_FUNC
-      Section: .text
-    - Name: memcpy
-      Type: STT_FUNC
-      Section: .text
-ProgramHeaders:
-  - Type: PT_LOAD
-    Flags: [ PF_X, PF_R ]
-    Sections:
-      - Section: .text
-  - Type: PT_LOAD
-    Flags: [ PF_R ]
-    Sections:
-      - Section: .dynsym
-      - Section: .dynstr
-      - Section: .note.gnu.build-id
-  - Type: PT_NOTE
-    Flags: [ PF_R ]
-    Sections:
-      - Section: .note.gnu.build-id
diff --git a/debug/elflib/testdata/libc.yaml.section-only b/debug/elflib/testdata/libc.yaml.section-only
deleted file mode 100644
index 5bcd6ca..0000000
--- a/debug/elflib/testdata/libc.yaml.section-only
+++ /dev/null
@@ -1,12 +0,0 @@
---- !ELF
-FileHeader:
-  Class:           ELFCLASS64
-  Data:            ELFDATA2LSB
-  Type:            ET_EXEC
-  Machine:         EM_X86_64
-Sections:
-  - Name:            .note.gnu.build-id
-    Type:            SHT_NOTE
-    Flags:           [ SHF_ALLOC ]
-    AddressAlign:    0x0000000000000004
-    Content:         040000001000000003000000474E55004FCB712AA6387724A9F465A32CD8C14B
diff --git a/debug/symbolize/ast.go b/debug/symbolize/ast.go
deleted file mode 100644
index 4c9d9b8..0000000
--- a/debug/symbolize/ast.go
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"encoding/json"
-	"fmt"
-)
-
-// TODO (jakehehrlich): Add methods to make these node types usable
-
-// NodeVisitor is a visitor for all Node types
-type NodeVisitor interface {
-	VisitBt(elem *BacktraceElement)
-	VisitPc(elem *PCElement)
-	VisitColor(node *ColorCode)
-	VisitText(node *Text)
-	VisitDump(elem *DumpfileElement)
-	VisitReset(elem *ResetElement)
-	VisitModule(elem *ModuleElement)
-	VisitMapping(elem *MappingElement)
-}
-type Node interface {
-	Accept(visitor NodeVisitor)
-}
-
-// OptionalString implements possibly missing strings from llvm-symbolizer
-type OptStr struct {
-	val *string
-}
-
-func EmptyOptStr() OptStr {
-	return OptStr{}
-}
-
-func NewOptStr(s string) OptStr {
-	return OptStr{&s}
-}
-
-func (o *OptStr) Unwrap(def string) string {
-	if o.val != nil {
-		return *o.val
-	}
-	return def
-}
-
-func (o OptStr) IsEmpty() bool {
-	return o.val == nil
-}
-
-func (o OptStr) String() string {
-	return o.Unwrap("??")
-}
-
-func (o OptStr) MarshalJSON() ([]byte, error) {
-	return json.Marshal(o.String())
-}
-
-func (o OptStr) Format(f fmt.State, c rune) {
-	f.Write([]byte(o.String()))
-}
-
-// SourceLocation represents a location in a source file
-type SourceLocation struct {
-	file     OptStr
-	line     int
-	function OptStr
-}
-
-type BacktraceElement struct {
-	vaddr uint64
-	num   uint64
-	msg   string
-	info  addressInfo
-}
-
-func (b *BacktraceElement) Accept(visitor NodeVisitor) {
-	visitor.VisitBt(b)
-}
-
-// PcElement is an AST node representing a pc element in the markup
-type PCElement struct {
-	vaddr uint64
-	info  addressInfo
-}
-
-func (p *PCElement) Accept(visitor NodeVisitor) {
-	visitor.VisitPc(p)
-}
-
-// TODO(jakehehrlich): Make this semantic rather than literal (e.g. keep track of color/bold information directly)
-// ColorCode is an AST node representing a colored part of the markup
-type ColorCode struct {
-	color uint64
-}
-
-func (c *ColorCode) Accept(visitor NodeVisitor) {
-	visitor.VisitColor(c)
-}
-
-// Text represents text between the special parts of the markup
-type Text struct {
-	text string
-}
-
-func (t *Text) Accept(visitor NodeVisitor) {
-	visitor.VisitText(t)
-}
-
-type DumpfileElement struct {
-	sinkType string
-	name     string
-	context  *TriggerContext
-}
-
-func (d *DumpfileElement) Context() TriggerContext {
-	return *d.context
-}
-
-func (d *DumpfileElement) SinkType() string {
-	return d.sinkType
-}
-
-func (d *DumpfileElement) Name() string {
-	return d.name
-}
-
-func (d *DumpfileElement) Accept(visitor NodeVisitor) {
-	visitor.VisitDump(d)
-}
-
-type ResetElement struct{}
-
-func (r *ResetElement) Accept(visitor NodeVisitor) {
-	visitor.VisitReset(r)
-}
-
-// ModuleElement represents a module element in the markup
-type ModuleElement struct {
-	mod Module
-}
-
-func (m *ModuleElement) Accept(visitor NodeVisitor) {
-	visitor.VisitModule(m)
-}
-
-// MappingElement represents an mmap element in the markup
-type MappingElement struct {
-	seg Segment
-}
-
-func (s *MappingElement) Accept(visitor NodeVisitor) {
-	visitor.VisitMapping(s)
-}
diff --git a/debug/symbolize/cmd/main.go b/debug/symbolize/cmd/main.go
deleted file mode 100644
index 77763bf..0000000
--- a/debug/symbolize/cmd/main.go
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2018 The Fuchsia 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 (
-	"context"
-	"encoding/json"
-	"flag"
-	"fmt"
-	"io"
-	"os"
-
-	"go.fuchsia.dev/tools/debug/symbolize"
-	"go.fuchsia.dev/tools/lib/color"
-	"go.fuchsia.dev/tools/lib/logger"
-)
-
-type argList []string
-
-func (a *argList) String() string {
-	return fmt.Sprintf("%s", []string(*a))
-}
-
-func (a *argList) Set(value string) error {
-	*a = append(*a, value)
-	return nil
-}
-
-var (
-	buildIDDirPaths argList
-	colors          color.EnableColor
-	jsonOutput      string
-	idsPaths        argList
-	// TODO(jakehehrlich): Make idsRel always true and remove this flag.
-	idsRel        bool
-	level         logger.LogLevel
-	llvmSymboPath string
-)
-
-func init() {
-	colors = color.ColorAuto
-	level = logger.InfoLevel
-
-	flag.Var(&buildIDDirPaths, "build-id-dir", "path to .build-id directory")
-	flag.StringVar(&llvmSymboPath, "llvm-symbolizer", "llvm-symbolizer", "path to llvm-symbolizer")
-	flag.Var(&idsPaths, "ids", "path to ids.txt")
-	flag.Var(&colors, "color", "use color in output, can be never, auto, always")
-	flag.Var(&level, "level", "output verbosity, can be fatal, error, warning, info, debug or trace")
-	flag.StringVar(&jsonOutput, "json-output", "", "outputs trigger information to the specified file")
-	flag.BoolVar(&idsRel, "ids-rel", false, "tells the symbolizer to always use ids.txt relative paths")
-}
-
-type dumpEntry struct {
-	Modules  []symbolize.Module  `json:"modules"`
-	Segments []symbolize.Segment `json:"segments"`
-	Type     string              `json:"type"`
-	Name     string              `json:"name"`
-}
-
-type dumpHandler struct {
-	dumps []dumpEntry
-}
-
-func (d *dumpHandler) HandleDump(dump *symbolize.DumpfileElement) {
-	triggerCtx := dump.Context()
-	d.dumps = append(d.dumps, dumpEntry{
-		Modules:  triggerCtx.Mods,
-		Segments: triggerCtx.Segs,
-		Type:     dump.SinkType(),
-		Name:     dump.Name(),
-	})
-}
-
-func (d *dumpHandler) Write(buf io.Writer) error {
-	enc := json.NewEncoder(buf)
-	enc.SetIndent("", "  ")
-	err := enc.Encode(d.dumps)
-	if err != nil {
-		return err
-	}
-	return nil
-}
-
-func main() {
-	// Parse flags and setup helpers
-	flag.Parse()
-	var jsonTriggerHandler *dumpHandler
-	if jsonOutput != "" {
-		jsonTriggerHandler = &dumpHandler{}
-	}
-
-	// Setup logger and context
-	painter := color.NewColor(colors)
-	log := logger.NewLogger(level, painter, os.Stdout, os.Stderr, "")
-	ctx := logger.WithLogger(context.Background(), log)
-
-	// Construct the nodes of the pipeline
-	symbolizer := symbolize.NewLLVMSymbolizer(llvmSymboPath)
-	var repo symbolize.CompositeRepo
-	for _, dir := range buildIDDirPaths {
-		repo.AddRepo(symbolize.NewBuildIDRepo(dir))
-	}
-	for _, idsPath := range idsPaths {
-		repo.AddRepo(symbolize.NewIDsTxtRepo(idsPath, idsRel))
-	}
-	demuxer := symbolize.NewDemuxer(&repo, symbolizer)
-	tap := symbolize.NewTriggerTap()
-	if jsonTriggerHandler != nil {
-		tap.AddHandler(jsonTriggerHandler.HandleDump)
-	}
-	presenter := symbolize.NewBasicPresenter(os.Stdout, painter.Enabled())
-
-	// Build the pipeline to start presenting.
-	if err := symbolizer.Start(ctx); err != nil {
-		log.Fatalf("%v\n", err)
-	}
-	inputLines := symbolize.StartParsing(ctx, os.Stdin)
-	outputLines := demuxer.Start(ctx, inputLines)
-	trash := symbolize.ComposePostProcessors(ctx, outputLines,
-		tap,
-		&symbolize.ContextPresenter{},
-		&symbolize.OptimizeColor{},
-		symbolize.NewBacktracePresenter(os.Stdout, presenter))
-	symbolize.Consume(trash)
-
-	// Once the pipeline has finished output all triggers
-	if jsonTriggerHandler != nil {
-		file, err := os.Create(jsonOutput)
-		if err != nil {
-			log.Fatalf("%v\n", err)
-		}
-		if err := jsonTriggerHandler.Write(file); err != nil {
-			log.Fatalf("%v\n", err)
-		}
-	}
-}
diff --git a/debug/symbolize/demuxer.go b/debug/symbolize/demuxer.go
deleted file mode 100644
index 81c8c51..0000000
--- a/debug/symbolize/demuxer.go
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"context"
-	"fmt"
-
-	"go.fuchsia.dev/tools/lib/logger"
-)
-
-// TODO (jakehehrlich): Make as much of this private as possible.
-
-type remuxer struct {
-	seq chan (<-chan OutputLine)
-	out chan<- OutputLine
-}
-
-func newRemuxer() *remuxer {
-	return &remuxer{seq: make(chan (<-chan OutputLine), 1024)}
-}
-
-func (r *remuxer) sequence(in <-chan OutputLine) {
-	r.seq <- in
-}
-
-func (r *remuxer) start(ctx context.Context) (<-chan OutputLine, error) {
-	if r.out != nil {
-		return nil, fmt.Errorf("Attempt to start an already running remuxer")
-	}
-	out := make(chan OutputLine)
-	r.out = out
-	go func() {
-		defer close(r.out)
-		for {
-			select {
-			case <-ctx.Done():
-				return
-			case in, ok := <-r.seq:
-				if !ok {
-					return
-				}
-				r.out <- (<-in)
-			}
-		}
-	}()
-	return out, nil
-}
-
-func (r *remuxer) stop() error {
-	close(r.seq)
-	if r.seq == nil {
-		return fmt.Errorf("Attempt to stop a remuxer that hasn't been started")
-	}
-	return nil
-}
-
-type pipe struct {
-	in  chan<- InputLine
-	out <-chan OutputLine
-}
-
-// Demuxer demultiplexes incomming input lines, spins up new filters, and sends them input lines.
-type Demuxer struct {
-	// Spin up new filters as new procsses are found.
-	filters map[LineSource]pipe
-	// Use same symbolizer for all
-	symbolizer Symbolizer
-	// Use same repo for all
-	repo Repository
-}
-
-// NewDemuxer creates a new demuxer.
-func NewDemuxer(repo Repository, symbo Symbolizer) *Demuxer {
-	return &Demuxer{
-		repo:       repo,
-		symbolizer: symbo,
-		filters:    make(map[LineSource]pipe),
-	}
-}
-
-// Start tells the demuxer to start consuming input and dispatching to the filters.
-func (d *Demuxer) Start(ctx context.Context, input <-chan InputLine) <-chan OutputLine {
-	// Create the remuxer.
-	remux := newRemuxer()
-	out, err := remux.start(ctx)
-	if err != nil {
-		logger.Fatalf(ctx, "Failed to start remuxer in case where that should never happen.")
-	}
-	go func() {
-		// Clean up the channels/goroutines when we're done
-		defer func() {
-			for _, pipe := range d.filters {
-				close(pipe.in)
-			}
-			err := remux.stop()
-			if err != nil {
-				logger.Warningf(ctx, "%v", err)
-			}
-		}()
-		// Start multiplexing things out
-		for {
-			select {
-			case <-ctx.Done():
-				return
-			case line, ok := <-input:
-				if !ok {
-					return
-				}
-				var fpipe pipe
-				if fpipe, ok = d.filters[line.source]; !ok {
-					fin := make(chan InputLine)
-					// Spin up a new Filter for this process.
-					filt := NewFilter(d.repo, d.symbolizer)
-					fout := filt.Start(ctx, fin)
-					fpipe = pipe{in: fin, out: fout}
-					d.filters[line.source] = fpipe
-				}
-				// sequence a read from fpipe.out
-				remux.sequence(fpipe.out)
-				fpipe.in <- line
-			}
-		}
-	}()
-	return out
-}
diff --git a/debug/symbolize/demuxer_test.go b/debug/symbolize/demuxer_test.go
deleted file mode 100644
index 106e52f..0000000
--- a/debug/symbolize/demuxer_test.go
+++ /dev/null
@@ -1,415 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"bytes"
-	"context"
-	"os"
-	"strings"
-	"testing"
-)
-
-type triggerTester struct {
-	count    uint64
-	sinkType string
-	name     string
-	src      LineSource
-	mod      Module
-	seg      Segment
-	t        *testing.T
-}
-
-func (t *triggerTester) HandleDump(dump *DumpfileElement) {
-	t.count += 1
-	if dump == nil {
-		t.t.Fatal("dump was nil")
-	}
-	t.sinkType = dump.SinkType()
-	t.name = dump.Name()
-	t.src = dump.Context().Source
-	mods := dump.Context().Mods
-	segs := dump.Context().Segs
-	if len(mods) != 1 {
-		t.t.Fatal("expected exactly 1 module")
-	}
-	t.mod = mods[0]
-	if len(segs) != 1 {
-		t.t.Fatal("expected exactly 1 segment")
-	}
-	t.seg = segs[0]
-}
-
-func TestDumpfile(t *testing.T) {
-	msg := "[123.456] 01234.5678> {{{module:1:libc.so:elf:4fcb712aa6387724a9f465a32cd8c14b}}}\n" +
-		"[123.456] 1234:05678> {{{mmap:0x12345000:849596:load:1:rx:0x0}}}\n" +
-		"[123.456] 01234.05678> {{{dumpfile:llvm-cov:test}}}\n"
-
-	symbo := newMockSymbolizer([]mockModule{})
-	demuxer := NewDemuxer(testBinaries, symbo)
-	tap := NewTriggerTap()
-	tHandler := &triggerTester{t: t}
-	tap.AddHandler(tHandler.HandleDump)
-
-	ctx := context.Background()
-	in := StartParsing(ctx, strings.NewReader(msg))
-	out := demuxer.Start(ctx, in)
-	buf := new(bytes.Buffer)
-	Consume(ComposePostProcessors(ctx, out, tap, &ContextPresenter{}, &OptimizeColor{}, NewBasicPresenter(buf, true)))
-
-	expectedSrc := Process(1234)
-	expectedMod := Module{
-		Name:  "libc.so",
-		Build: "4fcb712aa6387724a9f465a32cd8c14b",
-		Id:    1,
-	}
-	expectedSeg := Segment{
-		Mod:        1,
-		Vaddr:      0x12345000,
-		Size:       849596,
-		Flags:      "rx",
-		ModRelAddr: 0x0,
-	}
-	expectedSink := "llvm-cov"
-	expectedName := "test"
-	expected := "[123.456] 01234.05678> [[[ELF module #0x1 \"libc.so\" BuildID=4fcb712aa6387724a9f465a32cd8c14b 0x12345000]]]\n" +
-		"[123.456] 01234.05678> {{{dumpfile:llvm-cov:test}}}\n"
-
-	actual := buf.String()
-	if actual != expected {
-		t.Error("expected", expected, "got", actual)
-	}
-	if tHandler.sinkType != expectedSink {
-		t.Error("expected", expectedSink, "got", tHandler.sinkType)
-	}
-	if tHandler.name != expectedName {
-		t.Error("expected", expectedName, "got", tHandler.name)
-	}
-	if tHandler.src != expectedSrc {
-		t.Error("expected", expectedSrc, "got", tHandler.src)
-	}
-	if tHandler.mod != expectedMod {
-		t.Error("expected", expectedMod, "got", tHandler.mod)
-	}
-	if tHandler.seg != expectedSeg {
-		t.Error("expected", expectedSeg, "got", tHandler.seg)
-	}
-	if tHandler.count == 0 {
-		t.Error("trigger handler was not called")
-	}
-	if tHandler.count > 1 {
-		t.Error("trigger handler was called more than once")
-	}
-}
-
-func TestSyslog(t *testing.T) {
-	msg := "[123.456][1234][05678][klog] INFO: Blarg\n"
-	symbo := newMockSymbolizer([]mockModule{})
-	demuxer := NewDemuxer(testBinaries, symbo)
-	ctx := context.Background()
-	in := StartParsing(ctx, strings.NewReader(msg))
-	out := demuxer.Start(ctx, in)
-	buf := new(bytes.Buffer)
-	Consume(ComposePostProcessors(ctx, out, &ContextPresenter{}, &OptimizeColor{}, NewBasicPresenter(buf, true)))
-	expected := "[00123.456000][1234][5678][klog] INFO: Blarg\n"
-	actual := buf.String()
-	if actual != expected {
-		t.Error("expected", expected, "got", actual)
-	}
-}
-
-func TestColor(t *testing.T) {
-	// TODO(jakehehrlich): Change presenter so that redundent resets are not used when user input already contains them.
-	msg := "[0.0] 01234.5678> \033[1mThis is bold \033[31mThis is red and bold \033[37mThis is bold white\n" +
-		"[0.0] 1234:05678> This is just normal and has no trailing ANSI code\n" +
-		"[0.0] 1234:5678> \033[1m\033[31m this line tests adjacent state changes\n" +
-		"[0.0] 01234.5678> \033[1m\033[31m this line will eventully test non-redundent reset \033[1m\n"
-	symbo := newMockSymbolizer([]mockModule{})
-	demuxer := NewDemuxer(testBinaries, symbo)
-	ctx := context.Background()
-	in := StartParsing(ctx, strings.NewReader(msg))
-	out := demuxer.Start(ctx, in)
-	buf := new(bytes.Buffer)
-	Consume(ComposePostProcessors(ctx, out, &ContextPresenter{}, &OptimizeColor{}, NewBasicPresenter(buf, true)))
-	expected := "[0.000] 01234.05678> \033[1mThis is bold \033[31mThis is red and bold \033[37mThis is bold white\033[0m\n" +
-		"[0.000] 01234.05678> This is just normal and has no trailing ANSI code\n" +
-		"[0.000] 01234.05678> \033[31m\033[1m this line tests adjacent state changes\033[0m\n" +
-		"[0.000] 01234.05678> \033[31m\033[1m this line will eventully test non-redundent reset \033[0m\n"
-	actual := buf.String()
-	if actual != expected {
-		t.Errorf("expected %#v got %#v", expected, actual)
-	}
-}
-
-func TestKeepLeadingSpace(t *testing.T) {
-	// mock the input and outputs of llvm-symbolizer
-	symbo := newMockSymbolizer([]mockModule{})
-	// make a demuxer
-	demuxer := NewDemuxer(testBinaries, symbo)
-
-	// define a little message that will need to be parsed
-	msg := "[0.000] 00000.00000>      \tkeep\n"
-
-	// start sending InputLines to the demuxer
-	ctx := context.Background()
-	in := StartParsing(ctx, strings.NewReader(msg))
-	// start the demuxer which will cause filters to send output lines to 'out'
-	out := demuxer.Start(ctx, in)
-	var buf bytes.Buffer
-	Consume(ComposePostProcessors(ctx, out, NewBasicPresenter(&buf, false)))
-	if string(buf.Bytes()) != msg {
-		t.Fatal("expected", msg, "got", string(buf.Bytes()))
-	}
-}
-
-func ExampleDummyProcess() {
-	// mock the input and outputs of llvm-symbolizer
-	symbo := newMockSymbolizer([]mockModule{
-		{"testdata/libc.elf", map[uint64][]SourceLocation{
-			0x429c0: {{NewOptStr("atan2.c"), 33, NewOptStr("atan2")}},
-		}},
-	})
-
-	// make a demuxer
-	demuxer := NewDemuxer(testBinaries, symbo)
-
-	// define a little message that will need to be parsed
-	msg := "{{{module:1:libc.so:elf:4fcb712aa6387724a9f465a32cd8c14b}}}\n" +
-		"{{{mmap:0x12345000:849596:load:1:rx:0x0}}}\n" +
-		"{{{pc:0x123879c0}}}\n" +
-		"blarg[0.0] 0.0> This should be on it's own line\n"
-
-	// start sending InputLines to the demuxer
-	ctx := context.Background()
-	in := StartParsing(ctx, strings.NewReader(msg))
-	// start the demuxer which will cause filters to send output lines to 'out'
-	out := demuxer.Start(ctx, in)
-
-	Consume(ComposePostProcessors(ctx, out, &ContextPresenter{}, &OptimizeColor{}, NewBasicPresenter(os.Stdout, false)))
-
-	//Output:
-	//[[[ELF module #0x1 "libc.so" BuildID=4fcb712aa6387724a9f465a32cd8c14b 0x12345000]]]
-	//atan2 at atan2.c:33
-	//blarg
-	//[0.000] 00000.00000> This should be on it's own line
-}
-
-func ExampleDemux() {
-	// mock the input and outputs of llvm-symbolizer
-	symbo := newMockSymbolizer([]mockModule{
-		{"testdata/libc.elf", map[uint64][]SourceLocation{
-			0x429c0: {{NewOptStr("atan2.c"), 49, NewOptStr("atan2")}, {NewOptStr("math.h"), 51, NewOptStr("__DOUBLE_FLOAT")}},
-			0x43680: {{NewOptStr("pow.c"), 23, NewOptStr("pow")}},
-			0x44987: {{NewOptStr("memcpy.c"), 76, NewOptStr("memcpy")}},
-		}},
-		{"testdata/libcrypto.elf", map[uint64][]SourceLocation{
-			0x81000: {{NewOptStr("rsa.c"), 101, NewOptStr("mod_exp")}},
-			0x82000: {{NewOptStr("aes.c"), 17, NewOptStr("gf256_mul")}},
-			0x83000: {{NewOptStr("aes.c"), 560, NewOptStr("gf256_div")}},
-		}},
-	})
-
-	// make a demuxer
-	demuxer := NewDemuxer(testBinaries, symbo)
-
-	// define a little message that will need to be parsed
-	msg := "[131.200] 1234.5678> keep {{{module:1:libc.so:elf:4fcb712aa6387724a9f465a32cd8c14b}}}\n" +
-		"[131.301] 1234.5678> {{{module:2:libcrypto.so:elf:b4b6c520ccf0aa11ff71d8ded7d6a2bc03037aa1}}} keep\n" +
-		"[131.402] 1234.5678> {{{mmap:0x12345000:0xcf6bc:load:1:rx:0x0}}}\n" +
-		"[131.503] 1234.5678> {{{mmap:0x23456000:0x83c80:load:2:rx:0x80000}}}\n" +
-		"[131.604] 1234.5678> \033[1mError at {{{pc:0x123879c0}}}\n"
-
-	// start sending InputLines to the demuxer
-	ctx := context.Background()
-	in := StartParsing(ctx, strings.NewReader(msg))
-	// start the demuxer which will cause filters to send output lines to 'out'
-	out := demuxer.Start(ctx, in)
-
-	Consume(ComposePostProcessors(ctx, out, &ContextPresenter{}, &OptimizeColor{}, NewBasicPresenter(os.Stdout, false)))
-
-	//Output:
-	//[131.200] 01234.05678> [[[ELF module #0x1 "libc.so" BuildID=4fcb712aa6387724a9f465a32cd8c14b]]]
-	//[131.200] 01234.05678> keep {{{module:4fcb712aa6387724a9f465a32cd8c14b:libc.so:1}}}
-	//[131.301] 01234.05678> [[[ELF module #0x2 "libcrypto.so" BuildID=b4b6c520ccf0aa11ff71d8ded7d6a2bc03037aa1]]]
-	//[131.301] 01234.05678> {{{module:b4b6c520ccf0aa11ff71d8ded7d6a2bc03037aa1:libcrypto.so:2}}} keep
-	//[131.402] 01234.05678> [[[ELF seg #0x1 0x12345000]]]
-	//[131.503] 01234.05678> [[[ELF seg #0x2 0x233d6000]]]
-	//[131.604] 01234.05678> Error at atan2 at atan2.c:49
-}
-
-func TestMsgSimpleBacktrace(t *testing.T) {
-	msg := "{{{bt:0:0xdeadbeef:this is a message}}}\n"
-	symbo := newMockSymbolizer([]mockModule{})
-	demuxer := NewDemuxer(testBinaries, symbo)
-	ctx := context.Background()
-	in := StartParsing(ctx, strings.NewReader(msg))
-	out := demuxer.Start(ctx, in)
-	buf := new(bytes.Buffer)
-	Consume(ComposePostProcessors(ctx, out, &ContextPresenter{},
-		NewBacktracePresenter(buf, NewBasicPresenter(buf, false))))
-	expected := "    #0    0x00000000deadbeef in <>+0xdeadbeef this is a message\n"
-	actual := buf.String()
-	if actual != expected {
-		t.Errorf("want %q got %q", expected, actual)
-	}
-}
-
-func ExampleMsgBacktrace() {
-	// mock the input and outputs of llvm-symbolizer
-	symbo := newMockSymbolizer([]mockModule{
-		{"testdata/libc.elf", map[uint64][]SourceLocation{
-			0x43680: {{NewOptStr("pow.c"), 23, NewOptStr("pow")}},
-		}},
-	})
-
-	// make a demuxer
-	demuxer := NewDemuxer(testBinaries, symbo)
-
-	// define a little message that will need to be parsed
-	msg := "{{{module:1:libc.so:elf:4fcb712aa6387724a9f465a32cd8c14b}}}\n" +
-		"{{{mmap:0x12345000:0xcf6bc:load:1:rx:0x0}}}\n" +
-		"{{{bt:0:0x12388680:sp 0xdeadbaaf bp 0xdeadbeef}}}\n"
-
-	// start sending InputLines to the demuxer
-	ctx := context.Background()
-	in := StartParsing(ctx, strings.NewReader(msg))
-	// start the demuxer which will cause filters to send output lines to 'out'
-	out := demuxer.Start(ctx, in)
-
-	Consume(ComposePostProcessors(ctx, out,
-		&ContextPresenter{},
-		NewBacktracePresenter(os.Stdout, NewBasicPresenter(os.Stdout, false))))
-
-	//Output:
-	//[[[ELF module #0x1 "libc.so" BuildID=4fcb712aa6387724a9f465a32cd8c14b 0x12345000]]]
-	//     #0    0x0000000012388680 in pow pow.c:23 <libc.so>+0x43680 sp 0xdeadbaaf bp 0xdeadbeef
-}
-
-func ExampleNoHeaderBacktrace() {
-	// mock the input and outputs of llvm-symbolizer
-	symbo := newMockSymbolizer([]mockModule{
-		{"testdata/libc.elf", map[uint64][]SourceLocation{
-			0x429c0: {{NewOptStr("math.h"), 51, NewOptStr("__DOUBLE_FLOAT")}, {NewOptStr("atan2.c"), 49, NewOptStr("atan2")}},
-			0x43680: {{NewOptStr("pow.c"), 23, NewOptStr("pow")}},
-			0x44987: {{NewOptStr("memcpy.c"), 76, NewOptStr("memcpy")}},
-		}},
-	})
-
-	// make a demuxer
-	demuxer := NewDemuxer(testBinaries, symbo)
-
-	// define a little message that will need to be parsed
-	msg := "{{{module:1:libc.so:elf:4fcb712aa6387724a9f465a32cd8c14b}}}\n" +
-		"{{{mmap:0x12345000:0xcf6bc:load:1:rx:0x0}}}\n" +
-		"Backtrace:\n" +
-		"{{{bt:0:0x12388680}}}\n" +
-		"{{{bt:1:0x123879c0}}}\n"
-
-	// start sending InputLines to the demuxer
-	ctx := context.Background()
-	in := StartParsing(ctx, strings.NewReader(msg))
-	// start the demuxer which will cause filters to send output lines to 'out'
-	out := demuxer.Start(ctx, in)
-
-	Consume(ComposePostProcessors(ctx, out,
-		&ContextPresenter{},
-		NewBacktracePresenter(os.Stdout, NewBasicPresenter(os.Stdout, false))))
-
-	//Output:
-	//[[[ELF module #0x1 "libc.so" BuildID=4fcb712aa6387724a9f465a32cd8c14b 0x12345000]]]
-	//Backtrace:
-	//     #0    0x0000000012388680 in pow pow.c:23 <libc.so>+0x43680
-	//     #1.1  0x00000000123879c0 in __DOUBLE_FLOAT math.h:51 <libc.so>+0x429c0
-	//     #1    0x00000000123879c0 in atan2 atan2.c:49 <libc.so>+0x429c0
-}
-
-func ExampleNewBacktracePresenter() {
-	// mock the input and outputs of llvm-symbolizer
-	symbo := newMockSymbolizer([]mockModule{
-		{"testdata/libc.elf", map[uint64][]SourceLocation{
-			0x429c0: {{NewOptStr("math.h"), 51, NewOptStr("__DOUBLE_FLOAT")}, {NewOptStr("atan2.c"), 49, NewOptStr("atan2")}},
-			0x43680: {{NewOptStr("pow.c"), 23, NewOptStr("pow")}},
-			0x44987: {{NewOptStr("memcpy.c"), 76, NewOptStr("memcpy")}},
-		}},
-		{"testdata/libcrypto.elf", map[uint64][]SourceLocation{
-			0x81000: {{NewOptStr("rsa.c"), 101, NewOptStr("mod_exp")}},
-			0x82000: {{NewOptStr("aes.c"), 17, NewOptStr("gf256_mul")}},
-			0x83000: {{NewOptStr("aes.c"), 560, NewOptStr("gf256_div")}},
-		}},
-	})
-
-	// make a demuxer
-	demuxer := NewDemuxer(testBinaries, symbo)
-
-	// define a little message that will need to be parsed
-	msg := "[131.200] 1234.5678> {{{module:1:libc.so:elf:4fcb712aa6387724a9f465a32cd8c14b}}}\n" +
-		"[131.301] 1234.5678> {{{module:9:libcrypto.so:elf:12ef5c50b3ed3599c07c02d4509311be}}}\n" +
-		"[131.301] 1234.5678> {{{module:3:libmissing.no:elf:deadbeef}}}\n" +
-		"[131.402] 1234.5678> {{{mmap:0x12345000:0xcf6bc:load:1:rx:0x0}}}\n" +
-		"[131.503] 1234.5678> {{{mmap:0x23456000:0x83c80:load:09:rx:0x80000}}}\n" +
-		"[131.503] 1234.5678> {{{mmap:0x34567000:0x1000:load:3:rx:0x0}}}\n" +
-		"[131.604] 1234.5678> Backtrace:\n" +
-		"[131.604] 1234.5678> {{{bt:0:0x12388680}}}\n" +
-		"[131.604] 1234.5678> {{{bt:1:0x23457000}}}\n" +
-		"[131.604] 1234.5678> {{{bt:2:0x123879c0}}}\n" +
-		"[131.705] 1234.5678> {{{bt:3:0x34567042}}}\n"
-
-	// start sending InputLines to the demuxer
-	ctx := context.Background()
-	in := StartParsing(ctx, strings.NewReader(msg))
-	// start the demuxer which will cause filters to send output lines to 'out'
-	out := demuxer.Start(ctx, in)
-
-	Consume(ComposePostProcessors(ctx, out,
-		&ContextPresenter{},
-		NewBacktracePresenter(os.Stdout, NewBasicPresenter(os.Stdout, false))))
-
-	//Output:
-	//[131.604] 01234.05678> [[[ELF module #0x1 "libc.so" BuildID=4fcb712aa6387724a9f465a32cd8c14b 0x12345000]]]
-	//[131.604] 01234.05678> [[[ELF module #0x3 "libmissing.no" BuildID=deadbeef 0x34567000]]]
-	//[131.604] 01234.05678> [[[ELF module #0x9 "libcrypto.so" BuildID=12ef5c50b3ed3599c07c02d4509311be 0x23456000]]]
-	//[131.604] 01234.05678> Backtrace:
-	//[131.604] 01234.05678>    #0    0x0000000012388680 in pow pow.c:23 <libc.so>+0x43680
-	//[131.604] 01234.05678>    #1    0x0000000023457000 in mod_exp rsa.c:101 <libcrypto.so>+0x81000
-	//[131.604] 01234.05678>    #2.1  0x00000000123879c0 in __DOUBLE_FLOAT math.h:51 <libc.so>+0x429c0
-	//[131.604] 01234.05678>    #2    0x00000000123879c0 in atan2 atan2.c:49 <libc.so>+0x429c0
-	//[131.705] 01234.05678>    #3    0x0000000034567042 in <libmissing.no>+0x42
-}
-
-func ExampleBadAddr() {
-	// mock the input and outputs of llvm-symbolizer
-	symbo := newMockSymbolizer([]mockModule{
-		{"testdata/libc.elf", map[uint64][]SourceLocation{
-			0x429c0: {{EmptyOptStr(), 0, NewOptStr("atan2")}, {NewOptStr("math.h"), 51, NewOptStr("__DOUBLE_FLOAT")}},
-			0x43680: {{NewOptStr("pow.c"), 67, EmptyOptStr()}},
-			0x44987: {{NewOptStr("memcpy.c"), 76, NewOptStr("memcpy")}},
-		}},
-	})
-
-	// make a demuxer
-	demuxer := NewDemuxer(testBinaries, symbo)
-
-	// define a little message that will need to be parsed
-	msg := "[131.200] 1234.5678> {{{module:1:libc.so:elf:4fcb712aa6387724a9f465a32cd8c14b}}}\n" +
-		"[131.402] 1234.5678> {{{mmap:0x12345000:0xcf6bc:load:1:rx:0x0}}}\n" +
-		"[131.402] 1234.5678> {{{mmap:0x12345000:0xcf6bc:load:01:rx:0x0}}}\n" +
-		"[131.604] 1234.5678> {{{pc:0x123879ff}}}\n" +
-		"[131.605] 1234.5678> {{{pc:0x123879c0}}}\n" +
-		"[131.606] 1234.5678> {{{pc:0x12388680}}}\n"
-
-	// start sending InputLines to the demuxer
-	ctx := context.Background()
-	in := StartParsing(ctx, strings.NewReader(msg))
-	// start the demuxer which will cause filters to send output lines to 'out'
-	out := demuxer.Start(ctx, in)
-
-	Consume(ComposePostProcessors(ctx, out, &ContextPresenter{}, &OptimizeColor{}, NewBasicPresenter(os.Stdout, true)))
-
-	//Output:
-	//[131.604] 01234.05678> [[[ELF module #0x1 "libc.so" BuildID=4fcb712aa6387724a9f465a32cd8c14b 0x12345000]]]
-	//[131.604] 01234.05678> <libc.so>+0x429ff
-	//[131.605] 01234.05678> atan2 at <libc.so>+0x429c0
-	//[131.606] 01234.05678> pow.c:67
-}
diff --git a/debug/symbolize/filter.go b/debug/symbolize/filter.go
deleted file mode 100644
index 07918df..0000000
--- a/debug/symbolize/filter.go
+++ /dev/null
@@ -1,293 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"context"
-	"fmt"
-
-	"go.fuchsia.dev/tools/lib/logger"
-)
-
-// TODO (jakehehrlich): LineSource is now a part of the public interface. This is needed to
-// allow for the proper construction of triggers since triggers need to know
-// where a triggering element came from. Right now this is just an empty
-// interface. It would be nice if the user could do soemthing other than cast this.
-type LineSource interface{}
-
-type Process uint64
-
-type DummySource struct{}
-
-type LineHeader interface {
-	Present() string
-}
-
-type logHeader struct {
-	time    float64
-	process uint64
-	thread  uint64
-}
-
-func (l logHeader) Present() string {
-	return fmt.Sprintf("[%.3f] %05d.%05d>", l.time, l.process, l.thread)
-}
-
-type sysLogHeader struct {
-	time    float64
-	process uint64
-	thread  uint64
-	tags    string
-	typ     string
-}
-
-func (s sysLogHeader) Present() string {
-	return fmt.Sprintf("[%012.6f][%d][%d][%s] %s:", s.time, s.process, s.thread, s.tags, s.typ)
-}
-
-type LogLine struct {
-	lineno uint64
-	header LineHeader
-	source LineSource
-}
-
-type InputLine struct {
-	LogLine
-	msg string
-}
-
-// Later this will be more general.
-type Segment struct {
-	Mod        uint64 `json:"mod"`
-	Vaddr      uint64 `json:"vaddr"`
-	Size       uint64 `json:"size"`
-	Flags      string `json:"flags"`
-	ModRelAddr uint64 `json:"modRelAddr"`
-}
-
-type addressInfo struct {
-	locs []SourceLocation
-	mod  Module
-	seg  Segment
-	addr uint64
-}
-
-type Module struct {
-	Name  string `json:"name"`
-	Build string `json:"build"`
-	Id    uint64 `json:"id"`
-}
-
-type OutputLine struct {
-	LogLine
-	line []Node
-}
-
-type missingObjError struct {
-	name    string
-	buildid string
-	err     error
-}
-
-func (m *missingObjError) Error() string {
-	return fmt.Sprintf("could not find file for module %s with build ID %s: %v", m.name, m.buildid, m.err)
-}
-
-type Repository interface {
-	GetBuildObject(buildID string) (string, error)
-}
-
-// Filter represents the state needed to process a log.
-type Filter struct {
-	// handles for llvm-symbolizer
-	symbolizer Symbolizer
-	// Symbolizer context
-	symContext        mappingStore
-	modules           map[uint64]Module
-	modNamesByBuildID map[string]string
-	// Symbolizer repository
-	repo Repository
-}
-
-// TODO (jakehehrlich): Consider making FindInfoForAddress private.
-
-// FindInfoForAddress takes a process an in memory address and converts it to a source location.
-func (s *Filter) findInfoForAddress(vaddr uint64) (addressInfo, error) {
-	info := addressInfo{addr: vaddr}
-	// Sometimes zero will be requested as an address. We should not warn in this case.
-	if vaddr == 0 {
-		return info, nil
-	}
-	seg := s.symContext.find(vaddr)
-	if seg == nil {
-		return info, fmt.Errorf("could not find segment that covers 0x%x", vaddr)
-	}
-	info.seg = *seg
-	if mod, ok := s.modules[info.seg.Mod]; ok {
-		info.mod = mod
-	} else {
-		return info, fmt.Errorf("could not find module for 0x%x", vaddr)
-	}
-	modRelAddr := vaddr - seg.Vaddr + seg.ModRelAddr
-	mod, ok := s.modules[seg.Mod]
-	if !ok {
-		return info, fmt.Errorf("could not find module with module ID %d", seg.Mod)
-	}
-	modPath, err := s.repo.GetBuildObject(mod.Build)
-	if err != nil {
-		out := &missingObjError{mod.Name, mod.Build, err}
-		return info, out
-	}
-	result := <-s.symbolizer.FindSrcLoc(modPath, mod.Build, modRelAddr)
-	if result.Err != nil {
-		return info, fmt.Errorf("in module %s with build ID %s: %v", mod.Name, mod.Build, result.Err)
-	}
-	info.locs = result.Locs
-	return info, nil
-}
-
-// NewFilter creates a new filter
-func NewFilter(repo Repository, symbo Symbolizer) *Filter {
-	return &Filter{
-		modules:           make(map[uint64]Module),
-		modNamesByBuildID: make(map[string]string),
-		repo:              repo,
-		symbolizer:        symbo,
-	}
-}
-
-// Reset resets the filter so that it can work for a new process
-func (s *Filter) reset() {
-	s.modules = make(map[uint64]Module)
-	s.symContext.clear()
-}
-
-// AddModule updates the filter state to inform it of a new module
-func (s *Filter) addModule(m Module) error {
-	var err error
-	// TODO(jakehehrlich): Add check to see if two modules with the same
-	// build IDs but different names are added and emit a warning if they
-	// are. Keep in mind that the notion of "same name" has to be carefully
-	// defined so that cases like <VMO#87378=ld.so.l> and <VMO#87393=ld.so.l>
-	// do not trigger the warning.
-
-	// Keep track of modules by build ID.
-	s.modNamesByBuildID[m.Build] = m.Name
-	s.modules[m.Id] = m
-	return err
-}
-
-// AddSegment updates the filter state to inform it of a new memory mapped location.
-func (s *Filter) addSegment(seg Segment) {
-	s.symContext.add(seg)
-}
-
-// Start tells the filter to start consuming input and produce output.
-func (f *Filter) Start(ctx context.Context, input <-chan InputLine) <-chan OutputLine {
-	out := make(chan OutputLine)
-	parseLine := GetLineParser()
-	go func() {
-		for {
-			select {
-			case <-ctx.Done():
-				return
-			case elem, ok := <-input:
-				if !ok {
-					return
-				}
-				var res OutputLine
-				if res.line = parseLine(elem.msg); res.line == nil {
-					res.line = []Node{&Text{text: elem.msg}}
-				}
-				// Update AST with source locations.
-				for _, token := range res.line {
-					token.Accept(&filterVisitor{filter: f, lineno: elem.lineno, ctx: ctx, source: elem.source})
-				}
-				res.LogLine = elem.LogLine
-				out <- res
-			}
-		}
-	}()
-	return out
-}
-
-type filterVisitor struct {
-	filter *Filter
-	lineno uint64
-	ctx    context.Context
-	source LineSource
-}
-
-func (f *filterVisitor) warn(err error) {
-	logger.Warningf(f.ctx, "on line %d: %v", f.lineno, err)
-}
-
-func (f *filterVisitor) debug(err error) {
-	logger.Debugf(f.ctx, "on line %d: %v", f.lineno, err)
-}
-
-func (f *filterVisitor) VisitBt(elem *BacktraceElement) {
-	info, err := f.filter.findInfoForAddress(elem.vaddr)
-	if err != nil {
-		// Don't be noisy about missing objects.
-		if _, ok := err.(*missingObjError); ok {
-			f.debug(err)
-		} else {
-			f.warn(err)
-		}
-	}
-	elem.info = info
-}
-
-func (f *filterVisitor) VisitPc(elem *PCElement) {
-	info, err := f.filter.findInfoForAddress(elem.vaddr)
-	if err != nil {
-		// Don't be noisy about missing objects.
-		if _, ok := err.(*missingObjError); !ok {
-			f.warn(err)
-		}
-	}
-	elem.info = info
-}
-
-func (f *filterVisitor) VisitColor(group *ColorCode) {
-
-}
-
-func (f *filterVisitor) VisitText(_ *Text) {
-	// This must be implemented in order to meet the interface but it has no effect.
-	// This visitor is supposed to do all of the non-parsing parts of constructing the AST.
-	// There is nothing to do for Text however.
-}
-
-func (f *filterVisitor) VisitDump(elem *DumpfileElement) {
-	// Defensive copies must be made here for two reasons:
-	//   1) We don't want the trigger handler to change internal state
-	//   2) The trigger handler is allowed to store/process the context
-	//      at a later date and we might have modified either of these
-	//      in the interim.
-	segs := f.filter.symContext.GetSegments()
-	mods := []Module{}
-	for _, mod := range f.filter.modules {
-		mods = append(mods, mod)
-	}
-	elem.context = &TriggerContext{Source: f.source, Mods: mods, Segs: segs}
-}
-
-func (f *filterVisitor) VisitReset(elem *ResetElement) {
-	// TODO: Check if Reset had an effect and output that a pid reuse occured.
-	f.filter.reset()
-}
-
-func (f *filterVisitor) VisitModule(elem *ModuleElement) {
-	err := f.filter.addModule(elem.mod)
-	if err != nil {
-		f.warn(err)
-	}
-}
-
-func (f *filterVisitor) VisitMapping(elem *MappingElement) {
-	f.filter.addSegment(elem.seg)
-}
diff --git a/debug/symbolize/filter_test.go b/debug/symbolize/filter_test.go
deleted file mode 100644
index cb24770..0000000
--- a/debug/symbolize/filter_test.go
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"context"
-	"encoding/json"
-	"fmt"
-	"reflect"
-	"testing"
-)
-
-type mockModule struct {
-	name      string
-	addr2line map[uint64][]SourceLocation
-}
-
-type mockSymbolizer struct {
-	modules map[string]mockModule
-}
-
-func newMockSymbolizer(modules []mockModule) Symbolizer {
-	var out mockSymbolizer
-	out.modules = make(map[string]mockModule)
-	for _, mod := range modules {
-		out.modules[mod.name] = mod
-	}
-	return &out
-}
-
-func (s *mockSymbolizer) FindSrcLoc(file, build string, modRelAddr uint64) <-chan LLVMSymbolizeResult {
-	out := make(chan LLVMSymbolizeResult, 1)
-	if mod, ok := s.modules[file]; ok {
-		if locs, ok := mod.addr2line[modRelAddr]; ok {
-			out <- LLVMSymbolizeResult{locs, nil}
-		} else {
-			out <- LLVMSymbolizeResult{nil, fmt.Errorf("0x%x was not a valid address in %s", modRelAddr, file)}
-		}
-	} else {
-		out <- LLVMSymbolizeResult{nil, fmt.Errorf("%s could not be found", file)}
-	}
-	return out
-}
-
-type symbolizerRepo struct {
-	builds map[string]string
-}
-
-func TestBasic(t *testing.T) {
-	// mock the input and outputs of llvm-symbolizer
-	symbo := newMockSymbolizer([]mockModule{
-		{"testdata/libc.elf", map[uint64][]SourceLocation{
-			0x429c0: {{NewOptStr("atan2.c"), 49, NewOptStr("atan2")}, {NewOptStr("math.h"), 51, NewOptStr("__DOUBLE_FLOAT")}},
-			0x43680: {{NewOptStr("pow.c"), 23, NewOptStr("pow")}},
-			0x44987: {{NewOptStr("memcpy.c"), 76, NewOptStr("memcpy")}},
-		}},
-		{"testdata/libcrypto.elf", map[uint64][]SourceLocation{
-			0x81000: {{NewOptStr("rsa.c"), 101, NewOptStr("mod_exp")}},
-			0x82000: {{NewOptStr("aes.c"), 17, NewOptStr("gf256_mul")}},
-			0x83000: {{NewOptStr("aes.c"), 560, NewOptStr("gf256_div")}},
-		}},
-	})
-	// Get a line parser
-	parseLine := GetLineParser()
-
-	// make an actual filter using those two mock objects
-	filter := NewFilter(testBinaries, symbo)
-
-	// parse some example lines
-	err := filter.addModule(Module{"libc.elf", "4fcb712aa6387724a9f465a32cd8c14b", 1})
-	if err != nil {
-		t.Fatal(err)
-	}
-	err = filter.addModule(Module{"libcrypto.elf", "12ef5c50b3ed3599c07c02d4509311be", 2})
-	if err != nil {
-		t.Fatal(err)
-	}
-	filter.addSegment(Segment{1, 0x12345000, 849596, "rx", 0x0})
-	filter.addSegment(Segment{2, 0x23456000, 539776, "rx", 0x80000})
-	line := parseLine("\033[1m Error at {{{pc:0x123879c0}}}")
-	// print out a more precise form
-	for _, token := range line {
-		token.Accept(&filterVisitor{filter, 1, context.Background(), DummySource{}})
-	}
-	json, err := GetLineJson(line)
-	if err != nil {
-		t.Fatalf("json did not parse correctly: %v", err)
-	}
-
-	expectedJson := []byte(`[
-    {"type": "color", "color": 1},
-    {"type": "text", "text": " Error at "},
-    {"type": "pc", "vaddr": 305691072, "file": "atan2.c",
-     "line": 49, "function": "atan2"}
-  ]`)
-
-	if !EqualJson(json, expectedJson) {
-		t.Error("expected", expectedJson, "got", json)
-	}
-}
-
-func TestMalformed(t *testing.T) {
-	parseLine := GetLineParser()
-	// Parse a bad line
-	line := parseLine("\033[1m Error at {{{pc:0x123879c0")
-	// Malformed lines should still parse
-	if line == nil {
-		t.Error("expected", "not nil", "got", line)
-	}
-}
-
-func EqualJson(a, b []byte) bool {
-	var j1, j2 interface{}
-	err := json.Unmarshal(a, &j1)
-	if err != nil {
-		panic(err.Error())
-	}
-	err = json.Unmarshal(b, &j2)
-	if err != nil {
-		panic(err.Error())
-	}
-	return reflect.DeepEqual(j1, j2)
-}
-
-func TestBacktrace(t *testing.T) {
-	parseLine := GetLineParser()
-	line := parseLine("Error at {{{bt:0:0x12389988}}}")
-
-	if line == nil {
-		t.Error("got", nil, "expected", "not nil")
-		return
-	}
-
-	// mock the input and outputs of llvm-symbolizer
-	symbo := newMockSymbolizer([]mockModule{
-		{"testdata/libc.elf", map[uint64][]SourceLocation{
-			0x44988: {{NewOptStr("duff.h"), 64, NewOptStr("duffcopy")}, {NewOptStr("memcpy.c"), 76, NewOptStr("memcpy")}},
-		}},
-	})
-
-	// make an actual filter using those two mock objects
-	filter := NewFilter(testBinaries, symbo)
-
-	// add some context
-	err := filter.addModule(Module{"libc.so", "4fcb712aa6387724a9f465a32cd8c14b", 1})
-	if err != nil {
-		t.Fatal(err)
-	}
-	filter.addSegment(Segment{1, 0x12345000, 849596, "rx", 0x0})
-	for _, token := range line {
-		token.Accept(&filterVisitor{filter, 1, context.Background(), DummySource{}})
-	}
-
-	json, err := GetLineJson(line)
-	if err != nil {
-		t.Error("json did not parse correctly", err)
-	}
-
-	expectedJson := []byte(`[
-    {"type": "text", "text": "Error at "},
-    {"type": "bt", "vaddr": 305699208, "num": 0, "locs":[
-      {"line": 64, "function": "duffcopy", "file": "duff.h"},
-      {"line": 76, "function": "memcpy", "file": "memcpy.c"}
-    ]}
-  ]`)
-
-	if !EqualJson(json, expectedJson) {
-		t.Error("unexpected json output", "got", string(json), "expected", string(expectedJson))
-	}
-}
-
-func TestReset(t *testing.T) {
-	parseLine := GetLineParser()
-	line := parseLine("{{{reset}}}")
-
-	json, err := GetLineJson(line)
-	if err != nil {
-		t.Error("json did not parse correctly", err)
-	}
-
-	expectedJson := []byte(`[{"type":"reset"}]`)
-	if !EqualJson(json, expectedJson) {
-		t.Error("unexpected json output", "got", string(json), "expected", string(expectedJson))
-	}
-
-	// mock the input and outputs of llvm-symbolizer
-	symbo := newMockSymbolizer([]mockModule{
-		{"testdata/libc.elf", map[uint64][]SourceLocation{
-			0x44987: {{NewOptStr("memcpy.c"), 76, NewOptStr("memcpy")}},
-		}},
-	})
-
-	// make an actual filter using those two mock objects
-	filter := NewFilter(testBinaries, symbo)
-
-	// add some context
-	mod := Module{"libc.so", "4fcb712aa6387724a9f465a32cd8c14b", 1}
-	err = filter.addModule(mod)
-	if err != nil {
-		t.Fatal(err)
-	}
-	seg := Segment{1, 0x12345000, 849596, "rx", 0x0}
-	filter.addSegment(seg)
-
-	addr := uint64(0x12389987)
-
-	if info, err := filter.findInfoForAddress(addr); err != nil {
-		t.Error("expected", nil, "got", err)
-		if len(info.locs) != 1 {
-			t.Error("expected", 1, "source location but got", len(info.locs))
-		} else {
-			loc := SourceLocation{NewOptStr("memcpy.c"), 76, NewOptStr("memcpy")}
-			if info.locs[0] != loc {
-				t.Error("expected", loc, "got", info.locs[0])
-			}
-		}
-		if info.mod != mod {
-			t.Error("expected", mod, "got", info.mod)
-		}
-		if info.seg != seg {
-			t.Error("expected", seg, "got", info.seg)
-		}
-		if info.addr != addr {
-			t.Error("expected", addr, "got", info.addr)
-		}
-	}
-
-	// now forget the context
-	for _, token := range line {
-		token.Accept(&filterVisitor{filter, 1, context.Background(), DummySource{}})
-	}
-
-	if _, err := filter.findInfoForAddress(addr); err == nil {
-		t.Error("expected non-nil error but got", err)
-	}
-}
diff --git a/debug/symbolize/json.go b/debug/symbolize/json.go
deleted file mode 100644
index cf02455..0000000
--- a/debug/symbolize/json.go
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"encoding/json"
-)
-
-type jsonVisitor struct {
-	stack []json.RawMessage
-}
-
-func GetLineJson(line []Node) ([]byte, error) {
-	var j jsonVisitor
-	for _, token := range line {
-		token.Accept(&j)
-	}
-	return j.getJson()
-}
-
-func (j *jsonVisitor) getJson() ([]byte, error) {
-	return json.MarshalIndent(j.stack, "", "\t")
-}
-
-func (j *jsonVisitor) VisitBt(elem *BacktraceElement) {
-	type loc struct {
-		File     OptStr `json:"file"`
-		Line     int    `json:"line"`
-		Function OptStr `json:"function"`
-	}
-	var locs []loc
-	for _, srcloc := range elem.info.locs {
-		locs = append(locs, loc{
-			File:     srcloc.file,
-			Line:     srcloc.line,
-			Function: srcloc.function,
-		})
-	}
-	msg, _ := json.Marshal(struct {
-		Type  string `json:"type"`
-		Vaddr uint64 `json:"vaddr"`
-		Num   uint64 `json:"num"`
-		Locs  []loc  `json:"locs"`
-	}{
-		Type:  "bt",
-		Vaddr: elem.vaddr,
-		Num:   elem.num,
-		Locs:  locs,
-	})
-	j.stack = append(j.stack, msg)
-}
-
-func (j *jsonVisitor) VisitPc(elem *PCElement) {
-	loc := elem.info.locs[0]
-	msg, _ := json.Marshal(struct {
-		Type     string `json:"type"`
-		Vaddr    uint64 `json:"vaddr"`
-		File     OptStr `json:"file"`
-		Line     int    `json:"line"`
-		Function OptStr `json:"function"`
-	}{
-		Type:     "pc",
-		Vaddr:    elem.vaddr,
-		File:     loc.file,
-		Line:     loc.line,
-		Function: loc.function,
-	})
-	j.stack = append(j.stack, msg)
-}
-
-func (j *jsonVisitor) VisitColor(elem *ColorCode) {
-	out := j.stack
-	msg, _ := json.Marshal(struct {
-		Type  string `json:"type"`
-		Color uint64 `json:"color"`
-	}{
-		Type:  "color",
-		Color: elem.color,
-	})
-	j.stack = append(out, msg)
-}
-
-func (j *jsonVisitor) VisitText(elem *Text) {
-	msg, _ := json.Marshal(struct {
-		Type string `json:"type"`
-		Text string `json:"text"`
-	}{
-		Type: "text",
-		Text: elem.text,
-	})
-	j.stack = append(j.stack, msg)
-}
-
-func (j *jsonVisitor) VisitDump(elem *DumpfileElement) {
-	msg, _ := json.Marshal(struct {
-		Type     string `json:"type"`
-		SinkType string `json:"sinkType"`
-		DumpName string `json:"name"`
-	}{
-		Type:     "dumpfile",
-		SinkType: elem.sinkType,
-		DumpName: elem.name,
-	})
-	j.stack = append(j.stack, msg)
-}
-
-// TODO: update this for generalized modules
-func (j *jsonVisitor) VisitModule(elem *ModuleElement) {
-	msg, _ := json.Marshal(struct {
-		Type  string `json:"type"`
-		Name  string `json:"name"`
-		Build string `json:"build"`
-		Id    uint64 `json:"id"`
-	}{
-		Type:  "module",
-		Name:  elem.mod.Name,
-		Build: elem.mod.Build,
-		Id:    elem.mod.Id,
-	})
-	j.stack = append(j.stack, msg)
-}
-
-func (j *jsonVisitor) VisitReset(elem *ResetElement) {
-	msg, _ := json.Marshal(map[string]string{
-		"type": "reset",
-	})
-	j.stack = append(j.stack, msg)
-}
-
-// TODO: update this for generalized loads
-func (j *jsonVisitor) VisitMapping(elem *MappingElement) {
-	msg, _ := json.Marshal(struct {
-		Type       string `json:"type"`
-		Mod        uint64 `json:"mod"`
-		Size       uint64 `json:"size"`
-		Vaddr      uint64 `json:"vaddr"`
-		Flags      string `json:"flags"`
-		ModRelAddr uint64 `json:"modRelAddr"`
-	}{
-		Type:       "mmap",
-		Mod:        elem.seg.Mod,
-		Size:       elem.seg.Size,
-		Vaddr:      elem.seg.Vaddr,
-		Flags:      elem.seg.Flags,
-		ModRelAddr: elem.seg.ModRelAddr,
-	})
-	j.stack = append(j.stack, msg)
-}
diff --git a/debug/symbolize/mapstore.go b/debug/symbolize/mapstore.go
deleted file mode 100644
index d20f832..0000000
--- a/debug/symbolize/mapstore.go
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"sort"
-)
-
-// TODO (jakehehrlich): This whole file should be private.
-
-type byVAddr []Segment
-
-func (b byVAddr) Len() int {
-	return len(b)
-}
-
-func (b byVAddr) Swap(i, j int) {
-	b[i], b[j] = b[j], b[i]
-}
-
-func (b byVAddr) Less(i, j int) bool {
-	return b[i].Vaddr < b[j].Vaddr
-}
-
-// TODO: replace with skip list
-// I call it a "lazy flat map". It stores mapped regions of memory in a way that
-// allows them to be efficentily looked up by an address within them.
-
-// MappingStore quasi-efficently indexes segments by their start address.
-type mappingStore struct {
-	segments []Segment
-	sorted   int
-}
-
-func merge(a []Segment, b []Segment) []Segment {
-	out := []Segment{}
-	for len(a) != 0 && len(b) != 0 {
-		var min Segment
-		if a[0].Vaddr < b[0].Vaddr {
-			min = a[0]
-			a = a[1:]
-		} else {
-			min = b[0]
-			b = b[1:]
-		}
-		out = append(out, min)
-	}
-	out = append(out, a...)
-	out = append(out, b...)
-	return out
-}
-
-// sortAndFind is meant to be called if an element couldn't be found.
-// sortAndFind sorts the unsorted range of segments, finds the missing element
-// and then merges the two sorted ranges so that sortAndFind won't have to be
-// called again for the same element.
-func (m *mappingStore) sortAndFind(vaddr uint64) *Segment {
-	sort.Sort(byVAddr(m.segments[m.sorted:]))
-	seg := findSegment(m.segments[m.sorted:], vaddr)
-	newMods := merge(m.segments[m.sorted:], m.segments[:m.sorted])
-	m.segments = newMods
-	m.sorted = len(newMods)
-	return seg
-}
-
-// findSegment finds a segment in sorted slice of segments.
-func findSegment(sorted []Segment, vaddr uint64) *Segment {
-	idx := sort.Search(len(sorted), func(i int) bool {
-		seg := sorted[i]
-		return seg.Vaddr+seg.Size >= vaddr
-	})
-	if idx < len(sorted) && sorted[idx].Vaddr <= vaddr {
-		return &sorted[idx]
-	}
-	return nil
-}
-
-// Find first trys to find the desired segment in the sorted segment. If the segment
-// can't be found we consult the unsorted part and update the structure.
-func (m *mappingStore) find(vaddr uint64) *Segment {
-	out := findSegment(m.segments[:m.sorted], vaddr)
-	if out == nil {
-		out = m.sortAndFind(vaddr)
-	}
-	return out
-}
-
-// Add adds a segment to the segment.
-func (m *mappingStore) add(seg Segment) {
-	m.segments = append(m.segments, seg)
-}
-
-// Clear clears the mapping store of all previous information
-func (m *mappingStore) clear() {
-	m.segments = nil
-	m.sorted = 0
-}
-
-// GetSegments returns a new slice containing all the segments
-func (m *mappingStore) GetSegments() []Segment {
-	out := make([]Segment, len(m.segments))
-	copy(out, m.segments)
-	return out
-}
diff --git a/debug/symbolize/mock_elf.go b/debug/symbolize/mock_elf.go
deleted file mode 100644
index 0cb7975..0000000
--- a/debug/symbolize/mock_elf.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"fmt"
-
-	"go.fuchsia.dev/tools/debug/elflib"
-)
-
-type mockSource []elflib.BinaryFileRef
-
-// Common binaries used for tests in this package.
-var testBinaries = mockSource{
-	{Filepath: "testdata/gobug.elf", BuildID: "5bf6a28a259b95b4f20ffbcea0cbb149"},
-	{Filepath: "testdata/libc.elf", BuildID: "4fcb712aa6387724a9f465a32cd8c14b"},
-	{Filepath: "testdata/libcrypto.elf", BuildID: "12ef5c50b3ed3599c07c02d4509311be"},
-}
-
-func (m mockSource) GetBuildObject(buildID string) (string, error) {
-	for _, file := range testBinaries {
-		if file.BuildID == buildID {
-			if err := file.Verify(); err != nil {
-				return "", err
-			}
-			return file.Filepath, nil
-		}
-	}
-	return "", fmt.Errorf("could not find file associated with %s", buildID)
-}
diff --git a/debug/symbolize/parser.go b/debug/symbolize/parser.go
deleted file mode 100644
index ca73ab4..0000000
--- a/debug/symbolize/parser.go
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"bufio"
-	"context"
-	"fmt"
-	"io"
-	"strconv"
-	"strings"
-)
-
-// TODO: Implement a reflection based means of automatically doing these conversions.
-func str2dec(what string) uint64 {
-	what = strings.TrimLeft(what, "0")
-	if len(what) == 0 {
-		return 0
-	}
-	out, err := strconv.ParseUint(what, 10, 64)
-	if err != nil {
-		panic(err.Error())
-	}
-	return out
-}
-
-func str2int(what string) uint64 {
-	// str2int assumes that the |what| matches either decRegex or ptrRegex.
-	// If we come across a hex value, we don't want to trim the leading zero.
-	// If we come across anything else and it still matched one of dec or ptr
-	// regexes then we want to trim leading zeros. This lets us match things like
-	// "01234" which is important for pids and things like that but also prevents
-	// panics like those seen in TC-273.
-	if !strings.HasPrefix(what, "0x") {
-		what = strings.TrimLeft(what, "0")
-		if len(what) == 0 {
-			return 0
-		}
-	}
-	out, err := strconv.ParseUint(what, 0, 64)
-	if err != nil {
-		panic(err.Error())
-	}
-	return out
-}
-
-func str2float(what string) float64 {
-	out, err := strconv.ParseFloat(what, 64)
-	if err != nil {
-		panic(err.Error())
-	}
-	return out
-}
-
-const (
-	decRegexp   = "(?:[[:digit:]]+)"
-	ptrRegexp   = "(?:0|0x[[:xdigit:]]{1,16})"
-	strRegexp   = "(?:[^{}:]*)"
-	spaceRegexp = `(?:\s*)`
-	floatRegexp = `(?:[[:digit:]]+)\.(?:[[:digit:]]+)`
-)
-
-type ParseLineFunc func(msg string) []Node
-
-func GetLineParser() ParseLineFunc {
-	var b regexpTokenizerBuilder
-	out := []Node{}
-	dec := decRegexp
-	ptr := ptrRegexp
-	str := strRegexp
-	num := fmt.Sprintf("(?:%s|%s)", dec, ptr)
-	b.addRule(fmt.Sprintf("{{{bt:(%s):(%s)(?::(%s))?}}}", dec, ptr, str), func(args ...string) {
-		out = append(out, &BacktraceElement{
-			num:   str2dec(args[1]),
-			vaddr: str2int(args[2]),
-			msg:   args[3],
-		})
-	})
-	b.addRule(fmt.Sprintf("{{{pc:(%s)}}}", ptr), func(args ...string) {
-		out = append(out, &PCElement{vaddr: str2int(args[1])})
-	})
-	b.addRule(fmt.Sprintf("\033\\[(%s)m", dec), func(args ...string) {
-		out = append(out, &ColorCode{color: str2dec(args[1])})
-	})
-	b.addRule(fmt.Sprintf("{{{dumpfile:(%s):(%s)}}}", str, str), func(args ...string) {
-		out = append(out, &DumpfileElement{sinkType: args[1], name: args[2]})
-	})
-	b.addRule(fmt.Sprintf(`{{{module:(%s):(%s):elf:(%s)}}}`, num, str, str), func(args ...string) {
-		out = append(out, &ModuleElement{mod: Module{
-			Id:    str2int(args[1]),
-			Name:  args[2],
-			Build: args[3],
-		}})
-	})
-	b.addRule(fmt.Sprintf(`{{{mmap:(%s):(%s):load:(%s):(%s):(%s)}}}`, ptr, num, num, str, ptr), func(args ...string) {
-		out = append(out, &MappingElement{seg: Segment{
-			Vaddr:      str2int(args[1]),
-			Size:       str2int(args[2]),
-			Mod:        str2int(args[3]),
-			Flags:      args[4],
-			ModRelAddr: str2int(args[5]),
-		}})
-	})
-	b.addRule(`{{{reset}}}`, func(args ...string) {
-		out = append(out, &ResetElement{})
-	})
-	tokenizer, err := b.compile(func(text string) {
-		out = append(out, &Text{text: text})
-	})
-	if err != nil {
-		panic(err.Error())
-	}
-	return func(msg string) []Node {
-		out = nil
-		tokenizer.run(msg)
-		return out
-	}
-}
-
-func StartParsing(ctx context.Context, reader io.Reader) <-chan InputLine {
-	out := make(chan InputLine)
-	// This is not used for demuxing. It is a human readable line number.
-	var lineno uint64 = 1
-	var b regexpTokenizerBuilder
-	space := spaceRegexp
-	float := floatRegexp
-	dec := decRegexp
-	tags := `[^\[\]]*`
-	b.addRule(fmt.Sprintf(`\[(%s)\]%s(%s)[.:](%s)>(.*)$`, float, space, dec, dec), func(args ...string) {
-		var hdr logHeader
-		var line InputLine
-		hdr.time = str2float(args[1])
-		hdr.process = str2dec(args[2])
-		hdr.thread = str2dec(args[3])
-		line.header = hdr
-		line.source = Process(hdr.process)
-		line.lineno = lineno
-		line.msg = args[4]
-		out <- line
-	})
-	b.addRule(fmt.Sprintf(`\[(%s)\]\[(%s)\]\[(%s)\]\[(%s)\] ([A-Z]+):?(.*)$`, float, dec, dec, tags), func(args ...string) {
-		var hdr sysLogHeader
-		var line InputLine
-		hdr.time = str2float(args[1])
-		hdr.process = str2dec(args[2])
-		hdr.thread = str2dec(args[3])
-		hdr.tags = args[4]
-		hdr.typ = args[5]
-		line.header = hdr
-		line.source = Process(hdr.process)
-		line.lineno = lineno
-		line.msg = args[6]
-		out <- line
-	})
-	tokenizer, err := b.compile(func(text string) {
-		var line InputLine
-		line.source = DummySource{}
-		line.msg = text
-		line.lineno = lineno
-		out <- line
-	})
-	if err != nil {
-		panic(err.Error())
-	}
-	go func() {
-		defer close(out)
-		scanner := bufio.NewScanner(reader)
-		for ; scanner.Scan(); lineno++ {
-			select {
-			case <-ctx.Done():
-				return
-			default:
-				tokenizer.run(scanner.Text())
-			}
-		}
-	}()
-	return out
-}
diff --git a/debug/symbolize/pipeline.go b/debug/symbolize/pipeline.go
deleted file mode 100644
index 8b6bd9f..0000000
--- a/debug/symbolize/pipeline.go
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"context"
-)
-
-// PostProcessor is the type of modifications to a stream of OutputLines
-type PostProcessor interface {
-	Process(OutputLine, chan<- OutputLine)
-}
-
-// PreProcessor is the type of modifications to a stream of InputLines
-type PreProcessor interface {
-	Process(InputLine, chan<- InputLine)
-}
-
-// Processor is the type of transformations from OutputLines to InputLines
-type Processor interface {
-	Process(InputLine, chan<- OutputLine)
-}
-
-type postProcessorNode struct {
-	postProc PostProcessor
-}
-
-func (p postProcessorNode) run(ctx context.Context, input <-chan OutputLine) <-chan OutputLine {
-	out := make(chan OutputLine)
-	go func() {
-		defer func() {
-			close(out)
-		}()
-		for {
-			select {
-			case <-ctx.Done():
-				return
-			case elem, ok := <-input:
-				if !ok {
-					return
-				}
-				p.postProc.Process(elem, out)
-			}
-		}
-	}()
-	return out
-}
-
-type preProcessorNode struct {
-	preProc PreProcessor
-}
-
-func (p preProcessorNode) run(ctx context.Context, input <-chan InputLine) <-chan InputLine {
-	out := make(chan InputLine)
-	go func() {
-		defer func() {
-			close(out)
-		}()
-		for {
-			select {
-			case <-ctx.Done():
-				return
-			case elem, ok := <-input:
-				if !ok {
-					return
-				}
-				p.preProc.Process(elem, out)
-			}
-		}
-	}()
-	return out
-}
-
-type processorNode struct {
-	proc Processor
-}
-
-func (p processorNode) run(ctx context.Context, input <-chan InputLine) <-chan OutputLine {
-	out := make(chan OutputLine)
-	go func() {
-		defer func() {
-			close(out)
-		}()
-		for {
-			select {
-			case <-ctx.Done():
-				return
-			case elem, ok := <-input:
-				if !ok {
-					return
-				}
-				p.proc.Process(elem, out)
-			}
-		}
-	}()
-	return out
-}
-
-// Consume eats and forgets all input from a channel. This is useful for keeping a goroutine alive
-// until a pipeline has finished processing to completion.
-func Consume(input <-chan OutputLine) {
-	for range input {
-	}
-}
-
-// ComposePreProcessors takes several PreProcessors and runs them in sequence
-func ComposePreProcessors(ctx context.Context, input <-chan InputLine, pres ...PreProcessor) <-chan InputLine {
-	for _, pre := range pres {
-		input = preProcessorNode{pre}.run(ctx, input)
-	}
-	return input
-}
-
-// ComposePostProcessors takes several PostProcessors and runs them in sequence
-func ComposePostProcessors(ctx context.Context, input <-chan OutputLine, posts ...PostProcessor) <-chan OutputLine {
-	for _, post := range posts {
-		input = postProcessorNode{post}.run(ctx, input)
-	}
-	return input
-}
-
-// Compose takes a single Processor and causes it to start transforming Input into Output
-func ComposeProcessors(ctx context.Context, input <-chan InputLine, proc Processor) <-chan OutputLine {
-	return processorNode{proc}.run(ctx, input)
-}
diff --git a/debug/symbolize/presenter.go b/debug/symbolize/presenter.go
deleted file mode 100644
index 3d23a93..0000000
--- a/debug/symbolize/presenter.go
+++ /dev/null
@@ -1,303 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"fmt"
-	"io"
-	"sort"
-	"unicode"
-)
-
-// BacktracePresenter intercepts backtrace elements on their own line and
-// presents them in text. Inlines are output as separate lines.
-// A PostProcessor is taken as an input to synchronously compose another
-// PostProcessor
-type BacktracePresenter struct {
-	out  io.Writer
-	next PostProcessor
-}
-
-// NewBacktracePresenter constructs a BacktracePresenter.
-func NewBacktracePresenter(out io.Writer, next PostProcessor) *BacktracePresenter {
-	return &BacktracePresenter{
-		out:  out,
-		next: next,
-	}
-}
-
-func printBacktrace(out io.Writer, hdr LineHeader, frame uint64, msg string, info addressInfo) {
-	modRelAddr := info.addr - info.seg.Vaddr + info.seg.ModRelAddr
-	var hdrString string
-	if hdr != nil {
-		hdrString = hdr.Present()
-	}
-	if len(info.locs) == 0 {
-		fmt.Fprintf(out, "%s    #%-4d %#016x in <%s>+%#x %s\n", hdrString, frame, info.addr, info.mod.Name, modRelAddr, msg)
-		return
-	}
-	for i, loc := range info.locs {
-		i = len(info.locs) - i - 1
-		fmt.Fprintf(out, "%s    ", hdrString)
-		var frameStr string
-		if i == 0 {
-			frameStr = fmt.Sprintf("#%d", frame)
-		} else {
-			frameStr = fmt.Sprintf("#%d.%d", frame, i)
-		}
-		fmt.Fprintf(out, "%-5s", frameStr)
-		fmt.Fprintf(out, " %#016x", info.addr)
-		if !loc.function.IsEmpty() {
-			fmt.Fprintf(out, " in %v", loc.function)
-		}
-		if !loc.file.IsEmpty() {
-			fmt.Fprintf(out, " %s:%d", loc.file, loc.line)
-		}
-		fmt.Fprintf(out, " <%s>+%#x", info.mod.Name, modRelAddr)
-		if msg != "" {
-			fmt.Fprintf(out, " %s", msg)
-		}
-		fmt.Fprintf(out, "\n")
-	}
-}
-
-func isSpace(s string) bool {
-	for _, r := range s {
-		if !unicode.IsSpace(r) {
-			return false
-		}
-	}
-	return true
-}
-
-func (b *BacktracePresenter) Process(line OutputLine, out chan<- OutputLine) {
-	if len(line.line) == 1 {
-		if bt, ok := line.line[0].(*BacktraceElement); ok {
-			printBacktrace(b.out, line.header, bt.num, bt.msg, bt.info)
-			// Don't process a backtrace we've already output.
-			return
-		}
-	}
-	if len(line.line) == 2 {
-		// Note that we're going to discard the text in front.
-		if txt, ok := line.line[0].(*Text); ok && isSpace(txt.text) {
-			if bt, ok := line.line[1].(*BacktraceElement); ok {
-				printBacktrace(b.out, line.header, bt.num, bt.msg, bt.info)
-				// Don't process a backtrace we've already output.
-				return
-			}
-		}
-	}
-	b.next.Process(line, out)
-}
-
-func printLine(line LogLine, fmtStr string, args ...interface{}) OutputLine {
-	node := Text{text: fmt.Sprintf(fmtStr, args...)}
-	return OutputLine{LogLine: line, line: []Node{&node}}
-}
-
-// Because apparently this is the world we live in, I have to write my own
-// min/max function.
-func min(x, y uint64) uint64 {
-	if x < y {
-		return x
-	}
-	return y
-}
-
-type dsoInfo struct {
-	id    uint64
-	name  string
-	build string
-	addr  *uint64
-}
-
-type ContextPresenter map[LineSource]map[uint64]dsoInfo
-
-func (c ContextPresenter) Process(line OutputLine, out chan<- OutputLine) {
-	if _, ok := c[line.source]; !ok {
-		c[line.source] = make(map[uint64]dsoInfo)
-	}
-	info := c[line.source]
-	blank := true
-	skip := false
-	for _, token := range line.line {
-		switch t := token.(type) {
-		case *ResetElement:
-			skip = true
-			delete(c, line.source)
-			break
-		case *ModuleElement:
-			skip = true
-			if _, ok := info[t.mod.Id]; !ok {
-				info[t.mod.Id] = dsoInfo{id: t.mod.Id, name: t.mod.Name, build: t.mod.Build}
-			}
-			break
-		case *MappingElement:
-			skip = true
-			dInfo, ok := info[t.seg.Mod]
-			if !ok {
-				// We might be missing the module because a non-context element was interleaved.
-				// It could also be missing but that isn't this function's job to point out.
-				out <- printLine(line.LogLine, " [[[ELF seg #%#x %#x]]]", t.seg.Mod, t.seg.Vaddr-t.seg.ModRelAddr)
-				break
-			}
-			if dInfo.addr == nil {
-				dInfo.addr = &t.seg.Vaddr
-			} else {
-				newAddr := min(*dInfo.addr, t.seg.Vaddr-t.seg.ModRelAddr)
-				dInfo.addr = &newAddr
-			}
-			info[t.seg.Mod] = dInfo
-			break
-		default:
-			// Save this token for output later
-			if t, ok := token.(*Text); !ok || !isSpace(t.text) {
-				blank = false
-			}
-		}
-	}
-	if !skip || !blank {
-		// Output all contextual information we've thus far consumed.
-		sortedInfo := []dsoInfo{}
-		for _, dInfo := range info {
-			sortedInfo = append(sortedInfo, dInfo)
-		}
-		sort.Slice(sortedInfo, func(i, j int) bool {
-			return sortedInfo[i].id < sortedInfo[j].id
-		})
-		// TODO(TC-615): We'd really like something more like the following:
-		// [[[ELF module #0 "libc.so" BuildID=1234abcdef 0x12345000(r)-0x12356000(rx)-0x12378000(rw)-0x12389000]]]
-		// but this requires a fair bit more work to track.
-		for _, dInfo := range sortedInfo {
-			if dInfo.addr != nil {
-				out <- printLine(line.LogLine, " [[[ELF module #%#x \"%s\" BuildID=%s %#x]]]", dInfo.id, dInfo.name, dInfo.build, *dInfo.addr)
-			} else {
-				out <- printLine(line.LogLine, " [[[ELF module #%#x \"%s\" BuildID=%s]]]", dInfo.id, dInfo.name, dInfo.build)
-			}
-		}
-		// Now so that we don't print this information out again, forget it all.
-		delete(c, line.source)
-		out <- line
-	}
-}
-
-// OptimizeColor attempts to transform output elements to use as few color
-// transisitions as is possible
-type OptimizeColor struct {
-}
-
-func (o *OptimizeColor) Process(line OutputLine, out chan<- OutputLine) {
-	// Maintain a current simulated color state
-	curColor := uint64(0)
-	curBold := false
-	// Keep track of the color state at the end of 'out'
-	color := uint64(0)
-	bold := false
-	// The new list of tokens we will output
-	newLine := []Node{}
-	// Go though each token
-	for _, token := range line.line {
-		if colorCode, ok := token.(*ColorCode); ok {
-			// If we encounter a color update the simulated color state
-			if colorCode.color == 1 {
-				curBold = true
-			} else if colorCode.color == 0 {
-				curColor = 0
-				curBold = false
-			} else {
-				curColor = colorCode.color
-			}
-		} else {
-			// If we encounter a non-color token make sure we output
-			// colors to handle the transition from the last color to the
-			// new color.
-			if curColor == 0 && color != 0 {
-				color = 0
-				bold = false
-				newLine = append(newLine, &ColorCode{color: 0})
-			} else if curColor != color {
-				color = curColor
-				newLine = append(newLine, &ColorCode{color: curColor})
-			}
-			// Make sure to bold the output even if a color 0 code was just output
-			if curBold && !bold {
-				bold = true
-				newLine = append(newLine, &ColorCode{color: 1})
-			}
-			// Append all non-color nodes
-			newLine = append(newLine, token)
-		}
-	}
-	// If the color state isn't already clear, clear it
-	if color != 0 || bold != false {
-		newLine = append(newLine, &ColorCode{color: 0})
-	}
-	line.line = newLine
-	out <- line
-}
-
-// BasicPresenter is a presenter to output very basic uncolored output
-type BasicPresenter struct {
-	enableColor bool
-	output      io.Writer
-}
-
-func NewBasicPresenter(output io.Writer, enableColor bool) *BasicPresenter {
-	return &BasicPresenter{output: output, enableColor: enableColor}
-}
-
-func (b *BasicPresenter) printSrcLoc(loc SourceLocation, info addressInfo) {
-	modRelAddr := info.addr - info.seg.Vaddr + info.seg.ModRelAddr
-	if !loc.function.IsEmpty() {
-		fmt.Fprintf(b.output, "%s at ", loc.function)
-	}
-	if !loc.file.IsEmpty() {
-		fmt.Fprintf(b.output, "%s:%d", loc.file, loc.line)
-	} else {
-		fmt.Fprintf(b.output, "<%s>+0x%x", info.mod.Name, modRelAddr)
-	}
-}
-
-func (b *BasicPresenter) Process(res OutputLine, out chan<- OutputLine) {
-	if res.header != nil {
-		fmt.Fprintf(b.output, "%s", res.header.Present())
-	}
-	for _, token := range res.line {
-		switch node := token.(type) {
-		case *BacktraceElement:
-			if len(node.info.locs) == 0 {
-				b.printSrcLoc(SourceLocation{}, node.info)
-			}
-			for i, loc := range node.info.locs {
-				b.printSrcLoc(loc, node.info)
-				if i != len(node.info.locs)-1 {
-					fmt.Fprintf(b.output, " inlined from ")
-				}
-			}
-		case *PCElement:
-			if len(node.info.locs) > 0 {
-				b.printSrcLoc(node.info.locs[0], node.info)
-			} else {
-				b.printSrcLoc(SourceLocation{}, node.info)
-			}
-		case *ColorCode:
-			if b.enableColor {
-				fmt.Fprintf(b.output, "\033[%dm", node.color)
-			}
-		case *Text:
-			fmt.Fprintf(b.output, "%s", node.text)
-		case *DumpfileElement:
-			fmt.Fprintf(b.output, "{{{dumpfile:%s:%s}}}", node.sinkType, node.name)
-		case *ResetElement:
-			fmt.Fprintf(b.output, "{{{reset}}}")
-		case *ModuleElement:
-			fmt.Fprintf(b.output, "{{{module:%s:%s:%d}}}", node.mod.Build, node.mod.Name, node.mod.Id)
-		case *MappingElement:
-			fmt.Fprintf(b.output, "{{{mmap:0x%x:0x%x:load:%d:%s:0x%x}}}", node.seg.Vaddr, node.seg.Size, node.seg.Mod, node.seg.Flags, node.seg.ModRelAddr)
-		}
-	}
-	fmt.Fprintf(b.output, "\n")
-}
diff --git a/debug/symbolize/regextokenizer.go b/debug/symbolize/regextokenizer.go
deleted file mode 100644
index f94a871..0000000
--- a/debug/symbolize/regextokenizer.go
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"fmt"
-	"regexp"
-	"strings"
-)
-
-// TODO: Make this whole file private
-
-type actionFunc func(...string)
-
-type regexInfo struct {
-	regex      *regexp.Regexp // the regex for this rule
-	groupCount int            // the number of groups in this regex
-	index      int            // the group index of this regex in the master regex
-	action     actionFunc     // the action to execute if this rule succeeds
-}
-
-// RegexpTokenizer allows for the splitting of input into tokens based on a list
-// of regexs a la (f)lex.
-type regexpTokenizer struct {
-	regexs        []regexInfo
-	master        *regexp.Regexp
-	defaultAction func(string)
-}
-
-type rule struct {
-	regexStr string
-	action   actionFunc
-}
-
-// RegexpTokenizerBuilder is the means by which a RegexpTokenizer can be constructed.
-type regexpTokenizerBuilder struct {
-	rules []rule
-}
-
-// TODO: Add a way to infer the automatic conversions that need to happen from
-// a user supplied function's type via reflection.
-// Rule adds a new regex to the builder
-func (r *regexpTokenizerBuilder) addRule(regex string, action actionFunc) {
-	r.rules = append(r.rules, rule{regex, action})
-}
-
-// End compiles the list of regular expressions and actions into a RegexpTokenizer
-func (r *regexpTokenizerBuilder) compile(defaultAction func(string)) (*regexpTokenizer, error) {
-	out := regexpTokenizer{defaultAction: defaultAction}
-	// Start groupIndex at 1 to account for the master regexp
-	groupIndex := 1
-	regexStrs := []string{}
-	for _, rule := range r.rules {
-		regex, err := regexp.Compile(rule.regexStr)
-		if err != nil {
-			return nil, err
-		}
-		// Add all needed information to an regexInfo for this rule.
-		toAdd := regexInfo{regex, len(regex.SubexpNames()), groupIndex, rule.action}
-		// Advance the groupIndex by the subgroups of this regex plus the additional group we add for the whole thing.
-		groupIndex += toAdd.groupCount
-		regexStrs = append(regexStrs, fmt.Sprintf("(%s)", rule.regexStr))
-		out.regexs = append(out.regexs, toAdd)
-	}
-	// Create the master regex
-	masterRegexp, err := regexp.Compile(strings.Join(regexStrs, "|"))
-	if err != nil {
-		return nil, err
-	}
-	out.master = masterRegexp
-	return &out, nil
-}
-
-// Run tokenizes 'input'
-func (r *regexpTokenizer) run(input string) {
-	for len(input) > 0 {
-		locs := r.master.FindStringSubmatchIndex(input)
-		if locs == nil {
-			// There are no more matches so parse the rest of the input and return
-			r.defaultAction(input)
-			return
-		}
-		// If there is anything before the match we need to pass it to the default case.
-		if locs[0] != 0 {
-			r.defaultAction(input[:locs[0]])
-		}
-		// If we have a match however find which regex produced the match
-		for _, regex := range r.regexs {
-			if locs[2*regex.index] >= 0 {
-				groups := []string{}
-				for i := 0; i < regex.groupCount; i++ {
-					groupBeginIdx := locs[2*(regex.index+i)]
-					groupEndIdx := locs[2*(regex.index+i)+1]
-					// When a group is optional it may not be included. Check for that.
-					if groupBeginIdx == -1 || groupEndIdx == -1 {
-						groups = append(groups, "")
-					} else {
-						groups = append(groups, input[groupBeginIdx:groupEndIdx])
-					}
-				}
-				// Pass the regex's groups to it
-				regex.action(groups...)
-				break
-			}
-		}
-		// Now we need to advance the input to not cover anything in the match.
-		input = input[locs[1]:]
-	}
-}
diff --git a/debug/symbolize/regextokenizer_test.go b/debug/symbolize/regextokenizer_test.go
deleted file mode 100644
index 0c6dca2..0000000
--- a/debug/symbolize/regextokenizer_test.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"bytes"
-	"fmt"
-	"testing"
-)
-
-func TestRegexTokenize(t *testing.T) {
-	var builder regexpTokenizerBuilder
-	var out bytes.Buffer
-	builder.addRule("{a+}", func(args ...string) {
-		fmt.Fprintf(&out, "a+ case: %v\n", args)
-	})
-	builder.addRule("{b+}", func(args ...string) {
-		fmt.Fprintf(&out, "b+ case: %v\n", args)
-	})
-	builder.addRule("{(x)(y)(z)}", func(args ...string) {
-		fmt.Fprintf(&out, "xyz case: %v\n", args)
-	})
-	tokenizer, err := builder.compile(func(str string) {
-		fmt.Fprintf(&out, "default case: %s\n", str)
-	})
-	if err != nil {
-		t.Fatal(err)
-	}
-	tokenizer.run("blarg{a}foo{bbbbb}{xyz}{aa}{aa}baz[test]rest")
-	expected := `default case: blarg
-a+ case: [{a}]
-default case: foo
-b+ case: [{bbbbb}]
-xyz case: [{xyz} x y z]
-a+ case: [{aa}]
-a+ case: [{aa}]
-default case: baz[test]rest
-`
-	actual := string(out.Bytes())
-	if expected != string(out.Bytes()) {
-		t.Error("expected\n", expected, "\ngot\n", actual)
-	}
-}
diff --git a/debug/symbolize/repo.go b/debug/symbolize/repo.go
deleted file mode 100644
index 1f5fcc4..0000000
--- a/debug/symbolize/repo.go
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"fmt"
-	"os"
-	"path/filepath"
-	"sync"
-
-	"go.fuchsia.dev/tools/debug/elflib"
-)
-
-// idsSource is a BinaryFileSource parsed from ids.txt
-type IDsTxtRepo struct {
-	lock      sync.RWMutex
-	cached    map[string]elflib.BinaryFileRef
-	pathToIDs string
-	rel       bool
-}
-
-func NewIDsTxtRepo(pathToIDs string, rel bool) *IDsTxtRepo {
-	return &IDsTxtRepo{
-		cached:    make(map[string]elflib.BinaryFileRef),
-		pathToIDs: pathToIDs,
-		rel:       rel,
-	}
-}
-
-func (i *IDsTxtRepo) getBinaries() ([]elflib.BinaryFileRef, error) {
-	file, err := os.Open(i.pathToIDs)
-	if err != nil {
-		return nil, err
-	}
-	defer file.Close()
-	out, err := elflib.ReadIDsFile(file)
-	if err != nil {
-		return nil, err
-	}
-	if i.rel {
-		base := filepath.Dir(i.pathToIDs)
-		for idx, ref := range out {
-			if !filepath.IsAbs(ref.Filepath) {
-				out[idx].Filepath = filepath.Join(base, ref.Filepath)
-			}
-		}
-	}
-	return out, nil
-}
-
-func (i *IDsTxtRepo) readFromCache(buildID string) (elflib.BinaryFileRef, bool) {
-	i.lock.RLock()
-	defer i.lock.RUnlock()
-	info, ok := i.cached[buildID]
-	return info, ok
-}
-
-func (i *IDsTxtRepo) updateCache() error {
-	i.lock.Lock()
-	defer i.lock.Unlock()
-	bins, err := i.getBinaries()
-	if err != nil {
-		return err
-	}
-	newCache := make(map[string]elflib.BinaryFileRef)
-	// TODO(jakehehrlich): Do this in parallel.
-	for _, bin := range bins {
-		newCache[bin.BuildID] = bin
-	}
-	i.cached = newCache
-	return nil
-}
-
-func (i *IDsTxtRepo) GetBuildObject(buildID string) (string, error) {
-	if file, ok := i.readFromCache(buildID); ok && file.Verify() != nil {
-		return file.Filepath, nil
-	}
-	if err := i.updateCache(); err != nil {
-		return "", err
-	}
-	if file, ok := i.readFromCache(buildID); ok {
-		if err := file.Verify(); err != nil {
-			return "", err
-		}
-		return file.Filepath, nil
-	}
-	return "", fmt.Errorf("could not find file for %s", buildID)
-}
-
-type CompositeRepo struct {
-	repos []Repository
-}
-
-// AddRepo adds a repo to be checked that has lower priority than any other
-// previouslly added repo. This operation is not thread safe.
-func (c *CompositeRepo) AddRepo(repo Repository) {
-	c.repos = append(c.repos, repo)
-}
-
-func (c *CompositeRepo) GetBuildObject(buildID string) (string, error) {
-	for _, repo := range c.repos {
-		file, err := repo.GetBuildObject(buildID)
-		if err != nil {
-			continue
-		}
-		return file, nil
-	}
-	return "", fmt.Errorf("could not find file for %s", buildID)
-}
-
-type NewBuildIDRepo string
-
-func (b NewBuildIDRepo) GetBuildObject(buildID string) (string, error) {
-	if len(buildID) < 4 {
-		return "", fmt.Errorf("build ID must be the hex representation of at least 2 bytes")
-	}
-	bin := elflib.BinaryFileRef{
-		Filepath: filepath.Join(string(b), buildID[:2], buildID[2:]) + ".debug",
-		BuildID:  buildID,
-	}
-	if err := bin.Verify(); err != nil {
-		return "", err
-	}
-	return bin.Filepath, nil
-}
diff --git a/debug/symbolize/repo_test.go b/debug/symbolize/repo_test.go
deleted file mode 100644
index 5a45f2a..0000000
--- a/debug/symbolize/repo_test.go
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"bytes"
-	"encoding/hex"
-	"os"
-	"testing"
-
-	"go.fuchsia.dev/tools/debug/elflib"
-)
-
-func hexEqual(a []byte, b string) bool {
-	bBytes, _ := hex.DecodeString(b)
-	return bytes.Equal(a, bBytes)
-}
-
-type gobugMockSource struct{}
-
-func (g *gobugMockSource) GetBinaries() ([]elflib.BinaryFileRef, error) {
-	out := []elflib.BinaryFileRef{
-		{BuildID: "5bf6a28a259b95b4f20ffbcea0cbb149", Filepath: "testdata/gobug.elf"},
-		{BuildID: "4FCB712AA6387724A9F465A3DEADBEEF", Filepath: "testdata/gobug.elf"},
-		{BuildID: "DEADBEEFA6387724A9F465A32CD8C14B", Filepath: "testdata/gobug.elf"},
-	}
-	for _, bin := range out {
-		if err := bin.Verify(); err != nil {
-			return nil, err
-		}
-	}
-	return out, nil
-}
-
-// The current go toolchain used in Fuchsia has a bug that causes multiple build ids
-// to wind up in go binaries. This tests to make sure we can handle that case and
-// still ensure that our mentioned build id matches any of the build ids in the file.
-func TestGoBug(t *testing.T) {
-	source := &gobugMockSource{}
-	data, err := os.Open("testdata/gobug.elf")
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer data.Close()
-	buildids, err := elflib.GetBuildIDs("testdata/gobug.elf", data)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if len(buildids) != 3 {
-		t.Error("expected", 3, "build IDs but got", len(buildids))
-		return
-	}
-	// Test that we get exactly the build IDs we expect
-	bins, err := source.GetBinaries()
-	if err != nil {
-		t.Fatal(err)
-	}
-	for i, bin := range bins {
-		if !hexEqual(buildids[i], bin.BuildID) {
-			t.Error("expected", bin.BuildID, "got", hex.EncodeToString(buildids[i]))
-		}
-	}
-}
diff --git a/debug/symbolize/symbolizer.go b/debug/symbolize/symbolizer.go
deleted file mode 100644
index 3bcff11..0000000
--- a/debug/symbolize/symbolizer.go
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-import (
-	"bufio"
-	"context"
-	"fmt"
-	"io"
-	"os/exec"
-	"strconv"
-	"strings"
-
-	"go.fuchsia.dev/tools/debug/elflib"
-	"go.fuchsia.dev/tools/lib/cache"
-)
-
-// Symbolizer is an interface to an object that maps addresses in a bianry to source locations
-type Symbolizer interface {
-	FindSrcLoc(file, build string, modRelAddr uint64) <-chan LLVMSymbolizeResult
-}
-
-type llvmSymbolizeArgsKey struct {
-	build      string
-	modRelAddr uint64
-}
-
-type llvmSymboArgs struct {
-	file       string
-	build      string
-	modRelAddr uint64
-	output     chan LLVMSymbolizeResult
-}
-
-const maxCacheSize = 128
-
-type LLVMSymbolizeResult struct {
-	Locs []SourceLocation
-	Err  error
-}
-
-type LLVMSymbolizer struct {
-	path       string
-	stdin      io.WriteCloser
-	stdout     io.ReadCloser
-	symbolizer *exec.Cmd
-	input      chan llvmSymboArgs
-	cache      cache.Cache
-}
-
-func NewLLVMSymbolizer(llvmSymboPath string) *LLVMSymbolizer {
-	var out LLVMSymbolizer
-	out.path = llvmSymboPath
-	out.symbolizer = exec.Command(llvmSymboPath)
-	out.input = make(chan llvmSymboArgs)
-	out.cache = &cache.LRUCache{Size: maxCacheSize}
-	return &out
-}
-
-func unknownStr(str string) OptStr {
-	if str == "??" || str == "" {
-		return EmptyOptStr()
-	}
-	return NewOptStr(str)
-}
-
-func (s *LLVMSymbolizer) handle(ctx context.Context) {
-	for {
-		select {
-		case <-ctx.Done():
-			return
-		case args, ok := <-s.input:
-			if !ok {
-				return
-			}
-			// See if we've seen this before and send off the result
-			key := llvmSymbolizeArgsKey{args.build, args.modRelAddr}
-			if res, ok := s.cache.Get(key); ok {
-				args.output <- res.(LLVMSymbolizeResult)
-				continue
-			}
-			if len(strings.TrimSpace(args.file)) == 0 {
-				args.output <- LLVMSymbolizeResult{
-					nil, fmt.Errorf("Attempt to request code location of unnamed file with build ID %x", args.build)}
-				continue
-			}
-			// Before sending a binary off to llvm-symbolizer, verify the binary
-			if err := elflib.NewBinaryFileRef(args.file, args.build).Verify(); err != nil {
-				args.output <- LLVMSymbolizeResult{nil, err}
-				continue
-			}
-			// From //zircon/docs/symbolizer_markup.md:
-			// In frames after frame zero, this code location identifies a call site.
-			// Some emitters may subtract one byte or one instruction length from the
-			// actual return address for the call site, with the intent that the address
-			// logged can be translated directly to a source location for the call site
-			// and not for the apparent return site thereafter (which can be confusing).
-			// It‘s recommended that emitters not do this, so that each frame’s code
-			// location is the exact return address given to its callee and e.g. could be
-			// highlighted in instruction-level disassembly. The symbolizing filter can do
-			// the adjustment to the address it translates into a source location. Assuming
-			// that a call instruction is longer than one byte on all supported machines,
-			// applying the "subtract one byte" adjustment a second time still results in an
-			// address somewhere in the call instruction, so a little sloppiness here does
-			// no harm.
-			fmt.Fprintf(s.stdin, "%s 0x%x\n", args.file, args.modRelAddr-1)
-			out := []SourceLocation{}
-			scanner := bufio.NewScanner(s.stdout)
-			for scanner.Scan() {
-				function := scanner.Text()
-				if len(function) == 0 {
-					break
-				}
-				good := scanner.Scan()
-				if !good {
-					panic(fmt.Sprintf("%s output ended too soon", s.path))
-				}
-				location := scanner.Text()
-				parts := strings.SplitN(location, ":", 3)
-				if len(parts) < 2 {
-					panic(fmt.Sprintf("%s output unrecgonized format", s.path))
-				}
-				line, _ := strconv.Atoi(parts[1])
-				out = append(out, SourceLocation{unknownStr(parts[0]), line, unknownStr(function)})
-			}
-			outputRes := LLVMSymbolizeResult{out, nil}
-			s.cache.Add(key, outputRes)
-			args.output <- outputRes
-		}
-	}
-}
-
-func (s *LLVMSymbolizer) Start(ctx context.Context) error {
-	var err error
-	if s.stdin, err = s.symbolizer.StdinPipe(); err != nil {
-		return err
-	}
-	if s.stdout, err = s.symbolizer.StdoutPipe(); err != nil {
-		return err
-	}
-	if err = s.symbolizer.Start(); err != nil {
-		return err
-	}
-	go s.handle(ctx)
-	return nil
-}
-
-func (s *LLVMSymbolizer) FindSrcLoc(file, build string, modRelAddr uint64) <-chan LLVMSymbolizeResult {
-	// Buffer the return chanel so we don't block handle().
-	out := make(chan LLVMSymbolizeResult, 1)
-	args := llvmSymboArgs{file: file, build: build, modRelAddr: modRelAddr, output: out}
-	s.input <- args
-	return out
-}
diff --git a/debug/symbolize/testdata/gobug.elf b/debug/symbolize/testdata/gobug.elf
deleted file mode 100644
index 15522ec..0000000
--- a/debug/symbolize/testdata/gobug.elf
+++ /dev/null
Binary files differ
diff --git a/debug/symbolize/testdata/gobug.yaml b/debug/symbolize/testdata/gobug.yaml
deleted file mode 100644
index b751320..0000000
--- a/debug/symbolize/testdata/gobug.yaml
+++ /dev/null
@@ -1,34 +0,0 @@
---- !ELF
-FileHeader:
-  Class:           ELFCLASS64
-  Data:            ELFDATA2LSB
-  Type:            ET_EXEC
-  Machine:         EM_X86_64
-Sections:
-  - Name:            .text
-    Type:            SHT_PROGBITS
-    Flags:           [ SHF_ALLOC ]
-  - Name:            .dynsym
-    Type:            SHT_DYNSYM
-  - Name:            .dynstr
-    Type:            SHT_STRTAB
-  - Name:            .note.gnu.build-id
-    Type:            SHT_NOTE
-    Flags:           [ SHF_ALLOC ]
-    AddressAlign:    0x0000000000000004
-    Content:         040000001000000003000000474E55005bf6a28a259b95b4f20ffbcea0cbb149040000001000000003000000474E55004FCB712AA6387724A9F465A3DEADBEEF040000001000000003000000474E5500DEADBEEFA6387724A9F465A32CD8C14B
-ProgramHeaders:
-  - Type: PT_LOAD
-    Flags: [ PF_X, PF_R ]
-    Sections:
-      - Section: .text
-  - Type: PT_LOAD
-    Flags: [ PF_R ]
-    Sections:
-      - Section: .dynsym
-      - Section: .dynstr
-      - Section: .note.gnu.build-id
-  - Type: PT_NOTE
-    Flags: [ PF_R ]
-    Sections:
-      - Section: .note.gnu.build-id
diff --git a/debug/symbolize/testdata/libc.elf b/debug/symbolize/testdata/libc.elf
deleted file mode 100644
index 8322c66..0000000
--- a/debug/symbolize/testdata/libc.elf
+++ /dev/null
Binary files differ
diff --git a/debug/symbolize/testdata/libc.yaml b/debug/symbolize/testdata/libc.yaml
deleted file mode 100644
index e33cfd0..0000000
--- a/debug/symbolize/testdata/libc.yaml
+++ /dev/null
@@ -1,45 +0,0 @@
---- !ELF
-FileHeader:
-  Class:           ELFCLASS64
-  Data:            ELFDATA2LSB
-  Type:            ET_EXEC
-  Machine:         EM_X86_64
-Sections:
-  - Name:            .text
-    Type:            SHT_PROGBITS
-    Flags:           [ SHF_ALLOC ]
-  - Name:            .dynsym
-    Type:            SHT_DYNSYM
-  - Name:            .dynstr
-    Type:            SHT_STRTAB
-  - Name:            .note.gnu.build-id
-    Type:            SHT_NOTE
-    Flags:           [ SHF_ALLOC ]
-    AddressAlign:    0x0000000000000004
-    Content:         040000001000000003000000474E55004FCB712AA6387724A9F465A32CD8C14B
-DynamicSymbols:
-  Global:
-    - Name: atan2
-      Type: STT_FUNC
-      Section: .text
-    - Name: pow
-      Type: STT_FUNC
-      Section: .text
-    - Name: memcpy
-      Type: STT_FUNC
-      Section: .text
-ProgramHeaders:
-  - Type: PT_LOAD
-    Flags: [ PF_X, PF_R ]
-    Sections:
-      - Section: .text
-  - Type: PT_LOAD
-    Flags: [ PF_R ]
-    Sections:
-      - Section: .dynsym
-      - Section: .dynstr
-      - Section: .note.gnu.build-id
-  - Type: PT_NOTE
-    Flags: [ PF_R ]
-    Sections:
-      - Section: .note.gnu.build-id
diff --git a/debug/symbolize/testdata/libcrypto.elf b/debug/symbolize/testdata/libcrypto.elf
deleted file mode 100644
index 6278d90..0000000
--- a/debug/symbolize/testdata/libcrypto.elf
+++ /dev/null
Binary files differ
diff --git a/debug/symbolize/testdata/libcrypto.yaml b/debug/symbolize/testdata/libcrypto.yaml
deleted file mode 100644
index 95654ea..0000000
--- a/debug/symbolize/testdata/libcrypto.yaml
+++ /dev/null
@@ -1,45 +0,0 @@
---- !ELF
-FileHeader:
-  Class:           ELFCLASS64
-  Data:            ELFDATA2LSB
-  Type:            ET_EXEC
-  Machine:         EM_X86_64
-Sections:
-  - Name:            .text
-    Type:            SHT_PROGBITS
-    Flags:           [ SHF_ALLOC ]
-  - Name:            .dynsym
-    Type:            SHT_DYNSYM
-  - Name:            .dynstr
-    Type:            SHT_STRTAB
-  - Name:            .note.gnu.build-id
-    Type:            SHT_NOTE
-    Flags:           [ SHF_ALLOC ]
-    AddressAlign:    0x0000000000000004
-    Content:         040000001000000003000000474E550012ef5c50b3ed3599c07c02d4509311be
-DynamicSymbols:
-  Global:
-    - Name: mod_exp
-      Type: STT_FUNC
-      Section: .text
-    - Name: gf256_mul
-      Type: STT_FUNC
-      Section: .text
-    - Name: gf256_div
-      Type: STT_FUNC
-      Section: .text
-ProgramHeaders:
-  - Type: PT_LOAD
-    Flags: [ PF_X, PF_R ]
-    Sections:
-      - Section: .text
-  - Type: PT_LOAD
-    Flags: [ PF_R ]
-    Sections:
-      - Section: .dynsym
-      - Section: .dynstr
-      - Section: .note.gnu.build-id
-  - Type: PT_NOTE
-    Flags: [ PF_R ]
-    Sections:
-      - Section: .note.gnu.build-id
diff --git a/debug/symbolize/triggers.go b/debug/symbolize/triggers.go
deleted file mode 100644
index ab35467..0000000
--- a/debug/symbolize/triggers.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2018 The Fuchsia 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 symbolize
-
-// TriggerHandler is a visitor for Node types that can trigger actions
-type TriggerContext struct {
-	Source LineSource
-	Mods   []Module
-	Segs   []Segment
-}
-
-// TriggerTap is a nop on the pipeline that reads trigger information out
-type TriggerTap struct {
-	handlers []func(*DumpfileElement)
-}
-
-func NewTriggerTap() *TriggerTap {
-	return &TriggerTap{}
-}
-
-func (t *TriggerTap) AddHandler(handler func(*DumpfileElement)) {
-	t.handlers = append(t.handlers, handler)
-}
-
-func (t *TriggerTap) Process(line OutputLine, out chan<- OutputLine) {
-	for _, node := range line.line {
-		if dumpElem, ok := node.(*DumpfileElement); ok {
-			for _, handler := range t.handlers {
-				handler(dumpElem)
-			}
-		}
-	}
-	out <- line
-}
diff --git a/debug/upload_debug_symbols/cmd/gcs_bucket.go b/debug/upload_debug_symbols/cmd/gcs_bucket.go
deleted file mode 100644
index d910d80..0000000
--- a/debug/upload_debug_symbols/cmd/gcs_bucket.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2019 The Fuchsia 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 (
-	"context"
-	"fmt"
-	"io"
-	"strings"
-
-	"cloud.google.com/go/storage"
-)
-
-// GCSBucket provides access to a cloud storage bucket.
-type GCSBucket struct {
-	bkt *storage.BucketHandle
-}
-
-func (bkt *GCSBucket) upload(ctx context.Context, object string, r io.Reader) error {
-	wc := bkt.bkt.Object(object).If(storage.Conditions{DoesNotExist: true}).NewWriter(ctx)
-	if _, err := io.Copy(wc, r); err != nil {
-		return fmt.Errorf("failed to write object %q: %v", object, err)
-	}
-	// Close completes the write operation and flushes any buffered data.
-	if err := wc.Close(); err != nil {
-		// Error 412 means the precondition of DoesNotExist doesn't match.
-		// It is the expected behavior since we don't want to upload duplicated files.
-		if !strings.Contains(err.Error(), "Error 412") {
-			return fmt.Errorf("failed in close: %v", err)
-		}
-	}
-	return nil
-}
-
-// newGCSBucket returns a new GCSBucket object for the given bucket name.
-func newGCSBucket(ctx context.Context, name string) (*GCSBucket, error) {
-	client, err := storage.NewClient(ctx)
-	if err != nil {
-		return nil, fmt.Errorf("failed to create client: %v", err)
-	}
-	bkt := client.Bucket(gcsBucket)
-	return &GCSBucket{
-		bkt: bkt,
-	}, nil
-}
diff --git a/debug/upload_debug_symbols/cmd/job.go b/debug/upload_debug_symbols/cmd/job.go
deleted file mode 100644
index 7886c35..0000000
--- a/debug/upload_debug_symbols/cmd/job.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2019 The Fuchsia 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 (
-	"context"
-	"fmt"
-	"os"
-
-	"go.fuchsia.dev/tools/debug/elflib"
-)
-
-// job is a description of some BinaryFileRef to upload to GCS. The object's name in GCS
-// is formed by concatenating the ref's BuildID with elflib.DebugFileSuffix.
-type job struct {
-	// The BinaryFileRef to upload to GCS.
-	bfr elflib.BinaryFileRef
-
-	// dstBucket is the destination GCS bucket.
-	dstBucket string
-
-	// gcsPath is the derived destination GCS path.
-	gcsPath string
-
-	// name is a human-readable display name for this job.
-	name string
-}
-
-func newJob(bfr elflib.BinaryFileRef, dstBucket string) job {
-	gcsPath := gcsPath(bfr, dstBucket)
-	name := name(bfr, gcsPath)
-	return job{
-		bfr:       bfr,
-		dstBucket: dstBucket,
-		gcsPath:   gcsPath,
-		name:      name,
-	}
-}
-
-// Returns the GCS path for a bfr upload.
-func gcsPath(bfr elflib.BinaryFileRef, dstBucket string) string {
-	return fmt.Sprintf("gs://%s/%s%s", dstBucket, bfr.BuildID, elflib.DebugFileSuffix)
-}
-
-// Returns a human-readable display name for a bfr upload.
-func name(bfr elflib.BinaryFileRef, gcsPath string) string {
-	return fmt.Sprintf("upload %q to %s", bfr.BuildID, gcsPath)
-}
-
-func (j *job) execute(ctx context.Context, bkt *GCSBucket) error {
-	object := j.bfr.BuildID + elflib.DebugFileSuffix
-	filepath := j.bfr.Filepath
-	reader, err := os.Open(filepath)
-	if err != nil {
-		return fmt.Errorf("failed to open %q: %v", filepath, err)
-	}
-	return bkt.upload(ctx, object, reader)
-}
diff --git a/debug/upload_debug_symbols/cmd/main.go b/debug/upload_debug_symbols/cmd/main.go
deleted file mode 100644
index 51cff0d..0000000
--- a/debug/upload_debug_symbols/cmd/main.go
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright 2019 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Uploads binary debug symbols to Google Cloud Storage.
-//
-// Example Usage:
-//
-// $ upload_debug_symbols -j 20 -bucket bucket-name -upload-record /path/to/record /path/to/.build-id
-
-package main
-
-import (
-	"context"
-	"errors"
-	"flag"
-	"fmt"
-	"io"
-	"log"
-	"os"
-	"strings"
-	"sync"
-
-	"go.fuchsia.dev/tools/debug/elflib"
-)
-
-const (
-	usage = `upload_debug_symbols [flags] [paths..]
-
-	Uploads binary debug symbols to Google Cloud Storage.
-	`
-
-	// The default number of files to upload at once. The storage API returns 4xx errors
-	// when we spawn too many go routines at once, and we can't predict the number of
-	// symbol files we'll have to upload. 100 is chosen as a sensible default. This can be
-	// overriden on the command line.
-	defaultConccurrentUploadCount = 100
-)
-
-// Command line flags.
-var (
-	// The GCS bucket to upload files to.
-	gcsBucket string
-
-	// GCS path to record of uploaded files.
-	uploadRecord string
-
-	// The maximum number of files to upload at once.
-	concurrentUploadCount int
-)
-
-func init() {
-	flag.Usage = func() {
-		fmt.Fprint(os.Stderr, usage)
-		flag.PrintDefaults()
-		os.Exit(1)
-	}
-	flag.StringVar(&gcsBucket, "bucket", "", "GCS bucket to upload symbols to")
-	flag.StringVar(&uploadRecord, "upload-record", "", "Path to write record of uploaded symbols")
-	flag.IntVar(&concurrentUploadCount, "j", defaultConccurrentUploadCount, "Number of concurrent threads to use to upload files")
-}
-
-func main() {
-	flag.Parse()
-	if flag.NArg() == 0 {
-		log.Fatal("expected at least one path to a .build-id directory")
-	}
-	if gcsBucket == "" {
-		log.Fatal("missing -bucket")
-	}
-	if err := execute(context.Background(), flag.Args()); err != nil {
-		log.Fatal(err)
-	}
-}
-
-func execute(ctx context.Context, paths []string) error {
-	bfrs, err := collectDebugSymbolFiles(paths)
-	if err != nil {
-		return fmt.Errorf("failed to collect symbol files: %v", err)
-	}
-	bfrs = filterInvalidDebugSymbolFiles(bfrs)
-	jobs, err := queueJobs(bfrs)
-	if err != nil {
-		return fmt.Errorf("failed to queue jobs: %v", err)
-	}
-	bkt, err := newGCSBucket(ctx, gcsBucket)
-	if err != nil {
-		return err
-	}
-	succeeded, uploadPaths := upload(ctx, bkt, jobs)
-	if !succeeded {
-		return errors.New("completed with errors")
-	}
-	if uploadRecord != "" {
-		if err = writeUploadRecord(uploadRecord, uploadPaths); err != nil {
-			return fmt.Errorf("failed to write record of uploaded symbols: %v", err)
-		}
-		log.Printf("wrote record of uploaded symbols to %s\n", uploadRecord)
-	}
-	return nil
-}
-
-// Returns filtered input of BinaryFileRefs, skipping files without .debug_info header or valid build ID.
-func filterInvalidDebugSymbolFiles(bfrs []elflib.BinaryFileRef) []elflib.BinaryFileRef {
-	var filteredBfrs []elflib.BinaryFileRef
-	for _, bfr := range bfrs {
-		hasDebugInfo, err := bfr.HasDebugInfo()
-		if err != nil {
-			log.Printf("WARNING: cannot read file %s: %v, skipping\n", bfr.Filepath, err)
-		} else if !hasDebugInfo {
-			log.Printf("WARNING: file %s missing .debug_info section, skipping\n", bfr.Filepath)
-		} else if err := bfr.Verify(); err != nil {
-			log.Printf("WARNING: validation failed for %s: %v, skipping\n", bfr.Filepath, err)
-		} else {
-			filteredBfrs = append(filteredBfrs, bfr)
-		}
-	}
-	return filteredBfrs
-}
-
-// Creates BinaryFileRefs for all debug symbol files in the directories named in dirs.
-func collectDebugSymbolFiles(dirs []string) ([]elflib.BinaryFileRef, error) {
-	var out []elflib.BinaryFileRef
-	for _, dir := range dirs {
-		refs, err := elflib.WalkBuildIDDir(dir)
-		if err != nil {
-			return nil, err
-		}
-		out = append(out, refs...)
-	}
-	return out, nil
-}
-
-// Returns a read-only channel of jobs to upload each file referenced in bfrs.
-func queueJobs(bfrs []elflib.BinaryFileRef) (<-chan job, error) {
-	jobs := make(chan job, len(bfrs))
-	for _, bfr := range bfrs {
-		jobs <- newJob(bfr, gcsBucket)
-	}
-	close(jobs)
-	return jobs, nil
-}
-
-// Upload executes all of the jobs to upload files from the input channel. Returns true
-// iff all uploads succeeded without error, and a record of all uploads as a string.
-func upload(ctx context.Context, bkt *GCSBucket, jobs <-chan job) (bool, string) {
-	errs := make(chan error, concurrentUploadCount)
-	defer close(errs)
-	uploadPaths := make(chan string, concurrentUploadCount)
-	defer close(uploadPaths)
-
-	// Spawn workers to execute the uploads.
-	workerCount := concurrentUploadCount
-	var wg sync.WaitGroup
-	wg.Add(workerCount)
-	for i := 0; i < workerCount; i++ {
-		go worker(ctx, bkt, &wg, jobs, errs, uploadPaths)
-	}
-
-	// Let the caller know whether any errors were emitted.
-	succeeded := true
-	go func() {
-		for e := range errs {
-			succeeded = false
-			log.Printf("error: %v", e)
-		}
-	}()
-	// Receive from uploadPaths channel to build upload record.
-	var builder strings.Builder
-	go func() {
-		for uploadPath := range uploadPaths {
-			fmt.Fprintf(&builder, "%s\n", uploadPath)
-		}
-	}()
-	wg.Wait()
-	return succeeded, builder.String()
-}
-
-// worker processes all jobs on the input channel, emitting any errors on errs.
-func worker(ctx context.Context, bkt *GCSBucket, wg *sync.WaitGroup, jobs <-chan job, errs chan<- error, uploadPaths chan<- string) {
-	defer wg.Done()
-	for job := range jobs {
-		log.Printf("executing %s", job.name)
-		err := job.execute(context.Background(), bkt)
-		if err != nil {
-			errs <- fmt.Errorf("job %s failed: %v", job.name, err)
-		} else {
-			uploadPaths <- job.gcsPath
-		}
-	}
-}
-
-// Write upload paths to local file.
-func writeUploadRecord(uploadRecord string, uploadPaths string) error {
-	file, err := os.Create(uploadRecord)
-	if err != nil {
-		return err
-	}
-	defer file.Close()
-	_, err = io.WriteString(file, uploadPaths)
-	return err
-}
diff --git a/go.mod b/go.mod
deleted file mode 100644
index d3ea3ed..0000000
--- a/go.mod
+++ /dev/null
@@ -1,14 +0,0 @@
-module go.fuchsia.dev/tools
-
-require (
-	cloud.google.com/go v0.44.3
-	github.com/google/go-cmp v0.3.1
-	github.com/google/subcommands v1.0.1
-	github.com/google/uuid v1.1.1
-	golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586
-	golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7
-	golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a
-	gopkg.in/yaml.v2 v2.2.2
-)
-
-go 1.13
diff --git a/go.sum b/go.sum
deleted file mode 100644
index b42d0ed..0000000
--- a/go.sum
+++ /dev/null
@@ -1,134 +0,0 @@
-cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
-cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
-cloud.google.com/go v0.44.3 h1:0sMegbmn/8uTwpNkB0q9cLEpZ2W5a6kl+wtBQgPWBJQ=
-cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
-cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
-github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
-github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
-github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
-github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
-github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
-github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
-github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
-github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
-github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/subcommands v1.0.1 h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TUH7k=
-github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
-github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
-github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
-github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
-github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
-github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
-github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
-go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
-go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
-go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0=
-golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
-golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
-golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
-golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
-golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
-golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
-golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
-golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
-golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
-golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
-golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
-golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
-golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
-google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
-google.golang.org/api v0.8.0 h1:VGGbLNyPF7dvYHhcUGYBBGCRDDK0RRJAI6KCvo0CL+E=
-google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
-google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
-google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
-google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
-google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64 h1:iKtrH9Y8mcbADOP0YFaEMth7OfuHY9xHOwNj4znpM1A=
-google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
-google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8=
-google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
diff --git a/integration/testsharder/cmd/main.go b/integration/testsharder/cmd/main.go
deleted file mode 100644
index 092718c..0000000
--- a/integration/testsharder/cmd/main.go
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2018 The Fuchsia 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 (
-	"encoding/json"
-	"flag"
-	"fmt"
-	"log"
-	"os"
-
-	"go.fuchsia.dev/tools/integration/testsharder"
-	"go.fuchsia.dev/tools/lib/command"
-)
-
-var (
-	// The path to the Fuchsia build directory root.
-	buildDir string
-
-	// The filepath to write output to. If unspecified, stdout is used.
-	outputFile string
-
-	// The mode in which to run the testsharder.
-	mode testsharder.Mode = testsharder.Normal
-
-	// Tags are keys on which to filter environments, which are labeled.
-	tags command.StringsFlag
-
-	// The path to the json manifest file containing the tests to mutiply.
-	multipliersPath string
-
-	// Maximum number of tests per shard.
-	maxShardSize int
-)
-
-func usage() {
-	fmt.Printf(`testsharder [flags]
-
-Shards tests produced by a build.
-For more information on the modes in which the testsharder may be run, see
-See https://go.fuchsia.dev/tools/+/master/testsharder/mode.go.
-`)
-}
-
-func init() {
-	flag.StringVar(&buildDir, "build-dir", "", "path to the fuchsia build directory root (required)")
-	flag.StringVar(&outputFile, "output-file", "", "path to a file which will contain the shards as JSON, default is stdout")
-	flag.Var(&mode, "mode", "mode in which to run the testsharder (e.g., normal or restricted).")
-	flag.Var(&tags, "tag", "environment tags on which to filter; only the tests that match all tags will be sharded")
-	flag.StringVar(&multipliersPath, "multipliers", "", "path to the json manifest containing tests to multiply")
-	flag.IntVar(&maxShardSize, "max-shard-size", 0, "maximum number of tests per shard. If <= 0, will be ignored. Otherwise, tests will be placed into more, smaller shards")
-	flag.Usage = usage
-}
-
-func main() {
-	flag.Parse()
-
-	if buildDir == "" {
-		log.Fatal("must specify a Fuchsia build output directory")
-	}
-
-	specs, err := testsharder.LoadTestSpecs(buildDir)
-	if err != nil {
-		log.Fatal(err)
-	}
-	platforms, err := testsharder.LoadPlatforms(buildDir)
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	// Verify that the produced specs specify valid test environments.
-	if err = testsharder.ValidateTestSpecs(specs, platforms); err != nil {
-		log.Fatal(err)
-	}
-
-	// Create shards and write them to an output file if specifed, else stdout.
-	shards := testsharder.MakeShards(specs, mode, tags)
-	if multipliersPath != "" {
-		multipliers, err := testsharder.LoadTestModifiers(multipliersPath)
-		if err != nil {
-			log.Fatal(err)
-		}
-		shards = testsharder.MultiplyShards(shards, multipliers)
-	}
-	shards = testsharder.WithMaxSize(shards, maxShardSize)
-	f := os.Stdout
-	if outputFile != "" {
-		var err error
-		f, err = os.Create(outputFile)
-		if err != nil {
-			log.Fatalf("unable to create %s: %v", outputFile, err)
-		}
-		defer f.Close()
-	}
-
-	encoder := json.NewEncoder(f)
-	encoder.SetIndent("", "  ")
-	if err := encoder.Encode(&shards); err != nil {
-		log.Fatal("failed to encode shards: ", err)
-	}
-}
diff --git a/integration/testsharder/doc.go b/integration/testsharder/doc.go
deleted file mode 100644
index d9a8b45..0000000
--- a/integration/testsharder/doc.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2018 The Fuchsia 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 testsharder creates shards based on tests and specified environments.
-//
-// Test authors in the Fuchsia source will specify `environments`in GN within
-// the packages they define their tests. These specifications will be printed
-// to disk in JSON-form during a build.
-//
-// This package is concerned with reading in those specifications, validating
-// that they correspond to valid test environments supported by the
-// infrastructure, and ultimately sharding the associated tests along the lines
-// of those environments.
-
-package testsharder
diff --git a/integration/testsharder/environment.go b/integration/testsharder/environment.go
deleted file mode 100644
index 8b8b6b1..0000000
--- a/integration/testsharder/environment.go
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2018 The Fuchsia 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 testsharder
-
-import (
-	"encoding/json"
-	"io/ioutil"
-	"path/filepath"
-	"strings"
-
-	"go.fuchsia.dev/tools/build/api"
-)
-
-// Environment describes the full environment a test requires.
-// The GN environments specified by test authors in the Fuchsia source
-// correspond directly to the Environment struct defined here.
-type Environment struct {
-	// Dimensions gives the Swarming dimensions a test wishes to target.
-	Dimensions DimensionSet `json:"dimensions"`
-
-	// Tags are keys given to an environment on which the testsharder may filter.
-	Tags []string `json:"tags,omitempty"`
-
-	// ServiceAccount gives a service account to attach to Swarming task.
-	ServiceAccount string `json:"service_account,omitempty"`
-}
-
-// Name returns a name calculated from its specfied properties.
-func (env Environment) Name() string {
-	tokens := []string{}
-	addToken := func(s string) {
-		if s != "" {
-			// s/-/_, so there is no ambiguity among the tokens
-			// making up a name.
-			s = strings.Replace(s, "-", "_", -1)
-			tokens = append(tokens, s)
-		}
-	}
-
-	addToken(env.Dimensions.DeviceType)
-	addToken(env.Dimensions.OS)
-	addToken(env.Dimensions.Testbed)
-	addToken(env.Dimensions.Pool)
-	if env.ServiceAccount != "" {
-		addToken(strings.Split(env.ServiceAccount, "@")[0])
-	}
-	return strings.Join(tokens, "-")
-}
-
-// DimensionSet encapsulates the Swarming dimensions a test wishes to target.
-type DimensionSet struct {
-	// DeviceType represents the class of device the test should run on.
-	// This is a required field.
-	DeviceType string `json:"device_type,omitempty"`
-
-	// The OS to run the test on (e.g., "Linux" or "Mac"). Used for host-side testing.
-	OS string `json:"os,omitempty"`
-
-	// The CPU type that the test is meant to run on.
-	CPU string `json:"cpu,omitempty"`
-
-	// Testbed denotes a physical test device configuration to run a test on (e.g., multi-device set-ups or devices inside chambers for connectivity testing).
-	Testbed string `json:"testbed,omitempty"`
-
-	// Pool denotes the swarming pool to run a test in.
-	Pool string `json:"pool,omitempty"`
-}
-
-// resolvesTo gives a partial ordering on DimensionSets in which one resolves to
-// another if the former's dimensions are given the latter.
-func (dims DimensionSet) resolvesTo(other DimensionSet) bool {
-	if dims.DeviceType != "" && dims.DeviceType != other.DeviceType {
-		return false
-	}
-	if dims.OS != "" && dims.OS != other.OS {
-		return false
-	}
-	if dims.Testbed != "" && dims.Testbed != other.Testbed {
-		return false
-	}
-	if dims.Pool != "" && dims.Pool != other.Pool {
-		return false
-	}
-	return true
-}
-
-// LoadPlatforms loads the list of test platforms specified as a JSON list
-// produced by a build, given the root of the build directory.
-// Note that by "platforms" we mean a specific group of dimension sets which
-// correspond to the currently available test platforms supported by the
-// infrastructure.
-func LoadPlatforms(fuchsiaBuildDir string) ([]DimensionSet, error) {
-	platformManifestPath := filepath.Join(fuchsiaBuildDir, build.PlatformManifestName)
-	bytes, err := ioutil.ReadFile(platformManifestPath)
-	if err != nil {
-		return nil, err
-	}
-	var platforms []DimensionSet
-	if err = json.Unmarshal(bytes, &platforms); err != nil {
-		return nil, err
-	}
-	return platforms, err
-}
diff --git a/integration/testsharder/mode.go b/integration/testsharder/mode.go
deleted file mode 100644
index 088cb90..0000000
--- a/integration/testsharder/mode.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2019 The Fuchsia 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 testsharder
-
-import (
-	"fmt"
-)
-
-// Mode is a mode in which the testsharder can be run.
-type Mode int
-
-const (
-	// Normal is the default mode in which all tests are sharded, except
-	// those excluded by differing tags.
-	Normal Mode = iota
-
-	// Restricted is the mode in which auth-needing tests (i.e., those that
-	// specify service accounts) are ignored. This mode is useful for
-	// running untrusted code.
-	Restricted
-)
-
-// String implements flag.Var.String.
-func (m *Mode) String() string {
-	switch *m {
-	case Normal:
-		return "normal"
-	case Restricted:
-		return "restricted"
-	}
-	return ""
-}
-
-// Set implements flag.Var.Set.
-func (m *Mode) Set(s string) error {
-	switch s {
-	case "normal":
-		*m = Normal
-	case "restricted":
-		*m = Restricted
-	default:
-		return fmt.Errorf("%s is not a valid mode", s)
-	}
-	return nil
-}
diff --git a/integration/testsharder/shard.go b/integration/testsharder/shard.go
deleted file mode 100644
index 3fd6a50..0000000
--- a/integration/testsharder/shard.go
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2018 The Fuchsia 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 testsharder
-
-import (
-	"fmt"
-	"sort"
-	"strings"
-)
-
-// Shard represents a set of tests with a common execution environment.
-type Shard struct {
-	// Name is the identifier for the shard.
-	Name string `json:"name"`
-
-	// Tests is the set of tests to be executed in this shard.
-	Tests []Test `json:"tests"`
-
-	// Env is a generalized notion of the execution environment for the shard.
-	Env Environment `json:"environment"`
-}
-
-// MakeShards is the core algorithm to this tool. It takes a set of test specs and produces
-// a set of shards which may then be converted into Swarming tasks.
-// A single output Shard will contain only tests that have the same Envs.
-//
-// Environments that do not match all tags will be ignored.
-//
-// In Restricted mode, environments that don't specify a ServiceAccount will be ignored.
-func MakeShards(specs []TestSpec, mode Mode, tags []string) []*Shard {
-	// Collect the order of the shards so our shard ordering is deterministic with
-	// respect to the input.
-	envToSuites := newEnvMap()
-	envs := []Environment{}
-	for _, spec := range specs {
-		for _, env := range spec.Envs {
-			if !stringSlicesEq(tags, env.Tags) {
-				continue
-			}
-			if mode == Restricted && env.ServiceAccount != "" {
-				continue
-			}
-
-			// Tags should not differ by ordering.
-			sortableTags := sort.StringSlice(tags)
-			sortableTags.Sort()
-			env.Tags = []string(sortableTags)
-
-			specs, ok := envToSuites.get(env)
-			if !ok {
-				envs = append(envs, env)
-			}
-			envToSuites.set(env, append(specs, spec))
-		}
-	}
-	shards := make([]*Shard, 0, len(envs))
-	for _, env := range envs {
-		specs, _ := envToSuites.get(env)
-		sort.Slice(specs, func(i, j int) bool {
-			return specs[i].Test.Name < specs[j].Test.Name
-		})
-		var tests []Test
-		for _, spec := range specs {
-			tests = append(tests, spec.Test)
-		}
-		shards = append(shards, &Shard{
-			Name:  env.Name(),
-			Tests: tests,
-			Env:   env,
-		})
-	}
-	return shards
-}
-
-// MultiplyShards appends new shards to shards where each new shard contains one test
-// repeated multiple times according to the specifications in multipliers.
-func MultiplyShards(shards []*Shard, multipliers []TestModifier) []*Shard {
-	for _, shard := range shards {
-		for _, multiplier := range multipliers {
-			for _, test := range shard.Tests {
-				if multiplier.Target == test.Name && multiplier.OS == test.OS {
-					shards = append(shards, &Shard{
-						Name:  shard.Name + "-" + normalizeTestName(test.Name),
-						Tests: multiplyTest(test, multiplier.TotalRuns),
-						Env:   shard.Env,
-					})
-				}
-			}
-		}
-	}
-	return shards
-}
-
-func min(a, b int) int {
-	if a < b {
-		return a
-	}
-	return b
-}
-
-func divRoundUp(a, b int) int {
-	if a%b == 0 {
-		return a / b
-	}
-	return (a / b) + 1
-}
-
-// WithMaxSize returns a list of shards such that each shard contains fewer than maxShardSize tests.
-// If maxShardSize <= 0, just returns its input.
-func WithMaxSize(shards []*Shard, maxShardSize int) []*Shard {
-	if maxShardSize <= 0 {
-		return shards
-	}
-	output := make([]*Shard, 0, len(shards))
-	for _, shard := range shards {
-		numNewShards := divRoundUp(len(shard.Tests), maxShardSize)
-		// Evenly distribute the tests between the new shards.
-		maxTestsPerNewShard := divRoundUp(len(shard.Tests), numNewShards)
-		for i := 0; i < numNewShards; i++ {
-			sliceStart := i * maxTestsPerNewShard
-			sliceLimit := min((i+1)*maxTestsPerNewShard, len(shard.Tests))
-			newName := shard.Name
-			if numNewShards > 1 {
-				newName = fmt.Sprintf("%s-(%d)", shard.Name, i+1)
-			}
-			output = append(output, &Shard{
-				Name:  newName,
-				Tests: shard.Tests[sliceStart:sliceLimit],
-				Env:   shard.Env,
-			})
-		}
-	}
-	return output
-}
-
-// Removes leading slashes and replaces all other `/` with `_`. This allows the
-// shard name to appear in filepaths.
-func normalizeTestName(name string) string {
-	trimmedName := strings.TrimLeft(name, "/")
-	return strings.ReplaceAll(trimmedName, "/", "_")
-}
-
-// Returns a list of Tests containing the same test multiplied by the number of runs.
-func multiplyTest(test Test, runs int) []Test {
-	var tests []Test
-	for i := 1; i <= runs; i++ {
-		testCopy := test
-		testCopy.Name = fmt.Sprintf("%s (%d)", test.Name, i)
-		tests = append(tests, testCopy)
-	}
-	return tests
-}
-
-// Abstracts a mapping Environment -> []string, as Environment contains non-comparable
-// members (e.g., string slices), which makes it invalid for a map key.
-type envMap struct {
-	m map[string][]TestSpec
-}
-
-func newEnvMap() envMap {
-	return envMap{m: make(map[string][]TestSpec)}
-}
-
-func (em envMap) get(e Environment) ([]TestSpec, bool) {
-	specs, ok := em.m[fmt.Sprintf("%v", e)]
-	return specs, ok
-}
-
-func (em *envMap) set(e Environment, specs []TestSpec) {
-	em.m[fmt.Sprintf("%v", e)] = specs
-}
-
-func stringSlicesEq(s []string, t []string) bool {
-	if len(s) != len(t) {
-		return false
-	}
-	seen := make(map[string]int)
-	for i := range s {
-		seen[s[i]]++
-		seen[t[i]]--
-	}
-	for _, v := range seen {
-		if v != 0 {
-			return false
-		}
-	}
-	return true
-}
diff --git a/integration/testsharder/shard_test.go b/integration/testsharder/shard_test.go
deleted file mode 100644
index 2185c5d..0000000
--- a/integration/testsharder/shard_test.go
+++ /dev/null
@@ -1,315 +0,0 @@
-// Copyright 2018 The Fuchsia 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 testsharder
-
-import (
-	"fmt"
-	"reflect"
-	"testing"
-)
-
-// Note that just printing a list of shard pointers will print a list of memory addresses,
-// which would make for an unhelpful error message.
-func assertEqual(t *testing.T, expected, actual []*Shard) {
-	if !reflect.DeepEqual(expected, actual) {
-		errMsg := "\nexpected:\n"
-		for _, shard := range expected {
-			errMsg += fmt.Sprintf("%v,\n", shard)
-		}
-		errMsg += "\nactual:\n"
-		for _, shard := range actual {
-			errMsg += fmt.Sprintf("%v,\n", shard)
-		}
-		t.Fatalf(errMsg)
-	}
-}
-
-func spec(id int, envs ...Environment) TestSpec {
-	return TestSpec{
-		Test: Test{
-			Location: fmt.Sprintf("/path/to/test/%d", id),
-		},
-		Envs: envs,
-	}
-}
-
-func shard(env Environment, ids ...int) *Shard {
-	return namedShard(env, env.Name(), ids...)
-}
-
-func namedShard(env Environment, name string, ids ...int) *Shard {
-	var tests []Test
-	for _, id := range ids {
-		tests = append(tests, spec(id, env).Test)
-	}
-	return &Shard{
-		Name:  name,
-		Tests: tests,
-		Env:   env,
-	}
-}
-
-func TestMakeShards(t *testing.T) {
-	env1 := Environment{
-		Dimensions: DimensionSet{DeviceType: "QEMU"},
-		Tags:       []string{},
-	}
-	env2 := Environment{
-		Dimensions: DimensionSet{DeviceType: "NUC"},
-		Tags:       []string{},
-	}
-	env3 := Environment{
-		Dimensions: DimensionSet{OS: "Linux"},
-		Tags:       []string{},
-	}
-	t.Run("environments have nonempty names", func(t *testing.T) {
-		envs := []Environment{env1, env2, env3}
-		for _, env := range envs {
-			if env.Name() == "" {
-				t.Fatalf("Environment\n%+v\n has an empty name", env)
-			}
-		}
-	})
-
-	t.Run("tests of same environment are grouped", func(t *testing.T) {
-		actual := MakeShards(
-			[]TestSpec{spec(1, env1, env2), spec(2, env1, env3), spec(3, env3)},
-			Normal,
-			[]string{},
-		)
-		expected := []*Shard{shard(env1, 1, 2), shard(env2, 1), shard(env3, 2, 3)}
-		assertEqual(t, expected, actual)
-	})
-
-	t.Run("there is no deduplication of tests", func(t *testing.T) {
-		actual := MakeShards(
-			[]TestSpec{spec(1, env1), spec(1, env1), spec(1, env1)},
-			Normal,
-			[]string{},
-		)
-		expected := []*Shard{shard(env1, 1, 1, 1)}
-		assertEqual(t, expected, actual)
-	})
-
-	// Ensure that the order of the shards is the order in which their
-	// corresponding environments appear in the input. This is the simplest
-	// deterministic order we can produce for the shards.
-	t.Run("shards are ordered", func(t *testing.T) {
-		actual := MakeShards(
-			[]TestSpec{spec(1, env2, env3), spec(2, env1), spec(3, env3)},
-			Normal,
-			[]string{},
-		)
-		expected := []*Shard{shard(env2, 1), shard(env3, 1, 3), shard(env1, 2)}
-		assertEqual(t, expected, actual)
-	})
-
-	t.Run("tags are respected", func(t *testing.T) {
-		tagger := func(env Environment, tags ...string) Environment {
-			env2 := env
-			env2.Tags = tags
-			return env2
-		}
-
-		actual := MakeShards(
-			[]TestSpec{
-				spec(1, tagger(env1, "A")),
-				spec(2, tagger(env1, "A", "B", "C")),
-				spec(3, tagger(env2, "B", "C")),
-				spec(4, tagger(env3, "C", "A")),
-				spec(5, tagger(env3, "A", "C")),
-			},
-			Normal,
-			[]string{"A", "C"},
-		)
-		expected := []*Shard{
-			// "C", "A" and "A", "C" should define the same tags.
-			shard(tagger(env3, "A", "C"), 4, 5),
-		}
-		assertEqual(t, expected, actual)
-	})
-
-	t.Run("different service accounts get different shards", func(t *testing.T) {
-		withAcct := func(env Environment, acct string) Environment {
-			env2 := env
-			env2.ServiceAccount = acct
-			return env2
-		}
-
-		actual := MakeShards(
-			[]TestSpec{
-				spec(1, env1),
-				spec(1, withAcct(env1, "acct1")),
-				spec(1, withAcct(env1, "acct2")),
-			},
-			Normal,
-			[]string{},
-		)
-		expected := []*Shard{
-			shard(env1, 1),
-			shard(withAcct(env1, "acct1"), 1),
-			shard(withAcct(env1, "acct2"), 1),
-		}
-		assertEqual(t, expected, actual)
-	})
-
-	t.Run("restricted mode is respected", func(t *testing.T) {
-		withAcct := func(env Environment, acct string) Environment {
-			env2 := env
-			env2.ServiceAccount = acct
-			return env2
-		}
-
-		actual := MakeShards(
-			[]TestSpec{
-				spec(1, env1),
-				spec(2, withAcct(env1, "acct1")),
-				spec(3, withAcct(env1, "acct2")),
-			},
-			Restricted,
-			[]string{},
-		)
-		expected := []*Shard{
-			shard(env1, 1),
-		}
-		assertEqual(t, expected, actual)
-	})
-}
-
-func TestMultiplyShards(t *testing.T) {
-	env1 := Environment{
-		Dimensions: DimensionSet{DeviceType: "QEMU"},
-		Tags:       []string{},
-	}
-	env2 := Environment{
-		Dimensions: DimensionSet{DeviceType: "NUC"},
-		Tags:       []string{},
-	}
-	env3 := Environment{
-		Dimensions: DimensionSet{OS: "Linux"},
-		Tags:       []string{},
-	}
-	makeTest := func(id int, os OS) Test {
-		return Test{
-			Name:     fmt.Sprintf("test%d", id),
-			Location: fmt.Sprintf("/path/to/test/%d", id),
-			OS:       os,
-		}
-	}
-
-	shard := func(env Environment, os OS, ids ...int) *Shard {
-		var tests []Test
-		for _, id := range ids {
-			tests = append(tests, makeTest(id, os))
-		}
-		return &Shard{
-			Name:  env.Name(),
-			Tests: tests,
-			Env:   env,
-		}
-	}
-
-	makeTestModifier := func(id int, os OS, runs int) TestModifier {
-		return TestModifier{
-			Target:    fmt.Sprintf("test%d", id),
-			OS:        os,
-			TotalRuns: runs,
-		}
-	}
-
-	multShard := func(env Environment, os OS, id int, runs int) *Shard {
-		var tests []Test
-		test := makeTest(id, os)
-		for i := 1; i <= runs; i++ {
-			testCopy := test
-			testCopy.Name = fmt.Sprintf("%s (%d)", test.Name, i)
-			tests = append(tests, testCopy)
-		}
-		return &Shard{
-			Name:  env.Name() + "-" + test.Name,
-			Tests: tests,
-			Env:   env,
-		}
-	}
-
-	t.Run("multiply tests in shards", func(t *testing.T) {
-		shards := []*Shard{
-			shard(env1, Fuchsia, 1),
-			shard(env2, Fuchsia, 1, 2),
-			shard(env3, Linux, 3),
-		}
-		multipliers := []TestModifier{
-			makeTestModifier(1, Fuchsia, 2),
-			makeTestModifier(3, Linux, 3),
-		}
-		actual := MultiplyShards(
-			shards,
-			multipliers,
-		)
-		expected := append(
-			shards,
-			multShard(env1, Fuchsia, 1, 2),
-			multShard(env2, Fuchsia, 1, 2),
-			multShard(env3, Linux, 3, 3),
-		)
-		assertEqual(t, expected, actual)
-	})
-}
-
-func max(a, b int) int {
-	if a > b {
-		return a
-	}
-	return b
-}
-
-func TestWithMaxSize(t *testing.T) {
-	env1 := Environment{
-		Tags: []string{"env1"},
-	}
-	env2 := Environment{
-		Dimensions: DimensionSet{DeviceType: "env2"},
-		Tags:       []string{"env2"},
-	}
-	input := []*Shard{namedShard(env1, "env1", 1, 2, 3, 4, 5), namedShard(env2, "env2", 6, 7, 8)}
-	t.Run("does nothing if max is 0", func(t *testing.T) {
-		assertEqual(t, input, WithMaxSize(input, 0))
-	})
-	t.Run("does nothing if max is < 0", func(t *testing.T) {
-		assertEqual(t, input, WithMaxSize(input, -7))
-	})
-	assertShardsLessThanSize := func(t *testing.T, actual []*Shard, maxSize int) {
-		for _, s := range actual {
-			if len(s.Tests) > maxSize {
-				t.Errorf("Shard %s has %d tests, expected at most %d", s.Name, len(s.Tests), maxSize)
-			}
-		}
-	}
-	t.Run("max is larger greater or equal to all shards", func(t *testing.T) {
-		maxSize := max(len(input[0].Tests), len(input[1].Tests))
-		actual := WithMaxSize(input, maxSize)
-		assertEqual(t, input, actual)
-		assertShardsLessThanSize(t, actual, maxSize)
-	})
-
-	t.Run("applies max", func(t *testing.T) {
-		maxSize := 2
-		actual := WithMaxSize(input, maxSize)
-		assertEqual(t, []*Shard{
-			namedShard(env1, "env1-(1)", 1, 2), namedShard(env1, "env1-(2)", 3, 4),
-			namedShard(env1, "env1-(3)", 5),
-			namedShard(env2, "env2-(1)", 6, 7), namedShard(env2, "env2-(2)", 8)},
-			actual)
-		assertShardsLessThanSize(t, actual, maxSize)
-	})
-	t.Run("evenly distributes tests", func(t *testing.T) {
-		maxSize := 4
-		actual := WithMaxSize(input, maxSize)
-		assertEqual(t, []*Shard{
-			namedShard(env1, "env1-(1)", 1, 2, 3), namedShard(env1, "env1-(2)", 4, 5),
-			namedShard(env2, "env2", 6, 7, 8)},
-			actual)
-		assertShardsLessThanSize(t, actual, maxSize)
-	})
-}
diff --git a/integration/testsharder/test_modifier.go b/integration/testsharder/test_modifier.go
deleted file mode 100644
index 36d8a59..0000000
--- a/integration/testsharder/test_modifier.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2019 The Fuchsia 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 testsharder
-
-import (
-	"encoding/json"
-	"fmt"
-	"io/ioutil"
-)
-
-// TestModifier is the specification for a single test and the number of
-// times it should be run.
-type TestModifier struct {
-	// Target is the GN target name of the test.
-	Target string `json:"target"`
-
-	// OS is the operating system in which this test must be executed; treated as "fuchsia" if not present.
-	OS OS `json:"os,omitempty"`
-
-	// TotalRuns is the number of times to run the test; treated as 1 if not present.
-	TotalRuns int `json:"total_runs,omitempty"`
-}
-
-// LoadTestModifiers loads a set of test modifiers from a json manifest.
-func LoadTestModifiers(manifestPath string) ([]TestModifier, error) {
-	bytes, err := ioutil.ReadFile(manifestPath)
-	if err != nil {
-		return nil, err
-	}
-	var specs []TestModifier
-	if err = json.Unmarshal(bytes, &specs); err != nil {
-		return nil, err
-	}
-
-	for i := range specs {
-		if specs[i].Target == "" {
-			return nil, fmt.Errorf("A test spec's target must have a non-empty name")
-		}
-		if specs[i].TotalRuns == 0 {
-			specs[i].TotalRuns = 1
-		}
-		if specs[i].OS == "" {
-			specs[i].OS = Fuchsia
-		}
-	}
-	return specs, nil
-}
diff --git a/integration/testsharder/test_modifier_test.go b/integration/testsharder/test_modifier_test.go
deleted file mode 100644
index 59785b1..0000000
--- a/integration/testsharder/test_modifier_test.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2019 The Fuchsia 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 testsharder
-
-import (
-	"encoding/json"
-	"fmt"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"reflect"
-	"sort"
-	"testing"
-)
-
-var barTestModifier = TestModifier{
-	Target:    "//obsidian/lib/bar:bar_tests",
-	TotalRuns: 2,
-}
-
-var bazTestModifier = TestModifier{
-	Target: "//obsidian/public/lib/baz:baz_host_tests",
-	OS:     Linux,
-}
-
-func TestLoadTestModifiers(t *testing.T) {
-	areEqual := func(a, b []TestModifier) bool {
-		stringify := func(modifier TestModifier) string {
-			return fmt.Sprintf("%#v", modifier)
-		}
-		sort := func(list []TestModifier) {
-			sort.Slice(list[:], func(i, j int) bool {
-				return stringify(list[i]) < stringify(list[j])
-			})
-		}
-		sort(a)
-		sort(b)
-		return reflect.DeepEqual(a, b)
-	}
-
-	tmpDir, err := ioutil.TempDir("", "test-spec")
-	if err != nil {
-		t.Fatalf("failed to create temp dir: %v", err)
-	}
-	defer os.RemoveAll(tmpDir)
-
-	initial := []TestModifier{barTestModifier, bazTestModifier}
-
-	modifiersPath := filepath.Join(tmpDir, "test_modifiers.json")
-	m, err := os.Create(modifiersPath)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer m.Close()
-	if err := json.NewEncoder(m).Encode(&initial); err != nil {
-		t.Fatal(err)
-	}
-
-	actual, err := LoadTestModifiers(modifiersPath)
-	if err != nil {
-		t.Fatalf("failed to load test modifiers: %v", err)
-	}
-
-	bazOut := bazTestModifier
-	// If TotalRuns is missing, it gets set to default 1.
-	bazOut.TotalRuns = 1
-	barOut := barTestModifier
-	// If OS is missing, it gets set to default Fuchsia.
-	barOut.OS = Fuchsia
-	expected := []TestModifier{barOut, bazOut}
-
-	if !areEqual(expected, actual) {
-		t.Fatalf("test modifiers not properly loaded:\nexpected:\n%+v\nactual:\n%+v", expected, actual)
-	}
-}
diff --git a/integration/testsharder/test_spec.go b/integration/testsharder/test_spec.go
deleted file mode 100644
index e05a35c..0000000
--- a/integration/testsharder/test_spec.go
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2018 The Fuchsia 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 testsharder
-
-import (
-	"encoding/json"
-	"fmt"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-
-	"go.fuchsia.dev/tools/build/api"
-)
-
-// OS is an operating system that a test may run in.
-type OS string
-
-// Acceptable OS constants.
-const (
-	Linux   OS = "linux"
-	Fuchsia OS = "fuchsia"
-	Mac     OS = "mac"
-)
-
-// TestSpec is the specification for a single test and the environments it
-// should be executed in.
-type TestSpec struct {
-	// Test is the test that this specification is for.
-	Test `json:"test"`
-
-	// Envs is a set of environments that the test should be executed in.
-	Envs []Environment `json:"environments"`
-}
-
-// Test encapsulates details about a particular test.
-type Test struct {
-	// Name is the full, GN source-relative target name of the test
-	// (e.g., //garnet/bin/foo/tests:foo_tests).
-	Name string `json:"name"`
-
-	// TODO(joshuaseaton): Remove and replace by `Path`.
-	//
-	// Location is a unique reference to a test: for example, a filesystem
-	// path or a Fuchsia URI.
-	Location string `json:"location"`
-
-	// Path is the path to the test.
-	Path string `json:"path"`
-
-	// OS is the operating system in which this test must be executed.
-	OS OS `json:"os"`
-
-	// Command is the command line to run to execute this test.
-	Command []string `json:"command,omitempty"`
-
-	// DepsFile is a relative path within the build directory to a file containing a JSON
-	// list of the test's runtime dependencies,
-	// Currently this field only makes sense for Linux and Mac tests.
-	DepsFile string `json:"deps_file,omitempty"`
-
-	// Deps is the list of paths to the test's runtime dependencies within the build
-	// directory. It is read out of DepsFile.
-	Deps []string `json:"deps,omitempty"`
-}
-
-func (spec TestSpec) validateAgainst(platforms []DimensionSet) error {
-	if spec.Test.Name == "" {
-		return fmt.Errorf("A test spec's test must have a non-empty name")
-	}
-	if len(spec.Command) == 0 && spec.Test.Path == "" && spec.Test.Location == "" {
-		return fmt.Errorf("A test spec's test must have one of a non-empty path, non-empty location, or non-empty command")
-	}
-	if spec.Test.OS == "" {
-		return fmt.Errorf("A test spec's test must have a non-empty OS")
-	}
-
-	resolvesToOneOf := func(env Environment, platforms []DimensionSet) bool {
-		for _, platform := range platforms {
-			if env.Dimensions.resolvesTo(platform) {
-				return true
-			}
-		}
-		return false
-	}
-
-	var badEnvs []Environment
-	for _, env := range spec.Envs {
-		if !resolvesToOneOf(env, platforms) {
-			badEnvs = append(badEnvs, env)
-		}
-	}
-	if len(badEnvs) > 0 {
-		return fmt.Errorf(
-			`the following environments of test\n%+v were malformed
-			or did not match any available test platforms:\n%+v`,
-			spec.Test, badEnvs)
-	}
-	return nil
-}
-
-// ValidateTestSpecs validates a list of test specs against a list of test
-// platform dimension sets.
-func ValidateTestSpecs(specs []TestSpec, platforms []DimensionSet) error {
-	errMsg := ""
-	for _, spec := range specs {
-		if err := spec.validateAgainst(platforms); err != nil {
-			errMsg += fmt.Sprintf("\n%v", err)
-		}
-	}
-	if errMsg != "" {
-		return fmt.Errorf(errMsg)
-	}
-	return nil
-}
-
-// LoadTestSpecs loads a set of test specifications from a build.
-func LoadTestSpecs(fuchsiaBuildDir string) ([]TestSpec, error) {
-	manifestPath := filepath.Join(fuchsiaBuildDir, build.TestSpecManifestName)
-	bytes, err := ioutil.ReadFile(manifestPath)
-	if err != nil {
-		return nil, err
-	}
-	var specs []TestSpec
-	if err = json.Unmarshal(bytes, &specs); err != nil {
-		return nil, err
-	}
-
-	for i := range specs {
-		if specs[i].Path == "" {
-			specs[i].Path = specs[i].Location
-		}
-
-		if specs[i].DepsFile == "" {
-			continue
-		}
-		path := filepath.Join(fuchsiaBuildDir, specs[i].DepsFile)
-		f, err := os.Open(path)
-		if err != nil {
-			return nil, err
-		}
-		if err = json.NewDecoder(f).Decode(&specs[i].Deps); err != nil {
-			return nil, err
-		}
-		specs[i].DepsFile = "" // No longer needed.
-	}
-	return specs, nil
-}
-
-// LoadTests loads the list of tests from the given path.
-func LoadTests(path string) ([]Test, error) {
-	bytes, err := ioutil.ReadFile(path)
-	if err != nil {
-		return nil, fmt.Errorf("failed to read %q: %v", path, err)
-	}
-
-	var tests []Test
-	if err := json.Unmarshal(bytes, &tests); err != nil {
-		return nil, fmt.Errorf("failed to unmarshal %q: %v", path, err)
-	}
-
-	return tests, nil
-}
diff --git a/integration/testsharder/test_spec_test.go b/integration/testsharder/test_spec_test.go
deleted file mode 100644
index 3d38a0b..0000000
--- a/integration/testsharder/test_spec_test.go
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright 2018 The Fuchsia 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 testsharder
-
-import (
-	"encoding/json"
-	"fmt"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"reflect"
-	"sort"
-	"testing"
-
-	"go.fuchsia.dev/tools/build/api"
-)
-
-var qemuPlatform = DimensionSet{
-	DeviceType: "QEMU",
-}
-
-var nucPlatform = DimensionSet{
-	DeviceType: "NUC",
-}
-
-var linuxPlatform = DimensionSet{
-	OS: "Linux",
-}
-
-var macPlatform = DimensionSet{
-	OS: "Mac",
-}
-
-var qemuEnv = Environment{
-	Dimensions: qemuPlatform,
-}
-
-var nucEnv = Environment{
-	Dimensions: nucPlatform,
-}
-
-var linuxEnv = Environment{
-	Dimensions: linuxPlatform,
-}
-
-var macEnv = Environment{
-	Dimensions: macPlatform,
-}
-
-var specFoo1 = TestSpec{
-	Test: Test{
-		Name:    "//obsidian/bin/foo:foo_unittests",
-		Path:    "/system/test/foo_unittests",
-		OS:      Fuchsia,
-		Command: []string{"/system/test/foo_unittests", "bar", "baz"},
-	},
-	Envs: []Environment{qemuEnv},
-}
-
-var specFoo2 = TestSpec{
-	Test: Test{
-		Name: "//obsidian/bin/foo:foo_integration_tests",
-		Path: "/system/test/foo_integration_tests",
-		OS:   Fuchsia,
-	},
-	Envs: []Environment{qemuEnv, nucEnv},
-}
-
-var specBar = TestSpec{
-	Test: Test{
-		Name: "//obsidian/lib/bar:bar_tests",
-		Path: "/system/test/bar_tests",
-		OS:   Fuchsia,
-	},
-	Envs: []Environment{qemuEnv},
-}
-
-var specBaz = TestSpec{
-	Test: Test{
-		Name: "//obsidian/public/lib/baz:baz_host_tests",
-		Path: "/$root_build_dir/baz_host_tests",
-		OS:   Linux,
-	},
-	Envs: []Environment{linuxEnv, macEnv},
-}
-
-func TestLoadTestSpecs(t *testing.T) {
-	areEqual := func(a, b []TestSpec) bool {
-		stringify := func(spec TestSpec) string {
-			return fmt.Sprintf("%#v", spec)
-		}
-		sort := func(list []TestSpec) {
-			sort.Slice(list[:], func(i, j int) bool {
-				return stringify(list[i]) < stringify(list[j])
-			})
-		}
-		sort(a)
-		sort(b)
-		return reflect.DeepEqual(a, b)
-	}
-
-	tmpDir, err := ioutil.TempDir("", "test-spec")
-	if err != nil {
-		t.Fatalf("failed to create temp dir: %v", err)
-	}
-	defer os.RemoveAll(tmpDir)
-
-	deps := []string{"path/to/first/dep", "path/to/second"}
-	depsFilepath := filepath.Join(tmpDir, "deps.json")
-	df, err := os.Create(depsFilepath)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer df.Close()
-	if err := json.NewEncoder(df).Encode(&deps); err != nil {
-		t.Fatalf("failed to create JSON encoder: %v", err)
-	}
-
-	specBazIn := specBaz
-	specBazIn.DepsFile = "deps.json"
-	initial := []TestSpec{specBar, specBazIn}
-
-	manifest := filepath.Join(tmpDir, build.TestSpecManifestName)
-	m, err := os.Create(manifest)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer m.Close()
-	if err := json.NewEncoder(m).Encode(&initial); err != nil {
-		t.Fatal(err)
-	}
-
-	actual, err := LoadTestSpecs(tmpDir)
-	if err != nil {
-		t.Fatalf("failed to load test specs: %v", err)
-	}
-
-	specBazOut := specBaz
-	specBazOut.Deps = deps
-	expected := []TestSpec{specBar, specBazOut}
-
-	if !areEqual(expected, actual) {
-		t.Fatalf("test specs not properly loaded:\nexpected:\n%+v\nactual:\n%+v", expected, actual)
-	}
-}
-
-func TestValidateTestSpecs(t *testing.T) {
-	noTestNameSpec := TestSpec{
-		Test: Test{
-			Path: "/system/test/baz_tests",
-			OS:   Linux,
-		},
-		Envs: []Environment{qemuEnv},
-	}
-	noTestPathSpec := TestSpec{
-		Test: Test{
-			Name: "//obsidian/public/lib/baz:baz_tests",
-			OS:   Linux,
-		},
-		Envs: []Environment{qemuEnv},
-	}
-	noOSSpec := TestSpec{
-		Test: Test{
-			Name: "//obsidian/bin/foo:foo_unittests",
-			Path: "/system/test/foo_unittests",
-		},
-	}
-	badEnvSpec := TestSpec{
-		Test: Test{
-			Name: "//obsidian/public/lib/baz:baz_tests",
-			Path: "/system/test/baz_tests",
-			OS:   Linux,
-		},
-		Envs: []Environment{
-			Environment{
-				Dimensions: DimensionSet{
-					DeviceType: "NON-EXISTENT-DEVICE",
-				},
-			},
-		},
-	}
-	platforms := []DimensionSet{qemuPlatform, nucPlatform}
-
-	t.Run("valid specs are validated", func(t *testing.T) {
-		validSpecLists := [][]TestSpec{
-			{specFoo1}, {specFoo2}, {specBar},
-			{specFoo1, specFoo2}, {specFoo1, specBar}, {specFoo2, specBar},
-			{specFoo1, specFoo2, specBar},
-		}
-		for _, list := range validSpecLists {
-			if err := ValidateTestSpecs(list, platforms); err != nil {
-				t.Fatalf("valid specs marked as invalid: %+v: %v", list, err)
-			}
-		}
-	})
-
-	t.Run("invalid specs are invalidated", func(t *testing.T) {
-		invalidSpecLists := [][]TestSpec{
-			{noOSSpec}, {noTestNameSpec}, {noTestPathSpec}, {badEnvSpec},
-			{noTestNameSpec, noTestPathSpec}, {noTestNameSpec, badEnvSpec},
-			{noTestPathSpec, badEnvSpec},
-			{noTestNameSpec, noTestPathSpec, badEnvSpec},
-		}
-		for _, list := range invalidSpecLists {
-			if err := ValidateTestSpecs(list, platforms); err == nil {
-				t.Fatalf("invalid specs marked as valid: %+v", list)
-			}
-		}
-	})
-}
diff --git a/lib/cache/cache.go b/lib/cache/cache.go
deleted file mode 100644
index 6a5ce6f..0000000
--- a/lib/cache/cache.go
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2018 The Fuchsia 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 cache provides methods for creating and using a cache.
-package cache
-
-import "container/list"
-
-// A Key may be any value that is comparable.
-type Key interface{}
-
-// Cache is the interface for cache.
-type Cache interface {
-	// Adds a value to the cache.
-	Add(key Key, value interface{}) interface{}
-
-	// Returns key's value from the cache.
-	Get(key Key) (interface{}, bool)
-
-	// Checks if a key exists in cache.
-	Contains(key Key) bool
-
-	// Removes a key from the cache.
-	Remove(key Key) interface{}
-
-	// Returns the number of items in the cache.
-	Len() int
-
-	// Clears all cache entries.
-	Clear()
-}
-
-// LRUCache is a simple LRU cache.
-type LRUCache struct {
-	// Size is the maximum number of entries before an item is evicted.
-	// Zero means no limit on the number of entries.
-	Size uint
-
-	ll    *list.List
-	cache map[interface{}]*list.Element
-}
-
-type entry struct {
-	key   Key
-	value interface{}
-}
-
-// Add adds a value to the cache and updates the "recently used"-ness of the key.
-func (c *LRUCache) Add(key Key, value interface{}) interface{} {
-	if c.cache == nil {
-		c.cache = make(map[interface{}]*list.Element)
-		c.ll = list.New()
-	}
-	if e, ok := c.cache[key]; ok {
-		c.ll.MoveToFront(e)
-		value, e.Value.(*entry).value = e.Value.(*entry).value, value
-		return value
-	}
-	e := c.ll.PushFront(&entry{key, value})
-	c.cache[key] = e
-	if c.Size != 0 && uint(c.ll.Len()) > c.Size {
-		v := c.ll.Remove(c.ll.Back())
-		delete(c.cache, v.(*entry).key)
-	}
-	return nil
-}
-
-// Get returns key's value from the cache and updates the "recently used"-ness.
-func (c *LRUCache) Get(key Key) (interface{}, bool) {
-	if c.cache == nil {
-		return nil, false
-	}
-	if e, ok := c.cache[key]; ok {
-		c.ll.MoveToFront(e)
-		return e.Value.(*entry).value, true
-	}
-	return nil, false
-}
-
-// Contains checks if a key exists in cache without updating the recent-ness.
-func (c *LRUCache) Contains(key Key) bool {
-	if c.cache == nil {
-		return false
-	}
-	_, ok := c.cache[key]
-	return ok
-}
-
-// Remove removes a key from the cache.
-func (c *LRUCache) Remove(key Key) interface{} {
-	if c.cache == nil {
-		return nil
-	}
-	if e, ok := c.cache[key]; ok {
-		c.ll.Remove(e)
-		delete(c.cache, key)
-		return e.Value.(*entry).value
-	}
-	return nil
-}
-
-// Len returns the number of items in the cache.
-func (c *LRUCache) Len() int {
-	if c.cache == nil {
-		return 0
-	}
-	return c.ll.Len()
-}
-
-// Clear clears all cache entries.
-func (c *LRUCache) Clear() {
-	c.ll = nil
-	c.cache = nil
-}
diff --git a/lib/cache/cache_test.go b/lib/cache/cache_test.go
deleted file mode 100644
index 389a530..0000000
--- a/lib/cache/cache_test.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2018 The Fuchsia 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 cache
-
-import (
-	"fmt"
-	"testing"
-)
-
-func init() {
-}
-
-var testCases = []struct {
-	key string
-	val string
-}{
-	{"foo", "aaa"},
-	{"bar", "bbb"},
-	{"baz", "ccc"},
-}
-
-func TestAdd(t *testing.T) {
-	var cache Cache = &LRUCache{}
-	for _, tc := range testCases {
-		t.Run(fmt.Sprintf("add %s", tc.key), func(t *testing.T) {
-			cache.Add(tc.key, tc.val)
-			if val, ok := cache.Get(tc.key); !ok {
-				t.Fatalf("not found")
-			} else if ok && val != tc.val {
-				t.Fatalf("got %v; want %v", tc.val, val)
-			}
-		})
-	}
-}
-
-func TestRemove(t *testing.T) {
-	var cache Cache = &LRUCache{}
-	for _, tc := range testCases {
-		cache.Add(tc.key, tc.val)
-	}
-	for _, tc := range testCases {
-		t.Run(fmt.Sprintf("remove %s", tc.key), func(t *testing.T) {
-			cache.Remove(tc.key)
-			if _, ok := cache.Get(tc.key); ok {
-				t.Fatalf("not removed")
-			}
-		})
-	}
-}
diff --git a/lib/color/color.go b/lib/color/color.go
deleted file mode 100644
index 4a5558e..0000000
--- a/lib/color/color.go
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2018 The Fuchsia 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 color provides functions for printing in different colors.
-package color
-
-import (
-	"fmt"
-	"os"
-
-	"go.fuchsia.dev/tools/lib/isatty"
-)
-
-// Colorfn is a function type that takes a formatted string and returns it in a certain color.
-type Colorfn func(format string, a ...interface{}) string
-
-const (
-	escape = "\033["
-	clear  = escape + "0m"
-)
-
-// ColorCode represents the int used for coloring formatted strings in a certain color.
-type ColorCode int
-
-// Foreground text colors
-const (
-	BlackFg ColorCode = iota + 30
-	RedFg
-	GreenFg
-	YellowFg
-	BlueFg
-	MagentaFg
-	CyanFg
-	WhiteFg
-	DefaultFg
-)
-
-// Color provides an interface for a color or monochrome type that will be returned by NewColor()
-// based on whether coloring is enabled or not.
-type Color interface {
-	Black(format string, a ...interface{}) string
-	Red(format string, a ...interface{}) string
-	Green(format string, a ...interface{}) string
-	Yellow(format string, a ...interface{}) string
-	Blue(format string, a ...interface{}) string
-	Magenta(format string, a ...interface{}) string
-	Cyan(format string, a ...interface{}) string
-	White(format string, a ...interface{}) string
-	DefaultColor(format string, a ...interface{}) string
-	WithColor(code ColorCode, format string, a ...interface{}) string
-	Enabled() bool
-}
-
-type color struct{}
-
-func (color) Black(format string, a ...interface{}) string { return colorString(BlackFg, format, a...) }
-func (color) Red(format string, a ...interface{}) string   { return colorString(RedFg, format, a...) }
-func (color) Green(format string, a ...interface{}) string { return colorString(GreenFg, format, a...) }
-func (color) Yellow(format string, a ...interface{}) string {
-	return colorString(YellowFg, format, a...)
-}
-func (color) Blue(format string, a ...interface{}) string { return colorString(BlueFg, format, a...) }
-func (color) Magenta(format string, a ...interface{}) string {
-	return colorString(MagentaFg, format, a...)
-}
-func (color) Cyan(format string, a ...interface{}) string  { return colorString(CyanFg, format, a...) }
-func (color) White(format string, a ...interface{}) string { return colorString(WhiteFg, format, a...) }
-func (color) DefaultColor(format string, a ...interface{}) string {
-	return colorString(DefaultFg, format, a...)
-}
-func (color) WithColor(code ColorCode, format string, a ...interface{}) string {
-	return colorString(code, format, a...)
-}
-func (color) Enabled() bool {
-	return true
-}
-
-func colorString(c ColorCode, format string, a ...interface{}) string {
-	if c == DefaultFg {
-		return fmt.Sprintf(format, a...)
-	}
-	return fmt.Sprintf("%v%vm%v%v", escape, c, fmt.Sprintf(format, a...), clear)
-}
-
-type monochrome struct{}
-
-func (monochrome) Black(format string, a ...interface{}) string   { return fmt.Sprintf(format, a...) }
-func (monochrome) Red(format string, a ...interface{}) string     { return fmt.Sprintf(format, a...) }
-func (monochrome) Green(format string, a ...interface{}) string   { return fmt.Sprintf(format, a...) }
-func (monochrome) Yellow(format string, a ...interface{}) string  { return fmt.Sprintf(format, a...) }
-func (monochrome) Blue(format string, a ...interface{}) string    { return fmt.Sprintf(format, a...) }
-func (monochrome) Magenta(format string, a ...interface{}) string { return fmt.Sprintf(format, a...) }
-func (monochrome) Cyan(format string, a ...interface{}) string    { return fmt.Sprintf(format, a...) }
-func (monochrome) White(format string, a ...interface{}) string   { return fmt.Sprintf(format, a...) }
-func (monochrome) DefaultColor(format string, a ...interface{}) string {
-	return fmt.Sprintf(format, a...)
-}
-func (monochrome) WithColor(_ ColorCode, format string, a ...interface{}) string {
-	return fmt.Sprintf(format, a...)
-}
-func (monochrome) Enabled() bool {
-	return false
-}
-
-// EnableColor represents whether or not to return colored strings.
-type EnableColor int
-
-const (
-	ColorNever EnableColor = iota
-	ColorAuto
-	ColorAlways
-)
-
-func isColorAvailable() bool {
-	term := os.Getenv("TERM")
-	switch term {
-	case "dumb", "":
-		return false
-	}
-	return isatty.IsTerminal()
-}
-
-// NewColor returns a color or monochrome type depending on the value of enableColor.
-// A monochrome type will always return the string in the default color.
-func NewColor(enableColor EnableColor) Color {
-	ec := enableColor != ColorNever
-	if enableColor == ColorAuto {
-		ec = isColorAvailable()
-	}
-	if ec {
-		return color{}
-	} else {
-		return monochrome{}
-	}
-}
-
-// String returns the string value of the EnableColor type.
-func (ec *EnableColor) String() string {
-	switch *ec {
-	case ColorNever:
-		return "never"
-	case ColorAuto:
-		return "auto"
-	case ColorAlways:
-		return "always"
-	}
-	return ""
-}
-
-// Set sets the EnableColor type based on the string value.
-func (ec *EnableColor) Set(s string) error {
-	switch s {
-	case "never":
-		*ec = ColorNever
-	case "auto":
-		*ec = ColorAuto
-	case "always":
-		*ec = ColorAlways
-	default:
-		return fmt.Errorf("%s is not a valid color value", s)
-	}
-	return nil
-}
diff --git a/lib/color/color_test.go b/lib/color/color_test.go
deleted file mode 100644
index c643d07..0000000
--- a/lib/color/color_test.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2018 The Fuchsia 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 color
-
-import (
-	"fmt"
-	"testing"
-)
-
-func TestColors(t *testing.T) {
-	c := NewColor(ColorAlways)
-	colorFns := []Colorfn{c.Black, c.Red, c.Green, c.Yellow, c.Magenta, c.Cyan, c.White, c.DefaultColor}
-	colorCodes := []ColorCode{BlackFg, RedFg, GreenFg, YellowFg, MagentaFg, CyanFg, WhiteFg, DefaultFg}
-
-	for i, colorCode := range colorCodes {
-		fn := colorFns[i]
-		str := fmt.Sprintf("test string: %d", i)
-		coloredStr := fn("test string: %d", i)
-		withColorStr := c.WithColor(colorCode, "test string: %d", i)
-		expectedStr := fmt.Sprintf("%v%vm%v%v", escape, colorCode, str, clear)
-		if colorCode == DefaultFg {
-			expectedStr = str
-		}
-		if coloredStr != expectedStr {
-			t.Fatalf("Expected string:%v\n, got: %v", expectedStr, coloredStr)
-		}
-		if withColorStr != expectedStr {
-			t.Fatalf("Expected string:%v\n, got: %v", expectedStr, withColorStr)
-		}
-	}
-}
-
-func TestColorsDisabled(t *testing.T) {
-	c := NewColor(ColorNever)
-	colorFns := []Colorfn{c.Black, c.Red, c.Green, c.Yellow, c.Magenta, c.Cyan, c.White, c.DefaultColor}
-	colorCodes := []ColorCode{BlackFg, RedFg, GreenFg, YellowFg, MagentaFg, CyanFg, WhiteFg, DefaultFg}
-
-	for i, colorCode := range colorCodes {
-		fn := colorFns[i]
-		str := fmt.Sprintf("test string: %d", i)
-		coloredStr := fn("test string: %d", i)
-		withColorStr := c.WithColor(colorCode, "test string: %d", i)
-		if coloredStr != str {
-			t.Fatalf("Expected string:%v\n, got: %v", str, coloredStr)
-		}
-		if withColorStr != str {
-			t.Fatalf("Expected string:%v\n, got: %v", str, withColorStr)
-		}
-	}
-}
diff --git a/lib/command/cancelable.go b/lib/command/cancelable.go
deleted file mode 100644
index 47e10fe..0000000
--- a/lib/command/cancelable.go
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2019 The Fuchsia 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 command
-
-import (
-	"context"
-	"flag"
-	"log"
-
-	"github.com/google/subcommands"
-)
-
-// Disposer is an object that performs tear down. This is used by Cancelable to gracefully
-// terminate a delegate Command before exiting.
-type Disposer interface {
-	Dispose()
-}
-
-// Cancelable wraps a subcommands.Command so that it is canceled if its input execution
-// context emits a Done event before execution is finished. If the given Command
-// implements the Disposer interface, Dispose is called before the program exits.
-func Cancelable(sub subcommands.Command) subcommands.Command {
-	return &cancelable{sub}
-}
-
-// cancelable wraps a subcommands.Command so that it is canceled if the input execution
-// context emits a Done event before execution is finished. cancelable "masquerades" as
-// the underlying Command. Example Registration:
-//
-//   subcommands.Register(command.Cancelable(&OtherSubcommand{}))
-type cancelable struct {
-	sub subcommands.Command
-}
-
-// Name forwards to the underlying Command.
-func (cmd *cancelable) Name() string {
-	return cmd.sub.Name()
-}
-
-// Usage forwards to the underlying Command.
-func (cmd *cancelable) Usage() string {
-	return cmd.sub.Usage()
-}
-
-// Synopsis forwards to the underlying Command.
-func (cmd *cancelable) Synopsis() string {
-	return cmd.sub.Synopsis()
-}
-
-// SetFlags forwards to the underlying Command.
-func (cmd *cancelable) SetFlags(f *flag.FlagSet) {
-	cmd.sub.SetFlags(f)
-}
-
-// Execute runs the underlying Command in a goroutine. If the input context is canceled
-// before execution finishes, execution is canceled and the context's error is logged.
-func (cmd *cancelable) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus {
-	status := make(chan subcommands.ExitStatus)
-	go func() {
-		status <- cmd.sub.Execute(ctx, f, args...)
-	}()
-	select {
-	case <-ctx.Done():
-		if d, ok := cmd.sub.(Disposer); ok {
-			d.Dispose()
-		}
-		log.Println(ctx.Err())
-		return subcommands.ExitFailure
-	case s := <-status:
-		close(status)
-		return s
-	}
-}
diff --git a/lib/command/cancelable_test.go b/lib/command/cancelable_test.go
deleted file mode 100644
index 22b14c7..0000000
--- a/lib/command/cancelable_test.go
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2019 The Fuchsia 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 command_test
-
-import (
-	"context"
-	"flag"
-	"testing"
-	"time"
-
-	"github.com/google/subcommands"
-	"go.fuchsia.dev/tools/lib/command"
-)
-
-func TestCancelableExecute(t *testing.T) {
-	tests := []struct {
-		// The name of this test case
-		name string
-
-		// Whether to cancel the execution context early.
-		cancelContextEarly bool
-
-		// Whether the underlying subcommand is expected to finish
-		expectToFinish bool
-	}{
-		{"when context is canceled early", true, false},
-		{"when context is never canceled", false, true},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			tcmd := &TestCommand{}
-			cmd := command.Cancelable(tcmd)
-			ctx, cancel := context.WithCancel(context.Background())
-			if tt.cancelContextEarly {
-				cancel()
-				cmd.Execute(ctx, flag.NewFlagSet("test", flag.ContinueOnError))
-			} else {
-				cmd.Execute(ctx, flag.NewFlagSet("test", flag.ContinueOnError))
-				cancel()
-			}
-
-			if tcmd.DidFinish && !tt.expectToFinish {
-				t.Errorf("wanted command to exit early but it finished")
-			} else if !tcmd.DidFinish && tt.expectToFinish {
-				t.Errorf("wanted command to finish but it exited early")
-			}
-		})
-	}
-}
-
-// TestCancelableDelegation verifies that Cancelable() returns a subcommand.Command that
-// delegates to the input subcommand.Command.
-func TestCancelableDelegation(t *testing.T) {
-	expectEq := func(t *testing.T, name, expected, actual string) {
-		if expected != actual {
-			t.Errorf("wanted %s to be %q but got %q", name, expected, actual)
-		}
-	}
-	cmd := command.Cancelable(&TestCommand{
-		name:     "test_name",
-		usage:    "test_usage",
-		synopsis: "test_synopsis",
-	})
-	expectEq(t, "Name", "test_name", cmd.Name())
-	expectEq(t, "Usage", "test_usage", cmd.Usage())
-	expectEq(t, "Synopsis", "test_synopsis", cmd.Synopsis())
-}
-
-type TestCommand struct {
-	name, usage, synopsis string
-	DidFinish             bool
-}
-
-func (cmd *TestCommand) Name() string             { return cmd.name }
-func (cmd *TestCommand) Usage() string            { return cmd.usage }
-func (cmd *TestCommand) Synopsis() string         { return cmd.synopsis }
-func (cmd *TestCommand) SetFlags(f *flag.FlagSet) {}
-func (cmd *TestCommand) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus {
-	time.Sleep(time.Millisecond)
-	cmd.DidFinish = true
-	return subcommands.ExitSuccess
-}
diff --git a/lib/command/doc.go b/lib/command/doc.go
deleted file mode 100644
index bc6b9bf..0000000
--- a/lib/command/doc.go
+++ /dev/null
@@ -1,6 +0,0 @@
-// Copyright 2019 The Fuchsia 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 command defines common code for writing Fuchsia command line tools.
-package command
diff --git a/lib/command/flags.go b/lib/command/flags.go
deleted file mode 100644
index 8647927..0000000
--- a/lib/command/flags.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2018 The Fuchsia 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 command
-
-import (
-	"strings"
-)
-
-// StringsFlag implements flag.Value so it may be treated as a flag type.
-type StringsFlag []string
-
-// Set implements flag.Value.Set.
-func (s *StringsFlag) Set(val string) error {
-	*s = append(*s, val)
-	return nil
-}
-
-// String implements flag.Value.String.
-func (s *StringsFlag) String() string {
-	if s == nil {
-		return ""
-	}
-	return strings.Join([]string(*s), ", ")
-}
diff --git a/lib/command/signals.go b/lib/command/signals.go
deleted file mode 100644
index 298517c..0000000
--- a/lib/command/signals.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2019 The Fuchsia 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 command
-
-import (
-	"context"
-	"os"
-	"os/signal"
-)
-
-// CancelOnSignals returns a Context that emits a Done event when any of the input signals
-// are received, assuming those signals can be handled by the current process.
-func CancelOnSignals(ctx context.Context, sigs ...os.Signal) context.Context {
-	ctx, cancel := context.WithCancel(ctx)
-	signals := make(chan os.Signal)
-	signal.Notify(signals, sigs...)
-	go func() {
-		select {
-		case s := <-signals:
-			if s != nil {
-				cancel()
-				close(signals)
-			}
-		}
-	}()
-	return ctx
-}
diff --git a/lib/isatty/isatty.go b/lib/isatty/isatty.go
deleted file mode 100644
index a468ae0..0000000
--- a/lib/isatty/isatty.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2018 The Fuchsia 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 linux darwin
-
-package isatty
-
-import (
-	"os"
-	"syscall"
-	"unsafe"
-)
-
-// IsTerminal returns whether the system is in a terminal.
-func IsTerminal() bool {
-	var termios syscall.Termios
-	_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, os.Stdout.Fd(), ioctlTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
-	return err == 0
-}
diff --git a/lib/isatty/isatty_darwin.go b/lib/isatty/isatty_darwin.go
deleted file mode 100644
index e044c21..0000000
--- a/lib/isatty/isatty_darwin.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2018 The Fuchsia 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 darwin
-
-package isatty
-
-import "syscall"
-
-const ioctlTermios = syscall.TIOCGETA
diff --git a/lib/isatty/isatty_linux.go b/lib/isatty/isatty_linux.go
deleted file mode 100644
index f510507..0000000
--- a/lib/isatty/isatty_linux.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2018 The Fuchsia 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 linux
-
-package isatty
-
-import "syscall"
-
-const ioctlTermios = syscall.TCGETS
diff --git a/lib/logger/logger.go b/lib/logger/logger.go
deleted file mode 100644
index e7ada50..0000000
--- a/lib/logger/logger.go
+++ /dev/null
@@ -1,206 +0,0 @@
-// Copyright 2018 The Fuchsia 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 logger provides methods for logging with different levels.
-package logger
-
-import (
-	"context"
-	"fmt"
-	"io"
-	goLog "log"
-	"os"
-
-	"go.fuchsia.dev/tools/lib/color"
-)
-
-type globalLoggerKeyType struct{}
-
-// WithLogger returns the context with its logger set as the provided Logger.
-func WithLogger(ctx context.Context, logger *Logger) context.Context {
-	return context.WithValue(ctx, globalLoggerKeyType{}, logger)
-}
-
-// Logger represents a specific LogLevel with a specified color and prefix.
-type Logger struct {
-	LoggerLevel   LogLevel
-	goLogger      *goLog.Logger
-	goErrorLogger *goLog.Logger
-	color         color.Color
-	prefix        string
-}
-
-// LogLevel represents different levels for logging depending on the amount of detail wanted.
-type LogLevel int
-
-const (
-	NoLogLevel LogLevel = iota
-	FatalLevel
-	ErrorLevel
-	WarningLevel
-	InfoLevel
-	DebugLevel
-	TraceLevel
-)
-
-// String returns the string representation of the LogLevel.
-func (l *LogLevel) String() string {
-	switch *l {
-	case NoLogLevel:
-		return "no"
-	case FatalLevel:
-		return "fatal"
-	case ErrorLevel:
-		return "error"
-	case WarningLevel:
-		return "warning"
-	case InfoLevel:
-		return "info"
-	case DebugLevel:
-		return "debug"
-	case TraceLevel:
-		return "trace"
-	}
-	return ""
-}
-
-// Set sets the LogLevel based on its string value.
-func (l *LogLevel) Set(s string) error {
-	switch s {
-	case "fatal":
-		*l = FatalLevel
-	case "error":
-		*l = ErrorLevel
-	case "warning":
-		*l = WarningLevel
-	case "info":
-		*l = InfoLevel
-	case "debug":
-		*l = DebugLevel
-	case "trace":
-		*l = TraceLevel
-	default:
-		return fmt.Errorf("%s is not a valid level", s)
-	}
-	return nil
-}
-
-// NewLogger creates a new logger instance. The loggerLevel variable sets the log level for the logger.
-// The color variable specifies the visual color of displayed log output.
-// The outWriter and errWriter variables set the destination to which non-error and error data will be written.
-// The prefix appears on the same line directly preceding any log data.
-func NewLogger(loggerLevel LogLevel, color color.Color, outWriter, errWriter io.Writer, prefix string) *Logger {
-	if outWriter == nil {
-		outWriter = os.Stdout
-	}
-	if errWriter == nil {
-		errWriter = os.Stderr
-	}
-	l := &Logger{
-		LoggerLevel:   loggerLevel,
-		goLogger:      goLog.New(outWriter, "", goLog.LstdFlags),
-		goErrorLogger: goLog.New(errWriter, "", goLog.LstdFlags),
-		color:         color,
-		prefix:        prefix,
-	}
-	return l
-}
-
-func (l *Logger) log(prefix, format string, a ...interface{}) {
-	l.goLogger.Printf("%s%s%s", l.prefix, prefix, fmt.Sprintf(format, a...))
-}
-
-// Logf logs the string based on the loglevel of the string and the LogLevel of the logger.
-func (l *Logger) Logf(loglevel LogLevel, format string, a ...interface{}) {
-	switch loglevel {
-	case InfoLevel:
-		l.Infof(format, a...)
-	case DebugLevel:
-		l.Debugf(format, a...)
-	case TraceLevel:
-		l.Tracef(format, a...)
-	case WarningLevel:
-		l.Warningf(format, a...)
-	case ErrorLevel:
-		l.Errorf(format, a...)
-	case FatalLevel:
-		l.Fatalf(format, a...)
-	default:
-		panic(fmt.Sprintf("Undefined loglevel: %v, log message: %s", loglevel, fmt.Sprintf(format, a...)))
-	}
-}
-
-func Logf(ctx context.Context, logLevel LogLevel, format string, a ...interface{}) {
-	if v, ok := ctx.Value(globalLoggerKeyType{}).(*Logger); ok && v != nil {
-		v.Logf(logLevel, format, a...)
-	} else {
-		goLog.Printf(format, a...)
-	}
-}
-
-// Infof logs the string if the logger is at least InfoLevel.
-func (l *Logger) Infof(format string, a ...interface{}) {
-	if l.LoggerLevel >= InfoLevel {
-		l.log("", format, a...)
-	}
-}
-
-func Infof(ctx context.Context, format string, a ...interface{}) {
-	Logf(ctx, InfoLevel, format, a...)
-}
-
-// Debugf logs the string if the logger is at least DebugLevel.
-func (l *Logger) Debugf(format string, a ...interface{}) {
-	if l.LoggerLevel >= DebugLevel {
-		l.log(l.color.Cyan("DEBUG: "), format, a...)
-	}
-}
-
-func Debugf(ctx context.Context, format string, a ...interface{}) {
-	Logf(ctx, DebugLevel, format, a...)
-}
-
-// Tracef logs the string if the logger is at least TraceLevel.
-func (l *Logger) Tracef(format string, a ...interface{}) {
-	if l.LoggerLevel >= TraceLevel {
-		l.log(l.color.Blue("TRACE: "), format, a...)
-	}
-}
-
-func Tracef(ctx context.Context, format string, a ...interface{}) {
-	Logf(ctx, TraceLevel, format, a...)
-}
-
-// Warningf logs the string if the logger is at least WarningLevel.
-func (l *Logger) Warningf(format string, a ...interface{}) {
-	if l.LoggerLevel >= WarningLevel {
-		l.log(l.color.Yellow("WARN: "), format, a...)
-	}
-}
-
-func Warningf(ctx context.Context, format string, a ...interface{}) {
-	Logf(ctx, WarningLevel, format, a...)
-}
-
-// Errorf logs the string if the logger is at least ErrorLevel.
-func (l *Logger) Errorf(format string, a ...interface{}) {
-	if l.LoggerLevel >= ErrorLevel {
-		l.goErrorLogger.Printf("%s%s%s", l.prefix, l.color.Red("ERROR: "), fmt.Sprintf(format, a...))
-	}
-}
-
-func Errorf(ctx context.Context, format string, a ...interface{}) {
-	Logf(ctx, ErrorLevel, format, a...)
-}
-
-// Fatalf logs the string if the logger is at least FatalLevel.
-func (l *Logger) Fatalf(format string, a ...interface{}) {
-	if l.LoggerLevel >= FatalLevel {
-		l.goErrorLogger.Fatalf("%s%s%s", l.prefix, l.color.Red("FATAL: "), fmt.Sprintf(format, a...))
-	}
-}
-
-func Fatalf(ctx context.Context, format string, a ...interface{}) {
-	Logf(ctx, FatalLevel, format, a...)
-}
diff --git a/lib/logger/logger_test.go b/lib/logger/logger_test.go
deleted file mode 100644
index 60ac5a8..0000000
--- a/lib/logger/logger_test.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2019 The Fuchsia 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 logger
-
-import (
-	"context"
-	goLog "log"
-	"os"
-	"testing"
-
-	"go.fuchsia.dev/tools/lib/color"
-)
-
-func TestWithContext(t *testing.T) {
-	logger := NewLogger(DebugLevel, color.NewColor(color.ColorAuto), os.Stdout, os.Stderr, "")
-	ctx := context.Background()
-	if v, ok := ctx.Value(globalLoggerKeyType{}).(*Logger); ok || v != nil {
-		t.Fatalf("Default context should not have globalLoggerKeyType. Expected: \nnil\n but got: \n%+v ", v)
-	}
-	ctx = WithLogger(ctx, logger)
-	if v, ok := ctx.Value(globalLoggerKeyType{}).(*Logger); !ok || v == nil {
-		t.Fatalf("Updated context should have globalLoggerKeyType, but got nil")
-	}
-
-}
-
-func TestNewLogger(t *testing.T) {
-	prefix := "testprefix "
-
-	logger := NewLogger(InfoLevel, color.NewColor(color.ColorAuto), nil, nil, prefix)
-	logFlags, errFlags := logger.goLogger.Flags(), logger.goErrorLogger.Flags()
-
-	if logFlags != goLog.LstdFlags || errFlags != goLog.LstdFlags {
-		t.Fatalf("New loggers should have the proper flags set for both standard and error logging. Expected: \n%+v and %+v\n but got: \n%+v and %+v", goLog.LstdFlags, goLog.LstdFlags, logFlags, errFlags)
-	}
-
-	logPrefix := logger.prefix
-	if logPrefix != prefix {
-		t.Fatalf("New loggers should use the specified prefix on creation. Expected: \n%+v\n but got: \n%+v", prefix, logPrefix)
-	}
-}
diff --git a/lib/retry/backoff.go b/lib/retry/backoff.go
deleted file mode 100644
index cfc163c..0000000
--- a/lib/retry/backoff.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2018 The Fuchsia 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 retry
-
-import (
-	"time"
-)
-
-// Stop indicates that no more retries should be made.
-const Stop time.Duration = -1
-
-type Backoff interface {
-	// Next gets the duration to wait before retrying the operation or |Stop|
-	// to indicate that no retries should be made.
-	Next() time.Duration
-
-	// Reset resets to initial state.
-	Reset()
-}
-
-// ZeroBackoff is a fixed policy whose back-off time is always zero, meaning
-// that the operation is retried immediately without waiting.
-type ZeroBackoff struct{}
-
-func (b *ZeroBackoff) Reset() {}
-
-func (b *ZeroBackoff) Next() time.Duration { return 0 }
-
-// ConstantBackoff is a fixed policy that always returns the same backoff delay.
-type ConstantBackoff struct {
-	interval time.Duration
-}
-
-func (b *ConstantBackoff) Reset() {}
-
-func (b *ConstantBackoff) Next() time.Duration { return b.interval }
-
-func NewConstantBackoff(d time.Duration) *ConstantBackoff {
-	return &ConstantBackoff{interval: d}
-}
-
-type maxTriesBackoff struct {
-	backOff  Backoff
-	maxTries uint64
-	numTries uint64
-}
-
-func (b *maxTriesBackoff) Next() time.Duration {
-	if b.maxTries > 0 {
-		if b.maxTries <= b.numTries {
-			return Stop
-		}
-		b.numTries++
-	}
-	return b.backOff.Next()
-}
-
-func (b *maxTriesBackoff) Reset() {
-	b.numTries = 0
-	b.backOff.Reset()
-}
-
-// WithMaxRetries wraps a back-off which stops after |max| retries.
-func WithMaxRetries(b Backoff, max uint64) Backoff {
-	return &maxTriesBackoff{backOff: b, maxTries: max}
-}
-
-type maxDurationBackoff struct {
-	backOff     Backoff
-	maxDuration time.Duration
-	startTime   time.Time
-	c           clock
-}
-
-func (b *maxDurationBackoff) Next() time.Duration {
-	if b.c.Since(b.startTime) < b.maxDuration {
-		return b.backOff.Next()
-	}
-	return Stop
-}
-
-func (b *maxDurationBackoff) Reset() {
-	b.startTime = b.c.Now()
-	b.backOff.Reset()
-}
-
-// WithMaxDuration wraps a back-off which stops attempting retries after |max|
-// duration.
-func WithMaxDuration(b Backoff, max time.Duration) Backoff {
-	return &maxDurationBackoff{backOff: b, maxDuration: max, c: &systemClock{}}
-}
diff --git a/lib/retry/backoff_test.go b/lib/retry/backoff_test.go
deleted file mode 100644
index d55780c..0000000
--- a/lib/retry/backoff_test.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2018 The Fuchsia 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 retry
-
-import (
-	"testing"
-	"time"
-)
-
-func TestZeroBackoff(t *testing.T) {
-	backoff := ZeroBackoff{}
-	backoff.Reset()
-	if backoff.Next() != 0 {
-		t.Error("invalid interval")
-	}
-}
-
-func TestConstantBackoff(t *testing.T) {
-	backoff := NewConstantBackoff(time.Second)
-	backoff.Reset()
-	if backoff.Next() != time.Second {
-		t.Error("invalid interval")
-	}
-}
-
-func TestMaxTriesBackoff(t *testing.T) {
-	backoff := WithMaxRetries(&ZeroBackoff{}, 10)
-	backoff.Reset()
-	for i := 0; i < 10; i++ {
-		if backoff.Next() != 0 {
-			t.Error("invalid interval")
-		}
-	}
-	if backoff.Next() != Stop {
-		t.Error("did not stop")
-	}
-}
-
-func TestMaxDurationBackoff(t *testing.T) {
-	c := &fakeClock{t: time.Now()}
-	backoff := &maxDurationBackoff{backOff: &ZeroBackoff{}, maxDuration: 10 * time.Second, c: c}
-	backoff.Reset()
-	if backoff.Next() != 0 {
-		t.Error("invalid interval")
-	}
-
-	c.Tick(9 * time.Second)
-	if backoff.Next() != 0 {
-		t.Error("invalid interval")
-	}
-
-	c.Tick(1 * time.Second)
-	if backoff.Next() != Stop {
-		t.Error("did not stop")
-	}
-}
diff --git a/lib/retry/clock.go b/lib/retry/clock.go
deleted file mode 100644
index f062574..0000000
--- a/lib/retry/clock.go
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2019 The Fuchsia 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 retry
-
-import "time"
-
-type clock interface {
-	Now() time.Time
-	Since(time.Time) time.Duration
-}
-
-type fakeClock struct {
-	t time.Time
-}
-
-func (c fakeClock) Now() time.Time {
-	return c.t
-}
-
-func (c fakeClock) Since(startTime time.Time) time.Duration {
-	return c.t.Sub(startTime)
-}
-
-func (c *fakeClock) Tick(d time.Duration) {
-	c.t = c.t.Add(d)
-}
-
-type systemClock struct{}
-
-func (c systemClock) Now() time.Time {
-	return time.Now()
-}
-
-func (c systemClock) Since(startTime time.Time) time.Duration {
-	return time.Since(startTime)
-}
diff --git a/lib/retry/retry.go b/lib/retry/retry.go
deleted file mode 100644
index 43e6d2a..0000000
--- a/lib/retry/retry.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2018 The Fuchsia 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 retry
-
-import (
-	"context"
-	"time"
-)
-
-// Retry the operation using the provided back-off policy until it succeeds,
-// or the context is cancelled.
-func Retry(ctx context.Context, b Backoff, f func() error, c chan<- error) error {
-	var err error
-	var next time.Duration
-
-	b.Reset()
-	for {
-		if err = f(); err == nil {
-			break
-		}
-
-		if next = b.Next(); next == Stop {
-			return err
-		}
-
-		timer := time.NewTimer(next)
-
-		select {
-		case <-ctx.Done():
-			timer.Stop()
-			return err
-		case <-timer.C:
-			if c != nil {
-				c <- err
-			}
-		}
-	}
-
-	return err
-}
diff --git a/lib/retry/retry_test.go b/lib/retry/retry_test.go
deleted file mode 100644
index fef9b7c..0000000
--- a/lib/retry/retry_test.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2018 The Fuchsia 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 retry
-
-import (
-	"context"
-	"fmt"
-	"testing"
-)
-
-func TestRetry(t *testing.T) {
-	const tries = 5
-	t.Run("error", func(t *testing.T) {
-		var i int
-		err := Retry(context.Background(), &ZeroBackoff{}, func() error {
-			i++
-			if i == tries {
-				return nil
-			}
-			return fmt.Errorf("try %d", i)
-		}, nil)
-
-		if err != nil {
-			t.Errorf("unexpected error: %v", err)
-		}
-		if i != tries {
-			t.Errorf("invalid number of tries: %d", i)
-		}
-	})
-	t.Run("cancel", func(t *testing.T) {
-		var i int
-		ctx, cancel := context.WithCancel(context.Background())
-		err := Retry(ctx, &ZeroBackoff{}, func() error {
-			i++
-			if i == tries {
-				cancel()
-			}
-			return fmt.Errorf("try %d", i)
-		}, nil)
-
-		if err == nil {
-			t.Error("error is nil")
-		}
-		if err.Error() != "try 5" {
-			t.Errorf("unexpected error: %v", err)
-		}
-		if i != tries {
-			t.Errorf("invalid number of tries: %d", i)
-		}
-	})
-}
diff --git a/lib/runner/ssh_runner.go b/lib/runner/ssh_runner.go
deleted file mode 100644
index 1917ce5..0000000
--- a/lib/runner/ssh_runner.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2019 The Fuchsia 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 runner
-
-import (
-	"context"
-	"io"
-	"strings"
-
-	"golang.org/x/crypto/ssh"
-)
-
-// SSHRunner runs commands over SSH.
-type SSHRunner struct {
-	Session *ssh.Session
-}
-
-// Run executes the given command.
-func (r *SSHRunner) Run(ctx context.Context, command []string, stdout io.Writer, stderr io.Writer) error {
-	r.Session.Stdout = stdout
-	r.Session.Stderr = stderr
-
-	// TERM-dumb, to avoid a loop fetching a cursor position.
-	r.Session.Setenv("TERM", "dumb")
-	cmd := strings.Join(command, " ")
-
-	if err := r.Session.Start(cmd); err != nil {
-		return err
-	}
-
-	done := make(chan error)
-	go func() {
-		done <- r.Session.Wait()
-	}()
-
-	select {
-	case err := <-done:
-		return err
-	case <-ctx.Done():
-		r.Session.Signal(ssh.SIGKILL)
-	}
-
-	return nil
-}
diff --git a/lib/runner/subprocess_runner.go b/lib/runner/subprocess_runner.go
deleted file mode 100644
index 4bc991c..0000000
--- a/lib/runner/subprocess_runner.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2019 The Fuchsia 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 runner provides implementations for running commands in different environments.
-package runner
-
-import (
-	"context"
-	"io"
-	"os/exec"
-	"syscall"
-
-	"go.fuchsia.dev/tools/lib/logger"
-)
-
-// SubprocessRunner is a Runner that runs commands as local subprocesses.
-type SubprocessRunner struct {
-	// Dir is the working directory of the subprocesses; if unspecified, that
-	// of the current process will be used.
-	Dir string
-
-	// Env is the environment of the subprocess, following the usual convention of a list of
-	// strings of the form "<environment variable name>=<value>".
-	Env []string
-}
-
-// Run runs a command until completion or until a context is canceled, in
-// which case the subprocess is killed so that no subprocesses it spun up are
-// orphaned.
-func (r *SubprocessRunner) Run(ctx context.Context, command []string, stdout io.Writer, stderr io.Writer) error {
-	cmd := exec.Cmd{
-		Path:        command[0],
-		Args:        command,
-		Stdout:      stdout,
-		Stderr:      stderr,
-		Dir:         r.Dir,
-		Env:         r.Env,
-		SysProcAttr: &syscall.SysProcAttr{Setpgid: true},
-	}
-	logger.Infof(ctx, "environment of subprocess:\n%v", cmd.Env)
-	logger.Infof(ctx, "starting:\n%v", cmd.Args)
-	if err := cmd.Start(); err != nil {
-		return err
-	}
-	done := make(chan error)
-	go func() {
-		done <- cmd.Wait()
-	}()
-	select {
-	case err := <-done:
-		return err
-	case <-ctx.Done():
-		syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
-		return ctx.Err()
-	}
-}
diff --git a/lib/runner/subprocess_runner_test.go b/lib/runner/subprocess_runner_test.go
deleted file mode 100644
index b322436..0000000
--- a/lib/runner/subprocess_runner_test.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2019 The Fuchsia 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 runner
-
-import (
-	"bytes"
-	"context"
-	"fmt"
-	"strings"
-	"testing"
-	"time"
-)
-
-const (
-	skipMessage      = "runner tests are meant for local testing only"
-	defaultIOTimeout = 100 * time.Millisecond
-)
-
-func TestSubprocessRunner(t *testing.T) {
-	t.Skip(skipMessage)
-
-	t.Run("Run", func(t *testing.T) {
-		t.Run("should execute a commmand", func(t *testing.T) {
-			r := SubprocessRunner{}
-			message := "Hello, World!"
-			command := []string{"/bin/echo", message}
-
-			stdout := new(bytes.Buffer)
-			stderr := new(bytes.Buffer)
-			if err := r.Run(context.Background(), command, stdout, stderr); err != nil {
-				t.Fatalf("failed to run test. Got an error %v", err)
-			}
-
-			stdoutS := strings.TrimSpace(stdout.String())
-			if stdoutS != "Hello, World!" {
-				t.Fatalf("expected output '%s', but got %s", message, stdoutS)
-			}
-
-			stderrS := strings.TrimSpace(stderr.String())
-			if stderrS != "" {
-				t.Fatalf("expected empty stderr, but got %s", stderrS)
-			}
-		})
-
-		t.Run("should error if the context Completes before the commmand", func(t *testing.T) {
-			ctx, cancel := context.WithCancel(context.Background())
-			cancel()
-			r := SubprocessRunner{}
-			command := []string{"/bin/sleep", "5"}
-
-			stdout := new(bytes.Buffer)
-			stderr := new(bytes.Buffer)
-
-			err := r.Run(ctx, command, stdout, stderr)
-			stdoutS := strings.TrimSpace(stdout.String())
-			stderrS := strings.TrimSpace(stderr.String())
-
-			if err == nil {
-				t.Fatal(strings.Join([]string{
-					"expected command to terminate early but it completed:",
-					fmt.Sprintf("(stdout): %s\n", stdoutS),
-					fmt.Sprintf("(stderr): %s\n", stderrS),
-				}, "\n"))
-			}
-		})
-
-		t.Run("should return an error if the command fails", func(t *testing.T) {
-			r := SubprocessRunner{}
-			command := []string{"not_a_command_12345"}
-
-			stdout := new(bytes.Buffer)
-			stderr := new(bytes.Buffer)
-
-			err := r.Run(context.Background(), command, stdout, stderr)
-			stdoutS := strings.TrimSpace(stdout.String())
-			stderrS := strings.TrimSpace(stderr.String())
-
-			if err == nil {
-				t.Fatal(strings.Join([]string{
-					"expected command to terminate early but it completed:",
-					fmt.Sprintf("(stdout): %s\n", stdoutS),
-					fmt.Sprintf("(stderr): %s\n", stderrS),
-				}, "\n"))
-			}
-		})
-	})
-
-}
diff --git a/lib/tarutil/tar.go b/lib/tarutil/tar.go
deleted file mode 100644
index 3abe83b..0000000
--- a/lib/tarutil/tar.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2019 The Fuchsia 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 tarutil provides methods for creating tar packages.
-package tarutil
-
-import (
-	"archive/tar"
-	"io"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-)
-
-// TarDirectory archives the given directory.
-func TarDirectory(tw *tar.Writer, dir string) error {
-	return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
-		if err != nil {
-			return err
-		}
-		if info.IsDir() {
-			return nil
-		}
-
-		hdr, err := tar.FileInfoHeader(info, path)
-		if err != nil {
-			return err
-		}
-		hdr.Name = path[len(dir)+1:]
-		if err := tw.WriteHeader(hdr); err != nil {
-			return err
-		}
-		fi, err := os.Open(path)
-		if err != nil {
-			return err
-		}
-		_, err = io.Copy(tw, fi)
-		return err
-	})
-}
-
-// TarBuffer writes the given bytes to a given path within an archive.
-func TarBuffer(tw *tar.Writer, buf []byte, path string) error {
-	hdr := &tar.Header{
-		Name: path,
-		Size: int64(len(buf)),
-		Mode: 0666,
-	}
-	if err := tw.WriteHeader(hdr); err != nil {
-		return err
-	}
-	_, err := tw.Write(buf)
-	return err
-}
-
-// TarReader writes data from the given Reader to the given tar.Writer.
-func TarReader(tw *tar.Writer, r io.Reader, path string) error {
-	bytes, err := ioutil.ReadAll(r)
-	if err != nil {
-		return err
-	}
-	return TarBuffer(tw, bytes, path)
-}
diff --git a/lib/tarutil/tar_test.go b/lib/tarutil/tar_test.go
deleted file mode 100644
index 5e2b5d0..0000000
--- a/lib/tarutil/tar_test.go
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2019 The Fuchsia 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 tarutil_test
-
-import (
-	"archive/tar"
-	"bytes"
-	"fmt"
-	"io"
-	"reflect"
-	"testing"
-
-	"go.fuchsia.dev/tools/lib/tarutil"
-)
-
-func TestTarBuffer(t *testing.T) {
-	type entry struct {
-		name, data string
-	}
-
-	tests := []struct {
-		// A name for this test case.
-		name string
-
-		// The input tarball.
-		input []entry
-
-		// The expected contents of the archive written by WriteTo.
-		output map[string]string
-	}{
-		{
-			name:   "should handle an empty buffer",
-			input:  []entry{{"", ""}},
-			output: map[string]string{"": ""},
-		},
-		{
-			name:  "should handle a non-empty buffer",
-			input: []entry{{"a", string("a data")}},
-			output: map[string]string{
-				"a": string("a data"),
-			},
-		},
-		{
-			name: "should handle multiple non-empty buffers",
-			input: []entry{
-				{"a", string("a data")},
-				{"b", string("b data")},
-			},
-			output: map[string]string{
-				"a": string("a data"),
-				"b": string("b data"),
-			},
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			var buf bytes.Buffer
-			tw := tar.NewWriter(&buf)
-			for _, ent := range tt.input {
-				tarutil.TarBuffer(tw, []byte(ent.data), ent.name)
-			}
-			actual, err := readTar(&buf)
-			if err != nil {
-				t.Errorf("failed to read tar archive: %v", err)
-				return
-			}
-			expected := tt.output
-			if !reflect.DeepEqual(actual, expected) {
-				t.Errorf("got:\n\n%v\n\nwanted:\n\n%v\n\n", actual, expected)
-			}
-		})
-	}
-
-}
-
-// Helper function to read data from a gzipped tar archive. The output maps each header's
-// name within the archive to its data.
-func readTar(r io.Reader) (map[string]string, error) {
-	tr := tar.NewReader(r)
-	output := make(map[string]string)
-	for {
-		hdr, err := tr.Next()
-		if err == io.EOF {
-			break // End of archive.
-		}
-		if err != nil {
-			return nil, fmt.Errorf("reading tarball failed, %v", err)
-
-		}
-		data := make([]byte, hdr.Size)
-		if _, err := tr.Read(data); err != nil && err != io.EOF {
-			return nil, fmt.Errorf("reading tarball data failed, %v", err)
-		}
-		output[hdr.Name] = string(data)
-	}
-
-	return output, nil
-}
diff --git a/manifest b/manifest
deleted file mode 100644
index 32733a1..0000000
--- a/manifest
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<manifest>
-  <projects>
-    <project name="tools"
-             path="go/src/go.fuchsia.dev/tools"
-             remote="https://fuchsia.googlesource.com/tools"
-             gerrithost="https://fuchsia-review.googlesource.com"/>
-  </projects>
-</manifest>
diff --git a/net/dev_finder/cmd/.gitignore b/net/dev_finder/cmd/.gitignore
deleted file mode 100644
index f9cecca..0000000
--- a/net/dev_finder/cmd/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/dev_finder
diff --git a/net/dev_finder/cmd/common.go b/net/dev_finder/cmd/common.go
deleted file mode 100644
index ac60e83..0000000
--- a/net/dev_finder/cmd/common.go
+++ /dev/null
@@ -1,267 +0,0 @@
-// Copyright 2018 The Fuchsia 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 (
-	"context"
-	"encoding/json"
-	"errors"
-	"flag"
-	"fmt"
-	"io"
-	"log"
-	"net"
-	"os"
-	"sort"
-	"strconv"
-	"strings"
-	"time"
-
-	"go.fuchsia.dev/tools/net/mdns"
-)
-
-type mDNSResponse struct {
-	rxIface  net.Interface
-	devAddr  net.Addr
-	rxPacket mdns.Packet
-}
-
-func (m *mDNSResponse) getReceiveIP() (net.IP, error) {
-	if unicastAddrs, err := m.rxIface.Addrs(); err != nil {
-		return nil, err
-	} else {
-		for _, addr := range unicastAddrs {
-			var ip net.IP
-			switch v := addr.(type) {
-			case *net.IPNet:
-				ip = v.IP
-			case *net.IPAddr:
-				ip = v.IP
-			}
-			if ip == nil || ip.To4() == nil {
-				continue
-			}
-			return ip, nil
-		}
-	}
-	return nil, fmt.Errorf("no IPv4 unicast addresses found on iface %v", m.rxIface)
-}
-
-type mDNSHandler func(mDNSResponse, bool, chan<- *fuchsiaDevice, chan<- error)
-
-type mdnsInterface interface {
-	AddHandler(f func(net.Interface, net.Addr, mdns.Packet))
-	AddWarningHandler(f func(net.Addr, error))
-	AddErrorHandler(f func(error))
-	SendTo(packet mdns.Packet, dst *net.UDPAddr) error
-	Send(packet mdns.Packet) error
-	Start(ctx context.Context, port int) error
-}
-
-type newMDNSFunc func(address string) mdnsInterface
-
-// Contains common command information for embedding in other dev_finder commands.
-type devFinderCmd struct {
-	// Outputs in JSON format if true.
-	json bool
-	// The mDNS addresses to connect to.
-	mdnsAddrs string
-	// The mDNS ports to connect to.
-	mdnsPorts string
-	// The timeout in ms to either give up or to exit the program after finding at least one
-	// device.
-	timeout int
-	// Determines whether to return the address of the address of the interface that
-	// established a connection to the Fuchsia device (rather than the address of the
-	// Fuchsia device on its own).
-	localResolve bool
-	// Determines whether to accept incoming unicast mDNS responses. This can happen if the
-	// receiving device is on a different subnet, or the receiving device's listener port
-	// has been forwarded to from a non-standard port.
-	acceptUnicast bool
-	// The limit of devices to discover. If this number of devices has been discovered before
-	// the timeout has been reached the program will exit successfully.
-	deviceLimit int
-
-	mdnsHandler mDNSHandler
-
-	// Only for testing.
-	newMDNSFunc newMDNSFunc
-	output      io.Writer
-}
-
-type fuchsiaDevice struct {
-	addr   net.IP
-	domain string
-}
-
-func (cmd *devFinderCmd) SetCommonFlags(f *flag.FlagSet) {
-	f.BoolVar(&cmd.json, "json", false, "Outputs in JSON format.")
-	f.StringVar(&cmd.mdnsAddrs, "addr", "224.0.0.251,224.0.0.250,ff02::fb", "Comma separated list of addresses to issue mDNS queries to.")
-	f.StringVar(&cmd.mdnsPorts, "port", "5353,5356", "Comma separated list of ports to issue mDNS queries to.")
-	f.IntVar(&cmd.timeout, "timeout", 2000, "The number of milliseconds before declaring a timeout.")
-	f.BoolVar(&cmd.localResolve, "local", false, "Returns the address of the interface to the host when doing service lookup/domain resolution.")
-	f.BoolVar(&cmd.acceptUnicast, "accept-unicast", false, "Accepts unicast responses. For if the receiving device responds from a different subnet or behind port forwarding.")
-	f.IntVar(&cmd.deviceLimit, "device-limit", 0, "Exits before the timeout at this many devices per resolution (zero means no limit).")
-}
-
-func (cmd *devFinderCmd) Output() io.Writer {
-	if cmd.output == nil {
-		return os.Stdout
-	}
-	return cmd.output
-}
-
-// Extracts the IP from its argument, returning an error if the type is unsupported.
-func addrToIP(addr net.Addr) (net.IP, error) {
-	switch v := addr.(type) {
-	case *net.IPNet:
-		return v.IP, nil
-	case *net.IPAddr:
-		return v.IP, nil
-	case *net.UDPAddr:
-		return v.IP, nil
-	}
-	return nil, errors.New("unsupported address type")
-}
-
-func (cmd *devFinderCmd) newMDNS(address string) mdnsInterface {
-	if cmd.newMDNSFunc != nil {
-		return cmd.newMDNSFunc(address)
-	}
-	m := mdns.NewMDNS()
-	ip := net.ParseIP(address)
-	if ip.To4() != nil {
-		m.EnableIPv4()
-	} else {
-		m.EnableIPv6()
-	}
-	m.SetAddress(address)
-	m.SetAcceptUnicastResponses(cmd.acceptUnicast)
-	return m
-}
-
-func sortDeviceMap(deviceMap map[string]*fuchsiaDevice) []*fuchsiaDevice {
-	keys := make([]string, 0)
-	for k := range deviceMap {
-		keys = append(keys, k)
-	}
-	sort.Strings(keys)
-	res := make([]*fuchsiaDevice, 0)
-	for _, k := range keys {
-		res = append(res, deviceMap[k])
-	}
-	return res
-}
-
-func (cmd *devFinderCmd) sendMDNSPacket(ctx context.Context, packet mdns.Packet) ([]*fuchsiaDevice, error) {
-	if cmd.mdnsHandler == nil {
-		return nil, fmt.Errorf("packet handler is nil")
-	}
-	if cmd.timeout <= 0 {
-		return nil, fmt.Errorf("invalid timeout value: %v", cmd.timeout)
-	}
-
-	addrs := strings.Split(cmd.mdnsAddrs, ",")
-	var ports []int
-	for _, s := range strings.Split(cmd.mdnsPorts, ",") {
-		p, err := strconv.ParseUint(s, 10, 16)
-		if err != nil {
-			return nil, fmt.Errorf("Could not parse port number %v: %v\n", s, err)
-		}
-		ports = append(ports, int(p))
-	}
-
-	ctx, cancel := context.WithTimeout(ctx, time.Duration(cmd.timeout)*time.Millisecond)
-	defer cancel()
-	errChan := make(chan error)
-	devChan := make(chan *fuchsiaDevice)
-	for _, addr := range addrs {
-		for _, p := range ports {
-			m := cmd.newMDNS(addr)
-			m.AddHandler(func(recv net.Interface, addr net.Addr, rxPacket mdns.Packet) {
-				response := mDNSResponse{recv, addr, rxPacket}
-				cmd.mdnsHandler(response, cmd.localResolve, devChan, errChan)
-			})
-			m.AddErrorHandler(func(err error) {
-				errChan <- err
-			})
-			m.AddWarningHandler(func(addr net.Addr, err error) {
-				log.Printf("from: %v warn: %v\n", addr, err)
-			})
-			if err := m.Start(ctx, p); err != nil {
-				return nil, fmt.Errorf("starting mdns: %v", err)
-			}
-			m.Send(packet)
-		}
-	}
-
-	devices := make(map[string]*fuchsiaDevice)
-	for {
-		select {
-		case <-ctx.Done():
-			if len(devices) == 0 {
-				return nil, fmt.Errorf("timeout")
-			}
-			// Devices are returned in sorted order to ensure that results are
-			// deterministic despite using a hashmap (which is non-deterministically
-			// ordered).
-			return sortDeviceMap(devices), nil
-		case err := <-errChan:
-			return nil, err
-		case device := <-devChan:
-			// Creates a hashable string to remove duplicate devices.
-			//
-			// There should only be one of each domain on the network, but given how
-			// mcast is sent on each interface, multiple responses with different IP
-			// addresses can be returned for a single device in the case of a device
-			// running on the host in an emulator (this is a special case). Each
-			// IP would be point to the localhost in this case.
-			devices[fmt.Sprintf("%s", device.domain)] = device
-			if cmd.deviceLimit != 0 && len(devices) == cmd.deviceLimit {
-				return sortDeviceMap(devices), nil
-			}
-		}
-	}
-}
-
-// jsonOutput represents the output in JSON format.
-type jsonOutput struct {
-	// List of devices found.
-	Devices []jsonDevice `json:"devices"`
-}
-
-type jsonDevice struct {
-	// Device IP address.
-	Addr string `json:"addr"`
-	// Device domain name. Can be omitted.
-	Domain string `json:"domain,omitempty"`
-}
-
-func (cmd *devFinderCmd) outputNormal(filteredDevices []*fuchsiaDevice, includeDomain bool) error {
-	for _, device := range filteredDevices {
-		if includeDomain {
-			fmt.Fprintf(cmd.Output(), "%v %v\n", device.addr, device.domain)
-		} else {
-			fmt.Fprintf(cmd.Output(), "%v\n", device.addr)
-		}
-	}
-	return nil
-}
-
-func (cmd *devFinderCmd) outputJSON(filteredDevices []*fuchsiaDevice, includeDomain bool) error {
-	jsonOut := jsonOutput{Devices: make([]jsonDevice, 0, len(filteredDevices))}
-
-	for _, device := range filteredDevices {
-		dev := jsonDevice{Addr: device.addr.String()}
-		if includeDomain {
-			dev.Domain = device.domain
-		}
-		jsonOut.Devices = append(jsonOut.Devices, dev)
-	}
-
-	e := json.NewEncoder(cmd.Output())
-	e.SetIndent("", "  ")
-	return e.Encode(jsonOut)
-}
diff --git a/net/dev_finder/cmd/dev_finder_test.go b/net/dev_finder/cmd/dev_finder_test.go
deleted file mode 100644
index 944d6f9..0000000
--- a/net/dev_finder/cmd/dev_finder_test.go
+++ /dev/null
@@ -1,403 +0,0 @@
-// Copyright 2019 The Fuchsia 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 (
-	"bytes"
-	"context"
-	"encoding/json"
-	"net"
-	"strings"
-	"testing"
-
-	"github.com/google/go-cmp/cmp"
-
-	"go.fuchsia.dev/tools/net/mdns"
-)
-
-// fakeMDNS is a fake implementation of MDNS for testing.
-type fakeMDNS struct {
-	answer           *fakeAnswer
-	handlers         []func(net.Interface, net.Addr, mdns.Packet)
-	sendEmptyData    bool
-	sendTooShortData bool
-}
-
-type fakeAnswer struct {
-	ip      string
-	domains []string
-}
-
-func (m *fakeMDNS) AddHandler(f func(net.Interface, net.Addr, mdns.Packet)) {
-	m.handlers = append(m.handlers, f)
-}
-func (m *fakeMDNS) AddWarningHandler(func(net.Addr, error)) {}
-func (m *fakeMDNS) AddErrorHandler(func(error))             {}
-func (m *fakeMDNS) SendTo(mdns.Packet, *net.UDPAddr) error  { return nil }
-func (m *fakeMDNS) Send(packet mdns.Packet) error {
-	if m.answer != nil {
-		go func() {
-			ifc := net.Interface{}
-			ip := net.IPAddr{IP: net.ParseIP(m.answer.ip).To4()}
-			for _, q := range packet.Questions {
-				switch {
-				case q.Type == mdns.PTR && q.Class == mdns.IN:
-					// 'list' command
-					answers := make([]mdns.Record, len(m.answer.domains))
-					for _, d := range m.answer.domains {
-						// Cases for malformed response.
-						if m.sendEmptyData {
-							answers = append(answers, mdns.Record{
-								Class: mdns.IN,
-								Type:  mdns.PTR,
-								Data:  nil, // Empty data
-							})
-							continue
-						}
-						if m.sendTooShortData {
-							data := make([]byte, len(d)) // One byte shorter
-							data[0] = byte(len(d))
-							copy(data[1:], []byte(d[1:]))
-							answers = append(answers, mdns.Record{
-								Class: mdns.IN,
-								Type:  mdns.PTR,
-								Data:  data,
-							})
-							continue
-						}
-
-						data := make([]byte, len(d)+1)
-						data[0] = byte(len(d))
-						copy(data[1:], []byte(d))
-						answers = append(answers, mdns.Record{
-							Class: mdns.IN,
-							Type:  mdns.PTR,
-							Data:  data,
-						})
-					}
-					pkt := mdns.Packet{Answers: answers}
-					for _, h := range m.handlers {
-						h(ifc, &ip, pkt)
-					}
-				case q.Type == mdns.A && q.Class == mdns.IN:
-					// 'resolve' command
-					answers := make([]mdns.Record, len(m.answer.domains))
-					for _, d := range m.answer.domains {
-						answers = append(answers, mdns.Record{
-							Class:  mdns.IN,
-							Type:   mdns.A,
-							Data:   net.ParseIP(m.answer.ip).To4(),
-							Domain: d,
-						})
-					}
-					pkt := mdns.Packet{Answers: answers}
-					for _, h := range m.handlers {
-						h(ifc, &ip, pkt)
-					}
-				}
-			}
-		}()
-	}
-	return nil
-}
-func (m *fakeMDNS) Start(context.Context, int) error { return nil }
-
-func newDevFinderCmd(handler mDNSHandler, answerDomains []string, sendEmptyData bool, sendTooShortData bool) devFinderCmd {
-	// Because mdnsAddrs have two addresses specified and mdnsPorts have
-	// two ports specified, four MDNS objects are created. To emulate the
-	// case where only one of them responds, create only one fake MDNS
-	// object with answers. The others wouldn't respond at all. See the
-	// Send() method above.
-	mdnsCount := 0
-	return devFinderCmd{
-		mdnsHandler: handler,
-		mdnsAddrs:   "224.0.0.251,224.0.0.250",
-		mdnsPorts:   "5353,5356",
-		timeout:     10,
-		newMDNSFunc: func(addr string) mdnsInterface {
-			mdnsCount++
-			switch mdnsCount {
-			case 1:
-				return &fakeMDNS{
-					answer: &fakeAnswer{
-						ip:      "192.168.0.42",
-						domains: answerDomains,
-					},
-					sendEmptyData:    sendEmptyData,
-					sendTooShortData: sendTooShortData,
-				}
-			default:
-				return &fakeMDNS{}
-			}
-		},
-	}
-}
-
-func compareFuchsiaDevices(d1, d2 *fuchsiaDevice) bool {
-	return cmp.Equal(d1.addr, d2.addr) && cmp.Equal(d1.domain, d2.domain)
-}
-
-//// Tests for the `list` command.
-
-func TestListDevices(t *testing.T) {
-	cmd := listCmd{
-		devFinderCmd: newDevFinderCmd(
-			listMDNSHandler,
-			[]string{
-				"some.domain",
-				"another.domain",
-			}, false, false),
-	}
-
-	got, err := cmd.listDevices(context.Background())
-	if err != nil {
-		t.Fatalf("listDevices: %v", err)
-	}
-	want := []*fuchsiaDevice{
-		{
-			addr:   net.ParseIP("192.168.0.42").To4(),
-			domain: "another.domain",
-		},
-		{
-			addr:   net.ParseIP("192.168.0.42").To4(),
-			domain: "some.domain",
-		},
-	}
-	if d := cmp.Diff(want, got, cmp.Comparer(compareFuchsiaDevices)); d != "" {
-		t.Errorf("listDevices mismatch: (-want +got):\n%s", d)
-	}
-}
-
-func TestListDevices_domainFilter(t *testing.T) {
-	cmd := listCmd{
-		devFinderCmd: newDevFinderCmd(
-			listMDNSHandler,
-			[]string{
-				"some.domain",
-				"another.domain",
-			}, false, false),
-		domainFilter: "some",
-	}
-
-	got, err := cmd.listDevices(context.Background())
-	if err != nil {
-		t.Fatalf("listDevices: %v", err)
-	}
-	want := []*fuchsiaDevice{
-		{
-			addr:   net.ParseIP("192.168.0.42").To4(),
-			domain: "some.domain",
-		},
-	}
-	if d := cmp.Diff(want, got, cmp.Comparer(compareFuchsiaDevices)); d != "" {
-		t.Errorf("listDevices mismatch: (-want +got):\n%s", d)
-	}
-}
-
-func TestListDevices_emptyData(t *testing.T) {
-	cmd := listCmd{
-		devFinderCmd: newDevFinderCmd(
-			listMDNSHandler,
-			[]string{
-				"some.domain",
-				"another.domain",
-			},
-			true, // sendEmptyData
-			false),
-	}
-
-	// Must not crash.
-	cmd.listDevices(context.Background())
-}
-
-func TestListDevices_duplicateDevices(t *testing.T) {
-	cmd := listCmd{
-		devFinderCmd: newDevFinderCmd(
-			listMDNSHandler,
-			[]string{
-				"some.domain",
-				"some.domain",
-				"some.domain",
-				"some.domain",
-				"some.domain",
-				"another.domain",
-			},
-			false,
-			false),
-	}
-	got, err := cmd.listDevices(context.Background())
-	if err != nil {
-		t.Fatalf("listDevices: %v", err)
-	}
-	want := []*fuchsiaDevice{
-		{
-			addr:   net.ParseIP("192.168.0.42").To4(),
-			domain: "another.domain",
-		},
-		{
-			addr:   net.ParseIP("192.168.0.42").To4(),
-			domain: "some.domain",
-		},
-	}
-	if d := cmp.Diff(want, got, cmp.Comparer(compareFuchsiaDevices)); d != "" {
-		t.Errorf("listDevices mismatch: (-want +got):\n%s", d)
-	}
-}
-
-func TestListDevices_tooShortData(t *testing.T) {
-	cmd := listCmd{
-		devFinderCmd: newDevFinderCmd(
-			listMDNSHandler,
-			[]string{
-				"some.domain",
-				"another.domain",
-			},
-			false,
-			true, // sendTooShortData
-		),
-	}
-
-	// Must not crash.
-	cmd.listDevices(context.Background())
-}
-
-//// Tests for the `resolve` command.
-
-func TestResolveDevices(t *testing.T) {
-	cmd := resolveCmd{
-		devFinderCmd: newDevFinderCmd(
-			resolveMDNSHandler,
-			[]string{
-				"some.domain.local",
-				"another.domain.local",
-			}, false, false),
-	}
-
-	got, err := cmd.resolveDevices(context.Background(), "some.domain")
-	if err != nil {
-		t.Fatalf("resolveDevices: %v", err)
-	}
-	want := []*fuchsiaDevice{
-		{
-			addr:   net.ParseIP("192.168.0.42").To4(),
-			domain: "some.domain.local",
-		},
-	}
-	if d := cmp.Diff(want, got, cmp.Comparer(compareFuchsiaDevices)); d != "" {
-		t.Errorf("resolveDevices mismatch: (-want +got):\n%s", d)
-	}
-}
-
-//// Tests for output functions.
-
-func TestOutputNormal(t *testing.T) {
-	devs := []*fuchsiaDevice{
-		{
-			addr:   net.ParseIP("123.12.234.23").To4(),
-			domain: "hello.world",
-		},
-		{
-			addr:   net.ParseIP("11.22.33.44").To4(),
-			domain: "fuchsia.rocks",
-		},
-	}
-
-	{
-		var buf strings.Builder
-		cmd := devFinderCmd{output: &buf}
-
-		cmd.outputNormal(devs, false)
-
-		got := buf.String()
-		want := `123.12.234.23
-11.22.33.44
-`
-		if d := cmp.Diff(want, got); d != "" {
-			t.Errorf("outputNormal mismatch: (-want +got):\n%s", d)
-		}
-	}
-
-	{
-		var buf strings.Builder
-		cmd := devFinderCmd{output: &buf}
-		cmd.outputNormal(devs, true)
-
-		got := buf.String()
-		want := `123.12.234.23 hello.world
-11.22.33.44 fuchsia.rocks
-`
-		if d := cmp.Diff(want, got); d != "" {
-			t.Errorf("outputNormal(includeDomain) mismatch: (-want +got):\n%s", d)
-		}
-	}
-}
-
-func TestOutputJSON(t *testing.T) {
-	devs := []*fuchsiaDevice{
-		{
-			addr:   net.ParseIP("123.12.234.23").To4(),
-			domain: "hello.world",
-		},
-		{
-			addr:   net.ParseIP("11.22.33.44").To4(),
-			domain: "fuchsia.rocks",
-		},
-	}
-
-	{
-		var buf bytes.Buffer
-		cmd := devFinderCmd{
-			json:   true,
-			output: &buf,
-		}
-
-		cmd.outputJSON(devs, false)
-
-		var got jsonOutput
-		if err := json.Unmarshal(buf.Bytes(), &got); err != nil {
-			t.Fatalf("json.Unmarshal: %v", err)
-		}
-		want := jsonOutput{
-			Devices: []jsonDevice{
-				{Addr: "123.12.234.23"},
-				{Addr: "11.22.33.44"},
-			},
-		}
-		if d := cmp.Diff(want, got); d != "" {
-			t.Errorf("outputNormal mismatch: (-want +got):\n%s", d)
-		}
-	}
-
-	{
-		var buf bytes.Buffer
-		cmd := devFinderCmd{
-			json:   true,
-			output: &buf,
-		}
-
-		cmd.outputJSON(devs, true)
-
-		var got jsonOutput
-		if err := json.Unmarshal(buf.Bytes(), &got); err != nil {
-			t.Fatalf("json.Unmarshal: %v", err)
-		}
-
-		want := jsonOutput{
-			Devices: []jsonDevice{
-				{
-					Addr:   "123.12.234.23",
-					Domain: "hello.world",
-				},
-				{
-					Addr:   "11.22.33.44",
-					Domain: "fuchsia.rocks",
-				},
-			},
-		}
-		if d := cmp.Diff(want, got); d != "" {
-			t.Errorf("outputNormal(includeDomain) mismatch: (-want +got):\n%s", d)
-		}
-	}
-}
diff --git a/net/dev_finder/cmd/list.go b/net/dev_finder/cmd/list.go
deleted file mode 100644
index 4a5e749..0000000
--- a/net/dev_finder/cmd/list.go
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2019 The Fuchsia 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 (
-	"context"
-	"flag"
-	"fmt"
-	"log"
-	"strings"
-
-	"github.com/google/subcommands"
-
-	"go.fuchsia.dev/tools/net/mdns"
-)
-
-const (
-	fuchsiaService = "_fuchsia._udp.local"
-)
-
-type listCmd struct {
-	devFinderCmd
-
-	// Determines whether or not to print the full device info.
-	fullInfo bool
-	// Filters domains that match this string when listing devices.
-	domainFilter string
-}
-
-func (*listCmd) Name() string {
-	return "list"
-}
-
-func (*listCmd) Usage() string {
-	return "list [flags...]\n\nflags:\n"
-}
-
-func (*listCmd) Synopsis() string {
-	return "lists all Fuchsia devices on the network"
-}
-
-func (cmd *listCmd) SetFlags(f *flag.FlagSet) {
-	cmd.SetCommonFlags(f)
-	f.StringVar(&cmd.domainFilter, "domain-filter", "", "When using the \"list\" command, returns only devices that match this domain name.")
-	f.BoolVar(&cmd.fullInfo, "full", false, "Print device address and domain")
-}
-
-func listMDNSHandler(resp mDNSResponse, localResolve bool, devChan chan<- *fuchsiaDevice, errChan chan<- error) {
-	for _, a := range resp.rxPacket.Answers {
-		if a.Class == mdns.IN && a.Type == mdns.PTR {
-			// DX-1498: Some protection against malformed responses.
-			if len(a.Data) == 0 {
-				log.Print("Empty data in response. Ignoring...")
-				continue
-			}
-			nameLength := int(a.Data[0])
-			if len(a.Data) < nameLength+1 {
-				log.Printf("Too short data in response. Got %d bytes; expected %d", len(a.Data), nameLength+1)
-				continue
-			}
-
-			// This is a bit convoluted: the domain param is being used
-			// as a "service", and the Data field actually contains the
-			// domain of the device.
-			fuchsiaDomain := string(a.Data[1 : nameLength+1])
-			if localResolve {
-				recvIP, err := resp.getReceiveIP()
-				if err != nil {
-					errChan <- err
-					return
-				}
-				devChan <- &fuchsiaDevice{recvIP, fuchsiaDomain}
-				continue
-			}
-			if ip, err := addrToIP(resp.devAddr); err != nil {
-				errChan <- fmt.Errorf("could not find addr for %v: %v", resp.devAddr, err)
-			} else {
-				devChan <- &fuchsiaDevice{
-					addr:   ip,
-					domain: fuchsiaDomain,
-				}
-			}
-		}
-	}
-}
-
-func (cmd *listCmd) listDevices(ctx context.Context) ([]*fuchsiaDevice, error) {
-	listPacket := mdns.Packet{
-		Header: mdns.Header{QDCount: 1},
-		Questions: []mdns.Question{
-			{
-				Domain:  fuchsiaService,
-				Type:    mdns.PTR,
-				Class:   mdns.IN,
-				Unicast: false,
-			},
-		},
-	}
-	devices, err := cmd.sendMDNSPacket(ctx, listPacket)
-	if err != nil {
-		return nil, fmt.Errorf("sending/receiving mdns packets: %v", err)
-	}
-	var filteredDevices []*fuchsiaDevice
-	for _, device := range devices {
-		if strings.Contains(device.domain, cmd.domainFilter) {
-			filteredDevices = append(filteredDevices, device)
-		}
-	}
-	if len(filteredDevices) == 0 {
-		return nil, fmt.Errorf("no devices with domain matching '%v'", cmd.domainFilter)
-	}
-	return filteredDevices, nil
-}
-
-func (cmd *listCmd) execute(ctx context.Context) error {
-	filteredDevices, err := cmd.listDevices(ctx)
-	if err != nil {
-		return err
-	}
-
-	if cmd.json {
-		return cmd.outputJSON(filteredDevices, cmd.fullInfo)
-	}
-	return cmd.outputNormal(filteredDevices, cmd.fullInfo)
-}
-
-func (cmd *listCmd) Execute(ctx context.Context, _ *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
-	cmd.mdnsHandler = listMDNSHandler
-	if err := cmd.execute(ctx); err != nil {
-		log.Print(err)
-		return subcommands.ExitFailure
-	}
-	return subcommands.ExitSuccess
-}
diff --git a/net/dev_finder/cmd/main.go b/net/dev_finder/cmd/main.go
deleted file mode 100644
index 72525e3..0000000
--- a/net/dev_finder/cmd/main.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2018 The Fuchsia 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
-
-// Uses mDNS for Fuchsia device discovery.
-
-import (
-	"context"
-	"flag"
-	"os"
-
-	"github.com/google/subcommands"
-)
-
-func main() {
-	subcommands.Register(subcommands.HelpCommand(), "")
-	subcommands.Register(subcommands.CommandsCommand(), "")
-	subcommands.Register(subcommands.FlagsCommand(), "")
-	subcommands.Register(&listCmd{}, "")
-	subcommands.Register(&resolveCmd{}, "")
-
-	flag.Parse()
-	os.Exit(int(subcommands.Execute(context.Background())))
-}
diff --git a/net/dev_finder/cmd/resolve.go b/net/dev_finder/cmd/resolve.go
deleted file mode 100644
index 691c697..0000000
--- a/net/dev_finder/cmd/resolve.go
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2018 The Fuchsia 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 (
-	"context"
-	"errors"
-	"flag"
-	"fmt"
-	"log"
-	"net"
-
-	"github.com/google/subcommands"
-
-	"go.fuchsia.dev/tools/net/mdns"
-)
-
-const (
-	ipv4AddrLength = 4
-)
-
-type resolveCmd struct {
-	devFinderCmd
-}
-
-func (*resolveCmd) Name() string {
-	return "resolve"
-}
-
-func (*resolveCmd) Usage() string {
-	return "resolve [flags...] [domains...]\n\nflags:\n"
-}
-
-func (*resolveCmd) Synopsis() string {
-	return "attempts to resolve all passed Fuchsia domain names on the network"
-}
-
-func (cmd *resolveCmd) SetFlags(f *flag.FlagSet) {
-	cmd.SetCommonFlags(f)
-}
-
-func resolveMDNSHandler(resp mDNSResponse, localResolve bool, devChan chan<- *fuchsiaDevice, errChan chan<- error) {
-	for _, a := range resp.rxPacket.Answers {
-		if a.Class == mdns.IN && a.Type == mdns.A &&
-			len(a.Data) == ipv4AddrLength {
-			if localResolve {
-				recvIP, err := resp.getReceiveIP()
-				if err != nil {
-					errChan <- err
-					return
-				}
-				devChan <- &fuchsiaDevice{recvIP, a.Domain}
-				continue
-			}
-			devChan <- &fuchsiaDevice{net.IP(a.Data), a.Domain}
-		}
-	}
-}
-
-func (cmd *resolveCmd) resolveDevices(ctx context.Context, domains ...string) ([]*fuchsiaDevice, error) {
-	if len(domains) == 0 {
-		return nil, errors.New("no domains supplied")
-	}
-
-	var outDevices []*fuchsiaDevice
-	for _, domain := range domains {
-		mDNSDomain := fmt.Sprintf("%s.local", domain)
-		devices, err := cmd.sendMDNSPacket(ctx, mdns.QuestionPacket(mDNSDomain))
-		if err != nil {
-			return nil, fmt.Errorf("sending/receiving mdns packets during resolve of domain '%s': %v", domain, err)
-		}
-		filteredDevices := make([]*fuchsiaDevice, 0)
-		for _, device := range devices {
-			if device.domain == mDNSDomain {
-				filteredDevices = append(filteredDevices, device)
-			}
-		}
-		if len(filteredDevices) == 0 {
-			return nil, fmt.Errorf("no devices with domain %v", domain)
-		}
-
-		for _, device := range filteredDevices {
-			outDevices = append(outDevices, device)
-		}
-	}
-	return outDevices, nil
-}
-
-func (cmd *resolveCmd) execute(ctx context.Context, domains ...string) error {
-	outDevices, err := cmd.resolveDevices(ctx, domains...)
-	if err != nil {
-		return err
-	}
-
-	if cmd.json {
-		return cmd.outputJSON(outDevices, false /* includeDomain */)
-	}
-	return cmd.outputNormal(outDevices, false /* includeDomain */)
-}
-
-func (cmd *resolveCmd) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
-	cmd.mdnsHandler = resolveMDNSHandler
-	if err := cmd.execute(ctx, f.Args()...); err != nil {
-		log.Print(err)
-		return subcommands.ExitFailure
-	}
-	return subcommands.ExitSuccess
-}
diff --git a/net/digest/digest.go b/net/digest/digest.go
deleted file mode 100644
index 607135e..0000000
--- a/net/digest/digest.go
+++ /dev/null
@@ -1,234 +0,0 @@
-// Copyright 2013 M-Lab
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package digest
-
-import (
-	"crypto/md5"
-	"crypto/rand"
-	"errors"
-	"fmt"
-	"io"
-	"net/http"
-	"strings"
-)
-
-var (
-	ErrNilTransport      = errors.New("transport is nil")
-	ErrBadChallenge      = errors.New("challenge is bad")
-	ErrAlgNotImplemented = errors.New("algorithm not implemented")
-)
-
-// Transport is an implementation of http.RoundTripper that supports HTTP
-// digest authentication.
-type Transport struct {
-	Username  string
-	Password  string
-	Transport http.RoundTripper
-}
-
-// NewTransport creates a new digest transport using http.DefaultTransport.
-func NewTransport(username, password string) *Transport {
-	return &Transport{
-		Username:  username,
-		Password:  password,
-		Transport: http.DefaultTransport,
-	}
-}
-
-// RoundTrip makes a request expecting a 401 response that will require digest
-// authentication. It creates the credentials it needs and makes a follow-up
-// request.
-func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) {
-	if t.Transport == nil {
-		return nil, ErrNilTransport
-	}
-
-	body, err := r.GetBody()
-	if err != nil {
-		return nil, err
-	}
-	req, err := http.NewRequest(r.Method, r.URL.String(), body)
-	if err != nil {
-		return nil, err
-	}
-
-	req.Header = make(http.Header)
-	for k, s := range r.Header {
-		req.Header[k] = s
-	}
-
-	// Make a request to get the 401 that contains the challenge.
-	res, err := t.Transport.RoundTrip(r)
-	if err != nil || res.StatusCode != 401 {
-		return res, err
-	}
-	defer res.Body.Close()
-
-	chal := res.Header.Get("WWW-Authenticate")
-	c, err := parseChallenge(chal)
-	if err != nil {
-		return res, err
-	}
-
-	// Generate credentials based on the challenge.
-	cr := t.authenticate(req, c)
-	auth, err := cr.authorize()
-	if err != nil {
-		return res, err
-	}
-
-	// Make authenticated request.
-	req.Header.Set("Authorization", auth)
-	return t.Transport.RoundTrip(req)
-}
-
-type challenge struct {
-	realm     string
-	domain    string
-	nonce     string
-	opaque    string
-	stale     string
-	algorithm string
-	qop       string
-}
-
-func parseChallenge(input string) (*challenge, error) {
-	const ws = " \n\r\t"
-	const qs = `"`
-	s := strings.Trim(input, ws)
-	if !strings.HasPrefix(s, "Digest ") {
-		return nil, ErrBadChallenge
-	}
-	s = strings.Trim(s[7:], ws)
-	sl := strings.Split(s, ",")
-	c := &challenge{
-		algorithm: "MD5",
-	}
-	var r []string
-	for i := range sl {
-		r = strings.SplitN(strings.Trim(sl[i], ws), "=", 2)
-		switch r[0] {
-		case "realm":
-			c.realm = strings.Trim(r[1], qs)
-		case "domain":
-			c.domain = strings.Trim(r[1], qs)
-		case "nonce":
-			c.nonce = strings.Trim(r[1], qs)
-		case "opaque":
-			c.opaque = strings.Trim(r[1], qs)
-		case "stale":
-			c.stale = strings.Trim(r[1], qs)
-		case "algorithm":
-			c.algorithm = strings.Trim(r[1], qs)
-		case "qop":
-			c.qop = strings.Trim(r[1], qs)
-		default:
-			return nil, ErrBadChallenge
-		}
-	}
-	return c, nil
-}
-
-type credentials struct {
-	userhash  bool
-	username  string
-	realm     string
-	nonce     string
-	uri       string
-	algorithm string
-	cnonce    string
-	opaque    string
-	qop       string
-	nc        int
-	method    string
-	password  string
-}
-
-func h(data string) string {
-	return fmt.Sprintf("%x", md5.Sum([]byte(data)))
-}
-
-func (c *credentials) ha1() string {
-	return h(fmt.Sprintf("%s:%s:%s", c.username, c.realm, c.password))
-}
-
-func (c *credentials) ha2() string {
-	return h(fmt.Sprintf("%s:%s", c.method, c.uri))
-}
-
-func (c *credentials) response(cnonce string) (string, error) {
-	c.nc++
-	if c.qop == "auth" {
-		if cnonce != "" {
-			c.cnonce = cnonce
-		} else {
-			b := make([]byte, 8)
-			io.ReadFull(rand.Reader, b)
-			c.cnonce = fmt.Sprintf("%x", b)[:16]
-		}
-		return h(fmt.Sprintf("%s:%s:%08x:%s:%s:%s",
-			c.ha1(), c.nonce, c.nc, c.cnonce, c.qop, c.ha2())), nil
-	} else if c.qop == "" {
-		return h(fmt.Sprintf("%s:%s:%s", c.ha1(), c.nonce, c.ha2())), nil
-	}
-	return "", ErrAlgNotImplemented
-}
-
-func (c *credentials) authorize() (string, error) {
-	if c.algorithm != "MD5" {
-		return "", ErrAlgNotImplemented
-	}
-	if c.qop != "auth" && c.qop != "" {
-		return "", ErrAlgNotImplemented
-	}
-	response, err := c.response("")
-	if err != nil {
-		return "", err
-	}
-	sl := []string{}
-	sl = append(sl, fmt.Sprintf(`username="%s"`, c.username))
-	sl = append(sl, fmt.Sprintf(`realm="%s"`, c.realm))
-	sl = append(sl, fmt.Sprintf(`nonce="%s"`, c.nonce))
-	sl = append(sl, fmt.Sprintf(`uri="%s"`, c.uri))
-	sl = append(sl, fmt.Sprintf(`response="%s"`, response))
-	sl = append(sl, fmt.Sprintf(`algorithm="%s"`, c.algorithm))
-	sl = append(sl, fmt.Sprintf(`cnonce="%s"`, c.cnonce))
-	if c.opaque != "" {
-		sl = append(sl, fmt.Sprintf(`opaque="%s"`, c.opaque))
-	}
-	if c.qop != "" {
-		sl = append(sl, fmt.Sprintf(`qop=%s`, c.qop))
-	}
-	sl = append(sl, fmt.Sprintf("nc=%08x", c.nc))
-	if c.userhash {
-		sl = append(sl, `userhash="true"`)
-	}
-	return fmt.Sprintf("Digest %s", strings.Join(sl, ", ")), nil
-}
-
-func (t *Transport) authenticate(req *http.Request, c *challenge) *credentials {
-	return &credentials{
-		username:  t.Username,
-		realm:     c.realm,
-		nonce:     c.nonce,
-		uri:       req.URL.RequestURI(),
-		algorithm: c.algorithm,
-		opaque:    c.opaque,
-		qop:       c.qop,
-		nc:        0,
-		method:    req.Method,
-		password:  t.Password,
-	}
-}
diff --git a/net/digest/digest_test.go b/net/digest/digest_test.go
deleted file mode 100644
index 8607a48..0000000
--- a/net/digest/digest_test.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2018 The Fuchsia 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 digest
-
-import (
-	"testing"
-)
-
-var c = &credentials{
-	username:  "admin",
-	realm:     "Digest:4C1F0000000000000000000000000000",
-	nonce:     "GZHoABAHAAAAAAAAtejSfCEQLbW+c/fM",
-	uri:       "/index",
-	algorithm: "MD5",
-	qop:       "auth",
-	method:    "POST",
-	password:  "password",
-}
-
-var cnonce = "0a4f113b"
-
-func TestHa1(t *testing.T) {
-	r := c.ha1()
-	if r != "e00fd2f74e4bb1ccd5c3f359e13822ce" {
-		t.Fail()
-	}
-}
-
-func TestHa2(t *testing.T) {
-	r := c.ha2()
-	if r != "f272ccec928f9de4e8e0bc6319ab2c66" {
-		t.Fail()
-	}
-}
-
-func TestResponse(t *testing.T) {
-	r, err := c.response(cnonce)
-	if err != nil {
-		t.Fail()
-	}
-	if r != "ce25c065de2d1c900b21ed6d6fbe886b" {
-		t.Fail()
-	}
-}
diff --git a/net/mdns/BUILD.gn b/net/mdns/BUILD.gn
deleted file mode 100644
index 35ff521..0000000
--- a/net/mdns/BUILD.gn
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2018 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import ("//build/go/go_library.gni")
-
-go_library("mdns_lib") {
-  name = "mdns_lib"
-
-  deps = [
-    "//garnet/public/go/third_party:golang.org/x/net",
-  ]
-}
diff --git a/net/mdns/mdns.go b/net/mdns/mdns.go
deleted file mode 100644
index c304d94..0000000
--- a/net/mdns/mdns.go
+++ /dev/null
@@ -1,1102 +0,0 @@
-// Copyright 2019 The Fuchsia 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 mdns
-
-import (
-	"bytes"
-	"context"
-	"encoding/binary"
-	"fmt"
-	"io"
-	"net"
-	"strings"
-	"syscall"
-	"unicode/utf8"
-
-	"golang.org/x/net/ipv4"
-	"golang.org/x/net/ipv6"
-	"golang.org/x/sys/unix"
-)
-
-// DefaultPort is the mDNS port required of the spec, though this library is port-agnostic.
-const DefaultPort int = 5353
-
-type Header struct {
-	ID      uint16
-	Flags   uint16
-	QDCount uint16
-	ANCount uint16
-	NSCount uint16
-	ARCount uint16
-}
-
-type Record struct {
-	Domain string
-	Type   uint16
-	Class  uint16
-	Flush  bool
-	TTL    uint32
-	Data   []byte
-}
-
-type Question struct {
-	Domain  string
-	Type    uint16
-	Class   uint16
-	Unicast bool
-}
-
-type Packet struct {
-	Header     Header
-	Questions  []Question
-	Answers    []Record
-	Authority  []Record
-	Additional []Record
-}
-
-// A small struct used to send received UDP packets and
-// information about their interface / source address through a channel.
-type receivedPacketInfo struct {
-	data  []byte
-	iface *net.Interface
-	src   net.Addr
-	err   error
-}
-
-func writeUint16(out io.Writer, val uint16) error {
-	buf := make([]byte, 2)
-	binary.BigEndian.PutUint16(buf, val)
-	_, err := out.Write(buf)
-	return err
-}
-
-func (h Header) serialize(out io.Writer) error {
-	if err := writeUint16(out, h.ID); err != nil {
-		return err
-	}
-	if err := writeUint16(out, h.Flags); err != nil {
-		return err
-	}
-	if err := writeUint16(out, h.QDCount); err != nil {
-		return err
-	}
-	if err := writeUint16(out, h.ANCount); err != nil {
-		return err
-	}
-	if err := writeUint16(out, h.NSCount); err != nil {
-		return err
-	}
-	if err := writeUint16(out, h.ARCount); err != nil {
-		return err
-	}
-	return nil
-}
-
-func writeDomain(out io.Writer, domain string) error {
-	domain = strings.TrimSuffix(domain, ".")
-	parts := strings.Split(domain, ".")
-	// TODO(jakehehrlich): Add check that each label is ASCII.
-	// TODO(jakehehrlich): Add check that each label is <= 63 in length.
-	// TODO(jakehehrlich): Add support for compression.
-	for _, dpart := range parts {
-		ascii := []byte(dpart)
-		if _, err := out.Write([]byte{byte(len(ascii))}); err != nil {
-			return err
-		}
-		if _, err := out.Write(ascii); err != nil {
-			return err
-		}
-	}
-	_, err := out.Write([]byte{0})
-	return err
-}
-
-func (q Question) serialize(out io.Writer) error {
-	if err := writeDomain(out, q.Domain); err != nil {
-		return err
-	}
-	if err := writeUint16(out, q.Type); err != nil {
-		return err
-	}
-	var unicast uint16
-	if q.Unicast {
-		unicast = 1 << 15
-	}
-	if err := writeUint16(out, unicast|q.Class); err != nil {
-		return err
-	}
-	return nil
-}
-
-func writeUint32(out io.Writer, val uint32) error {
-	buf := make([]byte, 4)
-	binary.BigEndian.PutUint32(buf, val)
-	_, err := out.Write(buf)
-	return err
-}
-
-func (r Record) serialize(out io.Writer) error {
-	if err := writeDomain(out, r.Domain); err != nil {
-		return err
-	}
-	if err := writeUint16(out, r.Type); err != nil {
-		return err
-	}
-	var flush uint16
-	if r.Flush {
-		flush = 1 << 15
-	}
-	if err := writeUint16(out, flush|r.Class); err != nil {
-		return err
-	}
-	if err := writeUint32(out, r.TTL); err != nil {
-		return err
-	}
-	if err := writeUint16(out, uint16(len(r.Data))); err != nil {
-		return err
-	}
-	if _, err := out.Write(r.Data); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p Packet) serialize(out io.Writer) error {
-	if err := p.Header.serialize(out); err != nil {
-		return err
-	}
-	for _, question := range p.Questions {
-		if err := question.serialize(out); err != nil {
-			return err
-		}
-	}
-	for _, answer := range p.Answers {
-		if err := answer.serialize(out); err != nil {
-			return err
-		}
-	}
-	for _, authority := range p.Authority {
-		if err := authority.serialize(out); err != nil {
-			return err
-		}
-	}
-	for _, addon := range p.Additional {
-		if err := addon.serialize(out); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func readUint16(in io.Reader, out *uint16) error {
-	buf := make([]byte, 2)
-	_, err := in.Read(buf)
-	if err != nil {
-		return err
-	}
-	*out = binary.BigEndian.Uint16(buf)
-	return nil
-}
-
-func (h *Header) deserialize(data []byte, in io.Reader) error {
-	if err := readUint16(in, &h.ID); err != nil {
-		return err
-	}
-	if err := readUint16(in, &h.Flags); err != nil {
-		return err
-	}
-	if err := readUint16(in, &h.QDCount); err != nil {
-		return err
-	}
-	if err := readUint16(in, &h.ANCount); err != nil {
-		return err
-	}
-	if err := readUint16(in, &h.NSCount); err != nil {
-		return err
-	}
-	if err := readUint16(in, &h.ARCount); err != nil {
-		return err
-	}
-	return nil
-}
-
-func readDomain(data []byte, in io.Reader, domain *string) error {
-	// TODO(jakehehrlich): Don't stack overflow when domain contains cycle.
-
-	var d bytes.Buffer
-	for {
-		sizeBuf := make([]byte, 1)
-		if _, err := in.Read(sizeBuf); err != nil {
-			return err
-		}
-		size := sizeBuf[0]
-		// A size of zero indicates that we're done.
-		if size == 0 {
-			break
-		}
-		// We don't support compressed domains right now.
-		if size > 63 {
-			if size < 192 {
-				return fmt.Errorf("invalid size for label")
-			}
-			if _, err := in.Read(sizeBuf); err != nil {
-				return err
-			}
-			offset := ((size & 0x3f) << 8) | sizeBuf[0]
-			var pDomain string
-			readDomain(data, bytes.NewBuffer(data[offset:]), &pDomain)
-			if _, err := d.WriteString(pDomain); err != nil {
-				return err
-			}
-			if err := d.WriteByte(byte('.')); err != nil {
-				return err
-			}
-			break
-		}
-		// Read in the specified bytes (max length 256)
-		buf := make([]byte, size)
-		if _, err := in.Read(buf); err != nil {
-			return err
-		}
-		// Make sure the string is ASCII
-		for _, b := range buf {
-			if b >= utf8.RuneSelf {
-				return fmt.Errorf("Found non-ASCII byte %v in domain", b)
-			}
-		}
-		// Now add this to a temporary domain
-		if _, err := d.Write(buf); err != nil {
-			return err
-		}
-		// Add the trailing "." as seen in the RFC.
-		if err := d.WriteByte(byte('.')); err != nil {
-			return err
-		}
-	}
-	*domain = string(d.Bytes())
-	// Remove the trailing '.' to canonicalize.
-	*domain = strings.TrimSuffix(*domain, ".")
-	return nil
-}
-
-func (q *Question) deserialize(data []byte, in io.Reader) error {
-	if err := readDomain(data, in, &q.Domain); err != nil {
-		return fmt.Errorf("reading domain: %v", err)
-	}
-	if err := readUint16(in, &q.Type); err != nil {
-		return err
-	}
-	var tmp uint16
-	if err := readUint16(in, &tmp); err != nil {
-		return err
-	}
-	// Extract class and unicast bit.
-	q.Unicast = (tmp >> 15) != 0
-	q.Class = (tmp << 1) >> 1
-	return nil
-}
-
-func readUint32(in io.Reader, out *uint32) error {
-	buf := make([]byte, 4)
-	_, err := in.Read(buf)
-	if err != nil {
-		return err
-	}
-	*out = binary.BigEndian.Uint32(buf)
-	return nil
-}
-
-func (r *Record) deserialize(data []byte, in io.Reader) error {
-	if err := readDomain(data, in, &r.Domain); err != nil {
-		return err
-	}
-	if err := readUint16(in, &r.Type); err != nil {
-		return err
-	}
-	var tmp uint16
-	if err := readUint16(in, &tmp); err != nil {
-		return err
-	}
-	// Extract class and flush bit.
-	r.Flush = (tmp >> 15) != 0
-	r.Class = (tmp << 1) >> 1
-	if err := readUint32(in, &r.TTL); err != nil {
-		return err
-	}
-
-	var dataLength uint16
-	if err := readUint16(in, &dataLength); err != nil {
-		return err
-	}
-	// Now read the data (max allocation size of 64k)
-	r.Data = make([]byte, dataLength)
-	if _, err := in.Read(r.Data); err != nil {
-		return err
-	}
-	return nil
-}
-
-// TODO(jakehehrlich): Handle truncation.
-func (p *Packet) deserialize(data []byte, in io.Reader) error {
-	if err := p.Header.deserialize(data, in); err != nil {
-		return err
-	}
-	p.Questions = make([]Question, p.Header.QDCount)
-	for i := uint16(0); i < p.Header.QDCount; i++ {
-		if err := p.Questions[i].deserialize(data, in); err != nil {
-			return err
-		}
-	}
-	p.Answers = make([]Record, p.Header.ANCount)
-	for i := uint16(0); i < p.Header.ANCount; i++ {
-		if err := p.Answers[i].deserialize(data, in); err != nil {
-			return err
-		}
-	}
-	p.Authority = make([]Record, p.Header.NSCount)
-	for i := uint16(0); i < p.Header.NSCount; i++ {
-		if err := p.Authority[i].deserialize(data, in); err != nil {
-			return err
-		}
-	}
-	p.Additional = make([]Record, p.Header.ARCount)
-	for i := uint16(0); i < p.Header.ARCount; i++ {
-		if err := p.Additional[i].deserialize(data, in); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// getFlag constructs the flag field of a header for the tiny subset of
-// flag options that we need.
-// TODO(jakehehrlich): Implement response code error handling.
-// TODO(jakehehrlich): Implement truncation.
-func getFlag(query bool, authority bool) uint16 {
-	var out uint16
-	if !query {
-		out |= 1
-	}
-	if authority {
-		out |= 1 << 5
-	}
-	return out
-}
-
-const (
-	// A is the DNS Type for ipv4
-	A = 1
-	// AAAA is the DNS Type for ipv6
-	AAAA = 28
-	// PTR is the DNS Type for domain name pointers
-	PTR = 12
-	// SRV is the DNS Type for services
-	SRV = 33
-	// IN is the Internet DNS Class
-	IN = 1
-)
-
-// IpToDnsRecordType returns either A or AAAA based on the type of ip.
-func IpToDnsRecordType(ip net.IP) uint16 {
-	if ip4 := ip.To4(); ip4 != nil {
-		return A
-	} else {
-		return AAAA
-	}
-}
-
-// MDNS is the central interface through which requests are sent and received.
-// This implementation is agnostic to use case and asynchronous.
-// To handle various responses add Handlers. To send a packet you may use
-// either SendTo (generally used for unicast) or Send (generally used for
-// multicast).
-type MDNS interface {
-	// EnableIPv4 enables listening on IPv4 network interfaces.
-	EnableIPv4()
-
-	// EnableIPv6 enables listening on IPv6 network interfaces.
-	EnableIPv6()
-
-	// SetAddress sets a non-default listen address.
-	SetAddress(address string) error
-
-	// Sets whether to accept unicast responses. These can be received when
-	// the receiving device is in a different subnet, or if there is port
-	// forwarding occurring between the host and the device.
-	SetAcceptUnicastResponses(accept bool)
-
-	// ipToSend returns the IP corresponding to the current address.
-	ipToSend() net.IP
-
-	// AddHandler calls f on every Packet received.
-	AddHandler(f func(net.Interface, net.Addr, Packet))
-
-	// AddWarningHandler calls f on every non-fatal error.
-	AddWarningHandler(f func(net.Addr, error))
-
-	// AddErrorHandler calls f on every fatal error. After
-	// all active handlers are called, m will stop listening and
-	// close it's connection so this function will not be called twice.
-	AddErrorHandler(f func(error))
-
-	// Start causes m to start listening for mDNS packets on all interfaces on
-	// the specified port. Listening will stop if ctx is done.
-	Start(ctx context.Context, port int) error
-
-	// Send serializes and sends packet out as a multicast to all interfaces
-	// using the port that m is listening on. Note that Start must be
-	// called prior to making this call.
-	Send(packet Packet) error
-
-	// SendTo serializes and sends packet to dst. If dst is a multicast
-	// address then packet is multicast to the corresponding group on
-	// all interfaces. Note that start must be called prior to making this
-	// call.
-	SendTo(packet Packet, dst *net.UDPAddr) error
-
-	// Close closes all connections.
-	Close()
-}
-
-// Interface used to read packets into a caller-owned buffer.
-type packetReceiver interface {
-	// Reads a packet from the connection into |buf|.  On success, returns
-	// the packet size in bytes, the interface |iface| on which it was
-	// received, and the source address |src|.
-	//
-	// On error, returns a non-nil |err|.
-	ReadPacket(buf []byte) (size int, iface *net.Interface, src net.Addr, err error)
-	// Implements ipv4/ipv6 JoinGroup functionality, joining a group address
-	// on the interface |iface|.
-	JoinGroup(iface *net.Interface, group net.Addr) error
-	Close() error
-}
-
-type packetReceiver4 struct {
-	conn *ipv4.PacketConn
-}
-
-func (p *packetReceiver4) ReadPacket(buf []byte) (size int, iface *net.Interface, src net.Addr, err error) {
-	var cm *ipv4.ControlMessage
-	size, cm, src, err = p.conn.ReadFrom(buf)
-	if err != nil {
-		return
-	}
-	iface, err = net.InterfaceByIndex(cm.IfIndex)
-	return
-}
-
-func (p *packetReceiver4) JoinGroup(iface *net.Interface, group net.Addr) error {
-	return p.conn.JoinGroup(iface, group)
-}
-
-func (p *packetReceiver4) Close() error {
-	err := p.conn.Close()
-	p.conn = nil
-	return err
-}
-
-type packetReceiver6 struct {
-	conn *ipv6.PacketConn
-}
-
-func (p *packetReceiver6) ReadPacket(buf []byte) (size int, iface *net.Interface, src net.Addr, err error) {
-	var cm *ipv6.ControlMessage
-	size, cm, src, err = p.conn.ReadFrom(buf)
-	if err != nil {
-		return
-	}
-	iface, err = net.InterfaceByIndex(cm.IfIndex)
-	return
-}
-
-func (p *packetReceiver6) JoinGroup(iface *net.Interface, group net.Addr) error {
-	return p.conn.JoinGroup(iface, group)
-}
-
-func (p *packetReceiver6) Close() error {
-	err := p.conn.Close()
-	p.conn = nil
-	return err
-}
-
-type mDNSConn interface {
-	Close() error
-	SetIp(ip net.IP) error
-	getIp() net.IP
-	SetAcceptUnicastResponses(accept bool)
-	SendTo(buf bytes.Buffer, dst *net.UDPAddr) error
-	Send(buf bytes.Buffer) error
-	InitReceiver(port int) error
-	// Starts a goroutine to listen for packets incoming on the multicast
-	// connection.
-	//
-	// If |SetAcceptUnicastResponses| has been set to true, starts a
-	// separate goroutine to listen to incoming unicast packets for each
-	// of the machine's interfaces.
-	//
-	// Returns a read-only channel on which received packets are written.
-	Listen() <-chan receivedPacketInfo
-	JoinGroup(iface net.Interface) error
-	// Connects to the specific port and interface.
-	//
-	// This is primarily for sending packets, but if
-	// |SetAcceptUnicastResponses(true)| has been called, then this
-	// connection becomes bidirectional, and is also used for reading
-	// packets when |Listen()| is later invoked.
-	//
-	// If |SetAcceptUnicastResponses| is called between multiple invocations
-	// of this function, then not all connections will be read from when
-	// |Listen| is called.
-	ConnectTo(port int, ip net.IP, iface *net.Interface) error
-	ReadFrom(buf []byte) (size int, iface *net.Interface, src net.Addr, err error)
-	NewPacketReceiver(net.PacketConn) packetReceiver
-}
-
-type mDNSConnBase struct {
-	dst            net.UDPAddr
-	acceptUnicast  bool
-	receiver       packetReceiver
-	senders        []net.PacketConn
-	ucastReceivers []packetReceiver
-}
-
-func (c *mDNSConnBase) Close() error {
-	if c.receiver != nil {
-		err := c.receiver.Close()
-		c.receiver = nil
-		if err != nil {
-			return err
-		}
-	}
-	for _, receiver := range c.ucastReceivers {
-		if err := receiver.Close(); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func (c *mDNSConnBase) Listen() <-chan receivedPacketInfo {
-	ch := make(chan receivedPacketInfo, 1)
-	startListenLoop(c.receiver, ch)
-	for _, receiver := range c.ucastReceivers {
-		startListenLoop(receiver, ch)
-	}
-	return ch
-}
-
-func (c *mDNSConnBase) getIp() net.IP {
-	return c.dst.IP
-}
-
-func (c *mDNSConnBase) SendTo(buf bytes.Buffer, dst *net.UDPAddr) error {
-	for _, sender := range c.senders {
-		if _, err := sender.WriteTo(buf.Bytes(), dst); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func (c *mDNSConnBase) SetAcceptUnicastResponses(accept bool) {
-	c.acceptUnicast = accept
-}
-
-func (c *mDNSConnBase) Send(buf bytes.Buffer) error {
-	return c.SendTo(buf, &c.dst)
-}
-
-type mDNSConn4 struct {
-	mDNSConnBase
-}
-
-var defaultMDNSMulticastIPv4 = net.ParseIP("224.0.0.251")
-
-// Helper function for the |Listen| method in the |mDNSConn| interface.
-//
-// Accepts write-only channel of receivePacketInfo items.
-//
-// Starts a goroutine which will stop when it cannot read anymore from
-// |receiver|, which will happen in the case of an error (like the connection
-// being closed).  In this case it will send a final receivedPacketInfo instance
-// with only an error code before exiting.
-func startListenLoop(receiver packetReceiver, ch chan<- receivedPacketInfo) {
-	go func() {
-		payloadBuf := make([]byte, 1<<16)
-		for {
-			size, iface, src, err := receiver.ReadPacket(payloadBuf)
-			if err != nil {
-				ch <- receivedPacketInfo{err: err}
-				return
-			}
-			data := make([]byte, size)
-			copy(data, payloadBuf[:size])
-			ch <- receivedPacketInfo{
-				data:  data,
-				iface: iface,
-				src:   src,
-				err:   nil}
-		}
-	}()
-}
-
-func newMDNSConn4() mDNSConn {
-	c := mDNSConn4{}
-	c.SetIp(defaultMDNSMulticastIPv4)
-	return &c
-}
-
-func (c *mDNSConn4) SetIp(ip net.IP) error {
-	if ip4 := ip.To4(); ip4 == nil {
-		panic(fmt.Errorf("Not an IPv-4 address: %v", ip))
-	}
-	c.dst.IP = ip
-	return nil
-}
-
-func (c *mDNSConn4) InitReceiver(port int) error {
-	c.dst.Port = port
-	conn, err := net.ListenUDP("udp4", &c.dst)
-	if err != nil {
-		return err
-	}
-	c.receiver = c.NewPacketReceiver(conn)
-	return nil
-}
-
-func (c *mDNSConn4) NewPacketReceiver(conn net.PacketConn) packetReceiver {
-	conn4 := ipv4.NewPacketConn(conn)
-	conn4.SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true)
-	return &packetReceiver4{conn4}
-}
-
-// This allows us to listen on this specific interface.
-func (c *mDNSConn4) JoinGroup(iface net.Interface) error {
-	if err := c.receiver.JoinGroup(&iface, &c.dst); err != nil {
-		c.Close()
-		return fmt.Errorf("joining %v%%%v: %v", iface, c.dst, err)
-	}
-	return nil
-}
-
-func (c *mDNSConn4) ConnectTo(port int, ip net.IP, iface *net.Interface) error {
-	ip4 := ip.To4()
-	if ip4 == nil {
-		return fmt.Errorf("Not a valid IPv4 address: %v", ip)
-	}
-	conn, err := makeUdpSocketWithReusePort(port, ip4, iface)
-	if err != nil {
-		return err
-	}
-	c.senders = append(c.senders, conn)
-	if c.acceptUnicast {
-		c.ucastReceivers = append(c.ucastReceivers, c.NewPacketReceiver(conn))
-	}
-	return nil
-}
-
-func (c *mDNSConn4) ReadFrom(buf []byte) (int, *net.Interface, net.Addr, error) {
-	return c.receiver.ReadPacket(buf)
-}
-
-type mDNSConn6 struct {
-	mDNSConnBase
-}
-
-var defaultMDNSMulticastIPv6 = net.ParseIP("ff02::fb")
-
-func newMDNSConn6() mDNSConn {
-	c := mDNSConn6{}
-	c.SetIp(defaultMDNSMulticastIPv6)
-	return &c
-}
-
-func (c *mDNSConn6) SetIp(ip net.IP) error {
-	if ip6 := ip.To16(); ip6 == nil {
-		panic(fmt.Errorf("Not an IPv6 address: %v", ip))
-	}
-	c.dst.IP = ip
-	return nil
-}
-
-func (c *mDNSConn6) InitReceiver(port int) error {
-	c.dst.Port = port
-	conn, err := net.ListenUDP("udp6", &c.dst)
-	if err != nil {
-		return err
-	}
-	c.receiver = c.NewPacketReceiver(conn)
-	return nil
-}
-
-func (c *mDNSConn6) NewPacketReceiver(conn net.PacketConn) packetReceiver {
-	conn6 := ipv6.NewPacketConn(conn)
-	conn6.SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true)
-	return &packetReceiver6{conn6}
-}
-
-// This allows us to listen on this specific interface.
-func (c *mDNSConn6) JoinGroup(iface net.Interface) error {
-	if err := c.receiver.JoinGroup(&iface, &c.dst); err != nil {
-		c.Close()
-		return fmt.Errorf("joining %v%%%v: %v", iface, c.dst, err)
-	}
-	return nil
-}
-
-func (c *mDNSConn6) ConnectTo(port int, ip net.IP, iface *net.Interface) error {
-	ip6 := ip.To16()
-	if ip6 == nil {
-		return fmt.Errorf("Not a valid IPv6 address: %v", ip)
-	}
-	conn, err := makeUdpSocketWithReusePort(port, ip6, iface)
-	if err != nil {
-		return err
-	}
-	c.senders = append(c.senders, conn)
-	if c.acceptUnicast {
-		c.ucastReceivers = append(c.ucastReceivers, c.NewPacketReceiver(conn))
-	}
-	return nil
-}
-
-func (c *mDNSConn6) ReadFrom(buf []byte) (int, *net.Interface, net.Addr, error) {
-	return c.receiver.ReadPacket(buf)
-}
-
-type mDNS struct {
-	conn4     mDNSConn
-	conn6     mDNSConn
-	port      int
-	pHandlers []func(net.Interface, net.Addr, Packet)
-	wHandlers []func(net.Addr, error)
-	eHandlers []func(error)
-}
-
-// NewMDNS creates a new object implementing the MDNS interface. Do not forget
-// to call EnableIPv4() or EnableIPv6() to enable listening on interfaces of
-// the corresponding type, or nothing will work.
-func NewMDNS() MDNS {
-	m := mDNS{}
-	m.conn4 = nil
-	m.conn6 = nil
-	return &m
-}
-
-func (m *mDNS) EnableIPv4() {
-	if m.conn4 == nil {
-		m.conn4 = newMDNSConn4()
-	}
-}
-
-func (m *mDNS) EnableIPv6() {
-	if m.conn6 == nil {
-		m.conn6 = newMDNSConn6()
-	}
-}
-
-func (m *mDNS) SetAcceptUnicastResponses(accept bool) {
-	if m.conn4 != nil {
-		m.conn4.SetAcceptUnicastResponses(accept)
-	}
-	if m.conn6 != nil {
-		m.conn6.SetAcceptUnicastResponses(accept)
-	}
-}
-
-func (m *mDNS) Close() {
-	if m.conn4 != nil {
-		m.conn4.Close()
-		m.conn4 = nil
-	}
-	if m.conn6 != nil {
-		m.conn6.Close()
-		m.conn6 = nil
-	}
-}
-
-func (m *mDNS) SetAddress(address string) error {
-	ip := net.ParseIP(address)
-	if ip == nil {
-		return fmt.Errorf("Not a valid IP address: %v", address)
-	}
-	if ip4 := ip.To4(); ip4 != nil {
-		if m.conn4 == nil {
-			return fmt.Errorf("mDNS IPv4 support is disabled")
-		}
-		return m.conn4.SetIp(ip4)
-	} else {
-		if m.conn6 == nil {
-			return fmt.Errorf("mDNS IPv6 support is disabled")
-		}
-		return m.conn6.SetIp(ip.To16())
-	}
-}
-
-func (m *mDNS) ipToSend() net.IP {
-	if m.conn4 != nil {
-		return m.conn4.getIp()
-	}
-	if m.conn6 != nil {
-		return m.conn6.getIp()
-	}
-	return nil
-}
-
-// AddHandler calls f on every Packet received.
-func (m *mDNS) AddHandler(f func(net.Interface, net.Addr, Packet)) {
-	m.pHandlers = append(m.pHandlers, f)
-}
-
-// AddWarningHandler calls f on every non-fatal error.
-func (m *mDNS) AddWarningHandler(f func(net.Addr, error)) {
-	m.wHandlers = append(m.wHandlers, f)
-}
-
-// AddErrorHandler calls f on every fatal error. After
-// all active handlers are called, m will stop listening and
-// close it's connection so this function will not be called twice.
-func (m *mDNS) AddErrorHandler(f func(error)) {
-	m.eHandlers = append(m.eHandlers, f)
-}
-
-// SendTo serializes and sends packet to dst. If dst is a multicast
-// address then packet is multicast to the corresponding group on
-// all interfaces. Note that start must be called prior to making this
-// call.
-func (m *mDNS) SendTo(packet Packet, dst *net.UDPAddr) error {
-	var buf bytes.Buffer
-	// TODO(jakehehrlich): Add checking that the packet is well formed.
-	if err := packet.serialize(&buf); err != nil {
-		return err
-	}
-	if dst.IP.To4() != nil {
-		if m.conn4 != nil {
-			return m.conn4.SendTo(buf, dst)
-		} else {
-			return fmt.Errorf("IPv4 was not enabled!")
-		}
-	} else {
-		if m.conn6 != nil {
-			return m.conn6.SendTo(buf, dst)
-		} else {
-			return fmt.Errorf("IPv6 was not enabled!")
-		}
-	}
-}
-
-// Send serializes and sends packet out as a multicast to all interfaces
-// using the port that m is listening on. Note that Start must be
-// called prior to making this call.
-func (m *mDNS) Send(packet Packet) error {
-	var buf bytes.Buffer
-	// TODO(jakehehrlich): Add checking that the packet is well formed.
-	if err := packet.serialize(&buf); err != nil {
-		return err
-	}
-	var err4 error
-	if m.conn4 != nil {
-		err4 = m.conn4.Send(buf)
-	}
-	var err6 error
-	if m.conn6 != nil {
-		err6 = m.conn6.Send(buf)
-	}
-	if err4 != nil {
-		return err4
-	}
-	return err6
-}
-
-func makeUdpSocketWithReusePort(port int, ip net.IP, iface *net.Interface) (net.PacketConn, error) {
-	is_ipv6 := ip.To4() == nil
-	network := "udp4"
-	var zone string
-	if is_ipv6 {
-		network = "udp6"
-		zone = iface.Name
-	}
-	address := (&net.UDPAddr{IP: ip, Port: port, Zone: zone}).String()
-
-	// A net.ListenConfig control function to set both SO_REUSEADDR and SO_REUSEPORT
-	// on a given socket fd. Only works on Unix-based systems, not Windows. For portability
-	// an alternative might be to use something like the go-reuseport library.
-	control := func(network, address string, c syscall.RawConn) error {
-		var err error
-		c.Control(func(fd uintptr) {
-			err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
-			if err != nil {
-				return
-			}
-
-			err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
-			if err != nil {
-				return
-			}
-		})
-		return err
-	}
-
-	listenConfig := net.ListenConfig{Control: control}
-	return listenConfig.ListenPacket(context.Background(), network, address)
-}
-
-// Start causes m to start listening for MDNS packets on all interfaces on
-// the specified port. Listening will stop if ctx is done.
-func (m *mDNS) Start(ctx context.Context, port int) error {
-	if m.conn4 != nil {
-		if err := m.conn4.InitReceiver(port); err != nil {
-			return err
-		}
-	}
-	if m.conn6 != nil {
-		if err := m.conn6.InitReceiver(port); err != nil {
-			return err
-		}
-	}
-	// Now we need to join this connection to every interface that supports
-	// Multicast.
-	ifaces, err := net.Interfaces()
-	if err != nil {
-		m.Close()
-		return fmt.Errorf("listing interfaces: %v", err)
-	}
-	// We need to make sure to handle each interface.
-	for _, iface := range ifaces {
-		if iface.Flags&net.FlagMulticast == 0 || iface.Flags&net.FlagUp == 0 {
-			continue
-		}
-		if m.conn4 != nil {
-			if err := m.conn4.JoinGroup(iface); err != nil {
-				m.Close()
-				return fmt.Errorf("joining %v: %v", iface, err)
-			}
-		}
-		if m.conn6 != nil {
-			if err := m.conn6.JoinGroup(iface); err != nil {
-				m.Close()
-				return fmt.Errorf("joining %v: %v", iface, err)
-			}
-		}
-		addrs, err := iface.Addrs()
-		if err != nil {
-			return fmt.Errorf("getting addresses of %v: %v", iface, err)
-		}
-		// When both IPv4 and IPv6 are enabled, only connect to the interface
-		// through its IPv6 address if it doesn't have an IPv4 one.
-		for _, addr := range addrs {
-			var ip net.IP
-			switch v := addr.(type) {
-			case *net.IPNet:
-				ip = v.IP
-			case *net.IPAddr:
-				ip = v.IP
-			}
-			if ip == nil {
-				continue
-			}
-			ip4 := ip.To4()
-			if m.conn4 != nil && ip4 != nil {
-				if err := m.conn4.ConnectTo(port, ip4, &iface); err != nil {
-					return fmt.Errorf("creating socket for %v via %v: %v", iface, ip, err)
-				}
-				break
-			}
-			if m.conn6 != nil && ip4 == nil {
-				if err := m.conn6.ConnectTo(port, ip, &iface); err != nil {
-					return fmt.Errorf("creating socket for %v via %v: %v", iface, ip, err)
-				}
-				break
-			}
-		}
-	}
-	go func() {
-		// NOTE: This defer statement will close connections, which will force
-		// the goroutines started by startListenLoop() to exit.
-		defer m.Close()
-
-		var chan4 <-chan receivedPacketInfo
-		var chan6 <-chan receivedPacketInfo
-
-		if m.conn4 != nil {
-			chan4 = m.conn4.Listen()
-		}
-		if m.conn6 != nil {
-			chan6 = m.conn6.Listen()
-		}
-		for {
-			var received receivedPacketInfo
-
-			select {
-			case <-ctx.Done():
-				return
-			case received = <-chan4:
-				break
-			case received = <-chan6:
-				break
-			}
-
-			if received.err != nil {
-				for _, e := range m.eHandlers {
-					go e(received.err)
-				}
-				return
-			}
-
-			var packet Packet
-			if err := packet.deserialize(received.data, bytes.NewBuffer(received.data)); err != nil {
-				for _, w := range m.wHandlers {
-					go w(received.src, err)
-				}
-				continue
-			}
-
-			for _, p := range m.pHandlers {
-				go p(*received.iface, received.src, packet)
-			}
-		}
-	}()
-	return nil
-}
-
-// QuestionPacket constructs and returns a packet that
-// requests the ip address associated with domain.
-func QuestionPacket(domain string) Packet {
-	return Packet{
-		Header: Header{QDCount: 2},
-		Questions: []Question{
-			{
-				Domain:  domain,
-				Type:    AAAA,
-				Class:   IN,
-				Unicast: false,
-			},
-			{
-				Domain:  domain,
-				Type:    A,
-				Class:   IN,
-				Unicast: false,
-			},
-		},
-	}
-}
-
-// AnswerPacket constructs and returns a packet that
-// gives a response to the
-func AnswerPacket(domain string, ip net.IP) Packet {
-	return Packet{
-		Header: Header{ANCount: 1},
-		Answers: []Record{
-			{
-				Domain: domain,
-				Type:   IpToDnsRecordType(ip),
-				Class:  IN,
-				Flush:  false,
-				Data:   []byte(ip),
-			},
-		},
-	}
-}
diff --git a/net/mdns/mdns_test.go b/net/mdns/mdns_test.go
deleted file mode 100644
index fec008a..0000000
--- a/net/mdns/mdns_test.go
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2019 The Fuchsia 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 mdns
-
-import (
-	"bytes"
-	"net"
-	"testing"
-
-	"github.com/google/go-cmp/cmp"
-)
-
-func TestUint16(t *testing.T) {
-	var buf bytes.Buffer
-	v := uint16(6857)
-	writeUint16(&buf, v)
-	var v2 uint16
-	readUint16(&buf, &v2)
-	if d := cmp.Diff(v, v2); d != "" {
-		t.Errorf("read/writeUint16: mismatch (-wrote +read)\n%s", d)
-	}
-}
-
-func TestUint32(t *testing.T) {
-	var buf bytes.Buffer
-	v := uint32(6857)
-	writeUint32(&buf, v)
-	var v2 uint32
-	readUint32(&buf, &v2)
-	if d := cmp.Diff(v, v2); d != "" {
-		t.Errorf("read/writeUint32: mismatch (-wrote +read)\n%s", d)
-	}
-}
-
-func TestHeader(t *testing.T) {
-	var buf bytes.Buffer
-	v := Header{
-		ID:      593,
-		Flags:   795,
-		QDCount: 5839,
-		ANCount: 9009,
-		NSCount: 8583,
-		ARCount: 7764,
-	}
-	v.serialize(&buf)
-	var v2 Header
-	v2.deserialize(buf.Bytes(), &buf)
-	if d := cmp.Diff(v, v2); d != "" {
-		t.Errorf("header (de)serialize: mismatch (-serialize +deserialize)\n%s", d)
-	}
-}
-
-func TestDomain(t *testing.T) {
-	var buf bytes.Buffer
-	v := "this.is.a.random.domain.to.check"
-	writeDomain(&buf, v)
-	var v2 string
-	readDomain(buf.Bytes(), &buf, &v2)
-	if d := cmp.Diff(v, v2); d != "" {
-		t.Errorf("read/writeDomain: mismatch (-wrote +read)\n%s", d)
-	}
-}
-
-func TestQuestion(t *testing.T) {
-	var buf bytes.Buffer
-	v := Question{
-		Domain:  "some.random.thing.local",
-		Type:    5954,
-		Unicast: true,
-	}
-	v.serialize(&buf)
-	var v2 Question
-	v2.deserialize(buf.Bytes(), &buf)
-	if d := cmp.Diff(v, v2); d != "" {
-		t.Errorf("question (de)serialize: mismatch (-serialize +deserialize)\n%s", d)
-	}
-}
-
-func TestRecord(t *testing.T) {
-	var buf bytes.Buffer
-	v := Record{
-		Domain: "some.random.thing",
-		Type:   1234,
-		Class:  8765,
-		Flush:  true,
-		TTL:    18656,
-		Data:   []byte{45, 145, 253, 167, 34, 74},
-	}
-	v.serialize(&buf)
-	var v2 Record
-	v2.deserialize(buf.Bytes(), &buf)
-	if d := cmp.Diff(v, v2); d != "" {
-		t.Errorf("record (de)serialize: mismatch (-serialize +deserialize)\n%s", d)
-	}
-}
-
-func TestIpToDnsRecordType(t *testing.T) {
-	ip1 := "224.0.0.251"
-	if addrType := IpToDnsRecordType(net.ParseIP(ip1)); addrType != A {
-		t.Errorf("IpToDnsRecordType(%s) mismatch %v, wanted %v", ip1, addrType, A)
-	}
-	ip2 := "ff2e::fb"
-	if addrType := IpToDnsRecordType(net.ParseIP(ip2)); addrType != AAAA {
-		t.Errorf("IpToDnsRecordType(%s) mismatch %v, wanted %v", ip2, addrType, AAAA)
-	}
-}
-
-func TestSetAddress(t *testing.T) {
-	m := NewMDNS()
-	m.EnableIPv4()
-	got := m.ipToSend()
-	// Should send to the default address.
-	want := net.ParseIP("224.0.0.251")
-	if d := cmp.Diff(want, got); d != "" {
-		t.Errorf("ipToSend (default): mismatch (-want +got)\n%s", d)
-	}
-
-	if err := m.SetAddress("11.22.33.44"); err != nil {
-		t.Errorf("SetAddress() returned error: %s", err)
-	} else {
-		got = m.ipToSend()
-		// Should send to the given custom address.
-		want = net.ParseIP("11.22.33.44")
-		if d := cmp.Diff(want, got); d != "" {
-			t.Errorf("ipToSend (custom): mismatch (-want +got)\n%s", d)
-		}
-	}
-
-	m = NewMDNS()
-	m.EnableIPv6()
-	got = m.ipToSend()
-	want = net.ParseIP("ff02::fb")
-	if d := cmp.Diff(want, got); d != "" {
-		t.Errorf("ipToSend (default): mismatch (-want +got)\n%s", d)
-	}
-
-	if err := m.SetAddress("11:22::33:44"); err != nil {
-		t.Errorf("SetAddress() returned error: %s", err)
-	} else {
-		got = m.ipToSend()
-		// Should send to the given custom address.
-		want = net.ParseIP("11:22::33:44")
-		if d := cmp.Diff(want, got); d != "" {
-			t.Errorf("ipToSend (custom): mismatch (-want +got)\n%s", d)
-		}
-	}
-}
diff --git a/net/mdnstool/cmd/main.go b/net/mdnstool/cmd/main.go
deleted file mode 100644
index 12a35be..0000000
--- a/net/mdnstool/cmd/main.go
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright 2019 The Fuchsia 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 (
-	"context"
-	"flag"
-	"fmt"
-	"log"
-	"net"
-	"os"
-	"time"
-
-	"go.fuchsia.dev/tools/net/mdns"
-)
-
-// TODO(jakehehrlich): This doesn't retry or anything, it just times out. It would
-// be nice to make this more robust.
-// sends out a request for the ip of domain. Waits for up to |dur| amount of time.
-// Will stop waiting for a response if ctx is done. The default port for mDNS is
-// 5353 but you're allowed to specify via port.
-func mDNSResolve(ctx context.Context, domain string, port int, dur time.Duration) (net.IP, error) {
-	m := mdns.NewMDNS()
-	m.EnableIPv4()
-	m.EnableIPv6()
-	out := make(chan net.IP)
-	// Add all of our handlers
-	m.AddHandler(func(iface net.Interface, addr net.Addr, packet mdns.Packet) {
-		for _, a := range packet.Answers {
-			if a.Class != mdns.IN || a.Domain != domain {
-				continue
-			}
-			if a.Type == mdns.A || a.Type == mdns.AAAA {
-				out <- net.IP(a.Data)
-				return
-			}
-		}
-	})
-	m.AddWarningHandler(func(addr net.Addr, err error) {
-		log.Printf("from: %v warn: %v", addr, err)
-	})
-	errs := make(chan error)
-	m.AddErrorHandler(func(err error) {
-		errs <- err
-	})
-	// Before we start we need to add a context to timeout with
-	ctx, cancel := context.WithTimeout(ctx, dur)
-	defer cancel()
-	// Start up the mdns loop
-	if err := m.Start(ctx, port); err != nil {
-		return nil, fmt.Errorf("starting mdns: %v", err)
-	}
-	// Send a packet requesting an answer to "what is the IP of |domain|?"
-	m.Send(mdns.QuestionPacket(domain))
-	// Now wait for either a timeout, an error, or an answer.
-	select {
-	case <-ctx.Done():
-		return nil, fmt.Errorf("timeout")
-	case err := <-errs:
-		return nil, err
-	case ip := <-out:
-		return ip, nil
-	}
-}
-
-// TODO(jakehehrlich): Add support for unicast.
-// mDNSPublish will respond to requests for the ip of domain by responding with ip.
-// Note that this responds on both IPv4 and IPv6 interfaces, independent on the type
-// of ip itself. You can stop the server by canceling ctx. Even though mDNS is
-// generally on 5353 you can specify any port via port.
-func mDNSPublish(ctx context.Context, domain string, port int, ip net.IP) error {
-	// Now create and mDNS server
-	m := mdns.NewMDNS()
-	m.EnableIPv4()
-	m.EnableIPv6()
-	addrType := mdns.IpToDnsRecordType(ip)
-	m.AddHandler(func(iface net.Interface, addr net.Addr, packet mdns.Packet) {
-		log.Printf("from %v packet %v", addr, packet)
-		for _, q := range packet.Questions {
-			if q.Class == mdns.IN && q.Type == addrType && q.Domain == domain {
-				// We ignore the Unicast bit here but in theory this could be handled via SendTo and addr.
-				m.Send(mdns.AnswerPacket(domain, ip))
-			}
-		}
-	})
-	m.AddWarningHandler(func(addr net.Addr, err error) {
-		log.Printf("from: %v warn: %v", addr, err)
-	})
-	errs := make(chan error)
-	m.AddErrorHandler(func(err error) {
-		errs <- err
-	})
-	// Now start the server.
-	if err := m.Start(ctx, port); err != nil {
-		return fmt.Errorf("starting mdns: %v", err)
-	}
-	// Now wait for either a timeout, an error, or an answer.
-	select {
-	case <-ctx.Done():
-		return nil
-	case err := <-errs:
-		return err
-	}
-}
-
-// This function makes a faulty assumption. It assumes that the first
-// multicast interface it finds with an ipv4 address will be the
-// address the user wants. There isn't really a way to guess exactly
-// the address that the user will want. If an IPv6 address is needed, then
-// using the -ip <address> option is required.
-func getMulticastIP() net.IP {
-	ifaces, err := net.Interfaces()
-	if err != nil {
-		return nil
-	}
-	for _, i := range ifaces {
-		if i.Flags&net.FlagMulticast == 0 {
-			continue
-		}
-		addrs, err := i.Addrs()
-		if err != nil {
-			return nil
-		}
-		for _, addr := range addrs {
-			switch v := addr.(type) {
-			case *net.IPNet:
-				if ip4 := v.IP.To4(); ip4 != nil {
-					return ip4
-				}
-			}
-		}
-	}
-	return nil
-}
-
-var (
-	port    int
-	timeout int
-	ipAddr  string
-)
-
-func init() {
-	flag.StringVar(&ipAddr, "ip", "", "the ip to respond with when serving.")
-	flag.IntVar(&port, "port", 5353, "the port your mDNS servers operate on")
-	flag.IntVar(&timeout, "timeout", 2000, "the number of milliseconds before declaring a timeout")
-}
-
-func publish(args ...string) error {
-	if len(args) < 1 {
-		return fmt.Errorf("missing domain to serve")
-	}
-	var ip net.IP
-	if ipAddr == "" {
-		ip = getMulticastIP()
-		if ip = getMulticastIP(); ip == nil {
-			return fmt.Errorf("could not find a suitable ip")
-		}
-	} else {
-		if ip = net.ParseIP(ipAddr); ip == nil {
-			return fmt.Errorf("'%s' is not a valid ip address", ipAddr)
-		}
-	}
-	domain := args[0]
-	if err := mDNSPublish(context.Background(), domain, port, ip); err != nil {
-		return err
-	}
-	return nil
-}
-
-func resolve(args ...string) error {
-	if len(args) < 1 {
-		return fmt.Errorf("missing domain to request")
-	}
-	domain := args[0]
-	ip, err := mDNSResolve(context.Background(), domain, port, time.Duration(timeout)*time.Millisecond)
-	if err != nil {
-		return err
-	}
-	fmt.Printf("%v\n", ip)
-	return nil
-}
-
-func main() {
-	flag.Parse()
-	args := flag.Args()
-	if len(args) < 1 {
-		log.Printf("error: no command given")
-		os.Exit(1)
-	}
-	mp := map[string]func(...string) error{
-		"publish": publish,
-		"resolve": resolve,
-	}
-	if f, ok := mp[args[0]]; ok {
-		if err := f(args[1:]...); err != nil {
-			log.Printf("error: %v", err)
-		}
-		return
-	} else {
-		log.Printf("error: %s is not a command", args[0])
-	}
-	os.Exit(1)
-}
diff --git a/net/netboot/loglistener.go b/net/netboot/loglistener.go
deleted file mode 100644
index 96a9661..0000000
--- a/net/netboot/loglistener.go
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2018 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file implements the Zircon loglistener protocol.
-package netboot
-
-import (
-	"bytes"
-	"encoding/binary"
-	"errors"
-	"net"
-	"os"
-	"syscall"
-
-	"golang.org/x/sys/unix"
-)
-
-// Magic constants used by the netboot protocol.
-const (
-	debugMagic = 0xAEAE1123 // see system/public/zircon/boot/netboot.h
-)
-
-// Port numbers used by the netboot protocol.
-const (
-	debugPort = 33337 // debugging log port
-)
-
-// logpacket is the network logging protocol packet.
-type logpacket struct {
-	Magic    uint32
-	Seqno    uint32
-	Nodename [64]byte
-	Data     [1216]byte
-}
-
-// LogListener is Zircon's debug log listener.
-type LogListener struct {
-	seq      uint32
-	conn     net.PacketConn
-	nodename string
-}
-
-// NewLogListener creates and connects a new instance of debug log listener.
-func NewLogListener(nodename string) (*LogListener, error) {
-	syscall.ForkLock.RLock()
-	fd, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
-	if err == nil {
-		unix.CloseOnExec(fd)
-	}
-	syscall.ForkLock.RUnlock()
-	if err != nil {
-		return nil, err
-	}
-
-	// SO_REUSEADDR and SO_REUSEPORT allows binding to the same port multiple
-	// times which is necessary in the case when there are multiple instances.
-	if err := syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, unix.SO_REUSEADDR, 1); err != nil {
-		syscall.Close(fd)
-		return nil, err
-	}
-
-	if err := syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
-		syscall.Close(fd)
-		return nil, err
-	}
-
-	// Bind the socket to the default debug log listener port.
-	if err := syscall.Bind(fd, &syscall.SockaddrInet6{Port: debugPort}); err != nil {
-		syscall.Close(fd)
-		return nil, err
-	}
-
-	f := os.NewFile(uintptr(fd), "")
-	conn, err := net.FilePacketConn(f)
-	f.Close()
-	if err != nil {
-		return nil, err
-	}
-
-	return &LogListener{
-		conn:     conn,
-		nodename: nodename,
-	}, nil
-}
-
-// Listen receive a single debug log packet.
-func (l *LogListener) Listen() (string, error) {
-	b := make([]byte, 4096)
-
-	// Wait for logpacket.
-	_, addr, err := l.conn.ReadFrom(b)
-	if err != nil {
-		return "", err
-	}
-
-	var pkt logpacket
-	if err := binary.Read(bytes.NewReader(b), binary.LittleEndian, &pkt); err != nil {
-		return "", err
-	}
-	if pkt.Magic != debugMagic {
-		// Not a valid debug packet.
-		return "", errors.New("invalid magic")
-	}
-	name, err := netbootString(pkt.Nodename[:])
-	if err != nil {
-		return "", err
-	}
-	if name != l.nodename {
-		// Not a packet from our node.
-		return "", errors.New("invalid nodename")
-	}
-
-	var data string
-	if pkt.Seqno != l.seq {
-		data, err = netbootString(pkt.Data[:])
-		if err != nil {
-			return data, err
-		}
-		l.seq = pkt.Seqno
-	}
-
-	// Acknowledge the packet.
-	if _, err = l.conn.WriteTo(b[:8], addr); err != nil {
-		return "", err
-	}
-
-	return data, nil
-}
-
-// Close shuts down the log listener underlying connection.
-func (l *LogListener) Close() error {
-	return l.conn.Close()
-}
diff --git a/net/netboot/netboot.go b/net/netboot/netboot.go
deleted file mode 100644
index 49ac636..0000000
--- a/net/netboot/netboot.go
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright 2017 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This package implements the Zircon netboot protocol.
-//
-// TODO(fxb/35957): Add testing for this package.
-package netboot
-
-import (
-	"bytes"
-	"encoding/binary"
-	"errors"
-	"fmt"
-	"net"
-	"strings"
-	"time"
-)
-
-// Magic constants used by the netboot protocol.
-const (
-	magic = 0xAA774217 // see system/public/zircon/boot/netboot.h
-)
-
-// Port numbers used by the netboot protocol.
-const (
-	serverPort = 33330 // netboot server port
-	advertPort = 33331 // advertisement port
-)
-
-// Commands supported by the netboot protocol.
-const (
-	cmdCommand  = uint32(1)  // command
-	cmdSendFile = uint32(2)  // send file
-	cmdData     = uint32(3)  // data
-	cmdBoot     = uint32(4)  // boot command
-	cmdQuery    = uint32(5)  // query command
-	cmdShell    = uint32(6)  // shell command
-	cmdOpen     = uint32(7)  // open file
-	cmdRead     = uint32(8)  // read data
-	cmdWrite    = uint32(9)  // write data
-	cmdClose    = uint32(10) // close file
-	cmdLastData = uint32(11) //
-	cmdReboot   = uint32(12) // reboot command
-)
-
-// Client implements the netboot protocol.
-type Client struct {
-	Port    int
-	Cookie  uint32
-	Timeout time.Duration
-	Wait    bool
-}
-
-// netbootHeader is the netboot protocol message header.
-type netbootHeader struct {
-	Magic  uint32
-	Cookie uint32
-	Cmd    uint32
-	Arg    uint32
-}
-
-// netbootMessage is the netboot protocol message.
-type netbootMessage struct {
-	Header netbootHeader
-	Data   [1024]byte
-}
-
-// NewClient creates a new Client instance.
-func NewClient(timeout time.Duration) *Client {
-	return &Client{
-		Timeout: timeout,
-		Cookie:  uint32(0x12345678),
-	}
-}
-
-// Discover resolves the address of host and returns either the netsvc or
-// Fuchsia address dependending on the value of fuchsia.
-func (n *Client) Discover(nodename string, fuchsia bool) (*net.UDPAddr, error) {
-	conn, err := net.ListenUDP("udp6", &net.UDPAddr{IP: net.IPv6zero})
-	if err != nil {
-		return nil, fmt.Errorf("failed to bind to udp6 port: %v\n", err)
-	}
-	defer conn.Close()
-
-	n.Cookie++
-	req := netbootMessage{
-		Header: netbootHeader{
-			Magic:  magic,
-			Cookie: n.Cookie,
-			Cmd:    cmdQuery,
-			Arg:    0,
-		},
-	}
-	copy(req.Data[:], nodename)
-
-	var buf bytes.Buffer
-	if err := binary.Write(&buf, binary.LittleEndian, req); err != nil {
-		return nil, err
-	}
-
-	// Enumerate all available network interfaces.
-	ifaces, err := net.Interfaces()
-	if err != nil {
-		return nil, fmt.Errorf("failed to enumerate network interfaces: %v\n", err)
-	}
-	for _, iface := range ifaces {
-		// Skip interfaces that are down.
-		if iface.Flags&net.FlagUp == 0 {
-			continue
-		}
-		// Skip loopback interfaces.
-		if iface.Flags&net.FlagLoopback != 0 {
-			continue
-		}
-		addrs, err := iface.Addrs()
-		if err != nil {
-			return nil, err
-		}
-
-		// Enumerate all interface addresses and find the usable ones.
-		for _, addr := range addrs {
-			var ip net.IP
-			switch v := addr.(type) {
-			case *net.IPNet:
-				ip = v.IP
-			case *net.IPAddr:
-				ip = v.IP
-			}
-			if ip == nil || ip.To16() == nil {
-				continue
-			}
-
-			// Send a broadcast query command using the interface.
-			conn.WriteToUDP(buf.Bytes(), &net.UDPAddr{
-				IP:   net.IPv6linklocalallnodes,
-				Port: serverPort,
-				Zone: iface.Name,
-			})
-		}
-	}
-
-	// Wait for response, this is a best effort approach so we may not receive
-	// any response if there're no usable interfaces or no devices connected.
-	conn.SetReadDeadline(time.Now().Add(n.Timeout))
-
-	b := make([]byte, 4096)
-	_, addr, err := conn.ReadFromUDP(b)
-	if err != nil {
-		return nil, err
-	}
-
-	r := bytes.NewReader(b)
-	var res netbootMessage
-	if err := binary.Read(r, binary.LittleEndian, &res); err != nil {
-		return nil, err
-	}
-
-	data, err := netbootString(res.Data[:])
-	if err != nil {
-		return nil, err
-	}
-	// The query packet payload contains the nodename.
-	if data != nodename {
-		return nil, fmt.Errorf("invalid nodename `%s`", data)
-	}
-
-	if fuchsia {
-		// The netstack link-local address has 11th byte always set to 0xff, set
-		// this byte to transform netsvc address to netstack address if needed.
-		addr.IP[11] = 0xff
-	}
-
-	return addr, nil
-}
-
-// Beacon receives the beacon packet, returning the address of the sender.
-func (n *Client) Beacon() (*net.UDPAddr, error) {
-	conn, err := net.ListenUDP("udp6", &net.UDPAddr{
-		IP:   net.IPv6zero,
-		Port: advertPort,
-	})
-	defer conn.Close()
-
-	conn.SetReadDeadline(time.Now().Add(n.Timeout))
-
-	b := make([]byte, 4096)
-	_, addr, err := conn.ReadFromUDP(b)
-	if err != nil {
-		return nil, err
-	}
-
-	r := bytes.NewReader(b)
-	var res netbootMessage
-	if err := binary.Read(r, binary.LittleEndian, &res); err != nil {
-		return nil, err
-	}
-
-	data, err := netbootString(res.Data[:])
-	if err != nil {
-		return nil, err
-	}
-	// The query packet payload contains fields separated by ;.
-	for _, f := range strings.Split(string(data[:]), ";") {
-		// The field has a key=value format.
-		vars := strings.SplitN(f, "=", 2)
-		// The field with the "nodename" key contains the name of the device.
-		if vars[0] == "nodename" {
-			return addr, nil
-		}
-	}
-
-	return nil, errors.New("no valid beacon")
-}
-
-// Boot sends a boot packet to the address.
-func (n *Client) Boot(addr *net.UDPAddr) error {
-	n.Cookie++
-	msg := &netbootHeader{
-		Magic:  magic,
-		Cookie: n.Cookie,
-		Cmd:    cmdBoot,
-		Arg:    0,
-	}
-	if err := sendPacket(msg, addr); err != nil {
-		return fmt.Errorf("failed to send boot command: %v\n", err)
-	}
-	return nil
-}
-
-// Reboot sends a reboot packet the address.
-func (n *Client) Reboot(addr *net.UDPAddr) error {
-	n.Cookie++
-	msg := &netbootHeader{
-		Magic:  magic,
-		Cookie: n.Cookie,
-		Cmd:    cmdReboot,
-		Arg:    0,
-	}
-	if err := sendPacket(msg, addr); err != nil {
-		return fmt.Errorf("failed to send reboot command: %v\n", err)
-	}
-	return nil
-}
-
-func sendPacket(msg *netbootHeader, addr *net.UDPAddr) error {
-	if msg == nil {
-		return errors.New("no message provided")
-	}
-	var buf bytes.Buffer
-	if err := binary.Write(&buf, binary.LittleEndian, *msg); err != nil {
-		return err
-	}
-
-	conn, err := net.ListenUDP("udp6", &net.UDPAddr{IP: net.IPv6zero})
-	if err != nil {
-		return fmt.Errorf("failed to create a socket: %v\n", err)
-	}
-	defer conn.Close()
-
-	_, err = conn.WriteToUDP(buf.Bytes(), &net.UDPAddr{
-		IP:   addr.IP,
-		Port: serverPort,
-		Zone: addr.Zone,
-	})
-	return err
-}
-
-func netbootString(bs []byte) (string, error) {
-	for i, b := range bs {
-		if b == 0 {
-			return string(bs[:i]), nil
-		}
-	}
-	return "", errors.New("no null terminated string found")
-}
diff --git a/net/netutil/netutil.go b/net/netutil/netutil.go
deleted file mode 100644
index 7d3c840..0000000
--- a/net/netutil/netutil.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2018 The Fuchsia 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 netutil
-
-import (
-	"context"
-	"fmt"
-	"net"
-	"time"
-
-	"go.fuchsia.dev/tools/lib/retry"
-	"go.fuchsia.dev/tools/net/netboot"
-)
-
-// GetNodeAddress returns the UDP address corresponding to a given node, specifically
-// the netsvc or fuchsia address dependending on the value of `fuchsia`.
-func GetNodeAddress(ctx context.Context, nodename string, fuchsia bool) (*net.UDPAddr, error) {
-	// Retry, as the netstack might not yet be up.
-	var addr *net.UDPAddr
-	var err error
-	n := netboot.NewClient(time.Second)
-	err = retry.Retry(ctx, retry.WithMaxDuration(&retry.ZeroBackoff{}, time.Minute), func() error {
-		addr, err = n.Discover(nodename, fuchsia)
-		return err
-	}, nil)
-	if err != nil {
-		return nil, fmt.Errorf("cannot find node %q: %v", nodename, err)
-	}
-	return addr, nil
-}
diff --git a/net/serial/serial.go b/net/serial/serial.go
deleted file mode 100644
index da33de2..0000000
--- a/net/serial/serial.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2018 The Fuchsia 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 serial provides support for serial connections.
-package serial
-
-import (
-	"io"
-)
-
-const (
-	defaultBaudRate    = 115200
-	defaultTimeoutSecs = 10
-)
-
-// Open opens a new serial port using defaults.
-func Open(name string) (io.ReadWriteCloser, error) {
-	return OpenWithOptions(name, defaultBaudRate, defaultTimeoutSecs)
-}
-
-// OpenWithOptions opens a new serial port with the given name and baud rate.
-func OpenWithOptions(name string, baudRate int, timeoutSecs int) (io.ReadWriteCloser, error) {
-	return open(name, baudRate, timeoutSecs)
-}
diff --git a/net/serial/serial_darwin.go b/net/serial/serial_darwin.go
deleted file mode 100644
index 7e6f0ce..0000000
--- a/net/serial/serial_darwin.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2018 The Fuchsia 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 serial
-
-import (
-	"errors"
-	"io"
-)
-
-func open(name string, baudRate int, timeoutSecs int) (io.ReadWriteCloser, error) {
-	return nil, errors.New("not supported")
-}
diff --git a/net/serial/serial_linux.go b/net/serial/serial_linux.go
deleted file mode 100644
index 22e7e17..0000000
--- a/net/serial/serial_linux.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2018 The Fuchsia 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 serial
-
-import (
-	"fmt"
-	"io"
-	"os"
-	"unsafe"
-
-	"golang.org/x/sys/unix"
-)
-
-var supportedBaudRates = map[int]uint32{
-	50:      unix.B50,
-	75:      unix.B75,
-	110:     unix.B110,
-	134:     unix.B134,
-	150:     unix.B150,
-	200:     unix.B200,
-	300:     unix.B300,
-	600:     unix.B600,
-	1200:    unix.B1200,
-	1800:    unix.B1800,
-	2400:    unix.B2400,
-	4800:    unix.B4800,
-	9600:    unix.B9600,
-	19200:   unix.B19200,
-	38400:   unix.B38400,
-	57600:   unix.B57600,
-	115200:  unix.B115200,
-	230400:  unix.B230400,
-	460800:  unix.B460800,
-	500000:  unix.B500000,
-	576000:  unix.B576000,
-	921600:  unix.B921600,
-	1000000: unix.B1000000,
-	1152000: unix.B1152000,
-	1500000: unix.B1500000,
-	2000000: unix.B2000000,
-	2500000: unix.B2500000,
-	3000000: unix.B3000000,
-	3500000: unix.B3500000,
-	4000000: unix.B4000000,
-}
-
-func open(name string, baudRate int, timeoutSecs int) (io.ReadWriteCloser, error) {
-	rate, ok := supportedBaudRates[baudRate]
-	if !ok {
-		return nil, fmt.Errorf("unsupported baud rate: %d", baudRate)
-	}
-	if timeoutSecs < 0 || (timeoutSecs*10) > (1<<8) {
-		return nil, fmt.Errorf("timeout must be between 0 and 25, got: %d", timeoutSecs)
-	}
-	f, err := os.OpenFile(name, unix.O_RDWR|unix.O_NOCTTY|unix.O_NONBLOCK, 0666)
-	if err != nil {
-		return nil, err
-	}
-	t := unix.Termios{
-		Iflag:  unix.IGNPAR,
-		Cflag:  unix.CREAD | unix.CLOCAL | unix.CS8 | rate,
-		Ispeed: rate,
-		Ospeed: rate,
-	}
-	t.Cc[unix.VTIME] = uint8(timeoutSecs * 10)
-	_, _, errno := unix.Syscall6(
-		unix.SYS_IOCTL,
-		uintptr(f.Fd()),
-		uintptr(unix.TCSETS),
-		uintptr(unsafe.Pointer(&t)),
-		0,
-		0,
-		0,
-	)
-	if errno != 0 {
-		return nil, errno
-	}
-	if err := unix.SetNonblock(int(f.Fd()), false); err != nil {
-		return nil, err
-	}
-	return f, nil
-}
diff --git a/net/sshutil/sshutil.go b/net/sshutil/sshutil.go
deleted file mode 100644
index 49dbc50..0000000
--- a/net/sshutil/sshutil.go
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2018 The Fuchsia 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 sshutil
-
-import (
-	"context"
-	"crypto/rand"
-	"crypto/rsa"
-	"crypto/x509"
-	"encoding/pem"
-	"fmt"
-	"net"
-	"time"
-
-	"go.fuchsia.dev/tools/lib/retry"
-	"go.fuchsia.dev/tools/net/netutil"
-
-	"golang.org/x/crypto/ssh"
-)
-
-const (
-	// Default SSH server port.
-	SSHPort = 22
-
-	// Default RSA key size.
-	RSAKeySize = 2048
-
-	// The allowed timeout to establish an SSH connection.
-	connTimeout = 5 * time.Second
-	// The total allowed timeout to establish an SSH connection and complete an auth handshake.
-	totalDialTimeout = 10 * time.Second
-
-	sshUser = "fuchsia"
-)
-
-// GeneratePrivateKey generates a private SSH key.
-func GeneratePrivateKey() ([]byte, error) {
-	key, err := rsa.GenerateKey(rand.Reader, RSAKeySize)
-	if err != nil {
-		return nil, err
-	}
-	privateKey := &pem.Block{
-		Type:  "RSA PRIVATE KEY",
-		Bytes: x509.MarshalPKCS1PrivateKey(key),
-	}
-	buf := pem.EncodeToMemory(privateKey)
-
-	return buf, nil
-}
-
-func Connect(ctx context.Context, address net.Addr, config *ssh.ClientConfig) (*ssh.Client, error) {
-	network, err := network(address)
-	if err != nil {
-		return nil, err
-	}
-
-	var client *ssh.Client
-	// TODO: figure out optimal backoff time and number of retries
-	if err := retry.Retry(ctx, retry.WithMaxDuration(&retry.ZeroBackoff{}, time.Minute), func() error {
-		var err error
-		client, err = dialWithTimeout(network, address.String(), config, totalDialTimeout)
-		return err
-	}, nil); err != nil {
-		return nil, fmt.Errorf("cannot connect to address %q: %v", address, err)
-	}
-
-	return client, nil
-}
-
-// ssh.Dial can hang during authentication, the 'timeout' being set in the config only
-// applying to establishment of the initial connection. This function is effectively
-// ssh.Dial with the ability to set a deadline on the underlying connection.
-//
-// See https://github.com/golang/go/issues/21941 for more details on the hang.
-func dialWithTimeout(network, addr string, config *ssh.ClientConfig, timeout time.Duration) (*ssh.Client, error) {
-	conn, err := net.DialTimeout(network, addr, config.Timeout)
-	if err != nil {
-		return nil, err
-	}
-	if err := conn.SetDeadline(time.Now().Add(timeout)); err != nil {
-		conn.Close()
-		return nil, err
-	}
-	c, chans, reqs, err := ssh.NewClientConn(conn, addr, config)
-	if err != nil {
-		conn.Close()
-		return nil, err
-	}
-	if err := conn.SetDeadline(time.Time{}); err != nil {
-		c.Close()
-		return nil, err
-	}
-	return ssh.NewClient(c, chans, reqs), nil
-}
-
-// ConnectToNode connects to the device with the given nodename.
-func ConnectToNode(ctx context.Context, nodename string, config *ssh.ClientConfig) (*ssh.Client, error) {
-	addr, err := netutil.GetNodeAddress(ctx, nodename, true)
-	if err != nil {
-		return nil, err
-	}
-	addr.Port = SSHPort
-	return Connect(ctx, addr, config)
-}
-
-// DefaultSSHConfig returns a basic SSH client configuration.
-func DefaultSSHConfig(privateKey []byte) (*ssh.ClientConfig, error) {
-	signer, err := ssh.ParsePrivateKey(privateKey)
-	if err != nil {
-		return nil, err
-	}
-	return DefaultSSHConfigFromSigners(signer)
-}
-
-// DefaultSSHConfigFromSigners returns a basic SSH client configuration.
-func DefaultSSHConfigFromSigners(signers ...ssh.Signer) (*ssh.ClientConfig, error) {
-	return &ssh.ClientConfig{
-		User:            sshUser,
-		Auth:            []ssh.AuthMethod{ssh.PublicKeys(signers...)},
-		Timeout:         connTimeout,
-		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
-	}, nil
-}
-
-// Returns the network to use to SSH into a device.
-func network(address net.Addr) (string, error) {
-	var ip *net.IP
-
-	// We need these type assertions because the net package (annoyingly) doesn't provide
-	// an interface for objects that have an IP address.
-	switch addr := address.(type) {
-	case *net.UDPAddr:
-		ip = &addr.IP
-	case *net.TCPAddr:
-		ip = &addr.IP
-	case *net.IPAddr:
-		ip = &addr.IP
-	default:
-		return "", fmt.Errorf("unsupported address type: %T", address)
-	}
-
-	if ip.To4() != nil {
-		return "tcp", nil // IPv4
-	}
-	if ip.To16() != nil {
-		return "tcp6", nil // IPv6
-	}
-	return "", fmt.Errorf("cannot infer network for IP address %s", ip.String())
-}
diff --git a/net/sshutil/sshutil_test.go b/net/sshutil/sshutil_test.go
deleted file mode 100644
index 458098b..0000000
--- a/net/sshutil/sshutil_test.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2018 The Fuchsia 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 sshutil
-
-import (
-	"net"
-	"testing"
-)
-
-func TestNetwork(t *testing.T) {
-	tests := []struct {
-		id      int
-		addr    net.Addr
-		family  string
-		wantErr bool
-	}{
-		// Valid tcp addresses.
-		{1, &net.TCPAddr{IP: net.IPv4(1, 2, 3, 4)}, "tcp", false},
-		{2, &net.UDPAddr{IP: net.IPv4(5, 6, 7, 8)}, "tcp", false},
-		{3, &net.IPAddr{IP: net.IPv4(9, 10, 11, 12)}, "tcp", false},
-
-		// Valid tcp6 addresses.
-		{4, &net.TCPAddr{IP: net.IPv6loopback}, "tcp6", false},
-		{5, &net.UDPAddr{IP: net.ParseIP("2001:db8::1")}, "tcp6", false},
-		{6, &net.IPAddr{IP: net.IPv6linklocalallrouters}, "tcp6", false},
-
-		// Invalid IP addresses
-		{7, &net.TCPAddr{IP: net.IP("")}, "", true},
-		{8, &net.UDPAddr{IP: net.IP("123456")}, "", true},
-		{9, &net.IPAddr{IP: nil}, "", true},
-
-		// Invalid net.AddrType
-		{10, &net.UnixAddr{}, "", true},
-	}
-
-	for _, test := range tests {
-		n, err := network(test.addr)
-		if test.wantErr && err == nil {
-			t.Errorf("Test %d: got no error; want error", test.id)
-		} else if !test.wantErr && err != nil {
-			t.Errorf("Test %d: got error %q; want no error", test.id, err)
-		} else if n != test.family {
-			t.Errorf("Test %d: got %q; want %q", test.id, n, test.family)
-		}
-	}
-}
diff --git a/net/tftp/tftp.go b/net/tftp/tftp.go
deleted file mode 100644
index 246808b..0000000
--- a/net/tftp/tftp.go
+++ /dev/null
@@ -1,563 +0,0 @@
-// Copyright 2017 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// TODO(fxb/35958): Add testing for this package.
-package tftp
-
-import (
-	"bytes"
-	"encoding/binary"
-	"errors"
-	"fmt"
-	"io"
-	"net"
-	"strconv"
-	"strings"
-	"time"
-)
-
-const (
-	ServerPort = 33340 // tftp server port
-	ClientPort = 33341 // tftp client port
-)
-
-const (
-	timeout      = 2 * time.Second // default client timeout
-	retries      = 5               // default number of retries
-	blockSize    = 1024            // default block size
-	datagramSize = 1028            // default datagram size
-	windowSize   = 256             // default window size
-)
-
-const (
-	opRrq   = uint8(1) // read request (RRQ)
-	opWrq   = uint8(2) // write request (WRQ)
-	opData  = uint8(3) // data
-	opAck   = uint8(4) // acknowledgement
-	opError = uint8(5) // error
-	opOack  = uint8(6) // option acknowledgment
-)
-
-const (
-	ErrorUndefined        = uint16(0) // Not defined, see error message (if any)
-	ErrorFileNotFound     = uint16(1) // File not found
-	ErrorAccessViolation  = uint16(2) // Access violation
-	ErrorDiskFull         = uint16(3) // Disk full or allocation exceeded
-	ErrorIllegalOperation = uint16(4) // Illegal TFTP operation
-	ErrorUnknownID        = uint16(5) // Unknown transfer ID
-	ErrorFileExists       = uint16(6) // File already exists
-	ErrorNoSuchUser       = uint16(7) // No such user
-	ErrorBadOptions       = uint16(8) // Bad options
-
-	// ErrorBusy is a Fuchsia-specific extension to the set of TFTP error
-	// codes, meant to indicate that the server cannot currently handle a
-	// request, but may be able to at some future time.
-	ErrorBusy = uint16(0x143) // 'B' + 'U' + 'S' + 'Y'
-)
-
-var (
-	ErrShouldWait = fmt.Errorf("target is busy")
-)
-
-type Client struct {
-	Timeout    time.Duration // duration to wait for the client to ack a packet
-	Retries    int           // how many times a packet will be resent
-	BlockSize  uint16        // maximum block size used for file transfers
-	WindowSize uint16        // window size used for file transfers.
-}
-
-func NewClient() *Client {
-	return &Client{
-		Timeout:    timeout,
-		Retries:    retries,
-		BlockSize:  blockSize,
-		WindowSize: windowSize,
-	}
-}
-
-type options struct {
-	timeout      time.Duration
-	blockSize    uint16
-	windowSize   uint16
-	transferSize int64
-}
-
-type Session interface {
-	// Size returns the transfer size, if set.
-	Size() int64
-
-	// RemoteAddr returns the remote adderss.
-	RemoteAddr() net.UDPAddr
-}
-
-// Send sends the filename of length size to server addr with the content being
-// read from the reader.
-//
-// If the server being talked to is running on Fuchsia, this method may return
-// ErrShouldWait, which indicates that the server is currently not ready to
-// handle a new request, but will be in the future. This case should be
-// explicitly handled by the caller.
-func (c *Client) Send(addr *net.UDPAddr, filename string, size int64) (io.ReaderFrom, error) {
-	conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv6zero})
-	if err != nil {
-		return nil, fmt.Errorf("creating socket: %s", err)
-	}
-
-	var b bytes.Buffer
-	writeRequest(&b, opWrq, filename, &options{
-		timeout:      c.Timeout,
-		blockSize:    c.BlockSize,
-		windowSize:   c.WindowSize,
-		transferSize: size,
-	})
-
-	opts, addr, err := c.sendRequest(conn, addr, b.Bytes())
-	if err != nil {
-		conn.Close()
-		if err == ErrShouldWait {
-			return nil, ErrShouldWait
-		}
-		return nil, fmt.Errorf("sending WRQ: %s", err)
-	}
-	b.Reset()
-	if opts.transferSize != size {
-		err := errors.New("transfer size mismatch")
-		abort(conn, addr, ErrorBadOptions, err)
-		return nil, err
-	}
-
-	return &sender{
-		addr:  addr,
-		conn:  conn,
-		opts:  opts,
-		retry: c.Retries,
-	}, nil
-}
-
-type sender struct {
-	addr  *net.UDPAddr
-	conn  *net.UDPConn
-	opts  *options
-	retry int
-}
-
-func (s *sender) Size() (n int64) {
-	return s.opts.transferSize
-}
-
-func (s *sender) RemoteAddr() net.UDPAddr {
-	return *s.addr
-}
-
-func (s *sender) ReadFrom(r io.Reader) (int64, error) {
-	l, err := s.send(r)
-	if err != nil {
-		abort(s.conn, s.addr, ErrorUndefined, err)
-		return l, err
-	}
-	s.conn.Close()
-	return l, nil
-}
-
-func (s *sender) send(r io.Reader) (int64, error) {
-	var n int64    // total number of bytes read
-	var seq uint64 // sequence number denoting the beginning of window
-	b := make([]byte, s.opts.blockSize+4)
-	ra, ok := r.(io.ReaderAt)
-	if !ok {
-		return n, fmt.Errorf("%t does not implement io.ReaderAt", r)
-	}
-
-Loop:
-	for {
-	Attempt:
-		for attempt := 0; attempt < s.retry; attempt++ {
-			for i := uint16(0); uint16(i) < s.opts.windowSize; i++ {
-				block := uint16(seq + uint64(i+1))
-				// Fill the first byte of the command with an arbitrary value to
-				// work around the issue where certain ethernet adapters would
-				// refuse to send the packet on retransmission.
-				b[0] = uint8(attempt)
-				b[1] = opData
-				binary.BigEndian.PutUint16(b[2:], block)
-				off := (seq + uint64(i)) * uint64(s.opts.blockSize)
-				l, err := ra.ReadAt(b[4:], int64(off))
-				n += int64(l)
-				if err != nil && err != io.EOF {
-					return n, fmt.Errorf("reading bytes for block %d: %s", block, err)
-				}
-				isEOF := err == io.EOF
-				if _, err := s.conn.WriteToUDP(b[:l+4], s.addr); err != nil {
-					return n, fmt.Errorf("sending block %d: %s", block, err)
-				}
-				if isEOF {
-					break
-				}
-			}
-
-			s.conn.SetReadDeadline(time.Now().Add(s.opts.timeout))
-
-			for {
-				m, addr, err := s.conn.ReadFromUDP(b[:])
-				if err != nil {
-					if t, ok := err.(net.Error); ok && t.Timeout() {
-						continue Attempt
-					}
-					return n, err
-				}
-				if m < 4 { // packet too small
-					continue
-				}
-				if !addr.IP.Equal(s.addr.IP) || addr.Port != s.addr.Port {
-					continue
-				}
-				break
-			}
-
-			switch b[1] {
-			case opAck:
-				num := binary.BigEndian.Uint16(b[2:4])
-				off := num - uint16(seq) // offset from the start of the window
-				if off > 0 && off <= s.opts.windowSize {
-					seq += uint64(off)
-					if seq*uint64(s.opts.blockSize) >= uint64(s.opts.transferSize) {
-						return n, nil // all data transferred, return number of bytes
-					}
-				}
-				continue Loop
-			case opError:
-				msg, _, _ := netasciiString(b[4:])
-				return n, fmt.Errorf("server aborted transfer: %s", msg)
-			}
-		}
-		return n, errors.New("timeout waiting for ACK")
-	}
-}
-
-// Receive reads the data from filename at the server addr with the content
-// being written to the writer.
-//
-// If the server being talked to is running on a Fuchsia, this method may return
-// ErrShouldWait, which indicates that the server is currently not ready to
-// handle a new request, but will be in the future. This case should be
-// explicitly handled by the caller.
-func (c *Client) Receive(addr *net.UDPAddr, filename string) (io.WriterTo, error) {
-	conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv6zero})
-	if err != nil {
-		return nil, fmt.Errorf("creating socket: %s", err)
-	}
-
-	var b bytes.Buffer
-	writeRequest(&b, opRrq, filename, &options{
-		blockSize:  c.BlockSize,
-		timeout:    c.Timeout,
-		windowSize: c.WindowSize,
-	})
-	opts, addr, err := c.sendRequest(conn, addr, b.Bytes())
-	if err != nil {
-		conn.Close()
-		if err == ErrShouldWait {
-			return nil, ErrShouldWait
-		}
-		return nil, fmt.Errorf("sending RRQ: %s", err)
-	}
-	b.Reset()
-	if err := acknowledge(conn, addr, uint16(0)); err != nil {
-		return nil, fmt.Errorf("sending ACK: %s", err)
-	}
-
-	return &receiver{
-		addr:  addr,
-		conn:  conn,
-		opts:  opts,
-		retry: c.Retries,
-	}, nil
-}
-
-type receiver struct {
-	addr  *net.UDPAddr
-	conn  *net.UDPConn
-	opts  *options
-	retry int
-}
-
-func (r *receiver) Size() (n int64) {
-	return r.opts.transferSize
-}
-
-func (r *receiver) RemoteAddr() net.UDPAddr {
-	return *r.addr
-}
-
-func (r *receiver) WriteTo(w io.Writer) (int64, error) {
-	l, err := r.receive(w)
-	if err != nil {
-		abort(r.conn, r.addr, ErrorUndefined, err)
-		return l, err
-	}
-	r.conn.Close()
-	return l, nil
-}
-
-func (r *receiver) receive(w io.Writer) (int64, error) {
-	var n int64
-	var seq uint64
-	recv := make([]byte, r.opts.blockSize+4)
-
-Loop:
-	for {
-	Attempt:
-		for attempt := 0; attempt < r.retry; attempt++ {
-			for i := uint16(0); i < uint16(r.opts.windowSize); i++ {
-				r.conn.SetReadDeadline(time.Now().Add(r.opts.timeout))
-
-				var m int
-				for {
-					var addr *net.UDPAddr
-					var err error
-					m, addr, err = r.conn.ReadFromUDP(recv[m:])
-					if err != nil {
-						if t, ok := err.(net.Error); ok && t.Timeout() {
-							acknowledge(r.conn, r.addr, uint16(seq))
-							continue Attempt
-						}
-						return n, err
-					}
-					if m < 4 { // packet too small
-						continue
-					}
-					if !addr.IP.Equal(r.addr.IP) || addr.Port != r.addr.Port {
-						continue
-					}
-					break
-				}
-
-				n += int64(m)
-
-				switch recv[1] {
-				case opData:
-					if num := binary.BigEndian.Uint16(recv[2:4]); num != uint16(seq)+1 {
-						if num-uint16(seq) < uint16(r.opts.windowSize) {
-							acknowledge(r.conn, r.addr, uint16(seq))
-						}
-						continue Loop
-					}
-					seq++
-					if _, err := w.Write(recv[4:m]); err != nil {
-						return n, fmt.Errorf("writing bytes for block %d: %v", seq, err)
-					}
-					if m < int(r.opts.blockSize+4) {
-						acknowledge(r.conn, r.addr, uint16(seq))
-						return n, nil
-					}
-				case opError:
-					msg, _, _ := netasciiString(recv[4:])
-					return n, fmt.Errorf("server aborted transfer: %s", msg)
-				}
-			}
-			// TODO: this should be addr
-			acknowledge(r.conn, r.addr, uint16(seq))
-			continue Loop
-		}
-		return n, errors.New("timeout waiting for DATA")
-	}
-}
-
-func writeRequest(b *bytes.Buffer, op uint8, filename string, o *options) {
-	b.WriteByte(0)
-	b.WriteByte(op)
-	writeString(b, filename)
-	// Only support octet mode, because in practice that's the
-	// only remaining sensible use of TFTP.
-	writeString(b, "octet")
-	writeOption(b, "tsize", o.transferSize)
-	writeOption(b, "blksize", int64(o.blockSize))
-	writeOption(b, "timeout", int64(o.timeout/time.Second))
-	writeOption(b, "windowsize", int64(o.windowSize))
-}
-
-func writeOption(b *bytes.Buffer, name string, value int64) {
-	writeString(b, name)
-	writeString(b, strconv.FormatInt(value, 10))
-}
-
-func writeString(b *bytes.Buffer, s string) {
-	b.WriteString(s)
-	b.WriteByte(0)
-}
-
-func (c *Client) sendRequest(conn *net.UDPConn, addr *net.UDPAddr, b []byte) (*options, *net.UDPAddr, error) {
-	for attempt := 0; attempt < c.Retries; attempt++ {
-		if _, err := conn.WriteToUDP(b, addr); err != nil {
-			return nil, nil, err
-		}
-
-		conn.SetReadDeadline(time.Now().Add(c.Timeout))
-
-		var recv [256]byte
-		for {
-			n, addr, err := conn.ReadFromUDP(recv[:])
-			if err != nil {
-				if t, ok := err.(net.Error); ok && t.Timeout() {
-					break
-				}
-				return nil, nil, err
-			}
-
-			if n < 4 { // packet too small
-				continue
-			}
-			switch recv[1] {
-			case opError:
-				// Handling ErrorBusy here is a Fuchsia-specific extension.
-				if code := binary.BigEndian.Uint16(recv[2:4]); code == ErrorBusy {
-					return nil, addr, ErrShouldWait
-				}
-				msg, _, _ := netasciiString(recv[4:n])
-				return nil, addr, fmt.Errorf("server aborted transfer: %s", msg)
-			case opOack:
-				options, err := parseOACK(recv[2:n])
-				return options, addr, err
-			}
-		}
-	}
-
-	return nil, nil, errors.New("timeout waiting for OACK")
-}
-
-func parseOACK(bs []byte) (*options, error) {
-	var o options
-
-	for len(bs) > 0 {
-		opt, rest, err := netasciiString(bs)
-		if err != nil {
-			return nil, fmt.Errorf("reading option name: %s", err)
-		}
-		bs = rest
-		val, rest, err := netasciiString(bs)
-		if err != nil {
-			return nil, fmt.Errorf("reading option %q value: %s", opt, err)
-		}
-		bs = rest
-		switch strings.ToLower(opt) {
-		case "blksize":
-			size, err := strconv.ParseUint(val, 10, 16)
-			if err != nil {
-				return nil, fmt.Errorf("unsupported block size %q", val)
-			}
-			o.blockSize = uint16(size)
-		case "timeout":
-			seconds, err := strconv.ParseUint(val, 10, 8)
-			if err != nil {
-				return nil, fmt.Errorf("unsupported timeout %q", val)
-			}
-			o.timeout = time.Second * time.Duration(seconds)
-		case "tsize":
-			size, err := strconv.ParseUint(val, 10, 64)
-			if err != nil {
-				return nil, fmt.Errorf("unsupported transfer size %q", val)
-			}
-			o.transferSize = int64(size)
-		case "windowsize":
-			size, err := strconv.ParseUint(val, 10, 16)
-			if err != nil {
-				return nil, fmt.Errorf("unsupported window size %q", val)
-			}
-			o.windowSize = uint16(size)
-		}
-	}
-
-	return &o, nil
-}
-
-func acknowledge(conn *net.UDPConn, addr *net.UDPAddr, seq uint16) error {
-	var b bytes.Buffer
-	b.WriteByte(0)
-	b.WriteByte(opAck)
-	if err := binary.Write(&b, binary.BigEndian, seq); err != nil {
-		return fmt.Errorf("writing seqnum: %v", err)
-	}
-	if _, err := conn.WriteToUDP(b.Bytes(), addr); err != nil {
-		return err
-	}
-	return nil
-}
-
-func abort(conn *net.UDPConn, addr *net.UDPAddr, code uint16, err error) error {
-	var b bytes.Buffer
-	b.WriteByte(0)
-	b.WriteByte(opError)
-	if binary.Write(&b, binary.BigEndian, code); err != nil {
-		return fmt.Errorf("writing code: %v", err)
-	}
-	b.WriteString(err.Error())
-	b.WriteByte(0)
-	if _, err := conn.WriteToUDP(b.Bytes(), addr); err != nil {
-		return err
-	}
-	conn.Close()
-	return nil
-}
-
-func netasciiString(bs []byte) (string, []byte, error) {
-	for i, b := range bs {
-		if b == 0 {
-			return string(bs[:i]), bs[i+1:], nil
-		} else if b < 0x20 || b > 0x7e {
-			return "", nil, fmt.Errorf("invalid netascii byte %q at offset %d", b, i)
-		}
-	}
-	return "", nil, errors.New("no null terminated string found")
-}
-
-// WindowReader supports reading bytes from an underlying stream using
-// fixed sized blocks and rewinding back up to slots blocks.
-type WindowReader struct {
-	buf     []byte    // buffer space
-	len     []int     // len of data written to each slot
-	reader  io.Reader // underlying reader object
-	current int       // current block to be read
-	head    int       // head of buffer
-	slots   int       // number of slots
-	size    int       // size of the slot
-}
-
-// NewWindowReader creates a new reader with slots blocks of size.
-func NewWindowReader(reader io.Reader, slots int, size int) *WindowReader {
-	return &WindowReader{
-		buf:    make([]byte, slots*size),
-		len:    make([]int, slots),
-		reader: reader,
-		slots:  slots,
-		size:   size,
-	}
-}
-
-func (r *WindowReader) Read(p []byte) (int, error) {
-	slot := r.current % r.slots
-	offset := slot * r.size
-
-	if r.current != r.head {
-		len := offset + r.len[slot]
-		n := copy(p, r.buf[offset:len])
-		r.current++
-		return n, nil
-	}
-
-	n, err := r.reader.Read(p)
-	if err != nil {
-		return n, err
-	}
-	n = copy(r.buf[offset:offset+n], p[:n])
-	r.len[slot] = n
-
-	r.current++
-	r.head = r.current
-	return n, err
-}
-
-// Unread rewinds the reader back by n blocks.
-func (r *WindowReader) Unread(n int) {
-	r.current -= n
-}
diff --git a/qemu/config.go b/qemu/config.go
deleted file mode 100644
index 3ca096d..0000000
--- a/qemu/config.go
+++ /dev/null
@@ -1,230 +0,0 @@
-// Copyright 2019 The Fuchsia 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 qemu
-
-import (
-	"fmt"
-	"os"
-	"path/filepath"
-	"strings"
-)
-
-const (
-	DefaultNetwork   = "10.0.2.0/24"
-	DefaultDHCPStart = "10.0.2.15"
-	DefaultGateway   = "10.0.2.2"
-	DefaultDNS       = "10.0.2.3"
-)
-
-const (
-	TargetAArch64 = "aarch64"
-	TargetX86_64  = "x86_64"
-)
-
-type Drive struct {
-	// ID is the block device identifier.
-	ID string
-
-	// File is the disk image file.
-	File string
-
-	// Addr is the PCI address of the block device.
-	Addr string
-}
-
-type Forward struct {
-	// HostPort is the port on the host.
-	HostPort int
-
-	// GuestPort is the port on the guest.
-	GuestPort int
-}
-
-type Netdev struct {
-	// ID is the network device identifier.
-	ID string
-
-	// User is a netdev user backend.
-	User *NetdevUser
-
-	// Tap is a netdev tap backend.
-	Tap *NetdevTap
-
-	// MAC is the network device MAC address.
-	MAC string
-}
-
-// NetdevUser defines a netdev backend giving user networking.
-type NetdevUser struct {
-	// Network is the network block.
-	Network string
-
-	// DHCPStart is the address at which the DHCP allocation starts.
-	DHCPStart string
-
-	// DNS is the address of the builtin DNS server.
-	DNS string
-
-	// Host is the host IP address.
-	Host string
-
-	// Forwards are the host forwardings.
-	Forwards []Forward
-}
-
-// NetdevTap defines a netdev backend giving a tap interface.
-type NetdevTap struct {
-	// Name is the name of the interface.
-	Name string
-}
-
-// Config gives a high-level configuration for QEMU on Fuchsia.
-type Config struct {
-	// QEMUBin is a path to the QEMU binary.
-	Binary string
-
-	// Target is the QEMU target (e.g., "x86_64" or "aarch64").
-	Target string
-
-	// CPU is the number of CPUs.
-	CPU int
-
-	// Memory is the amount of RAM.
-	Memory int
-
-	// KVM gives whether to enable KVM.
-	KVM bool
-
-	// Kernel is the path to the kernel image.
-	Kernel string
-
-	// Initrd is the path to the initrd image.
-	Initrd string
-
-	// Drives are drives to mount inside the QEMU instance.
-	Drives []Drive
-
-	// Networks are networks to set up inside the QEMU instance.
-	Networks []Netdev
-}
-
-// CreateInvocation creates a QEMU invocation given a particular configuration, a list of
-// images, and any specified command-line arguments.
-func CreateInvocation(cfg Config, cmdlineArgs []string) ([]string, error) {
-	if _, err := os.Stat(cfg.Binary); err != nil {
-		return nil, fmt.Errorf("QEMU binary not found: %v", err)
-	}
-	absBinaryPath, err := filepath.Abs(cfg.Binary)
-	if err != nil {
-		return nil, err
-	}
-
-	invocation := []string{absBinaryPath}
-
-	switch cfg.Target {
-	case TargetAArch64:
-		if cfg.KVM {
-			invocation = append(invocation, "-machine", "virt,gic_version=host")
-			invocation = append(invocation, "-cpu", "host")
-			invocation = append(invocation, "-enable-kvm")
-		} else {
-			invocation = append(invocation, "-machine", "virt,gic_version=3")
-			invocation = append(invocation, "-machine", "virtualization=true")
-			invocation = append(invocation, "-cpu", "cortex-a53")
-		}
-	case TargetX86_64:
-		invocation = append(invocation, "-machine", "q35")
-		// TODO: this is Fuchsia specific, factor it out as another device struct.
-		// Necessary for userboot.shutdown to trigger properly, since it writes
-		// to 0xf4 to debug-exit in QEMU.
-		invocation = append(invocation, "-device", "isa-debug-exit,iobase=0xf4,iosize=0x04")
-		if cfg.KVM {
-			invocation = append(invocation, "-cpu", "host")
-			invocation = append(invocation, "-enable-kvm")
-		} else {
-			invocation = append(invocation, "-cpu", "Haswell,+smap,-check,-fsgsbase")
-		}
-	default:
-		return nil, fmt.Errorf("cpu %q not recognized", cfg.Target)
-	}
-
-	invocation = append(invocation, "-m", fmt.Sprintf("%d", cfg.Memory))
-	invocation = append(invocation, "-smp", fmt.Sprintf("%d", cfg.CPU))
-	invocation = append(invocation, "-nographic")
-	invocation = append(invocation, "-serial", "stdio")
-	invocation = append(invocation, "-monitor", "none")
-
-	invocation = append(invocation, "-kernel", cfg.Kernel)
-	invocation = append(invocation, "-initrd", cfg.Initrd)
-
-	// TODO: maybe we should introduce Device interface with three different
-	// implementations: Drive, Netdev and ISADebugExit to cleanup the code
-	// below a bit.
-
-	for i, d := range cfg.Drives {
-		invocation = append(invocation, "-object", fmt.Sprintf("iothread,id=iothread%d", i))
-
-		var drive strings.Builder
-		fmt.Fprintf(&drive, "id=%s,file=%s,format=raw,if=none,cache=unsafe,aio=threads", d.ID, d.File)
-		invocation = append(invocation, "-drive", drive.String())
-
-		var device strings.Builder
-		fmt.Fprintf(&device, "virtio-blk-pci,drive=%s,iothread=iothread%d", d.ID, i)
-		if d.Addr != "" {
-			fmt.Fprintf(&device, ",addr=%s", d.Addr)
-		}
-		invocation = append(invocation, "-device", device.String())
-	}
-
-	for _, n := range cfg.Networks {
-		if n.ID == "" {
-			return nil, fmt.Errorf("a network must have an ID")
-		}
-
-		var netdev strings.Builder
-		if n.Tap != nil {
-			if n.Tap.Name == "" {
-				return nil, fmt.Errorf("network %q must specify a TAP interface name", n.ID)
-			}
-			// Overwrite any default configuration scripts with none; there is not currently a
-			// good use case for these parameters.
-			fmt.Fprintf(&netdev, "tap,id=%s,ifname=%s,script=no,downscript=no", n.ID, n.Tap.Name)
-		} else if n.User != nil {
-			fmt.Fprintf(&netdev, "user,id=%s", n.ID)
-			if n.User.Network != "" {
-				fmt.Fprintf(&netdev, ",net=%s", n.User.Network)
-			}
-			if n.User.DHCPStart != "" {
-				fmt.Fprintf(&netdev, ",dhcpstart=%s", n.User.DHCPStart)
-			}
-			if n.User.DNS != "" {
-				fmt.Fprintf(&netdev, ",dns=%s", n.User.DNS)
-			}
-			if n.User.Host != "" {
-				fmt.Fprintf(&netdev, ",host=%s", n.User.Host)
-			}
-			for _, f := range n.User.Forwards {
-				fmt.Fprintf(&netdev, ",hostfwd=tcp::%d-:%d", f.HostPort, f.GuestPort)
-			}
-		} else {
-			return nil, fmt.Errorf("network %q must specify a netdev backend", n.ID)
-		}
-		invocation = append(invocation, "-netdev", netdev.String())
-
-		var device strings.Builder
-		fmt.Fprintf(&device, "virtio-net-pci,netdev=%s", n.ID)
-		if n.MAC != "" {
-			fmt.Fprintf(&device, ",mac=%s", n.MAC)
-		}
-		invocation = append(invocation, "-device", device.String())
-	}
-	// Treat the absense of specified networks as a directive to disable networking entirely.
-	if len(cfg.Networks) == 0 {
-		invocation = append(invocation, "-net", "none")
-	}
-
-	invocation = append(invocation, "-append", strings.Join(cmdlineArgs, " "))
-	return invocation, nil
-}
diff --git a/qemu/exit.go b/qemu/exit.go
deleted file mode 100644
index 9d1a76a..0000000
--- a/qemu/exit.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2018 The Fuchsia 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 qemu
-
-import (
-	"fmt"
-	"log"
-	"os/exec"
-	"syscall"
-)
-
-// QEMUSuccessCodes encodes all possible QEMU exit codes that signify successful shutdown.
-var qemuSuccessCodes = map[int]bool{
-	0: true,
-
-	// QEMU returns 31 to signify a graceful shutdown when running Zircon's core-tests on
-	// x64 architecture. It writes a value to a specially declared I/O port, which is used
-	// to compute the return code as `(<value> << 1) | 1` (always odd and non-zero):
-	// 31 is that magic return code.
-	31: true,
-}
-
-// CheckExitCode checks whether a given error encodes a successful QEMU exit code.
-func CheckExitCode(err error) error {
-	if err == nil {
-		return nil
-	}
-
-	if exitErr, ok := err.(*exec.ExitError); ok {
-		// This works on both Unix and Windows. Although the syscall package is generally
-		// platform dependent, WaitStatus has a void-to-int ExitStatus() method in both cases.
-		if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
-			exitCode := status.ExitStatus()
-			_, ok = qemuSuccessCodes[exitCode]
-			if ok {
-				log.Printf("successful QEMU exit status: %d", exitCode)
-				return nil
-			} else {
-				return fmt.Errorf("unsuccessful QEMU exit status: %d", exitCode)
-			}
-		} else {
-			return fmt.Errorf("could not derive exit code from associated os.ProcessState: %v", err)
-		}
-	} else {
-		return fmt.Errorf("provided error is not of type *exec.ExitError: %v", err)
-	}
-}
diff --git a/testing/runtests/poll.go b/testing/runtests/poll.go
deleted file mode 100644
index 0fbb21b..0000000
--- a/testing/runtests/poll.go
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2019 The Fuchsia 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 runtests
-
-import (
-	"archive/tar"
-	"bytes"
-	"context"
-	"encoding/json"
-	"fmt"
-	"io"
-	"net"
-	"os"
-	"path"
-	"path/filepath"
-	"time"
-
-	"go.fuchsia.dev/tools/botanist"
-	"go.fuchsia.dev/tools/lib/logger"
-	"go.fuchsia.dev/tools/lib/retry"
-	"go.fuchsia.dev/tools/lib/tarutil"
-	"go.fuchsia.dev/tools/net/tftp"
-)
-
-// PollForSummary polls a node waiting for a summary.json to be written; this relies on
-// runtests having been run on target.
-func PollForSummary(ctx context.Context, addr *net.UDPAddr, summaryFilename, testResultsDir, outputArchive string, filePollInterval time.Duration) error {
-	t := tftp.NewClient()
-	tftpAddr := &net.UDPAddr{
-		IP:   addr.IP,
-		Port: tftp.ClientPort,
-		Zone: addr.Zone,
-	}
-	var buffer bytes.Buffer
-	var writer io.WriterTo
-	var err error
-	err = retry.Retry(ctx, retry.NewConstantBackoff(filePollInterval), func() error {
-		writer, err = t.Receive(tftpAddr, path.Join(testResultsDir, summaryFilename))
-		return err
-	}, nil)
-	if err != nil {
-		return fmt.Errorf("timed out waiting for tests to complete: %v", err)
-	}
-
-	logger.Debugf(ctx, "reading %q\n", summaryFilename)
-
-	if _, err := writer.WriteTo(&buffer); err != nil {
-		return fmt.Errorf("failed to receive summary file: %v", err)
-	}
-
-	// Parse and save the summary.json file.
-	var result TestSummary
-	if err := json.Unmarshal(buffer.Bytes(), &result); err != nil {
-		return fmt.Errorf("cannot unmarshall test results: %v", err)
-	}
-
-	outFile, err := os.OpenFile(outputArchive, os.O_WRONLY|os.O_CREATE, 0666)
-	if err != nil {
-		return fmt.Errorf("failed to create file %s: %v", outputArchive, err)
-	}
-
-	tw := tar.NewWriter(outFile)
-	defer tw.Close()
-
-	if err = tarutil.TarBuffer(tw, buffer.Bytes(), summaryFilename); err != nil {
-		return err
-	}
-
-	logger.Debugf(ctx, "copying test output\n")
-
-	// Tar in a subroutine while busy-printing so that we do not hit an i/o timeout when
-	// dealing with large files.
-	c := make(chan error)
-	go func() {
-		// Copy test output from the node.
-		for _, output := range result.Outputs {
-			remote := filepath.Join(testResultsDir, output)
-			if err = botanist.FetchAndArchiveFile(t, tftpAddr, tw, remote, output); err != nil {
-				c <- err
-				return
-			}
-		}
-		for _, test := range result.Tests {
-			remote := filepath.Join(testResultsDir, test.OutputFile)
-			if err = botanist.FetchAndArchiveFile(t, tftpAddr, tw, remote, test.OutputFile); err != nil {
-				c <- err
-				return
-			}
-			// Copy data sinks if any are present.
-			for _, sinks := range test.DataSinks {
-				for _, sink := range sinks {
-					remote := filepath.Join(testResultsDir, sink.File)
-					if err = botanist.FetchAndArchiveFile(t, tftpAddr, tw, remote, sink.File); err != nil {
-						c <- err
-						return
-					}
-				}
-			}
-		}
-		c <- nil
-	}()
-
-	logger.Debugf(ctx, "tarring test output...\n")
-	ticker := time.NewTicker(5 * time.Second)
-	for {
-		select {
-		case err := <-c:
-			ticker.Stop()
-			return err
-		case <-ticker.C:
-			logger.Debugf(ctx, "tarring test output...\n")
-		}
-	}
-}
diff --git a/testing/runtests/runtests.go b/testing/runtests/runtests.go
deleted file mode 100644
index bcb426e..0000000
--- a/testing/runtests/runtests.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2018 The Fuchsia 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 runtests contains specifics related to the runtests command.
-package runtests
-
-// TestResult is the exit result of a test.
-type TestResult string
-
-const (
-	// TestSummaryFilename is the summary file name expected by the fuchsia
-	// recipe module.
-	TestSummaryFilename = "summary.json"
-
-	// TestOutputFilename is the default output file name for a test.
-	TestOutputFilename = "stdout-and-stderr.txt"
-
-	// TestSuccess represents a passed test.
-	TestSuccess TestResult = "PASS"
-
-	// TestFailure represents a failed test.
-	TestFailure TestResult = "FAIL"
-)
-
-// TestSummary is a summary of a suite of test runs. It represents the output
-// file format of a runtests invocation.
-type TestSummary struct {
-	// Tests is a list of the details of the test runs.
-	Tests []TestDetails `json:"tests"`
-
-	// Outputs gives the suite-wide outputs, mapping canonical name of the
-	// output to its path.
-	Outputs map[string]string `json:"outputs,omitempty"`
-}
-
-// DataSink is a data sink exported by the test.
-type DataSink struct {
-	// Name is the name of the sink.
-	Name string `json:"name"`
-
-	// File is the file containing the sink data.
-	File string `json:"file"`
-}
-
-// TestDetails contains the details of a test run.
-type TestDetails struct {
-	// Name is the name of the test.
-	Name string `json:"name"`
-
-	// OutputFile is a file containing the test's output (stdout/stderr).
-	OutputFile string `json:"output_file"`
-
-	// Result is the result of the test.
-	Result TestResult `json:"result"`
-
-	// DataSinks gives the data sinks attached to a test.
-	DataSinks map[string][]DataSink `json:"data_sinks,omitempty"`
-
-	// Duration is how long the test execution took.
-	DurationMillis int64 `json:"duration_milliseconds"`
-}
diff --git a/testing/seriallistener/cmd/main.go b/testing/seriallistener/cmd/main.go
deleted file mode 100644
index d61ef89..0000000
--- a/testing/seriallistener/cmd/main.go
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2019 The Fuchsia 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
-
-// Program to watch for a specific string to appear in a socket and
-// then exits with code 0.  As long as the file is being actively written
-// to the tool will keep watching, but after ioTimeout of inactivity it
-// will fail.
-
-// To manually test, do something like the following.
-//
-// $ SOCKET=socket
-// $ rm $SOCKET &> /dev/null || true
-// $ go run main.go -socket $SOCKET -success-string FOO &
-// $ nc -U $SOCKET -l
-//
-// Any lines typed into stdin of nc will be sent to the this program.  When
-// the success string is sent, this program will exit, closing the socket,
-// and causing nc to exit.  Likewise, both programs will exit when the
-// timeout is reached.
-
-import (
-	"context"
-	"errors"
-	"flag"
-	"fmt"
-	"net"
-	"os"
-	"strings"
-	"time"
-
-	"go.fuchsia.dev/tools/lib/color"
-	"go.fuchsia.dev/tools/lib/logger"
-	"go.fuchsia.dev/tools/lib/retry"
-)
-
-var (
-	ioTimeout     time.Duration
-	socket        string
-	successString string
-	colors        color.EnableColor
-	level         logger.LogLevel
-)
-
-const serialSocketVar = "FUCHSIA_SERIAL_SOCKET"
-
-func init() {
-	flag.DurationVar(&ioTimeout, "io-timeout", 30*time.Second,
-		"amount of time to wait for new data (seconds)")
-
-	defaultSocket := os.Getenv(serialSocketVar)
-	flag.StringVar(&socket, "socket", defaultSocket,
-		fmt.Sprintf("unix socket to watch (required if %s not set)",
-			serialSocketVar))
-
-	flag.StringVar(&successString, "success-string", "",
-		"string which means the test passed")
-
-	colors = color.ColorAuto
-	flag.Var(&colors, "color",
-		"use color in output, can be never, auto, always")
-
-	level = logger.TraceLevel
-	flag.Var(&level, "level",
-		"output verbosity, can be fatal, error, warning, info, "+
-			"debug or trace")
-}
-
-func max(x int, y int) int {
-	if x < y {
-		return y
-	}
-	return x
-}
-
-func Main(ctx context.Context) error {
-	if socket == "" {
-		flag.Usage()
-		return errors.New("no socket specified")
-	}
-	logger.Infof(ctx, "socket: %s", socket)
-
-	if successString == "" {
-		flag.Usage()
-		return errors.New("no success string specified")
-	}
-	logger.Infof(ctx, "success string: %#v", successString)
-
-	logger.Infof(ctx, "io-timeout: %v", ioTimeout)
-
-	// Connect to the socket, retry for up to a minute.
-	var err error
-	var conn net.Conn
-	backoff := retry.WithMaxDuration(
-		retry.NewConstantBackoff(time.Second), time.Minute)
-	retry.Retry(ctx, backoff, func() error {
-		conn, err = net.DialTimeout("unix", socket, 5*time.Second)
-		return err
-	}, nil)
-	if err != nil {
-		return err
-	}
-	defer conn.Close()
-	logger.Infof(ctx, "connection successful")
-
-	buf := make([]byte, 4096)
-	currPage := ""
-
-	// Repeatedly read from the socket, setting a timeout before every Read().
-	for {
-		conn.SetReadDeadline(time.Now().Add(ioTimeout))
-		n, err := conn.Read(buf)
-		if err != nil {
-			return err
-		}
-
-		currPage = currPage[max(0, len(currPage)-len(successString)):]
-		currPage += string(buf[0:n])
-
-		logger.Infof(ctx, "currPage: %#v", currPage)
-		if strings.Contains(currPage, successString) {
-			logger.Infof(ctx, "success string found")
-			return nil
-		}
-	}
-}
-
-func main() {
-	flag.Parse()
-
-	log := logger.NewLogger(level, color.NewColor(colors),
-		os.Stdout, os.Stderr, "seriallistener ")
-	ctx := logger.WithLogger(context.Background(), log)
-
-	err := Main(ctx)
-	if err != nil {
-		logger.Fatalf(ctx, "%s", err)
-	}
-}
diff --git a/testing/tap/parser.go b/testing/tap/parser.go
deleted file mode 100644
index 3bbdc01..0000000
--- a/testing/tap/parser.go
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright 2019 The Fuchsia 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 tap
-
-import (
-	"errors"
-	"fmt"
-	"log"
-	"strconv"
-	"strings"
-
-	"go.fuchsia.dev/tools/testing/tap/tokenizer"
-)
-
-// Parse parses the given input string into a Document. The input is allowed to contain
-// garbage lines; The parser will skip them and parse as much of the input as possible.
-// The only execption is that the first line of input must be a TAP version header of the
-// form "TAP version XXX".
-func Parse(input []byte) (*Document, error) {
-	output := make(chan *Document)
-	go parse(tokenizer.NewTokenStream(input), output)
-	return <-output, nil
-}
-
-// State represents a parser state. Each state takes the current stream of input tokens
-// and the current Document and attempts to parse the next line of input. A state must
-// return the next state to use, even when an error is encountered. If nil is returned,
-// parsing stops.
-type state func(*tokenizer.TokenStream, *Document) (state, error)
-
-// Parse parses a Document from the given Token stream. The result is emitted on the
-// output channel.
-func parse(tokens *tokenizer.TokenStream, output chan<- *Document) {
-	document := &Document{}
-
-	for state := parseVersion; state != nil; {
-		next, err := state(tokens, document)
-		if err != nil {
-			// Garbage lines are allowed; Treat errors as non-fatal.
-			log.Println(err)
-		}
-		state = next
-	}
-
-	output <- document
-}
-
-// DiscardLine is a parser state that throws away every token until a newline or EOF.
-func discardLine(tokens *tokenizer.TokenStream, _ *Document) (state, error) {
-	for {
-		token := tokens.Peek()
-		switch {
-		case token.Type == tokenizer.TypeEOF:
-			return nil, nil
-		case token.Type != tokenizer.TypeNewline:
-			tokens.Next()
-		default:
-			tokens.Next() // Skip the newline.
-			return parseNextLine, nil
-		}
-	}
-}
-
-func parseNextLine(tokens *tokenizer.TokenStream, doc *Document) (state, error) {
-	rtokens := tokens.Raw()
-	if rtokens.Peek().Type == tokenizer.TypeEOF {
-		return nil, nil
-	}
-
-	if rtokens.Peek().Type == tokenizer.TypeSpace {
-		return parseYAMLBlock, nil
-	}
-
-	if rtokens.Peek().Type == tokenizer.TypeNumber {
-		return parsePlan, nil
-	}
-
-	if rtokens.Peek().Value == "ok" || rtokens.Peek().Value == "not" {
-		return parseTestLine, nil
-	}
-
-	return parseNextLine, unexpectedTokenError("one of 'ok', 'not' or a number", tokens.Next())
-}
-
-func parseVersion(tokens *tokenizer.TokenStream, doc *Document) (state, error) {
-	token := tokens.Next()
-	if token.Value != "TAP" {
-		return nil, unexpectedTokenError("'TAP'", token)
-	}
-
-	token = tokens.Next()
-	if token.Value != "version" {
-		return nil, unexpectedTokenError("'version'", token)
-	}
-
-	token = tokens.Next()
-	if token.Type != tokenizer.TypeNumber {
-		return nil, unexpectedTokenError("a version number", token)
-	}
-
-	version, err := strconv.ParseInt(token.Value, 10, 64)
-	if err != nil {
-		return nil, parserError(err.Error())
-	}
-
-	doc.Version = Version(version)
-	return parseNextLine, tokens.Eat(tokenizer.TypeNewline)
-}
-
-func parsePlan(tokens *tokenizer.TokenStream, doc *Document) (state, error) {
-	if doc.Plan.Start != 0 || doc.Plan.End != 0 {
-		return discardLine, errors.New("plan has already been parsed")
-	}
-
-	token := tokens.Peek()
-	if token.Type != tokenizer.TypeNumber {
-		return discardLine, unexpectedTokenError("a number", token)
-	}
-
-	start, err := strconv.ParseInt(tokens.Next().Value, 10, 64)
-	if err != nil {
-		return discardLine, parserError(err.Error())
-	}
-
-	if err := tokens.Eat(tokenizer.TypeDot); err != nil {
-		return discardLine, err
-	}
-
-	if err := tokens.Eat(tokenizer.TypeDot); err != nil {
-		return discardLine, err
-	}
-
-	token = tokens.Peek()
-	if token.Type != tokenizer.TypeNumber {
-		return discardLine, unexpectedTokenError("a number > 1", token)
-	}
-
-	end, err := strconv.ParseInt(tokens.Next().Value, 10, 64)
-	if err != nil {
-		return discardLine, parserError(err.Error())
-	}
-
-	doc.Plan = Plan{Start: int(start), End: int(end)}
-	return parseNextLine, tokens.Eat(tokenizer.TypeNewline)
-}
-
-func parseTestLine(tokens *tokenizer.TokenStream, doc *Document) (state, error) {
-	var testLine TestLine
-
-	// Parse test status.
-	token := tokens.Next()
-	switch token.Value {
-	case "not":
-		testLine.Ok = false
-		token = tokens.Next()
-		if token.Value != "ok" {
-			return discardLine, unexpectedTokenError("'ok'", token)
-		}
-	case "ok":
-		testLine.Ok = true
-	default:
-		return discardLine, unexpectedTokenError("'ok' or 'not ok'", token)
-	}
-
-	// Parse optional test number.
-	testLine.Count = len(doc.TestLines) + 1
-	if tokens.Peek().Type == tokenizer.TypeNumber {
-		count, err := strconv.ParseInt(tokens.Next().Value, 10, 64)
-		if err != nil {
-			return discardLine, parserError(err.Error())
-		}
-		testLine.Count = int(count)
-	}
-
-	// Parse optional description. Stop at a TypePound token which marks the start of a
-	// diagnostic.
-	description := tokens.Raw().ConcatUntil(tokenizer.TypePound, tokenizer.TypeNewline)
-	testLine.Description = strings.TrimSpace(description)
-
-	switch tokens.Peek().Type {
-	case tokenizer.TypeEOF:
-		doc.TestLines = append(doc.TestLines, testLine)
-		return nil, nil
-	case tokenizer.TypeNewline:
-		doc.TestLines = append(doc.TestLines, testLine)
-		return discardLine, nil
-	case tokenizer.TypePound:
-		tokens.Eat(tokenizer.TypePound)
-	}
-
-	// Parse optional directive.
-	token = tokens.Next()
-	switch token.Value {
-	case "TODO":
-		testLine.Directive = Todo
-	case "SKIP":
-		testLine.Directive = Skip
-	default:
-		return discardLine, unexpectedTokenError("a directive", token)
-	}
-
-	// Parse explanation.
-	explanation := tokens.Raw().ConcatUntil(tokenizer.TypeNewline)
-	testLine.Explanation = strings.TrimSpace(explanation)
-	doc.TestLines = append(doc.TestLines, testLine)
-
-	if tokens.Peek().Type == tokenizer.TypeEOF {
-		return nil, nil
-	}
-	tokens.Eat(tokenizer.TypeNewline)
-	return parseNextLine, nil
-}
-
-// Parses a YAML block. The block must begin as a line containing three dashes and end
-// with a line containing three dots.
-func parseYAMLBlock(tokens *tokenizer.TokenStream, doc *Document) (state, error) {
-	rtokens := tokens.Raw()
-	if len(doc.TestLines) == 0 {
-		return discardLine, parserError("found YAML with no parent test line")
-	}
-	testLine := &doc.TestLines[len(doc.TestLines)-1]
-	if len(testLine.YAML) > 0 {
-		return discardLine, parserError("found YAML with no parent test line")
-	}
-
-	// Expect the header to match /\s+---/
-	header := rtokens.ConcatUntil(tokenizer.TypeNewline)
-	if len(header) < 4 || !strings.HasPrefix(strings.TrimSpace(header), "---") {
-		return discardLine, fmt.Errorf("expected line matching /^\\s+---/ but got %q", header)
-	}
-	if err := rtokens.Eat(tokenizer.TypeNewline); err != nil {
-		return discardLine, unexpectedTokenError("a newline", rtokens.Peek())
-	}
-
-	var body string
-	for {
-		line := rtokens.ConcatUntil(tokenizer.TypeNewline)
-		// Expect the footer to match /\s+.../
-		if len(line) >= 4 && strings.HasPrefix(strings.TrimSpace(line), "...") {
-			break
-		}
-
-		body += strings.TrimSpace(line) + "\n"
-		if rtokens.Peek().Type == tokenizer.TypeEOF {
-			break
-		}
-		rtokens.Eat(tokenizer.TypeNewline)
-	}
-
-	testLine.YAML = body
-	return parseNextLine, nil
-}
-
-func unexpectedTokenError(wanted string, token tokenizer.Token) error {
-	return parserError("got %q but wanted %s", token, wanted)
-}
-
-func parserError(format string, args ...interface{}) error {
-	return fmt.Errorf("parse error: "+format, args...)
-}
diff --git a/testing/tap/parser_test.go b/testing/tap/parser_test.go
deleted file mode 100644
index 0d2a337..0000000
--- a/testing/tap/parser_test.go
+++ /dev/null
@@ -1,317 +0,0 @@
-// Copyright 2019 The Fuchsia 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 tap
-
-import (
-	"reflect"
-	"strings"
-	"testing"
-)
-
-func TestParse(t *testing.T) {
-	tests := []struct {
-		name     string
-		input    string
-		expected *Document
-	}{
-		{
-			name:  "should parse a document containing only the version",
-			input: strings.TrimSpace(`TAP version 13`),
-			expected: &Document{
-				Version: 13,
-			},
-		}, {
-			name: "should parse a document containing only the version and plan",
-			input: strings.TrimSpace(`
-TAP version 13
-1..2
-`),
-			expected: &Document{
-				Version: 13,
-				Plan:    Plan{Start: 1, End: 2},
-			},
-		}, {
-			name: "should parse a basic TAP document",
-			input: strings.TrimSpace(`
-TAP version 13
-1..4
-ok 1 - This test passed
-ok 2 # TODO this test is disabled
-not ok 3 - This test failed
-ok 4 - This test passed also # TODO congratulate the author
-`),
-			expected: &Document{
-				Version: 13,
-				Plan:    Plan{Start: 1, End: 4},
-				TestLines: []TestLine{
-					{Ok: true, Count: 1, Description: "- This test passed"},
-					{Ok: true, Count: 2, Directive: Todo, Explanation: "this test is disabled"},
-					{Ok: false, Count: 3, Description: "- This test failed"},
-					{Ok: true, Count: 4, Description: "- This test passed also", Directive: Todo, Explanation: "congratulate the author"},
-				},
-			},
-		},
-		{
-			name: "should parse a plan at the end of the document",
-			input: strings.TrimSpace(`
-TAP version 13
-ok 1 - This test passed
-ok 2 # TODO this test is disabled
-not ok 3 - This test failed
-1..3
-`),
-			expected: &Document{
-				Version: 13,
-				Plan: Plan{
-					Start: 1,
-					End:   3,
-				},
-				TestLines: []TestLine{
-					{Ok: true, Count: 1, Description: "- This test passed"},
-					{Ok: true, Count: 2, Directive: Todo, Explanation: "this test is disabled"},
-					{Ok: false, Count: 3, Description: "- This test failed"},
-				},
-			},
-		},
-		{
-			name: "should skip garbage output",
-			input: strings.TrimSpace(`
-TAP version 13
-ERROR: segfault at 0x33123. print stackdump;
-0x00001fff: 0x88881
-0x00001ffe: 0x88881
-0x00001ffd: 0x88881
-1..3
-0x00001ffc: 0x88881
-ok 1 - This test passed
-ok 2 # TODO this test is disabled
-exiting
-not ok 3 - This test failed
-`),
-			expected: &Document{
-				Version: 13,
-				Plan: Plan{
-					Start: 1,
-					End:   3,
-				},
-				TestLines: []TestLine{
-					{Ok: true, Count: 1, Description: "- This test passed"},
-					{Ok: true, Count: 2, Directive: Todo, Explanation: "this test is disabled"},
-					{Ok: false, Count: 3, Description: "- This test failed"},
-				},
-			},
-		},
-		{
-			name: "should skip a line with an incomplete test plan",
-			input: strings.TrimSpace(`
-TAP version 13
-1..
-not ok 3 - This test failed
-`),
-			expected: &Document{
-				Version: 13,
-				TestLines: []TestLine{
-					{Ok: false, Count: 3, Description: "- This test failed"},
-				},
-			},
-		},
-		{
-			name: "should preserve spaces in description",
-			input: strings.TrimSpace(`
-TAP version 13
-1..1
-ok 1 - This test     passed
-`),
-			expected: &Document{
-				Version: 13,
-				Plan:    Plan{Start: 1, End: 1},
-				TestLines: []TestLine{
-					{Ok: true, Count: 1, Description: "- This test     passed"},
-				},
-			},
-		},
-		{
-			name: "should preserve spaces in directive explanation",
-			input: strings.TrimSpace(`
-TAP version 13
-1..1
-ok 1 # SKIP this  is   disabled
-`),
-			expected: &Document{
-				Version: 13,
-				Plan:    Plan{Start: 1, End: 1},
-				TestLines: []TestLine{
-					{Ok: true, Count: 1, Directive: Skip, Explanation: "this  is   disabled"},
-				},
-			},
-		},
-		{
-			name: "should parse a YAML block",
-			input: strings.TrimSpace(`
-TAP version 13
-1..1
-ok 1
- ---
- name: foo
- start: 1
- end: 2
- ...
-`),
-			expected: &Document{
-				Version: 13,
-				Plan:    Plan{Start: 1, End: 1},
-				TestLines: []TestLine{
-					{
-						Ok:    true,
-						Count: 1,
-						YAML:  "name: foo\nstart: 1\nend: 2\n",
-					},
-				},
-			},
-		},
-		{
-			name: "should parse a YAML block whose header contains trailing characters",
-			input: strings.TrimSpace(`
-TAP version 13
-1..1
-ok 1
- ---trailing chars
- name: foo
- start: 1
- end: 2
- ...
-`),
-			expected: &Document{
-				Version: 13,
-				Plan:    Plan{Start: 1, End: 1},
-				TestLines: []TestLine{
-					{
-						Ok:    true,
-						Count: 1,
-						YAML:  "name: foo\nstart: 1\nend: 2\n",
-					},
-				},
-			},
-		},
-		{
-			name: "should parse a YAML block whose footer contains trailing characters",
-			input: strings.TrimSpace(`
-TAP version 13
-1..1
-ok 1
- ---
- name: foo
- start: 1
- end: 2
- ...trailing chars
-`),
-			expected: &Document{
-				Version: 13,
-				Plan:    Plan{Start: 1, End: 1},
-				TestLines: []TestLine{
-					{
-						Ok:    true,
-						Count: 1,
-						YAML:  "name: foo\nstart: 1\nend: 2\n",
-					},
-				},
-			},
-		},
-		{
-			name: "should parse a YAML block whose header and footer contain trailing characters",
-			input: strings.TrimSpace(`
-TAP version 13
-1..1
-ok 1
- --- trailing chars
- name: foo
- start: 1
- end: 2
- ... even more trailing chars
-`),
-			expected: &Document{
-				Version: 13,
-				Plan:    Plan{Start: 1, End: 1},
-				TestLines: []TestLine{
-					{
-						Ok:    true,
-						Count: 1,
-						YAML:  "name: foo\nstart: 1\nend: 2\n",
-					},
-				},
-			},
-		},
-		{
-			name: "should skip a YAML block at the start of the output",
-			input: strings.TrimSpace(`
-TAP version 13
-1..1
-	---
-	name: foo
-	start: 1
-	end: 2
-	...
-`),
-			expected: &Document{
-				Version: 13,
-				Plan:    Plan{Start: 1, End: 1},
-			},
-		},
-		{
-			name: "should skip a YAML block that does not follow a test line",
-			input: strings.TrimSpace(`
-TAP version 13
-1..1
-ok 1
-	---
-	name: foo_test
-	start: 1
-	end: 2
-	...
-	---
-	name: bar_test
-	start: 3
-	end: 4
-	...
-`),
-			expected: &Document{
-				Version:   13,
-				Plan:      Plan{Start: 1, End: 1},
-				TestLines: []TestLine{{Ok: true, Count: 1, YAML: "name: foo_test\nstart: 1\nend: 2\n"}},
-			},
-		},
-		{
-			name: "should parse a YAML block with no trailing /\\s+.../",
-			input: strings.TrimSpace(`
-TAP version 13
-1..1
-ok 1
-  ---
-  name: foo_test
-  start: 1
-  end: 2
-`),
-			expected: &Document{
-				Version: 13,
-				Plan:    Plan{Start: 1, End: 1},
-				TestLines: []TestLine{
-					{Ok: true, Count: 1, YAML: "name: foo_test\nstart: 1\nend: 2\n"},
-				},
-			},
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			doc, err := Parse([]byte(tt.input))
-			if err != nil {
-				t.Fatal(err)
-			}
-			if !reflect.DeepEqual(doc, tt.expected) {
-				t.Errorf("got\n%+v\nbut wanted\n%+v", doc, tt.expected)
-			}
-		})
-	}
-}
diff --git a/testing/tap/producer.go b/testing/tap/producer.go
deleted file mode 100644
index f203a0c..0000000
--- a/testing/tap/producer.go
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2019 The Fuchsia 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 tap
-
-import (
-	"fmt"
-	"io"
-	"os"
-	"strings"
-)
-
-// Producer produces TAP output.
-//
-// This producer always includes test numbers.
-type Producer struct {
-	output     io.Writer
-	directive  Directive
-	testNumber int
-}
-
-// NewProducer creates a new Producer that writes to the given Writer.
-func NewProducer(w io.Writer) *Producer {
-	p := &Producer{
-		output:    w,
-		directive: None,
-	}
-	// Output the TAP version line.
-	p.writeln("TAP version 13")
-	return p
-}
-
-// Plan outputs the TAP plan line: 1..count.  If count <= 0, nothing is printed
-func (p *Producer) Plan(count int) {
-	if count > 0 {
-		p.writeln("1..%d", count)
-	}
-}
-
-// Ok outputs a test line containing the given description and starting with either "ok"
-// if test is true or "not ok" if false.  If this producer was created using
-// Todo or Skip, then the corresponding directive is also printed, and the description is
-// used as the explanation of that directive.
-func (p *Producer) Ok(test bool, description string) {
-	p.testNumber++
-
-	ok := "ok"
-	if !test {
-		ok = "not ok"
-	}
-
-	switch p.directive {
-	case None:
-		p.writeln("%s %d %s", ok, p.testNumber, description)
-	case Todo:
-		p.writeln("%s %d # TODO %s", ok, p.testNumber, description)
-	case Skip:
-		p.writeln("%s %d # SKIP %s", ok, p.testNumber, description)
-	}
-
-	p.directive = None
-}
-
-// YAML produces a YAML block from the given input. This will indent the input data. The
-// caller should not do this themselves.
-func (p *Producer) YAML(input []byte) {
-	// Chomp empty lines from the end of the document.
-	content := strings.TrimSuffix(string(input), "\n")
-	p.writeln(p.indent("---"))
-	p.writeln(p.indent(content))
-	p.writeln(p.indent("..."))
-}
-
-// Todo returns a new Producer that prints TODO directives.
-func (p *Producer) Todo() *Producer {
-	p.directive = Todo
-	return p
-}
-
-// Skip returns a new Producer that prints SKIP directives.
-func (p *Producer) Skip() *Producer {
-	p.directive = Skip
-	return p
-}
-
-func (p *Producer) writeln(format string, args ...interface{}) {
-	fmt.Fprintln(p.writer(), fmt.Sprintf(format, args...))
-}
-
-// writer initializes the Writer to use for this Producer, in case the Producer was
-// initialized with nil output.
-func (p *Producer) writer() io.Writer {
-	if p.output == nil {
-		p.output = os.Stdout
-	}
-	return p.output
-}
-
-// Indent indents every line of the input text with a single space.
-func (p *Producer) indent(input string) string {
-	return string(p.indentBytes([]byte(input)))
-}
-
-// IndentBytes indents every line of the input text with a single space.
-func (p *Producer) indentBytes(input []byte) []byte {
-	var output []byte
-	startOfLine := true
-	for _, c := range input {
-		if startOfLine && c != '\n' {
-			output = append(output, ' ')
-		}
-		output = append(output, c)
-		startOfLine = c == '\n'
-	}
-	return output
-}
diff --git a/testing/tap/producer_test.go b/testing/tap/producer_test.go
deleted file mode 100644
index 86819f3..0000000
--- a/testing/tap/producer_test.go
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2019 The Fuchsia 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 tap_test
-
-import (
-	"os"
-	"time"
-
-	"go.fuchsia.dev/tools/testing/tap"
-	"gopkg.in/yaml.v2"
-)
-
-func ExampleProducer_single_test() {
-	p := tap.NewProducer(os.Stdout)
-	p.Plan(1)
-	p.Ok(true, "- this test passed")
-	// Output:
-	// TAP version 13
-	// 1..1
-	// ok 1 - this test passed
-}
-
-func ExampleProducer_Todo() {
-	p := tap.NewProducer(os.Stdout)
-	p.Plan(1)
-	p.Todo().Ok(true, "implement this test")
-	// Output:
-	// TAP version 13
-	// 1..1
-	// ok 1 # TODO implement this test
-}
-
-func ExampleProducer_Skip() {
-	p := tap.NewProducer(os.Stdout)
-	p.Plan(1)
-	p.Skip().Ok(true, "implement this test")
-	// Output:
-	// TAP version 13
-	// 1..1
-	// ok 1 # SKIP implement this test
-}
-
-func ExampleProducer_many_test() {
-	p := tap.NewProducer(os.Stdout)
-	p.Plan(4)
-	p.Ok(true, "- this test passed")
-	p.Ok(false, "")
-	// Output:
-	// TAP version 13
-	// 1..4
-	// ok 1 - this test passed
-	// not ok 2
-}
-
-func ExampleProducer_skip_todo_alternating() {
-	p := tap.NewProducer(os.Stdout)
-	p.Plan(4)
-	p.Skip().Ok(true, "implement this test")
-	p.Todo().Ok(false, "oh no!")
-	p.Skip().Ok(false, "skipped another")
-	p.Todo().Skip().Todo().Ok(true, "please don't write code like this")
-	// Output:
-	// TAP version 13
-	// 1..4
-	// ok 1 # SKIP implement this test
-	// not ok 2 # TODO oh no!
-	// not ok 3 # SKIP skipped another
-	// ok 4 # TODO please don't write code like this
-}
-
-func ExampleProducer_YAML() {
-	p := tap.NewProducer(os.Stdout)
-	p.Plan(1)
-	p.Ok(true, "passed")
-	bytes, err := yaml.Marshal(struct {
-		Name  string    `yaml:"name"`
-		Start time.Time `yaml:"start_time"`
-		End   time.Time `yaml:"end_time"`
-	}{
-		Name:  "foo_test",
-		Start: time.Date(2019, 1, 1, 12, 30, 0, 0, time.UTC),
-		End:   time.Date(2019, 1, 1, 12, 40, 0, 0, time.UTC),
-	})
-	if err != nil {
-		panic(err)
-	}
-	p.YAML(bytes)
-	// Output:
-	// TAP version 13
-	// 1..1
-	// ok 1 passed
-	//  ---
-	//  name: foo_test
-	//  start_time: 2019-01-01T12:30:00Z
-	//  end_time: 2019-01-01T12:40:00Z
-	//  ...
-}
diff --git a/testing/tap/tap.go b/testing/tap/tap.go
deleted file mode 100644
index 1f2f99a..0000000
--- a/testing/tap/tap.go
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2019 The Fuchsia 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 tap
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"strings"
-)
-
-// Type describes the type of TAP Object returned by the Parser.
-type Type int
-
-const (
-	// VersionType is the type returned by a Version Object.
-	VersionType Type = iota
-
-	// PlanType is the type returned by a Plan Object.
-	PlanType
-
-	// TestLineType is the type returned by a TestLine.
-	TestLineType
-)
-
-// Object is a TAP element such as a test line, plan, version header, or Yaml block.
-type Object interface {
-	Type() Type
-}
-
-// Document represents a complete TAP document.
-type Document struct {
-	Version   Version
-	Plan      Plan
-	TestLines []TestLine
-}
-
-// WriteTo writes this document to the given Writer as a formatted TAP output stream.
-func (d *Document) WriteTo(w io.Writer) (int64, error) {
-	n, err := w.Write([]byte(d.format()))
-	return int64(n), err
-}
-
-// Format renders this document as thought it were a TAP output stream.
-func (d *Document) format() string {
-	output := new(bytes.Buffer)
-	output.WriteString(fmt.Sprintf("TAP version %d\n", d.Version))
-	output.WriteString(fmt.Sprintf("%d..%d\n", d.Plan.Start, d.Plan.End))
-
-	for _, line := range d.TestLines {
-		var parts []string
-		ok := "ok"
-		if !line.Ok {
-			ok = "not ok"
-		}
-		parts = append(parts, ok)
-
-		if line.Count != 0 {
-			parts = append(parts, fmt.Sprintf("%d", line.Count))
-		}
-
-		if line.Description != "" {
-			parts = append(parts, line.Description)
-		}
-
-		switch line.Directive {
-		case Todo:
-			parts = append(parts, "# TODO", line.Explanation)
-		case Skip:
-			parts = append(parts, "# SKIP", line.Explanation)
-		}
-
-		output.WriteString(strings.Join(parts, " ") + "\n")
-	}
-
-	return output.String()
-}
-
-// Version represents a TAP version line.
-type Version int
-
-// Type implements Object.
-func (v Version) Type() Type {
-	return VersionType
-}
-
-func (v Version) String() string {
-	return fmt.Sprintf("TAP version %d", v)
-}
-
-// Plan represents a TAP plan line.
-type Plan struct {
-	Start int
-	End   int
-}
-
-// Type implements Object.
-func (p Plan) Type() Type {
-	return PlanType
-}
-
-func (p Plan) String() string {
-	return fmt.Sprintf("%d..%d", p.Start, p.End)
-}
-
-// Directive represents a TAP directive (TODO|SKIP|<none>)
-type Directive int
-
-// Valid Tap directives.
-const (
-	None Directive = iota
-	Todo
-	Skip
-)
-
-// TestLine represents a TAP test line beginning with "ok" or "not ok".
-type TestLine struct {
-	Ok          bool
-	Count       int
-	Description string
-	Directive   Directive
-	Explanation string
-	Diagnostic  string
-	YAML        string
-}
-
-// Type implements Object.
-func (t TestLine) Type() Type {
-	return TestLineType
-}
diff --git a/testing/tap/tokenizer/iterator.go b/testing/tap/tokenizer/iterator.go
deleted file mode 100644
index 6a7f0ea..0000000
--- a/testing/tap/tokenizer/iterator.go
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2019 The Fuchsia 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 tokenizer
-
-// noSpacesIterator iterates over a stream of tokens and skips whitespace characters, with
-// the exception of newlines.
-type noSpacesIterator struct {
-	raw *rawIterator
-}
-
-// Next consumes the next token in the stream.
-func (s *noSpacesIterator) Next() Token {
-	for {
-		next := s.raw.Next()
-		if next.Type != TypeSpace {
-			return next
-		}
-	}
-}
-
-// Peek returns a read-only copy of the next token in the stream, without consuming it.
-func (s *noSpacesIterator) Peek() Token {
-	for {
-		next := s.raw.Peek()
-		if next.Type == TypeSpace {
-			s.raw.Next()
-			continue
-		}
-		return next
-	}
-}
-
-// Raw returns a rawIterator using the same underlying channel of Tokens.
-func (s noSpacesIterator) Raw() *rawIterator {
-	return s.raw
-}
-
-// rawIterator iterates over a stream of tokens, including whitespace characters.
-type rawIterator struct {
-	stream    <-chan Token
-	eof       bool
-	lookahead *Token
-}
-
-// Next consumes the next token in the stream.
-func (s *rawIterator) Next() Token {
-	if s.eof {
-		return EOFToken()
-	}
-
-	next := new(Token)
-	if s.lookahead == nil {
-		*next = <-s.stream
-	} else {
-		next = s.lookahead
-		s.lookahead = nil
-	}
-
-	if next.Type == TypeEOF {
-		s.eof = true
-	}
-
-	return *next
-}
-
-// Peek returns a read-only copy of the next token in the stream, without consuming it.
-func (s *rawIterator) Peek() Token {
-	if s.eof {
-		return EOFToken()
-	}
-
-	if s.lookahead == nil {
-		s.lookahead = new(Token)
-		*s.lookahead = <-s.stream
-	}
-
-	return *s.lookahead
-}
-
-// Raw returns a rawIterator using the same underlying channel of Tokens.
-func (s rawIterator) Raw() *rawIterator {
-	return &s
-}
diff --git a/testing/tap/tokenizer/lexer.go b/testing/tap/tokenizer/lexer.go
deleted file mode 100644
index ca1c1c8..0000000
--- a/testing/tap/tokenizer/lexer.go
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright 2019 The Fuchsia 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 tokenizer
-
-import (
-	"log"
-	"strconv"
-	"unicode"
-	"unicode/utf8"
-)
-
-// TokenType describes the category a Token belongs to.
-type TokenType string
-
-// TokenType values recognized by the lexer.
-const (
-	TypePound   TokenType = "POUND"   // '#'
-	TypeNumber  TokenType = "NUMBER"  // A number
-	TypeText    TokenType = "TEXT"    // Catch-all type
-	TypeDot     TokenType = "DOT"     // '.'
-	TypeNewline TokenType = "NEWLINE" // '\n'
-	TypeEOF     TokenType = "EOF"     // Psuedo token to signal the end of input.
-	TypeSpace   TokenType = "SPACE"   // A whitespace character
-	TypeDash    TokenType = "DASH"    // '-'
-)
-
-// Token represents some atomic TAP output string.
-type Token struct {
-	Type  TokenType
-	Value string
-}
-
-// Tokenize generates a channel of Tokens read from the given input.
-func Tokenize(input []byte) <-chan Token {
-	l := &lexer{
-		input:  input,
-		Tokens: make(chan Token, 1),
-	}
-	go l.run()
-	return l.Tokens
-}
-
-// EOFToken is emitted to signal the end of input.
-func EOFToken() Token {
-	return Token{
-		Type:  TypeEOF,
-		Value: "",
-	}
-}
-
-// The rune emitted when the end of input has been reached.
-const eof = rune(-1)
-
-// State represents a lexical analysis state. Each state accepts a lexer as input and
-// returns the next lexer state. If the output state is nil, lexing stops.
-type state func(*lexer) state
-
-// Lexer manages the position of a lexical analysis on some TAP output string.
-type lexer struct {
-	input  []byte
-	start  int
-	pos    int
-	width  int
-	Tokens chan Token
-}
-
-func (l *lexer) run() {
-	for state := lexAny; state != nil; {
-		state = state(l)
-	}
-	close(l.Tokens)
-}
-
-func (l *lexer) emit(t TokenType) {
-	l.Tokens <- Token{Type: t, Value: string(l.input[l.start:l.pos])}
-	l.start = l.pos
-}
-
-func (l *lexer) next() rune {
-	if l.pos >= len(l.input) {
-		l.width = 0
-		return eof
-	}
-
-	// Read the next rune, skipping over all invalid utf8 sequences.
-	var rn rune
-	rn, l.width = utf8.DecodeRune(l.input[l.pos:])
-	for rn == utf8.RuneError && l.pos < len(l.input) {
-		log.Printf("invalid UTF-8 found at pos %d:\n\n%s", l.pos, string(l.input))
-		l.pos++
-		rn, l.width = utf8.DecodeRune(l.input[l.pos:])
-	}
-	l.pos += l.width
-	return rn
-}
-
-// Returns the current lexeme.
-func (l *lexer) lexeme() lexeme {
-	if l.pos >= len(l.input) {
-		return lexeme(eof)
-	}
-	return lexeme(l.input[l.pos : l.pos+1][0])
-}
-
-// LexAny is the lexer start state. It's job is to put the lexer into the proper state
-// according to the next input rune. Other states should return to this state after
-// emitting their lexemes. They should also not consume runes using l.next() immediately
-// before entering this state.
-func lexAny(l *lexer) state {
-	lxm := l.lexeme()
-	if lxm.isEOF() {
-		l.emit(TypeEOF)
-		return nil
-	}
-
-	l.start = l.pos
-
-	switch {
-	case lxm.isDash():
-		l.next()
-		l.emit(TypeDash)
-		return lexAny
-	case lxm.isNewline():
-		l.next()
-		l.emit(TypeNewline)
-		return lexAny
-	case lxm.isDot():
-		l.next()
-		l.emit(TypeDot)
-		return lexAny
-	case lxm.isPound():
-		l.next()
-		l.emit(TypePound)
-		return lexAny
-	case lxm.isSpace():
-		return lexSpace
-	case lxm.isDigit():
-		return lexNumber
-	}
-
-	return lexText
-}
-
-func lexSpace(l *lexer) state {
-	return lexUntil(l, TypeSpace, func(lxm lexeme) bool { return !lxm.isSpace() })
-}
-
-func lexNumber(l *lexer) state {
-	return lexUntil(l, TypeNumber, func(lxm lexeme) bool { return !lxm.isDigit() })
-}
-
-func lexText(l *lexer) state {
-	return lexUntil(l, TypeText, func(lxm lexeme) bool { return lxm.isNonText() })
-}
-
-// LexUntil consumes all runes into a token of the given type while `stop` is false.
-// Returns lexAny when complete or nil if the end of input was reached.
-func lexUntil(l *lexer, typ TokenType, stop func(lexeme) bool) state {
-	for {
-		lxm := l.lexeme()
-		if lxm.isEOF() || stop(lxm) {
-			l.emit(typ)
-			return lexAny
-		}
-		if l.next() == eof {
-			break
-		}
-	}
-	// Reached EOF
-	if l.pos > l.start {
-		l.emit(typ)
-	}
-	l.emit(TypeEOF)
-	return nil
-}
-
-type lexeme rune
-
-func (l lexeme) isSpace() bool {
-	return l != '\n' && unicode.IsSpace(rune(l))
-}
-
-func (l lexeme) isNewline() bool {
-	return l == '\n'
-}
-
-func (l lexeme) isDigit() bool {
-	_, err := strconv.Atoi(string(l))
-	return err == nil
-}
-
-func (l lexeme) isDot() bool {
-	return l == '.'
-}
-
-func (l lexeme) isDash() bool {
-	return l == '-'
-}
-
-func (l lexeme) isPound() bool {
-	return l == '#'
-}
-
-func (l lexeme) isEOF() bool {
-	return rune(l) == eof
-}
-
-func (l lexeme) isNonText() bool {
-	return l.isEOF() || l.isSpace() || l.isNewline() || l.isDigit() || l.isDot() || l.isPound() || l.isDash()
-}
diff --git a/testing/tap/tokenizer/stream.go b/testing/tap/tokenizer/stream.go
deleted file mode 100644
index ab04954..0000000
--- a/testing/tap/tokenizer/stream.go
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2019 The Fuchsia 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 tokenizer
-
-import "fmt"
-
-// Iterator iterates over a stream of tokens. This provides the core functionality for a
-// TokenStream.
-type iterator interface {
-	Next() Token
-	Peek() Token
-	Raw() *rawIterator
-}
-
-// NewTokenStream creates a stream of Token values read from input.
-func NewTokenStream(input []byte) *TokenStream {
-	return &TokenStream{
-		iter: &noSpacesIterator{
-			raw: &rawIterator{
-				stream: Tokenize(input),
-			},
-		},
-	}
-}
-
-// TokenStream is a read-only queue of Token values. The next Token in the stream can be
-// consumed by calling Next(). The next token can be inspected without being consumed by
-// calling Peek(). By default, TokenStream discards whitespace characters as though they
-// are not part of the stream. Use Raw get a TokenStream that respects whitespace.
-type TokenStream struct {
-	iter iterator
-}
-
-// Next consumes the next token in the stream.
-func (s *TokenStream) Next() Token {
-	return s.iter.Next()
-}
-
-// Peek returns a read-only copy of the next token in the stream, without consuming it.
-func (s *TokenStream) Peek() Token {
-	return s.iter.Peek()
-}
-
-// Raw returns a TokenStream that includes whitespace characters.
-func (s *TokenStream) Raw() *TokenStream {
-	return &TokenStream{iter: s.iter.Raw()}
-}
-
-// Eat consumes the next token from the stream iff it's type matches typ.  If the types
-// are different, an error is returned.
-func (s *TokenStream) Eat(typ TokenType) error {
-	token := s.iter.Peek()
-	if token.Type != typ {
-		return fmt.Errorf("unexpected token: %q", token.Type)
-	}
-	s.iter.Next()
-	return nil
-}
-
-// ConcatUntil concatenates the values of the next tokens in this stream as long as their
-// types are not anyOf. TypeEOF is implied and need not be specified. Returns the
-// contatenated output with outer spaces trimmed.
-func (s *TokenStream) ConcatUntil(anyOf ...TokenType) string {
-	var values string
-	stopAtType := map[TokenType]bool{TypeEOF: true}
-	for i := range anyOf {
-		stopAtType[anyOf[i]] = true
-	}
-	for !stopAtType[s.iter.Peek().Type] {
-		values += s.iter.Next().Value
-	}
-	return values
-}
diff --git a/testing/testrunner/cmd/main.go b/testing/testrunner/cmd/main.go
deleted file mode 100644
index 157fd1e..0000000
--- a/testing/testrunner/cmd/main.go
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2019 The Fuchsia 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 (
-	"bytes"
-	"context"
-	"flag"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"log"
-	"os"
-	"time"
-
-	"go.fuchsia.dev/tools/integration/testsharder"
-	"go.fuchsia.dev/tools/testing/runtests"
-	"go.fuchsia.dev/tools/testing/testrunner"
-)
-
-const (
-	// Default amount of time to wait before failing to perform any IO action.
-	defaultIOTimeout = 1 * time.Minute
-
-	// The username used to authenticate with the Fuchsia device.
-	sshUser = "fuchsia"
-)
-
-// Command-line flags
-var (
-	// Whether to show Usage and exit.
-	help bool
-
-	// The path where a tar archive containing test results should be created.
-	archive string
-
-	// Working directory of the local testing subprocesses.
-	localWD string
-)
-
-// Fuchsia-specific environment variables possibly exposed to the testrunner.
-const (
-	nodenameEnvVar = "FUCHSIA_NODENAME"
-	sshKeyEnvVar   = "FUCHSIA_SSH_KEY"
-)
-
-func usage() {
-	fmt.Printf(`testrunner [flags] tests-file
-
-Executes all tests found in the JSON [tests-file]
-Fuchsia tests require both the nodename of the fuchsia instance and a private
-SSH key corresponding to a authorized key to be set in the environment under
-%s and %s respectively.
-`, nodenameEnvVar, sshKeyEnvVar)
-}
-
-func init() {
-	flag.BoolVar(&help, "help", false, "Whether to show Usage and exit.")
-	flag.StringVar(&archive, "archive", "", "Optional path where a tar archive containing test results should be created.")
-	flag.StringVar(&localWD, "C", "", "Working directory of local testing subprocesses; if unset the current working directory will be used.")
-	flag.Usage = usage
-}
-
-func main() {
-	flag.Parse()
-
-	if help || flag.NArg() != 1 {
-		flag.Usage()
-		flag.PrintDefaults()
-		return
-	}
-
-	// Load tests.
-	testsPath := flag.Arg(0)
-	tests, err := testsharder.LoadTests(testsPath)
-	if err != nil {
-		log.Fatalf("failed to load tests from %q: %v", testsPath, err)
-	}
-
-	// Prepare test output drivers.
-	output := new(Output)
-	defer output.Complete()
-	output.SetupTAP(os.Stdout, len(tests))
-	output.SetupSummary()
-	if archive != "" {
-		if err := output.SetupTar(archive); err != nil {
-			log.Fatalf("failed to initialize tar output: %v", err)
-		}
-	}
-
-	// Execute.
-	nodename := os.Getenv(nodenameEnvVar)
-	sshKeyFile := os.Getenv(sshKeyEnvVar)
-	if err := execute(tests, output, nodename, sshKeyFile); err != nil {
-		log.Fatal(err)
-	}
-}
-
-func execute(tests []testsharder.Test, output *Output, nodename, sshKeyFile string) error {
-	var linux, mac, fuchsia, unknown []testsharder.Test
-	for _, test := range tests {
-		switch test.OS {
-		case testsharder.Fuchsia:
-			fuchsia = append(fuchsia, test)
-		case testsharder.Linux:
-			linux = append(linux, test)
-		case testsharder.Mac:
-			mac = append(mac, test)
-		default:
-			unknown = append(unknown, test)
-		}
-	}
-
-	if len(unknown) > 0 {
-		return fmt.Errorf("could not determine the runtime system for following tests %v", unknown)
-	}
-
-	localTester := &SubprocessTester{
-		dir: localWD,
-		env: os.Environ(),
-	}
-
-	if err := runTests(linux, localTester.Test, output); err != nil {
-		return err
-	}
-
-	if err := runTests(mac, localTester.Test, output); err != nil {
-		return err
-	}
-
-	return runFuchsiaTests(fuchsia, output, nodename, sshKeyFile)
-}
-
-func runFuchsiaTests(tests []testsharder.Test, output *Output, nodename, sshKeyFile string) error {
-	if len(tests) == 0 {
-		return nil
-	} else if nodename == "" {
-		return fmt.Errorf("%s must be set", nodenameEnvVar)
-	} else if sshKeyFile == "" {
-		return fmt.Errorf("%s must be set", sshKeyEnvVar)
-	}
-
-	sshKey, err := ioutil.ReadFile(sshKeyFile)
-	if err != nil {
-		return err
-	}
-	tester, err := NewFuchsiaTester(nodename, sshKey)
-	if err != nil {
-		return fmt.Errorf("failed to initialize fuchsia tester: %v", err)
-	}
-	defer tester.Close()
-	return runTests(tests, tester.Test, output)
-}
-
-func runTests(tests []testsharder.Test, tester Tester, output *Output) error {
-	for _, test := range tests {
-		result, err := runTest(context.Background(), test, tester)
-		if err != nil {
-			log.Println(err)
-		}
-		if result != nil {
-			output.Record(*result)
-		}
-	}
-	return nil
-}
-
-func runTest(ctx context.Context, test testsharder.Test, tester Tester) (*testrunner.TestResult, error) {
-	result := runtests.TestSuccess
-	stdout := new(bytes.Buffer)
-	stderr := new(bytes.Buffer)
-
-	// Fork the test's stdout and stderr streams to the test runner's stderr stream to
-	// make local debugging easier.  Writing both to stderr ensures that stdout only
-	// contains the test runner's TAP output stream.
-	multistdout := io.MultiWriter(stdout, os.Stderr)
-	multistderr := io.MultiWriter(stderr, os.Stderr)
-
-	startTime := time.Now()
-
-	if err := tester(ctx, test, multistdout, multistderr); err != nil {
-		result = runtests.TestFailure
-		log.Println(err)
-	}
-
-	endTime := time.Now()
-
-	// Record the test details in the summary.
-	return &testrunner.TestResult{
-		Name:      test.Name,
-		Stdout:    stdout.Bytes(),
-		Stderr:    stderr.Bytes(),
-		Result:    result,
-		StartTime: startTime,
-		EndTime:   endTime,
-	}, nil
-}
diff --git a/testing/testrunner/cmd/output.go b/testing/testrunner/cmd/output.go
deleted file mode 100644
index bad9f72..0000000
--- a/testing/testrunner/cmd/output.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2019 The Fuchsia 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 (
-	"encoding/json"
-	"fmt"
-	"io"
-	"os"
-
-	"go.fuchsia.dev/tools/testing/runtests"
-	"go.fuchsia.dev/tools/testing/testrunner"
-	"go.fuchsia.dev/tools/testing/testrunner/cmd/outputs"
-)
-
-// Output manages the test runner's output drivers. Upon completion, if tar output is
-// initialized, a TAR archive containing all other outputs is produced.
-type Output struct {
-	Summary *outputs.SummaryOutput
-	TAP     *outputs.TAPOutput
-	Tar     *outputs.TarOutput
-}
-
-// SetupTAP intializes a TAPOutput stream. out is where the stream is written. testCount
-// is used to print the TAP plan (e.g. 1..testCount). See outputs.TAPOutput for full docs.
-func (o *Output) SetupTAP(out io.Writer, testCount int) {
-	o.TAP = outputs.NewTAPOutput(out, testCount)
-}
-
-// SetupSummary initializes a Test Summary output. See outputs.SummaryOutput for docs.
-func (o *Output) SetupSummary() {
-	o.Summary = &outputs.SummaryOutput{}
-}
-
-// SetupTar initializes a TarOutput. See outputs.TarOutput for docs.
-func (o *Output) SetupTar(archivePath string) error {
-	fd, err := os.Create(archivePath)
-	if err != nil {
-		return fmt.Errorf("failed to open %q: %v", archivePath, err)
-	}
-	o.Tar = outputs.NewTarOutput(fd)
-	return nil
-}
-
-// Record writes the test result to initialized outputs.
-func (o *Output) Record(result testrunner.TestResult) {
-	if o.Summary != nil {
-		o.Summary.Record(result)
-	}
-	if o.TAP != nil {
-		o.TAP.Record(result)
-	}
-	if o.Tar != nil {
-		o.Tar.Record(result)
-	}
-}
-
-// Complete finishes producing output for the test run.
-func (o *Output) Complete() error {
-	if o.Tar == nil {
-		return nil
-	}
-	bytes, err := json.Marshal(o.Summary.Summary)
-	if err != nil {
-		return err
-	}
-	if err := o.Tar.TarFile(bytes, runtests.TestSummaryFilename); err != nil {
-		return err
-	}
-	return o.Tar.Close()
-}
diff --git a/testing/testrunner/cmd/outputs/summary.go b/testing/testrunner/cmd/outputs/summary.go
deleted file mode 100644
index db60a4d..0000000
--- a/testing/testrunner/cmd/outputs/summary.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2019 The Fuchsia 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 outputs
-
-import (
-	"path"
-	"strings"
-
-	"go.fuchsia.dev/tools/testing/runtests"
-	"go.fuchsia.dev/tools/testing/testrunner"
-)
-
-// SummaryOutput records test results in a TestSummary object.
-type SummaryOutput struct {
-	Summary runtests.TestSummary
-}
-
-// Record writes a TestDetails entry for the given test into a Summary.
-func (o *SummaryOutput) Record(result testrunner.TestResult) {
-	pathInArchive := path.Join(result.Name, runtests.TestOutputFilename)
-	// Strip any leading //, contributed by Linux/Mac test names, so that
-	// pathInArchive gives a valid relative path.
-	pathInArchive = strings.TrimLeft(pathInArchive, "//")
-	o.Summary.Tests = append(o.Summary.Tests, runtests.TestDetails{
-		Name:           result.Name,
-		OutputFile:     pathInArchive,
-		Result:         result.Result,
-		DurationMillis: result.EndTime.Sub(result.StartTime).Nanoseconds() / 1000 / 1000,
-	})
-}
-
-// AddFile registers a file on disk as a file to include in the summary.
-func (o *SummaryOutput) AddFile(name, path string) {
-	if o.Summary.Outputs == nil {
-		o.Summary.Outputs = make(map[string]string)
-	}
-	o.Summary.Outputs[name] = path
-}
diff --git a/testing/testrunner/cmd/outputs/summary_test.go b/testing/testrunner/cmd/outputs/summary_test.go
deleted file mode 100644
index 2bb6327..0000000
--- a/testing/testrunner/cmd/outputs/summary_test.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2019 The Fuchsia 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 outputs_test
-
-import (
-	"reflect"
-	"testing"
-	"time"
-
-	"go.fuchsia.dev/tools/testing/runtests"
-	"go.fuchsia.dev/tools/testing/testrunner"
-	"go.fuchsia.dev/tools/testing/testrunner/cmd/outputs"
-)
-
-func TestSummaryOutput(t *testing.T) {
-	start := time.Now()
-	inputs := []testrunner.TestResult{{
-		Name:      "test_a",
-		Result:    runtests.TestFailure,
-		StartTime: start,
-		EndTime:   start.Add(10 * time.Millisecond),
-	}, {
-		Name:   "test_b",
-		Result: runtests.TestSuccess,
-	}}
-
-	var output outputs.SummaryOutput
-	for _, input := range inputs {
-		output.Record(input)
-	}
-
-	expectedSummary := runtests.TestSummary{
-		Tests: []runtests.TestDetails{{
-			Name:           "test_a",
-			OutputFile:     "test_a/stdout-and-stderr.txt",
-			Result:         runtests.TestFailure,
-			DurationMillis: 10,
-		}, {
-			Name:       "test_b",
-			OutputFile: "test_b/stdout-and-stderr.txt",
-			Result:     runtests.TestSuccess,
-			// Unspecified start and end times == 0
-			DurationMillis: 0,
-		}},
-	}
-
-	actualSummary := output.Summary
-
-	if !reflect.DeepEqual(actualSummary, expectedSummary) {
-		t.Errorf("got\n%q\nbut wanted\n%q\n", actualSummary, expectedSummary)
-	}
-}
diff --git a/testing/testrunner/cmd/outputs/tap.go b/testing/testrunner/cmd/outputs/tap.go
deleted file mode 100644
index aad89ef..0000000
--- a/testing/testrunner/cmd/outputs/tap.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2019 The Fuchsia 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 outputs
-
-import (
-	"fmt"
-	"io"
-
-	"go.fuchsia.dev/tools/testing/runtests"
-	"go.fuchsia.dev/tools/testing/tap"
-	"go.fuchsia.dev/tools/testing/testrunner"
-)
-
-// TAPOutput records test results as a TAP output stream.
-type TAPOutput struct {
-	producer *tap.Producer
-}
-
-// NewTAPOutput creates a new TAPOutput that streams to the given writer. testCount is
-// used to print the TAP plan line.
-func NewTAPOutput(output io.Writer, testCount int) *TAPOutput {
-	producer := tap.NewProducer(output)
-	producer.Plan(testCount)
-	return &TAPOutput{producer}
-}
-
-// Record writes the test's result and name to the output given at construction time.
-func (o *TAPOutput) Record(result testrunner.TestResult) {
-	desc := fmt.Sprintf("%s (%v)", result.Name, result.EndTime.Sub(result.StartTime))
-	o.producer.Ok(result.Result == runtests.TestSuccess, desc)
-}
diff --git a/testing/testrunner/cmd/outputs/tap_test.go b/testing/testrunner/cmd/outputs/tap_test.go
deleted file mode 100644
index 620994e..0000000
--- a/testing/testrunner/cmd/outputs/tap_test.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2019 The Fuchsia 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 outputs_test
-
-import (
-	"bytes"
-	"strings"
-	"testing"
-	"time"
-
-	"go.fuchsia.dev/tools/testing/runtests"
-	"go.fuchsia.dev/tools/testing/testrunner"
-	"go.fuchsia.dev/tools/testing/testrunner/cmd/outputs"
-)
-
-func TestTapOutput(t *testing.T) {
-	s := time.Unix(0, 0)
-	inputs := []testrunner.TestResult{{
-		Name:      "test_a",
-		Result:    runtests.TestSuccess,
-		StartTime: s,
-		EndTime:   s.Add(time.Second * 2),
-	}, {
-		Name:      "test_b",
-		Result:    runtests.TestFailure,
-		StartTime: s.Add(time.Minute * 1),
-		EndTime:   s.Add(time.Minute * 2),
-	}}
-
-	var buf bytes.Buffer
-	output := outputs.NewTAPOutput(&buf, 10)
-	for _, input := range inputs {
-		output.Record(input)
-	}
-
-	expectedOutput := strings.TrimSpace(`
-TAP version 13
-1..10
-ok 1 test_a (2s)
-not ok 2 test_b (1m0s)
-`)
-
-	actualOutput := strings.TrimSpace(buf.String())
-	if actualOutput != expectedOutput {
-		t.Errorf("got\n%q\nbut wanted\n%q\n", actualOutput, expectedOutput)
-	}
-}
diff --git a/testing/testrunner/cmd/outputs/tar.go b/testing/testrunner/cmd/outputs/tar.go
deleted file mode 100644
index fe9ce2c..0000000
--- a/testing/testrunner/cmd/outputs/tar.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2019 The Fuchsia 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 outputs
-
-import (
-	"archive/tar"
-	"bytes"
-	"io"
-	"path"
-
-	"go.fuchsia.dev/tools/lib/tarutil"
-	"go.fuchsia.dev/tools/testing/runtests"
-	"go.fuchsia.dev/tools/testing/testrunner"
-)
-
-// TarOutput records test stdout and stderr streams in a TAR archive.
-type TarOutput struct {
-	w *tar.Writer
-}
-
-func NewTarOutput(w io.Writer) *TarOutput {
-	tw := tar.NewWriter(w)
-	return &TarOutput{w: tw}
-}
-
-// Record writes the given test result's stdout and stderr streams to the same file within
-// a Tar archive.
-func (o *TarOutput) Record(result testrunner.TestResult) {
-	pathInArchive := path.Join(result.Name, runtests.TestOutputFilename)
-	stdout := bytes.NewReader(result.Stdout)
-	stderr := bytes.NewReader(result.Stderr)
-	tarutil.TarReader(o.w, io.MultiReader(stdout, stderr), pathInArchive)
-}
-
-// TarFile adds a file to the underlying archive.
-func (o *TarOutput) TarFile(bytes []byte, filename string) error {
-	return tarutil.TarBuffer(o.w, bytes, filename)
-}
-
-// Close flushes all data to the archive.
-func (o *TarOutput) Close() error {
-	return o.w.Close()
-}
diff --git a/testing/testrunner/cmd/outputs/tar_test.go b/testing/testrunner/cmd/outputs/tar_test.go
deleted file mode 100644
index 7f7bd04..0000000
--- a/testing/testrunner/cmd/outputs/tar_test.go
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2019 The Fuchsia 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 outputs_test
-
-import (
-	"archive/tar"
-	"bytes"
-	"io"
-	"testing"
-
-	"go.fuchsia.dev/tools/testing/runtests"
-	"go.fuchsia.dev/tools/testing/testrunner"
-	"go.fuchsia.dev/tools/testing/testrunner/cmd/outputs"
-)
-
-func TestTarOutput(t *testing.T) {
-	tests := []struct {
-		name             string
-		input            testrunner.TestResult
-		expectedHeader   *tar.Header
-		expectedContents string
-	}{
-		{
-			name: "archive entry for test_a",
-			input: testrunner.TestResult{
-				Name:   "test_a",
-				Stdout: []byte("the test passed"),
-				Result: runtests.TestSuccess,
-			},
-			expectedHeader: &tar.Header{
-				Typeflag: tar.TypeReg,
-				Name:     "test_a/stdout-and-stderr.txt",
-				Size:     int64(len("the test passed")),
-				Mode:     0666,
-				Format:   tar.FormatUSTAR,
-			},
-			expectedContents: "the test passed",
-		},
-		{
-			name: "archive entry for test_b",
-			input: testrunner.TestResult{
-				Name:   "test_b",
-				Stdout: []byte("the test failed"),
-				Result: runtests.TestSuccess,
-			},
-			expectedHeader: &tar.Header{
-				Typeflag: tar.TypeReg,
-				Name:     "test_b/stdout-and-stderr.txt",
-				Size:     int64(len("the test failed")),
-				Mode:     0666,
-				Format:   tar.FormatUSTAR,
-			},
-			expectedContents: "the test failed",
-		},
-	}
-
-	// Helper to compare archive headers. Certain fields are ignored.
-	headersEqual := func(a *tar.Header, b *tar.Header) bool {
-		return a.Format == b.Format &&
-			a.Gid == b.Gid &&
-			a.Gname == b.Gname &&
-			a.Linkname == b.Linkname &&
-			a.Mode == b.Mode &&
-			a.Name == b.Name &&
-			a.Size == b.Size &&
-			a.Typeflag == b.Typeflag &&
-			a.Uid == b.Uid &&
-			a.Uname == b.Uname
-	}
-
-	for _, tt := range tests {
-		// Record output.
-		t.Run(tt.name, func(t *testing.T) {
-			var buf bytes.Buffer
-			to := outputs.NewTarOutput(&buf)
-			to.Record(tt.input)
-			to.Close()
-
-			// Check the contents of the tar archive.
-			tr := tar.NewReader(&buf)
-			hdr, err := tr.Next()
-			if err != nil {
-				t.Fatalf("got an error, wanted a header: %v", err)
-			}
-
-			if !headersEqual(hdr, tt.expectedHeader) {
-				t.Errorf("got:\n%+v\nwanted:\n%+v", hdr, tt.expectedHeader)
-			}
-
-			var actualContents bytes.Buffer
-			if _, err := io.Copy(&actualContents, tr); err != nil {
-				t.Fatalf("failed to read from the Tar Reader: %v", err)
-			}
-
-			if tt.expectedContents != actualContents.String() {
-				t.Errorf("got: %q, but wanted: %q", actualContents.String(), tt.expectedContents)
-			}
-		})
-	}
-}
diff --git a/testing/testrunner/cmd/tester.go b/testing/testrunner/cmd/tester.go
deleted file mode 100644
index f79c1f3..0000000
--- a/testing/testrunner/cmd/tester.go
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright 2019 The Fuchsia 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 (
-	"context"
-	"fmt"
-	"io"
-	"path"
-
-	"go.fuchsia.dev/tools/integration/testsharder"
-	"go.fuchsia.dev/tools/lib/logger"
-	"go.fuchsia.dev/tools/lib/runner"
-	"go.fuchsia.dev/tools/net/sshutil"
-	"golang.org/x/crypto/ssh"
-)
-
-const (
-	// The test output directory to create on the Fuchsia device.
-	fuchsiaOutputDir = "/data/infra/testrunner"
-
-	// A conventionally used global request name for checking the status of a client
-	// connection to an OpenSSH server.
-	keepAliveOpenSSH = "keepalive@openssh.com"
-)
-
-// Tester is executes a Test.
-type Tester func(context.Context, testsharder.Test, io.Writer, io.Writer) error
-
-// SubprocessTester executes tests in local subprocesses.
-type SubprocessTester struct {
-	dir string
-	env []string
-}
-
-func (t *SubprocessTester) Test(ctx context.Context, test testsharder.Test, stdout io.Writer, stderr io.Writer) error {
-	command := test.Command
-	if len(test.Command) == 0 {
-		if test.Path == "" {
-			return fmt.Errorf("test %q has no `command` or `path` set", test.Name)
-		}
-		command = []string{test.Path}
-	}
-
-	runner := &runner.SubprocessRunner{
-		Dir: t.dir,
-		Env: t.env,
-	}
-
-	return runner.Run(ctx, command, stdout, stderr)
-}
-
-// SSHTester executes tests over an SSH connection. It assumes the test.Command
-// contains the command line to execute on the remote machine. The caller should Close() the
-// tester when finished. Once closed, this object can no longer be used.
-type SSHTester struct {
-	client    *ssh.Client
-	newClient func(ctx context.Context) (*ssh.Client, error)
-}
-
-func NewSSHTester(newClient func(context.Context) (*ssh.Client, error)) (*SSHTester, error) {
-	client, err := newClient(context.Background())
-	if err != nil {
-		return nil, err
-	}
-	return &SSHTester{client: client, newClient: newClient}, nil
-}
-
-func (t *SSHTester) Test(ctx context.Context, test testsharder.Test, stdout io.Writer, stderr io.Writer) error {
-	if _, _, err := t.client.Conn.SendRequest(keepAliveOpenSSH, true, nil); err != nil {
-		logger.Errorf(ctx, "SSH client not responsive: %v", err)
-		client, err := t.newClient(ctx)
-		if err != nil {
-			return fmt.Errorf("failed to create new SSH client: %v", err)
-		}
-		t.client.Close()
-		t.client = client
-	}
-
-	session, err := t.client.NewSession()
-	if err != nil {
-		return err
-	}
-	defer session.Close()
-
-	runner := &runner.SSHRunner{Session: session}
-	return runner.Run(ctx, test.Command, stdout, stderr)
-}
-
-// Close stops this SSHTester.  The underlying SSH connection is terminated.  The object
-// is no longer usable after calling this method.
-func (t *SSHTester) Close() error {
-	return t.client.Close()
-}
-
-// FuchsiaTester executes tests on remote Fuchsia devices. The caller should Close() the
-// tester when finished. Once closed, this object can no longer be used.
-//
-// This is a hack. We have to run Fuchsia tests using `runtests` on the remote device
-// because there are many ways to execute Fuchsia tests and runtests already does this
-// correctly. This wrapper around SSHTester is meant to keep SSHTester free of OS-specific
-// behavior. Later we'll delete this and use SSHTester directly.
-type FuchsiaTester struct {
-	remoteOutputDir string
-	delegate        *SSHTester
-}
-
-// NewFuchsiaTester creates a FuchsiaTester object and starts a log_listener process on
-// the remote device. The log_listener output can be read from SysLogOutput().
-func NewFuchsiaTester(nodename string, sshKey []byte) (*FuchsiaTester, error) {
-	newClient := func(ctx context.Context) (*ssh.Client, error) {
-		config, err := sshutil.DefaultSSHConfig(sshKey)
-		if err != nil {
-			return nil, fmt.Errorf("failed to create an SSH client config: %v", err)
-		}
-		client, err := sshutil.ConnectToNode(ctx, nodename, config)
-		if err != nil {
-			return nil, fmt.Errorf("failed to connect to node %q: %v", nodename, err)
-		}
-		return client, nil
-	}
-
-	delegate, err := NewSSHTester(newClient)
-	if err != nil {
-		return nil, err
-	}
-	tester := &FuchsiaTester{
-		remoteOutputDir: fuchsiaOutputDir,
-		delegate:        delegate,
-	}
-	return tester, nil
-}
-
-func (t *FuchsiaTester) Test(ctx context.Context, test testsharder.Test, stdout io.Writer, stderr io.Writer) error {
-	if len(test.Command) == 0 {
-		name := path.Base(test.Path)
-		test.Command = []string{"runtests", "-t", name, "-o", t.remoteOutputDir + "runtests"}
-	}
-	return t.delegate.Test(ctx, test, stdout, stderr)
-}
-
-// Close stops this FuchsiaTester.  The remote log_listener process is terminated along
-// with the underlying SSH connection.  The object is no longer usable after calling this
-// method.
-func (t *FuchsiaTester) Close() error {
-	if err := t.delegate.Close(); err != nil {
-		return fmt.Errorf("failed to close delegate ssh runner: %v", err)
-	}
-	return nil
-}
diff --git a/testing/testrunner/cmd/tester_test.go b/testing/testrunner/cmd/tester_test.go
deleted file mode 100644
index b6d49b1..0000000
--- a/testing/testrunner/cmd/tester_test.go
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2019 The Fuchsia 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 (
-	"bytes"
-	"context"
-	"fmt"
-	"io/ioutil"
-	"os"
-	"strings"
-	"testing"
-
-	"go.fuchsia.dev/tools/integration/testsharder"
-	"go.fuchsia.dev/tools/net/sshutil"
-
-	"golang.org/x/crypto/ssh"
-)
-
-func TestTester(t *testing.T) {
-	cases := []struct {
-		name   string
-		test   testsharder.Test
-		stdout string
-		stderr string
-	}{
-		{
-			name: "should run a command a local subprocess",
-			test: testsharder.Test{
-				Name: "hello_world_test",
-				// Assumes that we're running on a Unix system.
-				Command: []string{"/bin/echo", "Hello world!"},
-			},
-			stdout: "Hello world!",
-		},
-	}
-
-	for _, tt := range cases {
-		t.Run(tt.name, func(t *testing.T) {
-			tester := &SubprocessTester{}
-
-			stdout := new(bytes.Buffer)
-			stderr := new(bytes.Buffer)
-
-			if err := tester.Test(context.Background(), tt.test, stdout, stderr); err != nil {
-				t.Errorf("failed to exected test %q: %v", tt.test.Name, err)
-				return
-			}
-
-			// Compare stdout
-			actual := strings.TrimSpace(stdout.String())
-			expected := tt.stdout
-			if actual != expected {
-				t.Errorf("got stdout %q but wanted %q", actual, expected)
-			}
-
-			// Compare stderr
-			actual = strings.TrimSpace(stderr.String())
-			expected = tt.stderr
-			if actual != expected {
-				t.Errorf("got stderr %q but wanted %q", actual, expected)
-			}
-		})
-	}
-}
-
-// Verifies that SSHTester can execute tests on a remote device. These tests are
-// only meant for local verification.  You can execute them like this:
-//
-//  FUCHSIA_NODENAME=<my nodename> FUCHSIA_SSH_KEY=<my key> go test ./...
-func TestSSHTester(t *testing.T) {
-	t.Skip("ssh tests are meant for local testing only")
-
-	nodename := os.Getenv("FUCHSIA_NODENAME")
-	if nodename == "" {
-		t.Fatal("FUCHSIA_NODENAME not set")
-	}
-	sshKeyFile := os.Getenv("FUCHSIA_SSH_KEY")
-	if sshKeyFile == "" {
-		t.Fatal("FUCHSIA_SSH_KEY not set")
-	}
-	sshKey, err := ioutil.ReadFile(sshKeyFile)
-	if err != nil {
-		t.Fatalf("could not read file %q", sshKeyFile)
-	}
-
-	cases := []struct {
-		name   string
-		tests  []testsharder.Test
-		stdout string
-		stderr string
-	}{
-		{
-			name: "should run a command over SSH",
-			tests: []testsharder.Test{
-				{
-					Name: "hello_world_test",
-					// Just 'echo' and not '/bin/echo' because this assumes we're running on
-					// Fuchsia.
-					Command: []string{"echo", "Hello world!"},
-				},
-			},
-			stdout: "Hello world!",
-		},
-		{
-			name: "should run successive commands over SSH",
-			tests: []testsharder.Test{
-				{
-					Name:    "test_1",
-					Command: []string{"echo", "this is test 1"},
-				},
-				{
-					Name:    "test_2",
-					Command: []string{"echo", "this is test 2"},
-				},
-			},
-			stdout: "this is test 1\nthis is test 2",
-		},
-	}
-
-	for _, tt := range cases {
-		t.Run(tt.name, func(t *testing.T) {
-			newClient := func(ctx context.Context) (*ssh.Client, error) {
-				config, err := sshutil.DefaultSSHConfig(sshKey)
-				if err != nil {
-					return nil, fmt.Errorf("failed to create an SSH client config: %v", err)
-				}
-				client, err := sshutil.ConnectToNode(ctx, nodename, config)
-				if err != nil {
-					return nil, fmt.Errorf("failed to connect to node %q: %v", nodename, err)
-				}
-				return client, nil
-			}
-
-			tester, err := NewSSHTester(newClient)
-			if err != nil {
-				t.Errorf("failed to intialize tester: %v", err)
-				return
-			}
-
-			stdout := new(bytes.Buffer)
-			stderr := new(bytes.Buffer)
-			for _, test := range tt.tests {
-				if err := tester.Test(context.Background(), test, stdout, stderr); err != nil {
-					t.Error(err)
-					return
-				}
-			}
-
-			if err := tester.Close(); err != nil {
-				t.Fatalf("failed to close tester: %v", err)
-			}
-
-			// Compare stdout
-			actual := strings.TrimSpace(stdout.String())
-			expected := tt.stdout
-			if actual != expected {
-				t.Errorf("got stdout %q but wanted %q", actual, expected)
-			}
-
-			// Compare stderr
-			actual = strings.TrimSpace(stderr.String())
-			expected = tt.stderr
-			if actual != expected {
-				t.Errorf("got stderr %q but wanted %q", actual, expected)
-			}
-		})
-	}
-}
diff --git a/testing/testrunner/result.go b/testing/testrunner/result.go
deleted file mode 100644
index e252c2c..0000000
--- a/testing/testrunner/result.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2019 The Fuchsia 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 testrunner handles specifics related to the testrunner tool.
-package testrunner
-
-import (
-	"time"
-
-	"go.fuchsia.dev/tools/testing/runtests"
-)
-
-// TestResult is the result of executing a test.
-type TestResult struct {
-	// Name is the name of the test that was executed.
-	Name string
-
-	// Result describes whether the test passed or failed.
-	Result runtests.TestResult
-
-	Stdout    []byte
-	Stderr    []byte
-	StartTime time.Time
-	EndTime   time.Time
-}