[llvm-lipo] Implement -archs
Displays the architecture names of an input file.
Unknown architectures are represented by unknown(cputype,cpusubtype).
Patch by Anusha Basana <anusha.basana@gmail.com>
Differential Revision: https://reviews.llvm.org/D62753
llvm-svn: 362840
diff --git a/llvm/test/tools/llvm-lipo/archs-macho-binary-unknown.test b/llvm/test/tools/llvm-lipo/archs-macho-binary-unknown.test
new file mode 100644
index 0000000..ceda7d4
--- /dev/null
+++ b/llvm/test/tools/llvm-lipo/archs-macho-binary-unknown.test
@@ -0,0 +1,15 @@
+# RUN: yaml2obj %s > %t
+# Tests that the output for an unknown architecture is the same as cctools lipo
+# RUN: llvm-lipo %t -archs | FileCheck %s
+# CHECK: unknown(151,3)
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACE
+ cputype: 0x00000097
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 0
+ sizeofcmds: 0
+ flags: 0x00002000
+...
diff --git a/llvm/test/tools/llvm-lipo/archs-macho-binary.test b/llvm/test/tools/llvm-lipo/archs-macho-binary.test
new file mode 100644
index 0000000..56f9132
--- /dev/null
+++ b/llvm/test/tools/llvm-lipo/archs-macho-binary.test
@@ -0,0 +1,19 @@
+# RUN: yaml2obj %s > %t
+
+# RUN: llvm-lipo %t -archs | FileCheck --check-prefix=ARCHS %s
+# RUN: llvm-lipo %t --archs | FileCheck --check-prefix=ARCHS %s
+# ARCHS: i386
+
+# RUN: not llvm-lipo %t %t -archs 2>&1 | FileCheck --check-prefix=MULTIPLE_INPUT_OBJ %s
+# MULTIPLE_INPUT_OBJ: archs expects a single input file
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACE
+ cputype: 0x00000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 0
+ sizeofcmds: 0
+ flags: 0x00002000
+...
diff --git a/llvm/test/tools/llvm-lipo/archs-universal-binary-arm.test b/llvm/test/tools/llvm-lipo/archs-universal-binary-arm.test
new file mode 100644
index 0000000..81c1125
--- /dev/null
+++ b/llvm/test/tools/llvm-lipo/archs-universal-binary-arm.test
@@ -0,0 +1,40 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-lipo %t -archs | FileCheck %s
+# CHECK: armv7k arm64
+
+--- !fat-mach-o
+FatHeader:
+ magic: 0xCAFEBABE
+ nfat_arch: 2
+FatArchs:
+ - cputype: 0x0000000C
+ cpusubtype: 0x0000000C
+ offset: 0x0000000000004000
+ size: 28
+ align: 14
+ - cputype: 0x0100000C
+ cpusubtype: 0x00000000
+ offset: 0x000000000001C000
+ size: 32
+ align: 14
+Slices:
+ - !mach-o
+ FileHeader:
+ magic: 0xFEEDFACE
+ cputype: 0x0000000C
+ cpusubtype: 0x0000000C
+ filetype: 0x00000002
+ ncmds: 0
+ sizeofcmds: 0
+ flags: 0x00200085
+ - !mach-o
+ FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x0100000C
+ cpusubtype: 0x00000000
+ filetype: 0x00000002
+ ncmds: 0
+ sizeofcmds: 0
+ flags: 0x00210085
+ reserved: 0x00000000
+...
diff --git a/llvm/test/tools/llvm-lipo/archs-universal-binary-unknown.test b/llvm/test/tools/llvm-lipo/archs-universal-binary-unknown.test
new file mode 100644
index 0000000..353a95d
--- /dev/null
+++ b/llvm/test/tools/llvm-lipo/archs-universal-binary-unknown.test
@@ -0,0 +1,41 @@
+# RUN: yaml2obj %s > %t
+# Tests that the output for an unknown architecture is the same as cctools lipo
+# RUN: llvm-lipo %t -archs 2>&1 | FileCheck %s
+# CHECK: i386 unknown(16777367,3)
+
+--- !fat-mach-o
+FatHeader:
+ magic: 0xCAFEBABE
+ nfat_arch: 2
+FatArchs:
+ - cputype: 0x00000007
+ cpusubtype: 0x00000003
+ offset: 0x0000000000001000
+ size: 28
+ align: 12
+ - cputype: 0x01000097
+ cpusubtype: 0x00000003
+ offset: 0x0000000000002000
+ size: 32
+ align: 12
+Slices:
+ - !mach-o
+ FileHeader:
+ magic: 0xFEEDFACE
+ cputype: 0x00000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 0
+ sizeofcmds: 0
+ flags: 0x00002000
+ - !mach-o
+ FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000097
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 0
+ sizeofcmds: 0
+ flags: 0x00002000
+ reserved: 0x00000000
+...
diff --git a/llvm/test/tools/llvm-lipo/archs-universal-binary-x86.test b/llvm/test/tools/llvm-lipo/archs-universal-binary-x86.test
new file mode 100644
index 0000000..e3b7af2
--- /dev/null
+++ b/llvm/test/tools/llvm-lipo/archs-universal-binary-x86.test
@@ -0,0 +1,40 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-lipo %t -archs | FileCheck %s
+# CHECK: i386 x86_64
+
+--- !fat-mach-o
+FatHeader:
+ magic: 0xCAFEBABE
+ nfat_arch: 2
+FatArchs:
+ - cputype: 0x00000007
+ cpusubtype: 0x00000003
+ offset: 0x0000000000001000
+ size: 28
+ align: 12
+ - cputype: 0x01000007
+ cpusubtype: 0x00000003
+ offset: 0x0000000000002000
+ size: 32
+ align: 12
+Slices:
+ - !mach-o
+ FileHeader:
+ magic: 0xFEEDFACE
+ cputype: 0x00000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 0
+ sizeofcmds: 0
+ flags: 0x00002000
+ - !mach-o
+ FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 0
+ sizeofcmds: 0
+ flags: 0x00002000
+ reserved: 0x00000000
+...
diff --git a/llvm/test/tools/llvm-lipo/help-message.test b/llvm/test/tools/llvm-lipo/help-error-messages.test
similarity index 76%
rename from llvm/test/tools/llvm-lipo/help-message.test
rename to llvm/test/tools/llvm-lipo/help-error-messages.test
index 8a9d48b6..78453b2 100644
--- a/llvm/test/tools/llvm-lipo/help-message.test
+++ b/llvm/test/tools/llvm-lipo/help-error-messages.test
@@ -8,6 +8,9 @@
# RUN: not llvm-lipo -abcabc 2>&1 | FileCheck --check-prefix=LIPO-UNKNOWN-ARG %s
# RUN: not llvm-lipo --abcabc 2>&1 | FileCheck --check-prefix=LIPO-UNKNOWN-ARG %s
+# RUN: not llvm-lipo %t -archs -verify_arch i386 2>&1 | FileCheck --check-prefix=MULTIPLE_FLAGS %s
+# MULTIPLE_FLAGS: only one of the following actions can be specified: -archs -verify_arch
+
# LIPO-USAGE: USAGE: llvm-lipo
# LIPO-UNKNOWN-ARG: unknown argument '{{-+}}abcabc'
# LIPO-VERSION: {{ version }}
diff --git a/llvm/test/tools/llvm-lipo/verify-arch-universal-binary.test b/llvm/test/tools/llvm-lipo/verify-arch-universal-binary.test
index 128813b..21e9f92 100644
--- a/llvm/test/tools/llvm-lipo/verify-arch-universal-binary.test
+++ b/llvm/test/tools/llvm-lipo/verify-arch-universal-binary.test
@@ -4,13 +4,15 @@
# RUN: llvm-lipo %t -verify_arch i386 x86_64
# RUN: not llvm-lipo %t -verify_arch aarch64
-# RUN: not llvm-lipo %t -verify_arch aarch64 i386
+# RUN: yaml2obj %s | not llvm-lipo - -verify_arch aarch64 i386
+# lipo does not support this (i.e. yaml2obj %s | not lipo -), included to test function with llvm-lipo
+# use the temporary %t when checking tests with lipo
--- !fat-mach-o
-FatHeader:
+FatHeader:
magic: 0xCAFEBABE
nfat_arch: 2
-FatArchs:
+FatArchs:
- cputype: 0x00000007
cpusubtype: 0x00000003
offset: 0x0000000000001000
@@ -21,9 +23,9 @@
offset: 0x0000000000002000
size: 32
align: 12
-Slices:
+Slices:
- !mach-o
- FileHeader:
+ FileHeader:
magic: 0xFEEDFACE
cputype: 0x00000007
cpusubtype: 0x00000003
@@ -32,7 +34,7 @@
sizeofcmds: 0
flags: 0x00002000
- !mach-o
- FileHeader:
+ FileHeader:
magic: 0xFEEDFACF
cputype: 0x01000007
cpusubtype: 0x00000003
diff --git a/llvm/tools/llvm-lipo/LipoOpts.td b/llvm/tools/llvm-lipo/LipoOpts.td
index 0ff667a..ba2e44f 100644
--- a/llvm/tools/llvm-lipo/LipoOpts.td
+++ b/llvm/tools/llvm-lipo/LipoOpts.td
@@ -6,5 +6,14 @@
def version : Flag<["-", "--"], "version">,
HelpText<"Print the version and exit.">;
-def verify_arch : Option<["-", "--"], "verify_arch", KIND_REMAINING_ARGS>,
- HelpText<"Verify that the specified arch_types are present in the 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">;
diff --git a/llvm/tools/llvm-lipo/llvm-lipo.cpp b/llvm/tools/llvm-lipo/llvm-lipo.cpp
index a38d3ae..3cd3ad5 100644
--- a/llvm/tools/llvm-lipo/llvm-lipo.cpp
+++ b/llvm/tools/llvm-lipo/llvm-lipo.cpp
@@ -53,6 +53,8 @@
#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
@@ -73,9 +75,15 @@
LipoOptTable() : OptTable(LipoInfoTable) {}
};
+enum class LipoAction {
+ PrintArchs,
+ VerifyArch,
+};
+
struct Config {
SmallVector<std::string, 1> InputFiles;
SmallVector<std::string, 1> VerifyArchList;
+ LipoAction ActionToPerform;
};
} // end namespace
@@ -113,7 +121,20 @@
if (C.InputFiles.empty())
reportError("at least one input file should be specified");
- if (InputArgs.hasArg(LIPO_verify_arch)) {
+ SmallVector<opt::Arg *, 1> ActionArgs(InputArgs.filtered(LIPO_action_group));
+ if (ActionArgs.empty())
+ reportError("at least one action should be specified");
+ if (ActionArgs.size() > 1) {
+ 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())
@@ -121,8 +142,18 @@
"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;
+
+ default:
+ reportError("llvm-lipo action unspecified");
}
- return C;
}
static SmallVector<OwningBinary<Binary>, 1>
@@ -144,8 +175,6 @@
LLVM_ATTRIBUTE_NORETURN
static void verifyArch(ArrayRef<OwningBinary<Binary>> InputBinaries,
ArrayRef<std::string> VerifyArchList) {
- assert(!InputBinaries.empty() &&
- "The list of input binaries should be non-empty");
assert(!VerifyArchList.empty() &&
"The list of architectures should be non-empty");
assert(InputBinaries.size() == 1 && "Incorrect number of input binaries");
@@ -174,12 +203,55 @@
exit(EXIT_SUCCESS);
}
+static void printArchOrUnknown(const MachOObjectFile *ObjectFile) {
+ // Prints trailing space and unknown in this format for compatibility with
+ // cctools lipo.
+ const std::string ObjectArch = ObjectFile->getArchTriple().getArchName();
+ if (ObjectArch.empty()) {
+ outs() << "unknown(" << ObjectFile->getHeader().cputype << ","
+ << ObjectFile->getHeader().cpusubtype << ") ";
+ } else {
+ outs() << ObjectArch + " ";
+ }
+}
+
+LLVM_ATTRIBUTE_NORETURN
+static void printArchs(ArrayRef<OwningBinary<Binary>> InputBinaries) {
+ assert(InputBinaries.size() == 1 && "Incorrect number of input binaries");
+ const Binary *InputBinary = InputBinaries.front().getBinary();
+ if (auto UO = dyn_cast<MachOUniversalBinary>(InputBinary)) {
+ for (MachOUniversalBinary::object_iterator I = UO->begin_objects(),
+ E = UO->end_objects();
+ I != E; ++I) {
+ Expected<std::unique_ptr<MachOObjectFile>> BinaryOrError =
+ I->getAsObjectFile();
+ if (!BinaryOrError)
+ reportError(InputBinary->getFileName(), BinaryOrError.takeError());
+ printArchOrUnknown(BinaryOrError.get().get());
+ }
+ } else if (auto O = dyn_cast<MachOObjectFile>(InputBinary)) {
+ printArchOrUnknown(O);
+ } else {
+ llvm_unreachable("Unexpected binary format");
+ }
+
+ outs() << "\n";
+ 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);
- if (!C.VerifyArchList.empty())
+
+ switch (C.ActionToPerform) {
+ case LipoAction::VerifyArch:
verifyArch(InputBinaries, C.VerifyArchList);
+ break;
+ case LipoAction::PrintArchs:
+ printArchs(InputBinaries);
+ break;
+ }
return EXIT_SUCCESS;
}