//===- llvm-ifs.cpp -------------------------------------------------------===//
//
// 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
//
//===-----------------------------------------------------------------------===/

#include "ErrorCollector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/InterfaceStub/ELFObjHandler.h"
#include "llvm/InterfaceStub/IFSHandler.h"
#include "llvm/InterfaceStub/IFSStub.h"
#include "llvm/ObjectYAML/yaml2obj.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TextAPI/InterfaceFile.h"
#include "llvm/TextAPI/TextAPIReader.h"
#include "llvm/TextAPI/TextAPIWriter.h"
#include <optional>
#include <set>
#include <string>
#include <vector>

using namespace llvm;
using namespace llvm::yaml;
using namespace llvm::MachO;
using namespace llvm::ifs;

#define DEBUG_TYPE "llvm-ifs"

namespace {
const VersionTuple IfsVersionCurrent(3, 0);

enum class FileFormat { IFS, ELF, TBD };
} // end anonymous namespace

using namespace llvm::opt;
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 "Opts.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 "Opts.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 "Opts.inc"
#undef OPTION
};

class IFSOptTable : public opt::GenericOptTable {
public:
  IFSOptTable() : opt::GenericOptTable(InfoTable) {
    setGroupedShortOptions(true);
  }
};

struct DriverConfig {
  std::vector<std::string> InputFilePaths;

  std::optional<FileFormat> InputFormat;
  std::optional<FileFormat> OutputFormat;

  std::optional<std::string> HintIfsTarget;
  std::optional<std::string> OptTargetTriple;
  std::optional<IFSArch> OverrideArch;
  std::optional<IFSBitWidthType> OverrideBitWidth;
  std::optional<IFSEndiannessType> OverrideEndianness;

  bool StripIfsArch = false;
  bool StripIfsBitwidth = false;
  bool StripIfsEndianness = false;
  bool StripIfsTarget = false;
  bool StripNeeded = false;
  bool StripSize = false;
  bool StripUndefined = false;

  std::vector<std::string> Exclude;

  std::optional<std::string> SoName;

  std::optional<std::string> Output;
  std::optional<std::string> OutputElf;
  std::optional<std::string> OutputIfs;
  std::optional<std::string> OutputTbd;

  bool WriteIfChanged = false;
};

static std::string getTypeName(IFSSymbolType Type) {
  switch (Type) {
  case IFSSymbolType::NoType:
    return "NoType";
  case IFSSymbolType::Func:
    return "Func";
  case IFSSymbolType::Object:
    return "Object";
  case IFSSymbolType::TLS:
    return "TLS";
  case IFSSymbolType::Unknown:
    return "Unknown";
  }
  llvm_unreachable("Unexpected ifs symbol type.");
}

static Expected<std::unique_ptr<IFSStub>>
readInputFile(std::optional<FileFormat> &InputFormat, StringRef FilePath) {
  // Read in file.
  ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
      MemoryBuffer::getFileOrSTDIN(FilePath, /*IsText=*/true);
  if (!BufOrError)
    return createStringError(BufOrError.getError(), "Could not open `%s`",
                             FilePath.data());

  std::unique_ptr<MemoryBuffer> FileReadBuffer = std::move(*BufOrError);
  ErrorCollector EC(/*UseFatalErrors=*/false);

  // First try to read as a binary (fails fast if not binary).
  if (!InputFormat || *InputFormat == FileFormat::ELF) {
    Expected<std::unique_ptr<IFSStub>> StubFromELF =
        readELFFile(FileReadBuffer->getMemBufferRef());
    if (StubFromELF) {
      InputFormat = FileFormat::ELF;
      (*StubFromELF)->IfsVersion = IfsVersionCurrent;
      return std::move(*StubFromELF);
    }
    EC.addError(StubFromELF.takeError(), "BinaryRead");
  }

  // Fall back to reading as a ifs.
  if (!InputFormat || *InputFormat == FileFormat::IFS) {
    Expected<std::unique_ptr<IFSStub>> StubFromIFS =
        readIFSFromBuffer(FileReadBuffer->getBuffer());
    if (StubFromIFS) {
      InputFormat = FileFormat::IFS;
      if ((*StubFromIFS)->IfsVersion > IfsVersionCurrent)
        EC.addError(
            createStringError(errc::not_supported,
                              "IFS version " +
                                  (*StubFromIFS)->IfsVersion.getAsString() +
                                  " is unsupported."),
            "ReadInputFile");
      else
        return std::move(*StubFromIFS);
    } else {
      EC.addError(StubFromIFS.takeError(), "YamlParse");
    }
  }

  // If both readers fail, build a new error that includes all information.
  EC.addError(createStringError(errc::not_supported,
                                "No file readers succeeded reading `%s` "
                                "(unsupported/malformed file?)",
                                FilePath.data()),
              "ReadInputFile");
  EC.escalateToFatal();
  return EC.makeError();
}

static int writeTbdStub(const Triple &T, const std::vector<IFSSymbol> &Symbols,
                        const StringRef Format, raw_ostream &Out) {

  auto PlatformTypeOrError =
      [](const llvm::Triple &T) -> llvm::Expected<llvm::MachO::PlatformType> {
    if (T.isMacOSX())
      return llvm::MachO::PLATFORM_MACOS;
    if (T.isTvOS())
      return llvm::MachO::PLATFORM_TVOS;
    if (T.isWatchOS())
      return llvm::MachO::PLATFORM_WATCHOS;
    // Note: put isiOS last because tvOS and watchOS are also iOS according
    // to the Triple.
    if (T.isiOS())
      return llvm::MachO::PLATFORM_IOS;

    return createStringError(errc::not_supported, "Invalid Platform.\n");
  }(T);

  if (!PlatformTypeOrError)
    return -1;

  PlatformType Plat = PlatformTypeOrError.get();
  TargetList Targets({Target(llvm::MachO::mapToArchitecture(T), Plat)});

  InterfaceFile File;
  File.setFileType(FileType::TBD_V3); // Only supporting v3 for now.
  File.addTargets(Targets);

  for (const auto &Symbol : Symbols) {
    auto Name = Symbol.Name;
    auto Kind = SymbolKind::GlobalSymbol;
    switch (Symbol.Type) {
    default:
    case IFSSymbolType::NoType:
      Kind = SymbolKind::GlobalSymbol;
      break;
    case IFSSymbolType::Object:
      Kind = SymbolKind::GlobalSymbol;
      break;
    case IFSSymbolType::Func:
      Kind = SymbolKind::GlobalSymbol;
      break;
    }
    if (Symbol.Weak)
      File.addSymbol(Kind, Name, Targets, SymbolFlags::WeakDefined);
    else
      File.addSymbol(Kind, Name, Targets);
  }

  SmallString<4096> Buffer;
  raw_svector_ostream OS(Buffer);
  if (Error Result = TextAPIWriter::writeToStream(OS, File))
    return -1;
  Out << OS.str();
  return 0;
}

static void fatalError(Error Err) {
  WithColor::defaultErrorHandler(std::move(Err));
  exit(1);
}

static void fatalError(Twine T) {
  WithColor::error() << T.str() << '\n';
  exit(1);
}

/// writeIFS() writes a Text-Based ELF stub to a file using the latest version
/// of the YAML parser.
static Error writeIFS(StringRef FilePath, IFSStub &Stub, bool WriteIfChanged) {
  // Write IFS to memory first.
  std::string IFSStr;
  raw_string_ostream OutStr(IFSStr);
  Error YAMLErr = writeIFSToOutputStream(OutStr, Stub);
  if (YAMLErr)
    return YAMLErr;
  OutStr.flush();

  if (WriteIfChanged) {
    if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
            MemoryBuffer::getFile(FilePath)) {
      // Compare IFS output with the existing IFS file. If unchanged, avoid
      // changing the file.
      if ((*BufOrError)->getBuffer() == IFSStr)
        return Error::success();
    }
  }
  // Open IFS file for writing.
  std::error_code SysErr;
  raw_fd_ostream Out(FilePath, SysErr);
  if (SysErr)
    return createStringError(SysErr, "Couldn't open `%s` for writing",
                             FilePath.data());
  Out << IFSStr;
  return Error::success();
}

static DriverConfig parseArgs(int argc, char *const *argv) {
  BumpPtrAllocator A;
  StringSaver Saver(A);
  IFSOptTable Tbl;
  StringRef ToolName = argv[0];
  llvm::opt::InputArgList Args = Tbl.parseArgs(
      argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) { fatalError(Msg); });
  if (Args.hasArg(OPT_help)) {
    Tbl.printHelp(llvm::outs(),
                  (Twine(ToolName) + " <input_file> <output_file> [options]")
                      .str()
                      .c_str(),
                  "shared object stubbing tool");
    std::exit(0);
  }
  if (Args.hasArg(OPT_version)) {
    llvm::outs() << ToolName << '\n';
    cl::PrintVersionMessage();
    std::exit(0);
  }

  DriverConfig Config;
  for (const opt::Arg *A : Args.filtered(OPT_INPUT))
    Config.InputFilePaths.push_back(A->getValue());
  if (const opt::Arg *A = Args.getLastArg(OPT_input_format_EQ)) {
    Config.InputFormat = StringSwitch<std::optional<FileFormat>>(A->getValue())
                             .Case("IFS", FileFormat::IFS)
                             .Case("ELF", FileFormat::ELF)
                             .Default(std::nullopt);
    if (!Config.InputFormat)
      fatalError(Twine("invalid argument '") + A->getValue());
  }

  auto OptionNotFound = [ToolName](StringRef FlagName, StringRef OptionName) {
    fatalError(Twine(ToolName) + ": for the " + FlagName +
               " option: Cannot find option named '" + OptionName + "'!");
  };
  if (const opt::Arg *A = Args.getLastArg(OPT_output_format_EQ)) {
    Config.OutputFormat = StringSwitch<std::optional<FileFormat>>(A->getValue())
                              .Case("IFS", FileFormat::IFS)
                              .Case("ELF", FileFormat::ELF)
                              .Case("TBD", FileFormat::TBD)
                              .Default(std::nullopt);
    if (!Config.OutputFormat)
      OptionNotFound("--output-format", A->getValue());
  }
  if (const opt::Arg *A = Args.getLastArg(OPT_arch_EQ))
    Config.OverrideArch = ELF::convertArchNameToEMachine(A->getValue());

  if (const opt::Arg *A = Args.getLastArg(OPT_bitwidth_EQ)) {
    size_t Width;
    llvm::StringRef S(A->getValue());
    if (!S.getAsInteger<size_t>(10, Width) || Width == 64 || Width == 32)
      Config.OverrideBitWidth =
          Width == 64 ? IFSBitWidthType::IFS64 : IFSBitWidthType::IFS32;
    else
      OptionNotFound("--bitwidth", A->getValue());
  }
  if (const opt::Arg *A = Args.getLastArg(OPT_endianness_EQ)) {
    Config.OverrideEndianness =
        StringSwitch<std::optional<IFSEndiannessType>>(A->getValue())
            .Case("little", IFSEndiannessType::Little)
            .Case("big", IFSEndiannessType::Big)
            .Default(std::nullopt);
    if (!Config.OverrideEndianness)
      OptionNotFound("--endianness", A->getValue());
  }
  if (const opt::Arg *A = Args.getLastArg(OPT_target_EQ))
    Config.OptTargetTriple = A->getValue();
  if (const opt::Arg *A = Args.getLastArg(OPT_hint_ifs_target_EQ))
    Config.HintIfsTarget = A->getValue();

  Config.StripIfsArch = Args.hasArg(OPT_strip_ifs_arch);
  Config.StripIfsBitwidth = Args.hasArg(OPT_strip_ifs_bitwidth);
  Config.StripIfsEndianness = Args.hasArg(OPT_strip_ifs_endianness);
  Config.StripIfsTarget = Args.hasArg(OPT_strip_ifs_target);
  Config.StripUndefined = Args.hasArg(OPT_strip_undefined);
  Config.StripNeeded = Args.hasArg(OPT_strip_needed);
  Config.StripSize = Args.hasArg(OPT_strip_size);

  for (const opt::Arg *A : Args.filtered(OPT_exclude_EQ))
    Config.Exclude.push_back(A->getValue());
  if (const opt::Arg *A = Args.getLastArg(OPT_soname_EQ))
    Config.SoName = A->getValue();
  if (const opt::Arg *A = Args.getLastArg(OPT_output_EQ))
    Config.Output = A->getValue();
  if (const opt::Arg *A = Args.getLastArg(OPT_output_elf_EQ))
    Config.OutputElf = A->getValue();
  if (const opt::Arg *A = Args.getLastArg(OPT_output_ifs_EQ))
    Config.OutputIfs = A->getValue();
  if (const opt::Arg *A = Args.getLastArg(OPT_output_tbd_EQ))
    Config.OutputTbd = A->getValue();
  Config.WriteIfChanged = Args.hasArg(OPT_write_if_changed);
  return Config;
}

int llvm_ifs_main(int argc, char **argv) {
  DriverConfig Config = parseArgs(argc, argv);

  if (Config.InputFilePaths.empty())
    Config.InputFilePaths.push_back("-");

  // If input files are more than one, they can only be IFS files.
  if (Config.InputFilePaths.size() > 1)
    Config.InputFormat = FileFormat::IFS;

  // Attempt to merge input.
  IFSStub Stub;
  std::map<std::string, IFSSymbol> SymbolMap;
  std::string PreviousInputFilePath;
  for (const std::string &InputFilePath : Config.InputFilePaths) {
    Expected<std::unique_ptr<IFSStub>> StubOrErr =
        readInputFile(Config.InputFormat, InputFilePath);
    if (!StubOrErr)
      fatalError(StubOrErr.takeError());

    std::unique_ptr<IFSStub> TargetStub = std::move(StubOrErr.get());
    if (PreviousInputFilePath.empty()) {
      Stub.IfsVersion = TargetStub->IfsVersion;
      Stub.Target = TargetStub->Target;
      Stub.SoName = TargetStub->SoName;
      Stub.NeededLibs = TargetStub->NeededLibs;
    } else {
      if (Stub.IfsVersion != TargetStub->IfsVersion) {
        if (Stub.IfsVersion.getMajor() != IfsVersionCurrent.getMajor()) {
          WithColor::error()
              << "Interface Stub: IfsVersion Mismatch."
              << "\nFilenames: " << PreviousInputFilePath << " "
              << InputFilePath << "\nIfsVersion Values: " << Stub.IfsVersion
              << " " << TargetStub->IfsVersion << "\n";
          return -1;
        }
        if (TargetStub->IfsVersion > Stub.IfsVersion)
          Stub.IfsVersion = TargetStub->IfsVersion;
      }
      if (Stub.Target != TargetStub->Target && !TargetStub->Target.empty()) {
        WithColor::error() << "Interface Stub: Target Mismatch."
                           << "\nFilenames: " << PreviousInputFilePath << " "
                           << InputFilePath;
        return -1;
      }
      if (Stub.SoName != TargetStub->SoName) {
        WithColor::error() << "Interface Stub: SoName Mismatch."
                           << "\nFilenames: " << PreviousInputFilePath << " "
                           << InputFilePath
                           << "\nSoName Values: " << Stub.SoName << " "
                           << TargetStub->SoName << "\n";
        return -1;
      }
      if (Stub.NeededLibs != TargetStub->NeededLibs) {
        WithColor::error() << "Interface Stub: NeededLibs Mismatch."
                           << "\nFilenames: " << PreviousInputFilePath << " "
                           << InputFilePath << "\n";
        return -1;
      }
    }

    for (auto Symbol : TargetStub->Symbols) {
      auto SI = SymbolMap.find(Symbol.Name);
      if (SI == SymbolMap.end()) {
        SymbolMap.insert(
            std::pair<std::string, IFSSymbol>(Symbol.Name, Symbol));
        continue;
      }

      assert(Symbol.Name == SI->second.Name && "Symbol Names Must Match.");

      // Check conflicts:
      if (Symbol.Type != SI->second.Type) {
        WithColor::error() << "Interface Stub: Type Mismatch for "
                           << Symbol.Name << ".\nFilename: " << InputFilePath
                           << "\nType Values: " << getTypeName(SI->second.Type)
                           << " " << getTypeName(Symbol.Type) << "\n";

        return -1;
      }
      if (Symbol.Size != SI->second.Size) {
        WithColor::error() << "Interface Stub: Size Mismatch for "
                           << Symbol.Name << ".\nFilename: " << InputFilePath
                           << "\nSize Values: " << SI->second.Size << " "
                           << Symbol.Size << "\n";

        return -1;
      }
      if (Symbol.Weak != SI->second.Weak) {
        Symbol.Weak = false;
        continue;
      }
      // TODO: Not checking Warning. Will be dropped.
    }

    PreviousInputFilePath = InputFilePath;
  }

  if (Stub.IfsVersion != IfsVersionCurrent)
    if (Stub.IfsVersion.getMajor() != IfsVersionCurrent.getMajor()) {
      WithColor::error() << "Interface Stub: Bad IfsVersion: "
                         << Stub.IfsVersion << ", llvm-ifs supported version: "
                         << IfsVersionCurrent << ".\n";
      return -1;
    }

  for (auto &Entry : SymbolMap)
    Stub.Symbols.push_back(Entry.second);

  // Change SoName before emitting stubs.
  if (Config.SoName)
    Stub.SoName = *Config.SoName;

  Error OverrideError =
      overrideIFSTarget(Stub, Config.OverrideArch, Config.OverrideEndianness,
                        Config.OverrideBitWidth, Config.OptTargetTriple);
  if (OverrideError)
    fatalError(std::move(OverrideError));

  if (Config.StripNeeded)
    Stub.NeededLibs.clear();

  if (Error E = filterIFSSyms(Stub, Config.StripUndefined, Config.Exclude))
    fatalError(std::move(E));

  if (Config.StripSize)
    for (IFSSymbol &Sym : Stub.Symbols)
      Sym.Size.reset();

  if (!Config.OutputElf && !Config.OutputIfs && !Config.OutputTbd) {
    if (!Config.OutputFormat) {
      WithColor::error() << "at least one output should be specified.";
      return -1;
    }
  } else if (Config.OutputFormat) {
    WithColor::error() << "'--output-format' cannot be used with "
                          "'--output-{FILE_FORMAT}' options at the same time";
    return -1;
  }
  if (Config.OutputFormat) {
    // TODO: Remove OutputFormat flag in the next revision.
    WithColor::warning() << "--output-format option is deprecated, please use "
                            "--output-{FILE_FORMAT} options instead\n";
    switch (*Config.OutputFormat) {
    case FileFormat::TBD: {
      std::error_code SysErr;
      raw_fd_ostream Out(*Config.Output, SysErr);
      if (SysErr) {
        WithColor::error() << "Couldn't open " << *Config.Output
                           << " for writing.\n";
        return -1;
      }
      if (!Stub.Target.Triple) {
        WithColor::error()
            << "Triple should be defined when output format is TBD";
        return -1;
      }
      return writeTbdStub(llvm::Triple(*Stub.Target.Triple), Stub.Symbols,
                          "TBD", Out);
    }
    case FileFormat::IFS: {
      Stub.IfsVersion = IfsVersionCurrent;
      if (*Config.InputFormat == FileFormat::ELF && Config.HintIfsTarget) {
        std::error_code HintEC(1, std::generic_category());
        IFSTarget HintTarget = parseTriple(*Config.HintIfsTarget);
        if (*Stub.Target.Arch != *HintTarget.Arch)
          fatalError(make_error<StringError>(
              "Triple hint does not match the actual architecture", HintEC));
        if (*Stub.Target.Endianness != *HintTarget.Endianness)
          fatalError(make_error<StringError>(
              "Triple hint does not match the actual endianness", HintEC));
        if (*Stub.Target.BitWidth != *HintTarget.BitWidth)
          fatalError(make_error<StringError>(
              "Triple hint does not match the actual bit width", HintEC));

        stripIFSTarget(Stub, true, false, false, false);
        Stub.Target.Triple = *Config.HintIfsTarget;
      } else {
        stripIFSTarget(Stub, Config.StripIfsTarget, Config.StripIfsArch,
                       Config.StripIfsEndianness, Config.StripIfsBitwidth);
      }
      Error IFSWriteError =
          writeIFS(*Config.Output, Stub, Config.WriteIfChanged);
      if (IFSWriteError)
        fatalError(std::move(IFSWriteError));
      break;
    }
    case FileFormat::ELF: {
      Error TargetError = validateIFSTarget(Stub, true);
      if (TargetError)
        fatalError(std::move(TargetError));
      Error BinaryWriteError =
          writeBinaryStub(*Config.Output, Stub, Config.WriteIfChanged);
      if (BinaryWriteError)
        fatalError(std::move(BinaryWriteError));
      break;
    }
    }
  } else {
    // Check if output path for individual format.
    if (Config.OutputElf) {
      Error TargetError = validateIFSTarget(Stub, true);
      if (TargetError)
        fatalError(std::move(TargetError));
      Error BinaryWriteError =
          writeBinaryStub(*Config.OutputElf, Stub, Config.WriteIfChanged);
      if (BinaryWriteError)
        fatalError(std::move(BinaryWriteError));
    }
    if (Config.OutputIfs) {
      Stub.IfsVersion = IfsVersionCurrent;
      if (*Config.InputFormat == FileFormat::ELF && Config.HintIfsTarget) {
        std::error_code HintEC(1, std::generic_category());
        IFSTarget HintTarget = parseTriple(*Config.HintIfsTarget);
        if (*Stub.Target.Arch != *HintTarget.Arch)
          fatalError(make_error<StringError>(
              "Triple hint does not match the actual architecture", HintEC));
        if (*Stub.Target.Endianness != *HintTarget.Endianness)
          fatalError(make_error<StringError>(
              "Triple hint does not match the actual endianness", HintEC));
        if (*Stub.Target.BitWidth != *HintTarget.BitWidth)
          fatalError(make_error<StringError>(
              "Triple hint does not match the actual bit width", HintEC));

        stripIFSTarget(Stub, true, false, false, false);
        Stub.Target.Triple = *Config.HintIfsTarget;
      } else {
        stripIFSTarget(Stub, Config.StripIfsTarget, Config.StripIfsArch,
                       Config.StripIfsEndianness, Config.StripIfsBitwidth);
      }
      Error IFSWriteError =
          writeIFS(*Config.OutputIfs, Stub, Config.WriteIfChanged);
      if (IFSWriteError)
        fatalError(std::move(IFSWriteError));
    }
    if (Config.OutputTbd) {
      std::error_code SysErr;
      raw_fd_ostream Out(*Config.OutputTbd, SysErr);
      if (SysErr) {
        WithColor::error() << "Couldn't open " << *Config.OutputTbd
                           << " for writing.\n";
        return -1;
      }
      if (!Stub.Target.Triple) {
        WithColor::error()
            << "Triple should be defined when output format is TBD";
        return -1;
      }
      return writeTbdStub(llvm::Triple(*Stub.Target.Triple), Stub.Symbols,
                          "TBD", Out);
    }
  }
  return 0;
}
