//===-- llvm-lipo.cpp - a tool for manipulating universal binaries --------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// A utility for creating / splitting / inspecting universal binaries.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/WithColor.h"
#include "llvm/TextAPI/MachO/Architecture.h"

using namespace llvm;
using namespace llvm::object;

static const StringRef ToolName = "llvm-lipo";

LLVM_ATTRIBUTE_NORETURN static void reportError(Twine Message) {
  WithColor::error(errs(), ToolName) << Message << "\n";
  errs().flush();
  exit(EXIT_FAILURE);
}

LLVM_ATTRIBUTE_NORETURN static void reportError(StringRef File, Error E) {
  assert(E);
  std::string Buf;
  raw_string_ostream OS(Buf);
  logAllUnhandledErrors(std::move(E), OS);
  OS.flush();
  WithColor::error(errs(), ToolName) << "'" << File << "': " << Buf;
  exit(EXIT_FAILURE);
}

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

// LipoInfoTable below references LIPO_##PREFIX. OptionGroup has prefix nullptr.
const char *const *LIPO_nullptr = nullptr;
#define PREFIX(NAME, VALUE) const char *const LIPO_##NAME[] = VALUE;
#include "LipoOpts.inc"
#undef PREFIX

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

class LipoOptTable : public opt::OptTable {
public:
  LipoOptTable() : OptTable(LipoInfoTable) {}
};

enum class LipoAction {
  PrintArchs,
  PrintInfo,
  VerifyArch,
  ThinArch,
  CreateUniversal,
  ReplaceArch,
};

struct InputFile {
  Optional<StringRef> ArchType;
  StringRef FileName;
};

struct Config {
  SmallVector<InputFile, 1> InputFiles;
  SmallVector<std::string, 1> VerifyArchList;
  SmallVector<InputFile, 1> ReplacementFiles;
  StringMap<const uint32_t> SegmentAlignments;
  std::string ThinArchType;
  std::string OutputFile;
  LipoAction ActionToPerform;
};

// For compatibility with cctools lipo, a file's alignment is calculated as the
// minimum aligment of all segments. For object files, the file's alignment is
// the maximum alignment of its sections.
static uint32_t calculateFileAlignment(const MachOObjectFile &O) {
  uint32_t P2CurrentAlignment;
  uint32_t P2MinAlignment = MachOUniversalBinary::MaxSectionAlignment;
  const bool Is64Bit = O.is64Bit();

  for (const auto &LC : O.load_commands()) {
    if (LC.C.cmd != (Is64Bit ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT))
      continue;
    if (O.getHeader().filetype == MachO::MH_OBJECT) {
      unsigned NumberOfSections =
          (Is64Bit ? O.getSegment64LoadCommand(LC).nsects
                   : O.getSegmentLoadCommand(LC).nsects);
      P2CurrentAlignment = NumberOfSections ? 2 : P2MinAlignment;
      for (unsigned SI = 0; SI < NumberOfSections; ++SI) {
        P2CurrentAlignment = std::max(P2CurrentAlignment,
                                      (Is64Bit ? O.getSection64(LC, SI).align
                                               : O.getSection(LC, SI).align));
      }
    } else {
      P2CurrentAlignment =
          countTrailingZeros(Is64Bit ? O.getSegment64LoadCommand(LC).vmaddr
                                     : O.getSegmentLoadCommand(LC).vmaddr);
    }
    P2MinAlignment = std::min(P2MinAlignment, P2CurrentAlignment);
  }
  // return a value >= 4 byte aligned, and less than MachO MaxSectionAlignment
  return std::max(
      static_cast<uint32_t>(2),
      std::min(P2MinAlignment, static_cast<uint32_t>(
                                   MachOUniversalBinary::MaxSectionAlignment)));
}

static uint32_t calculateAlignment(const MachOObjectFile *ObjectFile) {
  switch (ObjectFile->getHeader().cputype) {
  case MachO::CPU_TYPE_I386:
  case MachO::CPU_TYPE_X86_64:
  case MachO::CPU_TYPE_POWERPC:
  case MachO::CPU_TYPE_POWERPC64:
    return 12; // log2 value of page size(4k) for x86 and PPC
  case MachO::CPU_TYPE_ARM:
  case MachO::CPU_TYPE_ARM64:
  case MachO::CPU_TYPE_ARM64_32:
    return 14; // log2 value of page size(16k) for Darwin ARM
  default:
    return calculateFileAlignment(*ObjectFile);
  }
}

class Slice {
  const Binary *B;
  uint32_t CPUType;
  uint32_t CPUSubType;
  std::string ArchName;

  // P2Alignment field stores slice alignment values from universal
  // binaries. This is also needed to order the slices so the total
  // file size can be calculated before creating the output buffer.
  uint32_t P2Alignment;

public:
  Slice(const MachOObjectFile *O, uint32_t Align)
      : B(O), CPUType(O->getHeader().cputype),
        CPUSubType(O->getHeader().cpusubtype),
        ArchName(O->getArchTriple().getArchName()), P2Alignment(Align) {}

  explicit Slice(const MachOObjectFile *O) : Slice(O, calculateAlignment(O)){};

  explicit Slice(const Archive *A) : B(A) {
    Error Err = Error::success();
    std::unique_ptr<MachOObjectFile> FO = nullptr;
    for (const Archive::Child &Child : A->children(Err)) {
      Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
      if (!ChildOrErr)
        reportError(A->getFileName(), ChildOrErr.takeError());
      Binary *Bin = ChildOrErr.get().get();
      if (Bin->isMachOUniversalBinary())
        reportError(("archive member " + Bin->getFileName() +
                     " is a fat file (not allowed in an archive)")
                        .str());
      if (!Bin->isMachO())
        reportError(("archive member " + Bin->getFileName() +
                     " is not a MachO file (not allowed in an archive)"));
      MachOObjectFile *O = cast<MachOObjectFile>(Bin);
      if (FO &&
          std::tie(FO->getHeader().cputype, FO->getHeader().cpusubtype) !=
              std::tie(O->getHeader().cputype, O->getHeader().cpusubtype)) {
        reportError(("archive member " + O->getFileName() + " cputype (" +
                     Twine(O->getHeader().cputype) + ") and cpusubtype(" +
                     Twine(O->getHeader().cpusubtype) +
                     ") does not match previous archive members cputype (" +
                     Twine(FO->getHeader().cputype) + ") and cpusubtype(" +
                     Twine(FO->getHeader().cpusubtype) +
                     ") (all members must match) " + FO->getFileName())
                        .str());
      }
      if (!FO) {
        ChildOrErr.get().release();
        FO.reset(O);
      }
    }
    if (Err)
      reportError(A->getFileName(), std::move(Err));
    if (!FO)
      reportError(("empty archive with no architecture specification: " +
                   A->getFileName() + " (can't determine architecture for it)")
                      .str());
    CPUType = FO->getHeader().cputype;
    CPUSubType = FO->getHeader().cpusubtype;
    ArchName = FO->getArchTriple().getArchName();
    // Replicate the behavior of cctools lipo.
    P2Alignment = FO->is64Bit() ? 3 : 2;
  }

  void setP2Alignment(uint32_t Align) { P2Alignment = Align; }

  const Binary *getBinary() const { return B; }

  uint32_t getCPUType() const { return CPUType; }

  uint32_t getCPUSubType() const { return CPUSubType; }

  uint32_t getP2Alignment() const { return P2Alignment; }

  uint64_t getCPUID() const {
    return static_cast<uint64_t>(CPUType) << 32 | CPUSubType;
  }

  std::string getArchString() const {
    if (!ArchName.empty())
      return ArchName;
    return ("unknown(" + Twine(CPUType) + "," +
            Twine(CPUSubType & ~MachO::CPU_SUBTYPE_MASK) + ")")
        .str();
  }

  friend bool operator<(const Slice &Lhs, const Slice &Rhs) {
    if (Lhs.CPUType == Rhs.CPUType)
      return Lhs.CPUSubType < Rhs.CPUSubType;
    // force arm64-family to follow after all other slices for
    // compatibility with cctools lipo
    if (Lhs.CPUType == MachO::CPU_TYPE_ARM64)
      return false;
    if (Rhs.CPUType == MachO::CPU_TYPE_ARM64)
      return true;
    // Sort by alignment to minimize file size
    return Lhs.P2Alignment < Rhs.P2Alignment;
  }
};

} // end namespace

static void validateArchitectureName(StringRef ArchitectureName) {
  if (!MachOObjectFile::isValidArch(ArchitectureName)) {
    std::string Buf;
    raw_string_ostream OS(Buf);
    OS << "Invalid architecture: " << ArchitectureName
       << "\nValid architecture names are:";
    for (auto arch : MachOObjectFile::getValidArchs())
      OS << " " << arch;
    reportError(OS.str());
  }
}

static Config parseLipoOptions(ArrayRef<const char *> ArgsArr) {
  Config C;
  LipoOptTable T;
  unsigned MissingArgumentIndex, MissingArgumentCount;
  opt::InputArgList InputArgs =
      T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);

  if (MissingArgumentCount)
    reportError("missing argument to " +
                StringRef(InputArgs.getArgString(MissingArgumentIndex)) +
                " option");

  if (InputArgs.size() == 0) {
    // PrintHelp does not accept Twine.
    T.PrintHelp(errs(), "llvm-lipo input[s] option[s]", "llvm-lipo");
    exit(EXIT_FAILURE);
  }

  if (InputArgs.hasArg(LIPO_help)) {
    // PrintHelp does not accept Twine.
    T.PrintHelp(outs(), "llvm-lipo input[s] option[s]", "llvm-lipo");
    exit(EXIT_SUCCESS);
  }

  if (InputArgs.hasArg(LIPO_version)) {
    outs() << ToolName + "\n";
    cl::PrintVersionMessage();
    exit(EXIT_SUCCESS);
  }

  for (auto Arg : InputArgs.filtered(LIPO_UNKNOWN))
    reportError("unknown argument '" + Arg->getAsString(InputArgs) + "'");

  for (auto Arg : InputArgs.filtered(LIPO_INPUT))
    C.InputFiles.push_back({None, Arg->getValue()});
  for (auto Arg : InputArgs.filtered(LIPO_arch)) {
    validateArchitectureName(Arg->getValue(0));
    if (!Arg->getValue(1))
      reportError(
          "arch is missing an argument: expects -arch arch_type file_name");
    C.InputFiles.push_back({StringRef(Arg->getValue(0)), Arg->getValue(1)});
  }

  if (C.InputFiles.empty())
    reportError("at least one input file should be specified");

  if (InputArgs.hasArg(LIPO_output))
    C.OutputFile = InputArgs.getLastArgValue(LIPO_output);

  for (auto Segalign : InputArgs.filtered(LIPO_segalign)) {
    if (!Segalign->getValue(1))
      reportError("segalign is missing an argument: expects -segalign "
                  "arch_type alignment_value");

    validateArchitectureName(Segalign->getValue(0));

    uint32_t AlignmentValue;
    if (!to_integer<uint32_t>(Segalign->getValue(1), AlignmentValue, 16))
      reportError("argument to -segalign <arch_type> " +
                  Twine(Segalign->getValue(1)) +
                  " (hex) is not a proper hexadecimal number");
    if (!isPowerOf2_32(AlignmentValue))
      reportError("argument to -segalign <arch_type> " +
                  Twine(Segalign->getValue(1)) +
                  " (hex) must be a non-zero power of two");
    if (Log2_32(AlignmentValue) > MachOUniversalBinary::MaxSectionAlignment)
      reportError(
          "argument to -segalign <arch_type> " + Twine(Segalign->getValue(1)) +
          " (hex) must be less than or equal to the maximum section align 2^" +
          Twine(MachOUniversalBinary::MaxSectionAlignment));
    auto Entry = C.SegmentAlignments.try_emplace(Segalign->getValue(0),
                                                 Log2_32(AlignmentValue));
    if (!Entry.second)
      reportError("-segalign " + Twine(Segalign->getValue(0)) +
                  " <alignment_value> specified multiple times: " +
                  Twine(1 << Entry.first->second) + ", " +
                  Twine(AlignmentValue));
  }

  SmallVector<opt::Arg *, 1> ActionArgs(InputArgs.filtered(LIPO_action_group));
  if (ActionArgs.empty())
    reportError("at least one action should be specified");
  // errors if multiple actions specified other than replace
  // multiple replace flags may be specified, as long as they are not mixed with
  // other action flags
  auto ReplacementArgsRange = InputArgs.filtered(LIPO_replace);
  if (ActionArgs.size() > 1 &&
      ActionArgs.size() !=
          static_cast<size_t>(std::distance(ReplacementArgsRange.begin(),
                                            ReplacementArgsRange.end()))) {
    std::string Buf;
    raw_string_ostream OS(Buf);
    OS << "only one of the following actions can be specified:";
    for (auto Arg : ActionArgs)
      OS << " " << Arg->getSpelling();
    reportError(OS.str());
  }

  switch (ActionArgs[0]->getOption().getID()) {
  case LIPO_verify_arch:
    for (auto A : InputArgs.getAllArgValues(LIPO_verify_arch))
      C.VerifyArchList.push_back(A);
    if (C.VerifyArchList.empty())
      reportError(
          "verify_arch requires at least one architecture to be specified");
    if (C.InputFiles.size() > 1)
      reportError("verify_arch expects a single input file");
    C.ActionToPerform = LipoAction::VerifyArch;
    return C;

  case LIPO_archs:
    if (C.InputFiles.size() > 1)
      reportError("archs expects a single input file");
    C.ActionToPerform = LipoAction::PrintArchs;
    return C;

  case LIPO_info:
    C.ActionToPerform = LipoAction::PrintInfo;
    return C;

  case LIPO_thin:
    if (C.InputFiles.size() > 1)
      reportError("thin expects a single input file");
    C.ThinArchType = ActionArgs[0]->getValue();
    validateArchitectureName(C.ThinArchType);
    if (C.OutputFile.empty())
      reportError("thin expects a single output file");

    C.ActionToPerform = LipoAction::ThinArch;
    return C;

  case LIPO_create:
    if (C.OutputFile.empty())
      reportError("create expects a single output file to be specified");
    C.ActionToPerform = LipoAction::CreateUniversal;
    return C;

  case LIPO_replace:
    for (auto Action : ActionArgs) {
      if (!Action->getValue(1))
        reportError(
            "replace is missing an argument: expects -replace arch_type "
            "file_name");
      validateArchitectureName(Action->getValue(0));
      C.ReplacementFiles.push_back(
          {StringRef(Action->getValue(0)), Action->getValue(1)});
    }

    if (C.OutputFile.empty())
      reportError("replace expects a single output file to be specified");
    if (C.InputFiles.size() > 1)
      reportError("replace expects a single input file");
    C.ActionToPerform = LipoAction::ReplaceArch;
    return C;

  default:
    reportError("llvm-lipo action unspecified");
  }
}

static SmallVector<OwningBinary<Binary>, 1>
readInputBinaries(ArrayRef<InputFile> InputFiles) {
  SmallVector<OwningBinary<Binary>, 1> InputBinaries;
  for (const InputFile &IF : InputFiles) {
    Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(IF.FileName);
    if (!BinaryOrErr)
      reportError(IF.FileName, BinaryOrErr.takeError());
    const Binary *B = BinaryOrErr->getBinary();
    if (!B->isArchive() && !B->isMachO() && !B->isMachOUniversalBinary())
      reportError("File " + IF.FileName + " has unsupported binary format");
    if (IF.ArchType && (B->isMachO() || B->isArchive())) {
      const auto S = B->isMachO() ? Slice(cast<MachOObjectFile>(B))
                                  : Slice(cast<Archive>(B));
      const auto SpecifiedCPUType = MachO::getCPUTypeFromArchitecture(
                                        MachO::getArchitectureFromName(
                                            Triple(*IF.ArchType).getArchName()))
                                        .first;
      // For compatibility with cctools' lipo the comparison is relaxed just to
      // checking cputypes.
      if (S.getCPUType() != SpecifiedCPUType)
        reportError("specified architecture: " + *IF.ArchType +
                    " for file: " + B->getFileName() +
                    " does not match the file's architecture (" +
                    S.getArchString() + ")");
    }
    InputBinaries.push_back(std::move(*BinaryOrErr));
  }
  return InputBinaries;
}

LLVM_ATTRIBUTE_NORETURN
static void verifyArch(ArrayRef<OwningBinary<Binary>> InputBinaries,
                       ArrayRef<std::string> VerifyArchList) {
  assert(!VerifyArchList.empty() &&
         "The list of architectures should be non-empty");
  assert(InputBinaries.size() == 1 && "Incorrect number of input binaries");

  for (StringRef Arch : VerifyArchList)
    validateArchitectureName(Arch);

  if (auto UO =
          dyn_cast<MachOUniversalBinary>(InputBinaries.front().getBinary())) {
    for (StringRef Arch : VerifyArchList) {
      Expected<MachOUniversalBinary::ObjectForArch> Obj =
          UO->getObjectForArch(Arch);
      if (!Obj)
        exit(EXIT_FAILURE);
    }
  } else if (auto O =
                 dyn_cast<MachOObjectFile>(InputBinaries.front().getBinary())) {
    const Triple::ArchType ObjectArch = O->getArch();
    for (StringRef Arch : VerifyArchList)
      if (ObjectArch != Triple(Arch).getArch())
        exit(EXIT_FAILURE);
  } else {
    llvm_unreachable("Unexpected binary format");
  }
  exit(EXIT_SUCCESS);
}

static void printBinaryArchs(const Binary *Binary, raw_ostream &OS) {
  // Prints trailing space for compatibility with cctools lipo.
  if (auto UO = dyn_cast<MachOUniversalBinary>(Binary)) {
    for (const auto &O : UO->objects()) {
      Expected<std::unique_ptr<MachOObjectFile>> MachOObjOrError =
          O.getAsObjectFile();
      if (MachOObjOrError) {
        OS << Slice(MachOObjOrError->get()).getArchString() << " ";
        continue;
      }
      Expected<std::unique_ptr<Archive>> ArchiveOrError = O.getAsArchive();
      if (ArchiveOrError) {
        consumeError(MachOObjOrError.takeError());
        OS << Slice(ArchiveOrError->get()).getArchString() << " ";
        continue;
      }
      consumeError(ArchiveOrError.takeError());
      reportError(Binary->getFileName(), MachOObjOrError.takeError());
    }
    OS << "\n";
    return;
  }
  OS << Slice(cast<MachOObjectFile>(Binary)).getArchString() << " \n";
}

LLVM_ATTRIBUTE_NORETURN
static void printArchs(ArrayRef<OwningBinary<Binary>> InputBinaries) {
  assert(InputBinaries.size() == 1 && "Incorrect number of input binaries");
  printBinaryArchs(InputBinaries.front().getBinary(), outs());
  exit(EXIT_SUCCESS);
}

LLVM_ATTRIBUTE_NORETURN
static void printInfo(ArrayRef<OwningBinary<Binary>> InputBinaries) {
  // Group universal and thin files together for compatibility with cctools lipo
  for (auto &IB : InputBinaries) {
    const Binary *Binary = IB.getBinary();
    if (Binary->isMachOUniversalBinary()) {
      outs() << "Architectures in the fat file: " << Binary->getFileName()
             << " are: ";
      printBinaryArchs(Binary, outs());
    }
  }
  for (auto &IB : InputBinaries) {
    const Binary *Binary = IB.getBinary();
    if (!Binary->isMachOUniversalBinary()) {
      assert(Binary->isMachO() && "expected MachO binary");
      outs() << "Non-fat file: " << Binary->getFileName()
             << " is architecture: ";
      printBinaryArchs(Binary, outs());
    }
  }
  exit(EXIT_SUCCESS);
}

LLVM_ATTRIBUTE_NORETURN
static void extractSlice(ArrayRef<OwningBinary<Binary>> InputBinaries,
                         StringRef ThinArchType, StringRef OutputFileName) {
  assert(!ThinArchType.empty() && "The architecture type should be non-empty");
  assert(InputBinaries.size() == 1 && "Incorrect number of input binaries");
  assert(!OutputFileName.empty() && "Thin expects a single output file");

  if (InputBinaries.front().getBinary()->isMachO()) {
    reportError("input file " +
                InputBinaries.front().getBinary()->getFileName() +
                " must be a fat file when the -thin option is specified");
    exit(EXIT_FAILURE);
  }

  auto *UO = cast<MachOUniversalBinary>(InputBinaries.front().getBinary());
  Expected<std::unique_ptr<MachOObjectFile>> Obj =
      UO->getMachOObjectForArch(ThinArchType);
  Expected<std::unique_ptr<Archive>> Ar = UO->getArchiveForArch(ThinArchType);
  if (!Obj && !Ar)
    reportError("fat input file " + UO->getFileName() +
                " does not contain the specified architecture " + ThinArchType +
                " to thin it to");
  Binary *B = Obj ? static_cast<Binary *>(Obj->get())
                  : static_cast<Binary *>(Ar->get());
  Expected<std::unique_ptr<FileOutputBuffer>> OutFileOrError =
      FileOutputBuffer::create(OutputFileName,
                               B->getMemoryBufferRef().getBufferSize(),
                               sys::fs::can_execute(UO->getFileName())
                                   ? FileOutputBuffer::F_executable
                                   : 0);
  if (!OutFileOrError)
    reportError(OutputFileName, OutFileOrError.takeError());
  std::copy(B->getMemoryBufferRef().getBufferStart(),
            B->getMemoryBufferRef().getBufferEnd(),
            OutFileOrError.get()->getBufferStart());
  if (Error E = OutFileOrError.get()->commit())
    reportError(OutputFileName, std::move(E));
  exit(EXIT_SUCCESS);
}

static void checkArchDuplicates(ArrayRef<Slice> Slices) {
  DenseMap<uint64_t, const Binary *> CPUIds;
  for (const auto &S : Slices) {
    auto Entry = CPUIds.try_emplace(S.getCPUID(), S.getBinary());
    if (!Entry.second)
      reportError(Entry.first->second->getFileName() + " and " +
                  S.getBinary()->getFileName() +
                  " have the same architecture " + S.getArchString() +
                  " and therefore cannot be in the same universal binary");
  }
}

template <typename Range>
static void updateAlignments(Range &Slices,
                             const StringMap<const uint32_t> &Alignments) {
  for (auto &Slice : Slices) {
    auto Alignment = Alignments.find(Slice.getArchString());
    if (Alignment != Alignments.end())
      Slice.setP2Alignment(Alignment->second);
  }
}

static void checkUnusedAlignments(ArrayRef<Slice> Slices,
                                  const StringMap<const uint32_t> &Alignments) {
  auto HasArch = [&](StringRef Arch) {
    return llvm::find_if(Slices, [Arch](Slice S) {
             return S.getArchString() == Arch;
           }) != Slices.end();
  };
  for (StringRef Arch : Alignments.keys())
    if (!HasArch(Arch))
      reportError("-segalign " + Arch +
                  " <value> specified but resulting fat file does not contain "
                  "that architecture ");
}

// Updates vector ExtractedObjects with the MachOObjectFiles extracted from
// Universal Binary files to transfer ownership.
static SmallVector<Slice, 2> buildSlices(
    ArrayRef<OwningBinary<Binary>> InputBinaries,
    const StringMap<const uint32_t> &Alignments,
    SmallVectorImpl<std::unique_ptr<MachOObjectFile>> &ExtractedObjects) {
  SmallVector<Slice, 2> Slices;
  for (auto &IB : InputBinaries) {
    const Binary *InputBinary = IB.getBinary();
    if (auto UO = dyn_cast<MachOUniversalBinary>(InputBinary)) {
      for (const auto &O : UO->objects()) {
        Expected<std::unique_ptr<MachOObjectFile>> BinaryOrError =
            O.getAsObjectFile();
        if (!BinaryOrError)
          reportError(InputBinary->getFileName(), BinaryOrError.takeError());
        ExtractedObjects.push_back(std::move(BinaryOrError.get()));
        Slices.emplace_back(ExtractedObjects.back().get(), O.getAlign());
      }
    } else if (auto O = dyn_cast<MachOObjectFile>(InputBinary)) {
      Slices.emplace_back(O);
    } else if (auto A = dyn_cast<Archive>(InputBinary)) {
      Slices.emplace_back(A);
    } else {
      llvm_unreachable("Unexpected binary format");
    }
  }
  updateAlignments(Slices, Alignments);
  return Slices;
}

static SmallVector<MachO::fat_arch, 2>
buildFatArchList(ArrayRef<Slice> Slices) {
  SmallVector<MachO::fat_arch, 2> FatArchList;
  uint64_t Offset =
      sizeof(MachO::fat_header) + Slices.size() * sizeof(MachO::fat_arch);

  for (const auto &S : Slices) {
    Offset = alignTo(Offset, 1ull << S.getP2Alignment());
    if (Offset > UINT32_MAX)
      reportError("fat file too large to be created because the offset "
                  "field in struct fat_arch is only 32-bits and the offset " +
                  Twine(Offset) + " for " + S.getBinary()->getFileName() +
                  " for architecture " + S.getArchString() + "exceeds that.");

    MachO::fat_arch FatArch;
    FatArch.cputype = S.getCPUType();
    FatArch.cpusubtype = S.getCPUSubType();
    FatArch.offset = Offset;
    FatArch.size = S.getBinary()->getMemoryBufferRef().getBufferSize();
    FatArch.align = S.getP2Alignment();
    Offset += FatArch.size;
    FatArchList.push_back(FatArch);
  }
  return FatArchList;
}

static void createUniversalBinary(SmallVectorImpl<Slice> &Slices,
                                  StringRef OutputFileName) {
  MachO::fat_header FatHeader;
  FatHeader.magic = MachO::FAT_MAGIC;
  FatHeader.nfat_arch = Slices.size();

  stable_sort(Slices);
  SmallVector<MachO::fat_arch, 2> FatArchList = buildFatArchList(Slices);

  const bool IsExecutable = any_of(Slices, [](Slice S) {
    return sys::fs::can_execute(S.getBinary()->getFileName());
  });
  const uint64_t OutputFileSize =
      static_cast<uint64_t>(FatArchList.back().offset) +
      FatArchList.back().size;
  Expected<std::unique_ptr<FileOutputBuffer>> OutFileOrError =
      FileOutputBuffer::create(OutputFileName, OutputFileSize,
                               IsExecutable ? FileOutputBuffer::F_executable
                                            : 0);
  if (!OutFileOrError)
    reportError(OutputFileName, OutFileOrError.takeError());
  std::unique_ptr<FileOutputBuffer> OutFile = std::move(OutFileOrError.get());
  std::memset(OutFile->getBufferStart(), 0, OutputFileSize);

  if (sys::IsLittleEndianHost)
    MachO::swapStruct(FatHeader);
  std::memcpy(OutFile->getBufferStart(), &FatHeader, sizeof(MachO::fat_header));

  for (size_t Index = 0, Size = Slices.size(); Index < Size; ++Index) {
    MemoryBufferRef BufferRef = Slices[Index].getBinary()->getMemoryBufferRef();
    std::copy(BufferRef.getBufferStart(), BufferRef.getBufferEnd(),
              OutFile->getBufferStart() + FatArchList[Index].offset);
  }

  // FatArchs written after Slices in order to reduce the number of swaps for
  // the LittleEndian case
  if (sys::IsLittleEndianHost)
    for (MachO::fat_arch &FA : FatArchList)
      MachO::swapStruct(FA);
  std::memcpy(OutFile->getBufferStart() + sizeof(MachO::fat_header),
              FatArchList.begin(),
              sizeof(MachO::fat_arch) * FatArchList.size());

  if (Error E = OutFile->commit())
    reportError(OutputFileName, std::move(E));
}

LLVM_ATTRIBUTE_NORETURN
static void createUniversalBinary(ArrayRef<OwningBinary<Binary>> InputBinaries,
                                  const StringMap<const uint32_t> &Alignments,
                                  StringRef OutputFileName) {
  assert(InputBinaries.size() >= 1 && "Incorrect number of input binaries");
  assert(!OutputFileName.empty() && "Create expects a single output file");

  SmallVector<std::unique_ptr<MachOObjectFile>, 1> ExtractedObjects;
  SmallVector<Slice, 1> Slices =
      buildSlices(InputBinaries, Alignments, ExtractedObjects);
  checkArchDuplicates(Slices);
  checkUnusedAlignments(Slices, Alignments);
  createUniversalBinary(Slices, OutputFileName);

  exit(EXIT_SUCCESS);
}

static StringMap<Slice>
buildReplacementSlices(ArrayRef<OwningBinary<Binary>> ReplacementBinaries,
                       const StringMap<const uint32_t> &Alignments) {
  StringMap<Slice> Slices;
  // populates StringMap of slices to replace with; error checks for mismatched
  // replace flag args, fat files, and duplicate arch_types
  for (const auto &OB : ReplacementBinaries) {
    const Binary *ReplacementBinary = OB.getBinary();
    auto O = dyn_cast<MachOObjectFile>(ReplacementBinary);
    if (!O)
      reportError("replacement file: " + ReplacementBinary->getFileName() +
                  " is a fat file (must be a thin file)");
    Slice S(O);
    auto Entry = Slices.try_emplace(S.getArchString(), S);
    if (!Entry.second)
      reportError("-replace " + S.getArchString() +
                  " <file_name> specified multiple times: " +
                  Entry.first->second.getBinary()->getFileName() + ", " +
                  O->getFileName());
  }
  auto SlicesMapRange = map_range(
      Slices, [](StringMapEntry<Slice> &E) -> Slice & { return E.getValue(); });
  updateAlignments(SlicesMapRange, Alignments);
  return Slices;
}

LLVM_ATTRIBUTE_NORETURN
static void replaceSlices(ArrayRef<OwningBinary<Binary>> InputBinaries,
                          const StringMap<const uint32_t> &Alignments,
                          StringRef OutputFileName,
                          ArrayRef<InputFile> ReplacementFiles) {
  assert(InputBinaries.size() == 1 && "Incorrect number of input binaries");
  assert(!OutputFileName.empty() && "Replace expects a single output file");

  if (InputBinaries.front().getBinary()->isMachO())
    reportError("input file " +
                InputBinaries.front().getBinary()->getFileName() +
                " must be a fat file when the -replace option is specified");

  SmallVector<OwningBinary<Binary>, 1> ReplacementBinaries =
      readInputBinaries(ReplacementFiles);

  StringMap<Slice> ReplacementSlices =
      buildReplacementSlices(ReplacementBinaries, Alignments);
  SmallVector<std::unique_ptr<MachOObjectFile>, 2> ExtractedObjects;
  SmallVector<Slice, 2> Slices =
      buildSlices(InputBinaries, Alignments, ExtractedObjects);

  for (auto &Slice : Slices) {
    auto It = ReplacementSlices.find(Slice.getArchString());
    if (It != ReplacementSlices.end()) {
      Slice = It->second;
      ReplacementSlices.erase(It); // only keep remaining replacing arch_types
    }
  }

  if (!ReplacementSlices.empty())
    reportError("-replace " + ReplacementSlices.begin()->first() +
                " <file_name> specified but fat file: " +
                InputBinaries.front().getBinary()->getFileName() +
                " does not contain that architecture");

  checkUnusedAlignments(Slices, Alignments);
  createUniversalBinary(Slices, OutputFileName);
  exit(EXIT_SUCCESS);
}

int main(int argc, char **argv) {
  InitLLVM X(argc, argv);
  Config C = parseLipoOptions(makeArrayRef(argv + 1, argc));
  SmallVector<OwningBinary<Binary>, 1> InputBinaries =
      readInputBinaries(C.InputFiles);

  switch (C.ActionToPerform) {
  case LipoAction::VerifyArch:
    verifyArch(InputBinaries, C.VerifyArchList);
    break;
  case LipoAction::PrintArchs:
    printArchs(InputBinaries);
    break;
  case LipoAction::PrintInfo:
    printInfo(InputBinaries);
    break;
  case LipoAction::ThinArch:
    extractSlice(InputBinaries, C.ThinArchType, C.OutputFile);
    break;
  case LipoAction::CreateUniversal:
    createUniversalBinary(InputBinaries, C.SegmentAlignments, C.OutputFile);
    break;
  case LipoAction::ReplaceArch:
    replaceSlices(InputBinaries, C.SegmentAlignments, C.OutputFile,
                  C.ReplacementFiles);
    break;
  }
  return EXIT_SUCCESS;
}
