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