Home | History | Annotate | Download | only in Analysis
      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/Analysis/Passes.h"
     19 #include "llvm/ADT/Statistic.h"
     20 #include "llvm/IR/DebugInfo.h"
     21 #include "llvm/IR/Function.h"
     22 #include "llvm/Pass.h"
     23 #include "llvm/Support/ErrorHandling.h"
     24 #include "llvm/Support/raw_ostream.h"
     25 using namespace llvm;
     26 
     27 namespace {
     28   class ModuleDebugInfoPrinter : public ModulePass {
     29     DebugInfoFinder Finder;
     30   public:
     31     static char ID; // Pass identification, replacement for typeid
     32     ModuleDebugInfoPrinter() : ModulePass(ID) {
     33       initializeModuleDebugInfoPrinterPass(*PassRegistry::getPassRegistry());
     34     }
     35 
     36     bool runOnModule(Module &M) override;
     37 
     38     void getAnalysisUsage(AnalysisUsage &AU) const override {
     39       AU.setPreservesAll();
     40     }
     41     void print(raw_ostream &O, const Module *M) const override;
     42   };
     43 }
     44 
     45 char ModuleDebugInfoPrinter::ID = 0;
     46 INITIALIZE_PASS(ModuleDebugInfoPrinter, "module-debuginfo",
     47                 "Decodes module-level debug info", false, true)
     48 
     49 ModulePass *llvm::createModuleDebugInfoPrinterPass() {
     50   return new ModuleDebugInfoPrinter();
     51 }
     52 
     53 bool ModuleDebugInfoPrinter::runOnModule(Module &M) {
     54   Finder.processModule(M);
     55   return false;
     56 }
     57 
     58 static void printFile(raw_ostream &O, StringRef Filename, StringRef Directory,
     59                       unsigned Line = 0) {
     60   if (Filename.empty())
     61     return;
     62 
     63   O << " from ";
     64   if (!Directory.empty())
     65     O << Directory << "/";
     66   O << Filename;
     67   if (Line)
     68     O << ":" << Line;
     69 }
     70 
     71 void ModuleDebugInfoPrinter::print(raw_ostream &O, const Module *M) const {
     72   // Printing the nodes directly isn't particularly helpful (since they
     73   // reference other nodes that won't be printed, particularly for the
     74   // filenames), so just print a few useful things.
     75   for (DICompileUnit *CU : Finder.compile_units()) {
     76     O << "Compile unit: ";
     77     if (const char *Lang = dwarf::LanguageString(CU->getSourceLanguage()))
     78       O << Lang;
     79     else
     80       O << "unknown-language(" << CU->getSourceLanguage() << ")";
     81     printFile(O, CU->getFilename(), CU->getDirectory());
     82     O << '\n';
     83   }
     84 
     85   for (DISubprogram *S : Finder.subprograms()) {
     86     O << "Subprogram: " << S->getName();
     87     printFile(O, S->getFilename(), S->getDirectory(), S->getLine());
     88     if (!S->getLinkageName().empty())
     89       O << " ('" << S->getLinkageName() << "')";
     90     O << '\n';
     91   }
     92 
     93   for (const DIGlobalVariable *GV : Finder.global_variables()) {
     94     O << "Global variable: " << GV->getName();
     95     printFile(O, GV->getFilename(), GV->getDirectory(), GV->getLine());
     96     if (!GV->getLinkageName().empty())
     97       O << " ('" << GV->getLinkageName() << "')";
     98     O << '\n';
     99   }
    100 
    101   for (const DIType *T : Finder.types()) {
    102     O << "Type:";
    103     if (!T->getName().empty())
    104       O << ' ' << T->getName();
    105     printFile(O, T->getFilename(), T->getDirectory(), T->getLine());
    106     if (auto *BT = dyn_cast<DIBasicType>(T)) {
    107       O << " ";
    108       if (const char *Encoding =
    109               dwarf::AttributeEncodingString(BT->getEncoding()))
    110         O << Encoding;
    111       else
    112         O << "unknown-encoding(" << BT->getEncoding() << ')';
    113     } else {
    114       O << ' ';
    115       if (const char *Tag = dwarf::TagString(T->getTag()))
    116         O << Tag;
    117       else
    118         O << "unknown-tag(" << T->getTag() << ")";
    119     }
    120     if (auto *CT = dyn_cast<DICompositeType>(T)) {
    121       if (auto *S = CT->getRawIdentifier())
    122         O << " (identifier: '" << S->getString() << "')";
    123     }
    124     O << '\n';
    125   }
    126 }
    127