1 | //===-- llvm-modextract.cpp - LLVM module extractor utility ---------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This program is for testing features that rely on multi-module bitcode files. |
10 | // It takes a multi-module bitcode file, extracts one of the modules and writes |
11 | // it to the output file. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #include "llvm/Bitcode/BitcodeReader.h" |
16 | #include "llvm/Bitcode/BitcodeWriter.h" |
17 | #include "llvm/Support/CommandLine.h" |
18 | #include "llvm/Support/Error.h" |
19 | #include "llvm/Support/FileSystem.h" |
20 | #include "llvm/Support/MemoryBuffer.h" |
21 | #include "llvm/Support/ToolOutputFile.h" |
22 | #include "llvm/Support/WithColor.h" |
23 | |
24 | using namespace llvm; |
25 | |
26 | static cl::OptionCategory ("Modextract Options" ); |
27 | |
28 | static cl::opt<bool> |
29 | ("b" , cl::desc("Whether to perform binary extraction" ), |
30 | cl::cat(ModextractCategory)); |
31 | |
32 | static cl::opt<std::string> OutputFilename("o" , cl::Required, |
33 | cl::desc("Output filename" ), |
34 | cl::value_desc("filename" ), |
35 | cl::cat(ModextractCategory)); |
36 | |
37 | static cl::opt<std::string> InputFilename(cl::Positional, |
38 | cl::desc("<input bitcode>" ), |
39 | cl::init(Val: "-" ), |
40 | cl::cat(ModextractCategory)); |
41 | |
42 | static cl::opt<unsigned> ModuleIndex("n" , cl::Required, |
43 | cl::desc("Index of module to extract" ), |
44 | cl::value_desc("index" ), |
45 | cl::cat(ModextractCategory)); |
46 | |
47 | int main(int argc, char **argv) { |
48 | cl::HideUnrelatedOptions(Categories: {&ModextractCategory, &getColorCategory()}); |
49 | cl::ParseCommandLineOptions(argc, argv, Overview: "Module extractor" ); |
50 | |
51 | ExitOnError ExitOnErr("llvm-modextract: error: " ); |
52 | |
53 | std::unique_ptr<MemoryBuffer> MB = |
54 | ExitOnErr(errorOrToExpected(EO: MemoryBuffer::getFileOrSTDIN(Filename: InputFilename))); |
55 | std::vector<BitcodeModule> Ms = ExitOnErr(getBitcodeModuleList(Buffer: *MB)); |
56 | |
57 | LLVMContext Context; |
58 | if (ModuleIndex >= Ms.size()) { |
59 | errs() << "llvm-modextract: error: module index out of range; bitcode file " |
60 | "contains " |
61 | << Ms.size() << " module(s)\n" ; |
62 | return 1; |
63 | } |
64 | |
65 | std::error_code EC; |
66 | std::unique_ptr<ToolOutputFile> Out( |
67 | new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None)); |
68 | ExitOnErr(errorCodeToError(EC)); |
69 | |
70 | if (BinaryExtract) { |
71 | SmallVector<char, 0> Result; |
72 | BitcodeWriter Writer(Result); |
73 | Result.append(in_start: Ms[ModuleIndex].getBuffer().begin(), |
74 | in_end: Ms[ModuleIndex].getBuffer().end()); |
75 | Writer.copyStrtab(Strtab: Ms[ModuleIndex].getStrtab()); |
76 | Out->os() << Result; |
77 | Out->keep(); |
78 | return 0; |
79 | } |
80 | |
81 | std::unique_ptr<Module> M = ExitOnErr(Ms[ModuleIndex].parseModule(Context)); |
82 | WriteBitcodeToFile(M: *M, Out&: Out->os()); |
83 | |
84 | Out->keep(); |
85 | return 0; |
86 | } |
87 | |