# -*- coding: utf-8 -*-
# Copyright 2018 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Script for performing tasks that are useful for fuzzer development.

Run "cros_fuzz" in the chroot for a list of command or "cros_fuzz $COMMAND
--help" for their full details. Below is a summary of commands that the script
can perform:

coverage: Generate a coverage report for a given fuzzer (specified by "--fuzzer"
  option). You almost certainly want to specify the package to build (using
  the "--package" option) so that a coverage build is done, since a coverage
  build is needed to generate a report. If your fuzz target is running on
  ClusterFuzz already, you can use the "--download" option to download the
  corpus from ClusterFuzz. Otherwise, you can use the "--corpus" option to
  specify the path of the corpus to run the fuzzer on and generate a report.
  The corpus will be copied to the sysroot so that the fuzzer can use it.
  Note that "--download" and "--corpus" are mutually exclusive.

reproduce: Runs the fuzzer specified by the "--fuzzer" option on a testcase
  (path specified by the "--testcase" argument). Optionally does a build when
  the "--package" option is used. The type of build can be specified using the
  "--build_type" argument.

download: Downloads the corpus from ClusterFuzz of the fuzzer specified by the
  "--fuzzer" option. The path of the directory the corpus directory is
  downloaded to can be specified using the "--directory" option.

shell: Sets up the sysroot for fuzzing and then chroots into the sysroot giving
  you a shell that is ready to fuzz.

setup: Sets up the sysroot for fuzzing (done prior to doing "reproduce", "shell"
  and "coverage" commands).

cleanup: Undoes "setup".

Note that cros_fuzz will print every shell command it runs if you set the
log-level to debug ("--log-level debug"). Otherwise it will print commands that
fail.
"""

from __future__ import print_function

import os
import shutil
import sys

from elftools.elf.elffile import ELFFile
import lddtree

from chromite.lib import commandline
from chromite.lib import constants
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging
from chromite.lib import gs
from chromite.lib import osutils
from chromite.lib import portage_util


assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'


# Directory in sysroot's /tmp directory that this script will use for files it
# needs to write. We need a directory to write files to because this script uses
# external programs that must write and read to/from files and because these
# must be run inside the sysroot and thus are usually unable to read or write
# from directories in the chroot environment this script is executed in.
SCRIPT_STORAGE_DIRECTORY = 'fuzz'
SCRIPT_STORAGE_PATH = os.path.join('/', 'tmp', SCRIPT_STORAGE_DIRECTORY)

# Names of subdirectories in "fuzz" directory used by this script to store
# things.
CORPUS_DIRECTORY_NAME = 'corpus'
TESTCASE_DIRECTORY_NAME = 'testcase'
COVERAGE_REPORT_DIRECTORY_NAME = 'coverage-report'

# Constants for names of libFuzzer command line options.
RUNS_OPTION_NAME = 'runs'
MAX_TOTAL_TIME_OPTION_NAME = 'max_total_time'

# The default path a profraw file written by a clang coverage instrumented
# binary when run by this script (default is current working directory).
DEFAULT_PROFRAW_PATH = '/default.profraw'

# Constants for libFuzzer command line values.
# 0 runs means execute everything in the corpus and do no mutations.
RUNS_DEFAULT_VALUE = 0
# An arbitrary but short amount of time to run a fuzzer to get some coverage
# data (when a corpus hasn't been provided and we aren't told to download one.
MAX_TOTAL_TIME_DEFAULT_VALUE = 30


class BuildType(object):
  """Class to hold the different kinds of build types."""

  ASAN = 'asan'
  MSAN = 'msan'
  UBSAN = 'ubsan'
  COVERAGE = 'coverage'
  STANDARD = ''

  # Build types that users can specify.
  CHOICES = (ASAN, MSAN, UBSAN, COVERAGE)


class SysrootPath(object):
  """Class for representing a path that is in the sysroot.

  Useful for dealing with paths that we must interact with when chrooted into
  the sysroot and outside of it.

  For example, if we need to interact with the "/tmp" directory of the sysroot,
  SysrootPath('/tmp').sysroot returns the path of the directory if we are in
  chrooted into the sysroot, i.e. "/tmp".

  SysrootPath('/tmp').chroot returns the path of the directory when in the
  cros_sdk i.e. SYSROOT_DIRECTORY + "/tmp" (this will probably be
  "/build/amd64-generic/tmp" in most cases).
  """

  # The actual path to the sysroot (from within the chroot).
  path_to_sysroot = None

  def __init__(self, path):
    """Constructor.

    Args:
      path: An absolute path representing something in the sysroot.
    """

    assert path.startswith('/')
    if self.IsPathInSysroot(path):
      path = self.FromChrootPathInSysroot(os.path.abspath(path))
    self.path_list = path.split(os.sep)[1:]

  @classmethod
  def SetPathToSysroot(cls, board):
    """Sets path_to_sysroot

    Args:
      board: The board we will use for our sysroot.

    Returns:
      The path to the sysroot (the value of path_to_sysroot).
    """
    cls.path_to_sysroot = cros_build_lib.GetSysroot(board)
    return cls.path_to_sysroot

  @property
  def chroot(self):
    """Get the path of the object in the Chrome OS SDK chroot.

    Returns:
      The path this object represents when chrooted into the sysroot.
    """
    assert self.path_to_sysroot is not None, 'set SysrootPath.path_to_sysroot'
    return os.path.join(self.path_to_sysroot, *self.path_list)

  @property
  def sysroot(self):
    """Get the path of the object when in the sysroot.

    Returns:
      The path this object represents when in the Chrome OS SDK .
    """
    return os.path.join('/', *self.path_list)

  @classmethod
  def IsPathInSysroot(cls, path):
    """Is a path in the sysroot.

    Args:
      path: The path we are checking is in the sysroot.

    Returns:
      True if path is within the sysroot's path in the chroot.
    """
    assert cls.path_to_sysroot
    return path.startswith(cls.path_to_sysroot)

  @classmethod
  def FromChrootPathInSysroot(cls, path):
    """Converts a chroot-relative path that is in sysroot into sysroot-relative.

    Args:
      path: The chroot-relative path we are converting to sysroot relative.

    Returns:
      The sysroot relative version of |path|.
    """
    assert cls.IsPathInSysroot(path)
    common_prefix = os.path.commonprefix([cls.path_to_sysroot, path])
    return path[len(common_prefix):]


def GetScriptStoragePath(relative_path):
  """Get the SysrootPath representing a script storage path.

  Get a path of a directory this script will store things in.

  Args:
    relative_path: The path relative to the root of the script storage
      directory.

  Returns:
    The SysrootPath representing absolute path of |relative_path| in the script
    storage directory.
  """
  path = os.path.join(SCRIPT_STORAGE_PATH, relative_path)
  return SysrootPath(path)


def GetSysrootPath(path):
  """Get the chroot-relative path of a path in the sysroot.

  Args:
    path: An absolute path in the sysroot that we will get the path in the
      chroot for.

  Returns:
    The chroot-relative path of |path| in the sysroot.
  """
  return SysrootPath(path).chroot


def GetCoverageDirectory(fuzzer):
  """Get a coverage report directory for a fuzzer

  Args:
    fuzzer: The fuzzer to get the coverage report directory for.

  Returns:
    The location of the coverage report directory for the |fuzzer|.
  """
  relative_path = os.path.join(COVERAGE_REPORT_DIRECTORY_NAME, fuzzer)
  return GetScriptStoragePath(relative_path)


def GetFuzzerSysrootPath(fuzzer):
  """Get the path in the sysroot of a fuzzer.

  Args:
    fuzzer: The fuzzer to get the path of.

  Returns:
    The path of |fuzzer| in the sysroot.
  """
  return SysrootPath(os.path.join('/', 'usr', 'libexec', 'fuzzers', fuzzer))


def GetProfdataPath(fuzzer):
  """Get the profdata file of a fuzzer.

  Args:
    fuzzer: The fuzzer to get the profdata file of.

  Returns:
    The path of the profdata file that should be used by |fuzzer|.
  """
  return GetScriptStoragePath('%s.profdata' % fuzzer)


def GetPathForCopy(parent_directory, chroot_path):
  """Returns a path in the script storage directory to copy chroot_path.

  Returns a SysrootPath representing the location where |chroot_path| should
  copied. This path will be in the parent_directory which will be in the script
  storage directory.
  """
  basename = os.path.basename(chroot_path)
  return GetScriptStoragePath(os.path.join(parent_directory, basename))


def CopyCorpusToSysroot(src_corpus_path):
  """Copies corpus into the sysroot.

  Copies corpus into the sysroot. Doesn't copy if corpus is already in sysroot.

  Args:
    src_corpus_path: A path (in the chroot) to a corpus that will be copied into
      sysroot.

  Returns:
    The path in the sysroot that the corpus was copied to.
  """
  if src_corpus_path is None:
    return None

  if SysrootPath.IsPathInSysroot(src_corpus_path):
    # Don't copy if |src_testcase_path| is already in sysroot. Just return it in
    # the format expected by the caller.
    return SysrootPath(src_corpus_path)

  dest_corpus_path = GetPathForCopy(CORPUS_DIRECTORY_NAME, src_corpus_path)
  osutils.RmDir(dest_corpus_path.chroot, ignore_missing=True)
  shutil.copytree(src_corpus_path, dest_corpus_path.chroot)
  return dest_corpus_path


def CopyTestcaseToSysroot(src_testcase_path):
  """Copies a testcase into the sysroot.

  Copies a testcase into the sysroot. Doesn't copy if testcase is already in
  sysroot.

  Args:
    src_testcase_path: A path (in the chroot) to a testcase that will be copied
      into sysroot.

  Returns:
    The path in the sysroot that the testcase was copied to.
  """
  if SysrootPath.IsPathInSysroot(src_testcase_path):
    # Don't copy if |src_testcase_path| is already in sysroot. Just return it in
    # the format expected by the caller.
    return SysrootPath(src_testcase_path)

  dest_testcase_path = GetPathForCopy(TESTCASE_DIRECTORY_NAME,
                                      src_testcase_path)
  osutils.SafeMakedirsNonRoot(os.path.dirname(dest_testcase_path.chroot))
  osutils.SafeUnlink(dest_testcase_path.chroot)

  shutil.copy(src_testcase_path, dest_testcase_path.chroot)
  return dest_testcase_path


def sudo_run(*args, **kwargs):
  """Wrapper around cros_build_lib.sudo_run.

  Wrapper that calls cros_build_lib.sudo_run but sets debug_level by
  default.

  Args:
    *args: Positional arguments to pass to cros_build_lib.sudo_run.
    *kwargs: Keyword arguments to pass to cros_build_lib.sudo_run.

  Returns:
    The value returned by calling cros_build_lib.sudo_run.
  """
  kwargs.setdefault('debug_level', logging.DEBUG)
  return cros_build_lib.sudo_run(*args, **kwargs)


def GetLibFuzzerOption(option_name, option_value):
  """Gets the libFuzzer command line option with the specified name and value.

  Args:
    option_name: The name of the libFuzzer option.
    option_value: The value of the libFuzzer option.

  Returns:
    The libFuzzer option composed of |option_name| and |option_value|.
  """
  return '-%s=%s' % (option_name, option_value)


def IsOptionLimit(option):
  """Determines if fuzzer option limits fuzzing time."""
  for limit_name in [MAX_TOTAL_TIME_OPTION_NAME, RUNS_OPTION_NAME]:
    if option.startswith('-%s' % limit_name):
      return True

  return False


def LimitFuzzing(fuzz_command, corpus):
  """Limits how long fuzzing will go if unspecified.

  Adds a reasonable limit on how much fuzzing will be done unless there already
  is some kind of limit. Mutates fuzz_command.

  Args:
    fuzz_command: A command to run a fuzzer. Used to determine if a limit needs
      to be set. Mutated if it is needed to specify a limit.
    corpus: The corpus that will be passed to the fuzzer. If not None then
      fuzzing is limited by running everything in the corpus once.
  """
  if any(IsOptionLimit(x) for x in fuzz_command[1:]):
    # Don't do anything if there is already a limit.
    return

  if corpus:
    # If there is a corpus, just run everything in the corpus once.
    fuzz_command.append(
        GetLibFuzzerOption(RUNS_OPTION_NAME, RUNS_DEFAULT_VALUE))
    return

  # Since there is no corpus, just fuzz for 30 seconds.
  logging.info('Limiting fuzzing to %s seconds.', MAX_TOTAL_TIME_DEFAULT_VALUE)
  max_total_time_option = GetLibFuzzerOption(MAX_TOTAL_TIME_OPTION_NAME,
                                             MAX_TOTAL_TIME_DEFAULT_VALUE)
  fuzz_command.append(max_total_time_option)


def GetFuzzExtraEnv(extra_options=None):
  """Gets extra_env for fuzzing.

  Gets environment varaibles and values for running libFuzzer. Sets defaults and
  allows user to specify extra sanitizer options.

  Args:
    extra_options: A dict containing sanitizer options to set in addition to the
      defaults.

  Returns:
    A dict containing environment variables and their values that can be used in
    the environment libFuzzer runs in.
  """
  if extra_options is None:
    extra_options = {}

  # log_path must be set because Chrome OS's patched compiler changes it.
  options_dict = {'log_path': 'stderr'}
  options_dict.update(extra_options)
  sanitizer_options = ':'.join('%s=%s' % x for x in options_dict.items())
  sanitizers = ('ASAN', 'MSAN', 'UBSAN')
  return {x + '_OPTIONS': sanitizer_options for x in sanitizers}


def RunFuzzer(fuzzer,
              corpus_path=None,
              fuzz_args='',
              testcase_path=None,
              crash_expected=False):
  """Runs the fuzzer while chrooted into the sysroot.

  Args:
    fuzzer: The fuzzer to run.
    corpus_path: A path to a corpus (not necessarily in the sysroot) to run the
      fuzzer on.
    fuzz_args: Additional arguments to pass to the fuzzer when running it.
    testcase_path: A path to a testcase (not necessarily in the sysroot) to run
      the fuzzer on.
    crash_expected: Is it normal for the fuzzer to crash on this run?
  """
  logging.info('Running fuzzer: %s', fuzzer)
  fuzzer_sysroot_path = GetFuzzerSysrootPath(fuzzer)
  fuzz_command = [fuzzer_sysroot_path.sysroot]
  fuzz_command += fuzz_args.split()

  if testcase_path:
    fuzz_command.append(testcase_path)
  else:
    LimitFuzzing(fuzz_command, corpus_path)

  if corpus_path:
    fuzz_command.append(corpus_path)

  if crash_expected:
    # Don't return nonzero when fuzzer OOMs, leaks, or timesout, since we don't
    # want an exception in those cases. The user may be trying to reproduce
    # those issues.
    fuzz_command += ['-error_exitcode=0', '-timeout_exitcode=0']

    # We must set exitcode=0 or else the fuzzer will return nonzero on
    # successful reproduction.
    sanitizer_options = {'exitcode': '0'}
  else:
    sanitizer_options = {}

  extra_env = GetFuzzExtraEnv(sanitizer_options)
  RunSysrootCommand(fuzz_command, extra_env=extra_env, debug_level=logging.INFO)


def MergeProfraw(fuzzer):
  """Merges profraw file from a fuzzer and creates a profdata file.

  Args:
    fuzzer: The fuzzer to merge the profraw file from.
  """
  profdata_path = GetProfdataPath(fuzzer)
  command = [
      'llvm-profdata',
      'merge',
      '-sparse',
      DEFAULT_PROFRAW_PATH,
      '-o',
      profdata_path.sysroot,
  ]

  RunSysrootCommand(command)
  return profdata_path


def GenerateCoverageReport(fuzzer, shared_libraries):
  """Generates an HTML coverage report from a fuzzer run.

  Args:
    fuzzer: The fuzzer to generate the coverage report for.
    shared_libraries: Libraries loaded dynamically by |fuzzer|.

  Returns:
    The path of the coverage report.
  """
  fuzzer_path = GetFuzzerSysrootPath(fuzzer).chroot
  command = ['llvm-cov', 'show', '-object', fuzzer_path]
  for library in shared_libraries:
    command += ['-object', library]

  coverage_directory = GetCoverageDirectory(fuzzer)
  command += [
      '-format=html',
      '-instr-profile=%s' % GetProfdataPath(fuzzer).chroot,
      '-output-dir=%s' % coverage_directory.chroot,
  ]

  # TODO(metzman): Investigate error messages printed by this command.
  cros_build_lib.run(command, stderr=True, debug_level=logging.DEBUG)
  return coverage_directory


def GetSharedLibraries(binary_path):
  """Gets the shared libraries used by a binary.

  Gets the shared libraries used by the binary. Based on GetSharedLibraries from
  src/tools/code_coverage/coverage_utils.py in Chromium.

  Args:
    binary_path: The path to the binary we want to find the shared libraries of.

  Returns:
    The shared libraries used by |binary_path|.
  """
  logging.info('Finding shared libraries for targets (if any).')
  shared_libraries = []
  elf_dict = lddtree.ParseELF(
      binary_path.chroot, root=SysrootPath.path_to_sysroot)
  for shared_library in elf_dict['libs'].values():
    shared_library_path = shared_library['path']

    if shared_library_path in shared_libraries:
      continue

    assert os.path.exists(shared_library_path), ('Shared library "%s" used by '
                                                 'the given target(s) does not '
                                                 'exist.' % shared_library_path)

    if IsInstrumentedWithClangCoverage(shared_library_path):
      # Do not add non-instrumented libraries. Otherwise, llvm-cov errors out.
      shared_libraries.append(shared_library_path)

  logging.debug('Found shared libraries (%d): %s.', len(shared_libraries),
                shared_libraries)
  logging.info('Finished finding shared libraries for targets.')
  return shared_libraries


def IsInstrumentedWithClangCoverage(binary_path):
  """Determines if a binary is instrumented with clang source based coverage.

  Args:
    binary_path: The path of the binary (executable or library) we are checking
      is instrumented with clang source based coverage.

  Returns:
    True if the binary is instrumented with clang source based coverage.
  """
  with open(binary_path, 'rb') as file_handle:
    elf_file = ELFFile(file_handle)
    return elf_file.get_section_by_name('__llvm_covmap') is not None


def RunFuzzerAndGenerateCoverageReport(fuzzer, corpus, fuzz_args):
  """Runs a fuzzer generates a coverage report and returns the report's path.

  Gets a coverage report for a fuzzer.

  Args:
    fuzzer: The fuzzer to run and generate the coverage report for.
    corpus: The path to a corpus to run the fuzzer on.
    fuzz_args: Additional arguments to pass to the fuzzer.

  Returns:
    The path to the coverage report.
  """
  corpus_path = CopyCorpusToSysroot(corpus)
  if corpus_path:
    corpus_path = corpus_path.sysroot

  RunFuzzer(fuzzer, corpus_path=corpus_path, fuzz_args=fuzz_args)
  MergeProfraw(fuzzer)
  fuzzer_sysroot_path = GetFuzzerSysrootPath(fuzzer)
  shared_libraries = GetSharedLibraries(fuzzer_sysroot_path)
  return GenerateCoverageReport(fuzzer, shared_libraries)


def RunSysrootCommand(command, **kwargs):
  """Runs command while chrooted into sysroot and returns the output.

  Args:
    command: A command to run in the sysroot.
    kwargs: Extra arguments to pass to cros_build_lib.sudo_run.

  Returns:
    The result of a call to cros_build_lib.sudo_run.
  """
  command = ['chroot', SysrootPath.path_to_sysroot] + command
  return sudo_run(command, **kwargs)


def GetBuildExtraEnv(build_type):
  """Gets the extra_env for building a package.

  Args:
    build_type: The type of build we want to do.

  Returns:
    The extra_env to use when building.
  """
  if build_type is None:
    build_type = BuildType.ASAN

  use_flags = os.environ.get('USE', '').split()
  # Check that the user hasn't already set USE flags that we can set.
  # No good way to iterate over an enum in python2.
  for use_flag in BuildType.CHOICES:
    if use_flag in use_flags:
      logging.warning('%s in USE flags. Please use --build_type instead.',
                      use_flag)

  # Set USE flags.
  fuzzer_build_type = 'fuzzer'
  use_flags += [fuzzer_build_type, build_type]
  features_flags = os.environ.get('FEATURES', '').split()
  if build_type == BuildType.COVERAGE:
    # We must use ASan when doing coverage builds.
    use_flags.append(BuildType.ASAN)
    # Use noclean so that a coverage report can be generated based on the source
    # code.
    features_flags.append('noclean')

  return {
      'FEATURES': ' '.join(features_flags),
      'USE': ' '.join(use_flags),
  }


def BuildPackage(package, board, build_type):
  """Builds a package on a specified board.

  Args:
    package: The package to build. Nothing is built if None.
    board: The board to build the package on.
    build_type: The type of the build to do (e.g. asan, msan, ubsan, coverage).
  """
  if package is None:
    return

  logging.info('Building %s using %s.', package, build_type)
  extra_env = GetBuildExtraEnv(build_type)
  build_packages_path = os.path.join(constants.SOURCE_ROOT, 'src', 'scripts',
                                     'build_packages')
  command = [
      build_packages_path,
      '--board',
      board,
      '--skip_chroot_upgrade',
      package,
  ]
  # For msan builds, always use "--nousepkg" since all package needs to be
  # instrumented with msan.
  if build_type == BuildType.MSAN:
    command += ['--nousepkg']

  # Print the output of the build command. Do this because it is familiar to
  # devs and we don't want to leave them not knowing about the build's progress
  # for a long time.
  cros_build_lib.run(command, extra_env=extra_env)


def DownloadFuzzerCorpus(fuzzer, dest_directory=None):
  """Downloads a corpus and returns its path.

  Downloads a corpus to a subdirectory of dest_directory if specified and
  returns path on the filesystem of the corpus. Asks users to authenticate
  if permission to read from bucket is denied.

  Args:
    fuzzer: The name of the fuzzer who's corpus we want to download.
    dest_directory: The directory to download the corpus to.

  Returns:
    The path to the downloaded corpus.

  Raises:
    gs.NoSuchKey: A corpus for the fuzzer doesn't exist.
    gs.GSCommandError: The corpus failed to download for another reason.
  """
  if not fuzzer.startswith('chromeos_'):
    # ClusterFuzz internally appends "chromeos_" to chromeos targets' names.
    # Therefore we must do so in order to find the corpus.
    fuzzer = 'chromeos_%s' % fuzzer

  if dest_directory is None:
    dest_directory = GetScriptStoragePath(CORPUS_DIRECTORY_NAME).chroot
  osutils.SafeMakedirsNonRoot(dest_directory)

  clusterfuzz_gcs_corpus_bucket = 'chromeos-corpus'
  suburl = 'libfuzzer/%s' % fuzzer
  gcs_path = gs.GetGsURL(
      clusterfuzz_gcs_corpus_bucket,
      for_gsutil=True,
      public=False,
      suburl=suburl)

  dest_path = os.path.join(dest_directory, fuzzer)

  try:
    logging.info('Downloading corpus to %s.', dest_path)
    ctx = gs.GSContext()
    ctx.Copy(
        gcs_path,
        dest_directory,
        recursive=True,
        parallel=True,
        debug_level=logging.DEBUG)
    logging.info('Finished downloading corpus.')
  except gs.GSNoSuchKey as exception:
    logging.error('Corpus for fuzzer: %s does not exist.', fuzzer)
    raise exception
  # Try to authenticate if we were denied permission to access the corpus.
  except gs.GSCommandError as exception:
    logging.error(
        'gsutil failed to download the corpus. You may need to log in. See:\n'
        'https://chromium.googlesource.com/chromiumos/docs/+/master/gsutil.md'
        '#setup\n'
        'for instructions on doing this.')
    raise exception

  return dest_path


def Reproduce(fuzzer, testcase_path):
  """Runs a fuzzer in the sysroot on a testcase.

  Args:
    fuzzer: The fuzzer to run.
    testcase_path: The path (not necessarily in the sysroot) of the testcase to
      run the fuzzer on.
  """
  testcase_sysroot_path = CopyTestcaseToSysroot(testcase_path).sysroot
  RunFuzzer(fuzzer, testcase_path=testcase_sysroot_path, crash_expected=True)


def SetUpSysrootForFuzzing():
  """Sets up the the sysroot for fuzzing

  Prepares the sysroot for fuzzing. Idempotent.
  """
  logging.info('Setting up sysroot for fuzzing.')
  # TODO(metzman): Don't create devices or mount /proc, use platform2_test.py
  # instead.
  # Mount /proc in sysroot and setup dev there because they are needed by
  # sanitizers.
  proc_manager = ProcManager()
  proc_manager.Mount()

  # Setup devices in /dev that are needed by libFuzzer.
  device_manager = DeviceManager()
  device_manager.SetUp()

  # Set up asan_symbolize.py, llvm-symbolizer, and llvm-profdata in the
  # sysroot so that fuzzer output (including stack traces) can be symbolized
  # and so that coverage reports can be generated.
  tool_manager = ToolManager()
  tool_manager.Install()

  osutils.SafeMakedirsNonRoot(GetSysrootPath(SCRIPT_STORAGE_PATH))


def CleanUpSysroot():
  """Cleans up the the sysroot from SetUpSysrootForFuzzing.

  Undoes SetUpSysrootForFuzzing. Idempotent.
  """
  logging.info('Cleaning up the sysroot.')
  proc_manager = ProcManager()
  proc_manager.Unmount()

  device_manager = DeviceManager()
  device_manager.CleanUp()

  tool_manager = ToolManager()
  tool_manager.Uninstall()
  osutils.RmDir(GetSysrootPath(SCRIPT_STORAGE_PATH), ignore_missing=True)


class ToolManager(object):
  """Class that installs or uninstalls fuzzing tools to/from the sysroot.

  Install and Uninstall methods are idempotent. Both are safe to call at any
  point.
  """

  # Path to asan_symbolize.py.
  ASAN_SYMBOLIZE_PATH = os.path.join('/', 'usr', 'bin', 'asan_symbolize.py')

  # List of LLVM binaries we must install in sysroot.
  LLVM_BINARY_NAMES = ['gdbserver', 'llvm-symbolizer', 'llvm-profdata']

  def __init__(self):
    self.asan_symbolize_sysroot_path = GetSysrootPath(self.ASAN_SYMBOLIZE_PATH)

  def Install(self):
    """Installs tools to the sysroot."""
    # Install asan_symbolize.py.
    sudo_run(['cp', self.ASAN_SYMBOLIZE_PATH, self.asan_symbolize_sysroot_path])
    # Install the LLVM binaries.
    # TODO(metzman): Build these tools so that we don't mess up when board is
    # for a different ISA.
    for llvm_binary in self._GetLLVMBinaries():
      llvm_binary.Install()

  def Uninstall(self):
    """Uninstalls tools from the sysroot. Undoes Install."""
    # Uninstall asan_symbolize.py.
    osutils.SafeUnlink(self.asan_symbolize_sysroot_path, sudo=True)
    # Uninstall the LLVM binaries.
    for llvm_binary in self._GetLLVMBinaries():
      llvm_binary.Uninstall()

  def _GetLLVMBinaries(self):
    """Creates LllvmBinary objects for each binary name in LLVM_BINARY_NAMES."""
    return [LlvmBinary(x) for x in self.LLVM_BINARY_NAMES]


class LlvmBinary(object):
  """Class for representing installing/uninstalling an LLVM binary in sysroot.

  Install and Uninstall methods are idempotent. Both are safe to call at any
  time.
  """

  # Path to the lddtree chromite script.
  LDDTREE_SCRIPT_PATH = os.path.join(constants.CHROMITE_BIN_DIR, 'lddtree')

  def __init__(self, binary):
    self.binary = binary
    self.install_dir = GetSysrootPath(
        os.path.join('/', 'usr', 'libexec', binary))
    self.binary_dir_path = GetSysrootPath(os.path.join('/', 'usr', 'bin'))
    self.binary_chroot_dest_path = os.path.join(self.binary_dir_path, binary)

  def Uninstall(self):
    """Removes an LLVM binary from sysroot. Undoes Install."""
    osutils.RmDir(self.install_dir, ignore_missing=True, sudo=True)
    osutils.SafeUnlink(self.binary_chroot_dest_path, sudo=True)

  def Install(self):
    """Installs (sets up) an LLVM binary in the sysroot.

    Sets up an llvm binary in the sysroot so that it can be run there.
    """
    # Create a directory for installing |binary| and all of its dependencies in
    # the sysroot.
    binary_rel_path = ['usr', 'bin', self.binary]
    binary_chroot_path = os.path.join('/', *binary_rel_path)
    if not os.path.exists(binary_chroot_path):
      logging.warning('Cannot copy %s, file does not exist in chroot.',
                      binary_chroot_path)
      logging.warning('Functionality provided by %s will be missing.',
                      binary_chroot_path)
      return

    osutils.SafeMakedirsNonRoot(self.install_dir)

    # Copy the binary and everything needed to run it into the sysroot.
    cmd = [
        self.LDDTREE_SCRIPT_PATH,
        '-v',
        '--generate-wrappers',
        '--root',
        '/',
        '--copy-to-tree',
        self.install_dir,
        binary_chroot_path,
    ]
    sudo_run(cmd)

    # Create a symlink to the copy of the binary (we can't do lddtree in
    # self.binary_dir_path). Note that symlink should be relative so that it
    # will be valid when chrooted into the sysroot.
    rel_path = os.path.relpath(self.install_dir, self.binary_dir_path)
    link_path = os.path.join(rel_path, *binary_rel_path)
    osutils.SafeSymlink(link_path, self.binary_chroot_dest_path, sudo=True)


class DeviceManager(object):
  """Class that creates or removes devices from /dev in sysroot.

  SetUp and CleanUp methods are idempotent. Both are safe to call at any point.
  """

  DEVICE_MKNOD_PARAMS = {
      'null': (666, 3),
      'random': (444, 8),
      'urandom': (444, 9),
  }

  MKNOD_MAJOR = '1'

  def __init__(self):
    self.dev_path_chroot = GetSysrootPath('/dev')

  def _GetDevicePath(self, device_name):
    """Returns the path of |device_name| in sysroot's /dev."""
    return os.path.join(self.dev_path_chroot, device_name)

  def SetUp(self):
    """Sets up devices in the sysroot's /dev.

    Creates /dev/null, /dev/random, and /dev/urandom. If they already exist then
    recreates them.
    """
    self.CleanUp()
    osutils.SafeMakedirsNonRoot(self.dev_path_chroot)
    for device, mknod_params in self.DEVICE_MKNOD_PARAMS.items():
      device_path = self._GetDevicePath(device)
      self._MakeCharDevice(device_path, *mknod_params)

  def CleanUp(self):
    """Cleans up devices in the sysroot's /dev. Undoes SetUp.

    Removes /dev/null, /dev/random, and /dev/urandom if they exist.
    """
    for device in self.DEVICE_MKNOD_PARAMS:
      device_path = self._GetDevicePath(device)
      if os.path.exists(device_path):
        # Use -r since dev/null is sometimes a directory.
        sudo_run(['rm', '-r', device_path])

  def _MakeCharDevice(self, path, mode, minor):
    """Make a character device."""
    mode = str(mode)
    minor = str(minor)
    command = ['mknod', '-m', mode, path, 'c', self.MKNOD_MAJOR, minor]
    sudo_run(command)


class ProcManager(object):
  """Class that mounts or unmounts /proc in sysroot.

  Mount and Unmount are idempotent. Both are safe to call at any point.
  """

  PROC_PATH = '/proc'

  def __init__(self):
    self.proc_path_chroot = GetSysrootPath(self.PROC_PATH)
    self.is_mounted = osutils.IsMounted(self.proc_path_chroot)

  def Unmount(self):
    """Unmounts /proc in chroot. Undoes Mount."""
    if not self.is_mounted:
      return
    osutils.UmountDir(self.proc_path_chroot, cleanup=False)

  def Mount(self):
    """Mounts /proc in chroot. Remounts it if already mounted."""
    self.Unmount()
    osutils.MountDir(
        self.PROC_PATH,
        self.proc_path_chroot,
        'proc',
        debug_level=logging.DEBUG)


def EnterSysrootShell():
  """Spawns and gives user access to a bash shell in the sysroot."""
  command = ['/bin/bash', '-i']
  return RunSysrootCommand(
      command,
      extra_env=GetFuzzExtraEnv(),
      debug_level=logging.INFO,
      check=False).returncode


def StripFuzzerPrefixes(fuzzer_name):
  """Strip the prefix ClusterFuzz uses in case they are specified.

  Strip the prefixes used by ClusterFuzz if the users has included them by
  accident.

  Args:
    fuzzer_name: The fuzzer who's name may contain prefixes.

  Returns:
    The name of the fuzz target without prefixes.
  """
  initial_name = fuzzer_name

  def StripPrefix(prefix):
    if fuzzer_name.startswith(prefix):
      return fuzzer_name[len(prefix):]
    return fuzzer_name

  clusterfuzz_prefixes = ['libFuzzer_', 'chromeos_']

  for prefix in clusterfuzz_prefixes:
    fuzzer_name = StripPrefix(prefix)

  if initial_name != fuzzer_name:
    logging.warning(
        '%s contains a prefix from ClusterFuzz (one or more of %s) that is not '
        "part of the fuzzer's name. Interpreting --fuzzer as %s.",
        initial_name, clusterfuzz_prefixes, fuzzer_name)

  return fuzzer_name


def ExecuteShellCommand():
  """Executes the "shell" command.

  Sets up the sysroot for fuzzing and gives user access to a bash shell it
  spawns in the sysroot.

  Returns:
    The exit code of the shell command.
  """
  SetUpSysrootForFuzzing()
  return EnterSysrootShell()


def ExecuteSetupCommand():
  """Executes the "setup" command. Wrapper for SetUpSysrootForFuzzing.

  Sets up the sysroot for fuzzing.
  """
  SetUpSysrootForFuzzing()


def ExecuteCleanupCommand():
  """Executes the "cleanup" command. Wrapper for CleanUpSysroot.

  Undoes pre-fuzzing setup.
  """
  CleanUpSysroot()


def ExecuteCoverageCommand(options):
  """Executes the "coverage" command.

  Executes the "coverage" command by optionally doing a coverage build of a
  package, optionally downloading the fuzzer's corpus, optionally copying it
  into the sysroot, running the fuzzer and then generating a coverage report
  for the user to view. Causes program to exit if fuzzer is not instrumented
  with source based coverage.

  Args:
    options: The parsed arguments passed to this program.
  """
  BuildPackage(options.package, options.board, BuildType.COVERAGE)

  fuzzer = StripFuzzerPrefixes(options.fuzzer)
  fuzzer_sysroot_path = GetFuzzerSysrootPath(fuzzer)
  if not IsInstrumentedWithClangCoverage(fuzzer_sysroot_path.chroot):
    # Don't run the fuzzer if it isn't instrumented with source based coverage.
    # Quit and let the user know how to build the fuzzer properly.
    cros_build_lib.Die(
        '%s is not instrumented with source based coverage.\nSpecify --package '
        'to do a coverage build or build with USE flag: "coverage".', fuzzer)

  corpus = options.corpus
  if options.download:
    corpus = DownloadFuzzerCorpus(options.fuzzer)

  # Set up sysroot for fuzzing.
  SetUpSysrootForFuzzing()

  coverage_report_path = RunFuzzerAndGenerateCoverageReport(
      fuzzer, corpus, options.fuzz_args)

  # Get path on host so user can access it with their browser.
  # TODO(metzman): Add the ability to convert to host paths to path_util.
  external_trunk_path = os.getenv('EXTERNAL_TRUNK_PATH')
  coverage_report_host_path = os.path.join(external_trunk_path, 'chroot',
                                           coverage_report_path.chroot[1:])
  print('Coverage report written to file://%s/index.html' %
        coverage_report_host_path)


def ExecuteDownloadCommand(options):
  """Executes the "download" command. Wrapper around DownloadFuzzerCorpus."""
  DownloadFuzzerCorpus(StripFuzzerPrefixes(options.fuzzer), options.directory)


def ExecuteReproduceCommand(options):
  """Executes the "reproduce" command.

  Executes the "reproduce" command by Running a fuzzer on a testcase.
  May build the fuzzer before running.

  Args:
    options: The parsed arguments passed to this program.
  """
  if options.build_type and not options.package:
    raise Exception('Cannot specify --build_type without specifying --package.')

  # Verify that "msan-fuzzer" profile is being used with msan.
  # Check presence of "-fsanitize=memory" in CFLAGS.
  if options.build_type == BuildType.MSAN:
    cmd = ['portageq-%s' % options.board, 'envvar', 'CFLAGS']
    cflags = cros_build_lib.run(
        cmd, capture_output=True, encoding='utf-8').stdout.splitlines()
    check_string = '-fsanitize=memory'
    if not any(check_string in s for s in cflags):
      logging.error(
          '-fsanitize=memory not found in CFLAGS. '
          'Use "setup_board --board=amd64-generic --profile=msan-fuzzer" '
          'for MSan Fuzzing Builds.')
      raise Exception('Incompatible profile used for msan fuzzing.')

  BuildPackage(options.package, options.board, options.build_type)
  SetUpSysrootForFuzzing()
  Reproduce(StripFuzzerPrefixes(options.fuzzer), options.testcase)


def InstallBaseDependencies(options):
  """Installs the base packages needed to chroot in board sysroot.

  Args:
    options: The parsed arguments passed to this program.
  """
  package = 'virtual/implicit-system'
  if not portage_util.IsPackageInstalled(
      package, sysroot=SysrootPath.path_to_sysroot):
    build_type = getattr(options, 'build_type', None)
    BuildPackage(package, options.board, build_type)


def ParseArgs(argv):
  """Parses program arguments.

  Args:
    argv: The program arguments we want to parse.

  Returns:
    An options object which will tell us which command to run and which options
    to use for that command.
  """
  parser = commandline.ArgumentParser(description=__doc__)

  parser.add_argument(
      '--board',
      default=cros_build_lib.GetDefaultBoard(),
      help='Board on which to run test.')

  subparsers = parser.add_subparsers(dest='command')

  subparsers.add_parser('cleanup', help='Undo setup command.')
  coverage_parser = subparsers.add_parser(
      'coverage', help='Get a coverage report for a fuzzer.')

  coverage_parser.add_argument('--package', help='Package to build.')

  corpus_parser = coverage_parser.add_mutually_exclusive_group()
  corpus_parser.add_argument('--corpus', help='Corpus to run fuzzer on.')

  corpus_parser.add_argument(
      '--download',
      action='store_true',
      help='Generate coverage report based on corpus from ClusterFuzz.')

  coverage_parser.add_argument(
      '--fuzzer',
      required=True,
      help='The fuzz target to generate a coverage report for.')

  coverage_parser.add_argument(
      '--fuzz-args',
      default='',
      help='Arguments to pass libFuzzer. '
      'Please use an equals sign or parsing will fail '
      '(i.e. --fuzzer_args="-rss_limit_mb=2048 -print_funcs=1").')

  download_parser = subparsers.add_parser('download', help='Download a corpus.')

  download_parser.add_argument(
      '--directory', help='Path to directory to download the corpus to.')

  download_parser.add_argument(
      '--fuzzer', required=True, help='Fuzzer to download the corpus for.')

  reproduce_parser = subparsers.add_parser(
      'reproduce', help='Run a fuzzer on a testcase.')

  reproduce_parser.add_argument(
      '--testcase', required=True, help='Path of testcase to run fuzzer on.')

  reproduce_parser.add_argument(
      '--fuzzer', required=True, help='Fuzzer to reproduce the crash on.')

  reproduce_parser.add_argument('--package', help='Package to build.')

  reproduce_parser.add_argument(
      '--build-type',
      choices=BuildType.CHOICES,
      help='Type of build.',
      type=str.lower)  # Ignore sanitizer case.

  subparsers.add_parser('setup', help='Set up the sysroot to test fuzzing.')

  subparsers.add_parser(
      'shell',
      help='Set up sysroot for fuzzing and get a shell in the sysroot.')

  opts = parser.parse_args(argv)
  opts.Freeze()
  return opts


def main(argv):
  """Parses arguments and executes a command.

  Args:
    argv: The prorgram arguments.

  Returns:
    0 on success. Non-zero on failure.
  """
  cros_build_lib.AssertInsideChroot()
  options = ParseArgs(argv)
  if options.board is None:
    logging.error('Please specify "--board" or set ".default_board".')
    return 1

  SysrootPath.SetPathToSysroot(options.board)

  InstallBaseDependencies(options)

  if options.command == 'cleanup':
    ExecuteCleanupCommand()
  elif options.command == 'coverage':
    ExecuteCoverageCommand(options)
  elif options.command == 'setup':
    ExecuteSetupCommand()
  elif options.command == 'download':
    ExecuteDownloadCommand(options)
  elif options.command == 'reproduce':
    ExecuteReproduceCommand(options)
  elif options.command == 'shell':
    return ExecuteShellCommand()

  return 0
