117 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This pass decodes the debug info metadata in a module and prints in a10// (sufficiently-prepared-) human-readable form.11//12// For example, run this pass from opt along with the -analyze option, and13// 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"24using namespace llvm;25 26static 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 39static void printModuleDebugInfo(raw_ostream &O, const Module *M,40 const DebugInfoFinder &Finder) {41 // Printing the nodes directly isn't particularly helpful (since they42 // reference other nodes that won't be printed, particularly for the43 // filenames), so just print a few useful things.44 for (DICompileUnit *CU : Finder.compile_units()) {45 O << "Compile unit: ";46 47 DISourceLanguageName Lang = CU->getSourceLanguage();48 auto LangStr =49 Lang.hasVersionedName()50 ? dwarf::SourceLanguageNameString(51 static_cast<llvm::dwarf::SourceLanguageName>(Lang.getName()))52 : dwarf::LanguageString(Lang.getName());53 54 if (!LangStr.empty())55 O << LangStr;56 else57 O << "unknown-language(" << CU->getSourceLanguage().getName() << ")";58 59 printFile(O, CU->getFilename(), CU->getDirectory());60 O << '\n';61 }62 63 for (DISubprogram *S : Finder.subprograms()) {64 O << "Subprogram: " << S->getName();65 printFile(O, S->getFilename(), S->getDirectory(), S->getLine());66 if (!S->getLinkageName().empty())67 O << " ('" << S->getLinkageName() << "')";68 O << '\n';69 }70 71 for (auto *GVU : Finder.global_variables()) {72 const auto *GV = GVU->getVariable();73 O << "Global variable: " << GV->getName();74 printFile(O, GV->getFilename(), GV->getDirectory(), GV->getLine());75 if (!GV->getLinkageName().empty())76 O << " ('" << GV->getLinkageName() << "')";77 O << '\n';78 }79 80 for (const DIType *T : Finder.types()) {81 O << "Type:";82 if (!T->getName().empty())83 O << ' ' << T->getName();84 printFile(O, T->getFilename(), T->getDirectory(), T->getLine());85 if (auto *BT = dyn_cast<DIBasicType>(T)) {86 O << " ";87 auto Encoding = dwarf::AttributeEncodingString(BT->getEncoding());88 if (!Encoding.empty())89 O << Encoding;90 else91 O << "unknown-encoding(" << BT->getEncoding() << ')';92 } else {93 O << ' ';94 auto Tag = dwarf::TagString(T->getTag());95 if (!Tag.empty())96 O << Tag;97 else98 O << "unknown-tag(" << T->getTag() << ")";99 }100 if (auto *CT = dyn_cast<DICompositeType>(T)) {101 if (auto *S = CT->getRawIdentifier())102 O << " (identifier: '" << S->getString() << "')";103 }104 O << '\n';105 }106}107 108ModuleDebugInfoPrinterPass::ModuleDebugInfoPrinterPass(raw_ostream &OS)109 : OS(OS) {}110 111PreservedAnalyses ModuleDebugInfoPrinterPass::run(Module &M,112 ModuleAnalysisManager &AM) {113 Finder.processModule(M);114 printModuleDebugInfo(OS, &M, Finder);115 return PreservedAnalyses::all();116}117