[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