//===- dsymutil.cpp - Debug info dumping utility for llvm -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This program is a utility that aims to be a dropin replacement for Darwin's
// dsymutil.
//===----------------------------------------------------------------------===//

#include "dsymutil.h"
#include "BinaryHolder.h"
#include "CFBundle.h"
#include "DebugMap.h"
#include "DwarfLinkerForBinary.h"
#include "LinkUtils.h"
#include "MachOUtils.h"
#include "Reproducer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/MachO.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/FileCollector.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/LLVMDriver.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/thread.h"
#include "llvm/TargetParser/Triple.h"
#include <algorithm>
#include <cstdint>
#include <cstdlib>
#include <string>
#include <system_error>

using namespace llvm;
using namespace llvm::dsymutil;
using namespace object;

namespace {
enum ID {
  OPT_INVALID = 0, // This is not an option ID.
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
               HELPTEXT, METAVAR, VALUES)                                      \
  OPT_##ID,
#include "Options.inc"
#undef OPTION
};

#define PREFIX(NAME, VALUE)                                                    \
  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
                                                std::size(NAME##_init) - 1);
#include "Options.inc"
#undef PREFIX

static constexpr opt::OptTable::Info InfoTable[] = {
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
               HELPTEXT, METAVAR, VALUES)                                      \
  {                                                                            \
      PREFIX,      NAME,      HELPTEXT,                                        \
      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
      PARAM,       FLAGS,     OPT_##GROUP,                                     \
      OPT_##ALIAS, ALIASARGS, VALUES},
#include "Options.inc"
#undef OPTION
};

class DsymutilOptTable : public opt::GenericOptTable {
public:
  DsymutilOptTable() : opt::GenericOptTable(InfoTable) {}
};
} // namespace

enum class DWARFVerify : uint8_t {
  None = 0,
  Input = 1 << 0,
  Output = 1 << 1,
  OutputOnValidInput = 1 << 2,
  All = Input | Output,
  Auto = Input | OutputOnValidInput,
#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
  Default = None // FIXME: Auto
#else
  Default = None
#endif
};

inline bool flagIsSet(DWARFVerify Flags, DWARFVerify SingleFlag) {
  return static_cast<uint8_t>(Flags) & static_cast<uint8_t>(SingleFlag);
}

struct DsymutilOptions {
  bool DumpDebugMap = false;
  bool DumpStab = false;
  bool Flat = false;
  bool InputIsYAMLDebugMap = false;
  bool PaperTrailWarnings = false;
  bool ForceKeepFunctionForStatic = false;
  std::string SymbolMap;
  std::string OutputFile;
  std::string Toolchain;
  std::string ReproducerPath;
  std::vector<std::string> Archs;
  std::vector<std::string> InputFiles;
  unsigned NumThreads;
  DWARFVerify Verify = DWARFVerify::Default;
  ReproducerMode ReproMode = ReproducerMode::GenerateOnCrash;
  dsymutil::LinkOptions LinkOpts;
};

/// Return a list of input files. This function has logic for dealing with the
/// special case where we might have dSYM bundles as input. The function
/// returns an error when the directory structure doesn't match that of a dSYM
/// bundle.
static Expected<std::vector<std::string>> getInputs(opt::InputArgList &Args,
                                                    bool DsymAsInput) {
  std::vector<std::string> InputFiles;
  for (auto *File : Args.filtered(OPT_INPUT))
    InputFiles.push_back(File->getValue());

  if (!DsymAsInput)
    return InputFiles;

  // If we are updating, we might get dSYM bundles as input.
  std::vector<std::string> Inputs;
  for (const auto &Input : InputFiles) {
    if (!sys::fs::is_directory(Input)) {
      Inputs.push_back(Input);
      continue;
    }

    // Make sure that we're dealing with a dSYM bundle.
    SmallString<256> BundlePath(Input);
    sys::path::append(BundlePath, "Contents", "Resources", "DWARF");
    if (!sys::fs::is_directory(BundlePath))
      return make_error<StringError>(
          Input + " is a directory, but doesn't look like a dSYM bundle.",
          inconvertibleErrorCode());

    // Create a directory iterator to iterate over all the entries in the
    // bundle.
    std::error_code EC;
    sys::fs::directory_iterator DirIt(BundlePath, EC);
    sys::fs::directory_iterator DirEnd;
    if (EC)
      return errorCodeToError(EC);

    // Add each entry to the list of inputs.
    while (DirIt != DirEnd) {
      Inputs.push_back(DirIt->path());
      DirIt.increment(EC);
      if (EC)
        return errorCodeToError(EC);
    }
  }
  return Inputs;
}

// Verify that the given combination of options makes sense.
static Error verifyOptions(const DsymutilOptions &Options) {
  if (Options.InputFiles.empty()) {
    return make_error<StringError>("no input files specified",
                                   errc::invalid_argument);
  }

  if (Options.LinkOpts.Update && llvm::is_contained(Options.InputFiles, "-")) {
    // FIXME: We cannot use stdin for an update because stdin will be
    // consumed by the BinaryHolder during the debugmap parsing, and
    // then we will want to consume it again in DwarfLinker. If we
    // used a unique BinaryHolder object that could cache multiple
    // binaries this restriction would go away.
    return make_error<StringError>(
        "standard input cannot be used as input for a dSYM update.",
        errc::invalid_argument);
  }

  if (!Options.Flat && Options.OutputFile == "-")
    return make_error<StringError>(
        "cannot emit to standard output without --flat.",
        errc::invalid_argument);

  if (Options.InputFiles.size() > 1 && Options.Flat &&
      !Options.OutputFile.empty())
    return make_error<StringError>(
        "cannot use -o with multiple inputs in flat mode.",
        errc::invalid_argument);

  if (Options.PaperTrailWarnings && Options.InputIsYAMLDebugMap)
    return make_error<StringError>(
        "paper trail warnings are not supported for YAML input.",
        errc::invalid_argument);

  if (!Options.ReproducerPath.empty() &&
      Options.ReproMode != ReproducerMode::Use)
    return make_error<StringError>(
        "cannot combine --gen-reproducer and --use-reproducer.",
        errc::invalid_argument);

  return Error::success();
}

static Expected<DsymutilAccelTableKind>
getAccelTableKind(opt::InputArgList &Args) {
  if (opt::Arg *Accelerator = Args.getLastArg(OPT_accelerator)) {
    StringRef S = Accelerator->getValue();
    if (S == "Apple")
      return DsymutilAccelTableKind::Apple;
    if (S == "Dwarf")
      return DsymutilAccelTableKind::Dwarf;
    if (S == "Pub")
      return DsymutilAccelTableKind::Pub;
    if (S == "Default")
      return DsymutilAccelTableKind::Default;
    if (S == "None")
      return DsymutilAccelTableKind::None;
    return make_error<StringError>("invalid accelerator type specified: '" + S +
                                       "'. Supported values are 'Apple', "
                                       "'Dwarf', 'Pub', 'Default' and 'None'.",
                                   inconvertibleErrorCode());
  }
  return DsymutilAccelTableKind::Default;
}

static Expected<ReproducerMode> getReproducerMode(opt::InputArgList &Args) {
  if (Args.hasArg(OPT_gen_reproducer))
    return ReproducerMode::GenerateOnExit;
  if (opt::Arg *Reproducer = Args.getLastArg(OPT_reproducer)) {
    StringRef S = Reproducer->getValue();
    if (S == "GenerateOnExit")
      return ReproducerMode::GenerateOnExit;
    if (S == "GenerateOnCrash")
      return ReproducerMode::GenerateOnCrash;
    if (S == "Off")
      return ReproducerMode::Off;
    return make_error<StringError>(
        "invalid reproducer mode: '" + S +
            "'. Supported values are 'GenerateOnExit', 'GenerateOnCrash', "
            "'Off'.",
        inconvertibleErrorCode());
  }
  return ReproducerMode::GenerateOnCrash;
}

static Expected<DWARFVerify> getVerifyKind(opt::InputArgList &Args) {
  if (Args.hasArg(OPT_verify))
    return DWARFVerify::Output;
  if (opt::Arg *Verify = Args.getLastArg(OPT_verify_dwarf)) {
    StringRef S = Verify->getValue();
    if (S == "input")
      return DWARFVerify::Input;
    if (S == "output")
      return DWARFVerify::Output;
    if (S == "all")
      return DWARFVerify::All;
    if (S == "auto")
      return DWARFVerify::Auto;
    if (S == "none")
      return DWARFVerify::None;
    return make_error<StringError>("invalid verify type specified: '" + S +
                                       "'. Supported values are 'none', "
                                       "'input', 'output', 'all' and 'auto'.",
                                   inconvertibleErrorCode());
  }
  return DWARFVerify::Default;
}

/// Parses the command line options into the LinkOptions struct and performs
/// some sanity checking. Returns an error in case the latter fails.
static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
  DsymutilOptions Options;

  Options.DumpDebugMap = Args.hasArg(OPT_dump_debug_map);
  Options.DumpStab = Args.hasArg(OPT_symtab);
  Options.Flat = Args.hasArg(OPT_flat);
  Options.InputIsYAMLDebugMap = Args.hasArg(OPT_yaml_input);
  Options.PaperTrailWarnings = Args.hasArg(OPT_papertrail);

  if (Expected<DWARFVerify> Verify = getVerifyKind(Args)) {
    Options.Verify = *Verify;
  } else {
    return Verify.takeError();
  }

  Options.LinkOpts.NoODR = Args.hasArg(OPT_no_odr);
  Options.LinkOpts.VerifyInputDWARF =
      flagIsSet(Options.Verify, DWARFVerify::Input);
  Options.LinkOpts.NoOutput = Args.hasArg(OPT_no_output);
  Options.LinkOpts.NoTimestamp = Args.hasArg(OPT_no_swiftmodule_timestamp);
  Options.LinkOpts.Update = Args.hasArg(OPT_update);
  Options.LinkOpts.Verbose = Args.hasArg(OPT_verbose);
  Options.LinkOpts.Statistics = Args.hasArg(OPT_statistics);
  Options.LinkOpts.Fat64 = Args.hasArg(OPT_fat64);
  Options.LinkOpts.KeepFunctionForStatic =
      Args.hasArg(OPT_keep_func_for_static);

  if (opt::Arg *ReproducerPath = Args.getLastArg(OPT_use_reproducer)) {
    Options.ReproMode = ReproducerMode::Use;
    Options.ReproducerPath = ReproducerPath->getValue();
  } else {
    if (Expected<ReproducerMode> ReproMode = getReproducerMode(Args)) {
      Options.ReproMode = *ReproMode;
    } else {
      return ReproMode.takeError();
    }
  }

  if (Expected<DsymutilAccelTableKind> AccelKind = getAccelTableKind(Args)) {
    Options.LinkOpts.TheAccelTableKind = *AccelKind;
  } else {
    return AccelKind.takeError();
  }

  if (opt::Arg *SymbolMap = Args.getLastArg(OPT_symbolmap))
    Options.SymbolMap = SymbolMap->getValue();

  if (Args.hasArg(OPT_symbolmap))
    Options.LinkOpts.Update = true;

  if (Expected<std::vector<std::string>> InputFiles =
          getInputs(Args, Options.LinkOpts.Update)) {
    Options.InputFiles = std::move(*InputFiles);
  } else {
    return InputFiles.takeError();
  }

  for (auto *Arch : Args.filtered(OPT_arch))
    Options.Archs.push_back(Arch->getValue());

  if (opt::Arg *OsoPrependPath = Args.getLastArg(OPT_oso_prepend_path))
    Options.LinkOpts.PrependPath = OsoPrependPath->getValue();

  for (const auto &Arg : Args.getAllArgValues(OPT_object_prefix_map)) {
    auto Split = StringRef(Arg).split('=');
    Options.LinkOpts.ObjectPrefixMap.insert(
        {std::string(Split.first), std::string(Split.second)});
  }

  if (opt::Arg *OutputFile = Args.getLastArg(OPT_output))
    Options.OutputFile = OutputFile->getValue();

  if (opt::Arg *Toolchain = Args.getLastArg(OPT_toolchain))
    Options.Toolchain = Toolchain->getValue();

  if (Args.hasArg(OPT_assembly))
    Options.LinkOpts.FileType = OutputFileType::Assembly;

  if (opt::Arg *NumThreads = Args.getLastArg(OPT_threads))
    Options.LinkOpts.Threads = atoi(NumThreads->getValue());
  else
    Options.LinkOpts.Threads = 0; // Use all available hardware threads

  if (Options.DumpDebugMap || Options.LinkOpts.Verbose)
    Options.LinkOpts.Threads = 1;

  if (getenv("RC_DEBUG_OPTIONS"))
    Options.PaperTrailWarnings = true;

  if (opt::Arg *RemarksPrependPath = Args.getLastArg(OPT_remarks_prepend_path))
    Options.LinkOpts.RemarksPrependPath = RemarksPrependPath->getValue();

  if (opt::Arg *RemarksOutputFormat =
          Args.getLastArg(OPT_remarks_output_format)) {
    if (Expected<remarks::Format> FormatOrErr =
            remarks::parseFormat(RemarksOutputFormat->getValue()))
      Options.LinkOpts.RemarksFormat = *FormatOrErr;
    else
      return FormatOrErr.takeError();
  }

  Options.LinkOpts.RemarksKeepAll =
      !Args.hasArg(OPT_remarks_drop_without_debug);

  if (Error E = verifyOptions(Options))
    return std::move(E);
  return Options;
}

static Error createPlistFile(StringRef Bin, StringRef BundleRoot,
                             StringRef Toolchain) {
  // Create plist file to write to.
  SmallString<128> InfoPlist(BundleRoot);
  sys::path::append(InfoPlist, "Contents/Info.plist");
  std::error_code EC;
  raw_fd_ostream PL(InfoPlist, EC, sys::fs::OF_TextWithCRLF);
  if (EC)
    return make_error<StringError>(
        "cannot create Plist: " + toString(errorCodeToError(EC)), EC);

  CFBundleInfo BI = getBundleInfo(Bin);

  if (BI.IDStr.empty()) {
    StringRef BundleID = *sys::path::rbegin(BundleRoot);
    if (sys::path::extension(BundleRoot) == ".dSYM")
      BI.IDStr = std::string(sys::path::stem(BundleID));
    else
      BI.IDStr = std::string(BundleID);
  }

  // Print out information to the plist file.
  PL << "<?xml version=\"1.0\" encoding=\"UTF-8\"\?>\n"
     << "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
     << "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
     << "<plist version=\"1.0\">\n"
     << "\t<dict>\n"
     << "\t\t<key>CFBundleDevelopmentRegion</key>\n"
     << "\t\t<string>English</string>\n"
     << "\t\t<key>CFBundleIdentifier</key>\n"
     << "\t\t<string>com.apple.xcode.dsym.";
  printHTMLEscaped(BI.IDStr, PL);
  PL << "</string>\n"
     << "\t\t<key>CFBundleInfoDictionaryVersion</key>\n"
     << "\t\t<string>6.0</string>\n"
     << "\t\t<key>CFBundlePackageType</key>\n"
     << "\t\t<string>dSYM</string>\n"
     << "\t\t<key>CFBundleSignature</key>\n"
     << "\t\t<string>\?\?\?\?</string>\n";

  if (!BI.OmitShortVersion()) {
    PL << "\t\t<key>CFBundleShortVersionString</key>\n";
    PL << "\t\t<string>";
    printHTMLEscaped(BI.ShortVersionStr, PL);
    PL << "</string>\n";
  }

  PL << "\t\t<key>CFBundleVersion</key>\n";
  PL << "\t\t<string>";
  printHTMLEscaped(BI.VersionStr, PL);
  PL << "</string>\n";

  if (!Toolchain.empty()) {
    PL << "\t\t<key>Toolchain</key>\n";
    PL << "\t\t<string>";
    printHTMLEscaped(Toolchain, PL);
    PL << "</string>\n";
  }

  PL << "\t</dict>\n"
     << "</plist>\n";

  PL.close();
  return Error::success();
}

static Error createBundleDir(StringRef BundleBase) {
  SmallString<128> Bundle(BundleBase);
  sys::path::append(Bundle, "Contents", "Resources", "DWARF");
  if (std::error_code EC =
          create_directories(Bundle.str(), true, sys::fs::perms::all_all))
    return make_error<StringError>(
        "cannot create bundle: " + toString(errorCodeToError(EC)), EC);

  return Error::success();
}

static bool verifyOutput(StringRef OutputFile, StringRef Arch,
                         DsymutilOptions Options) {

  if (OutputFile == "-") {
    WithColor::warning() << "verification skipped for " << Arch
                         << " because writing to stdout.\n";
    return true;
  }

  if (Options.LinkOpts.NoOutput) {
    WithColor::warning() << "verification skipped for " << Arch
                         << " because --no-output was passed.\n";
    return true;
  }

  Expected<OwningBinary<Binary>> BinOrErr = createBinary(OutputFile);
  if (!BinOrErr) {
    WithColor::error() << OutputFile << ": " << toString(BinOrErr.takeError());
    return false;
  }

  Binary &Binary = *BinOrErr.get().getBinary();
  if (auto *Obj = dyn_cast<MachOObjectFile>(&Binary)) {
    std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(*Obj);
    if (DICtx->getMaxVersion() >= 5) {
      WithColor::warning() << "verification skipped for " << Arch
                           << " because DWARFv5 is not fully supported yet.\n";
      return true;
    }
    raw_ostream &os = Options.LinkOpts.Verbose ? errs() : nulls();
    os << "Verifying DWARF for architecture: " << Arch << "\n";
    DIDumpOptions DumpOpts;
    bool success = DICtx->verify(os, DumpOpts.noImplicitRecursion());
    if (!success)
      WithColor::error() << "output verification failed for " << Arch << '\n';
    return success;
  }

  return false;
}

namespace {
struct OutputLocation {
  OutputLocation(std::string DWARFFile,
                 std::optional<std::string> ResourceDir = {})
      : DWARFFile(DWARFFile), ResourceDir(ResourceDir) {}
  /// This method is a workaround for older compilers.
  std::optional<std::string> getResourceDir() const { return ResourceDir; }
  std::string DWARFFile;
  std::optional<std::string> ResourceDir;
};
} // namespace

static Expected<OutputLocation>
getOutputFileName(StringRef InputFile, const DsymutilOptions &Options) {
  if (Options.OutputFile == "-")
    return OutputLocation(Options.OutputFile);

  // When updating, do in place replacement.
  if (Options.OutputFile.empty() &&
      (Options.LinkOpts.Update || !Options.SymbolMap.empty()))
    return OutputLocation(std::string(InputFile));

  // When dumping the debug map, just return an empty output location. This
  // allows us to compute the output location once.
  if (Options.DumpDebugMap)
    return OutputLocation("");

  // If a flat dSYM has been requested, things are pretty simple.
  if (Options.Flat) {
    if (Options.OutputFile.empty()) {
      if (InputFile == "-")
        return OutputLocation{"a.out.dwarf", {}};
      return OutputLocation((InputFile + ".dwarf").str());
    }

    return OutputLocation(Options.OutputFile);
  }

  // We need to create/update a dSYM bundle.
  // A bundle hierarchy looks like this:
  //   <bundle name>.dSYM/
  //       Contents/
  //          Info.plist
  //          Resources/
  //             DWARF/
  //                <DWARF file(s)>
  std::string DwarfFile =
      std::string(InputFile == "-" ? StringRef("a.out") : InputFile);
  SmallString<128> Path(Options.OutputFile);
  if (Path.empty())
    Path = DwarfFile + ".dSYM";
  if (!Options.LinkOpts.NoOutput) {
    if (auto E = createBundleDir(Path))
      return std::move(E);
    if (auto E = createPlistFile(DwarfFile, Path, Options.Toolchain))
      return std::move(E);
  }

  sys::path::append(Path, "Contents", "Resources");
  std::string ResourceDir = std::string(Path.str());
  sys::path::append(Path, "DWARF", sys::path::filename(DwarfFile));
  return OutputLocation(std::string(Path.str()), ResourceDir);
}

int main(int argc, char **argv) {
  InitLLVM X(argc, argv);

  // Parse arguments.
  DsymutilOptTable T;
  unsigned MAI;
  unsigned MAC;
  ArrayRef<const char *> ArgsArr = ArrayRef(argv + 1, argc - 1);
  opt::InputArgList Args = T.ParseArgs(ArgsArr, MAI, MAC);

  void *P = (void *)(intptr_t)getOutputFileName;
  std::string SDKPath = sys::fs::getMainExecutable(argv[0], P);
  SDKPath = std::string(sys::path::parent_path(SDKPath));

  for (auto *Arg : Args.filtered(OPT_UNKNOWN)) {
    WithColor::warning() << "ignoring unknown option: " << Arg->getSpelling()
                         << '\n';
  }

  if (Args.hasArg(OPT_help)) {
    T.printHelp(
        outs(), (std::string(argv[0]) + " [options] <input files>").c_str(),
        "manipulate archived DWARF debug symbol files.\n\n"
        "dsymutil links the DWARF debug information found in the object files\n"
        "for the executable <input file> by using debug symbols information\n"
        "contained in its symbol table.\n",
        false);
    return EXIT_SUCCESS;
  }

  if (Args.hasArg(OPT_version)) {
    cl::PrintVersionMessage();
    return EXIT_SUCCESS;
  }

  auto OptionsOrErr = getOptions(Args);
  if (!OptionsOrErr) {
    WithColor::error() << toString(OptionsOrErr.takeError()) << '\n';
    return EXIT_FAILURE;
  }

  auto &Options = *OptionsOrErr;

  InitializeAllTargetInfos();
  InitializeAllTargetMCs();
  InitializeAllTargets();
  InitializeAllAsmPrinters();

  auto Repro = Reproducer::createReproducer(Options.ReproMode,
                                            Options.ReproducerPath, argc, argv);
  if (!Repro) {
    WithColor::error() << toString(Repro.takeError()) << '\n';
    return EXIT_FAILURE;
  }

  Options.LinkOpts.VFS = (*Repro)->getVFS();

  for (const auto &Arch : Options.Archs)
    if (Arch != "*" && Arch != "all" &&
        !object::MachOObjectFile::isValidArch(Arch)) {
      WithColor::error() << "unsupported cpu architecture: '" << Arch << "'\n";
      return EXIT_FAILURE;
    }

  SymbolMapLoader SymMapLoader(Options.SymbolMap);

  for (auto &InputFile : Options.InputFiles) {
    // Dump the symbol table for each input file and requested arch
    if (Options.DumpStab) {
      if (!dumpStab(Options.LinkOpts.VFS, InputFile, Options.Archs,
                    Options.LinkOpts.PrependPath))
        return EXIT_FAILURE;
      continue;
    }

    auto DebugMapPtrsOrErr =
        parseDebugMap(Options.LinkOpts.VFS, InputFile, Options.Archs,
                      Options.LinkOpts.PrependPath, Options.PaperTrailWarnings,
                      Options.LinkOpts.Verbose, Options.InputIsYAMLDebugMap);

    if (auto EC = DebugMapPtrsOrErr.getError()) {
      WithColor::error() << "cannot parse the debug map for '" << InputFile
                         << "': " << EC.message() << '\n';
      return EXIT_FAILURE;
    }

    // Remember the number of debug maps that are being processed to decide how
    // to name the remark files.
    Options.LinkOpts.NumDebugMaps = DebugMapPtrsOrErr->size();

    if (Options.LinkOpts.Update) {
      // The debug map should be empty. Add one object file corresponding to
      // the input file.
      for (auto &Map : *DebugMapPtrsOrErr)
        Map->addDebugMapObject(InputFile,
                               sys::TimePoint<std::chrono::seconds>());
    }

    // Ensure that the debug map is not empty (anymore).
    if (DebugMapPtrsOrErr->empty()) {
      WithColor::error() << "no architecture to link\n";
      return EXIT_FAILURE;
    }

    // Shared a single binary holder for all the link steps.
    BinaryHolder BinHolder(Options.LinkOpts.VFS);

    // Compute the output location and update the resource directory.
    Expected<OutputLocation> OutputLocationOrErr =
        getOutputFileName(InputFile, Options);
    if (!OutputLocationOrErr) {
      WithColor::error() << toString(OutputLocationOrErr.takeError());
      return EXIT_FAILURE;
    }
    Options.LinkOpts.ResourceDir = OutputLocationOrErr->getResourceDir();

    // Statistics only require different architectures to be processed
    // sequentially, the link itself can still happen in parallel. Change the
    // thread pool strategy here instead of modifying LinkOpts.Threads.
    ThreadPoolStrategy S = hardware_concurrency(
        Options.LinkOpts.Statistics ? 1 : Options.LinkOpts.Threads);
    if (Options.LinkOpts.Threads == 0) {
      // If NumThreads is not specified, create one thread for each input, up to
      // the number of hardware threads.
      S.ThreadsRequested = DebugMapPtrsOrErr->size();
      S.Limit = true;
    }
    ThreadPool Threads(S);

    // If there is more than one link to execute, we need to generate
    // temporary files.
    const bool NeedsTempFiles =
        !Options.DumpDebugMap && (Options.OutputFile != "-") &&
        (DebugMapPtrsOrErr->size() != 1 || Options.LinkOpts.Update);

    // Set up a crash recovery context.
    CrashRecoveryContext::Enable();
    CrashRecoveryContext CRC;
    CRC.DumpStackAndCleanupOnFailure = true;

    std::atomic_char AllOK(1);
    SmallVector<MachOUtils::ArchAndFile, 4> TempFiles;

    std::mutex ErrorHandlerMutex;

    const bool Crashed = !CRC.RunSafely([&]() {
      for (auto &Map : *DebugMapPtrsOrErr) {
        if (Options.LinkOpts.Verbose || Options.DumpDebugMap)
          Map->print(outs());

        if (Options.DumpDebugMap)
          continue;

        if (!Options.SymbolMap.empty())
          Options.LinkOpts.Translator = SymMapLoader.Load(InputFile, *Map);

        if (Map->begin() == Map->end())
          WithColor::warning()
              << "no debug symbols in executable (-arch "
              << MachOUtils::getArchName(Map->getTriple().getArchName())
              << ")\n";

        // Using a std::shared_ptr rather than std::unique_ptr because move-only
        // types don't work with std::bind in the ThreadPool implementation.
        std::shared_ptr<raw_fd_ostream> OS;

        std::string OutputFile = OutputLocationOrErr->DWARFFile;
        if (NeedsTempFiles) {
          TempFiles.emplace_back(Map->getTriple().getArchName().str());

          auto E = TempFiles.back().createTempFile();
          if (E) {
            WithColor::error() << toString(std::move(E));
            AllOK.fetch_and(false);
            return;
          }

          auto &TempFile = *(TempFiles.back().File);
          OS = std::make_shared<raw_fd_ostream>(TempFile.FD,
                                                /*shouldClose*/ false);
          OutputFile = TempFile.TmpName;
        } else {
          std::error_code EC;
          OS = std::make_shared<raw_fd_ostream>(
              Options.LinkOpts.NoOutput ? "-" : OutputFile, EC,
              sys::fs::OF_None);
          if (EC) {
            WithColor::error() << OutputFile << ": " << EC.message();
            AllOK.fetch_and(false);
            return;
          }
        }

        auto LinkLambda = [&,
                           OutputFile](std::shared_ptr<raw_fd_ostream> Stream) {
          DwarfLinkerForBinary Linker(*Stream, BinHolder, Options.LinkOpts,
                                      ErrorHandlerMutex);
          AllOK.fetch_and(Linker.link(*Map));
          Stream->flush();
          if (flagIsSet(Options.Verify, DWARFVerify::Output) ||
              (flagIsSet(Options.Verify, DWARFVerify::OutputOnValidInput) &&
               !Linker.InputVerificationFailed())) {
            AllOK.fetch_and(verifyOutput(
                OutputFile, Map->getTriple().getArchName(), Options));
          }
        };

        // FIXME: The DwarfLinker can have some very deep recursion that can max
        // out the (significantly smaller) stack when using threads. We don't
        // want this limitation when we only have a single thread.
        if (S.ThreadsRequested == 1)
          LinkLambda(OS);
        else
          Threads.async(LinkLambda, OS);
      }

      Threads.wait();
    });

    if (Crashed)
      (*Repro)->generate();

    if (!AllOK)
      return EXIT_FAILURE;

    if (NeedsTempFiles) {
      const bool Fat64 = Options.LinkOpts.Fat64;
      if (!Fat64) {
        // Universal Mach-O files can't have an archicture slice that starts
        // beyond the 4GB boundary. "lipo" can create a 64 bit universal
        // header, but not all tools can parse these files so we want to return
        // an error if the file can't be encoded as a file with a 32 bit
        // universal header. To detect this, we check the size of each
        // architecture's skinny Mach-O file and add up the offsets. If they
        // exceed 4GB, then we return an error.

        // First we compute the right offset where the first architecture will
        // fit followin the 32 bit universal header. The 32 bit universal header
        // starts with a uint32_t magic and a uint32_t number of architecture
        // infos. Then it is followed by 5 uint32_t values for each
        // architecture. So we set the start offset to the right value so we can
        // calculate the exact offset that the first architecture slice can
        // start at.
        constexpr uint64_t MagicAndCountSize = 2 * 4;
        constexpr uint64_t UniversalArchInfoSize = 5 * 4;
        uint64_t FileOffset =
            MagicAndCountSize + UniversalArchInfoSize * TempFiles.size();
        for (const auto &File : TempFiles) {
          ErrorOr<vfs::Status> stat = Options.LinkOpts.VFS->status(File.path());
          if (!stat)
            break;
          if (FileOffset > UINT32_MAX) {
            WithColor::error()
                << formatv("the universal binary has a slice with a starting "
                           "offset ({0:x}) that exceeds 4GB and will produce "
                           "an invalid Mach-O file. Use the -fat64 flag to "
                           "generate a universal binary with a 64-bit header "
                           "but note that not all tools support this format.",
                           FileOffset);
            return EXIT_FAILURE;
          }
          FileOffset += stat->getSize();
        }
      }
      if (!MachOUtils::generateUniversalBinary(
              TempFiles, OutputLocationOrErr->DWARFFile, Options.LinkOpts,
              SDKPath, Fat64))
        return EXIT_FAILURE;
    }
  }

  return EXIT_SUCCESS;
}
