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