[llvm] b6d3774 - [llvm-lipo] Add support for -extract

Alexander Shaposhnikov via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 21 16:12:13 PST 2019


Author: Alexander Shaposhnikov
Date: 2019-11-21T16:11:48-08:00
New Revision: b6d3774a2721516399a10714519f22fb41bd0cd1

URL: https://github.com/llvm/llvm-project/commit/b6d3774a2721516399a10714519f22fb41bd0cd1
DIFF: https://github.com/llvm/llvm-project/commit/b6d3774a2721516399a10714519f22fb41bd0cd1.diff

LOG: [llvm-lipo] Add support for -extract

This diff adds support for -extract.

Test plan: make check-all

Differential revision: https://reviews.llvm.org/D70522

Added: 
    llvm/test/tools/llvm-lipo/extract.test

Modified: 
    llvm/tools/llvm-lipo/LipoOpts.td
    llvm/tools/llvm-lipo/llvm-lipo.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-lipo/extract.test b/llvm/test/tools/llvm-lipo/extract.test
new file mode 100644
index 000000000000..49f22f46f632
--- /dev/null
+++ b/llvm/test/tools/llvm-lipo/extract.test
@@ -0,0 +1,14 @@
+# RUN: yaml2obj %p/Inputs/i386-x86_64-universal.yaml > %t-universal.o
+
+# RUN: not llvm-lipo %t-universal.o -extract arm64_32 -output /dev/null 2>&1 | FileCheck --check-prefix=ARCH_NOT_IN_FILE %s
+# ARCH_NOT_IN_FILE: does not contain the specified architecture arm64_32
+
+# RUN: yaml2obj %p/Inputs/i386-slice.yaml > %t-i386.o
+# RUN: not llvm-lipo %t-i386.o -extract arm64_32 -output /dev/null 2>&1 | FileCheck --check-prefix=INPUT_NOT_A_FAT_FILE %s
+# INPUT_NOT_A_FAT_FILE: must be a fat file when the -extract option is specified
+
+# RUN: llvm-lipo -create %t-i386.o -output %t-i386-universal.o
+# RUN: llvm-lipo -extract i386 %t-universal.o -output %t-i386-universal-extracted.o
+# RUN: cmp %t-i386-universal.o %t-i386-universal-extracted.o
+# RUN: llvm-lipo -thin i386 %t-i386-universal-extracted.o -output %t-i386-thinned.o
+# RUN: cmp %t-i386.o %t-i386-thinned.o

diff  --git a/llvm/tools/llvm-lipo/LipoOpts.td b/llvm/tools/llvm-lipo/LipoOpts.td
index 344e407ca239..866353573cba 100644
--- a/llvm/tools/llvm-lipo/LipoOpts.td
+++ b/llvm/tools/llvm-lipo/LipoOpts.td
@@ -39,6 +39,11 @@ def thin : Option<["-", "--"], "thin", KIND_SEPARATE>,
            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 "

diff  --git a/llvm/tools/llvm-lipo/llvm-lipo.cpp b/llvm/tools/llvm-lipo/llvm-lipo.cpp
index a063fcec7574..a82030b13595 100644
--- a/llvm/tools/llvm-lipo/llvm-lipo.cpp
+++ b/llvm/tools/llvm-lipo/llvm-lipo.cpp
@@ -83,6 +83,7 @@ enum class LipoAction {
   PrintInfo,
   VerifyArch,
   ThinArch,
+  ExtractArch,
   CreateUniversal,
   ReplaceArch,
 };
@@ -97,7 +98,7 @@ struct Config {
   SmallVector<std::string, 1> VerifyArchList;
   SmallVector<InputFile, 1> ReplacementFiles;
   StringMap<const uint32_t> SegmentAlignments;
-  std::string ThinArchType;
+  std::string ArchType;
   std::string OutputFile;
   LipoAction ActionToPerform;
 };
@@ -391,14 +392,23 @@ static Config parseLipoOptions(ArrayRef<const char *> ArgsArr) {
   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.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");
@@ -544,9 +554,9 @@ static void printInfo(ArrayRef<OwningBinary<Binary>> InputBinaries) {
 }
 
 LLVM_ATTRIBUTE_NORETURN
-static void extractSlice(ArrayRef<OwningBinary<Binary>> InputBinaries,
-                         StringRef ThinArchType, StringRef OutputFileName) {
-  assert(!ThinArchType.empty() && "The architecture type should be non-empty");
+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");
 
@@ -559,11 +569,11 @@ static void extractSlice(ArrayRef<OwningBinary<Binary>> InputBinaries,
 
   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);
+      UO->getMachOObjectForArch(ArchType);
+  Expected<std::unique_ptr<Archive>> Ar = UO->getArchiveForArch(ArchType);
   if (!Obj && !Ar)
     reportError("fat input file " + UO->getFileName() +
-                " does not contain the specified architecture " + ThinArchType +
+                " does not contain the specified architecture " + ArchType +
                 " to thin it to");
   Binary *B = Obj ? static_cast<Binary *>(Obj->get())
                   : static_cast<Binary *>(Ar->get());
@@ -739,6 +749,37 @@ static void createUniversalBinary(ArrayRef<OwningBinary<Binary>> InputBinaries,
   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_FAILURE);
+  }
+
+  SmallVector<std::unique_ptr<MachOObjectFile>, 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);
+  createUniversalBinary(Slices, OutputFileName);
+  exit(EXIT_SUCCESS);
+}
+
 static StringMap<Slice>
 buildReplacementSlices(ArrayRef<OwningBinary<Binary>> ReplacementBinaries,
                        const StringMap<const uint32_t> &Alignments) {
@@ -823,7 +864,10 @@ int main(int argc, char **argv) {
     printInfo(InputBinaries);
     break;
   case LipoAction::ThinArch:
-    extractSlice(InputBinaries, C.ThinArchType, C.OutputFile);
+    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);


        


More information about the llvm-commits mailing list