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
24using namespace llvm;
25
26static cl::OptionCategory ModextractCategory("Modextract Options");
27
28static cl::opt<bool>
29 BinaryExtract("b", cl::desc("Whether to perform binary extraction"),
30 cl::cat(ModextractCategory));
31
32static cl::opt<std::string> OutputFilename("o", cl::Required,
33 cl::desc("Output filename"),
34 cl::value_desc("filename"),
35 cl::cat(ModextractCategory));
36
37static cl::opt<std::string> InputFilename(cl::Positional,
38 cl::desc("<input bitcode>"),
39 cl::init(Val: "-"),
40 cl::cat(ModextractCategory));
41
42static 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
47int main(int argc, char **argv) {
48 cl::HideUnrelatedOptions(Categories: {&ModextractCategory, &getColorCategory()});
49 LLVMContext Context;
50 cl::parseCommandLineOptions(Context&: Context.getLibraryOptions(), Args: ArrayRef(argv, argc),
51 Overview: "Module extractor");
52
53 ExitOnError ExitOnErr("llvm-modextract: error: ");
54
55 std::unique_ptr<MemoryBuffer> MB =
56 ExitOnErr(errorOrToExpected(EO: MemoryBuffer::getFileOrSTDIN(Filename: InputFilename)));
57 std::vector<BitcodeModule> Ms = ExitOnErr(getBitcodeModuleList(Buffer: *MB));
58
59 if (ModuleIndex >= Ms.size()) {
60 errs() << "llvm-modextract: error: module index out of range; bitcode file "
61 "contains "
62 << Ms.size() << " module(s)\n";
63 return 1;
64 }
65
66 std::error_code EC;
67 std::unique_ptr<ToolOutputFile> Out(
68 new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None));
69 ExitOnErr(errorCodeToError(EC));
70
71 if (BinaryExtract) {
72 SmallVector<char, 0> Result;
73 BitcodeWriter Writer(Result);
74 Result.append(in_start: Ms[ModuleIndex].getBuffer().begin(),
75 in_end: Ms[ModuleIndex].getBuffer().end());
76 Writer.copyStrtab(Strtab: Ms[ModuleIndex].getStrtab());
77 Out->os() << Result;
78 Out->keep();
79 return 0;
80 }
81
82 std::unique_ptr<Module> M = ExitOnErr(Ms[ModuleIndex].parseModule(Context));
83 WriteBitcodeToFile(M: *M, Out&: Out->os());
84
85 Out->keep();
86 return 0;
87}
88