diff options
author | orivej <orivej@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
commit | 718c552901d703c502ccbefdfc3c9028d608b947 (patch) | |
tree | 46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/libs/llvm12/tools/llvm-lipo | |
parent | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff) | |
download | ydb-718c552901d703c502ccbefdfc3c9028d608b947.tar.gz |
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/llvm12/tools/llvm-lipo')
-rw-r--r-- | contrib/libs/llvm12/tools/llvm-lipo/LipoOpts.td | 120 | ||||
-rw-r--r-- | contrib/libs/llvm12/tools/llvm-lipo/llvm-lipo.cpp | 1252 | ||||
-rw-r--r-- | contrib/libs/llvm12/tools/llvm-lipo/ya.make | 42 |
3 files changed, 707 insertions, 707 deletions
diff --git a/contrib/libs/llvm12/tools/llvm-lipo/LipoOpts.td b/contrib/libs/llvm12/tools/llvm-lipo/LipoOpts.td index 866353573c..f1a8d1140b 100644 --- a/contrib/libs/llvm12/tools/llvm-lipo/LipoOpts.td +++ b/contrib/libs/llvm12/tools/llvm-lipo/LipoOpts.td @@ -1,60 +1,60 @@ -include "llvm/Option/OptParser.td" - -def help : Flag<["-", "--"], "help">; -def h : Flag<["-"], "h">, Alias<help>; - -def version : Flag<["-", "--"], "version">, - HelpText<"Print the version and exit.">; - -def segalign - : MultiArg<["-", "--"], "segalign", 2>, - HelpText<"Specifies the segment alignment for the specified " - "architecture when creating a universal binary file. The " - "alignment is a hexadecimal number that is a power of 2.">; - -def arch - : MultiArg<["-", "--"], "arch", 2>, - HelpText<"Specifies the architecture and the corresponding input file">; - -def action_group : OptionGroup<"action group">; - -def verify_arch - : Option<["-", "--"], "verify_arch", KIND_REMAINING_ARGS>, - Group<action_group>, - HelpText< - "Verify that the specified arch_types are present in the input file">; - -def archs : Option<["-", "--"], "archs", KIND_FLAG>, - Group<action_group>, - HelpText<"Display the arch_types present in the input file">; - -def info : Option<["-", "--"], "info", KIND_FLAG>, - Group<action_group>, - HelpText<"Display descriptions of each input file including " - "filename and arch_types. Groups universal binaries " - "together followed by thin files">; - -def thin : Option<["-", "--"], "thin", KIND_SEPARATE>, - Group<action_group>, - HelpText<"Create a thin output file of specified arch_type from the " - "fat input file. Requires -output option">; - -def extract : Option<["-", "--"], "extract", KIND_SEPARATE>, - Group<action_group>, - HelpText<"Create a universal output file containing only the specified " - "arch_type from the fat input file. Requires -output option">; - -def create : Option<["-", "--"], "create", KIND_FLAG>, - Group<action_group>, - HelpText<"Create a universal binary output file from the input " - "files. Requires -output option">; - -def replace - : MultiArg<["-", "--"], "replace", 2>, - Group<action_group>, - HelpText<"Replace the specified arch type with the contents of the " - "input_file in a universal binary. Requires -output option">; - -def output : Option<["-", "--"], "output", KIND_SEPARATE>, - HelpText<"Create output file with specified name">; -def o : JoinedOrSeparate<["-"], "o">, Alias<output>; +include "llvm/Option/OptParser.td" + +def help : Flag<["-", "--"], "help">; +def h : Flag<["-"], "h">, Alias<help>; + +def version : Flag<["-", "--"], "version">, + HelpText<"Print the version and exit.">; + +def segalign + : MultiArg<["-", "--"], "segalign", 2>, + HelpText<"Specifies the segment alignment for the specified " + "architecture when creating a universal binary file. The " + "alignment is a hexadecimal number that is a power of 2.">; + +def arch + : MultiArg<["-", "--"], "arch", 2>, + HelpText<"Specifies the architecture and the corresponding input file">; + +def action_group : OptionGroup<"action group">; + +def verify_arch + : Option<["-", "--"], "verify_arch", KIND_REMAINING_ARGS>, + Group<action_group>, + HelpText< + "Verify that the specified arch_types are present in the input file">; + +def archs : Option<["-", "--"], "archs", KIND_FLAG>, + Group<action_group>, + HelpText<"Display the arch_types present in the input file">; + +def info : Option<["-", "--"], "info", KIND_FLAG>, + Group<action_group>, + HelpText<"Display descriptions of each input file including " + "filename and arch_types. Groups universal binaries " + "together followed by thin files">; + +def thin : Option<["-", "--"], "thin", KIND_SEPARATE>, + Group<action_group>, + HelpText<"Create a thin output file of specified arch_type from the " + "fat input file. Requires -output option">; + +def extract : Option<["-", "--"], "extract", KIND_SEPARATE>, + Group<action_group>, + HelpText<"Create a universal output file containing only the specified " + "arch_type from the fat input file. Requires -output option">; + +def create : Option<["-", "--"], "create", KIND_FLAG>, + Group<action_group>, + HelpText<"Create a universal binary output file from the input " + "files. Requires -output option">; + +def replace + : MultiArg<["-", "--"], "replace", 2>, + Group<action_group>, + HelpText<"Replace the specified arch type with the contents of the " + "input_file in a universal binary. Requires -output option">; + +def output : Option<["-", "--"], "output", KIND_SEPARATE>, + HelpText<"Create output file with specified name">; +def o : JoinedOrSeparate<["-"], "o">, Alias<output>; diff --git a/contrib/libs/llvm12/tools/llvm-lipo/llvm-lipo.cpp b/contrib/libs/llvm12/tools/llvm-lipo/llvm-lipo.cpp index 7fbe489ecc..e1881745b1 100644 --- a/contrib/libs/llvm12/tools/llvm-lipo/llvm-lipo.cpp +++ b/contrib/libs/llvm12/tools/llvm-lipo/llvm-lipo.cpp @@ -1,47 +1,47 @@ -//===-- 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" +//===-- 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/BinaryFormat/MachO.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" -#include "llvm/Object/Binary.h" +#include "llvm/Object/Binary.h" #include "llvm/Object/IRObjectFile.h" -#include "llvm/Object/MachO.h" -#include "llvm/Object/MachOUniversal.h" +#include "llvm/Object/MachO.h" +#include "llvm/Object/MachOUniversal.h" #include "llvm/Object/MachOUniversalWriter.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"; +#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"; static LLVMContext LLVMCtx; - -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(Twine Message) { + WithColor::error(errs(), ToolName) << Message << "\n"; + errs().flush(); + exit(EXIT_FAILURE); +} + LLVM_ATTRIBUTE_NORETURN static void reportError(Error E) { assert(E); std::string Buf; @@ -51,347 +51,347 @@ LLVM_ATTRIBUTE_NORETURN static void reportError(Error E) { reportError(Buf); } -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, - ExtractArch, - 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 ArchType; - std::string OutputFile; - LipoAction ActionToPerform; -}; - +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, + ExtractArch, + 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 ArchType; + std::string OutputFile; + LipoAction ActionToPerform; +}; + static Slice createSliceFromArchive(const Archive &A) { Expected<Slice> ArchiveOrSlice = Slice::create(A, &LLVMCtx); if (!ArchiveOrSlice) reportError(A.getFileName(), ArchiveOrSlice.takeError()); return *ArchiveOrSlice; -} - +} + static Slice createSliceFromIR(const IRObjectFile &IRO, unsigned Align) { Expected<Slice> IROrErr = Slice::create(IRO, Align); if (!IROrErr) reportError(IRO.getFileName(), IROrErr.takeError()); return *IROrErr; -} - -} // 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 = std::string(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"); - if (C.OutputFile.empty()) - reportError("thin expects a single output file"); - C.ArchType = ActionArgs[0]->getValue(); - validateArchitectureName(C.ArchType); - C.ActionToPerform = LipoAction::ThinArch; - return C; - - case LIPO_extract: - if (C.InputFiles.size() > 1) - reportError("extract expects a single input file"); - if (C.OutputFile.empty()) - reportError("extract expects a single output file"); - C.ArchType = ActionArgs[0]->getValue(); - validateArchitectureName(C.ArchType); - C.ActionToPerform = LipoAction::ExtractArch; - 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) { +} + +} // 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 = std::string(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"); + if (C.OutputFile.empty()) + reportError("thin expects a single output file"); + C.ArchType = ActionArgs[0]->getValue(); + validateArchitectureName(C.ArchType); + C.ActionToPerform = LipoAction::ThinArch; + return C; + + case LIPO_extract: + if (C.InputFiles.size() > 1) + reportError("extract expects a single input file"); + if (C.OutputFile.empty()) + reportError("extract expects a single output file"); + C.ArchType = ActionArgs[0]->getValue(); + validateArchitectureName(C.ArchType); + C.ActionToPerform = LipoAction::ExtractArch; + 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, &LLVMCtx); - if (!BinaryOrErr) - reportError(IF.FileName, BinaryOrErr.takeError()); - const Binary *B = BinaryOrErr->getBinary(); + if (!BinaryOrErr) + reportError(IF.FileName, BinaryOrErr.takeError()); + const Binary *B = BinaryOrErr->getBinary(); if (!B->isArchive() && !B->isMachO() && !B->isMachOUniversalBinary() && !B->isIR()) - reportError("File " + IF.FileName + " has unsupported binary format"); + reportError("File " + IF.FileName + " has unsupported binary format"); if (IF.ArchType && (B->isMachO() || B->isArchive() || B->isIR())) { const auto S = B->isMachO() ? Slice(*cast<MachOObjectFile>(B)) : B->isArchive() ? createSliceFromArchive(*cast<Archive>(B)) : createSliceFromIR(*cast<IRObjectFile>(B), 0); - 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()) { + 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()) { // Order here is important, because both MachOObjectFile and // IRObjectFile can be created with a binary that has embedded bitcode. - Expected<std::unique_ptr<MachOObjectFile>> MachOObjOrError = - O.getAsObjectFile(); - if (MachOObjOrError) { + Expected<std::unique_ptr<MachOObjectFile>> MachOObjOrError = + O.getAsObjectFile(); + if (MachOObjOrError) { OS << Slice(*(MachOObjOrError->get())).getArchString() << " "; - continue; - } + continue; + } Expected<std::unique_ptr<IRObjectFile>> IROrError = O.getAsIRObject(LLVMCtx); if (IROrError) { @@ -404,20 +404,20 @@ static void printBinaryArchs(const Binary *Binary, raw_ostream &OS) { OS << SliceOrErr.get().getArchString() << " "; continue; } - Expected<std::unique_ptr<Archive>> ArchiveOrError = O.getAsArchive(); - if (ArchiveOrError) { - consumeError(MachOObjOrError.takeError()); + Expected<std::unique_ptr<Archive>> ArchiveOrError = O.getAsArchive(); + if (ArchiveOrError) { + consumeError(MachOObjOrError.takeError()); consumeError(IROrError.takeError()); OS << createSliceFromArchive(**ArchiveOrError).getArchString() << " "; - continue; - } - consumeError(ArchiveOrError.takeError()); - reportError(Binary->getFileName(), MachOObjOrError.takeError()); + continue; + } + consumeError(ArchiveOrError.takeError()); + reportError(Binary->getFileName(), MachOObjOrError.takeError()); reportError(Binary->getFileName(), IROrError.takeError()); - } - OS << "\n"; - return; - } + } + OS << "\n"; + return; + } if (const auto *MachO = dyn_cast<MachOObjectFile>(Binary)) { OS << Slice(*MachO).getArchString() << " \n"; @@ -431,62 +431,62 @@ static void printBinaryArchs(const Binary *Binary, raw_ostream &OS) { reportError(IR->getFileName(), SliceOrErr.takeError()); OS << SliceOrErr->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 thinSlice(ArrayRef<OwningBinary<Binary>> InputBinaries, - StringRef ArchType, StringRef OutputFileName) { - assert(!ArchType.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(ArchType); +} + +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 thinSlice(ArrayRef<OwningBinary<Binary>> InputBinaries, + StringRef ArchType, StringRef OutputFileName) { + assert(!ArchType.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(ArchType); Expected<std::unique_ptr<IRObjectFile>> IRObj = UO->getIRObjectForArch(ArchType, LLVMCtx); - Expected<std::unique_ptr<Archive>> Ar = UO->getArchiveForArch(ArchType); + Expected<std::unique_ptr<Archive>> Ar = UO->getArchiveForArch(ArchType); if (!Obj && !IRObj && !Ar) - reportError("fat input file " + UO->getFileName() + - " does not contain the specified architecture " + ArchType + - " to thin it to"); + reportError("fat input file " + UO->getFileName() + + " does not contain the specified architecture " + ArchType + + " to thin it to"); Binary *B; // Order here is important, because both Obj and IRObj will be valid with a // binary that has embedded bitcode. @@ -497,72 +497,72 @@ static void thinSlice(ArrayRef<OwningBinary<Binary>> InputBinaries, else B = 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) { + 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::any_of(Slices, [Arch](Slice S) { return S.getArchString() == Arch; }); - }; - 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. + }; + 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<SymbolicFile>> &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()) { + 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()) { // Order here is important, because both MachOObjectFile and // IRObjectFile can be created with a binary that has embedded bitcode. - Expected<std::unique_ptr<MachOObjectFile>> BinaryOrError = - O.getAsObjectFile(); + Expected<std::unique_ptr<MachOObjectFile>> BinaryOrError = + O.getAsObjectFile(); if (BinaryOrError) { Slices.emplace_back(*(BinaryOrError.get()), O.getAlign()); ExtractedObjects.push_back(std::move(BinaryOrError.get())); @@ -578,7 +578,7 @@ buildSlices(ArrayRef<OwningBinary<Binary>> InputBinaries, continue; } reportError(InputBinary->getFileName(), BinaryOrError.takeError()); - } + } } else if (const auto *O = dyn_cast<MachOObjectFile>(InputBinary)) { Slices.emplace_back(*O); } else if (const auto *A = dyn_cast<Archive>(InputBinary)) { @@ -591,166 +591,166 @@ buildSlices(ArrayRef<OwningBinary<Binary>> InputBinaries, continue; } Slices.emplace_back(std::move(SliceOrErr.get())); - } else { - llvm_unreachable("Unexpected binary format"); - } - } - updateAlignments(Slices, Alignments); - return Slices; -} - -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"); - + } else { + llvm_unreachable("Unexpected binary format"); + } + } + updateAlignments(Slices, Alignments); + return Slices; +} + +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<SymbolicFile>, 1> ExtractedObjects; - SmallVector<Slice, 1> Slices = - buildSlices(InputBinaries, Alignments, ExtractedObjects); - checkArchDuplicates(Slices); - checkUnusedAlignments(Slices, Alignments); - + SmallVector<Slice, 1> Slices = + buildSlices(InputBinaries, Alignments, ExtractedObjects); + checkArchDuplicates(Slices); + checkUnusedAlignments(Slices, Alignments); + llvm::stable_sort(Slices); if (Error E = writeUniversalBinary(Slices, OutputFileName)) reportError(std::move(E)); - exit(EXIT_SUCCESS); -} - -LLVM_ATTRIBUTE_NORETURN -static void extractSlice(ArrayRef<OwningBinary<Binary>> InputBinaries, - const StringMap<const uint32_t> &Alignments, - StringRef ArchType, StringRef OutputFileName) { - assert(!ArchType.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 -extract option is specified"); - } - + exit(EXIT_SUCCESS); +} + +LLVM_ATTRIBUTE_NORETURN +static void extractSlice(ArrayRef<OwningBinary<Binary>> InputBinaries, + const StringMap<const uint32_t> &Alignments, + StringRef ArchType, StringRef OutputFileName) { + assert(!ArchType.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 -extract option is specified"); + } + SmallVector<std::unique_ptr<SymbolicFile>, 2> ExtractedObjects; - SmallVector<Slice, 2> Slices = - buildSlices(InputBinaries, Alignments, ExtractedObjects); - erase_if(Slices, [ArchType](const Slice &S) { - return ArchType != S.getArchString(); - }); - - if (Slices.empty()) - reportError( - "fat input file " + InputBinaries.front().getBinary()->getFileName() + - " does not contain the specified architecture " + ArchType); + SmallVector<Slice, 2> Slices = + buildSlices(InputBinaries, Alignments, ExtractedObjects); + erase_if(Slices, [ArchType](const Slice &S) { + return ArchType != S.getArchString(); + }); + + if (Slices.empty()) + reportError( + "fat input file " + InputBinaries.front().getBinary()->getFileName() + + " does not contain the specified architecture " + ArchType); llvm::stable_sort(Slices); if (Error E = writeUniversalBinary(Slices, OutputFileName)) reportError(std::move(E)); - 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)"); + 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); + 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<SymbolicFile>, 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); + 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); llvm::stable_sort(Slices); if (Error E = writeUniversalBinary(Slices, OutputFileName)) reportError(std::move(E)); - 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: - thinSlice(InputBinaries, C.ArchType, C.OutputFile); - break; - case LipoAction::ExtractArch: - extractSlice(InputBinaries, C.SegmentAlignments, C.ArchType, 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; -} + 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: + thinSlice(InputBinaries, C.ArchType, C.OutputFile); + break; + case LipoAction::ExtractArch: + extractSlice(InputBinaries, C.SegmentAlignments, C.ArchType, 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; +} diff --git a/contrib/libs/llvm12/tools/llvm-lipo/ya.make b/contrib/libs/llvm12/tools/llvm-lipo/ya.make index afb28b31ce..157bfe611e 100644 --- a/contrib/libs/llvm12/tools/llvm-lipo/ya.make +++ b/contrib/libs/llvm12/tools/llvm-lipo/ya.make @@ -1,17 +1,17 @@ -# Generated by devtools/yamaker. - -PROGRAM() - +# Generated by devtools/yamaker. + +PROGRAM() + OWNER( orivej g:cpp-contrib ) - + LICENSE(Apache-2.0 WITH LLVM-exception) - + LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -PEERDIR( +PEERDIR( contrib/libs/llvm12 contrib/libs/llvm12/include contrib/libs/llvm12/lib/BinaryFormat @@ -56,19 +56,19 @@ PEERDIR( contrib/libs/llvm12/lib/Target/X86/MCTargetDesc contrib/libs/llvm12/lib/Target/X86/TargetInfo contrib/libs/llvm12/lib/TextAPI/MachO -) - -ADDINCL( +) + +ADDINCL( ${ARCADIA_BUILD_ROOT}/contrib/libs/llvm12/tools/llvm-lipo contrib/libs/llvm12/tools/llvm-lipo -) - -NO_COMPILER_WARNINGS() - -NO_UTIL() - -SRCS( - llvm-lipo.cpp -) - -END() +) + +NO_COMPILER_WARNINGS() + +NO_UTIL() + +SRCS( + llvm-lipo.cpp +) + +END() |