aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm14/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
blob: a238b0cf5922449f1701161fcd6c189a28ad6ddf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//===-- llvm-bcanalyzer.cpp - Bitcode Analyzer --------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This tool may be invoked in the following manner:
//  llvm-bcanalyzer [options]      - Read LLVM bitcode from stdin
//  llvm-bcanalyzer [options] x.bc - Read LLVM bitcode from the x.bc file
//
//  Options:
//      --help            - Output information about command line switches
//      --dump            - Dump low-level bitcode structure in readable format
//      --dump-blockinfo  - Dump the BLOCKINFO_BLOCK, when used with --dump
//
// This tool provides analytical information about a bitcode file. It is
// intended as an aid to developers of bitcode reading and writing software. It
// produces on std::out a summary of the bitcode file that shows various
// statistics about the contents of the file. By default this information is
// detailed and contains information about individual bitcode blocks and the
// functions in the module.
// The tool is also able to print a bitcode file in a straight forward text
// format that shows the containment and relationships of the information in
// the bitcode file (-dump option).
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/Optional.h"
#include "llvm/Bitcode/BitcodeAnalyzer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
using namespace llvm;

static cl::OptionCategory BCAnalyzerCategory("BC Analyzer Options");

static cl::opt<std::string> InputFilename(cl::Positional,
                                          cl::desc("<input bitcode>"),
                                          cl::init("-"),
                                          cl::cat(BCAnalyzerCategory));

static cl::opt<bool> Dump("dump", cl::desc("Dump low level bitcode trace"),
                          cl::cat(BCAnalyzerCategory));

static cl::opt<bool> DumpBlockinfo("dump-blockinfo",
                                   cl::desc("Include BLOCKINFO details in low"
                                            " level dump"),
                                   cl::cat(BCAnalyzerCategory));

//===----------------------------------------------------------------------===//
// Bitcode specific analysis.
//===----------------------------------------------------------------------===//

static cl::opt<bool> NoHistogram("disable-histogram",
                                 cl::desc("Do not print per-code histogram"),
                                 cl::cat(BCAnalyzerCategory));

static cl::opt<bool> NonSymbolic("non-symbolic",
                                 cl::desc("Emit numeric info in dump even if"
                                          " symbolic info is available"),
                                 cl::cat(BCAnalyzerCategory));

static cl::opt<std::string>
    BlockInfoFilename("block-info",
                      cl::desc("Use the BLOCK_INFO from the given file"),
                      cl::cat(BCAnalyzerCategory));

static cl::opt<bool>
    ShowBinaryBlobs("show-binary-blobs",
                    cl::desc("Print binary blobs using hex escapes"),
                    cl::cat(BCAnalyzerCategory));

static cl::opt<std::string> CheckHash(
    "check-hash",
    cl::desc("Check module hash using the argument as a string table"),
    cl::cat(BCAnalyzerCategory));

static Error reportError(StringRef Message) {
  return createStringError(std::errc::illegal_byte_sequence, Message.data());
}

static Expected<std::unique_ptr<MemoryBuffer>> openBitcodeFile(StringRef Path) {
  // Read the input file.
  Expected<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
      errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Path));
  if (Error E = MemBufOrErr.takeError())
    return std::move(E);

  std::unique_ptr<MemoryBuffer> MemBuf = std::move(*MemBufOrErr);

  if (MemBuf->getBufferSize() & 3)
    return reportError(
        "Bitcode stream should be a multiple of 4 bytes in length");
  return std::move(MemBuf);
}

int main(int argc, char **argv) {
  InitLLVM X(argc, argv);

  cl::HideUnrelatedOptions({&BCAnalyzerCategory, &getColorCategory()});
  cl::ParseCommandLineOptions(argc, argv, "llvm-bcanalyzer file analyzer\n");
  ExitOnError ExitOnErr("llvm-bcanalyzer: ");

  std::unique_ptr<MemoryBuffer> MB = ExitOnErr(openBitcodeFile(InputFilename));
  std::unique_ptr<MemoryBuffer> BlockInfoMB = nullptr;
  if (!BlockInfoFilename.empty())
    BlockInfoMB = ExitOnErr(openBitcodeFile(BlockInfoFilename));

  BitcodeAnalyzer BA(MB->getBuffer(),
                     BlockInfoMB ? Optional<StringRef>(BlockInfoMB->getBuffer())
                                 : None);

  BCDumpOptions O(outs());
  O.Histogram = !NoHistogram;
  O.Symbolic = !NonSymbolic;
  O.ShowBinaryBlobs = ShowBinaryBlobs;
  O.DumpBlockinfo = DumpBlockinfo;

  ExitOnErr(BA.analyze(
      Dump ? Optional<BCDumpOptions>(O) : Optional<BCDumpOptions>(None),
      CheckHash.empty() ? None : Optional<StringRef>(CheckHash)));

  if (Dump)
    outs() << "\n\n";

  BA.printStats(O, StringRef(InputFilename.getValue()));
  return 0;
}