xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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