1 | //===-- ModuleDebugInfoPrinter.cpp - Prints module debug info metadata ----===// |
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 pass decodes the debug info metadata in a module and prints in a |
10 | // (sufficiently-prepared-) human-readable form. |
11 | // |
12 | // For example, run this pass from opt along with the -analyze option, and |
13 | // it'll print to standard output. |
14 | // |
15 | //===----------------------------------------------------------------------===// |
16 | |
17 | #include "llvm/Analysis/ModuleDebugInfoPrinter.h" |
18 | #include "llvm/BinaryFormat/Dwarf.h" |
19 | #include "llvm/IR/DebugInfo.h" |
20 | #include "llvm/IR/PassManager.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 | static void printFile(raw_ostream &O, StringRef Filename, StringRef Directory, |
27 | unsigned Line = 0) { |
28 | if (Filename.empty()) |
29 | return; |
30 | |
31 | O << " from " ; |
32 | if (!Directory.empty()) |
33 | O << Directory << "/" ; |
34 | O << Filename; |
35 | if (Line) |
36 | O << ":" << Line; |
37 | } |
38 | |
39 | static void printModuleDebugInfo(raw_ostream &O, const Module *M, |
40 | const DebugInfoFinder &Finder) { |
41 | // Printing the nodes directly isn't particularly helpful (since they |
42 | // reference other nodes that won't be printed, particularly for the |
43 | // filenames), so just print a few useful things. |
44 | for (DICompileUnit *CU : Finder.compile_units()) { |
45 | O << "Compile unit: " ; |
46 | auto Lang = dwarf::LanguageString(Language: CU->getSourceLanguage()); |
47 | if (!Lang.empty()) |
48 | O << Lang; |
49 | else |
50 | O << "unknown-language(" << CU->getSourceLanguage() << ")" ; |
51 | printFile(O, Filename: CU->getFilename(), Directory: CU->getDirectory()); |
52 | O << '\n'; |
53 | } |
54 | |
55 | for (DISubprogram *S : Finder.subprograms()) { |
56 | O << "Subprogram: " << S->getName(); |
57 | printFile(O, Filename: S->getFilename(), Directory: S->getDirectory(), Line: S->getLine()); |
58 | if (!S->getLinkageName().empty()) |
59 | O << " ('" << S->getLinkageName() << "')" ; |
60 | O << '\n'; |
61 | } |
62 | |
63 | for (auto *GVU : Finder.global_variables()) { |
64 | const auto *GV = GVU->getVariable(); |
65 | O << "Global variable: " << GV->getName(); |
66 | printFile(O, Filename: GV->getFilename(), Directory: GV->getDirectory(), Line: GV->getLine()); |
67 | if (!GV->getLinkageName().empty()) |
68 | O << " ('" << GV->getLinkageName() << "')" ; |
69 | O << '\n'; |
70 | } |
71 | |
72 | for (const DIType *T : Finder.types()) { |
73 | O << "Type:" ; |
74 | if (!T->getName().empty()) |
75 | O << ' ' << T->getName(); |
76 | printFile(O, Filename: T->getFilename(), Directory: T->getDirectory(), Line: T->getLine()); |
77 | if (auto *BT = dyn_cast<DIBasicType>(Val: T)) { |
78 | O << " " ; |
79 | auto Encoding = dwarf::AttributeEncodingString(Encoding: BT->getEncoding()); |
80 | if (!Encoding.empty()) |
81 | O << Encoding; |
82 | else |
83 | O << "unknown-encoding(" << BT->getEncoding() << ')'; |
84 | } else { |
85 | O << ' '; |
86 | auto Tag = dwarf::TagString(Tag: T->getTag()); |
87 | if (!Tag.empty()) |
88 | O << Tag; |
89 | else |
90 | O << "unknown-tag(" << T->getTag() << ")" ; |
91 | } |
92 | if (auto *CT = dyn_cast<DICompositeType>(Val: T)) { |
93 | if (auto *S = CT->getRawIdentifier()) |
94 | O << " (identifier: '" << S->getString() << "')" ; |
95 | } |
96 | O << '\n'; |
97 | } |
98 | } |
99 | |
100 | ModuleDebugInfoPrinterPass::ModuleDebugInfoPrinterPass(raw_ostream &OS) |
101 | : OS(OS) {} |
102 | |
103 | PreservedAnalyses ModuleDebugInfoPrinterPass::run(Module &M, |
104 | ModuleAnalysisManager &AM) { |
105 | Finder.processModule(M); |
106 | printModuleDebugInfo(O&: OS, M: &M, Finder); |
107 | return PreservedAnalyses::all(); |
108 | } |
109 | |