]> granicus.if.org Git - llvm/commitdiff
[llvm-lipo] Implement -archs
authorShoaib Meenai <smeenai@fb.com>
Fri, 7 Jun 2019 20:47:58 +0000 (20:47 +0000)
committerShoaib Meenai <smeenai@fb.com>
Fri, 7 Jun 2019 20:47:58 +0000 (20:47 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@362840 91177308-0d34-0410-b5e6-96231b3b80d8

test/tools/llvm-lipo/archs-macho-binary-unknown.test [new file with mode: 0644]
test/tools/llvm-lipo/archs-macho-binary.test [new file with mode: 0644]
test/tools/llvm-lipo/archs-universal-binary-arm.test [new file with mode: 0644]
test/tools/llvm-lipo/archs-universal-binary-unknown.test [new file with mode: 0644]
test/tools/llvm-lipo/archs-universal-binary-x86.test [new file with mode: 0644]
test/tools/llvm-lipo/help-error-messages.test [moved from test/tools/llvm-lipo/help-message.test with 76% similarity]
test/tools/llvm-lipo/verify-arch-universal-binary.test
tools/llvm-lipo/LipoOpts.td
tools/llvm-lipo/llvm-lipo.cpp

diff --git a/test/tools/llvm-lipo/archs-macho-binary-unknown.test b/test/tools/llvm-lipo/archs-macho-binary-unknown.test
new file mode 100644 (file)
index 0000000..ceda7d4
--- /dev/null
@@ -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/test/tools/llvm-lipo/archs-macho-binary.test b/test/tools/llvm-lipo/archs-macho-binary.test
new file mode 100644 (file)
index 0000000..56f9132
--- /dev/null
@@ -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/test/tools/llvm-lipo/archs-universal-binary-arm.test b/test/tools/llvm-lipo/archs-universal-binary-arm.test
new file mode 100644 (file)
index 0000000..81c1125
--- /dev/null
@@ -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/test/tools/llvm-lipo/archs-universal-binary-unknown.test b/test/tools/llvm-lipo/archs-universal-binary-unknown.test
new file mode 100644 (file)
index 0000000..353a95d
--- /dev/null
@@ -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/test/tools/llvm-lipo/archs-universal-binary-x86.test b/test/tools/llvm-lipo/archs-universal-binary-x86.test
new file mode 100644 (file)
index 0000000..e3b7af2
--- /dev/null
@@ -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
+...
similarity index 76%
rename from test/tools/llvm-lipo/help-message.test
rename to test/tools/llvm-lipo/help-error-messages.test
index 8a9d48b6cc2a5cdde03d5146bc372fe34446cb16..78453b2adbce72536b4e8a4378a57a60a19276d3 100644 (file)
@@ -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 }}
index 128813b6f76fa6174ab53769b6db33456a9a595e..21e9f92813b0e5a5078acdc8adf7cbef1edfc0e6 100644 (file)
@@ -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 @@ FatArchs:
     offset:          0x0000000000002000
     size:            32
     align:           12
-Slices:          
+Slices:
   - !mach-o
-    FileHeader:      
+    FileHeader:
       magic:           0xFEEDFACE
       cputype:         0x00000007
       cpusubtype:      0x00000003
@@ -32,7 +34,7 @@ Slices:
       sizeofcmds:      0
       flags:           0x00002000
   - !mach-o
-    FileHeader:      
+    FileHeader:
       magic:           0xFEEDFACF
       cputype:         0x01000007
       cpusubtype:      0x00000003
index 0ff667aafff6e8a4ba7ef379833ee8550b8ada7d..ba2e44f2bd3001f468df5161460e8ddaf17f3e51 100644 (file)
@@ -6,5 +6,14 @@ def h : Flag<["-"], "h">, Alias<help>;
 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">;
index a38d3ae7d0bf196123dfbc0f306a848525bbd9e1..3cd3ad53a6ff07096d56867d18abce70eb60a72d 100644 (file)
@@ -53,6 +53,8 @@ enum LipoID {
 #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 @@ public:
   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 @@ static Config parseLipoOptions(ArrayRef<const char *> ArgsArr) {
   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 @@ static Config parseLipoOptions(ArrayRef<const char *> ArgsArr) {
           "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 @@ readInputBinaries(ArrayRef<std::string> InputFiles) {
 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 @@ static void verifyArch(ArrayRef<OwningBinary<Binary>> InputBinaries,
   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;
 }