10b57cec5SDimitry Andric //===-- llvm-bcanalyzer.cpp - Bitcode Analyzer --------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This tool may be invoked in the following manner:
100b57cec5SDimitry Andric // llvm-bcanalyzer [options] - Read LLVM bitcode from stdin
110b57cec5SDimitry Andric // llvm-bcanalyzer [options] x.bc - Read LLVM bitcode from the x.bc file
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric // Options:
140b57cec5SDimitry Andric // --help - Output information about command line switches
150b57cec5SDimitry Andric // --dump - Dump low-level bitcode structure in readable format
16349cc55cSDimitry Andric // --dump-blockinfo - Dump the BLOCKINFO_BLOCK, when used with --dump
170b57cec5SDimitry Andric //
180b57cec5SDimitry Andric // This tool provides analytical information about a bitcode file. It is
190b57cec5SDimitry Andric // intended as an aid to developers of bitcode reading and writing software. It
200b57cec5SDimitry Andric // produces on std::out a summary of the bitcode file that shows various
210b57cec5SDimitry Andric // statistics about the contents of the file. By default this information is
220b57cec5SDimitry Andric // detailed and contains information about individual bitcode blocks and the
230b57cec5SDimitry Andric // functions in the module.
240b57cec5SDimitry Andric // The tool is also able to print a bitcode file in a straight forward text
250b57cec5SDimitry Andric // format that shows the containment and relationships of the information in
260b57cec5SDimitry Andric // the bitcode file (-dump option).
270b57cec5SDimitry Andric //
280b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric #include "llvm/Bitcode/BitcodeAnalyzer.h"
310b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
320b57cec5SDimitry Andric #include "llvm/Support/Error.h"
330b57cec5SDimitry Andric #include "llvm/Support/InitLLVM.h"
340b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
35fe6060f1SDimitry Andric #include "llvm/Support/WithColor.h"
360b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
370b57cec5SDimitry Andric #include <memory>
38*bdd1243dSDimitry Andric #include <optional>
390b57cec5SDimitry Andric using namespace llvm;
400b57cec5SDimitry Andric
41fe6060f1SDimitry Andric static cl::OptionCategory BCAnalyzerCategory("BC Analyzer Options");
420b57cec5SDimitry Andric
43fe6060f1SDimitry Andric static cl::opt<std::string> InputFilename(cl::Positional,
44fe6060f1SDimitry Andric cl::desc("<input bitcode>"),
45fe6060f1SDimitry Andric cl::init("-"),
46fe6060f1SDimitry Andric cl::cat(BCAnalyzerCategory));
47fe6060f1SDimitry Andric
48fe6060f1SDimitry Andric static cl::opt<bool> Dump("dump", cl::desc("Dump low level bitcode trace"),
49fe6060f1SDimitry Andric cl::cat(BCAnalyzerCategory));
500b57cec5SDimitry Andric
51349cc55cSDimitry Andric static cl::opt<bool> DumpBlockinfo("dump-blockinfo",
52349cc55cSDimitry Andric cl::desc("Include BLOCKINFO details in low"
53349cc55cSDimitry Andric " level dump"),
54349cc55cSDimitry Andric cl::cat(BCAnalyzerCategory));
55349cc55cSDimitry Andric
560b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
570b57cec5SDimitry Andric // Bitcode specific analysis.
580b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
590b57cec5SDimitry Andric
600b57cec5SDimitry Andric static cl::opt<bool> NoHistogram("disable-histogram",
61fe6060f1SDimitry Andric cl::desc("Do not print per-code histogram"),
62fe6060f1SDimitry Andric cl::cat(BCAnalyzerCategory));
630b57cec5SDimitry Andric
640b57cec5SDimitry Andric static cl::opt<bool> NonSymbolic("non-symbolic",
650b57cec5SDimitry Andric cl::desc("Emit numeric info in dump even if"
66fe6060f1SDimitry Andric " symbolic info is available"),
67fe6060f1SDimitry Andric cl::cat(BCAnalyzerCategory));
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric static cl::opt<std::string>
700b57cec5SDimitry Andric BlockInfoFilename("block-info",
71fe6060f1SDimitry Andric cl::desc("Use the BLOCK_INFO from the given file"),
72fe6060f1SDimitry Andric cl::cat(BCAnalyzerCategory));
730b57cec5SDimitry Andric
740b57cec5SDimitry Andric static cl::opt<bool>
750b57cec5SDimitry Andric ShowBinaryBlobs("show-binary-blobs",
76fe6060f1SDimitry Andric cl::desc("Print binary blobs using hex escapes"),
77fe6060f1SDimitry Andric cl::cat(BCAnalyzerCategory));
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric static cl::opt<std::string> CheckHash(
800b57cec5SDimitry Andric "check-hash",
81fe6060f1SDimitry Andric cl::desc("Check module hash using the argument as a string table"),
82fe6060f1SDimitry Andric cl::cat(BCAnalyzerCategory));
830b57cec5SDimitry Andric
reportError(StringRef Message)840b57cec5SDimitry Andric static Error reportError(StringRef Message) {
850b57cec5SDimitry Andric return createStringError(std::errc::illegal_byte_sequence, Message.data());
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric
openBitcodeFile(StringRef Path)880b57cec5SDimitry Andric static Expected<std::unique_ptr<MemoryBuffer>> openBitcodeFile(StringRef Path) {
890b57cec5SDimitry Andric // Read the input file.
900b57cec5SDimitry Andric Expected<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
910b57cec5SDimitry Andric errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Path));
920b57cec5SDimitry Andric if (Error E = MemBufOrErr.takeError())
930b57cec5SDimitry Andric return std::move(E);
940b57cec5SDimitry Andric
950b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> MemBuf = std::move(*MemBufOrErr);
960b57cec5SDimitry Andric
970b57cec5SDimitry Andric if (MemBuf->getBufferSize() & 3)
980b57cec5SDimitry Andric return reportError(
990b57cec5SDimitry Andric "Bitcode stream should be a multiple of 4 bytes in length");
1000b57cec5SDimitry Andric return std::move(MemBuf);
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric
main(int argc,char ** argv)1030b57cec5SDimitry Andric int main(int argc, char **argv) {
1040b57cec5SDimitry Andric InitLLVM X(argc, argv);
105fe6060f1SDimitry Andric
106fe6060f1SDimitry Andric cl::HideUnrelatedOptions({&BCAnalyzerCategory, &getColorCategory()});
1070b57cec5SDimitry Andric cl::ParseCommandLineOptions(argc, argv, "llvm-bcanalyzer file analyzer\n");
1080b57cec5SDimitry Andric ExitOnError ExitOnErr("llvm-bcanalyzer: ");
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> MB = ExitOnErr(openBitcodeFile(InputFilename));
1110b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> BlockInfoMB = nullptr;
1120b57cec5SDimitry Andric if (!BlockInfoFilename.empty())
1130b57cec5SDimitry Andric BlockInfoMB = ExitOnErr(openBitcodeFile(BlockInfoFilename));
1140b57cec5SDimitry Andric
1150b57cec5SDimitry Andric BitcodeAnalyzer BA(MB->getBuffer(),
116*bdd1243dSDimitry Andric BlockInfoMB
117*bdd1243dSDimitry Andric ? std::optional<StringRef>(BlockInfoMB->getBuffer())
118*bdd1243dSDimitry Andric : std::nullopt);
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric BCDumpOptions O(outs());
1210b57cec5SDimitry Andric O.Histogram = !NoHistogram;
1220b57cec5SDimitry Andric O.Symbolic = !NonSymbolic;
1230b57cec5SDimitry Andric O.ShowBinaryBlobs = ShowBinaryBlobs;
124349cc55cSDimitry Andric O.DumpBlockinfo = DumpBlockinfo;
1250b57cec5SDimitry Andric
126480093f4SDimitry Andric ExitOnErr(BA.analyze(
127*bdd1243dSDimitry Andric Dump ? std::optional<BCDumpOptions>(O) : std::optional<BCDumpOptions>(),
128*bdd1243dSDimitry Andric CheckHash.empty() ? std::nullopt : std::optional<StringRef>(CheckHash)));
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric if (Dump)
1310b57cec5SDimitry Andric outs() << "\n\n";
1320b57cec5SDimitry Andric
1330b57cec5SDimitry Andric BA.printStats(O, StringRef(InputFilename.getValue()));
1340b57cec5SDimitry Andric return 0;
1350b57cec5SDimitry Andric }
136