// Copyright 2020 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.

// @dart = 2.8

import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:core';
import 'dart:io';

import 'package:crypto/crypto.dart' show sha256;
import 'package:pool/pool.dart';
import 'package:path/path.dart' as path;
import 'package:googleapis/discovery/v1.dart' as discovery;

import 'package:codesize/codesize.dart';
import 'package:codesize/crash_handling.dart' as crash_handling;
import 'package:codesize/cli.dart' as cli;
import 'package:codesize/io.dart' as io;

import 'progress_bar.dart';

/// The common location for storing Fuchsia debug symbols. See fxbug.dev/41031.
const _fxSymbolCache = '.fuchsia/debug/symbol-cache';

/// Entry point of our application from the command line.
Future<void> main(List<String> args) =>
    runWithIo<io.Standard, void>(() => mainImpl(args));

Future<void> mainImpl(List<String> args) async {
  final parsedArgs = cli.parseArgs(args);
  if (parsedArgs == null) return;

  await crash_handling.withExceptionHandler(() async {
    // The high-level flow of the program:
    // - Generate bloaty reports if they aren't already cached.
    // - Run requested queries on those reports.
    // - Present the results in the specified format.
    await preflightChecks();

    final cs = CodeSize(parsedArgs.buildDir);

    AnalysisRequest allBloatyReportFiles = await ensureReportFiles(cs,
        cachingBehavior: parsedArgs.cachingBehavior,
        heatmap: parsedArgs.heatmap,
        heatmapFrameSize: parsedArgs.heatmapFrameSize);

    List<Query> populatedQueries = await runQueriesOnReports(
        parsedArgs.selectedQueries,
        parsedArgs.concurrency,
        parsedArgs.onlyLang,
        parsedArgs.fileRegex,
        allBloatyReportFiles,
        cs);

    await presentResults(
        parsedArgs.format, parsedArgs.output, populatedQueries);
  });
}

/// Checks preconditions for running codesize:
/// - The CPU architecture should be arm64.
Future<void> preflightChecks() async {
  final fxEnv = Io.get().fxEnv;
  if (fxEnv.fuchsiaArch != 'arm64') {
    throw crash_handling.KnownFailure('`fx codesize` is only supported '
        'in arm64 builds. The current architecture is ${fxEnv.fuchsiaArch}.\n'
        'Please switch to the correct product using `fx set`.');
  }
}

class ParseManifestResult {
  /// List of `meta.far` files indicating packages.
  final List<File> packageFars;

  /// A mapping from Merkel roots to blob information.
  final Map<String, Blob> blobsByHash;

  ParseManifestResult(this.packageFars, this.blobsByHash);
}

class CodeSize {
  CodeSize(String buildDir) : build = Build(buildDir);

  final Build build;

  /// List of packages in the build.
  final List<Package> packages = <Package>[];

  /// A mapping from BuildIds to build artifacts with that BuildId.
  /// There might be multiple artifacts with the same BuildId. For instance,
  /// the same binary might appear in both fuchsia.zbi and zedboot.zbi.
  HashMap<String, SplayTreeSet<BuildArtifact>> artifactsByBuildId =
      HashMap<String, SplayTreeSet<BuildArtifact>>();

  /// A mapping from BuildIds to lists of files with that BuildId.
  final HashMap<String, SplayTreeSet<File>> debugBinaries =
      HashMap<String, SplayTreeSet<File>>();

  /// A mapping from BuildIds to link map files.
  final HashMap<String, File> buildIdToLinkMapFile = HashMap<String, File>();

  /// The set of BuilIds for which we have obtained a debug binary.
  final Set<String> matchedDebugBinaries = <String>{};

  // Callbacks used to control the progress bar.
  void Function(int) jobInitCallback;
  void Function() jobIterationCallback;
  void Function() jobCompleteCallback;

  /// I/O operations implementation.
  final Io io = Io.get();

  Future<ParseManifestResult> parseManifest(File manifestFile) async {
    final List<File> packageFars = <File>[];
    final Map<String, Blob> blobsByHash = {};

    final manifestDir = manifestFile.parent;
    final lines = await manifestFile.readAsLines();
    // Format of the manifest:
    // HASH = RELATIVE PATH
    for (final line in lines) {
      final parts = line.split('=');
      final hash = parts[0];
      // Path entries are specified relative to the directory
      // containing the manifest.
      final entryPath = build.rebasePath((manifestDir / File(parts[1])).path);
      final file = build.openFile(entryPath);
      if (entryPath.endsWith('meta.far')) {
        // Blobs ending with `meta.far` indicate there is a
        // corresponding package.
        packageFars.add(file);
      }

      final stat = file.statSync();
      if (stat.type == FileSystemEntityType.notFound) {
        throw Exception('$entryPath does not exist');
      }
      if (blobsByHash.containsKey(hash)) {
        // Duplicate blob entry.
        io.err.writeln(
            'Duplicate blob entry: $hash -> ${build.rebasePath(entryPath)} '
            'and ${blobsByHash[hash].buildPath}');
        continue;
      }
      blobsByHash[hash] = await createBlob(hash, entryPath, stat);
    }
    return ParseManifestResult(
        packageFars.toList(growable: false), blobsByHash);
  }

  Future<Blob> createBlob(String hash, String entryPath, FileStat stat) async {
    final blob = Blob()
      ..hash = hash
      ..buildPath = build.rebasePath(entryPath)
      ..sizeOnHost = stat.size
      ..count = 0;

    // Extract contents as subBlobs if the blob is a Zircon Boot Image.
    if (entryPath.endsWith('.zbi.signed')) {
      blob.subBlobs = await extractZbi(entryPath);
    }
    return blob;
  }

  /// Extracts the ZBI inside the build directory and returns the contents
  /// as a list of `SubBlob`s.
  Future<List<SubBlob>> extractZbi(String entryPath) async {
    // Signed ZBI cannot be processed directly by the zbi tool.
    // Use the unsigned counterpart.
    final unsignedZbi =
        build.openFile(entryPath.substring(0, entryPath.length - 7));
    final bootfsDir = build.openDirectory(
        'obj/codesize/bootfs-${unsignedZbi.path.split('/').last}');
    if (bootfsDir.existsSync()) {
      // Clear previously extracted directory.
      await bootfsDir.delete(recursive: true);
    }
    await bootfsDir.create(recursive: true);
    print('Extracting ${build.rebasePath(unsignedZbi.path)}');
    // Run the zbi host tool.
    // out/default/host_x64/zbi --extract --output-dir ~/vg/out/tmp out/default/fuchsia.zbi
    final result = await io.processManager.run([
      build.openFile('host_x64/zbi').path,
      '--extract',
      '--output-dir',
      bootfsDir.absolute.path,
      unsignedZbi.absolute.path
    ],
        workingDirectory: build.dir.path,
        stdoutEncoding: const AsciiCodec(allowInvalid: true),
        stderrEncoding: const AsciiCodec(allowInvalid: true));
    if (result.exitCode != 0) {
      print('stdout: ${result.stdout}');
      print('stderr: ${result.stderr}');
      throw Exception('Failed to extract zbi for $unsignedZbi');
    }
    final files = bootfsDir.list(recursive: true, followLinks: false);
    final subBlobs = <SubBlob>[];
    await for (final file in files) {
      if (file is File) {
        final subBlob = SubBlob()
          ..name =
              path.relative(path.normalize(file.path), from: bootfsDir.path)
          ..buildPath = build.rebasePath(file.path)
          ..sizeOnHost = (file.statSync()).size;
        subBlobs.add(subBlob);
      }
    }
    return subBlobs;
  }

  Future<void> addBlobSizes(File path, Map<String, Blob> blobsByHash) async {
    final blobs = json.decode(await path.readAsString());
    for (var blob in blobs) {
      final b = blobsByHash[blob['merkle']];
      b?.size = blob['size'];
    }
  }

  String metaFarPathToBlobsJson(File far) {
    // Assumes details of //build/package.gni, namely that it generates
    //   <build-dir>/.../<package>/meta.far
    // and puts a blobs.json file into
    //   <build-dir>/.../<package>/blobs.json
    if (!far.path.endsWith('/meta.far')) {
      throw Exception('Build details have changed');
    }
    final jsonPath = "${removeSuffix(far.path, 'meta.far')}blobs.json";
    if (!build.openFile(jsonPath).existsSync()) {
      throw Exception('Build details have changed - '
          'path to blobs.json $jsonPath not found for ${far.path}');
    }
    return jsonPath;
  }

  Future<void> computePackagesInParallel(
      ParseManifestResult manifest, int jobs) async {
    final tasks = <Future>[];
    for (var i = 0; i < jobs; i++) {
      tasks.add(computePackages(manifest));
    }
    await Future.wait(tasks);
  }

  Future<void> computePackages(ParseManifestResult manifest) async {
    final packageFars = manifest.packageFars.toList();
    while (packageFars.isNotEmpty) {
      File far = packageFars.removeLast();

      var package = Package()..path = far.path;
      var parts = package.path.split('/');
      package
        ..name = maybeRemoveSuffix(
            parts.length > 1 ? parts[parts.length - 2] : parts.last, '.meta')
        ..size = 0
        ..private = 0
        ..blobCount = 0
        ..blobsByPath = <String, Blob>{};

      var blobs = json.decode(
          await build.openFile(metaFarPathToBlobsJson(far)).readAsString());

      for (var blob in blobs) {
        var hash = blob['merkle'];
        var blobPath = build.rebasePath(blob['path']);
        var b = manifest.blobsByHash[hash];
        if (b == null) {
          throw Exception('$blobPath $hash is in a package manifest '
              'but not the final manifest');
        }
        b.count++;
        var sourcePath = build.openFile(blob['source_path']).path;
        // If the source_path looks like <something>/blobs/<merkle>, it from a
        // prebuilt package and has no meaningful source. Instead, use the path
        // within the package as its identifier.
        if (sourcePath.endsWith('/blobs/$hash')) {
          sourcePath = 'pkg:${package.name}/${build.rebasePath(blobPath)}';
        } else {
          sourcePath = build.rebasePath(sourcePath);
        }
        // We may see the same blob referenced from different packages with
        // different source paths. If all references agree with each other, use
        // that. Otherwise we would print the first observed path and
        // append " *" to denote that the path is only one of many.
        b.sourcePaths.add(sourcePath);
        package.blobsByPath[blobPath] = b;
      }

      packages.add(package);
    }
  }

  void computeStats(Map<String, Blob> blobsByHash) {
    blobsByHash.forEach((hash, blob) {
      if (blob.count == 0) {
        throw Exception('${blob.hash} is in the final manifest '
            'but not any package manifest');
      }
    });

    for (var package in packages) {
      for (var blob in package.blobsByPath.values) {
        package.size += blob.size;
        if (blob.count == 1) {
          package.private += blob.size;
        }
        package.blobCount++;
      }
    }
  }

  Future<void> addBuildIdFromBlobsInImage(Map<String, Blob> blobsByHash) async {
    final artifacts = blobsByHash.values.expand((blob) {
      return <BuildArtifact>[blob] + blob.subBlobs;
    });
    artifactsByBuildId = await readBuildId(
        artifacts,
        (BuildArtifact art) => build.openFile(art.buildPath),
        Platform.numberOfProcessors * 2);
  }

  Future<void> addBuildIdFromSymbolSources() async {
    final fuchsiaBuildDir = build.openDirectory('.build-id');
    final Directory zirconBuildDir =
        build.zirconBuildDirectory() / Directory('.build-id');
    final sourceTree = Directory(Platform.environment['FUCHSIA_DIR']).absolute;
    final home = Directory(Platform.environment['HOME']);
    final maybeCipdBuildIdDirs = ([
              'prebuilt/.build-id',
              'prebuilt/third_party/clang/linux-x64/lib/debug/.build-id',
              'prebuilt/third_party/clang/mac-x64/lib/debug/.build-id',
            ].map((e) => sourceTree / Directory(e)).toList() +
            [
              home / Directory(_fxSymbolCache),
            ])
        .where((e) => e.existsSync());
    await _addBuildId(Stream.fromIterable(
        [fuchsiaBuildDir, zirconBuildDir, ...maybeCipdBuildIdDirs]));
  }

  Future<void> _addBuildId(Stream<Directory> dirs) async {
    final debugFiles = <File>[];
    final contents = dirs.asyncExpand((dir) {
      if (!dir.existsSync()) {
        throw Exception('Cannot find ${dir.absolute}');
      }
      return dir.list(recursive: true, followLinks: false).where(
          (entity) => (entity is File) && entity.path.endsWith('.debug'));
    });
    await for (final entity in contents) {
      if (entity is File) {
        debugFiles.add(entity);
      }
    }
    debugBinaries.addAll(await readBuildId(
        debugFiles, (x) => x, Platform.numberOfProcessors * 2,
        compare: (File a, File b) => a.path.compareTo(b.path)));
  }

  void matchDebugBinaries() {
    for (final buildId in debugBinaries.keys) {
      if (artifactsByBuildId.containsKey(buildId)) {
        matchedDebugBinaries.add(buildId);
      }
    }
  }

  Future<HashMap<String, SplayTreeSet<T>>> readBuildId<T>(
      Iterable<T> items, File Function(T) toFile, int jobs,
      {int compare(T a, T b)}) async {
    jobInitCallback?.call(items.length);
    final exp = RegExp(
        r'(.*): ELF 64-bit LSB .*ARM aarch64,.*BuildID(.*)=([a-f0-9]+),');
    final buildIdToBlob = HashMap<String, SplayTreeSet<T>>();
    final pool = Pool(jobs);
    final allFutures = <Future>[];
    for (final blob in items) {
      final file = toFile(blob);
      allFutures.add(pool.withResource(() async {
        final result =
            await io.processManager.run(['file', file.absolute.path]);
        if (result.exitCode != 0) {
          print(result.stdout);
          print(result.stderr);
          throw Exception('Failed to inspect $file');
        }
        final matches = exp.allMatches(result.stdout);
        if (matches.isNotEmpty) {
          if (matches.length != 1) {
            throw Exception('Unexpected matches on `file $file`');
          }
          final match = matches.first;
          // Fuchsia uses [xxHash]; Chromium uses [sha1]
          final buildIdAlgo = match.group(2);
          if (buildIdAlgo != '[xxHash]' &&
              buildIdAlgo != '[sha1]' &&
              buildIdAlgo != '[md5/uuid]') {
            throw Exception(
                'Unexpected BuildId algo `$buildIdAlgo` on `file $file`');
          }
          final buildId = match.group(3);
          buildIdToBlob.putIfAbsent(buildId, () => SplayTreeSet<T>(compare));
          buildIdToBlob[buildId].add(blob);
        }
        jobIterationCallback?.call();
      }));
    }
    await Future.wait(allFutures);
    jobCompleteCallback?.call();
    return buildIdToBlob;
  }

  // Finds all `.map` files in the build directory, and find the corresponding
  // BuildID of the unstripped binary that is next to it.
  Future<void> collectLinkMapFiles() async {
    final files = build.dir.list(recursive: true, followLinks: false).where(
        (file) =>
            file.path.endsWith('.map') &&
            file.statSync().type == FileSystemEntityType.file);
    final elfFiles = <String>[];
    await for (var mapFile in files) {
      final elfFile =
          build.openFile(mapFile.path.substring(0, mapFile.path.length - 4));
      if (!elfFile.existsSync()) continue;
      elfFiles.add(elfFile.path);
    }
    final buildIds = await readBuildId(
        elfFiles, build.openFile, Platform.numberOfProcessors * 2);
    for (final entry in buildIds.entries) {
      buildIdToLinkMapFile[entry.key] =
          build.openFile('${entry.value.first}.map');
    }
  }
}

Future<AnalysisRequest> ensureReportFiles(CodeSize cs,
    {cli.CachingBehavior cachingBehavior,
    File heatmap,
    int heatmapFrameSize}) async {
  AnalysisRequest allBloatyReportFiles;
  final bloatyStamp = cs.build.openFile('codesize_bloaty_report.stamp');
  if (bloatyStamp.existsSync()) {
    bool useCache;
    switch (cachingBehavior) {
      case cli.CachingBehavior.alwaysUseCache:
        print('Explicitly using cached report files');
        useCache = true;
        break;
      case cli.CachingBehavior.neverUseCache:
        print('Ignoring cached report files');
        useCache = false;
        break;
      case cli.CachingBehavior.useIfUpToDate:
        // Use the cached reports if no newer full build was performed.
        final manifestStat = cs.build.blobManifestFile().statSync();
        final stampStat = bloatyStamp.statSync();
        useCache = stampStat.modified.isAfter(manifestStat.modified);
        if (useCache) {
          // Check if heatmap file remained the same too.
          final lastRequest = AnalysisRequest.fromJson(
              json.decode(await bloatyStamp.readAsString()));
          if (lastRequest.heatmapContentSha != null) {
            if (heatmap == null) {
              useCache = false;
            } else {
              final digest = await _hashFile(heatmap);
              if (digest != lastRequest.heatmapContentSha) {
                useCache = false;
              }
            }
          } else {
            if (heatmap != null) {
              useCache = false;
            }
          }
          if (!useCache) {
            print('Not using cached report files since '
                'the heatmap option has changed');
          }
        } else {
          print('Not using cached report files since '
              'a new full build has been performed');
        }
        if (useCache) {
          print('Using cached report files since '
              'it was generated after the last full build');
        }
        break;
    }
    if (useCache) {
      // Skipping running bloaty; load `allBloatyReportFiles` from stamp
      allBloatyReportFiles = AnalysisRequest.fromJson(
          json.decode(await bloatyStamp.readAsString()));
      print('Loaded ${allBloatyReportFiles.items.length} reports from cache');
      return allBloatyReportFiles;
    }
  }

  // Rerun bloaty and save the report file index as a stamp.
  try {
    allBloatyReportFiles = await generateBloatyReportsFromBuild(cs,
        heatmap: heatmap, heatmapFrameSize: heatmapFrameSize);
    await bloatyStamp.writeAsString(json.encode(allBloatyReportFiles.toJson()));
  } finally {
    await GoogleApiClient.close();
  }
  return allBloatyReportFiles;
}

Future<String> _hashFile(File heatmap) async =>
    sha256.convert(await heatmap.readAsBytes()).toString();

Future<List<Query>> runQueriesOnReports(
    List<QueryThunk> queries,
    int concurrency,
    SourceLang onlyLang,
    RegExp fileRegex,
    AnalysisRequest allBloatyReportFiles,
    CodeSize cs) async {
  print('Running these queries: ${queries.map((s) => s().name).join(', ')}');
  final queryRunner =
      QueryRunner(queries, numConcurrency: concurrency, onlyLang: onlyLang);
  final filteredReports = allBloatyReportFiles.items
      .where((report) => fileRegex.hasMatch(report.name));
  print(
      'Analyzing ${filteredReports.length} reports whose names match the ${fileRegex.pattern} regex');
  await Future.wait([
    for (final reportFile in filteredReports)
      queryRunner.addReport(reportFile.absolute(cs.build.dir.path))
  ]);
  await queryRunner.join();
  return queryRunner.queries;
}

Future<void> presentResults(cli.OutputFormat outputFormat, IOSink output,
    List<Query> populatedQueries) async {
  final io = Io.get();
  // Data presentation
  Renderer renderer;
  switch (outputFormat) {
    case cli.OutputFormat.basic:
      renderer = BasicRenderer();
      break;
    case cli.OutputFormat.html:
      renderer = HtmlRenderer();
      break;
    case cli.OutputFormat.terminal:
      renderer = TerminalRenderer(supportsControlCharacters: output == io.out);
      break;
    case cli.OutputFormat.tsv:
      renderer = TsvRenderer();
      break;
  }

  try {
    renderer.render(output, populatedQueries);
  } finally {
    await output.flush();
    if (output != io.out) {
      await output.close();
    }
  }
}

Future<AnalysisRequest> generateBloatyReportsFromBuild(CodeSize cs,
    {File heatmap, int heatmapFrameSize}) async {
  final allBloatyReportFiles = AnalysisRequest(
      items: [], heatmapContentSha: await flatMap(heatmap, _hashFile));
  final io = Io.get();

  final manifest = await cs.parseManifest(cs.build.blobManifestFile());
  final blobsByHash = manifest.blobsByHash;
  await cs.addBlobSizes(cs.build.openFile('blobs.json'), blobsByHash);
  await cs.computePackagesInParallel(manifest, Platform.numberOfProcessors);
  cs.computeStats(blobsByHash);

  ProgressBar progress;
  cs
    ..jobInitCallback = ((max) => progress = ProgressBar(complete: max))
    ..jobIterationCallback = (() => progress.update(progress.current + 1))
    ..jobCompleteCallback = (() => progress.done());

  io.out.write('Loading link maps ');
  await cs.collectLinkMapFiles();

  io.out.write('Loading BuildId for blobs in image ');
  await cs.addBuildIdFromBlobsInImage(blobsByHash);
  final elfBlobSizes = cs.artifactsByBuildId.values
      .map((e) => e.first.sizeOnHost)
      .reduce((v, e) => v + e);
  final allBlobSizes =
      blobsByHash.values.map((e) => e.sizeOnHost).reduce((v, e) => v + e);
  print('${cs.artifactsByBuildId.length} (${formatSize(elfBlobSizes)}) out of '
      '${blobsByHash.length} (${formatSize(allBlobSizes)}) blobs are '
      'ELF binaries');

  io.out.write('Loading BuildId from symbol sources ');
  await cs.addBuildIdFromSymbolSources();
  print('${cs.debugBinaries.length} debug binaries found locally');

  cs.matchDebugBinaries();
  final matchedBinarySizes = cs.matchedDebugBinaries
      .map((k) => cs.artifactsByBuildId[k].first.sizeOnHost)
      .reduce((v, e) => v + e);
  print('${cs.matchedDebugBinaries.length} (${formatSize(matchedBinarySizes)})'
      ' out of ${cs.artifactsByBuildId.length} (${formatSize(elfBlobSizes)})'
      ' ELF binaries have matching debug info');

  Iterable<String> buildIdsWithoutDebugInfo() => cs.artifactsByBuildId.keys
      .where((buildId) => !cs.matchedDebugBinaries.contains(buildId));

  {
    final noDebugInfo = buildIdsWithoutDebugInfo();
    if (noDebugInfo.isNotEmpty) {
      io.out.write('Querying symbol servers ');
      final gotAny = await downloadUnmatchedDebugBinaries(noDebugInfo, cs);
      if (gotAny) {
        io.out.write('Incorporate downloaded symbols ');
        await cs.addBuildIdFromSymbolSources();
        cs.matchDebugBinaries();
      } else {
        print('Did not find any extra symbols from symbol servers');
      }
    }
  }

  {
    // Print binaries without debug info even after querying symbol servers.
    final noDebugInfo = buildIdsWithoutDebugInfo();
    if (noDebugInfo.isNotEmpty) {
      print('Binaries without matching debug info:');
      for (final buildId in noDebugInfo) {
        final buildPath = cs.artifactsByBuildId[buildId].first.buildPath;
        print('  ${cs.build.rebasePath(buildPath)}');
        print('  - BuildId: $buildId');
        if (blobsByHash.containsKey(buildPath.split('/').last)) {
          final sourcePath = blobsByHash[buildPath.split('/').last].sourcePaths;
          print('  - Source Path: $sourcePath');
        }
      }
    }
  }

  var buildIds = <String>{};
  HashMap<String, String> buildIdToAccessPattern;
  if (heatmap != null) {
    buildIdToAccessPattern = HashMap<String, String>();
    final HashMap<String, String> merkleToAccessPattern =
        HashMap<String, String>();
    for (final line in await heatmap.readAsLines()) {
      if (line.trim().isEmpty) continue;
      final firstComma = line.indexOf(',');
      final merkle = line.substring(0, firstComma);
      final accessPattern = line.substring(firstComma + 1);
      merkleToAccessPattern[merkle] = accessPattern;
    }
    for (final entry in cs.artifactsByBuildId.entries) {
      final buildId = entry.key;
      final artifact = entry.value.first;
      if (artifact is Blob) {
        if (cs.matchedDebugBinaries.contains(buildId) &&
            merkleToAccessPattern.containsKey(artifact.hash)) {
          final accessPattern = merkleToAccessPattern[artifact.hash];
          // Exclude fully-hot blobs, since downstream queries would be confused
          // as to which language this ELF is written in due to lack of symbols.
          final int elfSize =
              cs.build.openFile(artifact.buildPath).statSync().size;
          final int numFrames = (elfSize / heatmapFrameSize).ceil();
          final isFrameHot = List<bool>.generate(numFrames, (i) => false);
          for (final part in accessPattern.split(',')) {
            final frameAndCount = part.split(':').toList();
            if (frameAndCount.length != 2) {
              throw Exception('Invalid access pattern $accessPattern');
            }
            final frame = int.parse(frameAndCount[0]);
            final count = int.parse(frameAndCount[1]);
            if (frame >= numFrames) {
              throw Exception('Blob merkle ${artifact.hash} '
                  '(at: ${artifact.buildPath}) is $elfSize bytes on disk, '
                  'but access pattern indicated an out-of-range frame $frame. '
                  'Does the heatmap CSV match the version of the build?');
            }
            if (count > 0) isFrameHot[frame] = true;
          }
          if (isFrameHot.every((e) => e)) continue;

          buildIds.add(buildId);
          buildIdToAccessPattern[buildId] = accessPattern;
        }
      }
    }

    io.out.writeln('Blob access heatmap specified, only looking at '
        '${buildIds.length} files with both cold regions and debug info');
    for (final buildId in buildIds) {
      io.out.writeln('-> ${cs.artifactsByBuildId[buildId].first}');
    }
  } else {
    buildIds = cs.matchedDebugBinaries;
  }

  io.out.write('Running bloaty on matched binaries ');
  await runBloatyOnMatchedBinaries(buildIds,
      options: RunBloatyOptions(
        build: cs.build,
        artifactsByBuildId: cs.artifactsByBuildId,
        debugBinaries: cs.debugBinaries,
        buildIdToLinkMapFile: cs.buildIdToLinkMapFile,
        buildIdToAccessPattern: buildIdToAccessPattern,
        heatmapFrameSize: heatmapFrameSize,
        jobInitCallback: cs.jobInitCallback,
        jobIterationCallback: cs.jobIterationCallback,
        jobCompleteCallback: cs.jobCompleteCallback,
      ));

  final zbiExtractedBinary = RegExp(r'obj/codesize/bootfs-(.*)\.zbi/(.*)$');
  for (final buildId in buildIds) {
    final blob = cs.artifactsByBuildId[buildId].first;
    var name = blob.buildPath;
    if (blob is SubBlob) {
      final match = zbiExtractedBinary.firstMatch(blob.buildPath);
      if (match != null)
        name = '[zbi: ${match.group(1)}.zbi] /${match.group(2)} '
            '(at: ${cs.build.rebasePath(blob.buildPath)})';
    } else if (blob is Blob) {
      final formattedBuildPath = cs.build.rebasePath(blob.buildPath);
      final prebuiltDueToPkgHash = blob.sourcePaths
          .fold(true, (prev, element) => prev && element.startsWith('pkg:'));
      final prebuiltInPrebuiltFolder =
          formattedBuildPath.startsWith('../../prebuilt/');
      if (prebuiltDueToPkgHash || prebuiltInPrebuiltFolder) {
        name = '[prebuilt] '
            '${blob.sourcePaths.first}'
            '${blob.sourcePaths.length > 1 ? "* " : ""} '
            '(at: $formattedBuildPath)';
      } else {
        final maybeNonPkgPrebuilt =
            blob.sourcePaths.where((e) => !e.startsWith('pkg:')).first;
        if (maybeNonPkgPrebuilt != null) {
          name = maybeNonPkgPrebuilt;
        } else {
          name = formattedBuildPath;
        }
      }
    }
    // If heatmap was specified, we'd generate two versions of reports, one of
    // which is filtered using the heatmap.
    final report = AnalysisItem(
        path: cs.build.rebasePath('${blob.buildPath}.bloaty_report_pb'),
        filteredCounterpart: heatmap != null
            ? cs.build.rebasePath('${blob.buildPath}.filtered.bloaty_report_pb')
            : null,
        name: name);
    if (!cs.build.openFile(report.path).existsSync())
      throw Exception('Could not find bloaty report at ${report.path}');
    allBloatyReportFiles.items.add(report);
  }

  return allBloatyReportFiles;
}

Future<bool> downloadUnmatchedDebugBinaries(
    Iterable<String> buildIds, CodeSize cs) async {
  final homeDir = Directory(Platform.environment['HOME']);
  final repos = await Future.wait([
    'gs://fuchsia-artifacts/debug',
    'gs://fuchsia-artifacts-internal/debug',
    'gs://fuchsia-artifacts-release/debug',
  ].map(
      (e) => CloudRepo.create(e, Cache(homeDir / Directory(_fxSymbolCache)))));
  var downloadedAny = false;
  cs.jobInitCallback?.call(buildIds.length);

  // 2 concurrent symbol downloads
  final pool = Pool(2);
  final allFutures = <Future>[];
  for (final buildId in buildIds) {
    allFutures.add(pool.withResource(() async {
      var downloaded = false;
      for (var repo in repos) {
        try {
          await repo.getBuildObject(buildId);
          // A 404 error will be expected if the debug symbol is not found.
          // ignore: avoid_catching_errors
        } on discovery.DetailedApiRequestError catch (err) {
          if (err.status != 404) {
            rethrow;
          }
          continue;
        }
        downloaded = true;
        break;
      }
      if (downloaded) downloadedAny = true;
      cs.jobIterationCallback?.call();
    }));
  }
  await Future.wait(allFutures);
  cs.jobCompleteCallback?.call();
  return downloadedAny;
}
