Line data Source code
1 : //===-- ModuleDebugInfoPrinter.cpp - Prints module debug info metadata ----===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This pass decodes the debug info metadata in a module and prints in a
11 : // (sufficiently-prepared-) human-readable form.
12 : //
13 : // For example, run this pass from opt along with the -analyze option, and
14 : // it'll print to standard output.
15 : //
16 : //===----------------------------------------------------------------------===//
17 :
18 : #include "llvm/ADT/Statistic.h"
19 : #include "llvm/Analysis/Passes.h"
20 : #include "llvm/IR/DebugInfo.h"
21 : #include "llvm/Pass.h"
22 : #include "llvm/Support/ErrorHandling.h"
23 : #include "llvm/Support/raw_ostream.h"
24 : using namespace llvm;
25 :
26 : namespace {
27 : class ModuleDebugInfoPrinter : public ModulePass {
28 : DebugInfoFinder Finder;
29 : public:
30 : static char ID; // Pass identification, replacement for typeid
31 8 : ModuleDebugInfoPrinter() : ModulePass(ID) {
32 4 : initializeModuleDebugInfoPrinterPass(*PassRegistry::getPassRegistry());
33 4 : }
34 :
35 : bool runOnModule(Module &M) override;
36 :
37 4 : void getAnalysisUsage(AnalysisUsage &AU) const override {
38 : AU.setPreservesAll();
39 4 : }
40 : void print(raw_ostream &O, const Module *M) const override;
41 : };
42 : }
43 :
44 : char ModuleDebugInfoPrinter::ID = 0;
45 21516 : INITIALIZE_PASS(ModuleDebugInfoPrinter, "module-debuginfo",
46 : "Decodes module-level debug info", false, true)
47 :
48 0 : ModulePass *llvm::createModuleDebugInfoPrinterPass() {
49 0 : return new ModuleDebugInfoPrinter();
50 : }
51 :
52 4 : bool ModuleDebugInfoPrinter::runOnModule(Module &M) {
53 4 : Finder.processModule(M);
54 4 : return false;
55 : }
56 :
57 19 : static void printFile(raw_ostream &O, StringRef Filename, StringRef Directory,
58 : unsigned Line = 0) {
59 19 : if (Filename.empty())
60 : return;
61 :
62 15 : O << " from ";
63 15 : if (!Directory.empty())
64 15 : O << Directory << "/";
65 15 : O << Filename;
66 15 : if (Line)
67 9 : O << ":" << Line;
68 : }
69 :
70 4 : void ModuleDebugInfoPrinter::print(raw_ostream &O, const Module *M) const {
71 : // Printing the nodes directly isn't particularly helpful (since they
72 : // reference other nodes that won't be printed, particularly for the
73 : // filenames), so just print a few useful things.
74 10 : for (DICompileUnit *CU : Finder.compile_units()) {
75 6 : O << "Compile unit: ";
76 6 : auto Lang = dwarf::LanguageString(CU->getSourceLanguage());
77 6 : if (!Lang.empty())
78 6 : O << Lang;
79 : else
80 0 : O << "unknown-language(" << CU->getSourceLanguage() << ")";
81 6 : printFile(O, CU->getFilename(), CU->getDirectory());
82 : O << '\n';
83 : }
84 :
85 8 : for (DISubprogram *S : Finder.subprograms()) {
86 8 : O << "Subprogram: " << S->getName();
87 4 : printFile(O, S->getFilename(), S->getDirectory(), S->getLine());
88 4 : if (!S->getLinkageName().empty())
89 0 : O << " ('" << S->getLinkageName() << "')";
90 : O << '\n';
91 : }
92 :
93 6 : for (auto GVU : Finder.global_variables()) {
94 : const auto *GV = GVU->getVariable();
95 4 : O << "Global variable: " << GV->getName();
96 2 : printFile(O, GV->getFilename(), GV->getDirectory(), GV->getLine());
97 2 : if (!GV->getLinkageName().empty())
98 2 : O << " ('" << GV->getLinkageName() << "')";
99 : O << '\n';
100 : }
101 :
102 11 : for (const DIType *T : Finder.types()) {
103 7 : O << "Type:";
104 7 : if (!T->getName().empty())
105 4 : O << ' ' << T->getName();
106 7 : printFile(O, T->getFilename(), T->getDirectory(), T->getLine());
107 : if (auto *BT = dyn_cast<DIBasicType>(T)) {
108 1 : O << " ";
109 1 : auto Encoding = dwarf::AttributeEncodingString(BT->getEncoding());
110 1 : if (!Encoding.empty())
111 1 : O << Encoding;
112 : else
113 0 : O << "unknown-encoding(" << BT->getEncoding() << ')';
114 : } else {
115 : O << ' ';
116 12 : auto Tag = dwarf::TagString(T->getTag());
117 6 : if (!Tag.empty())
118 6 : O << Tag;
119 : else
120 0 : O << "unknown-tag(" << T->getTag() << ")";
121 : }
122 : if (auto *CT = dyn_cast<DICompositeType>(T)) {
123 : if (auto *S = CT->getRawIdentifier())
124 0 : O << " (identifier: '" << S->getString() << "')";
125 : }
126 : O << '\n';
127 : }
128 4 : }
|