From 7ab83427af0f77b59941ceba41d509d7d097b065 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 10 Jun 2017 13:44:06 +0000 Subject: Vendor import of llvm trunk r305145: https://llvm.org/svn/llvm-project/llvm/trunk@305145 --- tools/LLVMBuild.txt | 2 +- tools/bugpoint/OptimizerDriver.cpp | 5 +- tools/dsymutil/DwarfLinker.cpp | 9 +- tools/llc/llc.cpp | 97 +- tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp | 3 + tools/llvm-cvtres/LLVMBuild.txt | 2 +- tools/llvm-cvtres/llvm-cvtres.cpp | 73 +- tools/llvm-cvtres/llvm-cvtres.h | 2 - tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 4 + tools/llvm-lto2/llvm-lto2.cpp | 2 + tools/llvm-mc/llvm-mc.cpp | 22 +- tools/llvm-nm/llvm-nm.cpp | 2 +- tools/llvm-objdump/MachODump.cpp | 7 +- tools/llvm-pdbdump/Analyze.cpp | 152 --- tools/llvm-pdbdump/Analyze.h | 30 - tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp | 87 -- tools/llvm-pdbdump/C13DebugFragmentVisitor.h | 60 - tools/llvm-pdbdump/CMakeLists.txt | 35 - tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp | 59 - tools/llvm-pdbdump/CompactTypeDumpVisitor.h | 49 - tools/llvm-pdbdump/Diff.cpp | 537 --------- tools/llvm-pdbdump/Diff.h | 45 - tools/llvm-pdbdump/LLVMBuild.txt | 23 - tools/llvm-pdbdump/LLVMOutputStyle.cpp | 1036 ----------------- tools/llvm-pdbdump/LLVMOutputStyle.h | 70 -- tools/llvm-pdbdump/LinePrinter.cpp | 145 --- tools/llvm-pdbdump/LinePrinter.h | 102 -- tools/llvm-pdbdump/OutputStyle.h | 28 - tools/llvm-pdbdump/PdbYaml.cpp | 227 ---- tools/llvm-pdbdump/PdbYaml.h | 125 -- tools/llvm-pdbdump/PrettyBuiltinDumper.cpp | 94 -- tools/llvm-pdbdump/PrettyBuiltinDumper.h | 35 - tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp | 108 -- tools/llvm-pdbdump/PrettyClassDefinitionDumper.h | 47 - .../PrettyClassLayoutGraphicalDumper.cpp | 216 ---- .../PrettyClassLayoutGraphicalDumper.h | 58 - tools/llvm-pdbdump/PrettyCompilandDumper.cpp | 207 ---- tools/llvm-pdbdump/PrettyCompilandDumper.h | 44 - tools/llvm-pdbdump/PrettyEnumDumper.cpp | 53 - tools/llvm-pdbdump/PrettyEnumDumper.h | 31 - tools/llvm-pdbdump/PrettyExternalSymbolDumper.cpp | 41 - tools/llvm-pdbdump/PrettyExternalSymbolDumper.h | 34 - tools/llvm-pdbdump/PrettyFunctionDumper.cpp | 259 ----- tools/llvm-pdbdump/PrettyFunctionDumper.h | 43 - tools/llvm-pdbdump/PrettyTypeDumper.cpp | 251 ----- tools/llvm-pdbdump/PrettyTypeDumper.h | 36 - tools/llvm-pdbdump/PrettyTypedefDumper.cpp | 77 -- tools/llvm-pdbdump/PrettyTypedefDumper.h | 39 - tools/llvm-pdbdump/PrettyVariableDumper.cpp | 220 ---- tools/llvm-pdbdump/PrettyVariableDumper.h | 50 - tools/llvm-pdbdump/StreamUtil.cpp | 139 --- tools/llvm-pdbdump/StreamUtil.h | 25 - tools/llvm-pdbdump/YAMLOutputStyle.cpp | 322 ------ tools/llvm-pdbdump/YAMLOutputStyle.h | 49 - tools/llvm-pdbdump/fuzzer/CMakeLists.txt | 15 - tools/llvm-pdbdump/fuzzer/llvm-pdbdump-fuzzer.cpp | 105 -- tools/llvm-pdbdump/llvm-pdbdump.cpp | 981 ---------------- tools/llvm-pdbdump/llvm-pdbdump.h | 136 --- tools/llvm-pdbutil/Analyze.cpp | 152 +++ tools/llvm-pdbutil/Analyze.h | 30 + tools/llvm-pdbutil/CMakeLists.txt | 34 + tools/llvm-pdbutil/CompactTypeDumpVisitor.cpp | 59 + tools/llvm-pdbutil/CompactTypeDumpVisitor.h | 49 + tools/llvm-pdbutil/Diff.cpp | 537 +++++++++ tools/llvm-pdbutil/Diff.h | 45 + tools/llvm-pdbutil/LLVMBuild.txt | 23 + tools/llvm-pdbutil/LLVMOutputStyle.cpp | 1188 ++++++++++++++++++++ tools/llvm-pdbutil/LLVMOutputStyle.h | 70 ++ tools/llvm-pdbutil/LinePrinter.cpp | 145 +++ tools/llvm-pdbutil/LinePrinter.h | 102 ++ tools/llvm-pdbutil/OutputStyle.h | 28 + tools/llvm-pdbutil/PdbYaml.cpp | 227 ++++ tools/llvm-pdbutil/PdbYaml.h | 125 ++ tools/llvm-pdbutil/PrettyBuiltinDumper.cpp | 94 ++ tools/llvm-pdbutil/PrettyBuiltinDumper.h | 35 + tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp | 108 ++ tools/llvm-pdbutil/PrettyClassDefinitionDumper.h | 47 + .../PrettyClassLayoutGraphicalDumper.cpp | 216 ++++ .../PrettyClassLayoutGraphicalDumper.h | 58 + tools/llvm-pdbutil/PrettyCompilandDumper.cpp | 207 ++++ tools/llvm-pdbutil/PrettyCompilandDumper.h | 44 + tools/llvm-pdbutil/PrettyEnumDumper.cpp | 53 + tools/llvm-pdbutil/PrettyEnumDumper.h | 31 + tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp | 41 + tools/llvm-pdbutil/PrettyExternalSymbolDumper.h | 34 + tools/llvm-pdbutil/PrettyFunctionDumper.cpp | 259 +++++ tools/llvm-pdbutil/PrettyFunctionDumper.h | 43 + tools/llvm-pdbutil/PrettyTypeDumper.cpp | 255 +++++ tools/llvm-pdbutil/PrettyTypeDumper.h | 36 + tools/llvm-pdbutil/PrettyTypedefDumper.cpp | 77 ++ tools/llvm-pdbutil/PrettyTypedefDumper.h | 39 + tools/llvm-pdbutil/PrettyVariableDumper.cpp | 220 ++++ tools/llvm-pdbutil/PrettyVariableDumper.h | 50 + tools/llvm-pdbutil/StreamUtil.cpp | 139 +++ tools/llvm-pdbutil/StreamUtil.h | 25 + tools/llvm-pdbutil/YAMLOutputStyle.cpp | 317 ++++++ tools/llvm-pdbutil/YAMLOutputStyle.h | 49 + tools/llvm-pdbutil/fuzzer/CMakeLists.txt | 15 + tools/llvm-pdbutil/fuzzer/llvm-pdbutil-fuzzer.cpp | 105 ++ tools/llvm-pdbutil/llvm-pdbutil.cpp | 1025 +++++++++++++++++ tools/llvm-pdbutil/llvm-pdbutil.h | 157 +++ tools/llvm-readobj/CMakeLists.txt | 1 + tools/llvm-readobj/COFFDumper.cpp | 2 +- tools/llvm-readobj/COFFImportDumper.cpp | 2 +- tools/llvm-readobj/ELFDumper.cpp | 202 ++-- tools/llvm-readobj/LLVMBuild.txt | 2 +- tools/llvm-stress/llvm-stress.cpp | 3 + tools/llvm-xray/xray-extract.cc | 2 +- tools/obj2yaml/dwarf2yaml.cpp | 1 + tools/obj2yaml/macho2yaml.cpp | 2 +- tools/yaml2obj/yaml2elf.cpp | 2 +- tools/yaml2obj/yaml2macho.cpp | 6 +- 112 files changed, 6847 insertions(+), 6726 deletions(-) delete mode 100644 tools/llvm-pdbdump/Analyze.cpp delete mode 100644 tools/llvm-pdbdump/Analyze.h delete mode 100644 tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp delete mode 100644 tools/llvm-pdbdump/C13DebugFragmentVisitor.h delete mode 100644 tools/llvm-pdbdump/CMakeLists.txt delete mode 100644 tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp delete mode 100644 tools/llvm-pdbdump/CompactTypeDumpVisitor.h delete mode 100644 tools/llvm-pdbdump/Diff.cpp delete mode 100644 tools/llvm-pdbdump/Diff.h delete mode 100644 tools/llvm-pdbdump/LLVMBuild.txt delete mode 100644 tools/llvm-pdbdump/LLVMOutputStyle.cpp delete mode 100644 tools/llvm-pdbdump/LLVMOutputStyle.h delete mode 100644 tools/llvm-pdbdump/LinePrinter.cpp delete mode 100644 tools/llvm-pdbdump/LinePrinter.h delete mode 100644 tools/llvm-pdbdump/OutputStyle.h delete mode 100644 tools/llvm-pdbdump/PdbYaml.cpp delete mode 100644 tools/llvm-pdbdump/PdbYaml.h delete mode 100644 tools/llvm-pdbdump/PrettyBuiltinDumper.cpp delete mode 100644 tools/llvm-pdbdump/PrettyBuiltinDumper.h delete mode 100644 tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp delete mode 100644 tools/llvm-pdbdump/PrettyClassDefinitionDumper.h delete mode 100644 tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.cpp delete mode 100644 tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.h delete mode 100644 tools/llvm-pdbdump/PrettyCompilandDumper.cpp delete mode 100644 tools/llvm-pdbdump/PrettyCompilandDumper.h delete mode 100644 tools/llvm-pdbdump/PrettyEnumDumper.cpp delete mode 100644 tools/llvm-pdbdump/PrettyEnumDumper.h delete mode 100644 tools/llvm-pdbdump/PrettyExternalSymbolDumper.cpp delete mode 100644 tools/llvm-pdbdump/PrettyExternalSymbolDumper.h delete mode 100644 tools/llvm-pdbdump/PrettyFunctionDumper.cpp delete mode 100644 tools/llvm-pdbdump/PrettyFunctionDumper.h delete mode 100644 tools/llvm-pdbdump/PrettyTypeDumper.cpp delete mode 100644 tools/llvm-pdbdump/PrettyTypeDumper.h delete mode 100644 tools/llvm-pdbdump/PrettyTypedefDumper.cpp delete mode 100644 tools/llvm-pdbdump/PrettyTypedefDumper.h delete mode 100644 tools/llvm-pdbdump/PrettyVariableDumper.cpp delete mode 100644 tools/llvm-pdbdump/PrettyVariableDumper.h delete mode 100644 tools/llvm-pdbdump/StreamUtil.cpp delete mode 100644 tools/llvm-pdbdump/StreamUtil.h delete mode 100644 tools/llvm-pdbdump/YAMLOutputStyle.cpp delete mode 100644 tools/llvm-pdbdump/YAMLOutputStyle.h delete mode 100644 tools/llvm-pdbdump/fuzzer/CMakeLists.txt delete mode 100644 tools/llvm-pdbdump/fuzzer/llvm-pdbdump-fuzzer.cpp delete mode 100644 tools/llvm-pdbdump/llvm-pdbdump.cpp delete mode 100644 tools/llvm-pdbdump/llvm-pdbdump.h create mode 100644 tools/llvm-pdbutil/Analyze.cpp create mode 100644 tools/llvm-pdbutil/Analyze.h create mode 100644 tools/llvm-pdbutil/CMakeLists.txt create mode 100644 tools/llvm-pdbutil/CompactTypeDumpVisitor.cpp create mode 100644 tools/llvm-pdbutil/CompactTypeDumpVisitor.h create mode 100644 tools/llvm-pdbutil/Diff.cpp create mode 100644 tools/llvm-pdbutil/Diff.h create mode 100644 tools/llvm-pdbutil/LLVMBuild.txt create mode 100644 tools/llvm-pdbutil/LLVMOutputStyle.cpp create mode 100644 tools/llvm-pdbutil/LLVMOutputStyle.h create mode 100644 tools/llvm-pdbutil/LinePrinter.cpp create mode 100644 tools/llvm-pdbutil/LinePrinter.h create mode 100644 tools/llvm-pdbutil/OutputStyle.h create mode 100644 tools/llvm-pdbutil/PdbYaml.cpp create mode 100644 tools/llvm-pdbutil/PdbYaml.h create mode 100644 tools/llvm-pdbutil/PrettyBuiltinDumper.cpp create mode 100644 tools/llvm-pdbutil/PrettyBuiltinDumper.h create mode 100644 tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp create mode 100644 tools/llvm-pdbutil/PrettyClassDefinitionDumper.h create mode 100644 tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp create mode 100644 tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h create mode 100644 tools/llvm-pdbutil/PrettyCompilandDumper.cpp create mode 100644 tools/llvm-pdbutil/PrettyCompilandDumper.h create mode 100644 tools/llvm-pdbutil/PrettyEnumDumper.cpp create mode 100644 tools/llvm-pdbutil/PrettyEnumDumper.h create mode 100644 tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp create mode 100644 tools/llvm-pdbutil/PrettyExternalSymbolDumper.h create mode 100644 tools/llvm-pdbutil/PrettyFunctionDumper.cpp create mode 100644 tools/llvm-pdbutil/PrettyFunctionDumper.h create mode 100644 tools/llvm-pdbutil/PrettyTypeDumper.cpp create mode 100644 tools/llvm-pdbutil/PrettyTypeDumper.h create mode 100644 tools/llvm-pdbutil/PrettyTypedefDumper.cpp create mode 100644 tools/llvm-pdbutil/PrettyTypedefDumper.h create mode 100644 tools/llvm-pdbutil/PrettyVariableDumper.cpp create mode 100644 tools/llvm-pdbutil/PrettyVariableDumper.h create mode 100644 tools/llvm-pdbutil/StreamUtil.cpp create mode 100644 tools/llvm-pdbutil/StreamUtil.h create mode 100644 tools/llvm-pdbutil/YAMLOutputStyle.cpp create mode 100644 tools/llvm-pdbutil/YAMLOutputStyle.h create mode 100644 tools/llvm-pdbutil/fuzzer/CMakeLists.txt create mode 100644 tools/llvm-pdbutil/fuzzer/llvm-pdbutil-fuzzer.cpp create mode 100644 tools/llvm-pdbutil/llvm-pdbutil.cpp create mode 100644 tools/llvm-pdbutil/llvm-pdbutil.h (limited to 'tools') diff --git a/tools/LLVMBuild.txt b/tools/LLVMBuild.txt index e3041a6d40d4..bcf58842eac3 100644 --- a/tools/LLVMBuild.txt +++ b/tools/LLVMBuild.txt @@ -40,7 +40,7 @@ subdirectories = llvm-modextract llvm-nm llvm-objdump - llvm-pdbdump + llvm-pdbutil llvm-profdata llvm-rtdyld llvm-size diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp index ae3a31adaea3..489e50b88101 100644 --- a/tools/bugpoint/OptimizerDriver.cpp +++ b/tools/bugpoint/OptimizerDriver.cpp @@ -202,10 +202,11 @@ bool BugDriver::runPasses(Module *Program, } else Args.push_back(tool.c_str()); - Args.push_back("-o"); - Args.push_back(OutputFilename.c_str()); for (unsigned i = 0, e = OptArgs.size(); i != e; ++i) Args.push_back(OptArgs[i].c_str()); + Args.push_back("-disable-symbolication"); + Args.push_back("-o"); + Args.push_back(OutputFilename.c_str()); std::vector pass_args; for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) { pass_args.push_back(std::string("-load")); diff --git a/tools/dsymutil/DwarfLinker.cpp b/tools/dsymutil/DwarfLinker.cpp index f74d721e6149..88de2706544e 100644 --- a/tools/dsymutil/DwarfLinker.cpp +++ b/tools/dsymutil/DwarfLinker.cpp @@ -6,15 +6,15 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#include "DebugMap.h" #include "BinaryHolder.h" #include "DebugMap.h" -#include "dsymutil.h" #include "MachOUtils.h" #include "NonRelocatableStringpool.h" +#include "dsymutil.h" #include "llvm/ADT/IntervalMap.h" -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/DIE.h" #include "llvm/Config/config.h" @@ -23,8 +23,8 @@ #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" #include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCObjectFileInfo.h" @@ -33,7 +33,6 @@ #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCTargetOptionsCommandFlags.h" #include "llvm/Object/MachO.h" -#include "llvm/Support/Dwarf.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Target/TargetMachine.h" diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index e10d112dcf90..e71c3c5bb705 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -61,6 +61,9 @@ using namespace llvm; static cl::opt InputFilename(cl::Positional, cl::desc(""), cl::init("-")); +static cl::opt +InputLanguage("x", cl::desc("Input language ('ir' or 'mir')")); + static cl::opt OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); @@ -335,6 +338,12 @@ int main(int argc, char **argv) { llvm::make_unique(YamlFile->os())); } + if (InputLanguage != "" && InputLanguage != "ir" && + InputLanguage != "mir") { + errs() << argv[0] << "Input language must be '', 'IR' or 'MIR'\n"; + return 1; + } + // Compile the module TimeCompilations times to give better compile time // metrics. for (unsigned I = TimeCompilations; I; --I) @@ -398,10 +407,11 @@ static int compileModule(char **argv, LLVMContext &Context) { // If user just wants to list available options, skip module loading if (!SkipModule) { - if (StringRef(InputFilename).endswith_lower(".mir")) { + if (InputLanguage == "mir" || + (InputLanguage == "" && StringRef(InputFilename).endswith(".mir"))) { MIR = createMIRParserFromFile(InputFilename, Err, Context); if (MIR) - M = MIR->parseLLVMModule(); + M = MIR->parseIRModule(); } else M = parseIRFile(InputFilename, Err, Context); if (!M) { @@ -518,54 +528,67 @@ static int compileModule(char **argv, LLVMContext &Context) { OS = BOS.get(); } - if (!RunPassNames->empty()) { - if (!StartAfter.empty() || !StopAfter.empty() || !StartBefore.empty() || - !StopBefore.empty()) { - errs() << argv[0] << ": start-after and/or stop-after passes are " - "redundant when run-pass is specified.\n"; - return 1; - } - if (!MIR) { - errs() << argv[0] << ": run-pass needs a .mir input.\n"; - return 1; - } + const char *argv0 = argv[0]; + AnalysisID StartBeforeID = getPassID(argv0, "start-before", StartBefore); + AnalysisID StartAfterID = getPassID(argv0, "start-after", StartAfter); + AnalysisID StopAfterID = getPassID(argv0, "stop-after", StopAfter); + AnalysisID StopBeforeID = getPassID(argv0, "stop-before", StopBefore); + if (StartBeforeID && StartAfterID) { + errs() << argv0 << ": -start-before and -start-after specified!\n"; + return 1; + } + if (StopBeforeID && StopAfterID) { + errs() << argv0 << ": -stop-before and -stop-after specified!\n"; + return 1; + } + + if (MIR) { + // Construct a custom pass pipeline that starts after instruction + // selection. LLVMTargetMachine &LLVMTM = static_cast(*Target); TargetPassConfig &TPC = *LLVMTM.createPassConfig(PM); + TPC.setDisableVerify(NoVerify); PM.add(&TPC); MachineModuleInfo *MMI = new MachineModuleInfo(&LLVMTM); - MMI->setMachineFunctionInitializer(MIR.get()); + if (MIR->parseMachineFunctions(*M, *MMI)) + return 1; PM.add(MMI); TPC.printAndVerify(""); - for (const std::string &RunPassName : *RunPassNames) { - if (addPass(PM, argv[0], RunPassName, TPC)) + if (!RunPassNames->empty()) { + if (!StartAfter.empty() || !StopAfter.empty() || !StartBefore.empty() || + !StopBefore.empty()) { + errs() << argv0 << ": start-after and/or stop-after passes are " + "redundant when run-pass is specified.\n"; return 1; + } + + for (const std::string &RunPassName : *RunPassNames) { + if (addPass(PM, argv0, RunPassName, TPC)) + return 1; + } + } else { + TPC.setStartStopPasses(StartBeforeID, StartAfterID, StopBeforeID, + StopAfterID); + TPC.addISelPasses(); + TPC.addMachinePasses(); } - PM.add(createPrintMIRPass(*OS)); - } else { - const char *argv0 = argv[0]; - AnalysisID StartBeforeID = getPassID(argv0, "start-before", StartBefore); - AnalysisID StartAfterID = getPassID(argv0, "start-after", StartAfter); - AnalysisID StopAfterID = getPassID(argv0, "stop-after", StopAfter); - AnalysisID StopBeforeID = getPassID(argv0, "stop-before", StopBefore); - - if (StartBeforeID && StartAfterID) { - errs() << argv[0] << ": -start-before and -start-after specified!\n"; - return 1; - } - if (StopBeforeID && StopAfterID) { - errs() << argv[0] << ": -stop-before and -stop-after specified!\n"; - return 1; - } + TPC.setInitialized(); - // Ask the target to add backend passes as necessary. - if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, - StartBeforeID, StartAfterID, StopBeforeID, - StopAfterID, MIR.get())) { - errs() << argv[0] << ": target does not support generation of this" + if (!StopBefore.empty() || !StopAfter.empty() || !RunPassNames->empty()) { + PM.add(createPrintMIRPass(*OS)); + } else if (LLVMTM.addAsmPrinter(PM, *OS, FileType, MMI->getContext())) { + errs() << argv0 << ": target does not support generation of this" << " file type!\n"; return 1; } + PM.add(createFreeMachineFunctionPass()); + } else if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, + StartBeforeID, StartAfterID, + StopBeforeID, StopAfterID)) { + errs() << argv0 << ": target does not support generation of this" + << " file type!\n"; + return 1; } // Before executing passes, print the final values of the LLVM options. diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp index 676134ca2368..c8fa56d724bf 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -121,6 +121,8 @@ static const char *GetBlockName(unsigned BlockID, case bitc::USELIST_BLOCK_ID: return "USELIST_BLOCK_ID"; case bitc::GLOBALVAL_SUMMARY_BLOCK_ID: return "GLOBALVAL_SUMMARY_BLOCK"; + case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID: + return "FULL_LTO_GLOBALVAL_SUMMARY_BLOCK"; case bitc::MODULE_STRTAB_BLOCK_ID: return "MODULE_STRTAB_BLOCK"; case bitc::STRTAB_BLOCK_ID: return "STRTAB_BLOCK"; } @@ -298,6 +300,7 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, STRINGIFY_CODE(MST_CODE, HASH) } case bitc::GLOBALVAL_SUMMARY_BLOCK_ID: + case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID: switch (CodeID) { default: return nullptr; diff --git a/tools/llvm-cvtres/LLVMBuild.txt b/tools/llvm-cvtres/LLVMBuild.txt index 73693bccb0ea..78c598b75e31 100644 --- a/tools/llvm-cvtres/LLVMBuild.txt +++ b/tools/llvm-cvtres/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Tool name = llvm-cvtres parent = Tools -required_libraries = Option Support +required_libraries = Object Option Support diff --git a/tools/llvm-cvtres/llvm-cvtres.cpp b/tools/llvm-cvtres/llvm-cvtres.cpp index 95a6623b44eb..eaba02c16f39 100644 --- a/tools/llvm-cvtres/llvm-cvtres.cpp +++ b/tools/llvm-cvtres/llvm-cvtres.cpp @@ -112,20 +112,23 @@ int main(int argc_, const char *argv_[]) { return 0; } - machine Machine; + bool Verbose = InputArgs.hasArg(OPT_VERBOSE); + + Machine MachineType; if (InputArgs.hasArg(OPT_MACHINE)) { std::string MachineString = InputArgs.getLastArgValue(OPT_MACHINE).upper(); - Machine = StringSwitch(MachineString) - .Case("ARM", machine::ARM) - .Case("X64", machine::X64) - .Case("X86", machine::X86) - .Default(machine::UNKNOWN); - if (Machine == machine::UNKNOWN) + MachineType = StringSwitch(MachineString) + .Case("ARM", Machine::ARM) + .Case("X64", Machine::X64) + .Case("X86", Machine::X86) + .Default(Machine::UNKNOWN); + if (MachineType == Machine::UNKNOWN) reportError("Unsupported machine architecture"); } else { - outs() << "Machine architecture not specified; assumed X64.\n"; - Machine = machine::X64; + if (Verbose) + outs() << "Machine architecture not specified; assumed X64.\n"; + MachineType = Machine::X64; } std::vector InputFiles = InputArgs.getAllArgValues(OPT_INPUT); @@ -139,20 +142,22 @@ int main(int argc_, const char *argv_[]) { if (InputArgs.hasArg(OPT_OUT)) { OutputFile = InputArgs.getLastArgValue(OPT_OUT); } else { - OutputFile = StringRef(InputFiles[0]); + OutputFile = llvm::sys::path::filename(StringRef(InputFiles[0])); llvm::sys::path::replace_extension(OutputFile, ".obj"); } - outs() << "Machine: "; - switch (Machine) { - case machine::ARM: - outs() << "ARM\n"; - break; - case machine::X86: - outs() << "X86\n"; - break; - default: - outs() << "X64\n"; + if (Verbose) { + outs() << "Machine: "; + switch (MachineType) { + case Machine::ARM: + outs() << "ARM\n"; + break; + case Machine::X86: + outs() << "X86\n"; + break; + default: + outs() << "X64\n"; + } } WindowsResourceParser Parser; @@ -169,22 +174,28 @@ int main(int argc_, const char *argv_[]) { if (!RF) reportError(File + ": unrecognized file format.\n"); - int EntryNumber = 0; - Expected EntryOrErr = RF->getHeadEntry(); - if (!EntryOrErr) - error(EntryOrErr.takeError()); - ResourceEntryRef Entry = EntryOrErr.get(); - bool End = false; - while (!End) { - error(Entry.moveNext(End)); - EntryNumber++; + if (Verbose) { + int EntryNumber = 0; + Expected EntryOrErr = RF->getHeadEntry(); + if (!EntryOrErr) + error(EntryOrErr.takeError()); + ResourceEntryRef Entry = EntryOrErr.get(); + bool End = false; + while (!End) { + error(Entry.moveNext(End)); + EntryNumber++; + } + outs() << "Number of resources: " << EntryNumber << "\n"; } - outs() << "Number of resources: " << EntryNumber << "\n"; error(Parser.parse(RF)); } - Parser.printTree(); + if (Verbose) + Parser.printTree(); + + error( + llvm::object::writeWindowsResourceCOFF(OutputFile, MachineType, Parser)); return 0; } diff --git a/tools/llvm-cvtres/llvm-cvtres.h b/tools/llvm-cvtres/llvm-cvtres.h index 2e45b66461f0..f7b14faeebe3 100644 --- a/tools/llvm-cvtres/llvm-cvtres.h +++ b/tools/llvm-cvtres/llvm-cvtres.h @@ -14,6 +14,4 @@ void error(std::error_code EC); -enum class machine { UNKNOWN = 0, ARM, X64, X86 }; - #endif diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index 2b5babe79824..1da157c4e4d5 100644 --- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -67,6 +67,7 @@ static cl::opt DumpType( clEnumValN(DIDT_GnuPubnames, "gnu_pubnames", ".debug_gnu_pubnames"), clEnumValN(DIDT_GnuPubtypes, "gnu_pubtypes", ".debug_gnu_pubtypes"), clEnumValN(DIDT_Str, "str", ".debug_str"), + clEnumValN(DIDT_StrOffsets, "str_offsets", ".debug_str_offsets"), clEnumValN(DIDT_StrDwo, "str.dwo", ".debug_str.dwo"), clEnumValN(DIDT_StrOffsetsDwo, "str_offsets.dwo", ".debug_str_offsets.dwo"), @@ -83,6 +84,8 @@ static cl::opt Verify("verify", cl::desc("Verify the DWARF debug info")); static cl::opt Quiet("quiet", cl::desc("Use with -verify to not emit to STDOUT.")); +static cl::opt Brief("brief", cl::desc("Print fewer low-level details")); + static void error(StringRef Filename, std::error_code EC) { if (!EC) return; @@ -100,6 +103,7 @@ static void DumpObjectFile(ObjectFile &Obj, Twine Filename) { DIDumpOptions DumpOpts; DumpOpts.DumpType = DumpType; DumpOpts.SummarizeTypes = SummarizeTypes; + DumpOpts.Brief = Brief; DICtx->dump(outs(), DumpOpts); } diff --git a/tools/llvm-lto2/llvm-lto2.cpp b/tools/llvm-lto2/llvm-lto2.cpp index 89f85157e1df..bbfece517c80 100644 --- a/tools/llvm-lto2/llvm-lto2.cpp +++ b/tools/llvm-lto2/llvm-lto2.cpp @@ -162,6 +162,8 @@ static int run(int argc, char **argv) { Res.FinalDefinitionInLinkageUnit = true; else if (C == 'x') Res.VisibleToRegularObj = true; + else if (C == 'r') + Res.LinkerRedefined = true; else { llvm::errs() << "invalid character " << C << " in resolution: " << R << '\n'; diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 87efac2d33cf..8782588dfdd8 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -56,17 +56,15 @@ static cl::opt RelaxELFRel( "relax-relocations", cl::init(true), cl::desc("Emit R_X86_64_GOTPCRELX instead of R_X86_64_GOTPCREL")); -static cl::opt -CompressDebugSections("compress-debug-sections", cl::ValueOptional, - cl::init(DebugCompressionType::DCT_None), - cl::desc("Choose DWARF debug sections compression:"), - cl::values( - clEnumValN(DebugCompressionType::DCT_None, "none", - "No compression"), - clEnumValN(DebugCompressionType::DCT_Zlib, "zlib", - "Use zlib compression"), - clEnumValN(DebugCompressionType::DCT_ZlibGnu, "zlib-gnu", - "Use zlib-gnu compression (deprecated)"))); +static cl::opt CompressDebugSections( + "compress-debug-sections", cl::ValueOptional, + cl::init(DebugCompressionType::None), + cl::desc("Choose DWARF debug sections compression:"), + cl::values(clEnumValN(DebugCompressionType::None, "none", "No compression"), + clEnumValN(DebugCompressionType::Z, "zlib", + "Use zlib compression"), + clEnumValN(DebugCompressionType::GNU, "zlib-gnu", + "Use zlib-gnu compression (deprecated)"))); static cl::opt ShowInst("show-inst", cl::desc("Show internal instruction representation")); @@ -494,7 +492,7 @@ int main(int argc, char **argv) { MAI->setRelaxELFRelocations(RelaxELFRel); - if (CompressDebugSections != DebugCompressionType::DCT_None) { + if (CompressDebugSections != DebugCompressionType::None) { if (!zlib::isAvailable()) { errs() << ProgName << ": build tools with zlib to enable -compress-debug-sections"; diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index b022c300756d..722cb9e7e449 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -17,6 +17,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/StringSwitch.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalVariable.h" @@ -31,7 +32,6 @@ #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/Wasm.h" -#include "llvm/Support/COFF.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index a260d6ff42c5..8927f57cc97f 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -11,12 +11,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Object/MachO.h" #include "llvm-objdump.h" #include "llvm-c/Disassembler.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" +#include "llvm/BinaryFormat/MachO.h" #include "llvm/Config/config.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" @@ -30,6 +30,7 @@ #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Object/MachO.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" @@ -39,7 +40,6 @@ #include "llvm/Support/FormattedStream.h" #include "llvm/Support/GraphWriter.h" #include "llvm/Support/LEB128.h" -#include "llvm/Support/MachO.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" @@ -2594,7 +2594,8 @@ static const char *get_symbol_32(uint32_t sect_offset, SectionRef S, // These are structs in the Objective-C meta data and read to produce the // comments for disassembly. While these are part of the ABI they are no -// public defintions. So the are here not in include/llvm/Support/MachO.h . +// public defintions. So the are here not in include/llvm/BinaryFormat/MachO.h +// . // The cfstring object in a 64-bit Mach-O file. struct cfstring64_t { diff --git a/tools/llvm-pdbdump/Analyze.cpp b/tools/llvm-pdbdump/Analyze.cpp deleted file mode 100644 index b503cdcbf1ea..000000000000 --- a/tools/llvm-pdbdump/Analyze.cpp +++ /dev/null @@ -1,152 +0,0 @@ -//===- Analyze.cpp - PDB analysis functions ---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "Analyze.h" - -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" -#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" -#include "llvm/DebugInfo/PDB/Native/PDBFile.h" -#include "llvm/DebugInfo/PDB/Native/RawError.h" -#include "llvm/DebugInfo/PDB/Native/TpiStream.h" - -#include "llvm/Support/FormatVariadic.h" -#include "llvm/Support/raw_ostream.h" - -#include - -using namespace llvm; -using namespace llvm::codeview; -using namespace llvm::pdb; - -static StringRef getLeafTypeName(TypeLeafKind LT) { - switch (LT) { -#define TYPE_RECORD(ename, value, name) \ - case ename: \ - return #name; -#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" - default: - break; - } - return "UnknownLeaf"; -} - -namespace { -struct HashLookupVisitor : public TypeVisitorCallbacks { - struct Entry { - TypeIndex TI; - CVType Record; - }; - - explicit HashLookupVisitor(TpiStream &Tpi) : Tpi(Tpi) {} - - Error visitTypeBegin(CVType &Record) override { - uint32_t H = Tpi.getHashValues()[I]; - Record.Hash = H; - TypeIndex TI(I + TypeIndex::FirstNonSimpleIndex); - Lookup[H].push_back(Entry{TI, Record}); - ++I; - return Error::success(); - } - - uint32_t I = 0; - DenseMap> Lookup; - TpiStream &Tpi; -}; -} - -AnalysisStyle::AnalysisStyle(PDBFile &File) : File(File) {} - -Error AnalysisStyle::dump() { - auto Tpi = File.getPDBTpiStream(); - if (!Tpi) - return Tpi.takeError(); - - TypeDatabase TypeDB(Tpi->getNumTypeRecords()); - TypeDatabaseVisitor DBV(TypeDB); - TypeVisitorCallbackPipeline Pipeline; - HashLookupVisitor Hasher(*Tpi); - // Add them to the database - Pipeline.addCallbackToPipeline(DBV); - // Store their hash values - Pipeline.addCallbackToPipeline(Hasher); - - if (auto EC = codeview::visitTypeStream(Tpi->typeArray(), Pipeline)) - return EC; - - auto &Adjusters = Tpi->getHashAdjusters(); - DenseSet AdjusterSet; - for (const auto &Adj : Adjusters) { - assert(AdjusterSet.find(Adj.second) == AdjusterSet.end()); - AdjusterSet.insert(Adj.second); - } - - uint32_t Count = 0; - outs() << "Searching for hash collisions\n"; - for (const auto &H : Hasher.Lookup) { - if (H.second.size() <= 1) - continue; - ++Count; - outs() << formatv("Hash: {0}, Count: {1} records\n", H.first, - H.second.size()); - for (const auto &R : H.second) { - auto Iter = AdjusterSet.find(R.TI.getIndex()); - StringRef Prefix; - if (Iter != AdjusterSet.end()) { - Prefix = "[HEAD]"; - AdjusterSet.erase(Iter); - } - StringRef LeafName = getLeafTypeName(R.Record.Type); - uint32_t TI = R.TI.getIndex(); - StringRef TypeName = TypeDB.getTypeName(R.TI); - outs() << formatv("{0,-6} {1} ({2:x}) {3}\n", Prefix, LeafName, TI, - TypeName); - } - } - - outs() << "\n"; - outs() << "Dumping hash adjustment chains\n"; - for (const auto &A : Tpi->getHashAdjusters()) { - TypeIndex TI(A.second); - StringRef TypeName = TypeDB.getTypeName(TI); - const CVType &HeadRecord = TypeDB.getTypeRecord(TI); - assert(HeadRecord.Hash.hasValue()); - - auto CollisionsIter = Hasher.Lookup.find(*HeadRecord.Hash); - if (CollisionsIter == Hasher.Lookup.end()) - continue; - - const auto &Collisions = CollisionsIter->second; - outs() << TypeName << "\n"; - outs() << formatv(" [HEAD] {0:x} {1} {2}\n", A.second, - getLeafTypeName(HeadRecord.Type), TypeName); - for (const auto &Chain : Collisions) { - if (Chain.TI == TI) - continue; - const CVType &TailRecord = TypeDB.getTypeRecord(Chain.TI); - outs() << formatv(" {0:x} {1} {2}\n", Chain.TI.getIndex(), - getLeafTypeName(TailRecord.Type), - TypeDB.getTypeName(Chain.TI)); - } - } - outs() << formatv("There are {0} orphaned hash adjusters\n", - AdjusterSet.size()); - for (const auto &Adj : AdjusterSet) { - outs() << formatv(" {0}\n", Adj); - } - - uint32_t DistinctHashValues = Hasher.Lookup.size(); - outs() << formatv("{0}/{1} hash collisions", Count, DistinctHashValues); - return Error::success(); -} diff --git a/tools/llvm-pdbdump/Analyze.h b/tools/llvm-pdbdump/Analyze.h deleted file mode 100644 index 7230ae45b0c8..000000000000 --- a/tools/llvm-pdbdump/Analyze.h +++ /dev/null @@ -1,30 +0,0 @@ -//===- Analyze.h - PDB analysis functions -----------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_ANALYSIS_H -#define LLVM_TOOLS_LLVMPDBDUMP_ANALYSIS_H - -#include "OutputStyle.h" - -namespace llvm { -namespace pdb { -class PDBFile; -class AnalysisStyle : public OutputStyle { -public: - explicit AnalysisStyle(PDBFile &File); - - Error dump() override; - -private: - PDBFile &File; -}; -} -} - -#endif diff --git a/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp b/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp deleted file mode 100644 index 78971eb5879a..000000000000 --- a/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp +++ /dev/null @@ -1,87 +0,0 @@ -//===- C13DebugFragmentVisitor.cpp -------------------------------*- C++-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "C13DebugFragmentVisitor.h" - -#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" -#include "llvm/DebugInfo/PDB/Native/PDBFile.h" -#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" -#include "llvm/DebugInfo/PDB/Native/RawError.h" - -using namespace llvm; -using namespace llvm::codeview; -using namespace llvm::pdb; - -C13DebugFragmentVisitor::C13DebugFragmentVisitor(PDBFile &F) : F(F) {} - -C13DebugFragmentVisitor::~C13DebugFragmentVisitor() {} - -Error C13DebugFragmentVisitor::visitUnknown( - codeview::DebugUnknownSubsectionRef &Fragment) { - return Error::success(); -} - -Error C13DebugFragmentVisitor::visitFileChecksums( - codeview::DebugChecksumsSubsectionRef &Checksums) { - assert(!this->Checksums.hasValue()); - this->Checksums = Checksums; - return Error::success(); -} - -Error C13DebugFragmentVisitor::visitLines( - codeview::DebugLinesSubsectionRef &Lines) { - this->Lines.push_back(Lines); - return Error::success(); -} - -Error C13DebugFragmentVisitor::visitInlineeLines( - codeview::DebugInlineeLinesSubsectionRef &Lines) { - this->InlineeLines.push_back(Lines); - return Error::success(); -} - -Error C13DebugFragmentVisitor::finished() { - if (!Checksums.hasValue()) { - assert(Lines.empty()); - return Error::success(); - } - if (auto EC = handleFileChecksums()) - return EC; - - if (auto EC = handleLines()) - return EC; - - if (auto EC = handleInlineeLines()) - return EC; - - return Error::success(); -} - -Expected -C13DebugFragmentVisitor::getNameFromStringTable(uint32_t Offset) { - auto ST = F.getStringTable(); - if (!ST) - return ST.takeError(); - - return ST->getStringForID(Offset); -} - -Expected -C13DebugFragmentVisitor::getNameFromChecksumsBuffer(uint32_t Offset) { - assert(Checksums.hasValue()); - - auto Array = Checksums->getArray(); - auto ChecksumIter = Array.at(Offset); - if (ChecksumIter == Array.end()) - return make_error(raw_error_code::invalid_format); - const auto &Entry = *ChecksumIter; - return getNameFromStringTable(Entry.FileNameOffset); -} diff --git a/tools/llvm-pdbdump/C13DebugFragmentVisitor.h b/tools/llvm-pdbdump/C13DebugFragmentVisitor.h deleted file mode 100644 index a12f282c4c5c..000000000000 --- a/tools/llvm-pdbdump/C13DebugFragmentVisitor.h +++ /dev/null @@ -1,60 +0,0 @@ -//===- C13DebugFragmentVisitor.h - Visitor for CodeView Info ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_C13DEBUGFRAGMENTVISITOR_H -#define LLVM_TOOLS_LLVMPDBDUMP_C13DEBUGFRAGMENTVISITOR_H - -#include "llvm/ADT/Optional.h" -#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" -#include "llvm/Support/Error.h" - -#include - -namespace llvm { - -namespace pdb { - -class PDBFile; - -class C13DebugFragmentVisitor : public codeview::DebugSubsectionVisitor { -public: - C13DebugFragmentVisitor(PDBFile &F); - ~C13DebugFragmentVisitor(); - - Error visitUnknown(codeview::DebugUnknownSubsectionRef &Fragment) final; - - Error - visitFileChecksums(codeview::DebugChecksumsSubsectionRef &Checksums) final; - - Error visitLines(codeview::DebugLinesSubsectionRef &Lines) final; - - Error - visitInlineeLines(codeview::DebugInlineeLinesSubsectionRef &Lines) final; - - Error finished() final; - -protected: - virtual Error handleFileChecksums() { return Error::success(); } - virtual Error handleLines() { return Error::success(); } - virtual Error handleInlineeLines() { return Error::success(); } - - Expected getNameFromStringTable(uint32_t Offset); - Expected getNameFromChecksumsBuffer(uint32_t Offset); - - Optional Checksums; - std::vector InlineeLines; - std::vector Lines; - - PDBFile &F; -}; -} -} - -#endif diff --git a/tools/llvm-pdbdump/CMakeLists.txt b/tools/llvm-pdbdump/CMakeLists.txt deleted file mode 100644 index a1f54a3bff6a..000000000000 --- a/tools/llvm-pdbdump/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -set(LLVM_LINK_COMPONENTS - DebugInfoCodeView - DebugInfoMSF - DebugInfoPDB - Object - ObjectYAML - Support - ) - -add_llvm_tool(llvm-pdbdump - Analyze.cpp - C13DebugFragmentVisitor.cpp - CompactTypeDumpVisitor.cpp - Diff.cpp - llvm-pdbdump.cpp - LinePrinter.cpp - LLVMOutputStyle.cpp - PdbYaml.cpp - PrettyBuiltinDumper.cpp - PrettyClassDefinitionDumper.cpp - PrettyClassLayoutGraphicalDumper.cpp - PrettyCompilandDumper.cpp - PrettyEnumDumper.cpp - PrettyExternalSymbolDumper.cpp - PrettyFunctionDumper.cpp - PrettyTypeDumper.cpp - PrettyTypedefDumper.cpp - PrettyVariableDumper.cpp - StreamUtil.cpp - YAMLOutputStyle.cpp - ) - -if(LLVM_USE_SANITIZE_COVERAGE) - add_subdirectory(fuzzer) -endif() diff --git a/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp b/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp deleted file mode 100644 index 6dd54e0dbec1..000000000000 --- a/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp +++ /dev/null @@ -1,59 +0,0 @@ -//===-- CompactTypeDumpVisitor.cpp - CodeView type info dumper --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "CompactTypeDumpVisitor.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" -#include "llvm/Support/FormatVariadic.h" -#include "llvm/Support/ScopedPrinter.h" - -using namespace llvm; -using namespace llvm::codeview; -using namespace llvm::pdb; - -static const EnumEntry LeafTypeNames[] = { -#define CV_TYPE(enum, val) {#enum, enum}, -#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" -}; - -static StringRef getLeafName(TypeLeafKind K) { - for (const auto &E : LeafTypeNames) { - if (E.Value == K) - return E.Name; - } - return StringRef(); -} - -CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types, - ScopedPrinter *W) - : CompactTypeDumpVisitor(Types, TypeIndex(TypeIndex::FirstNonSimpleIndex), - W) {} - -CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types, - TypeIndex FirstTI, - ScopedPrinter *W) - : W(W), TI(FirstTI), Offset(0), Types(Types) {} - -Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) { - return Error::success(); -} - -Error CompactTypeDumpVisitor::visitTypeEnd(CVType &Record) { - uint32_t I = TI.getIndex(); - StringRef Leaf = getLeafName(Record.Type); - StringRef Name = Types.getTypeName(TI); - W->printString( - llvm::formatv("Index: {0:x} ({1:N} bytes, offset {2:N}) {3} \"{4}\"", I, - Record.length(), Offset, Leaf, Name) - .str()); - - Offset += Record.length(); - TI.setIndex(TI.getIndex() + 1); - - return Error::success(); -} diff --git a/tools/llvm-pdbdump/CompactTypeDumpVisitor.h b/tools/llvm-pdbdump/CompactTypeDumpVisitor.h deleted file mode 100644 index 41ccea0c2e90..000000000000 --- a/tools/llvm-pdbdump/CompactTypeDumpVisitor.h +++ /dev/null @@ -1,49 +0,0 @@ -//===-- CompactTypeDumpVisitor.h - CodeView type info dumper ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_DEBUGINFO_CODEVIEW_COMPACTTYPEDUMPVISITOR_H -#define LLVM_DEBUGINFO_CODEVIEW_COMPACTTYPEDUMPVISITOR_H - -#include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" - -namespace llvm { -class ScopedPrinter; -namespace codeview { -class TypeCollection; -} - -namespace pdb { - -/// Dumper for CodeView type streams found in COFF object files and PDB files. -/// Dumps records on a single line, and ignores member records. -class CompactTypeDumpVisitor : public codeview::TypeVisitorCallbacks { -public: - CompactTypeDumpVisitor(codeview::TypeCollection &Types, ScopedPrinter *W); - CompactTypeDumpVisitor(codeview::TypeCollection &Types, - codeview::TypeIndex FirstTI, ScopedPrinter *W); - - /// Paired begin/end actions for all types. Receives all record data, - /// including the fixed-length record prefix. - Error visitTypeBegin(codeview::CVType &Record) override; - Error visitTypeEnd(codeview::CVType &Record) override; - -private: - ScopedPrinter *W; - - codeview::TypeIndex TI; - uint32_t Offset; - codeview::TypeCollection &Types; -}; - -} // end namespace pdb -} // end namespace llvm - -#endif diff --git a/tools/llvm-pdbdump/Diff.cpp b/tools/llvm-pdbdump/Diff.cpp deleted file mode 100644 index 418c2361ac32..000000000000 --- a/tools/llvm-pdbdump/Diff.cpp +++ /dev/null @@ -1,537 +0,0 @@ -//===- Diff.cpp - PDB diff utility ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "Diff.h" - -#include "StreamUtil.h" -#include "llvm-pdbdump.h" - -#include "llvm/DebugInfo/PDB/Native/Formatters.h" -#include "llvm/DebugInfo/PDB/Native/InfoStream.h" -#include "llvm/DebugInfo/PDB/Native/PDBFile.h" -#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" -#include "llvm/DebugInfo/PDB/Native/RawConstants.h" - -#include "llvm/Support/FormatAdapters.h" -#include "llvm/Support/FormatProviders.h" -#include "llvm/Support/FormatVariadic.h" - -using namespace llvm; -using namespace llvm::pdb; - -namespace llvm { -template <> struct format_provider { - static void format(const PdbRaw_FeatureSig &Sig, raw_ostream &Stream, - StringRef Style) { - switch (Sig) { - case PdbRaw_FeatureSig::MinimalDebugInfo: - Stream << "MinimalDebugInfo"; - break; - case PdbRaw_FeatureSig::NoTypeMerge: - Stream << "NoTypeMerge"; - break; - case PdbRaw_FeatureSig::VC110: - Stream << "VC110"; - break; - case PdbRaw_FeatureSig::VC140: - Stream << "VC140"; - break; - } - } -}; -} - -template using ValueOfRange = llvm::detail::ValueOfRange; - -template -static void set_differences(Range &&R1, Range &&R2, - SmallVectorImpl> *OnlyLeft, - SmallVectorImpl> *OnlyRight, - SmallVectorImpl> *Intersection, - Comp Comparator) { - - std::sort(R1.begin(), R1.end(), Comparator); - std::sort(R2.begin(), R2.end(), Comparator); - - if (OnlyLeft) { - OnlyLeft->reserve(R1.size()); - auto End = std::set_difference(R1.begin(), R1.end(), R2.begin(), R2.end(), - OnlyLeft->begin(), Comparator); - OnlyLeft->set_size(std::distance(OnlyLeft->begin(), End)); - } - if (OnlyRight) { - OnlyLeft->reserve(R2.size()); - auto End = std::set_difference(R2.begin(), R2.end(), R1.begin(), R1.end(), - OnlyRight->begin(), Comparator); - OnlyRight->set_size(std::distance(OnlyRight->begin(), End)); - } - if (Intersection) { - Intersection->reserve(std::min(R1.size(), R2.size())); - auto End = std::set_intersection(R1.begin(), R1.end(), R2.begin(), R2.end(), - Intersection->begin(), Comparator); - Intersection->set_size(std::distance(Intersection->begin(), End)); - } -} - -template -static void -set_differences(Range &&R1, Range &&R2, - SmallVectorImpl> *OnlyLeft, - SmallVectorImpl> *OnlyRight, - SmallVectorImpl> *Intersection = nullptr) { - std::less> Comp; - set_differences(std::forward(R1), std::forward(R2), OnlyLeft, - OnlyRight, Intersection, Comp); -} - -DiffStyle::DiffStyle(PDBFile &File1, PDBFile &File2) - : File1(File1), File2(File2) {} - -Error DiffStyle::dump() { - if (auto EC = diffSuperBlock()) - return EC; - - if (auto EC = diffFreePageMap()) - return EC; - - if (auto EC = diffStreamDirectory()) - return EC; - - if (auto EC = diffStringTable()) - return EC; - - if (auto EC = diffInfoStream()) - return EC; - - if (auto EC = diffDbiStream()) - return EC; - - if (auto EC = diffSectionContribs()) - return EC; - - if (auto EC = diffSectionMap()) - return EC; - - if (auto EC = diffFpoStream()) - return EC; - - if (auto EC = diffTpiStream(StreamTPI)) - return EC; - - if (auto EC = diffTpiStream(StreamIPI)) - return EC; - - if (auto EC = diffPublics()) - return EC; - - if (auto EC = diffGlobals()) - return EC; - - return Error::success(); -} - -template -static bool diffAndPrint(StringRef Label, PDBFile &File1, PDBFile &File2, T V1, - T V2) { - if (V1 == V2) { - outs() << formatv(" {0}: No differences detected!\n", Label); - return false; - } - - outs().indent(2) << Label << "\n"; - outs().indent(4) << formatv("{0}: {1}\n", File1.getFilePath(), V1); - outs().indent(4) << formatv("{0}: {1}\n", File2.getFilePath(), V2); - return true; -} - -template -static bool diffAndPrint(StringRef Label, PDBFile &File1, PDBFile &File2, - ArrayRef V1, ArrayRef V2) { - if (V1 == V2) { - outs() << formatv(" {0}: No differences detected!\n", Label); - return false; - } - - outs().indent(2) << Label << "\n"; - outs().indent(4) << formatv("{0}: {1}\n", File1.getFilePath(), - make_range(V1.begin(), V1.end())); - outs().indent(4) << formatv("{0}: {1}\n", File2.getFilePath(), - make_range(V2.begin(), V2.end())); - return true; -} - -template -static bool printSymmetricDifferences(PDBFile &File1, PDBFile &File2, - T &&OnlyRange1, T &&OnlyRange2, - StringRef Label) { - bool HasDiff = false; - if (!OnlyRange1.empty()) { - HasDiff = true; - outs() << formatv(" {0} {1}(s) only in ({2})\n", OnlyRange1.size(), Label, - File1.getFilePath()); - for (const auto &Item : OnlyRange1) - outs() << formatv(" {0}\n", Label, Item); - } - if (!OnlyRange2.empty()) { - HasDiff = true; - outs() << formatv(" {0} {1}(s) only in ({2})\n", OnlyRange2.size(), - File2.getFilePath()); - for (const auto &Item : OnlyRange2) - outs() << formatv(" {0}\n", Item); - } - return HasDiff; -} - -Error DiffStyle::diffSuperBlock() { - outs() << "MSF Super Block: Searching for differences...\n"; - bool Diffs = false; - - Diffs |= diffAndPrint("Block Size", File1, File2, File1.getBlockSize(), - File2.getBlockSize()); - Diffs |= diffAndPrint("Block Count", File1, File2, File1.getBlockCount(), - File2.getBlockCount()); - Diffs |= diffAndPrint("Unknown 1", File1, File2, File1.getUnknown1(), - File2.getUnknown1()); - - if (opts::diff::Pedantic) { - Diffs |= diffAndPrint("Free Block Map", File1, File2, - File1.getFreeBlockMapBlock(), - File2.getFreeBlockMapBlock()); - Diffs |= diffAndPrint("Directory Size", File1, File2, - File1.getNumDirectoryBytes(), - File2.getNumDirectoryBytes()); - Diffs |= diffAndPrint("Block Map Addr", File1, File2, - File1.getBlockMapOffset(), File2.getBlockMapOffset()); - } - if (!Diffs) - outs() << "MSF Super Block: No differences detected...\n"; - return Error::success(); -} - -Error DiffStyle::diffStreamDirectory() { - SmallVector P; - SmallVector Q; - discoverStreamPurposes(File1, P); - discoverStreamPurposes(File2, Q); - outs() << "Stream Directory: Searching for differences...\n"; - - bool HasDifferences = false; - if (opts::diff::Pedantic) { - size_t Min = std::min(P.size(), Q.size()); - for (size_t I = 0; I < Min; ++I) { - StringRef Names[] = {P[I], Q[I]}; - uint32_t Sizes[] = {File1.getStreamByteSize(I), - File2.getStreamByteSize(I)}; - bool NamesDiffer = Names[0] != Names[1]; - bool SizesDiffer = Sizes[0] != Sizes[1]; - if (NamesDiffer) { - HasDifferences = true; - outs().indent(2) << formatv("Stream {0} - {1}: {2}, {3}: {4}\n", I, - File1.getFilePath(), Names[0], - File2.getFilePath(), Names[1]); - continue; - } - if (SizesDiffer) { - HasDifferences = true; - outs().indent(2) << formatv( - "Stream {0} ({1}): {2}: {3} bytes, {4}: {5} bytes\n", I, Names[0], - File1.getFilePath(), Sizes[0], File2.getFilePath(), Sizes[1]); - continue; - } - } - - ArrayRef MaxNames = (P.size() > Q.size() ? P : Q); - size_t Max = std::max(P.size(), Q.size()); - PDBFile &MaxFile = (P.size() > Q.size() ? File1 : File2); - StringRef MinFileName = - (P.size() < Q.size() ? File1.getFilePath() : File2.getFilePath()); - for (size_t I = Min; I < Max; ++I) { - HasDifferences = true; - StringRef StreamName = MaxNames[I]; - - outs().indent(2) << formatv( - "Stream {0} - {1}: , {2}: Index {3}, {4} bytes\n", - StreamName, MinFileName, MaxFile.getFilePath(), I, - MaxFile.getStreamByteSize(I)); - } - if (!HasDifferences) - outs() << "Stream Directory: No differences detected...\n"; - } else { - auto PI = to_vector<32>(enumerate(P)); - auto QI = to_vector<32>(enumerate(Q)); - - typedef decltype(PI) ContainerType; - typedef typename ContainerType::value_type value_type; - - auto Comparator = [](const value_type &I1, const value_type &I2) { - return I1.value() < I2.value(); - }; - - decltype(PI) OnlyP; - decltype(QI) OnlyQ; - decltype(PI) Common; - - set_differences(PI, QI, &OnlyP, &OnlyQ, &Common, Comparator); - - if (!OnlyP.empty()) { - HasDifferences = true; - outs().indent(2) << formatv("{0} Stream(s) only in ({1})\n", OnlyP.size(), - File1.getFilePath()); - for (auto &Item : OnlyP) { - outs().indent(4) << formatv("Stream {0} - {1}\n", Item.index(), - Item.value()); - } - } - - if (!OnlyQ.empty()) { - HasDifferences = true; - outs().indent(2) << formatv("{0} Streams(s) only in ({1})\n", - OnlyQ.size(), File2.getFilePath()); - for (auto &Item : OnlyQ) { - outs().indent(4) << formatv("Stream {0} - {1}\n", Item.index(), - Item.value()); - } - } - if (!Common.empty()) { - outs().indent(2) << formatv("Found {0} common streams. Searching for " - "intra-stream differences.\n", - Common.size()); - bool HasCommonDifferences = false; - for (const auto &Left : Common) { - // Left was copied from the first range so its index refers to a stream - // index in the first file. Find the corresponding stream index in the - // second file. - auto Range = - std::equal_range(QI.begin(), QI.end(), Left, - [](const value_type &L, const value_type &R) { - return L.value() < R.value(); - }); - const auto &Right = *Range.first; - assert(Left.value() == Right.value()); - uint32_t LeftSize = File1.getStreamByteSize(Left.index()); - uint32_t RightSize = File2.getStreamByteSize(Right.index()); - if (LeftSize != RightSize) { - HasDifferences = true; - HasCommonDifferences = true; - outs().indent(4) << formatv("{0} ({1}: {2} bytes, {3}: {4} bytes)\n", - Left.value(), File1.getFilePath(), - LeftSize, File2.getFilePath(), RightSize); - } - } - if (!HasCommonDifferences) - outs().indent(2) << "Common Streams: No differences detected!\n"; - } - if (!HasDifferences) - outs() << "Stream Directory: No differences detected!\n"; - } - - return Error::success(); -} - -Error DiffStyle::diffStringTable() { - auto ExpectedST1 = File1.getStringTable(); - auto ExpectedST2 = File2.getStringTable(); - outs() << "String Table: Searching for differences...\n"; - bool Has1 = !!ExpectedST1; - bool Has2 = !!ExpectedST2; - if (!(Has1 && Has2)) { - // If one has a string table and the other doesn't, we can print less - // output. - if (Has1 != Has2) { - if (Has1) { - outs() << formatv(" {0}: ({1} strings)\n", File1.getFilePath(), - ExpectedST1->getNameCount()); - outs() << formatv(" {0}: (string table not present)\n", - File2.getFilePath()); - } else { - outs() << formatv(" {0}: (string table not present)\n", - File1.getFilePath()); - outs() << formatv(" {0}: ({1})\n", File2.getFilePath(), - ExpectedST2->getNameCount()); - } - } - consumeError(ExpectedST1.takeError()); - consumeError(ExpectedST2.takeError()); - return Error::success(); - } - - bool HasDiff = false; - auto &ST1 = *ExpectedST1; - auto &ST2 = *ExpectedST2; - - if (ST1.getByteSize() != ST2.getByteSize()) { - outs() << " Stream Size\n"; - outs() << formatv(" {0} - {1} byte(s)\n", File1.getFilePath(), - ST1.getByteSize()); - outs() << formatv(" {0} - {1} byte(s)\n", File2.getFilePath(), - ST2.getByteSize()); - outs() << formatv(" Difference: {0} bytes\n", - AbsoluteDifference(ST1.getByteSize(), ST2.getByteSize())); - HasDiff = true; - } - HasDiff |= diffAndPrint("Hash Version", File1, File2, ST1.getHashVersion(), - ST1.getHashVersion()); - HasDiff |= diffAndPrint("Signature", File1, File2, ST1.getSignature(), - ST1.getSignature()); - - // Both have a valid string table, dive in and compare individual strings. - - auto IdList1 = ST1.name_ids(); - auto IdList2 = ST2.name_ids(); - if (opts::diff::Pedantic) { - // In pedantic mode, we compare index by index (i.e. the strings are in the - // same order - // in both tables. - uint32_t Max = std::max(IdList1.size(), IdList2.size()); - for (uint32_t I = 0; I < Max; ++I) { - Optional Id1, Id2; - StringRef S1, S2; - if (I < IdList1.size()) { - Id1 = IdList1[I]; - if (auto Result = ST1.getStringForID(*Id1)) - S1 = *Result; - else - return Result.takeError(); - } - if (I < IdList2.size()) { - Id2 = IdList2[I]; - if (auto Result = ST2.getStringForID(*Id2)) - S2 = *Result; - else - return Result.takeError(); - } - if (Id1 == Id2 && S1 == S2) - continue; - - std::string OutId1 = - Id1 ? formatv("{0}", *Id1).str() : "(index not present)"; - std::string OutId2 = - Id2 ? formatv("{0}", *Id2).str() : "(index not present)"; - outs() << formatv(" String {0}\n", I); - outs() << formatv(" {0}: Hash - {1}, Value - {2}\n", - File1.getFilePath(), OutId1, S1); - outs() << formatv(" {0}: Hash - {1}, Value - {2}\n", - File2.getFilePath(), OutId2, S2); - HasDiff = true; - } - } else { - std::vector Strings1, Strings2; - Strings1.reserve(IdList1.size()); - Strings2.reserve(IdList2.size()); - for (auto ID : IdList1) { - auto S = ST1.getStringForID(ID); - if (!S) - return S.takeError(); - Strings1.push_back(*S); - } - for (auto ID : IdList2) { - auto S = ST2.getStringForID(ID); - if (!S) - return S.takeError(); - Strings2.push_back(*S); - } - - SmallVector OnlyP; - SmallVector OnlyQ; - auto End1 = std::remove(Strings1.begin(), Strings1.end(), ""); - auto End2 = std::remove(Strings2.begin(), Strings2.end(), ""); - uint32_t Empty1 = std::distance(End1, Strings1.end()); - uint32_t Empty2 = std::distance(End2, Strings2.end()); - Strings1.erase(End1, Strings1.end()); - Strings2.erase(End2, Strings2.end()); - set_differences(Strings1, Strings2, &OnlyP, &OnlyQ); - printSymmetricDifferences(File1, File2, OnlyP, OnlyQ, "String"); - - if (Empty1 != Empty2) { - PDBFile &MoreF = (Empty1 > Empty2) ? File1 : File2; - PDBFile &LessF = (Empty1 < Empty2) ? File1 : File2; - uint32_t Difference = AbsoluteDifference(Empty1, Empty2); - outs() << formatv(" {0} had {1} more empty strings than {2}\n", - MoreF.getFilePath(), Difference, LessF.getFilePath()); - } - } - if (!HasDiff) - outs() << "String Table: No differences detected!\n"; - return Error::success(); -} - -Error DiffStyle::diffFreePageMap() { return Error::success(); } - -Error DiffStyle::diffInfoStream() { - auto ExpectedInfo1 = File1.getPDBInfoStream(); - auto ExpectedInfo2 = File2.getPDBInfoStream(); - - outs() << "PDB Stream: Searching for differences...\n"; - bool Has1 = !!ExpectedInfo1; - bool Has2 = !!ExpectedInfo2; - if (!(Has1 && Has2)) { - if (Has1 != Has2) - outs() << formatv("{0} does not have a PDB Stream!\n", - Has1 ? File1.getFilePath() : File2.getFilePath()); - consumeError(ExpectedInfo2.takeError()); - consumeError(ExpectedInfo2.takeError()); - return Error::success(); - } - - bool HasDiff = false; - auto &IS1 = *ExpectedInfo1; - auto &IS2 = *ExpectedInfo2; - if (IS1.getStreamSize() != IS2.getStreamSize()) { - outs() << " Stream Size\n"; - outs() << formatv(" {0} - {1} byte(s)\n", File1.getFilePath(), - IS1.getStreamSize()); - outs() << formatv(" {0} - {1} byte(s)\n", File2.getFilePath(), - IS2.getStreamSize()); - outs() << formatv( - " Difference: {0} bytes\n", - AbsoluteDifference(IS1.getStreamSize(), IS2.getStreamSize())); - HasDiff = true; - } - HasDiff |= diffAndPrint("Age", File1, File2, IS1.getAge(), IS2.getAge()); - HasDiff |= diffAndPrint("Guid", File1, File2, IS1.getGuid(), IS2.getGuid()); - HasDiff |= diffAndPrint("Signature", File1, File2, IS1.getSignature(), - IS2.getSignature()); - HasDiff |= - diffAndPrint("Version", File1, File2, IS1.getVersion(), IS2.getVersion()); - HasDiff |= diffAndPrint("Features", File1, File2, IS1.getFeatureSignatures(), - IS2.getFeatureSignatures()); - HasDiff |= diffAndPrint("Named Stream Byte Size", File1, File2, - IS1.getNamedStreamMapByteSize(), - IS2.getNamedStreamMapByteSize()); - SmallVector NS1; - SmallVector NS2; - for (const auto &X : IS1.getNamedStreams().entries()) - NS1.push_back(X.getKey()); - for (const auto &X : IS2.getNamedStreams().entries()) - NS2.push_back(X.getKey()); - SmallVector OnlyP; - SmallVector OnlyQ; - set_differences(NS1, NS2, &OnlyP, &OnlyQ); - printSymmetricDifferences(File1, File2, OnlyP, OnlyQ, "Named Streams"); - if (!HasDiff) - outs() << "PDB Stream: No differences detected!\n"; - - return Error::success(); -} - -Error DiffStyle::diffDbiStream() { return Error::success(); } - -Error DiffStyle::diffSectionContribs() { return Error::success(); } - -Error DiffStyle::diffSectionMap() { return Error::success(); } - -Error DiffStyle::diffFpoStream() { return Error::success(); } - -Error DiffStyle::diffTpiStream(int Index) { return Error::success(); } - -Error DiffStyle::diffModuleInfoStream(int Index) { return Error::success(); } - -Error DiffStyle::diffPublics() { return Error::success(); } - -Error DiffStyle::diffGlobals() { return Error::success(); } diff --git a/tools/llvm-pdbdump/Diff.h b/tools/llvm-pdbdump/Diff.h deleted file mode 100644 index 6037576e21bb..000000000000 --- a/tools/llvm-pdbdump/Diff.h +++ /dev/null @@ -1,45 +0,0 @@ -//===- Diff.h - PDB diff utility --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_DIFF_H -#define LLVM_TOOLS_LLVMPDBDUMP_DIFF_H - -#include "OutputStyle.h" - -namespace llvm { -namespace pdb { -class PDBFile; -class DiffStyle : public OutputStyle { -public: - explicit DiffStyle(PDBFile &File1, PDBFile &File2); - - Error dump() override; - -private: - Error diffSuperBlock(); - Error diffStreamDirectory(); - Error diffStringTable(); - Error diffFreePageMap(); - Error diffInfoStream(); - Error diffDbiStream(); - Error diffSectionContribs(); - Error diffSectionMap(); - Error diffFpoStream(); - Error diffTpiStream(int Index); - Error diffModuleInfoStream(int Index); - Error diffPublics(); - Error diffGlobals(); - - PDBFile &File1; - PDBFile &File2; -}; -} -} - -#endif diff --git a/tools/llvm-pdbdump/LLVMBuild.txt b/tools/llvm-pdbdump/LLVMBuild.txt deleted file mode 100644 index 4043e13ceaec..000000000000 --- a/tools/llvm-pdbdump/LLVMBuild.txt +++ /dev/null @@ -1,23 +0,0 @@ -;===- ./tools/llvm-pdbdump/LLVMBuild.txt -----------------------*- Conf -*--===; -; -; The LLVM Compiler Infrastructure -; -; This file is distributed under the University of Illinois Open Source -; License. See LICENSE.TXT for details. -; -;===------------------------------------------------------------------------===; -; -; This is an LLVMBuild description file for the components in this subdirectory. -; -; For more information on the LLVMBuild system, please see: -; -; http://llvm.org/docs/LLVMBuild.html -; -;===------------------------------------------------------------------------===; - -[component_0] -type = Tool -name = llvm-pdbdump -parent = Tools -required_libraries = DebugInfoMSF DebugInfoPDB - diff --git a/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/tools/llvm-pdbdump/LLVMOutputStyle.cpp deleted file mode 100644 index 31c342cd0f5a..000000000000 --- a/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ /dev/null @@ -1,1036 +0,0 @@ -//===- LLVMOutputStyle.cpp ------------------------------------ *- C++ --*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "LLVMOutputStyle.h" - -#include "C13DebugFragmentVisitor.h" -#include "CompactTypeDumpVisitor.h" -#include "StreamUtil.h" -#include "llvm-pdbdump.h" - -#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" -#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h" -#include "llvm/DebugInfo/CodeView/EnumTables.h" -#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" -#include "llvm/DebugInfo/CodeView/Line.h" -#include "llvm/DebugInfo/CodeView/SymbolDumper.h" -#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" -#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" -#include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" -#include "llvm/DebugInfo/PDB/Native/DbiStream.h" -#include "llvm/DebugInfo/PDB/Native/EnumTables.h" -#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" -#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h" -#include "llvm/DebugInfo/PDB/Native/InfoStream.h" -#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" -#include "llvm/DebugInfo/PDB/Native/PDBFile.h" -#include "llvm/DebugInfo/PDB/Native/PublicsStream.h" -#include "llvm/DebugInfo/PDB/Native/RawError.h" -#include "llvm/DebugInfo/PDB/Native/TpiHashing.h" -#include "llvm/DebugInfo/PDB/Native/TpiStream.h" -#include "llvm/DebugInfo/PDB/PDBExtras.h" -#include "llvm/Object/COFF.h" -#include "llvm/Support/BinaryStreamReader.h" -#include "llvm/Support/FormatVariadic.h" - -#include - -using namespace llvm; -using namespace llvm::codeview; -using namespace llvm::msf; -using namespace llvm::pdb; - -namespace { -struct PageStats { - explicit PageStats(const BitVector &FreePages) - : Upm(FreePages), ActualUsedPages(FreePages.size()), - MultiUsePages(FreePages.size()), UseAfterFreePages(FreePages.size()) { - const_cast(Upm).flip(); - // To calculate orphaned pages, we start with the set of pages that the - // MSF thinks are used. Each time we find one that actually *is* used, - // we unset it. Whichever bits remain set at the end are orphaned. - OrphanedPages = Upm; - } - - // The inverse of the MSF File's copy of the Fpm. The basis for which we - // determine the allocation status of each page. - const BitVector Upm; - - // Pages which are marked as used in the FPM and are used at least once. - BitVector ActualUsedPages; - - // Pages which are marked as used in the FPM but are used more than once. - BitVector MultiUsePages; - - // Pages which are marked as used in the FPM but are not used at all. - BitVector OrphanedPages; - - // Pages which are marked free in the FPM but are used. - BitVector UseAfterFreePages; -}; - -class C13RawVisitor : public C13DebugFragmentVisitor { -public: - C13RawVisitor(ScopedPrinter &P, PDBFile &F, LazyRandomTypeCollection &IPI) - : C13DebugFragmentVisitor(F), P(P), IPI(IPI) {} - - Error handleLines() override { - if (Lines.empty()) - return Error::success(); - - DictScope DD(P, "Lines"); - - for (const auto &Fragment : Lines) { - DictScope DDD(P, "Block"); - P.printNumber("RelocSegment", Fragment.header()->RelocSegment); - P.printNumber("RelocOffset", Fragment.header()->RelocOffset); - P.printNumber("CodeSize", Fragment.header()->CodeSize); - P.printBoolean("HasColumns", Fragment.hasColumnInfo()); - - for (const auto &L : Fragment) { - DictScope DDDD(P, "Lines"); - - if (auto EC = printFileName("FileName", L.NameIndex)) - return EC; - - for (const auto &N : L.LineNumbers) { - DictScope DDD(P, "Line"); - LineInfo LI(N.Flags); - P.printNumber("Offset", N.Offset); - if (LI.isAlwaysStepInto()) - P.printString("StepInto", StringRef("Always")); - else if (LI.isNeverStepInto()) - P.printString("StepInto", StringRef("Never")); - else - P.printNumber("LineNumberStart", LI.getStartLine()); - P.printNumber("EndDelta", LI.getLineDelta()); - P.printBoolean("IsStatement", LI.isStatement()); - } - for (const auto &C : L.Columns) { - DictScope DDD(P, "Column"); - P.printNumber("Start", C.StartColumn); - P.printNumber("End", C.EndColumn); - } - } - } - - return Error::success(); - } - - Error handleFileChecksums() override { - if (!Checksums.hasValue()) - return Error::success(); - - DictScope DD(P, "FileChecksums"); - for (const auto &CS : *Checksums) { - DictScope DDD(P, "Checksum"); - if (auto Result = getNameFromStringTable(CS.FileNameOffset)) - P.printString("FileName", *Result); - else - return Result.takeError(); - P.printEnum("Kind", uint8_t(CS.Kind), getFileChecksumNames()); - P.printBinaryBlock("Checksum", CS.Checksum); - } - return Error::success(); - } - - Error handleInlineeLines() override { - if (InlineeLines.empty()) - return Error::success(); - - DictScope D(P, "InlineeLines"); - for (const auto &IL : InlineeLines) { - P.printBoolean("HasExtraFiles", IL.hasExtraFiles()); - ListScope LS(P, "Lines"); - for (const auto &L : IL) { - DictScope DDD(P, "Inlinee"); - if (auto EC = printFileName("FileName", L.Header->FileID)) - return EC; - - if (auto EC = dumpTypeRecord("Function", L.Header->Inlinee)) - return EC; - P.printNumber("SourceLine", L.Header->SourceLineNum); - if (IL.hasExtraFiles()) { - ListScope DDDD(P, "ExtraFiles"); - for (const auto &EF : L.ExtraFiles) { - if (auto EC = printFileName("File", EF)) - return EC; - } - } - } - } - return Error::success(); - } - -private: - Error dumpTypeRecord(StringRef Label, TypeIndex Index) { - CompactTypeDumpVisitor CTDV(IPI, Index, &P); - DictScope D(P, Label); - if (IPI.contains(Index)) { - CVType Type = IPI.getType(Index); - if (auto EC = codeview::visitTypeRecord(Type, CTDV)) - return EC; - } else { - P.printString( - llvm::formatv("Index: {0:x} (unknown function)", Index.getIndex()) - .str()); - } - return Error::success(); - } - Error printFileName(StringRef Label, uint32_t Offset) { - if (auto Result = getNameFromChecksumsBuffer(Offset)) { - P.printString(Label, *Result); - return Error::success(); - } else - return Result.takeError(); - } - - ScopedPrinter &P; - LazyRandomTypeCollection &IPI; -}; -} - -static void recordKnownUsedPage(PageStats &Stats, uint32_t UsedIndex) { - if (Stats.Upm.test(UsedIndex)) { - if (Stats.ActualUsedPages.test(UsedIndex)) - Stats.MultiUsePages.set(UsedIndex); - Stats.ActualUsedPages.set(UsedIndex); - Stats.OrphanedPages.reset(UsedIndex); - } else { - // The MSF doesn't think this page is used, but it is. - Stats.UseAfterFreePages.set(UsedIndex); - } -} - -static void printSectionOffset(llvm::raw_ostream &OS, - const SectionOffset &Off) { - OS << Off.Off << ", " << Off.Isect; -} - -LLVMOutputStyle::LLVMOutputStyle(PDBFile &File) : File(File), P(outs()) {} - -Error LLVMOutputStyle::dump() { - if (auto EC = dumpFileHeaders()) - return EC; - - if (auto EC = dumpStreamSummary()) - return EC; - - if (auto EC = dumpFreePageMap()) - return EC; - - if (auto EC = dumpStreamBlocks()) - return EC; - - if (auto EC = dumpBlockRanges()) - return EC; - - if (auto EC = dumpStreamBytes()) - return EC; - - if (auto EC = dumpStringTable()) - return EC; - - if (auto EC = dumpInfoStream()) - return EC; - - if (auto EC = dumpTpiStream(StreamTPI)) - return EC; - - if (auto EC = dumpTpiStream(StreamIPI)) - return EC; - - if (auto EC = dumpDbiStream()) - return EC; - - if (auto EC = dumpSectionContribs()) - return EC; - - if (auto EC = dumpSectionMap()) - return EC; - - if (auto EC = dumpGlobalsStream()) - return EC; - - if (auto EC = dumpPublicsStream()) - return EC; - - if (auto EC = dumpSectionHeaders()) - return EC; - - if (auto EC = dumpFpoStream()) - return EC; - - flush(); - - return Error::success(); -} - -Error LLVMOutputStyle::dumpFileHeaders() { - if (!opts::raw::DumpHeaders) - return Error::success(); - - DictScope D(P, "FileHeaders"); - P.printNumber("BlockSize", File.getBlockSize()); - P.printNumber("FreeBlockMap", File.getFreeBlockMapBlock()); - P.printNumber("NumBlocks", File.getBlockCount()); - P.printNumber("NumDirectoryBytes", File.getNumDirectoryBytes()); - P.printNumber("Unknown1", File.getUnknown1()); - P.printNumber("BlockMapAddr", File.getBlockMapIndex()); - P.printNumber("NumDirectoryBlocks", File.getNumDirectoryBlocks()); - - // The directory is not contiguous. Instead, the block map contains a - // contiguous list of block numbers whose contents, when concatenated in - // order, make up the directory. - P.printList("DirectoryBlocks", File.getDirectoryBlockArray()); - P.printNumber("NumStreams", File.getNumStreams()); - return Error::success(); -} - -Error LLVMOutputStyle::dumpStreamSummary() { - if (!opts::raw::DumpStreamSummary) - return Error::success(); - - if (StreamPurposes.empty()) - discoverStreamPurposes(File, StreamPurposes); - - uint32_t StreamCount = File.getNumStreams(); - - ListScope L(P, "Streams"); - for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) { - std::string Label("Stream "); - Label += to_string(StreamIdx); - - std::string Value = "[" + StreamPurposes[StreamIdx] + "] ("; - Value += to_string(File.getStreamByteSize(StreamIdx)); - Value += " bytes)"; - - P.printString(Label, Value); - } - - P.flush(); - return Error::success(); -} - -Error LLVMOutputStyle::dumpFreePageMap() { - if (!opts::raw::DumpPageStats) - return Error::success(); - - // Start with used pages instead of free pages because - // the number of free pages is far larger than used pages. - BitVector FPM = File.getMsfLayout().FreePageMap; - - PageStats PS(FPM); - - recordKnownUsedPage(PS, 0); // MSF Super Block - - uint32_t BlocksPerSection = msf::getFpmIntervalLength(File.getMsfLayout()); - uint32_t NumSections = msf::getNumFpmIntervals(File.getMsfLayout()); - for (uint32_t I = 0; I < NumSections; ++I) { - uint32_t Fpm0 = 1 + BlocksPerSection * I; - // 2 Fpm blocks spaced at `getBlockSize()` block intervals - recordKnownUsedPage(PS, Fpm0); - recordKnownUsedPage(PS, Fpm0 + 1); - } - - recordKnownUsedPage(PS, File.getBlockMapIndex()); // Stream Table - - for (auto DB : File.getDirectoryBlockArray()) - recordKnownUsedPage(PS, DB); - - // Record pages used by streams. Note that pages for stream 0 - // are considered being unused because that's what MSVC tools do. - // Stream 0 doesn't contain actual data, so it makes some sense, - // though it's a bit confusing to us. - for (auto &SE : File.getStreamMap().drop_front(1)) - for (auto &S : SE) - recordKnownUsedPage(PS, S); - - dumpBitVector("Msf Free Pages", FPM); - dumpBitVector("Orphaned Pages", PS.OrphanedPages); - dumpBitVector("Multiply Used Pages", PS.MultiUsePages); - dumpBitVector("Use After Free Pages", PS.UseAfterFreePages); - return Error::success(); -} - -void LLVMOutputStyle::dumpBitVector(StringRef Name, const BitVector &V) { - std::vector Vec; - for (uint32_t I = 0, E = V.size(); I != E; ++I) - if (V[I]) - Vec.push_back(I); - P.printList(Name, Vec); -} - -Error LLVMOutputStyle::dumpGlobalsStream() { - if (!opts::raw::DumpGlobals) - return Error::success(); - if (!File.hasPDBGlobalsStream()) { - P.printString("Globals Stream not present"); - return Error::success(); - } - - auto Globals = File.getPDBGlobalsStream(); - if (!Globals) - return Globals.takeError(); - DictScope D(P, "Globals Stream"); - - auto Dbi = File.getPDBDbiStream(); - if (!Dbi) - return Dbi.takeError(); - - P.printNumber("Stream number", Dbi->getGlobalSymbolStreamIndex()); - P.printNumber("Number of buckets", Globals->getNumBuckets()); - P.printList("Hash Buckets", Globals->getHashBuckets()); - - return Error::success(); -} - -Error LLVMOutputStyle::dumpStreamBlocks() { - if (!opts::raw::DumpStreamBlocks) - return Error::success(); - - ListScope L(P, "StreamBlocks"); - uint32_t StreamCount = File.getNumStreams(); - for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) { - std::string Name("Stream "); - Name += to_string(StreamIdx); - auto StreamBlocks = File.getStreamBlockList(StreamIdx); - P.printList(Name, StreamBlocks); - } - return Error::success(); -} - -Error LLVMOutputStyle::dumpBlockRanges() { - if (!opts::raw::DumpBlockRange.hasValue()) - return Error::success(); - auto &R = *opts::raw::DumpBlockRange; - uint32_t Max = R.Max.getValueOr(R.Min); - - if (Max < R.Min) - return make_error( - "Invalid block range specified. Max < Min", - std::make_error_code(std::errc::bad_address)); - if (Max >= File.getBlockCount()) - return make_error( - "Invalid block range specified. Requested block out of bounds", - std::make_error_code(std::errc::bad_address)); - - DictScope D(P, "Block Data"); - for (uint32_t I = R.Min; I <= Max; ++I) { - auto ExpectedData = File.getBlockData(I, File.getBlockSize()); - if (!ExpectedData) - return ExpectedData.takeError(); - std::string Label; - llvm::raw_string_ostream S(Label); - S << "Block " << I; - S.flush(); - P.printBinaryBlock(Label, *ExpectedData); - } - - return Error::success(); -} - -static Error parseStreamSpec(StringRef Str, uint32_t &SI, uint32_t &Offset, - uint32_t &Size) { - if (Str.consumeInteger(0, SI)) - return make_error(raw_error_code::invalid_format, - "Invalid Stream Specification"); - if (Str.consume_front(":")) { - if (Str.consumeInteger(0, Offset)) - return make_error(raw_error_code::invalid_format, - "Invalid Stream Specification"); - } - if (Str.consume_front("@")) { - if (Str.consumeInteger(0, Size)) - return make_error(raw_error_code::invalid_format, - "Invalid Stream Specification"); - } - if (!Str.empty()) - return make_error(raw_error_code::invalid_format, - "Invalid Stream Specification"); - return Error::success(); -} - -Error LLVMOutputStyle::dumpStreamBytes() { - if (opts::raw::DumpStreamData.empty()) - return Error::success(); - - if (StreamPurposes.empty()) - discoverStreamPurposes(File, StreamPurposes); - - DictScope D(P, "Stream Data"); - for (auto &Str : opts::raw::DumpStreamData) { - uint32_t SI = 0; - uint32_t Begin = 0; - uint32_t Size = 0; - uint32_t End = 0; - - if (auto EC = parseStreamSpec(Str, SI, Begin, Size)) - return EC; - - if (SI >= File.getNumStreams()) - return make_error(raw_error_code::no_stream); - - auto S = MappedBlockStream::createIndexedStream( - File.getMsfLayout(), File.getMsfBuffer(), SI, File.getAllocator()); - if (!S) - continue; - DictScope DD(P, "Stream"); - if (Size == 0) - End = S->getLength(); - else { - End = Begin + Size; - if (End >= S->getLength()) - return make_error(raw_error_code::index_out_of_bounds, - "Stream is not long enough!"); - } - - P.printNumber("Index", SI); - P.printString("Type", StreamPurposes[SI]); - P.printNumber("Size", S->getLength()); - auto Blocks = File.getMsfLayout().StreamMap[SI]; - P.printList("Blocks", Blocks); - - BinaryStreamReader R(*S); - ArrayRef StreamData; - if (auto EC = R.readBytes(StreamData, S->getLength())) - return EC; - Size = End - Begin; - StreamData = StreamData.slice(Begin, Size); - P.printBinaryBlock("Data", StreamData, Begin); - } - return Error::success(); -} - -Error LLVMOutputStyle::dumpStringTable() { - if (!opts::raw::DumpStringTable) - return Error::success(); - - auto IS = File.getStringTable(); - if (!IS) - return IS.takeError(); - - DictScope D(P, "String Table"); - for (uint32_t I : IS->name_ids()) { - auto ES = IS->getStringForID(I); - if (!ES) - return ES.takeError(); - - if (ES->empty()) - continue; - llvm::SmallString<32> Str; - Str.append("'"); - Str.append(*ES); - Str.append("'"); - P.printString(Str); - } - return Error::success(); -} - -Error LLVMOutputStyle::dumpInfoStream() { - if (!opts::raw::DumpHeaders) - return Error::success(); - if (!File.hasPDBInfoStream()) { - P.printString("PDB Stream not present"); - return Error::success(); - } - auto IS = File.getPDBInfoStream(); - if (!IS) - return IS.takeError(); - - DictScope D(P, "PDB Stream"); - P.printNumber("Version", IS->getVersion()); - P.printHex("Signature", IS->getSignature()); - P.printNumber("Age", IS->getAge()); - P.printObject("Guid", IS->getGuid()); - P.printHex("Features", IS->getFeatures()); - { - DictScope DD(P, "Named Streams"); - for (const auto &S : IS->getNamedStreams().entries()) - P.printObject(S.getKey(), S.getValue()); - } - return Error::success(); -} - -namespace { -class RecordBytesVisitor : public TypeVisitorCallbacks { -public: - explicit RecordBytesVisitor(ScopedPrinter &P) : P(P) {} - - Error visitTypeEnd(CVType &Record) override { - P.printBinaryBlock("Bytes", Record.content()); - return Error::success(); - } - -private: - ScopedPrinter &P; -}; -} - -Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { - assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI); - - bool DumpRecordBytes = false; - bool DumpRecords = false; - bool DumpTpiHash = false; - StringRef Label; - StringRef VerLabel; - if (StreamIdx == StreamTPI) { - if (!File.hasPDBTpiStream()) { - P.printString("Type Info Stream (TPI) not present"); - return Error::success(); - } - DumpRecordBytes = opts::raw::DumpTpiRecordBytes; - DumpRecords = opts::raw::DumpTpiRecords; - DumpTpiHash = opts::raw::DumpTpiHash; - Label = "Type Info Stream (TPI)"; - VerLabel = "TPI Version"; - } else if (StreamIdx == StreamIPI) { - if (!File.hasPDBIpiStream()) { - P.printString("Type Info Stream (IPI) not present"); - return Error::success(); - } - DumpRecordBytes = opts::raw::DumpIpiRecordBytes; - DumpRecords = opts::raw::DumpIpiRecords; - Label = "Type Info Stream (IPI)"; - VerLabel = "IPI Version"; - } - - auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream() - : File.getPDBIpiStream(); - if (!Tpi) - return Tpi.takeError(); - - auto ExpectedTypes = initializeTypeDatabase(StreamIdx); - if (!ExpectedTypes) - return ExpectedTypes.takeError(); - auto &Types = *ExpectedTypes; - - if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash) - return Error::success(); - - std::unique_ptr StreamScope; - std::unique_ptr RecordScope; - - StreamScope = llvm::make_unique(P, Label); - P.printNumber(VerLabel, Tpi->getTpiVersion()); - P.printNumber("Record count", Tpi->getNumTypeRecords()); - - std::vector> Visitors; - - // If we're in dump mode, add a dumper with the appropriate detail level. - if (DumpRecords) { - std::unique_ptr Dumper; - if (opts::raw::CompactRecords) - Dumper = make_unique(Types, &P); - else { - assert(TpiTypes); - - auto X = make_unique(*TpiTypes, &P, false); - if (StreamIdx == StreamIPI) - X->setIpiTypes(*IpiTypes); - Dumper = std::move(X); - } - Visitors.push_back(std::move(Dumper)); - } - if (DumpRecordBytes) - Visitors.push_back(make_unique(P)); - - // We always need to deserialize and add it to the type database. This is - // true if even if we're not dumping anything, because we could need the - // type database for the purposes of dumping symbols. - TypeVisitorCallbackPipeline Pipeline; - for (const auto &V : Visitors) - Pipeline.addCallbackToPipeline(*V); - - if (DumpRecords || DumpRecordBytes) - RecordScope = llvm::make_unique(P, "Records"); - - Optional I = Types.getFirst(); - while (I) { - std::unique_ptr OneRecordScope; - - if ((DumpRecords || DumpRecordBytes) && !opts::raw::CompactRecords) - OneRecordScope = llvm::make_unique(P, ""); - - auto T = Types.getType(*I); - if (auto EC = codeview::visitTypeRecord(T, *I, Pipeline)) - return EC; - I = Types.getNext(*I); - } - - if (DumpTpiHash) { - DictScope DD(P, "Hash"); - P.printNumber("Number of Hash Buckets", Tpi->getNumHashBuckets()); - P.printNumber("Hash Key Size", Tpi->getHashKeySize()); - P.printList("Values", Tpi->getHashValues()); - - ListScope LHA(P, "Adjusters"); - auto ExpectedST = File.getStringTable(); - if (!ExpectedST) - return ExpectedST.takeError(); - const auto &ST = *ExpectedST; - for (const auto &E : Tpi->getHashAdjusters()) { - DictScope DHA(P); - auto Name = ST.getStringForID(E.first); - if (!Name) - return Name.takeError(); - - P.printString("Type", *Name); - P.printHex("TI", E.second); - } - } - - ListScope L(P, "TypeIndexOffsets"); - for (const auto &IO : Tpi->getTypeIndexOffsets()) { - P.printString(formatv("Index: {0:x}, Offset: {1:N}", IO.Type.getIndex(), - (uint32_t)IO.Offset) - .str()); - } - - P.flush(); - return Error::success(); -} - -Expected -LLVMOutputStyle::initializeTypeDatabase(uint32_t SN) { - auto &TypeCollection = (SN == StreamTPI) ? TpiTypes : IpiTypes; - auto Tpi = - (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream(); - if (!Tpi) - return Tpi.takeError(); - - if (!TypeCollection) { - // Initialize the type collection, even if we're not going to dump it. This - // way if some other part of the dumper decides it wants to use some or all - // of the records for whatever purposes, it can still access them lazily. - auto &Types = Tpi->typeArray(); - uint32_t Count = Tpi->getNumTypeRecords(); - auto Offsets = Tpi->getTypeIndexOffsets(); - TypeCollection = - llvm::make_unique(Types, Count, Offsets); - } - - return *TypeCollection; -} - -Error LLVMOutputStyle::dumpDbiStream() { - bool DumpModules = opts::raw::DumpModules || opts::raw::DumpModuleSyms || - opts::raw::DumpModuleFiles || opts::raw::DumpLineInfo; - if (!opts::raw::DumpHeaders && !DumpModules) - return Error::success(); - if (!File.hasPDBDbiStream()) { - P.printString("DBI Stream not present"); - return Error::success(); - } - - auto DS = File.getPDBDbiStream(); - if (!DS) - return DS.takeError(); - - DictScope D(P, "DBI Stream"); - P.printNumber("Dbi Version", DS->getDbiVersion()); - P.printNumber("Age", DS->getAge()); - P.printBoolean("Incremental Linking", DS->isIncrementallyLinked()); - P.printBoolean("Has CTypes", DS->hasCTypes()); - P.printBoolean("Is Stripped", DS->isStripped()); - P.printObject("Machine Type", DS->getMachineType()); - P.printNumber("Symbol Record Stream Index", DS->getSymRecordStreamIndex()); - P.printNumber("Public Symbol Stream Index", DS->getPublicSymbolStreamIndex()); - P.printNumber("Global Symbol Stream Index", DS->getGlobalSymbolStreamIndex()); - - uint16_t Major = DS->getBuildMajorVersion(); - uint16_t Minor = DS->getBuildMinorVersion(); - P.printVersion("Toolchain Version", Major, Minor); - - std::string DllName; - raw_string_ostream DllStream(DllName); - DllStream << "mspdb" << Major << Minor << ".dll version"; - DllStream.flush(); - P.printVersion(DllName, Major, Minor, DS->getPdbDllVersion()); - - if (DumpModules) { - ListScope L(P, "Modules"); - const DbiModuleList &Modules = DS->modules(); - for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) { - const DbiModuleDescriptor &Modi = Modules.getModuleDescriptor(I); - DictScope DD(P); - P.printString("Name", Modi.getModuleName().str()); - P.printNumber("Debug Stream Index", Modi.getModuleStreamIndex()); - P.printString("Object File Name", Modi.getObjFileName().str()); - P.printNumber("Num Files", Modi.getNumberOfFiles()); - P.printNumber("Source File Name Idx", Modi.getSourceFileNameIndex()); - P.printNumber("Pdb File Name Idx", Modi.getPdbFilePathNameIndex()); - P.printNumber("Line Info Byte Size", Modi.getC11LineInfoByteSize()); - P.printNumber("C13 Line Info Byte Size", Modi.getC13LineInfoByteSize()); - P.printNumber("Symbol Byte Size", Modi.getSymbolDebugInfoByteSize()); - P.printNumber("Type Server Index", Modi.getTypeServerIndex()); - P.printBoolean("Has EC Info", Modi.hasECInfo()); - if (opts::raw::DumpModuleFiles) { - std::string FileListName = to_string(Modules.getSourceFileCount(I)) + - " Contributing Source Files"; - ListScope LL(P, FileListName); - for (auto File : Modules.source_files(I)) - P.printString(File); - } - bool HasModuleDI = (Modi.getModuleStreamIndex() < File.getNumStreams()); - bool ShouldDumpSymbols = - (opts::raw::DumpModuleSyms || opts::raw::DumpSymRecordBytes); - if (HasModuleDI && (ShouldDumpSymbols || opts::raw::DumpLineInfo)) { - auto ModStreamData = MappedBlockStream::createIndexedStream( - File.getMsfLayout(), File.getMsfBuffer(), - Modi.getModuleStreamIndex(), File.getAllocator()); - - ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData)); - if (auto EC = ModS.reload()) - return EC; - - if (ShouldDumpSymbols) { - auto ExpectedTypes = initializeTypeDatabase(StreamTPI); - if (!ExpectedTypes) - return ExpectedTypes.takeError(); - auto &Types = *ExpectedTypes; - - ListScope SS(P, "Symbols"); - codeview::CVSymbolDumper SD(P, Types, CodeViewContainer::Pdb, nullptr, - false); - bool HadError = false; - for (auto S : ModS.symbols(&HadError)) { - DictScope LL(P, ""); - if (opts::raw::DumpModuleSyms) { - if (auto EC = SD.dump(S)) { - llvm::consumeError(std::move(EC)); - HadError = true; - break; - } - } - if (opts::raw::DumpSymRecordBytes) - P.printBinaryBlock("Bytes", S.content()); - } - if (HadError) - return make_error( - raw_error_code::corrupt_file, - "DBI stream contained corrupt symbol record"); - } - if (opts::raw::DumpLineInfo) { - ListScope SS(P, "LineInfo"); - auto ExpectedTypes = initializeTypeDatabase(StreamIPI); - if (!ExpectedTypes) - return ExpectedTypes.takeError(); - auto &IpiItems = *ExpectedTypes; - C13RawVisitor V(P, File, IpiItems); - if (auto EC = codeview::visitDebugSubsections(ModS.subsections(), V)) - return EC; - } - } - } - } - return Error::success(); -} - -Error LLVMOutputStyle::dumpSectionContribs() { - if (!opts::raw::DumpSectionContribs) - return Error::success(); - if (!File.hasPDBDbiStream()) { - P.printString("DBI Stream not present"); - return Error::success(); - } - - auto Dbi = File.getPDBDbiStream(); - if (!Dbi) - return Dbi.takeError(); - - ListScope L(P, "Section Contributions"); - class Visitor : public ISectionContribVisitor { - public: - Visitor(ScopedPrinter &P, DbiStream &DS) : P(P), DS(DS) {} - void visit(const SectionContrib &SC) override { - DictScope D(P, "Contribution"); - P.printNumber("ISect", SC.ISect); - P.printNumber("Off", SC.Off); - P.printNumber("Size", SC.Size); - P.printFlags("Characteristics", SC.Characteristics, - codeview::getImageSectionCharacteristicNames(), - COFF::SectionCharacteristics(0x00F00000)); - { - DictScope DD(P, "Module"); - P.printNumber("Index", SC.Imod); - const DbiModuleList &Modules = DS.modules(); - if (Modules.getModuleCount() > SC.Imod) { - P.printString("Name", - Modules.getModuleDescriptor(SC.Imod).getModuleName()); - } - } - P.printNumber("Data CRC", SC.DataCrc); - P.printNumber("Reloc CRC", SC.RelocCrc); - P.flush(); - } - void visit(const SectionContrib2 &SC) override { - visit(SC.Base); - P.printNumber("ISect Coff", SC.ISectCoff); - P.flush(); - } - - private: - ScopedPrinter &P; - DbiStream &DS; - }; - Visitor V(P, *Dbi); - Dbi->visitSectionContributions(V); - return Error::success(); -} - -Error LLVMOutputStyle::dumpSectionMap() { - if (!opts::raw::DumpSectionMap) - return Error::success(); - if (!File.hasPDBDbiStream()) { - P.printString("DBI Stream not present"); - return Error::success(); - } - - auto Dbi = File.getPDBDbiStream(); - if (!Dbi) - return Dbi.takeError(); - - ListScope L(P, "Section Map"); - for (auto &M : Dbi->getSectionMap()) { - DictScope D(P, "Entry"); - P.printFlags("Flags", M.Flags, getOMFSegMapDescFlagNames()); - P.printNumber("Ovl", M.Ovl); - P.printNumber("Group", M.Group); - P.printNumber("Frame", M.Frame); - P.printNumber("SecName", M.SecName); - P.printNumber("ClassName", M.ClassName); - P.printNumber("Offset", M.Offset); - P.printNumber("SecByteLength", M.SecByteLength); - P.flush(); - } - return Error::success(); -} - -Error LLVMOutputStyle::dumpPublicsStream() { - if (!opts::raw::DumpPublics) - return Error::success(); - if (!File.hasPDBPublicsStream()) { - P.printString("Publics Stream not present"); - return Error::success(); - } - - auto Publics = File.getPDBPublicsStream(); - if (!Publics) - return Publics.takeError(); - DictScope D(P, "Publics Stream"); - - auto Dbi = File.getPDBDbiStream(); - if (!Dbi) - return Dbi.takeError(); - - P.printNumber("Stream number", Dbi->getPublicSymbolStreamIndex()); - P.printNumber("SymHash", Publics->getSymHash()); - P.printNumber("AddrMap", Publics->getAddrMap()); - P.printNumber("Number of buckets", Publics->getNumBuckets()); - P.printList("Hash Buckets", Publics->getHashBuckets()); - P.printList("Address Map", Publics->getAddressMap()); - P.printList("Thunk Map", Publics->getThunkMap()); - P.printList("Section Offsets", Publics->getSectionOffsets(), - printSectionOffset); - ListScope L(P, "Symbols"); - auto ExpectedTypes = initializeTypeDatabase(StreamTPI); - if (!ExpectedTypes) - return ExpectedTypes.takeError(); - auto &Tpi = *ExpectedTypes; - - codeview::CVSymbolDumper SD(P, Tpi, CodeViewContainer::Pdb, nullptr, false); - bool HadError = false; - for (auto S : Publics->getSymbols(&HadError)) { - DictScope DD(P, ""); - - if (auto EC = SD.dump(S)) { - HadError = true; - break; - } - if (opts::raw::DumpSymRecordBytes) - P.printBinaryBlock("Bytes", S.content()); - } - if (HadError) - return make_error( - raw_error_code::corrupt_file, - "Public symbol stream contained corrupt record"); - - return Error::success(); -} - -Error LLVMOutputStyle::dumpSectionHeaders() { - if (!opts::raw::DumpSectionHeaders) - return Error::success(); - if (!File.hasPDBDbiStream()) { - P.printString("DBI Stream not present"); - return Error::success(); - } - - auto Dbi = File.getPDBDbiStream(); - if (!Dbi) - return Dbi.takeError(); - - ListScope D(P, "Section Headers"); - for (const object::coff_section &Section : Dbi->getSectionHeaders()) { - DictScope DD(P, ""); - - // If a name is 8 characters long, there is no NUL character at end. - StringRef Name(Section.Name, strnlen(Section.Name, sizeof(Section.Name))); - P.printString("Name", Name); - P.printNumber("Virtual Size", Section.VirtualSize); - P.printNumber("Virtual Address", Section.VirtualAddress); - P.printNumber("Size of Raw Data", Section.SizeOfRawData); - P.printNumber("File Pointer to Raw Data", Section.PointerToRawData); - P.printNumber("File Pointer to Relocations", Section.PointerToRelocations); - P.printNumber("File Pointer to Linenumbers", Section.PointerToLinenumbers); - P.printNumber("Number of Relocations", Section.NumberOfRelocations); - P.printNumber("Number of Linenumbers", Section.NumberOfLinenumbers); - P.printFlags("Characteristics", Section.Characteristics, - getImageSectionCharacteristicNames()); - } - return Error::success(); -} - -Error LLVMOutputStyle::dumpFpoStream() { - if (!opts::raw::DumpFpo) - return Error::success(); - if (!File.hasPDBDbiStream()) { - P.printString("DBI Stream not present"); - return Error::success(); - } - - auto Dbi = File.getPDBDbiStream(); - if (!Dbi) - return Dbi.takeError(); - - ListScope D(P, "New FPO"); - for (const object::FpoData &Fpo : Dbi->getFpoRecords()) { - DictScope DD(P, ""); - P.printNumber("Offset", Fpo.Offset); - P.printNumber("Size", Fpo.Size); - P.printNumber("Number of locals", Fpo.NumLocals); - P.printNumber("Number of params", Fpo.NumParams); - P.printNumber("Size of Prolog", Fpo.getPrologSize()); - P.printNumber("Number of Saved Registers", Fpo.getNumSavedRegs()); - P.printBoolean("Has SEH", Fpo.hasSEH()); - P.printBoolean("Use BP", Fpo.useBP()); - P.printNumber("Frame Pointer", Fpo.getFP()); - } - return Error::success(); -} - -void LLVMOutputStyle::flush() { P.flush(); } diff --git a/tools/llvm-pdbdump/LLVMOutputStyle.h b/tools/llvm-pdbdump/LLVMOutputStyle.h deleted file mode 100644 index 184dc4e1f44d..000000000000 --- a/tools/llvm-pdbdump/LLVMOutputStyle.h +++ /dev/null @@ -1,70 +0,0 @@ -//===- LLVMOutputStyle.h -------------------------------------- *- C++ --*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMOUTPUTSTYLE_H -#define LLVM_TOOLS_LLVMPDBDUMP_LLVMOUTPUTSTYLE_H - -#include "OutputStyle.h" - -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" -#include "llvm/Support/ScopedPrinter.h" - -#include - -namespace llvm { -class BitVector; - -namespace codeview { -class LazyRandomTypeCollection; -} - -namespace pdb { -class LLVMOutputStyle : public OutputStyle { -public: - LLVMOutputStyle(PDBFile &File); - - Error dump() override; - -private: - Expected - initializeTypeDatabase(uint32_t SN); - - Error dumpFileHeaders(); - Error dumpStreamSummary(); - Error dumpFreePageMap(); - Error dumpBlockRanges(); - Error dumpGlobalsStream(); - Error dumpStreamBytes(); - Error dumpStreamBlocks(); - Error dumpStringTable(); - Error dumpInfoStream(); - Error dumpTpiStream(uint32_t StreamIdx); - Error dumpDbiStream(); - Error dumpSectionContribs(); - Error dumpSectionMap(); - Error dumpPublicsStream(); - Error dumpSectionHeaders(); - Error dumpFpoStream(); - - void dumpBitVector(StringRef Name, const BitVector &V); - - void flush(); - - PDBFile &File; - ScopedPrinter P; - std::unique_ptr TpiTypes; - std::unique_ptr IpiTypes; - SmallVector StreamPurposes; -}; -} -} - -#endif diff --git a/tools/llvm-pdbdump/LinePrinter.cpp b/tools/llvm-pdbdump/LinePrinter.cpp deleted file mode 100644 index 7fa524400aef..000000000000 --- a/tools/llvm-pdbdump/LinePrinter.cpp +++ /dev/null @@ -1,145 +0,0 @@ -//===- LinePrinter.cpp ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "LinePrinter.h" - -#include "llvm-pdbdump.h" - -#include "llvm/ADT/STLExtras.h" -#include "llvm/DebugInfo/PDB/UDTLayout.h" -#include "llvm/Support/Regex.h" - -#include - -using namespace llvm; -using namespace llvm::pdb; - -namespace { -bool IsItemExcluded(llvm::StringRef Item, - std::list &IncludeFilters, - std::list &ExcludeFilters) { - if (Item.empty()) - return false; - - auto match_pred = [Item](llvm::Regex &R) { return R.match(Item); }; - - // Include takes priority over exclude. If the user specified include - // filters, and none of them include this item, them item is gone. - if (!IncludeFilters.empty() && !any_of(IncludeFilters, match_pred)) - return true; - - if (any_of(ExcludeFilters, match_pred)) - return true; - - return false; -} -} - -using namespace llvm; - -LinePrinter::LinePrinter(int Indent, bool UseColor, llvm::raw_ostream &Stream) - : OS(Stream), IndentSpaces(Indent), CurrentIndent(0), UseColor(UseColor) { - SetFilters(ExcludeTypeFilters, opts::pretty::ExcludeTypes.begin(), - opts::pretty::ExcludeTypes.end()); - SetFilters(ExcludeSymbolFilters, opts::pretty::ExcludeSymbols.begin(), - opts::pretty::ExcludeSymbols.end()); - SetFilters(ExcludeCompilandFilters, opts::pretty::ExcludeCompilands.begin(), - opts::pretty::ExcludeCompilands.end()); - - SetFilters(IncludeTypeFilters, opts::pretty::IncludeTypes.begin(), - opts::pretty::IncludeTypes.end()); - SetFilters(IncludeSymbolFilters, opts::pretty::IncludeSymbols.begin(), - opts::pretty::IncludeSymbols.end()); - SetFilters(IncludeCompilandFilters, opts::pretty::IncludeCompilands.begin(), - opts::pretty::IncludeCompilands.end()); -} - -void LinePrinter::Indent() { CurrentIndent += IndentSpaces; } - -void LinePrinter::Unindent() { - CurrentIndent = std::max(0, CurrentIndent - IndentSpaces); -} - -void LinePrinter::NewLine() { - OS << "\n"; - OS.indent(CurrentIndent); -} - -bool LinePrinter::IsClassExcluded(const ClassLayout &Class) { - if (IsTypeExcluded(Class.getName(), Class.getSize())) - return true; - if (Class.deepPaddingSize() < opts::pretty::PaddingThreshold) - return true; - return false; -} - -bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size) { - if (IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters)) - return true; - if (Size < opts::pretty::SizeThreshold) - return true; - return false; -} - -bool LinePrinter::IsSymbolExcluded(llvm::StringRef SymbolName) { - return IsItemExcluded(SymbolName, IncludeSymbolFilters, ExcludeSymbolFilters); -} - -bool LinePrinter::IsCompilandExcluded(llvm::StringRef CompilandName) { - return IsItemExcluded(CompilandName, IncludeCompilandFilters, - ExcludeCompilandFilters); -} - -WithColor::WithColor(LinePrinter &P, PDB_ColorItem C) - : OS(P.OS), UseColor(P.hasColor()) { - if (UseColor) - applyColor(C); -} - -WithColor::~WithColor() { - if (UseColor) - OS.resetColor(); -} - -void WithColor::applyColor(PDB_ColorItem C) { - switch (C) { - case PDB_ColorItem::None: - OS.resetColor(); - return; - case PDB_ColorItem::Comment: - OS.changeColor(raw_ostream::GREEN, false); - return; - case PDB_ColorItem::Address: - OS.changeColor(raw_ostream::YELLOW, /*bold=*/true); - return; - case PDB_ColorItem::Keyword: - OS.changeColor(raw_ostream::MAGENTA, true); - return; - case PDB_ColorItem::Register: - case PDB_ColorItem::Offset: - OS.changeColor(raw_ostream::YELLOW, false); - return; - case PDB_ColorItem::Type: - OS.changeColor(raw_ostream::CYAN, true); - return; - case PDB_ColorItem::Identifier: - OS.changeColor(raw_ostream::CYAN, false); - return; - case PDB_ColorItem::Path: - OS.changeColor(raw_ostream::CYAN, false); - return; - case PDB_ColorItem::Padding: - case PDB_ColorItem::SectionHeader: - OS.changeColor(raw_ostream::RED, true); - return; - case PDB_ColorItem::LiteralValue: - OS.changeColor(raw_ostream::GREEN, true); - return; - } -} diff --git a/tools/llvm-pdbdump/LinePrinter.h b/tools/llvm-pdbdump/LinePrinter.h deleted file mode 100644 index 1a922feb1e62..000000000000 --- a/tools/llvm-pdbdump/LinePrinter.h +++ /dev/null @@ -1,102 +0,0 @@ -//===- LinePrinter.h ------------------------------------------ *- C++ --*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H -#define LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Regex.h" - -#include - -namespace llvm { -namespace pdb { - -class ClassLayout; - -class LinePrinter { - friend class WithColor; - -public: - LinePrinter(int Indent, bool UseColor, raw_ostream &Stream); - - void Indent(); - void Unindent(); - void NewLine(); - - bool hasColor() const { return UseColor; } - raw_ostream &getStream() { return OS; } - int getIndentLevel() const { return CurrentIndent; } - - bool IsClassExcluded(const ClassLayout &Class); - bool IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size); - bool IsSymbolExcluded(llvm::StringRef SymbolName); - bool IsCompilandExcluded(llvm::StringRef CompilandName); - -private: - template - void SetFilters(std::list &List, Iter Begin, Iter End) { - List.clear(); - for (; Begin != End; ++Begin) - List.emplace_back(StringRef(*Begin)); - } - - raw_ostream &OS; - int IndentSpaces; - int CurrentIndent; - bool UseColor; - - std::list ExcludeCompilandFilters; - std::list ExcludeTypeFilters; - std::list ExcludeSymbolFilters; - - std::list IncludeCompilandFilters; - std::list IncludeTypeFilters; - std::list IncludeSymbolFilters; -}; - -template -inline raw_ostream &operator<<(LinePrinter &Printer, const T &Item) { - Printer.getStream() << Item; - return Printer.getStream(); -} - -enum class PDB_ColorItem { - None, - Address, - Type, - Comment, - Padding, - Keyword, - Offset, - Identifier, - Path, - SectionHeader, - LiteralValue, - Register, -}; - -class WithColor { -public: - WithColor(LinePrinter &P, PDB_ColorItem C); - ~WithColor(); - - raw_ostream &get() { return OS; } - -private: - void applyColor(PDB_ColorItem C); - raw_ostream &OS; - bool UseColor; -}; -} -} - -#endif diff --git a/tools/llvm-pdbdump/OutputStyle.h b/tools/llvm-pdbdump/OutputStyle.h deleted file mode 100644 index dfefc25a215e..000000000000 --- a/tools/llvm-pdbdump/OutputStyle.h +++ /dev/null @@ -1,28 +0,0 @@ -//===- OutputStyle.h ------------------------------------------ *- C++ --*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_OUTPUTSTYLE_H -#define LLVM_TOOLS_LLVMPDBDUMP_OUTPUTSTYLE_H - -#include "llvm/Support/Error.h" - -namespace llvm { -namespace pdb { -class PDBFile; - -class OutputStyle { -public: - virtual ~OutputStyle() {} - - virtual Error dump() = 0; -}; -} -} - -#endif diff --git a/tools/llvm-pdbdump/PdbYaml.cpp b/tools/llvm-pdbdump/PdbYaml.cpp deleted file mode 100644 index b4a41fbfdb8f..000000000000 --- a/tools/llvm-pdbdump/PdbYaml.cpp +++ /dev/null @@ -1,227 +0,0 @@ -//===- PdbYAML.cpp -------------------------------------------- *- C++ --*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PdbYaml.h" - -#include "llvm/ADT/StringExtras.h" -#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" -#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" -#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" -#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h" -#include "llvm/DebugInfo/CodeView/TypeSerializer.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" -#include "llvm/DebugInfo/PDB/Native/PDBFile.h" -#include "llvm/DebugInfo/PDB/Native/RawTypes.h" -#include "llvm/DebugInfo/PDB/Native/TpiHashing.h" -#include "llvm/DebugInfo/PDB/PDBExtras.h" -#include "llvm/DebugInfo/PDB/PDBTypes.h" -#include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h" -#include "llvm/ObjectYAML/CodeViewYAMLTypes.h" - -using namespace llvm; -using namespace llvm::pdb; -using namespace llvm::pdb::yaml; -using namespace llvm::yaml; - -LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::StringRef) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::NamedStreamMapping) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbDbiModuleInfo) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList) -LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::pdb::PdbRaw_FeatureSig) - -namespace llvm { -namespace yaml { - -template <> struct ScalarTraits { - static void output(const llvm::pdb::PDB_UniqueId &S, void *, - llvm::raw_ostream &OS) { - OS << S; - } - - static StringRef input(StringRef Scalar, void *Ctx, - llvm::pdb::PDB_UniqueId &S) { - if (Scalar.size() != 38) - return "GUID strings are 38 characters long"; - if (Scalar[0] != '{' || Scalar[37] != '}') - return "GUID is not enclosed in {}"; - if (Scalar[9] != '-' || Scalar[14] != '-' || Scalar[19] != '-' || - Scalar[24] != '-') - return "GUID sections are not properly delineated with dashes"; - - uint8_t *OutBuffer = S.Guid; - for (auto Iter = Scalar.begin(); Iter != Scalar.end();) { - if (*Iter == '-' || *Iter == '{' || *Iter == '}') { - ++Iter; - continue; - } - uint8_t Value = (llvm::hexDigitValue(*Iter) << 4); - ++Iter; - Value |= llvm::hexDigitValue(*Iter); - ++Iter; - *OutBuffer++ = Value; - } - - return ""; - } - - static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); } -}; - -template <> struct ScalarEnumerationTraits { - static void enumeration(IO &io, llvm::pdb::PDB_Machine &Value) { - io.enumCase(Value, "Invalid", PDB_Machine::Invalid); - io.enumCase(Value, "Am33", PDB_Machine::Am33); - io.enumCase(Value, "Amd64", PDB_Machine::Amd64); - io.enumCase(Value, "Arm", PDB_Machine::Arm); - io.enumCase(Value, "ArmNT", PDB_Machine::ArmNT); - io.enumCase(Value, "Ebc", PDB_Machine::Ebc); - io.enumCase(Value, "x86", PDB_Machine::x86); - io.enumCase(Value, "Ia64", PDB_Machine::Ia64); - io.enumCase(Value, "M32R", PDB_Machine::M32R); - io.enumCase(Value, "Mips16", PDB_Machine::Mips16); - io.enumCase(Value, "MipsFpu", PDB_Machine::MipsFpu); - io.enumCase(Value, "MipsFpu16", PDB_Machine::MipsFpu16); - io.enumCase(Value, "PowerPCFP", PDB_Machine::PowerPCFP); - io.enumCase(Value, "R4000", PDB_Machine::R4000); - io.enumCase(Value, "SH3", PDB_Machine::SH3); - io.enumCase(Value, "SH3DSP", PDB_Machine::SH3DSP); - io.enumCase(Value, "Thumb", PDB_Machine::Thumb); - io.enumCase(Value, "WceMipsV2", PDB_Machine::WceMipsV2); - } -}; - -template <> struct ScalarEnumerationTraits { - static void enumeration(IO &io, llvm::pdb::PdbRaw_DbiVer &Value) { - io.enumCase(Value, "V41", llvm::pdb::PdbRaw_DbiVer::PdbDbiVC41); - io.enumCase(Value, "V50", llvm::pdb::PdbRaw_DbiVer::PdbDbiV50); - io.enumCase(Value, "V60", llvm::pdb::PdbRaw_DbiVer::PdbDbiV60); - io.enumCase(Value, "V70", llvm::pdb::PdbRaw_DbiVer::PdbDbiV70); - io.enumCase(Value, "V110", llvm::pdb::PdbRaw_DbiVer::PdbDbiV110); - } -}; - -template <> struct ScalarEnumerationTraits { - static void enumeration(IO &io, llvm::pdb::PdbRaw_ImplVer &Value) { - io.enumCase(Value, "VC2", llvm::pdb::PdbRaw_ImplVer::PdbImplVC2); - io.enumCase(Value, "VC4", llvm::pdb::PdbRaw_ImplVer::PdbImplVC4); - io.enumCase(Value, "VC41", llvm::pdb::PdbRaw_ImplVer::PdbImplVC41); - io.enumCase(Value, "VC50", llvm::pdb::PdbRaw_ImplVer::PdbImplVC50); - io.enumCase(Value, "VC98", llvm::pdb::PdbRaw_ImplVer::PdbImplVC98); - io.enumCase(Value, "VC70Dep", llvm::pdb::PdbRaw_ImplVer::PdbImplVC70Dep); - io.enumCase(Value, "VC70", llvm::pdb::PdbRaw_ImplVer::PdbImplVC70); - io.enumCase(Value, "VC80", llvm::pdb::PdbRaw_ImplVer::PdbImplVC80); - io.enumCase(Value, "VC110", llvm::pdb::PdbRaw_ImplVer::PdbImplVC110); - io.enumCase(Value, "VC140", llvm::pdb::PdbRaw_ImplVer::PdbImplVC140); - } -}; - -template <> struct ScalarEnumerationTraits { - static void enumeration(IO &io, llvm::pdb::PdbRaw_TpiVer &Value) { - io.enumCase(Value, "VC40", llvm::pdb::PdbRaw_TpiVer::PdbTpiV40); - io.enumCase(Value, "VC41", llvm::pdb::PdbRaw_TpiVer::PdbTpiV41); - io.enumCase(Value, "VC50", llvm::pdb::PdbRaw_TpiVer::PdbTpiV50); - io.enumCase(Value, "VC70", llvm::pdb::PdbRaw_TpiVer::PdbTpiV70); - io.enumCase(Value, "VC80", llvm::pdb::PdbRaw_TpiVer::PdbTpiV80); - } -}; - -template <> struct ScalarEnumerationTraits { - static void enumeration(IO &io, PdbRaw_FeatureSig &Features) { - io.enumCase(Features, "MinimalDebugInfo", - PdbRaw_FeatureSig::MinimalDebugInfo); - io.enumCase(Features, "NoTypeMerge", PdbRaw_FeatureSig::NoTypeMerge); - io.enumCase(Features, "VC110", PdbRaw_FeatureSig::VC110); - io.enumCase(Features, "VC140", PdbRaw_FeatureSig::VC140); - } -}; -} -} - -void MappingTraits::mapping(IO &IO, PdbObject &Obj) { - IO.mapOptional("MSF", Obj.Headers); - IO.mapOptional("StreamSizes", Obj.StreamSizes); - IO.mapOptional("StreamMap", Obj.StreamMap); - IO.mapOptional("StringTable", Obj.StringTable); - IO.mapOptional("PdbStream", Obj.PdbStream); - IO.mapOptional("DbiStream", Obj.DbiStream); - IO.mapOptional("TpiStream", Obj.TpiStream); - IO.mapOptional("IpiStream", Obj.IpiStream); -} - -void MappingTraits::mapping(IO &IO, MSFHeaders &Obj) { - IO.mapOptional("SuperBlock", Obj.SuperBlock); - IO.mapOptional("NumDirectoryBlocks", Obj.NumDirectoryBlocks); - IO.mapOptional("DirectoryBlocks", Obj.DirectoryBlocks); - IO.mapOptional("NumStreams", Obj.NumStreams); - IO.mapOptional("FileSize", Obj.FileSize); -} - -void MappingTraits::mapping(IO &IO, msf::SuperBlock &SB) { - if (!IO.outputting()) { - ::memcpy(SB.MagicBytes, msf::Magic, sizeof(msf::Magic)); - } - - using u32 = support::ulittle32_t; - IO.mapOptional("BlockSize", SB.BlockSize, u32(4096U)); - IO.mapOptional("FreeBlockMap", SB.FreeBlockMapBlock, u32(0U)); - IO.mapOptional("NumBlocks", SB.NumBlocks, u32(0U)); - IO.mapOptional("NumDirectoryBytes", SB.NumDirectoryBytes, u32(0U)); - IO.mapOptional("Unknown1", SB.Unknown1, u32(0U)); - IO.mapOptional("BlockMapAddr", SB.BlockMapAddr, u32(0U)); -} - -void MappingTraits::mapping(IO &IO, StreamBlockList &SB) { - IO.mapRequired("Stream", SB.Blocks); -} - -void MappingTraits::mapping(IO &IO, PdbInfoStream &Obj) { - IO.mapOptional("Age", Obj.Age, 1U); - IO.mapOptional("Guid", Obj.Guid); - IO.mapOptional("Signature", Obj.Signature, 0U); - IO.mapOptional("Features", Obj.Features); - IO.mapOptional("Version", Obj.Version, PdbImplVC70); -} - -void MappingTraits::mapping(IO &IO, PdbDbiStream &Obj) { - IO.mapOptional("VerHeader", Obj.VerHeader, PdbDbiV70); - IO.mapOptional("Age", Obj.Age, 1U); - IO.mapOptional("BuildNumber", Obj.BuildNumber, uint16_t(0U)); - IO.mapOptional("PdbDllVersion", Obj.PdbDllVersion, 0U); - IO.mapOptional("PdbDllRbld", Obj.PdbDllRbld, uint16_t(0U)); - IO.mapOptional("Flags", Obj.Flags, uint16_t(1U)); - IO.mapOptional("MachineType", Obj.MachineType, PDB_Machine::x86); - IO.mapOptional("Modules", Obj.ModInfos); -} - -void MappingTraits::mapping(IO &IO, - pdb::yaml::PdbTpiStream &Obj) { - IO.mapOptional("Version", Obj.Version, PdbTpiV80); - IO.mapRequired("Records", Obj.Records); -} - -void MappingTraits::mapping(IO &IO, - NamedStreamMapping &Obj) { - IO.mapRequired("Name", Obj.StreamName); - IO.mapRequired("StreamNum", Obj.StreamNumber); -} - -void MappingTraits::mapping(IO &IO, PdbModiStream &Obj) { - IO.mapOptional("Signature", Obj.Signature, 4U); - IO.mapRequired("Records", Obj.Symbols); -} - -void MappingTraits::mapping(IO &IO, PdbDbiModuleInfo &Obj) { - IO.mapRequired("Module", Obj.Mod); - IO.mapOptional("ObjFile", Obj.Obj, Obj.Mod); - IO.mapOptional("SourceFiles", Obj.SourceFiles); - IO.mapOptional("Subsections", Obj.Subsections); - IO.mapOptional("Modi", Obj.Modi); -} diff --git a/tools/llvm-pdbdump/PdbYaml.h b/tools/llvm-pdbdump/PdbYaml.h deleted file mode 100644 index 62ed608916fc..000000000000 --- a/tools/llvm-pdbdump/PdbYaml.h +++ /dev/null @@ -1,125 +0,0 @@ -//===- PdbYAML.h ---------------------------------------------- *- C++ --*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H -#define LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H - -#include "OutputStyle.h" - -#include "llvm/ADT/Optional.h" -#include "llvm/DebugInfo/CodeView/SymbolRecord.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/MSF/MSFCommon.h" -#include "llvm/DebugInfo/PDB/Native/PDBFile.h" -#include "llvm/DebugInfo/PDB/Native/RawConstants.h" -#include "llvm/DebugInfo/PDB/PDBTypes.h" -#include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h" -#include "llvm/ObjectYAML/CodeViewYAMLSymbols.h" -#include "llvm/ObjectYAML/CodeViewYAMLTypes.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/YAMLTraits.h" - -#include - -namespace llvm { -namespace codeview { -class DebugStringTableSubsection; -} -namespace pdb { - -namespace yaml { -struct SerializationContext; - -struct MSFHeaders { - msf::SuperBlock SuperBlock; - uint32_t NumDirectoryBlocks = 0; - std::vector DirectoryBlocks; - uint32_t NumStreams = 0; - uint32_t FileSize = 0; -}; - -struct StreamBlockList { - std::vector Blocks; -}; - -struct NamedStreamMapping { - StringRef StreamName; - uint32_t StreamNumber; -}; - -struct PdbInfoStream { - PdbRaw_ImplVer Version = PdbImplVC70; - uint32_t Signature = 0; - uint32_t Age = 1; - PDB_UniqueId Guid; - std::vector Features; - std::vector NamedStreams; -}; - -struct PdbModiStream { - uint32_t Signature; - std::vector Symbols; -}; - -struct PdbDbiModuleInfo { - StringRef Obj; - StringRef Mod; - std::vector SourceFiles; - std::vector Subsections; - Optional Modi; -}; - -struct PdbDbiStream { - PdbRaw_DbiVer VerHeader = PdbDbiV70; - uint32_t Age = 1; - uint16_t BuildNumber = 0; - uint32_t PdbDllVersion = 0; - uint16_t PdbDllRbld = 0; - uint16_t Flags = 1; - PDB_Machine MachineType = PDB_Machine::x86; - - std::vector ModInfos; -}; - -struct PdbTpiStream { - PdbRaw_TpiVer Version = PdbTpiV80; - std::vector Records; -}; - -struct PdbObject { - explicit PdbObject(BumpPtrAllocator &Allocator) : Allocator(Allocator) {} - - Optional Headers; - Optional> StreamSizes; - Optional> StreamMap; - Optional PdbStream; - Optional DbiStream; - Optional TpiStream; - Optional IpiStream; - - Optional> StringTable; - - BumpPtrAllocator &Allocator; -}; -} -} -} - -LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbObject) -LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::MSFHeaders) -LLVM_YAML_DECLARE_MAPPING_TRAITS(msf::SuperBlock) -LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::StreamBlockList) -LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbInfoStream) -LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbDbiStream) -LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbTpiStream) -LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::NamedStreamMapping) -LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbModiStream) -LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbDbiModuleInfo) - -#endif // LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H diff --git a/tools/llvm-pdbdump/PrettyBuiltinDumper.cpp b/tools/llvm-pdbdump/PrettyBuiltinDumper.cpp deleted file mode 100644 index 591d5e70cfd6..000000000000 --- a/tools/llvm-pdbdump/PrettyBuiltinDumper.cpp +++ /dev/null @@ -1,94 +0,0 @@ -//===- PrettyBuiltinDumper.cpp ---------------------------------- *- C++ *-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PrettyBuiltinDumper.h" -#include "LinePrinter.h" -#include "llvm-pdbdump.h" - -#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" - -using namespace llvm; -using namespace llvm::pdb; - -BuiltinDumper::BuiltinDumper(LinePrinter &P) - : PDBSymDumper(false), Printer(P) {} - -void BuiltinDumper::start(const PDBSymbolTypeBuiltin &Symbol) { - if (Symbol.isConstType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; - if (Symbol.isVolatileType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; - WithColor(Printer, PDB_ColorItem::Type).get() << getTypeName(Symbol); -} - -StringRef BuiltinDumper::getTypeName(const PDBSymbolTypeBuiltin &Symbol) { - PDB_BuiltinType Type = Symbol.getBuiltinType(); - switch (Type) { - case PDB_BuiltinType::Float: - if (Symbol.getLength() == 4) - return "float"; - return "double"; - case PDB_BuiltinType::UInt: - switch (Symbol.getLength()) { - case 8: - return "unsigned __int64"; - case 4: - return "unsigned int"; - case 2: - return "unsigned short"; - case 1: - return "unsigned char"; - default: - return "unsigned"; - } - case PDB_BuiltinType::Int: - switch (Symbol.getLength()) { - case 8: - return "__int64"; - case 4: - return "int"; - case 2: - return "short"; - case 1: - return "char"; - default: - return "int"; - } - case PDB_BuiltinType::Char: - return "char"; - case PDB_BuiltinType::WCharT: - return "wchar_t"; - case PDB_BuiltinType::Void: - return "void"; - case PDB_BuiltinType::Long: - return "long"; - case PDB_BuiltinType::ULong: - return "unsigned long"; - case PDB_BuiltinType::Bool: - return "bool"; - case PDB_BuiltinType::Currency: - return "CURRENCY"; - case PDB_BuiltinType::Date: - return "DATE"; - case PDB_BuiltinType::Variant: - return "VARIANT"; - case PDB_BuiltinType::Complex: - return "complex"; - case PDB_BuiltinType::Bitfield: - return "bitfield"; - case PDB_BuiltinType::BSTR: - return "BSTR"; - case PDB_BuiltinType::HResult: - return "HRESULT"; - case PDB_BuiltinType::BCD: - return "HRESULT"; - default: - return "void"; - } -} diff --git a/tools/llvm-pdbdump/PrettyBuiltinDumper.h b/tools/llvm-pdbdump/PrettyBuiltinDumper.h deleted file mode 100644 index fb6b0b172e6e..000000000000 --- a/tools/llvm-pdbdump/PrettyBuiltinDumper.h +++ /dev/null @@ -1,35 +0,0 @@ -//===- PrettyBuiltinDumper.h ---------------------------------- *- C++ --*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYBUILTINDUMPER_H -#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYBUILTINDUMPER_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/DebugInfo/PDB/PDBSymDumper.h" - -namespace llvm { -namespace pdb { - -class LinePrinter; - -class BuiltinDumper : public PDBSymDumper { -public: - BuiltinDumper(LinePrinter &P); - - void start(const PDBSymbolTypeBuiltin &Symbol); - -private: - StringRef getTypeName(const PDBSymbolTypeBuiltin &Symbol); - - LinePrinter &Printer; -}; -} -} - -#endif diff --git a/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp b/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp deleted file mode 100644 index 90f7772001d7..000000000000 --- a/tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp +++ /dev/null @@ -1,108 +0,0 @@ -//===- PrettyClassDefinitionDumper.cpp --------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PrettyClassDefinitionDumper.h" - -#include "LinePrinter.h" -#include "PrettyClassLayoutGraphicalDumper.h" -#include "llvm-pdbdump.h" - -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" -#include "llvm/DebugInfo/PDB/UDTLayout.h" - -#include "llvm/Support/Format.h" - -using namespace llvm; -using namespace llvm::pdb; - -ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P) - : PDBSymDumper(true), Printer(P) {} - -void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) { - assert(opts::pretty::ClassFormat != - opts::pretty::ClassDefinitionFormat::None); - - ClassLayout Layout(Class); - start(Layout); -} - -void ClassDefinitionDumper::start(const ClassLayout &Layout) { - prettyPrintClassIntro(Layout); - - PrettyClassLayoutGraphicalDumper Dumper(Printer, 1, 0); - DumpedAnything |= Dumper.start(Layout); - - prettyPrintClassOutro(Layout); -} - -void ClassDefinitionDumper::prettyPrintClassIntro(const ClassLayout &Layout) { - DumpedAnything = false; - Printer.NewLine(); - - uint32_t Size = Layout.getSize(); - const PDBSymbolTypeUDT &Class = Layout.getClass(); - - WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " "; - WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName(); - WithColor(Printer, PDB_ColorItem::Comment).get() << " [sizeof = " << Size - << "]"; - uint32_t BaseCount = Layout.bases().size(); - if (BaseCount > 0) { - Printer.Indent(); - char NextSeparator = ':'; - for (auto BC : Layout.bases()) { - const auto &Base = BC->getBase(); - if (Base.isIndirectVirtualBaseClass()) - continue; - - Printer.NewLine(); - Printer << NextSeparator << " "; - WithColor(Printer, PDB_ColorItem::Keyword).get() << Base.getAccess(); - if (BC->isVirtualBase()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual"; - - WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base.getName(); - NextSeparator = ','; - } - - Printer.Unindent(); - } - - Printer << " {"; - Printer.Indent(); -} - -void ClassDefinitionDumper::prettyPrintClassOutro(const ClassLayout &Layout) { - Printer.Unindent(); - if (DumpedAnything) - Printer.NewLine(); - Printer << "}"; - Printer.NewLine(); - if (Layout.deepPaddingSize() > 0) { - APFloat Pct(100.0 * (double)Layout.deepPaddingSize() / - (double)Layout.getSize()); - SmallString<8> PctStr; - Pct.toString(PctStr, 4); - WithColor(Printer, PDB_ColorItem::Padding).get() - << "Total padding " << Layout.deepPaddingSize() << " bytes (" << PctStr - << "% of class size)"; - Printer.NewLine(); - APFloat Pct2(100.0 * (double)Layout.immediatePadding() / - (double)Layout.getSize()); - PctStr.clear(); - Pct2.toString(PctStr, 4); - WithColor(Printer, PDB_ColorItem::Padding).get() - << "Immediate padding " << Layout.immediatePadding() << " bytes (" - << PctStr << "% of class size)"; - Printer.NewLine(); - } -} diff --git a/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h b/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h deleted file mode 100644 index 6569a1d304f6..000000000000 --- a/tools/llvm-pdbdump/PrettyClassDefinitionDumper.h +++ /dev/null @@ -1,47 +0,0 @@ -//===- PrettyClassDefinitionDumper.h ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSDEFINITIONDUMPER_H -#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSDEFINITIONDUMPER_H - -#include "llvm/ADT/BitVector.h" - -#include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbolData.h" -#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" - -#include -#include -#include - -namespace llvm { -class BitVector; - -namespace pdb { - -class ClassLayout; -class LinePrinter; - -class ClassDefinitionDumper : public PDBSymDumper { -public: - ClassDefinitionDumper(LinePrinter &P); - - void start(const PDBSymbolTypeUDT &Class); - void start(const ClassLayout &Class); - -private: - void prettyPrintClassIntro(const ClassLayout &Class); - void prettyPrintClassOutro(const ClassLayout &Class); - - LinePrinter &Printer; - bool DumpedAnything = false; -}; -} -} -#endif diff --git a/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.cpp b/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.cpp deleted file mode 100644 index d11472679626..000000000000 --- a/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.cpp +++ /dev/null @@ -1,216 +0,0 @@ -//===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PrettyClassLayoutGraphicalDumper.h" - -#include "LinePrinter.h" -#include "PrettyClassDefinitionDumper.h" -#include "PrettyEnumDumper.h" -#include "PrettyFunctionDumper.h" -#include "PrettyTypedefDumper.h" -#include "PrettyVariableDumper.h" -#include "PrettyVariableDumper.h" -#include "llvm-pdbdump.h" - -#include "llvm/DebugInfo/PDB/PDBSymbolData.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" -#include "llvm/DebugInfo/PDB/UDTLayout.h" -#include "llvm/Support/Format.h" - -using namespace llvm; -using namespace llvm::pdb; - -PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper( - LinePrinter &P, uint32_t RecurseLevel, uint32_t InitialOffset) - : PDBSymDumper(true), Printer(P), RecursionLevel(RecurseLevel), - ClassOffsetZero(InitialOffset), CurrentAbsoluteOffset(InitialOffset) {} - -bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) { - - if (RecursionLevel == 1 && - opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::All) { - for (auto &Other : Layout.other_items()) - Other->dump(*this); - for (auto &Func : Layout.funcs()) - Func->dump(*this); - } - - const BitVector &UseMap = Layout.usedBytes(); - int NextPaddingByte = UseMap.find_first_unset(); - - for (auto &Item : Layout.layout_items()) { - // Calculate the absolute offset of the first byte of the next field. - uint32_t RelativeOffset = Item->getOffsetInParent(); - CurrentAbsoluteOffset = ClassOffsetZero + RelativeOffset; - - // Since there is storage there, it should be set! However, this might - // be an empty base, in which case it could extend outside the bounds of - // the parent class. - if (RelativeOffset < UseMap.size() && (Item->getSize() > 0)) { - assert(UseMap.test(RelativeOffset)); - - // If there is any remaining padding in this class, and the offset of the - // new item is after the padding, then we must have just jumped over some - // padding. Print a padding row and then look for where the next block - // of padding begins. - if ((NextPaddingByte >= 0) && - (RelativeOffset > uint32_t(NextPaddingByte))) { - printPaddingRow(RelativeOffset - NextPaddingByte); - NextPaddingByte = UseMap.find_next_unset(RelativeOffset); - } - } - - CurrentItem = Item; - if (Item->isVBPtr()) { - VTableLayoutItem &Layout = static_cast(*CurrentItem); - - VariableDumper VarDumper(Printer); - VarDumper.startVbptr(CurrentAbsoluteOffset, Layout.getSize()); - } else { - if (auto Sym = Item->getSymbol()) - Sym->dump(*this); - } - - if (Item->getLayoutSize() > 0) { - uint32_t Prev = RelativeOffset + Item->getLayoutSize() - 1; - if (Prev < UseMap.size()) - NextPaddingByte = UseMap.find_next_unset(Prev); - } - } - - auto TailPadding = Layout.tailPadding(); - if (TailPadding > 0) { - if (TailPadding != 1 || Layout.getSize() != 1) { - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Padding).get() - << " (" << TailPadding << " bytes)"; - DumpedAnything = true; - } - } - - return DumpedAnything; -} - -void PrettyClassLayoutGraphicalDumper::printPaddingRow(uint32_t Amount) { - if (Amount == 0) - return; - - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Padding).get() << " (" << Amount - << " bytes)"; - DumpedAnything = true; -} - -void PrettyClassLayoutGraphicalDumper::dump( - const PDBSymbolTypeBaseClass &Symbol) { - assert(CurrentItem != nullptr); - - Printer.NewLine(); - BaseClassLayout &Layout = static_cast(*CurrentItem); - - std::string Label = "base"; - if (Layout.isVirtualBase()) { - Label.insert(Label.begin(), 'v'); - if (Layout.getBase().isIndirectVirtualBaseClass()) - Label.insert(Label.begin(), 'i'); - } - Printer << Label << " "; - - uint32_t Size = Layout.isEmptyBase() ? 1 : Layout.getLayoutSize(); - - WithColor(Printer, PDB_ColorItem::Offset).get() - << "+" << format_hex(CurrentAbsoluteOffset, 4) << " [sizeof=" << Size - << "] "; - - WithColor(Printer, PDB_ColorItem::Identifier).get() << Layout.getName(); - - if (shouldRecurse()) { - Printer.Indent(); - uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent(); - PrettyClassLayoutGraphicalDumper BaseDumper(Printer, RecursionLevel + 1, - ChildOffsetZero); - DumpedAnything |= BaseDumper.start(Layout); - Printer.Unindent(); - } - - DumpedAnything = true; -} - -bool PrettyClassLayoutGraphicalDumper::shouldRecurse() const { - uint32_t Limit = opts::pretty::ClassRecursionDepth; - if (Limit == 0) - return true; - return RecursionLevel < Limit; -} - -void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) { - assert(CurrentItem != nullptr); - - DataMemberLayoutItem &Layout = - static_cast(*CurrentItem); - - VariableDumper VarDumper(Printer); - VarDumper.start(Symbol, ClassOffsetZero); - - if (Layout.hasUDTLayout() && shouldRecurse()) { - uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent(); - Printer.Indent(); - PrettyClassLayoutGraphicalDumper TypeDumper(Printer, RecursionLevel + 1, - ChildOffsetZero); - TypeDumper.start(Layout.getUDTLayout()); - Printer.Unindent(); - } - - DumpedAnything = true; -} - -void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeVTable &Symbol) { - assert(CurrentItem != nullptr); - - VariableDumper VarDumper(Printer); - VarDumper.start(Symbol, ClassOffsetZero); - - DumpedAnything = true; -} - -void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeEnum &Symbol) { - DumpedAnything = true; - Printer.NewLine(); - EnumDumper Dumper(Printer); - Dumper.start(Symbol); -} - -void PrettyClassLayoutGraphicalDumper::dump( - const PDBSymbolTypeTypedef &Symbol) { - DumpedAnything = true; - Printer.NewLine(); - TypedefDumper Dumper(Printer); - Dumper.start(Symbol); -} - -void PrettyClassLayoutGraphicalDumper::dump( - const PDBSymbolTypeBuiltin &Symbol) {} - -void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeUDT &Symbol) {} - -void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolFunc &Symbol) { - if (Printer.IsSymbolExcluded(Symbol.getName())) - return; - if (Symbol.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated) - return; - if (Symbol.getLength() == 0 && !Symbol.isPureVirtual() && - !Symbol.isIntroVirtualFunction()) - return; - - DumpedAnything = true; - Printer.NewLine(); - FunctionDumper Dumper(Printer); - Dumper.start(Symbol, FunctionDumper::PointerType::None); -} diff --git a/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.h b/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.h deleted file mode 100644 index f83f1a6c1b34..000000000000 --- a/tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.h +++ /dev/null @@ -1,58 +0,0 @@ -//===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSLAYOUTGRAPHICALDUMPER_H -#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSLAYOUTGRAPHICALDUMPER_H - -#include "llvm/ADT/BitVector.h" - -#include "llvm/DebugInfo/PDB/PDBSymDumper.h" - -namespace llvm { - -namespace pdb { - -class UDTLayoutBase; -class LayoutItemBase; -class LinePrinter; - -class PrettyClassLayoutGraphicalDumper : public PDBSymDumper { -public: - PrettyClassLayoutGraphicalDumper(LinePrinter &P, uint32_t RecurseLevel, - uint32_t InitialOffset); - - bool start(const UDTLayoutBase &Layout); - - // Layout based symbol types. - void dump(const PDBSymbolTypeBaseClass &Symbol) override; - void dump(const PDBSymbolData &Symbol) override; - void dump(const PDBSymbolTypeVTable &Symbol) override; - - // Non layout-based symbol types. - void dump(const PDBSymbolTypeEnum &Symbol) override; - void dump(const PDBSymbolFunc &Symbol) override; - void dump(const PDBSymbolTypeTypedef &Symbol) override; - void dump(const PDBSymbolTypeUDT &Symbol) override; - void dump(const PDBSymbolTypeBuiltin &Symbol) override; - -private: - bool shouldRecurse() const; - void printPaddingRow(uint32_t Amount); - - LinePrinter &Printer; - - LayoutItemBase *CurrentItem = nullptr; - uint32_t RecursionLevel = 0; - uint32_t ClassOffsetZero = 0; - uint32_t CurrentAbsoluteOffset = 0; - bool DumpedAnything = false; -}; -} -} -#endif diff --git a/tools/llvm-pdbdump/PrettyCompilandDumper.cpp b/tools/llvm-pdbdump/PrettyCompilandDumper.cpp deleted file mode 100644 index 9cf7bf82a164..000000000000 --- a/tools/llvm-pdbdump/PrettyCompilandDumper.cpp +++ /dev/null @@ -1,207 +0,0 @@ -//===- PrettyCompilandDumper.cpp - llvm-pdbdump compiland dumper -*- C++ *-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PrettyCompilandDumper.h" - -#include "LinePrinter.h" -#include "PrettyFunctionDumper.h" -#include "llvm-pdbdump.h" - -#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" -#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" -#include "llvm/DebugInfo/PDB/IPDBSession.h" -#include "llvm/DebugInfo/PDB/IPDBSourceFile.h" -#include "llvm/DebugInfo/PDB/PDBExtras.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" -#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" -#include "llvm/DebugInfo/PDB/PDBSymbolData.h" -#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" -#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h" -#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h" -#include "llvm/DebugInfo/PDB/PDBSymbolLabel.h" -#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" -#include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" - -#include - -using namespace llvm; -using namespace llvm::pdb; - -CompilandDumper::CompilandDumper(LinePrinter &P) - : PDBSymDumper(true), Printer(P) {} - -void CompilandDumper::dump(const PDBSymbolCompilandDetails &Symbol) {} - -void CompilandDumper::dump(const PDBSymbolCompilandEnv &Symbol) {} - -void CompilandDumper::start(const PDBSymbolCompiland &Symbol, - CompilandDumpFlags opts) { - std::string FullName = Symbol.getName(); - if (Printer.IsCompilandExcluded(FullName)) - return; - - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Path).get() << FullName; - - if (opts & Flags::Lines) { - const IPDBSession &Session = Symbol.getSession(); - auto Files = Session.getSourceFilesForCompiland(Symbol); - Printer.Indent(); - while (auto File = Files->getNext()) { - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Path).get() << File->getFileName(); - - auto Lines = Session.findLineNumbers(Symbol, *File); - Printer.Indent(); - while (auto Line = Lines->getNext()) { - Printer.NewLine(); - uint32_t LineStart = Line->getLineNumber(); - uint32_t LineEnd = Line->getLineNumberEnd(); - - Printer << "Line "; - PDB_ColorItem StatementColor = Line->isStatement() - ? PDB_ColorItem::Keyword - : PDB_ColorItem::LiteralValue; - WithColor(Printer, StatementColor).get() << LineStart; - if (LineStart != LineEnd) - WithColor(Printer, StatementColor).get() << " - " << LineEnd; - - uint32_t ColumnStart = Line->getColumnNumber(); - uint32_t ColumnEnd = Line->getColumnNumberEnd(); - if (ColumnStart != 0 || ColumnEnd != 0) { - Printer << ", Column: "; - WithColor(Printer, StatementColor).get() << ColumnStart; - if (ColumnEnd != ColumnStart) - WithColor(Printer, StatementColor).get() << " - " << ColumnEnd; - } - - Printer << ", Address: "; - if (Line->getLength() > 0) { - uint64_t AddrStart = Line->getVirtualAddress(); - uint64_t AddrEnd = AddrStart + Line->getLength() - 1; - WithColor(Printer, PDB_ColorItem::Address).get() - << "[" << format_hex(AddrStart, 10) << " - " - << format_hex(AddrEnd, 10) << "]"; - Printer << " (" << Line->getLength() << " bytes)"; - } else { - uint64_t AddrStart = Line->getVirtualAddress(); - WithColor(Printer, PDB_ColorItem::Address).get() - << "[" << format_hex(AddrStart, 10) << "] "; - Printer << "(0 bytes)"; - } - } - Printer.Unindent(); - } - Printer.Unindent(); - } - - if (opts & Flags::Children) { - auto ChildrenEnum = Symbol.findAllChildren(); - Printer.Indent(); - while (auto Child = ChildrenEnum->getNext()) - Child->dump(*this); - Printer.Unindent(); - } -} - -void CompilandDumper::dump(const PDBSymbolData &Symbol) { - if (!shouldDumpSymLevel(opts::pretty::SymLevel::Data)) - return; - if (Printer.IsSymbolExcluded(Symbol.getName())) - return; - - Printer.NewLine(); - - switch (auto LocType = Symbol.getLocationType()) { - case PDB_LocType::Static: - Printer << "data: "; - WithColor(Printer, PDB_ColorItem::Address).get() - << "[" << format_hex(Symbol.getVirtualAddress(), 10) << "]"; - - WithColor(Printer, PDB_ColorItem::Comment).get() - << " [sizeof = " << getTypeLength(Symbol) << "]"; - - break; - case PDB_LocType::Constant: - Printer << "constant: "; - WithColor(Printer, PDB_ColorItem::LiteralValue).get() - << "[" << Symbol.getValue() << "]"; - WithColor(Printer, PDB_ColorItem::Comment).get() - << " [sizeof = " << getTypeLength(Symbol) << "]"; - break; - default: - Printer << "data(unexpected type=" << LocType << ")"; - } - - Printer << " "; - WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); -} - -void CompilandDumper::dump(const PDBSymbolFunc &Symbol) { - if (!shouldDumpSymLevel(opts::pretty::SymLevel::Functions)) - return; - if (Symbol.getLength() == 0) - return; - if (Printer.IsSymbolExcluded(Symbol.getName())) - return; - - Printer.NewLine(); - FunctionDumper Dumper(Printer); - Dumper.start(Symbol, FunctionDumper::PointerType::None); -} - -void CompilandDumper::dump(const PDBSymbolLabel &Symbol) { - if (Printer.IsSymbolExcluded(Symbol.getName())) - return; - - Printer.NewLine(); - Printer << "label "; - WithColor(Printer, PDB_ColorItem::Address).get() - << "[" << format_hex(Symbol.getVirtualAddress(), 10) << "] "; - WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); -} - -void CompilandDumper::dump(const PDBSymbolThunk &Symbol) { - if (!shouldDumpSymLevel(opts::pretty::SymLevel::Thunks)) - return; - if (Printer.IsSymbolExcluded(Symbol.getName())) - return; - - Printer.NewLine(); - Printer << "thunk "; - codeview::ThunkOrdinal Ordinal = Symbol.getThunkOrdinal(); - uint64_t VA = Symbol.getVirtualAddress(); - if (Ordinal == codeview::ThunkOrdinal::TrampIncremental) { - uint64_t Target = Symbol.getTargetVirtualAddress(); - WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(VA, 10); - Printer << " -> "; - WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Target, 10); - } else { - WithColor(Printer, PDB_ColorItem::Address).get() - << "[" << format_hex(VA, 10) << " - " - << format_hex(VA + Symbol.getLength(), 10) << "]"; - } - Printer << " ("; - WithColor(Printer, PDB_ColorItem::Register).get() << Ordinal; - Printer << ") "; - std::string Name = Symbol.getName(); - if (!Name.empty()) - WithColor(Printer, PDB_ColorItem::Identifier).get() << Name; -} - -void CompilandDumper::dump(const PDBSymbolTypeTypedef &Symbol) {} - -void CompilandDumper::dump(const PDBSymbolUnknown &Symbol) { - Printer.NewLine(); - Printer << "unknown (" << Symbol.getSymTag() << ")"; -} diff --git a/tools/llvm-pdbdump/PrettyCompilandDumper.h b/tools/llvm-pdbdump/PrettyCompilandDumper.h deleted file mode 100644 index 2127e7d1f529..000000000000 --- a/tools/llvm-pdbdump/PrettyCompilandDumper.h +++ /dev/null @@ -1,44 +0,0 @@ -//===- PrettyCompilandDumper.h - llvm-pdbdump compiland dumper -*- C++ --*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYCOMPILANDDUMPER_H -#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCOMPILANDDUMPER_H - -#include "llvm/DebugInfo/PDB/PDBSymDumper.h" - -namespace llvm { -namespace pdb { - -class LinePrinter; - -typedef int CompilandDumpFlags; -class CompilandDumper : public PDBSymDumper { -public: - enum Flags { None = 0x0, Children = 0x1, Symbols = 0x2, Lines = 0x4 }; - - CompilandDumper(LinePrinter &P); - - void start(const PDBSymbolCompiland &Symbol, CompilandDumpFlags flags); - - void dump(const PDBSymbolCompilandDetails &Symbol) override; - void dump(const PDBSymbolCompilandEnv &Symbol) override; - void dump(const PDBSymbolData &Symbol) override; - void dump(const PDBSymbolFunc &Symbol) override; - void dump(const PDBSymbolLabel &Symbol) override; - void dump(const PDBSymbolThunk &Symbol) override; - void dump(const PDBSymbolTypeTypedef &Symbol) override; - void dump(const PDBSymbolUnknown &Symbol) override; - -private: - LinePrinter &Printer; -}; -} -} - -#endif diff --git a/tools/llvm-pdbdump/PrettyEnumDumper.cpp b/tools/llvm-pdbdump/PrettyEnumDumper.cpp deleted file mode 100644 index 965ca1b9f989..000000000000 --- a/tools/llvm-pdbdump/PrettyEnumDumper.cpp +++ /dev/null @@ -1,53 +0,0 @@ -//===- PrettyEnumDumper.cpp -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PrettyEnumDumper.h" - -#include "LinePrinter.h" -#include "PrettyBuiltinDumper.h" -#include "llvm-pdbdump.h" - -#include "llvm/DebugInfo/PDB/PDBSymbolData.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" - -using namespace llvm; -using namespace llvm::pdb; - -EnumDumper::EnumDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {} - -void EnumDumper::start(const PDBSymbolTypeEnum &Symbol) { - WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum "; - WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); - if (!opts::pretty::NoEnumDefs) { - auto BuiltinType = Symbol.getUnderlyingType(); - if (BuiltinType->getBuiltinType() != PDB_BuiltinType::Int || - BuiltinType->getLength() != 4) { - Printer << " : "; - BuiltinDumper Dumper(Printer); - Dumper.start(*BuiltinType); - } - Printer << " {"; - Printer.Indent(); - auto EnumValues = Symbol.findAllChildren(); - while (auto EnumValue = EnumValues->getNext()) { - if (EnumValue->getDataKind() != PDB_DataKind::Constant) - continue; - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Identifier).get() - << EnumValue->getName(); - Printer << " = "; - WithColor(Printer, PDB_ColorItem::LiteralValue).get() - << EnumValue->getValue(); - } - Printer.Unindent(); - Printer.NewLine(); - Printer << "}"; - } -} diff --git a/tools/llvm-pdbdump/PrettyEnumDumper.h b/tools/llvm-pdbdump/PrettyEnumDumper.h deleted file mode 100644 index c6e65a6d1772..000000000000 --- a/tools/llvm-pdbdump/PrettyEnumDumper.h +++ /dev/null @@ -1,31 +0,0 @@ -//===- PrettyEnumDumper.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYENUMDUMPER_H -#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYENUMDUMPER_H - -#include "llvm/DebugInfo/PDB/PDBSymDumper.h" - -namespace llvm { -namespace pdb { - -class LinePrinter; - -class EnumDumper : public PDBSymDumper { -public: - EnumDumper(LinePrinter &P); - - void start(const PDBSymbolTypeEnum &Symbol); - -private: - LinePrinter &Printer; -}; -} -} -#endif diff --git a/tools/llvm-pdbdump/PrettyExternalSymbolDumper.cpp b/tools/llvm-pdbdump/PrettyExternalSymbolDumper.cpp deleted file mode 100644 index fc40d90cee96..000000000000 --- a/tools/llvm-pdbdump/PrettyExternalSymbolDumper.cpp +++ /dev/null @@ -1,41 +0,0 @@ -//===- PrettyExternalSymbolDumper.cpp -------------------------- *- C++ *-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PrettyExternalSymbolDumper.h" -#include "LinePrinter.h" - -#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" -#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h" -#include "llvm/Support/Format.h" - -using namespace llvm; -using namespace llvm::pdb; - -ExternalSymbolDumper::ExternalSymbolDumper(LinePrinter &P) - : PDBSymDumper(true), Printer(P) {} - -void ExternalSymbolDumper::start(const PDBSymbolExe &Symbol) { - auto Vars = Symbol.findAllChildren(); - while (auto Var = Vars->getNext()) - Var->dump(*this); -} - -void ExternalSymbolDumper::dump(const PDBSymbolPublicSymbol &Symbol) { - std::string LinkageName = Symbol.getName(); - if (Printer.IsSymbolExcluded(LinkageName)) - return; - - Printer.NewLine(); - uint64_t Addr = Symbol.getVirtualAddress(); - - Printer << "["; - WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Addr, 10); - Printer << "] "; - WithColor(Printer, PDB_ColorItem::Identifier).get() << LinkageName; -} diff --git a/tools/llvm-pdbdump/PrettyExternalSymbolDumper.h b/tools/llvm-pdbdump/PrettyExternalSymbolDumper.h deleted file mode 100644 index 6a009862ddd4..000000000000 --- a/tools/llvm-pdbdump/PrettyExternalSymbolDumper.h +++ /dev/null @@ -1,34 +0,0 @@ -//===- PrettyExternalSymbolDumper.h --------------------------- *- C++ --*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYEXTERNALSYMBOLDUMPER_H -#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYEXTERNALSYMBOLDUMPER_H - -#include "llvm/DebugInfo/PDB/PDBSymDumper.h" - -namespace llvm { -namespace pdb { - -class LinePrinter; - -class ExternalSymbolDumper : public PDBSymDumper { -public: - ExternalSymbolDumper(LinePrinter &P); - - void start(const PDBSymbolExe &Symbol); - - void dump(const PDBSymbolPublicSymbol &Symbol) override; - -private: - LinePrinter &Printer; -}; -} -} - -#endif diff --git a/tools/llvm-pdbdump/PrettyFunctionDumper.cpp b/tools/llvm-pdbdump/PrettyFunctionDumper.cpp deleted file mode 100644 index 8b2043989b81..000000000000 --- a/tools/llvm-pdbdump/PrettyFunctionDumper.cpp +++ /dev/null @@ -1,259 +0,0 @@ -//===- PrettyFunctionDumper.cpp --------------------------------- *- C++ *-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PrettyFunctionDumper.h" -#include "LinePrinter.h" -#include "PrettyBuiltinDumper.h" -#include "llvm-pdbdump.h" - -#include "llvm/DebugInfo/PDB/IPDBSession.h" -#include "llvm/DebugInfo/PDB/PDBExtras.h" -#include "llvm/DebugInfo/PDB/PDBSymbolData.h" -#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" -#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h" -#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/FormatVariadic.h" - -using namespace llvm; -using namespace llvm::codeview; -using namespace llvm::pdb; - -namespace { -template -void dumpClassParentWithScopeOperator(const T &Symbol, LinePrinter &Printer, - FunctionDumper &Dumper) { - uint32_t ClassParentId = Symbol.getClassParentId(); - auto ClassParent = - Symbol.getSession().template getConcreteSymbolById( - ClassParentId); - if (!ClassParent) - return; - - WithColor(Printer, PDB_ColorItem::Type).get() << ClassParent->getName(); - Printer << "::"; -} -} - -FunctionDumper::FunctionDumper(LinePrinter &P) - : PDBSymDumper(true), Printer(P) {} - -void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol, - const char *Name, PointerType Pointer) { - auto ReturnType = Symbol.getReturnType(); - ReturnType->dump(*this); - Printer << " "; - uint32_t ClassParentId = Symbol.getClassParentId(); - auto ClassParent = - Symbol.getSession().getConcreteSymbolById( - ClassParentId); - - PDB_CallingConv CC = Symbol.getCallingConvention(); - bool ShouldDumpCallingConvention = true; - if ((ClassParent && CC == CallingConvention::ThisCall) || - (!ClassParent && CC == CallingConvention::NearStdCall)) { - ShouldDumpCallingConvention = false; - } - - if (Pointer == PointerType::None) { - if (ShouldDumpCallingConvention) - WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " "; - if (ClassParent) { - Printer << "("; - WithColor(Printer, PDB_ColorItem::Identifier).get() - << ClassParent->getName(); - Printer << "::)"; - } - } else { - Printer << "("; - if (ShouldDumpCallingConvention) - WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " "; - if (ClassParent) { - WithColor(Printer, PDB_ColorItem::Identifier).get() - << ClassParent->getName(); - Printer << "::"; - } - if (Pointer == PointerType::Reference) - Printer << "&"; - else - Printer << "*"; - if (Name) - WithColor(Printer, PDB_ColorItem::Identifier).get() << Name; - Printer << ")"; - } - - Printer << "("; - if (auto ChildEnum = Symbol.getArguments()) { - uint32_t Index = 0; - while (auto Arg = ChildEnum->getNext()) { - Arg->dump(*this); - if (++Index < ChildEnum->getChildCount()) - Printer << ", "; - } - } - Printer << ")"; - - if (Symbol.isConstType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << " const"; - if (Symbol.isVolatileType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile"; -} - -void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) { - uint64_t FuncStart = Symbol.getVirtualAddress(); - uint64_t FuncEnd = FuncStart + Symbol.getLength(); - - Printer << "func ["; - WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10); - if (auto DebugStart = Symbol.findOneChild()) { - uint64_t Prologue = DebugStart->getVirtualAddress() - FuncStart; - WithColor(Printer, PDB_ColorItem::Offset).get() - << formatv("+{0,2}", Prologue); - } - Printer << " - "; - WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10); - if (auto DebugEnd = Symbol.findOneChild()) { - uint64_t Epilogue = FuncEnd - DebugEnd->getVirtualAddress(); - WithColor(Printer, PDB_ColorItem::Offset).get() - << formatv("-{0,2}", Epilogue); - } - - WithColor(Printer, PDB_ColorItem::Comment).get() - << formatv(" | sizeof={0,3}", Symbol.getLength()); - Printer << "] ("; - - if (Symbol.hasFramePointer()) { - WithColor(Printer, PDB_ColorItem::Register).get() - << Symbol.getLocalBasePointerRegisterId(); - } else { - WithColor(Printer, PDB_ColorItem::Register).get() << "FPO"; - } - Printer << ") "; - - if (Symbol.isVirtual() || Symbol.isPureVirtual()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual "; - - auto Signature = Symbol.getSignature(); - if (!Signature) { - WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); - if (Pointer == PointerType::Pointer) - Printer << "*"; - else if (Pointer == FunctionDumper::PointerType::Reference) - Printer << "&"; - return; - } - - auto ReturnType = Signature->getReturnType(); - ReturnType->dump(*this); - Printer << " "; - - auto ClassParent = Symbol.getClassParent(); - CallingConvention CC = Signature->getCallingConvention(); - if (Pointer != FunctionDumper::PointerType::None) - Printer << "("; - - if ((ClassParent && CC != CallingConvention::ThisCall) || - (!ClassParent && CC != CallingConvention::NearStdCall)) { - WithColor(Printer, PDB_ColorItem::Keyword).get() - << Signature->getCallingConvention() << " "; - } - WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); - if (Pointer != FunctionDumper::PointerType::None) { - if (Pointer == PointerType::Pointer) - Printer << "*"; - else if (Pointer == FunctionDumper::PointerType::Reference) - Printer << "&"; - Printer << ")"; - } - - Printer << "("; - if (auto Arguments = Symbol.getArguments()) { - uint32_t Index = 0; - while (auto Arg = Arguments->getNext()) { - auto ArgType = Arg->getType(); - ArgType->dump(*this); - WithColor(Printer, PDB_ColorItem::Identifier).get() << " " - << Arg->getName(); - if (++Index < Arguments->getChildCount()) - Printer << ", "; - } - } - Printer << ")"; - if (Symbol.isConstType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << " const"; - if (Symbol.isVolatileType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile"; - if (Symbol.isPureVirtual()) - Printer << " = 0"; -} - -void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol) { - auto ElementType = Symbol.getElementType(); - - ElementType->dump(*this); - Printer << "["; - WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getLength(); - Printer << "]"; -} - -void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol) { - BuiltinDumper Dumper(Printer); - Dumper.start(Symbol); -} - -void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol) { - dumpClassParentWithScopeOperator(Symbol, Printer, *this); - WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); -} - -void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol) { - // PDBSymbolTypeFunctionArg is just a shim over the real argument. Just drill - // through to the real thing and dump it. - uint32_t TypeId = Symbol.getTypeId(); - auto Type = Symbol.getSession().getSymbolById(TypeId); - if (!Type) - return; - Type->dump(*this); -} - -void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol) { - dumpClassParentWithScopeOperator(Symbol, Printer, *this); - WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); -} - -void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol) { - auto PointeeType = Symbol.getPointeeType(); - if (!PointeeType) - return; - - if (auto FuncSig = unique_dyn_cast(PointeeType)) { - FunctionDumper NestedDumper(Printer); - PointerType Pointer = - Symbol.isReference() ? PointerType::Reference : PointerType::Pointer; - NestedDumper.start(*FuncSig, nullptr, Pointer); - } else { - if (Symbol.isConstType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; - if (Symbol.isVolatileType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; - PointeeType->dump(*this); - Printer << (Symbol.isReference() ? "&" : "*"); - } -} - -void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol) { - WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); -} diff --git a/tools/llvm-pdbdump/PrettyFunctionDumper.h b/tools/llvm-pdbdump/PrettyFunctionDumper.h deleted file mode 100644 index 1a6f5430ec5a..000000000000 --- a/tools/llvm-pdbdump/PrettyFunctionDumper.h +++ /dev/null @@ -1,43 +0,0 @@ -//===- PrettyFunctionDumper.h --------------------------------- *- C++ --*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYFUNCTIONDUMPER_H -#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYFUNCTIONDUMPER_H - -#include "llvm/DebugInfo/PDB/PDBSymDumper.h" - -namespace llvm { -namespace pdb { -class LinePrinter; - -class FunctionDumper : public PDBSymDumper { -public: - FunctionDumper(LinePrinter &P); - - enum class PointerType { None, Pointer, Reference }; - - void start(const PDBSymbolTypeFunctionSig &Symbol, const char *Name, - PointerType Pointer); - void start(const PDBSymbolFunc &Symbol, PointerType Pointer); - - void dump(const PDBSymbolTypeArray &Symbol) override; - void dump(const PDBSymbolTypeBuiltin &Symbol) override; - void dump(const PDBSymbolTypeEnum &Symbol) override; - void dump(const PDBSymbolTypeFunctionArg &Symbol) override; - void dump(const PDBSymbolTypePointer &Symbol) override; - void dump(const PDBSymbolTypeTypedef &Symbol) override; - void dump(const PDBSymbolTypeUDT &Symbol) override; - -private: - LinePrinter &Printer; -}; -} -} - -#endif diff --git a/tools/llvm-pdbdump/PrettyTypeDumper.cpp b/tools/llvm-pdbdump/PrettyTypeDumper.cpp deleted file mode 100644 index cd156f051573..000000000000 --- a/tools/llvm-pdbdump/PrettyTypeDumper.cpp +++ /dev/null @@ -1,251 +0,0 @@ -//===- PrettyTypeDumper.cpp - PDBSymDumper type dumper *------------ C++ *-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PrettyTypeDumper.h" - -#include "LinePrinter.h" -#include "PrettyBuiltinDumper.h" -#include "PrettyClassDefinitionDumper.h" -#include "PrettyEnumDumper.h" -#include "PrettyTypedefDumper.h" -#include "llvm-pdbdump.h" - -#include "llvm/DebugInfo/PDB/IPDBSession.h" -#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" -#include "llvm/DebugInfo/PDB/UDTLayout.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/FormatVariadic.h" - -using namespace llvm; -using namespace llvm::pdb; - -using LayoutPtr = std::unique_ptr; - -typedef bool (*CompareFunc)(const LayoutPtr &S1, const LayoutPtr &S2); - -static bool CompareNames(const LayoutPtr &S1, const LayoutPtr &S2) { - return S1->getName() < S2->getName(); -} - -static bool CompareSizes(const LayoutPtr &S1, const LayoutPtr &S2) { - return S1->getSize() < S2->getSize(); -} - -static bool ComparePadding(const LayoutPtr &S1, const LayoutPtr &S2) { - return S1->deepPaddingSize() < S2->deepPaddingSize(); -} - -static bool ComparePaddingPct(const LayoutPtr &S1, const LayoutPtr &S2) { - double Pct1 = (double)S1->deepPaddingSize() / (double)S1->getSize(); - double Pct2 = (double)S2->deepPaddingSize() / (double)S2->getSize(); - return Pct1 < Pct2; -} - -static bool ComparePaddingImmediate(const LayoutPtr &S1, const LayoutPtr &S2) { - return S1->immediatePadding() < S2->immediatePadding(); -} - -static bool ComparePaddingPctImmediate(const LayoutPtr &S1, - const LayoutPtr &S2) { - double Pct1 = (double)S1->immediatePadding() / (double)S1->getSize(); - double Pct2 = (double)S2->immediatePadding() / (double)S2->getSize(); - return Pct1 < Pct2; -} - -static CompareFunc getComparisonFunc(opts::pretty::ClassSortMode Mode) { - switch (Mode) { - case opts::pretty::ClassSortMode::Name: - return CompareNames; - case opts::pretty::ClassSortMode::Size: - return CompareSizes; - case opts::pretty::ClassSortMode::Padding: - return ComparePadding; - case opts::pretty::ClassSortMode::PaddingPct: - return ComparePaddingPct; - case opts::pretty::ClassSortMode::PaddingImmediate: - return ComparePaddingImmediate; - case opts::pretty::ClassSortMode::PaddingPctImmediate: - return ComparePaddingPctImmediate; - default: - return nullptr; - } -} - -template -static std::vector> -filterAndSortClassDefs(LinePrinter &Printer, Enumerator &E, - uint32_t UnfilteredCount) { - std::vector> Filtered; - - Filtered.reserve(UnfilteredCount); - CompareFunc Comp = getComparisonFunc(opts::pretty::ClassOrder); - - if (UnfilteredCount > 10000) { - errs() << formatv("Filtering and sorting {0} types", UnfilteredCount); - errs().flush(); - } - uint32_t Examined = 0; - uint32_t Discarded = 0; - while (auto Class = E.getNext()) { - ++Examined; - if (Examined % 10000 == 0) { - errs() << formatv("Examined {0}/{1} items. {2} items discarded\n", - Examined, UnfilteredCount, Discarded); - errs().flush(); - } - - if (Class->getUnmodifiedTypeId() != 0) { - ++Discarded; - continue; - } - - if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) { - ++Discarded; - continue; - } - - auto Layout = llvm::make_unique(std::move(Class)); - if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold) { - ++Discarded; - continue; - } - if (Layout->immediatePadding() < opts::pretty::ImmediatePaddingThreshold) { - ++Discarded; - continue; - } - - Filtered.push_back(std::move(Layout)); - } - - if (Comp) - std::sort(Filtered.begin(), Filtered.end(), Comp); - return Filtered; -} - -TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {} - -void TypeDumper::start(const PDBSymbolExe &Exe) { - if (opts::pretty::Enums) { - auto Enums = Exe.findAllChildren(); - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Identifier).get() << "Enums"; - Printer << ": (" << Enums->getChildCount() << " items)"; - Printer.Indent(); - while (auto Enum = Enums->getNext()) - Enum->dump(*this); - Printer.Unindent(); - } - - if (opts::pretty::Typedefs) { - auto Typedefs = Exe.findAllChildren(); - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Identifier).get() << "Typedefs"; - Printer << ": (" << Typedefs->getChildCount() << " items)"; - Printer.Indent(); - while (auto Typedef = Typedefs->getNext()) - Typedef->dump(*this); - Printer.Unindent(); - } - - if (opts::pretty::Classes) { - auto Classes = Exe.findAllChildren(); - uint32_t All = Classes->getChildCount(); - - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes"; - - bool Precompute = false; - Precompute = - (opts::pretty::ClassOrder != opts::pretty::ClassSortMode::None); - - // If we're using no sort mode, then we can start getting immediate output - // from the tool by just filtering as we go, rather than processing - // everything up front so that we can sort it. This makes the tool more - // responsive. So only precompute the filtered/sorted set of classes if - // necessary due to the specified options. - std::vector Filtered; - uint32_t Shown = All; - if (Precompute) { - Filtered = filterAndSortClassDefs(Printer, *Classes, All); - - Shown = Filtered.size(); - } - - Printer << ": (Showing " << Shown << " items"; - if (Shown < All) - Printer << ", " << (All - Shown) << " filtered"; - Printer << ")"; - Printer.Indent(); - - // If we pre-computed, iterate the filtered/sorted list, otherwise iterate - // the DIA enumerator and filter on the fly. - if (Precompute) { - for (auto &Class : Filtered) - dumpClassLayout(*Class); - } else { - while (auto Class = Classes->getNext()) { - if (Class->getUnmodifiedTypeId() != 0) - continue; - - if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) - continue; - - auto Layout = llvm::make_unique(std::move(Class)); - if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold) - continue; - - dumpClassLayout(*Layout); - } - } - - Printer.Unindent(); - } -} - -void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) { - assert(opts::pretty::Enums); - - if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength())) - return; - // Dump member enums when dumping their class definition. - if (nullptr != Symbol.getClassParent()) - return; - - Printer.NewLine(); - EnumDumper Dumper(Printer); - Dumper.start(Symbol); -} - -void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) { - assert(opts::pretty::Typedefs); - - if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength())) - return; - - Printer.NewLine(); - TypedefDumper Dumper(Printer); - Dumper.start(Symbol); -} - -void TypeDumper::dumpClassLayout(const ClassLayout &Class) { - assert(opts::pretty::Classes); - - if (opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::None) { - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Keyword).get() << "class "; - WithColor(Printer, PDB_ColorItem::Identifier).get() << Class.getName(); - } else { - ClassDefinitionDumper Dumper(Printer); - Dumper.start(Class); - } -} diff --git a/tools/llvm-pdbdump/PrettyTypeDumper.h b/tools/llvm-pdbdump/PrettyTypeDumper.h deleted file mode 100644 index 68a2f0246eba..000000000000 --- a/tools/llvm-pdbdump/PrettyTypeDumper.h +++ /dev/null @@ -1,36 +0,0 @@ -//===- PrettyTypeDumper.h - PDBSymDumper implementation for types *- C++ *-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDUMPER_H -#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDUMPER_H - -#include "llvm/DebugInfo/PDB/PDBSymDumper.h" - -namespace llvm { -namespace pdb { -class LinePrinter; -class ClassLayout; - -class TypeDumper : public PDBSymDumper { -public: - TypeDumper(LinePrinter &P); - - void start(const PDBSymbolExe &Exe); - - void dump(const PDBSymbolTypeEnum &Symbol) override; - void dump(const PDBSymbolTypeTypedef &Symbol) override; - - void dumpClassLayout(const ClassLayout &Class); - -private: - LinePrinter &Printer; -}; -} -} -#endif diff --git a/tools/llvm-pdbdump/PrettyTypedefDumper.cpp b/tools/llvm-pdbdump/PrettyTypedefDumper.cpp deleted file mode 100644 index 2d8e915d7604..000000000000 --- a/tools/llvm-pdbdump/PrettyTypedefDumper.cpp +++ /dev/null @@ -1,77 +0,0 @@ -//===- PrettyTypedefDumper.cpp - PDBSymDumper impl for typedefs -- * C++ *-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PrettyTypedefDumper.h" - -#include "LinePrinter.h" -#include "PrettyBuiltinDumper.h" -#include "PrettyFunctionDumper.h" -#include "llvm-pdbdump.h" - -#include "llvm/DebugInfo/PDB/IPDBSession.h" -#include "llvm/DebugInfo/PDB/PDBExtras.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" - -using namespace llvm; -using namespace llvm::pdb; - -TypedefDumper::TypedefDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {} - -void TypedefDumper::start(const PDBSymbolTypeTypedef &Symbol) { - WithColor(Printer, PDB_ColorItem::Keyword).get() << "typedef "; - uint32_t TargetId = Symbol.getTypeId(); - if (auto TypeSymbol = Symbol.getSession().getSymbolById(TargetId)) - TypeSymbol->dump(*this); - WithColor(Printer, PDB_ColorItem::Identifier).get() << " " - << Symbol.getName(); -} - -void TypedefDumper::dump(const PDBSymbolTypeArray &Symbol) {} - -void TypedefDumper::dump(const PDBSymbolTypeBuiltin &Symbol) { - BuiltinDumper Dumper(Printer); - Dumper.start(Symbol); -} - -void TypedefDumper::dump(const PDBSymbolTypeEnum &Symbol) { - WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum "; - WithColor(Printer, PDB_ColorItem::Type).get() << " " << Symbol.getName(); -} - -void TypedefDumper::dump(const PDBSymbolTypePointer &Symbol) { - if (Symbol.isConstType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; - if (Symbol.isVolatileType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; - auto PointeeType = Symbol.getPointeeType(); - if (auto FuncSig = unique_dyn_cast(PointeeType)) { - FunctionDumper::PointerType Pointer = FunctionDumper::PointerType::Pointer; - if (Symbol.isReference()) - Pointer = FunctionDumper::PointerType::Reference; - FunctionDumper NestedDumper(Printer); - NestedDumper.start(*FuncSig, nullptr, Pointer); - } else { - PointeeType->dump(*this); - Printer << ((Symbol.isReference()) ? "&" : "*"); - } -} - -void TypedefDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) { - FunctionDumper Dumper(Printer); - Dumper.start(Symbol, nullptr, FunctionDumper::PointerType::None); -} - -void TypedefDumper::dump(const PDBSymbolTypeUDT &Symbol) { - WithColor(Printer, PDB_ColorItem::Keyword).get() << "class "; - WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); -} diff --git a/tools/llvm-pdbdump/PrettyTypedefDumper.h b/tools/llvm-pdbdump/PrettyTypedefDumper.h deleted file mode 100644 index 34c139601301..000000000000 --- a/tools/llvm-pdbdump/PrettyTypedefDumper.h +++ /dev/null @@ -1,39 +0,0 @@ -//===- PrettyTypedefDumper.h - llvm-pdbdump typedef dumper ---*- C++ ----*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDEFDUMPER_H -#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDEFDUMPER_H - -#include "llvm/DebugInfo/PDB/PDBSymDumper.h" - -namespace llvm { -namespace pdb { - -class LinePrinter; - -class TypedefDumper : public PDBSymDumper { -public: - TypedefDumper(LinePrinter &P); - - void start(const PDBSymbolTypeTypedef &Symbol); - - void dump(const PDBSymbolTypeArray &Symbol) override; - void dump(const PDBSymbolTypeBuiltin &Symbol) override; - void dump(const PDBSymbolTypeEnum &Symbol) override; - void dump(const PDBSymbolTypeFunctionSig &Symbol) override; - void dump(const PDBSymbolTypePointer &Symbol) override; - void dump(const PDBSymbolTypeUDT &Symbol) override; - -private: - LinePrinter &Printer; -}; -} -} - -#endif diff --git a/tools/llvm-pdbdump/PrettyVariableDumper.cpp b/tools/llvm-pdbdump/PrettyVariableDumper.cpp deleted file mode 100644 index 70925f4b03d0..000000000000 --- a/tools/llvm-pdbdump/PrettyVariableDumper.cpp +++ /dev/null @@ -1,220 +0,0 @@ -//===- PrettyVariableDumper.cpp ---------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PrettyVariableDumper.h" - -#include "LinePrinter.h" -#include "PrettyBuiltinDumper.h" -#include "PrettyFunctionDumper.h" -#include "llvm-pdbdump.h" - -#include "llvm/DebugInfo/PDB/IPDBSession.h" -#include "llvm/DebugInfo/PDB/PDBSymbolData.h" -#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" -#include "llvm/DebugInfo/PDB/PDBTypes.h" - -#include "llvm/Support/Format.h" - -using namespace llvm; -using namespace llvm::codeview; -using namespace llvm::pdb; - -VariableDumper::VariableDumper(LinePrinter &P) - : PDBSymDumper(true), Printer(P) {} - -void VariableDumper::start(const PDBSymbolData &Var, uint32_t Offset) { - if (Var.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated) - return; - if (Printer.IsSymbolExcluded(Var.getName())) - return; - - auto VarType = Var.getType(); - - uint64_t Length = VarType->getRawSymbol().getLength(); - - switch (auto LocType = Var.getLocationType()) { - case PDB_LocType::Static: - Printer.NewLine(); - Printer << "data ["; - WithColor(Printer, PDB_ColorItem::Address).get() - << format_hex(Var.getVirtualAddress(), 10); - Printer << ", sizeof=" << Length << "] "; - WithColor(Printer, PDB_ColorItem::Keyword).get() << "static "; - dumpSymbolTypeAndName(*VarType, Var.getName()); - break; - case PDB_LocType::Constant: - if (isa(*VarType)) - break; - Printer.NewLine(); - Printer << "data [sizeof=" << Length << "] "; - dumpSymbolTypeAndName(*VarType, Var.getName()); - Printer << " = "; - WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getValue(); - break; - case PDB_LocType::ThisRel: - Printer.NewLine(); - Printer << "data "; - WithColor(Printer, PDB_ColorItem::Offset).get() - << "+" << format_hex(Offset + Var.getOffset(), 4) - << " [sizeof=" << Length << "] "; - dumpSymbolTypeAndName(*VarType, Var.getName()); - break; - case PDB_LocType::BitField: - Printer.NewLine(); - Printer << "data "; - WithColor(Printer, PDB_ColorItem::Offset).get() - << "+" << format_hex(Offset + Var.getOffset(), 4) - << " [sizeof=" << Length << "] "; - dumpSymbolTypeAndName(*VarType, Var.getName()); - Printer << " : "; - WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getLength(); - break; - default: - Printer.NewLine(); - Printer << "data [sizeof=" << Length << "] "; - Printer << "unknown(" << LocType << ") "; - WithColor(Printer, PDB_ColorItem::Identifier).get() << Var.getName(); - break; - } -} - -void VariableDumper::startVbptr(uint32_t Offset, uint32_t Size) { - Printer.NewLine(); - Printer << "vbptr "; - - WithColor(Printer, PDB_ColorItem::Offset).get() - << "+" << format_hex(Offset, 4) << " [sizeof=" << Size << "] "; -} - -void VariableDumper::start(const PDBSymbolTypeVTable &Var, uint32_t Offset) { - Printer.NewLine(); - Printer << "vfptr "; - auto VTableType = cast(Var.getType()); - uint32_t PointerSize = VTableType->getLength(); - - WithColor(Printer, PDB_ColorItem::Offset).get() - << "+" << format_hex(Offset + Var.getOffset(), 4) - << " [sizeof=" << PointerSize << "] "; -} - -void VariableDumper::dump(const PDBSymbolTypeArray &Symbol) { - auto ElementType = Symbol.getElementType(); - assert(ElementType); - if (!ElementType) - return; - ElementType->dump(*this); -} - -void VariableDumper::dumpRight(const PDBSymbolTypeArray &Symbol) { - auto ElementType = Symbol.getElementType(); - assert(ElementType); - if (!ElementType) - return; - Printer << '[' << Symbol.getCount() << ']'; - ElementType->dumpRight(*this); -} - -void VariableDumper::dump(const PDBSymbolTypeBuiltin &Symbol) { - BuiltinDumper Dumper(Printer); - Dumper.start(Symbol); -} - -void VariableDumper::dump(const PDBSymbolTypeEnum &Symbol) { - WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); -} - -void VariableDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) { - auto ReturnType = Symbol.getReturnType(); - ReturnType->dump(*this); - Printer << " "; - - uint32_t ClassParentId = Symbol.getClassParentId(); - auto ClassParent = - Symbol.getSession().getConcreteSymbolById( - ClassParentId); - - if (ClassParent) { - WithColor(Printer, PDB_ColorItem::Identifier).get() - << ClassParent->getName(); - Printer << "::"; - } -} - -void VariableDumper::dumpRight(const PDBSymbolTypeFunctionSig &Symbol) { - Printer << "("; - if (auto Arguments = Symbol.getArguments()) { - uint32_t Index = 0; - while (auto Arg = Arguments->getNext()) { - Arg->dump(*this); - if (++Index < Arguments->getChildCount()) - Printer << ", "; - } - } - Printer << ")"; - - if (Symbol.isConstType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << " const"; - if (Symbol.isVolatileType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile"; -} - -void VariableDumper::dump(const PDBSymbolTypePointer &Symbol) { - auto PointeeType = Symbol.getPointeeType(); - if (!PointeeType) - return; - PointeeType->dump(*this); - if (auto FuncSig = unique_dyn_cast(PointeeType)) { - // A hack to get the calling convention in the right spot. - Printer << " ("; - PDB_CallingConv CC = FuncSig->getCallingConvention(); - WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " "; - } else if (isa(PointeeType)) { - Printer << " ("; - } - Printer << (Symbol.isReference() ? "&" : "*"); - if (Symbol.isConstType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << " const "; - if (Symbol.isVolatileType()) - WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile "; -} - -void VariableDumper::dumpRight(const PDBSymbolTypePointer &Symbol) { - auto PointeeType = Symbol.getPointeeType(); - assert(PointeeType); - if (!PointeeType) - return; - if (isa(PointeeType) || - isa(PointeeType)) { - Printer << ")"; - } - PointeeType->dumpRight(*this); -} - -void VariableDumper::dump(const PDBSymbolTypeTypedef &Symbol) { - WithColor(Printer, PDB_ColorItem::Keyword).get() << "typedef "; - WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); -} - -void VariableDumper::dump(const PDBSymbolTypeUDT &Symbol) { - WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); -} - -void VariableDumper::dumpSymbolTypeAndName(const PDBSymbol &Type, - StringRef Name) { - Type.dump(*this); - WithColor(Printer, PDB_ColorItem::Identifier).get() << " " << Name; - Type.dumpRight(*this); -} diff --git a/tools/llvm-pdbdump/PrettyVariableDumper.h b/tools/llvm-pdbdump/PrettyVariableDumper.h deleted file mode 100644 index cacf1ce9577b..000000000000 --- a/tools/llvm-pdbdump/PrettyVariableDumper.h +++ /dev/null @@ -1,50 +0,0 @@ -//===- PrettyVariableDumper.h - PDBSymDumper variable dumper ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYVARIABLEDUMPER_H -#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYVARIABLEDUMPER_H - -#include "llvm/DebugInfo/PDB/PDBSymDumper.h" - -namespace llvm { - -class StringRef; - -namespace pdb { - -class LinePrinter; - -class VariableDumper : public PDBSymDumper { -public: - VariableDumper(LinePrinter &P); - - void start(const PDBSymbolData &Var, uint32_t Offset = 0); - void start(const PDBSymbolTypeVTable &Var, uint32_t Offset = 0); - void startVbptr(uint32_t Offset, uint32_t Size); - - void dump(const PDBSymbolTypeArray &Symbol) override; - void dump(const PDBSymbolTypeBuiltin &Symbol) override; - void dump(const PDBSymbolTypeEnum &Symbol) override; - void dump(const PDBSymbolTypeFunctionSig &Symbol) override; - void dump(const PDBSymbolTypePointer &Symbol) override; - void dump(const PDBSymbolTypeTypedef &Symbol) override; - void dump(const PDBSymbolTypeUDT &Symbol) override; - - void dumpRight(const PDBSymbolTypeArray &Symbol) override; - void dumpRight(const PDBSymbolTypeFunctionSig &Symbol) override; - void dumpRight(const PDBSymbolTypePointer &Symbol) override; - -private: - void dumpSymbolTypeAndName(const PDBSymbol &Type, StringRef Name); - - LinePrinter &Printer; -}; -} -} -#endif diff --git a/tools/llvm-pdbdump/StreamUtil.cpp b/tools/llvm-pdbdump/StreamUtil.cpp deleted file mode 100644 index 81aa256b5002..000000000000 --- a/tools/llvm-pdbdump/StreamUtil.cpp +++ /dev/null @@ -1,139 +0,0 @@ -//===- StreamUtil.cpp - PDB stream utilities --------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "StreamUtil.h" - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseMapInfo.h" -#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" -#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h" -#include "llvm/DebugInfo/PDB/Native/DbiStream.h" -#include "llvm/DebugInfo/PDB/Native/InfoStream.h" -#include "llvm/DebugInfo/PDB/Native/PDBFile.h" -#include "llvm/DebugInfo/PDB/Native/TpiStream.h" - -namespace llvm { -namespace pdb { -void discoverStreamPurposes(PDBFile &File, - SmallVectorImpl &Purposes) { - - // It's OK if we fail to load some of these streams, we still attempt to print - // what we can. - auto Dbi = File.getPDBDbiStream(); - auto Tpi = File.getPDBTpiStream(); - auto Ipi = File.getPDBIpiStream(); - auto Info = File.getPDBInfoStream(); - - uint32_t StreamCount = File.getNumStreams(); - DenseMap ModStreams; - DenseMap NamedStreams; - - if (Dbi) { - const DbiModuleList &Modules = Dbi->modules(); - for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) { - DbiModuleDescriptor Descriptor = Modules.getModuleDescriptor(I); - uint16_t SN = Descriptor.getModuleStreamIndex(); - if (SN != kInvalidStreamIndex) - ModStreams[SN] = Descriptor; - } - } - if (Info) { - for (auto &NSE : Info->named_streams()) { - if (NSE.second != kInvalidStreamIndex) - NamedStreams[NSE.second] = NSE.first(); - } - } - - Purposes.resize(StreamCount); - for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) { - std::string Value; - if (StreamIdx == OldMSFDirectory) - Value = "Old MSF Directory"; - else if (StreamIdx == StreamPDB) - Value = "PDB Stream"; - else if (StreamIdx == StreamDBI) - Value = "DBI Stream"; - else if (StreamIdx == StreamTPI) - Value = "TPI Stream"; - else if (StreamIdx == StreamIPI) - Value = "IPI Stream"; - else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex()) - Value = "Global Symbol Hash"; - else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex()) - Value = "Public Symbol Hash"; - else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex()) - Value = "Public Symbol Records"; - else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex()) - Value = "TPI Hash"; - else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex()) - Value = "TPI Aux Hash"; - else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex()) - Value = "IPI Hash"; - else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex()) - Value = "IPI Aux Hash"; - else if (Dbi && - StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception)) - Value = "Exception Data"; - else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup)) - Value = "Fixup Data"; - else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO)) - Value = "FPO Data"; - else if (Dbi && - StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO)) - Value = "New FPO Data"; - else if (Dbi && - StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc)) - Value = "Omap From Source Data"; - else if (Dbi && - StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc)) - Value = "Omap To Source Data"; - else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata)) - Value = "Pdata"; - else if (Dbi && - StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr)) - Value = "Section Header Data"; - else if (Dbi && - StreamIdx == - Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig)) - Value = "Section Header Original Data"; - else if (Dbi && - StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap)) - Value = "Token Rid Data"; - else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata)) - Value = "Xdata"; - else { - auto ModIter = ModStreams.find(StreamIdx); - auto NSIter = NamedStreams.find(StreamIdx); - if (ModIter != ModStreams.end()) { - Value = "Module \""; - Value += ModIter->second.getModuleName(); - Value += "\""; - } else if (NSIter != NamedStreams.end()) { - Value = "Named Stream \""; - Value += NSIter->second; - Value += "\""; - } else { - Value = "???"; - } - } - Purposes[StreamIdx] = Value; - } - - // Consume errors from missing streams. - if (!Dbi) - consumeError(Dbi.takeError()); - if (!Tpi) - consumeError(Tpi.takeError()); - if (!Ipi) - consumeError(Ipi.takeError()); - if (!Info) - consumeError(Info.takeError()); -} -} -} diff --git a/tools/llvm-pdbdump/StreamUtil.h b/tools/llvm-pdbdump/StreamUtil.h deleted file mode 100644 index b5c0beba44fe..000000000000 --- a/tools/llvm-pdbdump/StreamUtil.h +++ /dev/null @@ -1,25 +0,0 @@ -//===- Streamutil.h - PDB stream utilities ----------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_STREAMUTIL_H -#define LLVM_TOOLS_LLVMPDBDUMP_STREAMUTIL_H - -#include "llvm/ADT/SmallVector.h" - -#include - -namespace llvm { -namespace pdb { -class PDBFile; -void discoverStreamPurposes(PDBFile &File, - SmallVectorImpl &Purposes); -} -} - -#endif diff --git a/tools/llvm-pdbdump/YAMLOutputStyle.cpp b/tools/llvm-pdbdump/YAMLOutputStyle.cpp deleted file mode 100644 index ee72b90b12d1..000000000000 --- a/tools/llvm-pdbdump/YAMLOutputStyle.cpp +++ /dev/null @@ -1,322 +0,0 @@ -//===- YAMLOutputStyle.cpp ------------------------------------ *- C++ --*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "YAMLOutputStyle.h" - -#include "C13DebugFragmentVisitor.h" -#include "PdbYaml.h" -#include "llvm-pdbdump.h" - -#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" -#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h" -#include "llvm/DebugInfo/CodeView/Line.h" -#include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/PDB/Native/DbiStream.h" -#include "llvm/DebugInfo/PDB/Native/InfoStream.h" -#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" -#include "llvm/DebugInfo/PDB/Native/PDBFile.h" -#include "llvm/DebugInfo/PDB/Native/RawConstants.h" -#include "llvm/DebugInfo/PDB/Native/RawError.h" -#include "llvm/DebugInfo/PDB/Native/TpiStream.h" - -using namespace llvm; -using namespace llvm::codeview; -using namespace llvm::pdb; - -YAMLOutputStyle::YAMLOutputStyle(PDBFile &File) - : File(File), Out(outs()), Obj(File.getAllocator()) { - Out.setWriteDefaultValues(!opts::pdb2yaml::Minimal); -} - -Error YAMLOutputStyle::dump() { - if (opts::pdb2yaml::All) { - opts::pdb2yaml::StreamMetadata = true; - opts::pdb2yaml::StreamDirectory = true; - opts::pdb2yaml::PdbStream = true; - opts::pdb2yaml::StringTable = true; - opts::pdb2yaml::DbiStream = true; - opts::pdb2yaml::DbiModuleInfo = true; - opts::pdb2yaml::DbiModuleSyms = true; - opts::pdb2yaml::DbiModuleSourceFileInfo = true; - opts::pdb2yaml::DbiModuleSourceLineInfo = true; - opts::pdb2yaml::TpiStream = true; - opts::pdb2yaml::IpiStream = true; - } - - if (opts::pdb2yaml::StreamDirectory) - opts::pdb2yaml::StreamMetadata = true; - if (opts::pdb2yaml::DbiModuleSyms) - opts::pdb2yaml::DbiModuleInfo = true; - - if (opts::pdb2yaml::DbiModuleSourceLineInfo) - opts::pdb2yaml::DbiModuleSourceFileInfo = true; - - if (opts::pdb2yaml::DbiModuleSourceFileInfo) - opts::pdb2yaml::DbiModuleInfo = true; - - if (opts::pdb2yaml::DbiModuleInfo) - opts::pdb2yaml::DbiStream = true; - - // Some names from the module source file info get pulled from the string - // table, so if we're writing module source info, we have to write the string - // table as well. - if (opts::pdb2yaml::DbiModuleSourceLineInfo) - opts::pdb2yaml::StringTable = true; - - if (auto EC = dumpFileHeaders()) - return EC; - - if (auto EC = dumpStreamMetadata()) - return EC; - - if (auto EC = dumpStreamDirectory()) - return EC; - - if (auto EC = dumpStringTable()) - return EC; - - if (auto EC = dumpPDBStream()) - return EC; - - if (auto EC = dumpDbiStream()) - return EC; - - if (auto EC = dumpTpiStream()) - return EC; - - if (auto EC = dumpIpiStream()) - return EC; - - flush(); - return Error::success(); -} - - -Error YAMLOutputStyle::dumpFileHeaders() { - if (opts::pdb2yaml::NoFileHeaders) - return Error::success(); - - yaml::MSFHeaders Headers; - Obj.Headers.emplace(); - Obj.Headers->SuperBlock.NumBlocks = File.getBlockCount(); - Obj.Headers->SuperBlock.BlockMapAddr = File.getBlockMapIndex(); - Obj.Headers->SuperBlock.BlockSize = File.getBlockSize(); - auto Blocks = File.getDirectoryBlockArray(); - Obj.Headers->DirectoryBlocks.assign(Blocks.begin(), Blocks.end()); - Obj.Headers->NumDirectoryBlocks = File.getNumDirectoryBlocks(); - Obj.Headers->SuperBlock.NumDirectoryBytes = File.getNumDirectoryBytes(); - Obj.Headers->NumStreams = - opts::pdb2yaml::StreamMetadata ? File.getNumStreams() : 0; - Obj.Headers->SuperBlock.FreeBlockMapBlock = File.getFreeBlockMapBlock(); - Obj.Headers->SuperBlock.Unknown1 = File.getUnknown1(); - Obj.Headers->FileSize = File.getFileSize(); - - return Error::success(); -} - -Error YAMLOutputStyle::dumpStringTable() { - bool RequiresStringTable = opts::pdb2yaml::DbiModuleSourceFileInfo || - opts::pdb2yaml::DbiModuleSourceLineInfo; - bool RequestedStringTable = opts::pdb2yaml::StringTable; - if (!RequiresStringTable && !RequestedStringTable) - return Error::success(); - - auto ExpectedST = File.getStringTable(); - if (!ExpectedST) - return ExpectedST.takeError(); - - Obj.StringTable.emplace(); - const auto &ST = ExpectedST.get(); - for (auto ID : ST.name_ids()) { - auto S = ST.getStringForID(ID); - if (!S) - return S.takeError(); - if (S->empty()) - continue; - Obj.StringTable->push_back(*S); - } - return Error::success(); -} - -Error YAMLOutputStyle::dumpStreamMetadata() { - if (!opts::pdb2yaml::StreamMetadata) - return Error::success(); - - Obj.StreamSizes.emplace(); - Obj.StreamSizes->assign(File.getStreamSizes().begin(), - File.getStreamSizes().end()); - return Error::success(); -} - -Error YAMLOutputStyle::dumpStreamDirectory() { - if (!opts::pdb2yaml::StreamDirectory) - return Error::success(); - - auto StreamMap = File.getStreamMap(); - Obj.StreamMap.emplace(); - for (auto &Stream : StreamMap) { - pdb::yaml::StreamBlockList BlockList; - BlockList.Blocks.assign(Stream.begin(), Stream.end()); - Obj.StreamMap->push_back(BlockList); - } - - return Error::success(); -} - -Error YAMLOutputStyle::dumpPDBStream() { - if (!opts::pdb2yaml::PdbStream) - return Error::success(); - - auto IS = File.getPDBInfoStream(); - if (!IS) - return IS.takeError(); - - auto &InfoS = IS.get(); - Obj.PdbStream.emplace(); - Obj.PdbStream->Age = InfoS.getAge(); - Obj.PdbStream->Guid = InfoS.getGuid(); - Obj.PdbStream->Signature = InfoS.getSignature(); - Obj.PdbStream->Version = InfoS.getVersion(); - Obj.PdbStream->Features = InfoS.getFeatureSignatures(); - - return Error::success(); -} - -Error YAMLOutputStyle::dumpDbiStream() { - if (!opts::pdb2yaml::DbiStream) - return Error::success(); - - auto DbiS = File.getPDBDbiStream(); - if (!DbiS) - return DbiS.takeError(); - - auto &DS = DbiS.get(); - Obj.DbiStream.emplace(); - Obj.DbiStream->Age = DS.getAge(); - Obj.DbiStream->BuildNumber = DS.getBuildNumber(); - Obj.DbiStream->Flags = DS.getFlags(); - Obj.DbiStream->MachineType = DS.getMachineType(); - Obj.DbiStream->PdbDllRbld = DS.getPdbDllRbld(); - Obj.DbiStream->PdbDllVersion = DS.getPdbDllVersion(); - Obj.DbiStream->VerHeader = DS.getDbiVersion(); - if (opts::pdb2yaml::DbiModuleInfo) { - const auto &Modules = DS.modules(); - for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) { - DbiModuleDescriptor MI = Modules.getModuleDescriptor(I); - - Obj.DbiStream->ModInfos.emplace_back(); - yaml::PdbDbiModuleInfo &DMI = Obj.DbiStream->ModInfos.back(); - - DMI.Mod = MI.getModuleName(); - DMI.Obj = MI.getObjFileName(); - if (opts::pdb2yaml::DbiModuleSourceFileInfo) { - auto Files = Modules.source_files(I); - DMI.SourceFiles.assign(Files.begin(), Files.end()); - } - - uint16_t ModiStream = MI.getModuleStreamIndex(); - if (ModiStream == kInvalidStreamIndex) - continue; - - auto ModStreamData = msf::MappedBlockStream::createIndexedStream( - File.getMsfLayout(), File.getMsfBuffer(), ModiStream, - File.getAllocator()); - - pdb::ModuleDebugStreamRef ModS(MI, std::move(ModStreamData)); - if (auto EC = ModS.reload()) - return EC; - - auto ExpectedST = File.getStringTable(); - if (!ExpectedST) - return ExpectedST.takeError(); - if (opts::pdb2yaml::DbiModuleSourceLineInfo && - ModS.hasDebugSubsections()) { - auto ExpectedChecksums = ModS.findChecksumsSubsection(); - if (!ExpectedChecksums) - return ExpectedChecksums.takeError(); - - for (const auto &SS : ModS.subsections()) { - auto Converted = - CodeViewYAML::YAMLDebugSubsection::fromCodeViewSubection( - ExpectedST->getStringTable(), *ExpectedChecksums, SS); - if (!Converted) - return Converted.takeError(); - DMI.Subsections.push_back(*Converted); - } - } - - if (opts::pdb2yaml::DbiModuleSyms) { - DMI.Modi.emplace(); - - DMI.Modi->Signature = ModS.signature(); - bool HadError = false; - for (auto &Sym : ModS.symbols(&HadError)) { - auto ES = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(Sym); - if (!ES) - return ES.takeError(); - - DMI.Modi->Symbols.push_back(*ES); - } - } - } - } - return Error::success(); -} - -Error YAMLOutputStyle::dumpTpiStream() { - if (!opts::pdb2yaml::TpiStream) - return Error::success(); - - auto TpiS = File.getPDBTpiStream(); - if (!TpiS) - return TpiS.takeError(); - - auto &TS = TpiS.get(); - Obj.TpiStream.emplace(); - Obj.TpiStream->Version = TS.getTpiVersion(); - for (auto &Record : TS.types(nullptr)) { - auto ExpectedRecord = CodeViewYAML::LeafRecord::fromCodeViewRecord(Record); - if (!ExpectedRecord) - return ExpectedRecord.takeError(); - Obj.TpiStream->Records.push_back(*ExpectedRecord); - } - - return Error::success(); -} - -Error YAMLOutputStyle::dumpIpiStream() { - if (!opts::pdb2yaml::IpiStream) - return Error::success(); - - auto IpiS = File.getPDBIpiStream(); - if (!IpiS) - return IpiS.takeError(); - - auto &IS = IpiS.get(); - Obj.IpiStream.emplace(); - Obj.IpiStream->Version = IS.getTpiVersion(); - for (auto &Record : IS.types(nullptr)) { - auto ExpectedRecord = CodeViewYAML::LeafRecord::fromCodeViewRecord(Record); - if (!ExpectedRecord) - return ExpectedRecord.takeError(); - - Obj.IpiStream->Records.push_back(*ExpectedRecord); - } - - return Error::success(); -} - -void YAMLOutputStyle::flush() { - Out << Obj; - outs().flush(); -} diff --git a/tools/llvm-pdbdump/YAMLOutputStyle.h b/tools/llvm-pdbdump/YAMLOutputStyle.h deleted file mode 100644 index 3690e3529d4a..000000000000 --- a/tools/llvm-pdbdump/YAMLOutputStyle.h +++ /dev/null @@ -1,49 +0,0 @@ -//===- YAMLOutputStyle.h -------------------------------------- *- C++ --*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_YAMLOUTPUTSTYLE_H -#define LLVM_TOOLS_LLVMPDBDUMP_YAMLOUTPUTSTYLE_H - -#include "OutputStyle.h" -#include "PdbYaml.h" - -#include "llvm/Support/ScopedPrinter.h" -#include "llvm/Support/YAMLTraits.h" - -namespace llvm { -namespace pdb { -class ModuleDebugStreamRef; - -class YAMLOutputStyle : public OutputStyle { -public: - YAMLOutputStyle(PDBFile &File); - - Error dump() override; - -private: - Error dumpStringTable(); - Error dumpFileHeaders(); - Error dumpStreamMetadata(); - Error dumpStreamDirectory(); - Error dumpPDBStream(); - Error dumpDbiStream(); - Error dumpTpiStream(); - Error dumpIpiStream(); - - void flush(); - - PDBFile &File; - llvm::yaml::Output Out; - - yaml::PdbObject Obj; -}; -} // namespace pdb -} // namespace llvm - -#endif // LLVM_TOOLS_LLVMPDBDUMP_YAMLOUTPUTSTYLE_H diff --git a/tools/llvm-pdbdump/fuzzer/CMakeLists.txt b/tools/llvm-pdbdump/fuzzer/CMakeLists.txt deleted file mode 100644 index cf5a0f70aab3..000000000000 --- a/tools/llvm-pdbdump/fuzzer/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -set(LLVM_LINK_COMPONENTS - DebugInfoCodeView - DebugInfoPDB - Object - Support - ) - -add_llvm_executable(llvm-pdbdump-fuzzer - EXCLUDE_FROM_ALL - llvm-pdbdump-fuzzer.cpp - ) - -target_link_libraries(llvm-pdbdump-fuzzer - LLVMFuzzer - ) diff --git a/tools/llvm-pdbdump/fuzzer/llvm-pdbdump-fuzzer.cpp b/tools/llvm-pdbdump/fuzzer/llvm-pdbdump-fuzzer.cpp deleted file mode 100644 index 5f09416a9ff6..000000000000 --- a/tools/llvm-pdbdump/fuzzer/llvm-pdbdump-fuzzer.cpp +++ /dev/null @@ -1,105 +0,0 @@ -//===-- llvm-pdbdump-fuzzer.cpp - Fuzz the llvm-pdbdump tool --------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief This file implements a function that runs llvm-pdbdump -/// on a single input. This function is then linked into the Fuzzer library. -/// -//===----------------------------------------------------------------------===// -#include "llvm/ADT/STLExtras.h" -#include "llvm/DebugInfo/CodeView/BinaryByteStream.h" -#include "llvm/DebugInfo/CodeView/SymbolDumper.h" -#include "llvm/DebugInfo/CodeView/TypeDumper.h" -#include "llvm/DebugInfo/PDB/Raw/DbiStream.h" -#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h" -#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" -#include "llvm/DebugInfo/PDB/Raw/ModuleDebugStream.h" -#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" -#include "llvm/DebugInfo/PDB/Raw/RawSession.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/ScopedPrinter.h" - -using namespace llvm; - -namespace { -// We need a class which behaves like an immutable BinaryByteStream, but whose -// data -// is backed by an llvm::MemoryBuffer. It also needs to own the underlying -// MemoryBuffer, so this simple adapter is a good way to achieve that. -class InputByteStream : public codeview::BinaryByteStream { -public: - explicit InputByteStream(std::unique_ptr Buffer) - : BinaryByteStream(ArrayRef(Buffer->getBuffer().bytes_begin(), - Buffer->getBuffer().bytes_end())), - MemBuffer(std::move(Buffer)) {} - - std::unique_ptr MemBuffer; -}; -} - -extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) { - std::unique_ptr Buff = MemoryBuffer::getMemBuffer( - StringRef((const char *)data, size), "", false); - - ScopedPrinter P(nulls()); - codeview::CVTypeDumper TD(&P, false); - - auto InputStream = llvm::make_unique(std::move(Buff)); - std::unique_ptr File(new pdb::PDBFile(std::move(InputStream))); - if (auto E = File->parseFileHeaders()) { - consumeError(std::move(E)); - return 0; - } - if (auto E = File->parseStreamData()) { - consumeError(std::move(E)); - return 0; - } - - auto DbiS = File->getPDBDbiStream(); - if (auto E = DbiS.takeError()) { - consumeError(std::move(E)); - return 0; - } - auto TpiS = File->getPDBTpiStream(); - if (auto E = TpiS.takeError()) { - consumeError(std::move(E)); - return 0; - } - auto IpiS = File->getPDBIpiStream(); - if (auto E = IpiS.takeError()) { - consumeError(std::move(E)); - return 0; - } - auto InfoS = File->getPDBInfoStream(); - if (auto E = InfoS.takeError()) { - consumeError(std::move(E)); - return 0; - } - pdb::DbiStream &DS = DbiS.get(); - - for (auto &Modi : DS.modules()) { - auto ModStreamData = pdb::MappedBlockStream::createIndexedStream( - Modi.Info.getModuleStreamIndex(), *File, File->getAllocator()); - if (!ModStreamData) { - consumeError(ModStreamData.takeError()); - return 0; - } - pdb::ModuleDebugStreamRef ModS(Modi.Info, std::move(*ModStreamData)); - if (auto E = ModS.reload()) { - consumeError(std::move(E)); - return 0; - } - codeview::CVSymbolDumper SD(P, TD, nullptr, false); - bool HadError = false; - for (auto &S : ModS.symbols(&HadError)) { - SD.dump(S); - } - } - return 0; -} diff --git a/tools/llvm-pdbdump/llvm-pdbdump.cpp b/tools/llvm-pdbdump/llvm-pdbdump.cpp deleted file mode 100644 index 4626de9c4440..000000000000 --- a/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ /dev/null @@ -1,981 +0,0 @@ -//===- llvm-pdbdump.cpp - Dump debug info from a PDB file -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Dumps debug information present in PDB files. -// -//===----------------------------------------------------------------------===// - -#include "llvm-pdbdump.h" - -#include "Analyze.h" -#include "Diff.h" -#include "LLVMOutputStyle.h" -#include "LinePrinter.h" -#include "OutputStyle.h" -#include "PrettyCompilandDumper.h" -#include "PrettyExternalSymbolDumper.h" -#include "PrettyFunctionDumper.h" -#include "PrettyTypeDumper.h" -#include "PrettyVariableDumper.h" -#include "YAMLOutputStyle.h" - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Config/config.h" -#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" -#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" -#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" -#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" -#include "llvm/DebugInfo/MSF/MSFBuilder.h" -#include "llvm/DebugInfo/PDB/GenericError.h" -#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" -#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" -#include "llvm/DebugInfo/PDB/IPDBSession.h" -#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" -#include "llvm/DebugInfo/PDB/Native/DbiStream.h" -#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" -#include "llvm/DebugInfo/PDB/Native/InfoStream.h" -#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" -#include "llvm/DebugInfo/PDB/Native/NativeSession.h" -#include "llvm/DebugInfo/PDB/Native/PDBFile.h" -#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" -#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" -#include "llvm/DebugInfo/PDB/Native/RawConstants.h" -#include "llvm/DebugInfo/PDB/Native/RawError.h" -#include "llvm/DebugInfo/PDB/Native/TpiStream.h" -#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h" -#include "llvm/DebugInfo/PDB/PDB.h" -#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" -#include "llvm/DebugInfo/PDB/PDBSymbolData.h" -#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" -#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" -#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h" -#include "llvm/Support/BinaryByteStream.h" -#include "llvm/Support/COM.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ConvertUTF.h" -#include "llvm/Support/FileOutputBuffer.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/Process.h" -#include "llvm/Support/Regex.h" -#include "llvm/Support/ScopedPrinter.h" -#include "llvm/Support/Signals.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; -using namespace llvm::codeview; -using namespace llvm::msf; -using namespace llvm::pdb; - -namespace opts { - -cl::SubCommand RawSubcommand("raw", "Dump raw structure of the PDB file"); -cl::SubCommand - PrettySubcommand("pretty", - "Dump semantic information about types and symbols"); - -cl::SubCommand DiffSubcommand("diff", "Diff the contents of 2 PDB files"); - -cl::SubCommand - YamlToPdbSubcommand("yaml2pdb", - "Generate a PDB file from a YAML description"); -cl::SubCommand - PdbToYamlSubcommand("pdb2yaml", - "Generate a detailed YAML description of a PDB File"); - -cl::SubCommand - AnalyzeSubcommand("analyze", - "Analyze various aspects of a PDB's structure"); - -cl::SubCommand MergeSubcommand("merge", - "Merge multiple PDBs into a single PDB"); - -cl::OptionCategory TypeCategory("Symbol Type Options"); -cl::OptionCategory FilterCategory("Filtering and Sorting Options"); -cl::OptionCategory OtherOptions("Other Options"); - -namespace pretty { -cl::list InputFilenames(cl::Positional, - cl::desc(""), - cl::OneOrMore, cl::sub(PrettySubcommand)); - -cl::opt Compilands("compilands", cl::desc("Display compilands"), - cl::cat(TypeCategory), cl::sub(PrettySubcommand)); -cl::opt Symbols("module-syms", - cl::desc("Display symbols for each compiland"), - cl::cat(TypeCategory), cl::sub(PrettySubcommand)); -cl::opt Globals("globals", cl::desc("Dump global symbols"), - cl::cat(TypeCategory), cl::sub(PrettySubcommand)); -cl::opt Externals("externals", cl::desc("Dump external symbols"), - cl::cat(TypeCategory), cl::sub(PrettySubcommand)); -cl::list SymTypes( - "sym-types", cl::desc("Type of symbols to dump (default all)"), - cl::cat(TypeCategory), cl::sub(PrettySubcommand), cl::ZeroOrMore, - cl::values( - clEnumValN(SymLevel::Thunks, "thunks", "Display thunk symbols"), - clEnumValN(SymLevel::Data, "data", "Display data symbols"), - clEnumValN(SymLevel::Functions, "funcs", "Display function symbols"), - clEnumValN(SymLevel::All, "all", "Display all symbols (default)"))); - -cl::opt - Types("types", - cl::desc("Display all types (implies -classes, -enums, -typedefs)"), - cl::cat(TypeCategory), cl::sub(PrettySubcommand)); -cl::opt Classes("classes", cl::desc("Display class types"), - cl::cat(TypeCategory), cl::sub(PrettySubcommand)); -cl::opt Enums("enums", cl::desc("Display enum types"), - cl::cat(TypeCategory), cl::sub(PrettySubcommand)); -cl::opt Typedefs("typedefs", cl::desc("Display typedef types"), - cl::cat(TypeCategory), cl::sub(PrettySubcommand)); -cl::opt SymbolOrder( - "symbol-order", cl::desc("symbol sort order"), - cl::init(SymbolSortMode::None), - cl::values(clEnumValN(SymbolSortMode::None, "none", - "Undefined / no particular sort order"), - clEnumValN(SymbolSortMode::Name, "name", "Sort symbols by name"), - clEnumValN(SymbolSortMode::Size, "size", - "Sort symbols by size")), - cl::cat(TypeCategory), cl::sub(PrettySubcommand)); - -cl::opt ClassOrder( - "class-order", cl::desc("Class sort order"), cl::init(ClassSortMode::None), - cl::values( - clEnumValN(ClassSortMode::None, "none", - "Undefined / no particular sort order"), - clEnumValN(ClassSortMode::Name, "name", "Sort classes by name"), - clEnumValN(ClassSortMode::Size, "size", "Sort classes by size"), - clEnumValN(ClassSortMode::Padding, "padding", - "Sort classes by amount of padding"), - clEnumValN(ClassSortMode::PaddingPct, "padding-pct", - "Sort classes by percentage of space consumed by padding"), - clEnumValN(ClassSortMode::PaddingImmediate, "padding-imm", - "Sort classes by amount of immediate padding"), - clEnumValN(ClassSortMode::PaddingPctImmediate, "padding-pct-imm", - "Sort classes by percentage of space consumed by immediate " - "padding")), - cl::cat(TypeCategory), cl::sub(PrettySubcommand)); - -cl::opt ClassFormat( - "class-definitions", cl::desc("Class definition format"), - cl::init(ClassDefinitionFormat::All), - cl::values( - clEnumValN(ClassDefinitionFormat::All, "all", - "Display all class members including data, constants, " - "typedefs, functions, etc"), - clEnumValN(ClassDefinitionFormat::Layout, "layout", - "Only display members that contribute to class size."), - clEnumValN(ClassDefinitionFormat::None, "none", - "Don't display class definitions")), - cl::cat(TypeCategory), cl::sub(PrettySubcommand)); -cl::opt ClassRecursionDepth( - "class-recurse-depth", cl::desc("Class recursion depth (0=no limit)"), - cl::init(0), cl::cat(TypeCategory), cl::sub(PrettySubcommand)); - -cl::opt Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory), - cl::sub(PrettySubcommand)); -cl::opt - All("all", cl::desc("Implies all other options in 'Symbol Types' category"), - cl::cat(TypeCategory), cl::sub(PrettySubcommand)); - -cl::opt LoadAddress( - "load-address", - cl::desc("Assume the module is loaded at the specified address"), - cl::cat(OtherOptions), cl::sub(PrettySubcommand)); -cl::opt Native("native", cl::desc("Use native PDB reader instead of DIA"), - cl::cat(OtherOptions), cl::sub(PrettySubcommand)); -cl::opt - ColorOutput("color-output", - cl::desc("Override use of color (default = isatty)"), - cl::cat(OtherOptions), cl::sub(PrettySubcommand)); -cl::list ExcludeTypes( - "exclude-types", cl::desc("Exclude types by regular expression"), - cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); -cl::list ExcludeSymbols( - "exclude-symbols", cl::desc("Exclude symbols by regular expression"), - cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); -cl::list ExcludeCompilands( - "exclude-compilands", cl::desc("Exclude compilands by regular expression"), - cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); - -cl::list IncludeTypes( - "include-types", - cl::desc("Include only types which match a regular expression"), - cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); -cl::list IncludeSymbols( - "include-symbols", - cl::desc("Include only symbols which match a regular expression"), - cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); -cl::list IncludeCompilands( - "include-compilands", - cl::desc("Include only compilands those which match a regular expression"), - cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); -cl::opt SizeThreshold( - "min-type-size", cl::desc("Displays only those types which are greater " - "than or equal to the specified size."), - cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand)); -cl::opt PaddingThreshold( - "min-class-padding", cl::desc("Displays only those classes which have at " - "least the specified amount of padding."), - cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand)); -cl::opt ImmediatePaddingThreshold( - "min-class-padding-imm", - cl::desc("Displays only those classes which have at least the specified " - "amount of immediate padding, ignoring padding internal to bases " - "and aggregates."), - cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand)); - -cl::opt ExcludeCompilerGenerated( - "no-compiler-generated", - cl::desc("Don't show compiler generated types and symbols"), - cl::cat(FilterCategory), cl::sub(PrettySubcommand)); -cl::opt - ExcludeSystemLibraries("no-system-libs", - cl::desc("Don't show symbols from system libraries"), - cl::cat(FilterCategory), cl::sub(PrettySubcommand)); - -cl::opt NoEnumDefs("no-enum-definitions", - cl::desc("Don't display full enum definitions"), - cl::cat(FilterCategory), cl::sub(PrettySubcommand)); -} - -namespace diff { -cl::opt Pedantic("pedantic", - cl::desc("Finds all differences (even structural ones " - "that produce otherwise identical PDBs)"), - cl::sub(DiffSubcommand)); - -cl::list InputFilenames(cl::Positional, - cl::desc(" "), - cl::OneOrMore, cl::sub(DiffSubcommand)); -} - -namespace raw { - -cl::OptionCategory MsfOptions("MSF Container Options"); -cl::OptionCategory TypeOptions("Type Record Options"); -cl::OptionCategory FileOptions("Module & File Options"); -cl::OptionCategory SymbolOptions("Symbol Options"); -cl::OptionCategory MiscOptions("Miscellaneous Options"); - -// MSF OPTIONS -cl::opt DumpHeaders("headers", cl::desc("dump PDB headers"), - cl::cat(MsfOptions), cl::sub(RawSubcommand)); -cl::opt DumpStreamBlocks("stream-blocks", - cl::desc("dump PDB stream blocks"), - cl::cat(MsfOptions), cl::sub(RawSubcommand)); -cl::opt DumpStreamSummary("stream-summary", - cl::desc("dump summary of the PDB streams"), - cl::cat(MsfOptions), cl::sub(RawSubcommand)); -cl::opt DumpPageStats( - "page-stats", - cl::desc("dump allocation stats of the pages in the MSF file"), - cl::cat(MsfOptions), cl::sub(RawSubcommand)); -cl::opt - DumpBlockRangeOpt("block-data", cl::value_desc("start[-end]"), - cl::desc("Dump binary data from specified range."), - cl::cat(MsfOptions), cl::sub(RawSubcommand)); -llvm::Optional DumpBlockRange; - -cl::list - DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore, - cl::desc("Dump binary data from specified streams. Format " - "is SN[:Start][@Size]"), - cl::cat(MsfOptions), cl::sub(RawSubcommand)); - -// TYPE OPTIONS -cl::opt - CompactRecords("compact-records", - cl::desc("Dump type and symbol records with less detail"), - cl::cat(TypeOptions), cl::sub(RawSubcommand)); - -cl::opt - DumpTpiRecords("tpi-records", - cl::desc("dump CodeView type records from TPI stream"), - cl::cat(TypeOptions), cl::sub(RawSubcommand)); -cl::opt DumpTpiRecordBytes( - "tpi-record-bytes", - cl::desc("dump CodeView type record raw bytes from TPI stream"), - cl::cat(TypeOptions), cl::sub(RawSubcommand)); -cl::opt DumpTpiHash("tpi-hash", cl::desc("dump CodeView TPI hash stream"), - cl::cat(TypeOptions), cl::sub(RawSubcommand)); -cl::opt - DumpIpiRecords("ipi-records", - cl::desc("dump CodeView type records from IPI stream"), - cl::cat(TypeOptions), cl::sub(RawSubcommand)); -cl::opt DumpIpiRecordBytes( - "ipi-record-bytes", - cl::desc("dump CodeView type record raw bytes from IPI stream"), - cl::cat(TypeOptions), cl::sub(RawSubcommand)); - -// MODULE & FILE OPTIONS -cl::opt DumpModules("modules", cl::desc("dump compiland information"), - cl::cat(FileOptions), cl::sub(RawSubcommand)); -cl::opt DumpModuleFiles("module-files", cl::desc("dump file information"), - cl::cat(FileOptions), cl::sub(RawSubcommand)); -cl::opt DumpLineInfo("line-info", - cl::desc("dump file and line information"), - cl::cat(FileOptions), cl::sub(RawSubcommand)); - -// SYMBOL OPTIONS -cl::opt DumpGlobals("globals", cl::desc("dump globals stream data"), - cl::cat(SymbolOptions), cl::sub(RawSubcommand)); -cl::opt DumpModuleSyms("module-syms", cl::desc("dump module symbols"), - cl::cat(SymbolOptions), cl::sub(RawSubcommand)); -cl::opt DumpPublics("publics", cl::desc("dump Publics stream data"), - cl::cat(SymbolOptions), cl::sub(RawSubcommand)); -cl::opt - DumpSymRecordBytes("sym-record-bytes", - cl::desc("dump CodeView symbol record raw bytes"), - cl::cat(SymbolOptions), cl::sub(RawSubcommand)); - -// MISCELLANEOUS OPTIONS -cl::opt DumpStringTable("string-table", cl::desc("dump PDB String Table"), - cl::cat(MiscOptions), cl::sub(RawSubcommand)); - -cl::opt DumpSectionContribs("section-contribs", - cl::desc("dump section contributions"), - cl::cat(MiscOptions), cl::sub(RawSubcommand)); -cl::opt DumpSectionMap("section-map", cl::desc("dump section map"), - cl::cat(MiscOptions), cl::sub(RawSubcommand)); -cl::opt DumpSectionHeaders("section-headers", - cl::desc("dump section headers"), - cl::cat(MiscOptions), cl::sub(RawSubcommand)); -cl::opt DumpFpo("fpo", cl::desc("dump FPO records"), cl::cat(MiscOptions), - cl::sub(RawSubcommand)); - -cl::opt RawAll("all", cl::desc("Implies most other options."), - cl::cat(MiscOptions), cl::sub(RawSubcommand)); - -cl::list InputFilenames(cl::Positional, - cl::desc(""), - cl::OneOrMore, cl::sub(RawSubcommand)); -} - -namespace yaml2pdb { -cl::opt - YamlPdbOutputFile("pdb", cl::desc("the name of the PDB file to write"), - cl::sub(YamlToPdbSubcommand)); - -cl::opt InputFilename(cl::Positional, - cl::desc(""), cl::Required, - cl::sub(YamlToPdbSubcommand)); -} - -namespace pdb2yaml { -cl::opt All("all", - cl::desc("Dump everything we know how to dump."), - cl::sub(PdbToYamlSubcommand), cl::init(false)); -cl::opt - NoFileHeaders("no-file-headers", - cl::desc("Do not dump MSF file headers (you will not be able " - "to generate a fresh PDB from the resulting YAML)"), - cl::sub(PdbToYamlSubcommand), cl::init(false)); -cl::opt Minimal("minimal", - cl::desc("Don't write fields with default values"), - cl::sub(PdbToYamlSubcommand), cl::init(false)); - -cl::opt StreamMetadata( - "stream-metadata", - cl::desc("Dump the number of streams and each stream's size"), - cl::sub(PdbToYamlSubcommand), cl::init(false)); -cl::opt StreamDirectory( - "stream-directory", - cl::desc("Dump each stream's block map (implies -stream-metadata)"), - cl::sub(PdbToYamlSubcommand), cl::init(false)); -cl::opt PdbStream("pdb-stream", - cl::desc("Dump the PDB Stream (Stream 1)"), - cl::sub(PdbToYamlSubcommand), cl::init(false)); - -cl::opt StringTable("string-table", cl::desc("Dump the PDB String Table"), - cl::sub(PdbToYamlSubcommand), cl::init(false)); - -cl::opt DbiStream("dbi-stream", - cl::desc("Dump the DBI Stream (Stream 2)"), - cl::sub(PdbToYamlSubcommand), cl::init(false)); -cl::opt - DbiModuleInfo("dbi-module-info", - cl::desc("Dump DBI Module Information (implies -dbi-stream)"), - cl::sub(PdbToYamlSubcommand), cl::init(false)); - -cl::opt DbiModuleSyms( - "dbi-module-syms", - cl::desc("Dump DBI Module Information (implies -dbi-module-info)"), - cl::sub(PdbToYamlSubcommand), cl::init(false)); - -cl::opt DbiModuleSourceFileInfo( - "dbi-module-source-info", - cl::desc( - "Dump DBI Module Source File Information (implies -dbi-module-info)"), - cl::sub(PdbToYamlSubcommand), cl::init(false)); - -cl::opt - DbiModuleSourceLineInfo("dbi-module-lines", - cl::desc("Dump DBI Module Source Line Information " - "(implies -dbi-module-source-info)"), - cl::sub(PdbToYamlSubcommand), cl::init(false)); - -cl::opt TpiStream("tpi-stream", - cl::desc("Dump the TPI Stream (Stream 3)"), - cl::sub(PdbToYamlSubcommand), cl::init(false)); - -cl::opt IpiStream("ipi-stream", - cl::desc("Dump the IPI Stream (Stream 5)"), - cl::sub(PdbToYamlSubcommand), cl::init(false)); - -cl::list InputFilename(cl::Positional, - cl::desc(""), cl::Required, - cl::sub(PdbToYamlSubcommand)); -} - -namespace analyze { -cl::opt StringTable("hash-collisions", cl::desc("Find hash collisions"), - cl::sub(AnalyzeSubcommand), cl::init(false)); -cl::list InputFilename(cl::Positional, - cl::desc(""), cl::Required, - cl::sub(AnalyzeSubcommand)); -} - -namespace merge { -cl::list InputFilenames(cl::Positional, - cl::desc(""), - cl::OneOrMore, cl::sub(MergeSubcommand)); -cl::opt - PdbOutputFile("pdb", cl::desc("the name of the PDB file to write"), - cl::sub(MergeSubcommand)); -} -} - -static ExitOnError ExitOnErr; - -static void yamlToPdb(StringRef Path) { - BumpPtrAllocator Allocator; - ErrorOr> ErrorOrBuffer = - MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1, - /*RequiresNullTerminator=*/false); - - if (ErrorOrBuffer.getError()) { - ExitOnErr(make_error(generic_error_code::invalid_path, Path)); - } - - std::unique_ptr &Buffer = ErrorOrBuffer.get(); - - llvm::yaml::Input In(Buffer->getBuffer()); - pdb::yaml::PdbObject YamlObj(Allocator); - In >> YamlObj; - - PDBFileBuilder Builder(Allocator); - - uint32_t BlockSize = 4096; - if (YamlObj.Headers.hasValue()) - BlockSize = YamlObj.Headers->SuperBlock.BlockSize; - ExitOnErr(Builder.initialize(BlockSize)); - // Add each of the reserved streams. We ignore stream metadata in the - // yaml, because we will reconstruct our own view of the streams. For - // example, the YAML may say that there were 20 streams in the original - // PDB, but maybe we only dump a subset of those 20 streams, so we will - // have fewer, and the ones we do have may end up with different indices - // than the ones in the original PDB. So we just start with a clean slate. - for (uint32_t I = 0; I < kSpecialStreamCount; ++I) - ExitOnErr(Builder.getMsfBuilder().addStream(0)); - - if (YamlObj.StringTable.hasValue()) { - auto &Strings = Builder.getStringTableBuilder(); - for (auto S : *YamlObj.StringTable) - Strings.insert(S); - } - - pdb::yaml::PdbInfoStream DefaultInfoStream; - pdb::yaml::PdbDbiStream DefaultDbiStream; - pdb::yaml::PdbTpiStream DefaultTpiStream; - pdb::yaml::PdbTpiStream DefaultIpiStream; - - const auto &Info = YamlObj.PdbStream.getValueOr(DefaultInfoStream); - - auto &InfoBuilder = Builder.getInfoBuilder(); - InfoBuilder.setAge(Info.Age); - InfoBuilder.setGuid(Info.Guid); - InfoBuilder.setSignature(Info.Signature); - InfoBuilder.setVersion(Info.Version); - for (auto F : Info.Features) - InfoBuilder.addFeature(F); - - auto &Strings = Builder.getStringTableBuilder().getStrings(); - - const auto &Dbi = YamlObj.DbiStream.getValueOr(DefaultDbiStream); - auto &DbiBuilder = Builder.getDbiBuilder(); - DbiBuilder.setAge(Dbi.Age); - DbiBuilder.setBuildNumber(Dbi.BuildNumber); - DbiBuilder.setFlags(Dbi.Flags); - DbiBuilder.setMachineType(Dbi.MachineType); - DbiBuilder.setPdbDllRbld(Dbi.PdbDllRbld); - DbiBuilder.setPdbDllVersion(Dbi.PdbDllVersion); - DbiBuilder.setVersionHeader(Dbi.VerHeader); - for (const auto &MI : Dbi.ModInfos) { - auto &ModiBuilder = ExitOnErr(DbiBuilder.addModuleInfo(MI.Mod)); - ModiBuilder.setObjFileName(MI.Obj); - - for (auto S : MI.SourceFiles) - ExitOnErr(DbiBuilder.addModuleSourceFile(MI.Mod, S)); - if (MI.Modi.hasValue()) { - const auto &ModiStream = *MI.Modi; - for (auto Symbol : ModiStream.Symbols) { - ModiBuilder.addSymbol( - Symbol.toCodeViewSymbol(Allocator, CodeViewContainer::Pdb)); - } - } - - auto CodeViewSubsections = - ExitOnErr(CodeViewYAML::convertSubsectionList(MI.Subsections, Strings)); - for (auto &SS : CodeViewSubsections) { - ModiBuilder.addDebugSubsection(std::move(SS)); - } - } - - auto &TpiBuilder = Builder.getTpiBuilder(); - const auto &Tpi = YamlObj.TpiStream.getValueOr(DefaultTpiStream); - TpiBuilder.setVersionHeader(Tpi.Version); - for (const auto &R : Tpi.Records) { - CVType Type = R.toCodeViewRecord(Allocator); - TpiBuilder.addTypeRecord(Type.RecordData, None); - } - - const auto &Ipi = YamlObj.IpiStream.getValueOr(DefaultIpiStream); - auto &IpiBuilder = Builder.getIpiBuilder(); - IpiBuilder.setVersionHeader(Ipi.Version); - for (const auto &R : Ipi.Records) { - CVType Type = R.toCodeViewRecord(Allocator); - IpiBuilder.addTypeRecord(Type.RecordData, None); - } - - ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile)); -} - -static PDBFile &loadPDB(StringRef Path, std::unique_ptr &Session) { - ExitOnErr(loadDataForPDB(PDB_ReaderType::Native, Path, Session)); - - NativeSession *NS = static_cast(Session.get()); - return NS->getPDBFile(); -} - -static void pdb2Yaml(StringRef Path) { - std::unique_ptr Session; - auto &File = loadPDB(Path, Session); - - auto O = llvm::make_unique(File); - O = llvm::make_unique(File); - - ExitOnErr(O->dump()); -} - -static void dumpRaw(StringRef Path) { - std::unique_ptr Session; - auto &File = loadPDB(Path, Session); - - auto O = llvm::make_unique(File); - - ExitOnErr(O->dump()); -} - -static void dumpAnalysis(StringRef Path) { - std::unique_ptr Session; - auto &File = loadPDB(Path, Session); - auto O = llvm::make_unique(File); - - ExitOnErr(O->dump()); -} - -static void diff(StringRef Path1, StringRef Path2) { - std::unique_ptr Session1; - std::unique_ptr Session2; - - auto &File1 = loadPDB(Path1, Session1); - auto &File2 = loadPDB(Path2, Session2); - - auto O = llvm::make_unique(File1, File2); - - ExitOnErr(O->dump()); -} - -bool opts::pretty::shouldDumpSymLevel(SymLevel Search) { - if (SymTypes.empty()) - return true; - if (llvm::find(SymTypes, Search) != SymTypes.end()) - return true; - if (llvm::find(SymTypes, SymLevel::All) != SymTypes.end()) - return true; - return false; -} - -uint32_t llvm::pdb::getTypeLength(const PDBSymbolData &Symbol) { - auto SymbolType = Symbol.getType(); - const IPDBRawSymbol &RawType = SymbolType->getRawSymbol(); - - return RawType.getLength(); -} - -bool opts::pretty::compareFunctionSymbols( - const std::unique_ptr &F1, - const std::unique_ptr &F2) { - assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None); - - if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name) - return F1->getName() < F2->getName(); - - // Note that we intentionally sort in descending order on length, since - // long functions are more interesting than short functions. - return F1->getLength() > F2->getLength(); -} - -bool opts::pretty::compareDataSymbols( - const std::unique_ptr &F1, - const std::unique_ptr &F2) { - assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None); - - if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name) - return F1->getName() < F2->getName(); - - // Note that we intentionally sort in descending order on length, since - // large types are more interesting than short ones. - return getTypeLength(*F1) > getTypeLength(*F2); -} - -static void dumpPretty(StringRef Path) { - std::unique_ptr Session; - - const auto ReaderType = - opts::pretty::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA; - ExitOnErr(loadDataForPDB(ReaderType, Path, Session)); - - if (opts::pretty::LoadAddress) - Session->setLoadAddress(opts::pretty::LoadAddress); - - auto &Stream = outs(); - const bool UseColor = opts::pretty::ColorOutput == cl::BOU_UNSET - ? Stream.has_colors() - : opts::pretty::ColorOutput == cl::BOU_TRUE; - LinePrinter Printer(2, UseColor, Stream); - - auto GlobalScope(Session->getGlobalScope()); - std::string FileName(GlobalScope->getSymbolsFileName()); - - WithColor(Printer, PDB_ColorItem::None).get() << "Summary for "; - WithColor(Printer, PDB_ColorItem::Path).get() << FileName; - Printer.Indent(); - uint64_t FileSize = 0; - - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size"; - if (!sys::fs::file_size(FileName, FileSize)) { - Printer << ": " << FileSize << " bytes"; - } else { - Printer << ": (Unable to obtain file size)"; - } - - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid"; - Printer << ": " << GlobalScope->getGuid(); - - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age"; - Printer << ": " << GlobalScope->getAge(); - - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes"; - Printer << ": "; - if (GlobalScope->hasCTypes()) - outs() << "HasCTypes "; - if (GlobalScope->hasPrivateSymbols()) - outs() << "HasPrivateSymbols "; - Printer.Unindent(); - - if (opts::pretty::Compilands) { - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::SectionHeader).get() - << "---COMPILANDS---"; - Printer.Indent(); - auto Compilands = GlobalScope->findAllChildren(); - CompilandDumper Dumper(Printer); - CompilandDumpFlags options = CompilandDumper::Flags::None; - if (opts::pretty::Lines) - options = options | CompilandDumper::Flags::Lines; - while (auto Compiland = Compilands->getNext()) - Dumper.start(*Compiland, options); - Printer.Unindent(); - } - - if (opts::pretty::Classes || opts::pretty::Enums || opts::pretty::Typedefs) { - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---"; - Printer.Indent(); - TypeDumper Dumper(Printer); - Dumper.start(*GlobalScope); - Printer.Unindent(); - } - - if (opts::pretty::Symbols) { - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---"; - Printer.Indent(); - auto Compilands = GlobalScope->findAllChildren(); - CompilandDumper Dumper(Printer); - while (auto Compiland = Compilands->getNext()) - Dumper.start(*Compiland, true); - Printer.Unindent(); - } - - if (opts::pretty::Globals) { - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---"; - Printer.Indent(); - if (shouldDumpSymLevel(opts::pretty::SymLevel::Functions)) { - FunctionDumper Dumper(Printer); - auto Functions = GlobalScope->findAllChildren(); - if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) { - while (auto Function = Functions->getNext()) { - Printer.NewLine(); - Dumper.start(*Function, FunctionDumper::PointerType::None); - } - } else { - std::vector> Funcs; - while (auto Func = Functions->getNext()) - Funcs.push_back(std::move(Func)); - std::sort(Funcs.begin(), Funcs.end(), - opts::pretty::compareFunctionSymbols); - for (const auto &Func : Funcs) { - Printer.NewLine(); - Dumper.start(*Func, FunctionDumper::PointerType::None); - } - } - } - if (shouldDumpSymLevel(opts::pretty::SymLevel::Data)) { - auto Vars = GlobalScope->findAllChildren(); - VariableDumper Dumper(Printer); - if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) { - while (auto Var = Vars->getNext()) - Dumper.start(*Var); - } else { - std::vector> Datas; - while (auto Var = Vars->getNext()) - Datas.push_back(std::move(Var)); - std::sort(Datas.begin(), Datas.end(), opts::pretty::compareDataSymbols); - for (const auto &Var : Datas) - Dumper.start(*Var); - } - } - if (shouldDumpSymLevel(opts::pretty::SymLevel::Thunks)) { - auto Thunks = GlobalScope->findAllChildren(); - CompilandDumper Dumper(Printer); - while (auto Thunk = Thunks->getNext()) - Dumper.dump(*Thunk); - } - Printer.Unindent(); - } - if (opts::pretty::Externals) { - Printer.NewLine(); - WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---"; - Printer.Indent(); - ExternalSymbolDumper Dumper(Printer); - Dumper.start(*GlobalScope); - } - if (opts::pretty::Lines) { - Printer.NewLine(); - } - outs().flush(); -} - -static void mergePdbs() { - BumpPtrAllocator Allocator; - TypeTableBuilder MergedTpi(Allocator); - TypeTableBuilder MergedIpi(Allocator); - - // Create a Tpi and Ipi type table with all types from all input files. - for (const auto &Path : opts::merge::InputFilenames) { - std::unique_ptr Session; - auto &File = loadPDB(Path, Session); - SmallVector TypeMap; - SmallVector IdMap; - if (File.hasPDBTpiStream()) { - auto &Tpi = ExitOnErr(File.getPDBTpiStream()); - ExitOnErr(codeview::mergeTypeRecords(MergedTpi, TypeMap, nullptr, - Tpi.typeArray())); - } - if (File.hasPDBIpiStream()) { - auto &Ipi = ExitOnErr(File.getPDBIpiStream()); - ExitOnErr(codeview::mergeIdRecords(MergedIpi, TypeMap, IdMap, - Ipi.typeArray())); - } - } - - // Then write the PDB. - PDBFileBuilder Builder(Allocator); - ExitOnErr(Builder.initialize(4096)); - // Add each of the reserved streams. We might not put any data in them, - // but at least they have to be present. - for (uint32_t I = 0; I < kSpecialStreamCount; ++I) - ExitOnErr(Builder.getMsfBuilder().addStream(0)); - - auto &DestTpi = Builder.getTpiBuilder(); - auto &DestIpi = Builder.getIpiBuilder(); - MergedTpi.ForEachRecord([&DestTpi](TypeIndex TI, ArrayRef Data) { - DestTpi.addTypeRecord(Data, None); - }); - MergedIpi.ForEachRecord([&DestIpi](TypeIndex TI, ArrayRef Data) { - DestIpi.addTypeRecord(Data, None); - }); - - SmallString<64> OutFile(opts::merge::PdbOutputFile); - if (OutFile.empty()) { - OutFile = opts::merge::InputFilenames[0]; - llvm::sys::path::replace_extension(OutFile, "merged.pdb"); - } - ExitOnErr(Builder.commit(OutFile)); -} - -int main(int argc_, const char *argv_[]) { - // Print a stack trace if we signal out. - sys::PrintStackTraceOnErrorSignal(argv_[0]); - PrettyStackTraceProgram X(argc_, argv_); - - ExitOnErr.setBanner("llvm-pdbdump: "); - - SmallVector argv; - SpecificBumpPtrAllocator ArgAllocator; - ExitOnErr(errorCodeToError(sys::Process::GetArgumentVector( - argv, makeArrayRef(argv_, argc_), ArgAllocator))); - - llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. - - cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n"); - if (!opts::raw::DumpBlockRangeOpt.empty()) { - llvm::Regex R("^([0-9]+)(-([0-9]+))?$"); - llvm::SmallVector Matches; - if (!R.match(opts::raw::DumpBlockRangeOpt, &Matches)) { - errs() << "Argument '" << opts::raw::DumpBlockRangeOpt - << "' invalid format.\n"; - errs().flush(); - exit(1); - } - opts::raw::DumpBlockRange.emplace(); - Matches[1].getAsInteger(10, opts::raw::DumpBlockRange->Min); - if (!Matches[3].empty()) { - opts::raw::DumpBlockRange->Max.emplace(); - Matches[3].getAsInteger(10, *opts::raw::DumpBlockRange->Max); - } - } - - if (opts::RawSubcommand) { - if (opts::raw::RawAll) { - opts::raw::DumpHeaders = true; - opts::raw::DumpModules = true; - opts::raw::DumpModuleFiles = true; - opts::raw::DumpModuleSyms = true; - opts::raw::DumpGlobals = true; - opts::raw::DumpPublics = true; - opts::raw::DumpSectionHeaders = true; - opts::raw::DumpStreamSummary = true; - opts::raw::DumpPageStats = true; - opts::raw::DumpStreamBlocks = true; - opts::raw::DumpTpiRecords = true; - opts::raw::DumpTpiHash = true; - opts::raw::DumpIpiRecords = true; - opts::raw::DumpSectionMap = true; - opts::raw::DumpSectionContribs = true; - opts::raw::DumpLineInfo = true; - opts::raw::DumpFpo = true; - opts::raw::DumpStringTable = true; - } - - if (opts::raw::CompactRecords && - (opts::raw::DumpTpiRecordBytes || opts::raw::DumpIpiRecordBytes)) { - errs() << "-compact-records is incompatible with -tpi-record-bytes and " - "-ipi-record-bytes.\n"; - exit(1); - } - } - - llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded); - - if (opts::PdbToYamlSubcommand) { - pdb2Yaml(opts::pdb2yaml::InputFilename.front()); - } else if (opts::YamlToPdbSubcommand) { - if (opts::yaml2pdb::YamlPdbOutputFile.empty()) { - SmallString<16> OutputFilename(opts::yaml2pdb::InputFilename.getValue()); - sys::path::replace_extension(OutputFilename, ".pdb"); - opts::yaml2pdb::YamlPdbOutputFile = OutputFilename.str(); - } - yamlToPdb(opts::yaml2pdb::InputFilename); - } else if (opts::AnalyzeSubcommand) { - dumpAnalysis(opts::analyze::InputFilename.front()); - } else if (opts::PrettySubcommand) { - if (opts::pretty::Lines) - opts::pretty::Compilands = true; - - if (opts::pretty::All) { - opts::pretty::Compilands = true; - opts::pretty::Symbols = true; - opts::pretty::Globals = true; - opts::pretty::Types = true; - opts::pretty::Externals = true; - opts::pretty::Lines = true; - } - - if (opts::pretty::Types) { - opts::pretty::Classes = true; - opts::pretty::Typedefs = true; - opts::pretty::Enums = true; - } - - // When adding filters for excluded compilands and types, we need to - // remember that these are regexes. So special characters such as * and \ - // need to be escaped in the regex. In the case of a literal \, this means - // it needs to be escaped again in the C++. So matching a single \ in the - // input requires 4 \es in the C++. - if (opts::pretty::ExcludeCompilerGenerated) { - opts::pretty::ExcludeTypes.push_back("__vc_attributes"); - opts::pretty::ExcludeCompilands.push_back("\\* Linker \\*"); - } - if (opts::pretty::ExcludeSystemLibraries) { - opts::pretty::ExcludeCompilands.push_back( - "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld"); - opts::pretty::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt"); - opts::pretty::ExcludeCompilands.push_back( - "d:\\\\th.obj.x86fre\\\\minkernel"); - } - std::for_each(opts::pretty::InputFilenames.begin(), - opts::pretty::InputFilenames.end(), dumpPretty); - } else if (opts::RawSubcommand) { - std::for_each(opts::raw::InputFilenames.begin(), - opts::raw::InputFilenames.end(), dumpRaw); - } else if (opts::DiffSubcommand) { - if (opts::diff::InputFilenames.size() != 2) { - errs() << "diff subcommand expects exactly 2 arguments.\n"; - exit(1); - } - diff(opts::diff::InputFilenames[0], opts::diff::InputFilenames[1]); - } else if (opts::MergeSubcommand) { - if (opts::merge::InputFilenames.size() < 2) { - errs() << "merge subcommand requires at least 2 input files.\n"; - exit(1); - } - mergePdbs(); - } - - outs().flush(); - return 0; -} diff --git a/tools/llvm-pdbdump/llvm-pdbdump.h b/tools/llvm-pdbdump/llvm-pdbdump.h deleted file mode 100644 index b344129d217a..000000000000 --- a/tools/llvm-pdbdump/llvm-pdbdump.h +++ /dev/null @@ -1,136 +0,0 @@ -//===- llvm-pdbdump.h ----------------------------------------- *- C++ --*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H -#define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H - -#include "llvm/ADT/Optional.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/raw_ostream.h" - -#include -#include - -namespace llvm { -namespace pdb { -class PDBSymbolData; -class PDBSymbolFunc; -uint32_t getTypeLength(const PDBSymbolData &Symbol); -} -} - -namespace opts { - -namespace pretty { - -enum class ClassDefinitionFormat { None, Layout, All }; -enum class ClassSortMode { - None, - Name, - Size, - Padding, - PaddingPct, - PaddingImmediate, - PaddingPctImmediate -}; - -enum class SymbolSortMode { None, Name, Size }; - -enum class SymLevel { Functions, Data, Thunks, All }; - -bool shouldDumpSymLevel(SymLevel Level); -bool compareFunctionSymbols( - const std::unique_ptr &F1, - const std::unique_ptr &F2); -bool compareDataSymbols(const std::unique_ptr &F1, - const std::unique_ptr &F2); - -extern llvm::cl::opt Compilands; -extern llvm::cl::opt Symbols; -extern llvm::cl::opt Globals; -extern llvm::cl::opt Classes; -extern llvm::cl::opt Enums; -extern llvm::cl::opt Typedefs; -extern llvm::cl::opt All; -extern llvm::cl::opt ExcludeCompilerGenerated; - -extern llvm::cl::opt NoEnumDefs; -extern llvm::cl::list ExcludeTypes; -extern llvm::cl::list ExcludeSymbols; -extern llvm::cl::list ExcludeCompilands; -extern llvm::cl::list IncludeTypes; -extern llvm::cl::list IncludeSymbols; -extern llvm::cl::list IncludeCompilands; -extern llvm::cl::opt SymbolOrder; -extern llvm::cl::opt ClassOrder; -extern llvm::cl::opt SizeThreshold; -extern llvm::cl::opt PaddingThreshold; -extern llvm::cl::opt ImmediatePaddingThreshold; -extern llvm::cl::opt ClassFormat; -extern llvm::cl::opt ClassRecursionDepth; -} - -namespace raw { -struct BlockRange { - uint32_t Min; - llvm::Optional Max; -}; - -extern llvm::Optional DumpBlockRange; -extern llvm::cl::list DumpStreamData; - -extern llvm::cl::opt CompactRecords; -extern llvm::cl::opt DumpGlobals; -extern llvm::cl::opt DumpHeaders; -extern llvm::cl::opt DumpStreamBlocks; -extern llvm::cl::opt DumpStreamSummary; -extern llvm::cl::opt DumpPageStats; -extern llvm::cl::opt DumpTpiHash; -extern llvm::cl::opt DumpTpiRecordBytes; -extern llvm::cl::opt DumpTpiRecords; -extern llvm::cl::opt DumpIpiRecords; -extern llvm::cl::opt DumpIpiRecordBytes; -extern llvm::cl::opt DumpModules; -extern llvm::cl::opt DumpModuleFiles; -extern llvm::cl::opt DumpModuleLines; -extern llvm::cl::opt DumpModuleSyms; -extern llvm::cl::opt DumpPublics; -extern llvm::cl::opt DumpSectionContribs; -extern llvm::cl::opt DumpLineInfo; -extern llvm::cl::opt DumpSectionMap; -extern llvm::cl::opt DumpSymRecordBytes; -extern llvm::cl::opt DumpSectionHeaders; -extern llvm::cl::opt DumpFpo; -extern llvm::cl::opt DumpStringTable; -} - -namespace diff { -extern llvm::cl::opt Pedantic; -} - -namespace pdb2yaml { -extern llvm::cl::opt All; -extern llvm::cl::opt NoFileHeaders; -extern llvm::cl::opt Minimal; -extern llvm::cl::opt StreamMetadata; -extern llvm::cl::opt StreamDirectory; -extern llvm::cl::opt StringTable; -extern llvm::cl::opt PdbStream; -extern llvm::cl::opt DbiStream; -extern llvm::cl::opt DbiModuleInfo; -extern llvm::cl::opt DbiModuleSyms; -extern llvm::cl::opt DbiModuleSourceFileInfo; -extern llvm::cl::opt DbiModuleSourceLineInfo; -extern llvm::cl::opt TpiStream; -extern llvm::cl::opt IpiStream; -extern llvm::cl::list InputFilename; -} -} - -#endif diff --git a/tools/llvm-pdbutil/Analyze.cpp b/tools/llvm-pdbutil/Analyze.cpp new file mode 100644 index 000000000000..b503cdcbf1ea --- /dev/null +++ b/tools/llvm-pdbutil/Analyze.cpp @@ -0,0 +1,152 @@ +//===- Analyze.cpp - PDB analysis functions ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Analyze.h" + +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" + +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/raw_ostream.h" + +#include + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +static StringRef getLeafTypeName(TypeLeafKind LT) { + switch (LT) { +#define TYPE_RECORD(ename, value, name) \ + case ename: \ + return #name; +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" + default: + break; + } + return "UnknownLeaf"; +} + +namespace { +struct HashLookupVisitor : public TypeVisitorCallbacks { + struct Entry { + TypeIndex TI; + CVType Record; + }; + + explicit HashLookupVisitor(TpiStream &Tpi) : Tpi(Tpi) {} + + Error visitTypeBegin(CVType &Record) override { + uint32_t H = Tpi.getHashValues()[I]; + Record.Hash = H; + TypeIndex TI(I + TypeIndex::FirstNonSimpleIndex); + Lookup[H].push_back(Entry{TI, Record}); + ++I; + return Error::success(); + } + + uint32_t I = 0; + DenseMap> Lookup; + TpiStream &Tpi; +}; +} + +AnalysisStyle::AnalysisStyle(PDBFile &File) : File(File) {} + +Error AnalysisStyle::dump() { + auto Tpi = File.getPDBTpiStream(); + if (!Tpi) + return Tpi.takeError(); + + TypeDatabase TypeDB(Tpi->getNumTypeRecords()); + TypeDatabaseVisitor DBV(TypeDB); + TypeVisitorCallbackPipeline Pipeline; + HashLookupVisitor Hasher(*Tpi); + // Add them to the database + Pipeline.addCallbackToPipeline(DBV); + // Store their hash values + Pipeline.addCallbackToPipeline(Hasher); + + if (auto EC = codeview::visitTypeStream(Tpi->typeArray(), Pipeline)) + return EC; + + auto &Adjusters = Tpi->getHashAdjusters(); + DenseSet AdjusterSet; + for (const auto &Adj : Adjusters) { + assert(AdjusterSet.find(Adj.second) == AdjusterSet.end()); + AdjusterSet.insert(Adj.second); + } + + uint32_t Count = 0; + outs() << "Searching for hash collisions\n"; + for (const auto &H : Hasher.Lookup) { + if (H.second.size() <= 1) + continue; + ++Count; + outs() << formatv("Hash: {0}, Count: {1} records\n", H.first, + H.second.size()); + for (const auto &R : H.second) { + auto Iter = AdjusterSet.find(R.TI.getIndex()); + StringRef Prefix; + if (Iter != AdjusterSet.end()) { + Prefix = "[HEAD]"; + AdjusterSet.erase(Iter); + } + StringRef LeafName = getLeafTypeName(R.Record.Type); + uint32_t TI = R.TI.getIndex(); + StringRef TypeName = TypeDB.getTypeName(R.TI); + outs() << formatv("{0,-6} {1} ({2:x}) {3}\n", Prefix, LeafName, TI, + TypeName); + } + } + + outs() << "\n"; + outs() << "Dumping hash adjustment chains\n"; + for (const auto &A : Tpi->getHashAdjusters()) { + TypeIndex TI(A.second); + StringRef TypeName = TypeDB.getTypeName(TI); + const CVType &HeadRecord = TypeDB.getTypeRecord(TI); + assert(HeadRecord.Hash.hasValue()); + + auto CollisionsIter = Hasher.Lookup.find(*HeadRecord.Hash); + if (CollisionsIter == Hasher.Lookup.end()) + continue; + + const auto &Collisions = CollisionsIter->second; + outs() << TypeName << "\n"; + outs() << formatv(" [HEAD] {0:x} {1} {2}\n", A.second, + getLeafTypeName(HeadRecord.Type), TypeName); + for (const auto &Chain : Collisions) { + if (Chain.TI == TI) + continue; + const CVType &TailRecord = TypeDB.getTypeRecord(Chain.TI); + outs() << formatv(" {0:x} {1} {2}\n", Chain.TI.getIndex(), + getLeafTypeName(TailRecord.Type), + TypeDB.getTypeName(Chain.TI)); + } + } + outs() << formatv("There are {0} orphaned hash adjusters\n", + AdjusterSet.size()); + for (const auto &Adj : AdjusterSet) { + outs() << formatv(" {0}\n", Adj); + } + + uint32_t DistinctHashValues = Hasher.Lookup.size(); + outs() << formatv("{0}/{1} hash collisions", Count, DistinctHashValues); + return Error::success(); +} diff --git a/tools/llvm-pdbutil/Analyze.h b/tools/llvm-pdbutil/Analyze.h new file mode 100644 index 000000000000..7230ae45b0c8 --- /dev/null +++ b/tools/llvm-pdbutil/Analyze.h @@ -0,0 +1,30 @@ +//===- Analyze.h - PDB analysis functions -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_ANALYSIS_H +#define LLVM_TOOLS_LLVMPDBDUMP_ANALYSIS_H + +#include "OutputStyle.h" + +namespace llvm { +namespace pdb { +class PDBFile; +class AnalysisStyle : public OutputStyle { +public: + explicit AnalysisStyle(PDBFile &File); + + Error dump() override; + +private: + PDBFile &File; +}; +} +} + +#endif diff --git a/tools/llvm-pdbutil/CMakeLists.txt b/tools/llvm-pdbutil/CMakeLists.txt new file mode 100644 index 000000000000..9875dfb5a257 --- /dev/null +++ b/tools/llvm-pdbutil/CMakeLists.txt @@ -0,0 +1,34 @@ +set(LLVM_LINK_COMPONENTS + DebugInfoCodeView + DebugInfoMSF + DebugInfoPDB + Object + ObjectYAML + Support + ) + +add_llvm_tool(llvm-pdbutil + Analyze.cpp + CompactTypeDumpVisitor.cpp + Diff.cpp + llvm-pdbutil.cpp + LinePrinter.cpp + LLVMOutputStyle.cpp + PdbYaml.cpp + PrettyBuiltinDumper.cpp + PrettyClassDefinitionDumper.cpp + PrettyClassLayoutGraphicalDumper.cpp + PrettyCompilandDumper.cpp + PrettyEnumDumper.cpp + PrettyExternalSymbolDumper.cpp + PrettyFunctionDumper.cpp + PrettyTypeDumper.cpp + PrettyTypedefDumper.cpp + PrettyVariableDumper.cpp + StreamUtil.cpp + YAMLOutputStyle.cpp + ) + +if(LLVM_USE_SANITIZE_COVERAGE) + add_subdirectory(fuzzer) +endif() diff --git a/tools/llvm-pdbutil/CompactTypeDumpVisitor.cpp b/tools/llvm-pdbutil/CompactTypeDumpVisitor.cpp new file mode 100644 index 000000000000..6dd54e0dbec1 --- /dev/null +++ b/tools/llvm-pdbutil/CompactTypeDumpVisitor.cpp @@ -0,0 +1,59 @@ +//===-- CompactTypeDumpVisitor.cpp - CodeView type info dumper --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "CompactTypeDumpVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/ScopedPrinter.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +static const EnumEntry LeafTypeNames[] = { +#define CV_TYPE(enum, val) {#enum, enum}, +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" +}; + +static StringRef getLeafName(TypeLeafKind K) { + for (const auto &E : LeafTypeNames) { + if (E.Value == K) + return E.Name; + } + return StringRef(); +} + +CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types, + ScopedPrinter *W) + : CompactTypeDumpVisitor(Types, TypeIndex(TypeIndex::FirstNonSimpleIndex), + W) {} + +CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types, + TypeIndex FirstTI, + ScopedPrinter *W) + : W(W), TI(FirstTI), Offset(0), Types(Types) {} + +Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) { + return Error::success(); +} + +Error CompactTypeDumpVisitor::visitTypeEnd(CVType &Record) { + uint32_t I = TI.getIndex(); + StringRef Leaf = getLeafName(Record.Type); + StringRef Name = Types.getTypeName(TI); + W->printString( + llvm::formatv("Index: {0:x} ({1:N} bytes, offset {2:N}) {3} \"{4}\"", I, + Record.length(), Offset, Leaf, Name) + .str()); + + Offset += Record.length(); + TI.setIndex(TI.getIndex() + 1); + + return Error::success(); +} diff --git a/tools/llvm-pdbutil/CompactTypeDumpVisitor.h b/tools/llvm-pdbutil/CompactTypeDumpVisitor.h new file mode 100644 index 000000000000..41ccea0c2e90 --- /dev/null +++ b/tools/llvm-pdbutil/CompactTypeDumpVisitor.h @@ -0,0 +1,49 @@ +//===-- CompactTypeDumpVisitor.h - CodeView type info dumper ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_COMPACTTYPEDUMPVISITOR_H +#define LLVM_DEBUGINFO_CODEVIEW_COMPACTTYPEDUMPVISITOR_H + +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" + +namespace llvm { +class ScopedPrinter; +namespace codeview { +class TypeCollection; +} + +namespace pdb { + +/// Dumper for CodeView type streams found in COFF object files and PDB files. +/// Dumps records on a single line, and ignores member records. +class CompactTypeDumpVisitor : public codeview::TypeVisitorCallbacks { +public: + CompactTypeDumpVisitor(codeview::TypeCollection &Types, ScopedPrinter *W); + CompactTypeDumpVisitor(codeview::TypeCollection &Types, + codeview::TypeIndex FirstTI, ScopedPrinter *W); + + /// Paired begin/end actions for all types. Receives all record data, + /// including the fixed-length record prefix. + Error visitTypeBegin(codeview::CVType &Record) override; + Error visitTypeEnd(codeview::CVType &Record) override; + +private: + ScopedPrinter *W; + + codeview::TypeIndex TI; + uint32_t Offset; + codeview::TypeCollection &Types; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif diff --git a/tools/llvm-pdbutil/Diff.cpp b/tools/llvm-pdbutil/Diff.cpp new file mode 100644 index 000000000000..3fe6c511d35f --- /dev/null +++ b/tools/llvm-pdbutil/Diff.cpp @@ -0,0 +1,537 @@ +//===- Diff.cpp - PDB diff utility ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Diff.h" + +#include "StreamUtil.h" +#include "llvm-pdbutil.h" + +#include "llvm/DebugInfo/PDB/Native/Formatters.h" +#include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" + +#include "llvm/Support/FormatAdapters.h" +#include "llvm/Support/FormatProviders.h" +#include "llvm/Support/FormatVariadic.h" + +using namespace llvm; +using namespace llvm::pdb; + +namespace llvm { +template <> struct format_provider { + static void format(const PdbRaw_FeatureSig &Sig, raw_ostream &Stream, + StringRef Style) { + switch (Sig) { + case PdbRaw_FeatureSig::MinimalDebugInfo: + Stream << "MinimalDebugInfo"; + break; + case PdbRaw_FeatureSig::NoTypeMerge: + Stream << "NoTypeMerge"; + break; + case PdbRaw_FeatureSig::VC110: + Stream << "VC110"; + break; + case PdbRaw_FeatureSig::VC140: + Stream << "VC140"; + break; + } + } +}; +} + +template using ValueOfRange = llvm::detail::ValueOfRange; + +template +static void set_differences(Range &&R1, Range &&R2, + SmallVectorImpl> *OnlyLeft, + SmallVectorImpl> *OnlyRight, + SmallVectorImpl> *Intersection, + Comp Comparator) { + + std::sort(R1.begin(), R1.end(), Comparator); + std::sort(R2.begin(), R2.end(), Comparator); + + if (OnlyLeft) { + OnlyLeft->reserve(R1.size()); + auto End = std::set_difference(R1.begin(), R1.end(), R2.begin(), R2.end(), + OnlyLeft->begin(), Comparator); + OnlyLeft->set_size(std::distance(OnlyLeft->begin(), End)); + } + if (OnlyRight) { + OnlyLeft->reserve(R2.size()); + auto End = std::set_difference(R2.begin(), R2.end(), R1.begin(), R1.end(), + OnlyRight->begin(), Comparator); + OnlyRight->set_size(std::distance(OnlyRight->begin(), End)); + } + if (Intersection) { + Intersection->reserve(std::min(R1.size(), R2.size())); + auto End = std::set_intersection(R1.begin(), R1.end(), R2.begin(), R2.end(), + Intersection->begin(), Comparator); + Intersection->set_size(std::distance(Intersection->begin(), End)); + } +} + +template +static void +set_differences(Range &&R1, Range &&R2, + SmallVectorImpl> *OnlyLeft, + SmallVectorImpl> *OnlyRight, + SmallVectorImpl> *Intersection = nullptr) { + std::less> Comp; + set_differences(std::forward(R1), std::forward(R2), OnlyLeft, + OnlyRight, Intersection, Comp); +} + +DiffStyle::DiffStyle(PDBFile &File1, PDBFile &File2) + : File1(File1), File2(File2) {} + +Error DiffStyle::dump() { + if (auto EC = diffSuperBlock()) + return EC; + + if (auto EC = diffFreePageMap()) + return EC; + + if (auto EC = diffStreamDirectory()) + return EC; + + if (auto EC = diffStringTable()) + return EC; + + if (auto EC = diffInfoStream()) + return EC; + + if (auto EC = diffDbiStream()) + return EC; + + if (auto EC = diffSectionContribs()) + return EC; + + if (auto EC = diffSectionMap()) + return EC; + + if (auto EC = diffFpoStream()) + return EC; + + if (auto EC = diffTpiStream(StreamTPI)) + return EC; + + if (auto EC = diffTpiStream(StreamIPI)) + return EC; + + if (auto EC = diffPublics()) + return EC; + + if (auto EC = diffGlobals()) + return EC; + + return Error::success(); +} + +template +static bool diffAndPrint(StringRef Label, PDBFile &File1, PDBFile &File2, T V1, + T V2) { + if (V1 == V2) { + outs() << formatv(" {0}: No differences detected!\n", Label); + return false; + } + + outs().indent(2) << Label << "\n"; + outs().indent(4) << formatv("{0}: {1}\n", File1.getFilePath(), V1); + outs().indent(4) << formatv("{0}: {1}\n", File2.getFilePath(), V2); + return true; +} + +template +static bool diffAndPrint(StringRef Label, PDBFile &File1, PDBFile &File2, + ArrayRef V1, ArrayRef V2) { + if (V1 == V2) { + outs() << formatv(" {0}: No differences detected!\n", Label); + return false; + } + + outs().indent(2) << Label << "\n"; + outs().indent(4) << formatv("{0}: {1}\n", File1.getFilePath(), + make_range(V1.begin(), V1.end())); + outs().indent(4) << formatv("{0}: {1}\n", File2.getFilePath(), + make_range(V2.begin(), V2.end())); + return true; +} + +template +static bool printSymmetricDifferences(PDBFile &File1, PDBFile &File2, + T &&OnlyRange1, T &&OnlyRange2, + StringRef Label) { + bool HasDiff = false; + if (!OnlyRange1.empty()) { + HasDiff = true; + outs() << formatv(" {0} {1}(s) only in ({2})\n", OnlyRange1.size(), Label, + File1.getFilePath()); + for (const auto &Item : OnlyRange1) + outs() << formatv(" {0}\n", Label, Item); + } + if (!OnlyRange2.empty()) { + HasDiff = true; + outs() << formatv(" {0} {1}(s) only in ({2})\n", OnlyRange2.size(), + File2.getFilePath()); + for (const auto &Item : OnlyRange2) + outs() << formatv(" {0}\n", Item); + } + return HasDiff; +} + +Error DiffStyle::diffSuperBlock() { + outs() << "MSF Super Block: Searching for differences...\n"; + bool Diffs = false; + + Diffs |= diffAndPrint("Block Size", File1, File2, File1.getBlockSize(), + File2.getBlockSize()); + Diffs |= diffAndPrint("Block Count", File1, File2, File1.getBlockCount(), + File2.getBlockCount()); + Diffs |= diffAndPrint("Unknown 1", File1, File2, File1.getUnknown1(), + File2.getUnknown1()); + + if (opts::diff::Pedantic) { + Diffs |= diffAndPrint("Free Block Map", File1, File2, + File1.getFreeBlockMapBlock(), + File2.getFreeBlockMapBlock()); + Diffs |= diffAndPrint("Directory Size", File1, File2, + File1.getNumDirectoryBytes(), + File2.getNumDirectoryBytes()); + Diffs |= diffAndPrint("Block Map Addr", File1, File2, + File1.getBlockMapOffset(), File2.getBlockMapOffset()); + } + if (!Diffs) + outs() << "MSF Super Block: No differences detected...\n"; + return Error::success(); +} + +Error DiffStyle::diffStreamDirectory() { + SmallVector P; + SmallVector Q; + discoverStreamPurposes(File1, P); + discoverStreamPurposes(File2, Q); + outs() << "Stream Directory: Searching for differences...\n"; + + bool HasDifferences = false; + if (opts::diff::Pedantic) { + size_t Min = std::min(P.size(), Q.size()); + for (size_t I = 0; I < Min; ++I) { + StringRef Names[] = {P[I], Q[I]}; + uint32_t Sizes[] = {File1.getStreamByteSize(I), + File2.getStreamByteSize(I)}; + bool NamesDiffer = Names[0] != Names[1]; + bool SizesDiffer = Sizes[0] != Sizes[1]; + if (NamesDiffer) { + HasDifferences = true; + outs().indent(2) << formatv("Stream {0} - {1}: {2}, {3}: {4}\n", I, + File1.getFilePath(), Names[0], + File2.getFilePath(), Names[1]); + continue; + } + if (SizesDiffer) { + HasDifferences = true; + outs().indent(2) << formatv( + "Stream {0} ({1}): {2}: {3} bytes, {4}: {5} bytes\n", I, Names[0], + File1.getFilePath(), Sizes[0], File2.getFilePath(), Sizes[1]); + continue; + } + } + + ArrayRef MaxNames = (P.size() > Q.size() ? P : Q); + size_t Max = std::max(P.size(), Q.size()); + PDBFile &MaxFile = (P.size() > Q.size() ? File1 : File2); + StringRef MinFileName = + (P.size() < Q.size() ? File1.getFilePath() : File2.getFilePath()); + for (size_t I = Min; I < Max; ++I) { + HasDifferences = true; + StringRef StreamName = MaxNames[I]; + + outs().indent(2) << formatv( + "Stream {0} - {1}: , {2}: Index {3}, {4} bytes\n", + StreamName, MinFileName, MaxFile.getFilePath(), I, + MaxFile.getStreamByteSize(I)); + } + if (!HasDifferences) + outs() << "Stream Directory: No differences detected...\n"; + } else { + auto PI = to_vector<32>(enumerate(P)); + auto QI = to_vector<32>(enumerate(Q)); + + typedef decltype(PI) ContainerType; + typedef typename ContainerType::value_type value_type; + + auto Comparator = [](const value_type &I1, const value_type &I2) { + return I1.value() < I2.value(); + }; + + decltype(PI) OnlyP; + decltype(QI) OnlyQ; + decltype(PI) Common; + + set_differences(PI, QI, &OnlyP, &OnlyQ, &Common, Comparator); + + if (!OnlyP.empty()) { + HasDifferences = true; + outs().indent(2) << formatv("{0} Stream(s) only in ({1})\n", OnlyP.size(), + File1.getFilePath()); + for (auto &Item : OnlyP) { + outs().indent(4) << formatv("Stream {0} - {1}\n", Item.index(), + Item.value()); + } + } + + if (!OnlyQ.empty()) { + HasDifferences = true; + outs().indent(2) << formatv("{0} Streams(s) only in ({1})\n", + OnlyQ.size(), File2.getFilePath()); + for (auto &Item : OnlyQ) { + outs().indent(4) << formatv("Stream {0} - {1}\n", Item.index(), + Item.value()); + } + } + if (!Common.empty()) { + outs().indent(2) << formatv("Found {0} common streams. Searching for " + "intra-stream differences.\n", + Common.size()); + bool HasCommonDifferences = false; + for (const auto &Left : Common) { + // Left was copied from the first range so its index refers to a stream + // index in the first file. Find the corresponding stream index in the + // second file. + auto Range = + std::equal_range(QI.begin(), QI.end(), Left, + [](const value_type &L, const value_type &R) { + return L.value() < R.value(); + }); + const auto &Right = *Range.first; + assert(Left.value() == Right.value()); + uint32_t LeftSize = File1.getStreamByteSize(Left.index()); + uint32_t RightSize = File2.getStreamByteSize(Right.index()); + if (LeftSize != RightSize) { + HasDifferences = true; + HasCommonDifferences = true; + outs().indent(4) << formatv("{0} ({1}: {2} bytes, {3}: {4} bytes)\n", + Left.value(), File1.getFilePath(), + LeftSize, File2.getFilePath(), RightSize); + } + } + if (!HasCommonDifferences) + outs().indent(2) << "Common Streams: No differences detected!\n"; + } + if (!HasDifferences) + outs() << "Stream Directory: No differences detected!\n"; + } + + return Error::success(); +} + +Error DiffStyle::diffStringTable() { + auto ExpectedST1 = File1.getStringTable(); + auto ExpectedST2 = File2.getStringTable(); + outs() << "String Table: Searching for differences...\n"; + bool Has1 = !!ExpectedST1; + bool Has2 = !!ExpectedST2; + if (!(Has1 && Has2)) { + // If one has a string table and the other doesn't, we can print less + // output. + if (Has1 != Has2) { + if (Has1) { + outs() << formatv(" {0}: ({1} strings)\n", File1.getFilePath(), + ExpectedST1->getNameCount()); + outs() << formatv(" {0}: (string table not present)\n", + File2.getFilePath()); + } else { + outs() << formatv(" {0}: (string table not present)\n", + File1.getFilePath()); + outs() << formatv(" {0}: ({1})\n", File2.getFilePath(), + ExpectedST2->getNameCount()); + } + } + consumeError(ExpectedST1.takeError()); + consumeError(ExpectedST2.takeError()); + return Error::success(); + } + + bool HasDiff = false; + auto &ST1 = *ExpectedST1; + auto &ST2 = *ExpectedST2; + + if (ST1.getByteSize() != ST2.getByteSize()) { + outs() << " Stream Size\n"; + outs() << formatv(" {0} - {1} byte(s)\n", File1.getFilePath(), + ST1.getByteSize()); + outs() << formatv(" {0} - {1} byte(s)\n", File2.getFilePath(), + ST2.getByteSize()); + outs() << formatv(" Difference: {0} bytes\n", + AbsoluteDifference(ST1.getByteSize(), ST2.getByteSize())); + HasDiff = true; + } + HasDiff |= diffAndPrint("Hash Version", File1, File2, ST1.getHashVersion(), + ST1.getHashVersion()); + HasDiff |= diffAndPrint("Signature", File1, File2, ST1.getSignature(), + ST1.getSignature()); + + // Both have a valid string table, dive in and compare individual strings. + + auto IdList1 = ST1.name_ids(); + auto IdList2 = ST2.name_ids(); + if (opts::diff::Pedantic) { + // In pedantic mode, we compare index by index (i.e. the strings are in the + // same order + // in both tables. + uint32_t Max = std::max(IdList1.size(), IdList2.size()); + for (uint32_t I = 0; I < Max; ++I) { + Optional Id1, Id2; + StringRef S1, S2; + if (I < IdList1.size()) { + Id1 = IdList1[I]; + if (auto Result = ST1.getStringForID(*Id1)) + S1 = *Result; + else + return Result.takeError(); + } + if (I < IdList2.size()) { + Id2 = IdList2[I]; + if (auto Result = ST2.getStringForID(*Id2)) + S2 = *Result; + else + return Result.takeError(); + } + if (Id1 == Id2 && S1 == S2) + continue; + + std::string OutId1 = + Id1 ? formatv("{0}", *Id1).str() : "(index not present)"; + std::string OutId2 = + Id2 ? formatv("{0}", *Id2).str() : "(index not present)"; + outs() << formatv(" String {0}\n", I); + outs() << formatv(" {0}: Hash - {1}, Value - {2}\n", + File1.getFilePath(), OutId1, S1); + outs() << formatv(" {0}: Hash - {1}, Value - {2}\n", + File2.getFilePath(), OutId2, S2); + HasDiff = true; + } + } else { + std::vector Strings1, Strings2; + Strings1.reserve(IdList1.size()); + Strings2.reserve(IdList2.size()); + for (auto ID : IdList1) { + auto S = ST1.getStringForID(ID); + if (!S) + return S.takeError(); + Strings1.push_back(*S); + } + for (auto ID : IdList2) { + auto S = ST2.getStringForID(ID); + if (!S) + return S.takeError(); + Strings2.push_back(*S); + } + + SmallVector OnlyP; + SmallVector OnlyQ; + auto End1 = std::remove(Strings1.begin(), Strings1.end(), ""); + auto End2 = std::remove(Strings2.begin(), Strings2.end(), ""); + uint32_t Empty1 = std::distance(End1, Strings1.end()); + uint32_t Empty2 = std::distance(End2, Strings2.end()); + Strings1.erase(End1, Strings1.end()); + Strings2.erase(End2, Strings2.end()); + set_differences(Strings1, Strings2, &OnlyP, &OnlyQ); + printSymmetricDifferences(File1, File2, OnlyP, OnlyQ, "String"); + + if (Empty1 != Empty2) { + PDBFile &MoreF = (Empty1 > Empty2) ? File1 : File2; + PDBFile &LessF = (Empty1 < Empty2) ? File1 : File2; + uint32_t Difference = AbsoluteDifference(Empty1, Empty2); + outs() << formatv(" {0} had {1} more empty strings than {2}\n", + MoreF.getFilePath(), Difference, LessF.getFilePath()); + } + } + if (!HasDiff) + outs() << "String Table: No differences detected!\n"; + return Error::success(); +} + +Error DiffStyle::diffFreePageMap() { return Error::success(); } + +Error DiffStyle::diffInfoStream() { + auto ExpectedInfo1 = File1.getPDBInfoStream(); + auto ExpectedInfo2 = File2.getPDBInfoStream(); + + outs() << "PDB Stream: Searching for differences...\n"; + bool Has1 = !!ExpectedInfo1; + bool Has2 = !!ExpectedInfo2; + if (!(Has1 && Has2)) { + if (Has1 != Has2) + outs() << formatv("{0} does not have a PDB Stream!\n", + Has1 ? File1.getFilePath() : File2.getFilePath()); + consumeError(ExpectedInfo2.takeError()); + consumeError(ExpectedInfo2.takeError()); + return Error::success(); + } + + bool HasDiff = false; + auto &IS1 = *ExpectedInfo1; + auto &IS2 = *ExpectedInfo2; + if (IS1.getStreamSize() != IS2.getStreamSize()) { + outs() << " Stream Size\n"; + outs() << formatv(" {0} - {1} byte(s)\n", File1.getFilePath(), + IS1.getStreamSize()); + outs() << formatv(" {0} - {1} byte(s)\n", File2.getFilePath(), + IS2.getStreamSize()); + outs() << formatv( + " Difference: {0} bytes\n", + AbsoluteDifference(IS1.getStreamSize(), IS2.getStreamSize())); + HasDiff = true; + } + HasDiff |= diffAndPrint("Age", File1, File2, IS1.getAge(), IS2.getAge()); + HasDiff |= diffAndPrint("Guid", File1, File2, IS1.getGuid(), IS2.getGuid()); + HasDiff |= diffAndPrint("Signature", File1, File2, IS1.getSignature(), + IS2.getSignature()); + HasDiff |= + diffAndPrint("Version", File1, File2, IS1.getVersion(), IS2.getVersion()); + HasDiff |= diffAndPrint("Features", File1, File2, IS1.getFeatureSignatures(), + IS2.getFeatureSignatures()); + HasDiff |= diffAndPrint("Named Stream Byte Size", File1, File2, + IS1.getNamedStreamMapByteSize(), + IS2.getNamedStreamMapByteSize()); + SmallVector NS1; + SmallVector NS2; + for (const auto &X : IS1.getNamedStreams().entries()) + NS1.push_back(X.getKey()); + for (const auto &X : IS2.getNamedStreams().entries()) + NS2.push_back(X.getKey()); + SmallVector OnlyP; + SmallVector OnlyQ; + set_differences(NS1, NS2, &OnlyP, &OnlyQ); + printSymmetricDifferences(File1, File2, OnlyP, OnlyQ, "Named Streams"); + if (!HasDiff) + outs() << "PDB Stream: No differences detected!\n"; + + return Error::success(); +} + +Error DiffStyle::diffDbiStream() { return Error::success(); } + +Error DiffStyle::diffSectionContribs() { return Error::success(); } + +Error DiffStyle::diffSectionMap() { return Error::success(); } + +Error DiffStyle::diffFpoStream() { return Error::success(); } + +Error DiffStyle::diffTpiStream(int Index) { return Error::success(); } + +Error DiffStyle::diffModuleInfoStream(int Index) { return Error::success(); } + +Error DiffStyle::diffPublics() { return Error::success(); } + +Error DiffStyle::diffGlobals() { return Error::success(); } diff --git a/tools/llvm-pdbutil/Diff.h b/tools/llvm-pdbutil/Diff.h new file mode 100644 index 000000000000..6037576e21bb --- /dev/null +++ b/tools/llvm-pdbutil/Diff.h @@ -0,0 +1,45 @@ +//===- Diff.h - PDB diff utility --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_DIFF_H +#define LLVM_TOOLS_LLVMPDBDUMP_DIFF_H + +#include "OutputStyle.h" + +namespace llvm { +namespace pdb { +class PDBFile; +class DiffStyle : public OutputStyle { +public: + explicit DiffStyle(PDBFile &File1, PDBFile &File2); + + Error dump() override; + +private: + Error diffSuperBlock(); + Error diffStreamDirectory(); + Error diffStringTable(); + Error diffFreePageMap(); + Error diffInfoStream(); + Error diffDbiStream(); + Error diffSectionContribs(); + Error diffSectionMap(); + Error diffFpoStream(); + Error diffTpiStream(int Index); + Error diffModuleInfoStream(int Index); + Error diffPublics(); + Error diffGlobals(); + + PDBFile &File1; + PDBFile &File2; +}; +} +} + +#endif diff --git a/tools/llvm-pdbutil/LLVMBuild.txt b/tools/llvm-pdbutil/LLVMBuild.txt new file mode 100644 index 000000000000..adbe4993e3fa --- /dev/null +++ b/tools/llvm-pdbutil/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- ./tools/llvm-pdbutil/LLVMBuild.txt -----------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-pdbutil +parent = Tools +required_libraries = DebugInfoMSF DebugInfoPDB + diff --git a/tools/llvm-pdbutil/LLVMOutputStyle.cpp b/tools/llvm-pdbutil/LLVMOutputStyle.cpp new file mode 100644 index 000000000000..824f88f8efd0 --- /dev/null +++ b/tools/llvm-pdbutil/LLVMOutputStyle.cpp @@ -0,0 +1,1188 @@ +//===- LLVMOutputStyle.cpp ------------------------------------ *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "LLVMOutputStyle.h" + +#include "CompactTypeDumpVisitor.h" +#include "StreamUtil.h" +#include "llvm-pdbutil.h" + +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" +#include "llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h" +#include "llvm/DebugInfo/CodeView/EnumTables.h" +#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" +#include "llvm/DebugInfo/CodeView/Line.h" +#include "llvm/DebugInfo/CodeView/SymbolDumper.h" +#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" +#include "llvm/DebugInfo/PDB/Native/DbiStream.h" +#include "llvm/DebugInfo/PDB/Native/EnumTables.h" +#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" +#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h" +#include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/PublicsStream.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/TpiHashing.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" +#include "llvm/DebugInfo/PDB/PDBExtras.h" +#include "llvm/Object/COFF.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/FormatVariadic.h" + +#include + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::msf; +using namespace llvm::pdb; + +namespace { +struct PageStats { + explicit PageStats(const BitVector &FreePages) + : Upm(FreePages), ActualUsedPages(FreePages.size()), + MultiUsePages(FreePages.size()), UseAfterFreePages(FreePages.size()) { + const_cast(Upm).flip(); + // To calculate orphaned pages, we start with the set of pages that the + // MSF thinks are used. Each time we find one that actually *is* used, + // we unset it. Whichever bits remain set at the end are orphaned. + OrphanedPages = Upm; + } + + // The inverse of the MSF File's copy of the Fpm. The basis for which we + // determine the allocation status of each page. + const BitVector Upm; + + // Pages which are marked as used in the FPM and are used at least once. + BitVector ActualUsedPages; + + // Pages which are marked as used in the FPM but are used more than once. + BitVector MultiUsePages; + + // Pages which are marked as used in the FPM but are not used at all. + BitVector OrphanedPages; + + // Pages which are marked free in the FPM but are used. + BitVector UseAfterFreePages; +}; + +class C13RawVisitor : public DebugSubsectionVisitor { +public: + C13RawVisitor(ScopedPrinter &P, LazyRandomTypeCollection &TPI, + LazyRandomTypeCollection &IPI) + : P(P), TPI(TPI), IPI(IPI) {} + + Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::Unknown)) + return Error::success(); + DictScope DD(P, "Unknown"); + P.printHex("Kind", static_cast(Unknown.kind())); + ArrayRef Data; + BinaryStreamReader Reader(Unknown.getData()); + consumeError(Reader.readBytes(Data, Reader.bytesRemaining())); + P.printBinaryBlock("Data", Data); + return Error::success(); + } + + Error visitLines(DebugLinesSubsectionRef &Lines, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::Lines)) + return Error::success(); + + DictScope DD(P, "Lines"); + + P.printNumber("RelocSegment", Lines.header()->RelocSegment); + P.printNumber("RelocOffset", Lines.header()->RelocOffset); + P.printNumber("CodeSize", Lines.header()->CodeSize); + P.printBoolean("HasColumns", Lines.hasColumnInfo()); + + for (const auto &L : Lines) { + DictScope DDDD(P, "FileEntry"); + + if (auto EC = printFileName("FileName", L.NameIndex, State)) + return EC; + + for (const auto &N : L.LineNumbers) { + DictScope DDD(P, "Line"); + LineInfo LI(N.Flags); + P.printNumber("Offset", N.Offset); + if (LI.isAlwaysStepInto()) + P.printString("StepInto", StringRef("Always")); + else if (LI.isNeverStepInto()) + P.printString("StepInto", StringRef("Never")); + else + P.printNumber("LineNumberStart", LI.getStartLine()); + P.printNumber("EndDelta", LI.getLineDelta()); + P.printBoolean("IsStatement", LI.isStatement()); + } + for (const auto &C : L.Columns) { + DictScope DDD(P, "Column"); + P.printNumber("Start", C.StartColumn); + P.printNumber("End", C.EndColumn); + } + } + + return Error::success(); + } + + Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::FileChecksums)) + return Error::success(); + + DictScope DD(P, "FileChecksums"); + for (const auto &CS : Checksums) { + DictScope DDD(P, "Checksum"); + if (auto Result = getNameFromStringTable(CS.FileNameOffset, State)) + P.printString("FileName", *Result); + else + return Result.takeError(); + P.printEnum("Kind", uint8_t(CS.Kind), getFileChecksumNames()); + P.printBinaryBlock("Checksum", CS.Checksum); + } + return Error::success(); + } + + Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::InlineeLines)) + return Error::success(); + + DictScope D(P, "InlineeLines"); + P.printBoolean("HasExtraFiles", Inlinees.hasExtraFiles()); + ListScope LS(P, "Lines"); + for (const auto &L : Inlinees) { + DictScope DDD(P, "Inlinee"); + if (auto EC = printFileName("FileName", L.Header->FileID, State)) + return EC; + + if (auto EC = dumpTypeRecord("Function", L.Header->Inlinee)) + return EC; + P.printNumber("SourceLine", L.Header->SourceLineNum); + if (Inlinees.hasExtraFiles()) { + ListScope DDDD(P, "ExtraFiles"); + for (const auto &EF : L.ExtraFiles) { + if (auto EC = printFileName("File", EF, State)) + return EC; + } + } + } + return Error::success(); + } + + Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeExports)) + return Error::success(); + + ListScope D(P, "CrossModuleExports"); + for (const auto &M : CSE) { + DictScope D(P, "Export"); + P.printHex("Local", M.Local); + P.printHex("Global", M.Global); + } + return Error::success(); + } + + Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSI, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeImports)) + return Error::success(); + + ListScope L(P, "CrossModuleImports"); + for (const auto &M : CSI) { + DictScope D(P, "ModuleImport"); + auto Name = getNameFromStringTable(M.Header->ModuleNameOffset, State); + if (!Name) + return Name.takeError(); + P.printString("Module", *Name); + P.printHexList("Imports", M.Imports); + } + return Error::success(); + } + + Error visitFrameData(DebugFrameDataSubsectionRef &FD, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::FrameData)) + return Error::success(); + + ListScope L(P, "FrameData"); + for (const auto &Frame : FD) { + DictScope D(P, "Frame"); + auto Name = getNameFromStringTable(Frame.FrameFunc, State); + if (!Name) + return joinErrors(make_error(raw_error_code::invalid_format, + "Invalid Frame.FrameFunc index"), + Name.takeError()); + P.printNumber("Rva", Frame.RvaStart); + P.printNumber("CodeSize", Frame.CodeSize); + P.printNumber("LocalSize", Frame.LocalSize); + P.printNumber("ParamsSize", Frame.ParamsSize); + P.printNumber("MaxStackSize", Frame.MaxStackSize); + P.printString("FrameFunc", *Name); + P.printNumber("PrologSize", Frame.PrologSize); + P.printNumber("SavedRegsSize", Frame.SavedRegsSize); + P.printNumber("Flags", Frame.Flags); + } + return Error::success(); + } + + Error visitSymbols(DebugSymbolsSubsectionRef &Symbols, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::Symbols)) + return Error::success(); + ListScope L(P, "Symbols"); + + // This section should not actually appear in a PDB file, it really only + // appears in object files. But we support it here for testing. So we + // specify the Object File container type. + codeview::CVSymbolDumper SD(P, TPI, CodeViewContainer::ObjectFile, nullptr, + false); + for (auto S : Symbols) { + DictScope LL(P, ""); + if (auto EC = SD.dump(S)) { + return make_error( + raw_error_code::corrupt_file, + "DEBUG_S_SYMBOLS subsection contained corrupt symbol record"); + } + } + return Error::success(); + } + + Error visitStringTable(DebugStringTableSubsectionRef &Strings, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::StringTable)) + return Error::success(); + + ListScope D(P, "String Table"); + BinaryStreamReader Reader(Strings.getBuffer()); + StringRef S; + consumeError(Reader.readCString(S)); + while (Reader.bytesRemaining() > 0) { + consumeError(Reader.readCString(S)); + if (S.empty() && Reader.bytesRemaining() < 4) + break; + P.printString(S); + } + return Error::success(); + } + + Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &RVAs, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::CoffSymbolRVAs)) + return Error::success(); + + ListScope D(P, "COFF Symbol RVAs"); + P.printHexList("RVAs", RVAs); + return Error::success(); + } + +private: + Error dumpTypeRecord(StringRef Label, TypeIndex Index) { + CompactTypeDumpVisitor CTDV(IPI, Index, &P); + DictScope D(P, Label); + if (IPI.contains(Index)) { + CVType Type = IPI.getType(Index); + if (auto EC = codeview::visitTypeRecord(Type, CTDV)) + return EC; + } else { + P.printString( + llvm::formatv("Index: {0:x} (unknown function)", Index.getIndex()) + .str()); + } + return Error::success(); + } + Error printFileName(StringRef Label, uint32_t Offset, + const DebugSubsectionState &State) { + if (auto Result = getNameFromChecksumsBuffer(Offset, State)) { + P.printString(Label, *Result); + return Error::success(); + } else + return Result.takeError(); + } + + Expected + getNameFromStringTable(uint32_t Offset, const DebugSubsectionState &State) { + return State.strings().getString(Offset); + } + + Expected + getNameFromChecksumsBuffer(uint32_t Offset, + const DebugSubsectionState &State) { + auto Array = State.checksums().getArray(); + auto ChecksumIter = Array.at(Offset); + if (ChecksumIter == Array.end()) + return make_error(raw_error_code::invalid_format); + const auto &Entry = *ChecksumIter; + return getNameFromStringTable(Entry.FileNameOffset, State); + } + + ScopedPrinter &P; + LazyRandomTypeCollection &TPI; + LazyRandomTypeCollection &IPI; +}; +} + +static void recordKnownUsedPage(PageStats &Stats, uint32_t UsedIndex) { + if (Stats.Upm.test(UsedIndex)) { + if (Stats.ActualUsedPages.test(UsedIndex)) + Stats.MultiUsePages.set(UsedIndex); + Stats.ActualUsedPages.set(UsedIndex); + Stats.OrphanedPages.reset(UsedIndex); + } else { + // The MSF doesn't think this page is used, but it is. + Stats.UseAfterFreePages.set(UsedIndex); + } +} + +static void printSectionOffset(llvm::raw_ostream &OS, + const SectionOffset &Off) { + OS << Off.Off << ", " << Off.Isect; +} + +LLVMOutputStyle::LLVMOutputStyle(PDBFile &File) : File(File), P(outs()) {} + +Error LLVMOutputStyle::dump() { + if (auto EC = dumpFileHeaders()) + return EC; + + if (auto EC = dumpStreamSummary()) + return EC; + + if (auto EC = dumpFreePageMap()) + return EC; + + if (auto EC = dumpStreamBlocks()) + return EC; + + if (auto EC = dumpBlockRanges()) + return EC; + + if (auto EC = dumpStreamBytes()) + return EC; + + if (auto EC = dumpStringTable()) + return EC; + + if (auto EC = dumpInfoStream()) + return EC; + + if (auto EC = dumpTpiStream(StreamTPI)) + return EC; + + if (auto EC = dumpTpiStream(StreamIPI)) + return EC; + + if (auto EC = dumpDbiStream()) + return EC; + + if (auto EC = dumpSectionContribs()) + return EC; + + if (auto EC = dumpSectionMap()) + return EC; + + if (auto EC = dumpGlobalsStream()) + return EC; + + if (auto EC = dumpPublicsStream()) + return EC; + + if (auto EC = dumpSectionHeaders()) + return EC; + + if (auto EC = dumpFpoStream()) + return EC; + + flush(); + + return Error::success(); +} + +Error LLVMOutputStyle::dumpFileHeaders() { + if (!opts::raw::DumpHeaders) + return Error::success(); + + DictScope D(P, "FileHeaders"); + P.printNumber("BlockSize", File.getBlockSize()); + P.printNumber("FreeBlockMap", File.getFreeBlockMapBlock()); + P.printNumber("NumBlocks", File.getBlockCount()); + P.printNumber("NumDirectoryBytes", File.getNumDirectoryBytes()); + P.printNumber("Unknown1", File.getUnknown1()); + P.printNumber("BlockMapAddr", File.getBlockMapIndex()); + P.printNumber("NumDirectoryBlocks", File.getNumDirectoryBlocks()); + + // The directory is not contiguous. Instead, the block map contains a + // contiguous list of block numbers whose contents, when concatenated in + // order, make up the directory. + P.printList("DirectoryBlocks", File.getDirectoryBlockArray()); + P.printNumber("NumStreams", File.getNumStreams()); + return Error::success(); +} + +Error LLVMOutputStyle::dumpStreamSummary() { + if (!opts::raw::DumpStreamSummary) + return Error::success(); + + if (StreamPurposes.empty()) + discoverStreamPurposes(File, StreamPurposes); + + uint32_t StreamCount = File.getNumStreams(); + + ListScope L(P, "Streams"); + for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) { + std::string Label("Stream "); + Label += to_string(StreamIdx); + + std::string Value = "[" + StreamPurposes[StreamIdx] + "] ("; + Value += to_string(File.getStreamByteSize(StreamIdx)); + Value += " bytes)"; + + P.printString(Label, Value); + } + + P.flush(); + return Error::success(); +} + +Error LLVMOutputStyle::dumpFreePageMap() { + if (!opts::raw::DumpPageStats) + return Error::success(); + + // Start with used pages instead of free pages because + // the number of free pages is far larger than used pages. + BitVector FPM = File.getMsfLayout().FreePageMap; + + PageStats PS(FPM); + + recordKnownUsedPage(PS, 0); // MSF Super Block + + uint32_t BlocksPerSection = msf::getFpmIntervalLength(File.getMsfLayout()); + uint32_t NumSections = msf::getNumFpmIntervals(File.getMsfLayout()); + for (uint32_t I = 0; I < NumSections; ++I) { + uint32_t Fpm0 = 1 + BlocksPerSection * I; + // 2 Fpm blocks spaced at `getBlockSize()` block intervals + recordKnownUsedPage(PS, Fpm0); + recordKnownUsedPage(PS, Fpm0 + 1); + } + + recordKnownUsedPage(PS, File.getBlockMapIndex()); // Stream Table + + for (auto DB : File.getDirectoryBlockArray()) + recordKnownUsedPage(PS, DB); + + // Record pages used by streams. Note that pages for stream 0 + // are considered being unused because that's what MSVC tools do. + // Stream 0 doesn't contain actual data, so it makes some sense, + // though it's a bit confusing to us. + for (auto &SE : File.getStreamMap().drop_front(1)) + for (auto &S : SE) + recordKnownUsedPage(PS, S); + + dumpBitVector("Msf Free Pages", FPM); + dumpBitVector("Orphaned Pages", PS.OrphanedPages); + dumpBitVector("Multiply Used Pages", PS.MultiUsePages); + dumpBitVector("Use After Free Pages", PS.UseAfterFreePages); + return Error::success(); +} + +void LLVMOutputStyle::dumpBitVector(StringRef Name, const BitVector &V) { + std::vector Vec; + for (uint32_t I = 0, E = V.size(); I != E; ++I) + if (V[I]) + Vec.push_back(I); + P.printList(Name, Vec); +} + +Error LLVMOutputStyle::dumpGlobalsStream() { + if (!opts::raw::DumpGlobals) + return Error::success(); + if (!File.hasPDBGlobalsStream()) { + P.printString("Globals Stream not present"); + return Error::success(); + } + + auto Globals = File.getPDBGlobalsStream(); + if (!Globals) + return Globals.takeError(); + DictScope D(P, "Globals Stream"); + + auto Dbi = File.getPDBDbiStream(); + if (!Dbi) + return Dbi.takeError(); + + P.printNumber("Stream number", Dbi->getGlobalSymbolStreamIndex()); + P.printNumber("Number of buckets", Globals->getNumBuckets()); + P.printList("Hash Buckets", Globals->getHashBuckets()); + + return Error::success(); +} + +Error LLVMOutputStyle::dumpStreamBlocks() { + if (!opts::raw::DumpStreamBlocks) + return Error::success(); + + ListScope L(P, "StreamBlocks"); + uint32_t StreamCount = File.getNumStreams(); + for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) { + std::string Name("Stream "); + Name += to_string(StreamIdx); + auto StreamBlocks = File.getStreamBlockList(StreamIdx); + P.printList(Name, StreamBlocks); + } + return Error::success(); +} + +Error LLVMOutputStyle::dumpBlockRanges() { + if (!opts::raw::DumpBlockRange.hasValue()) + return Error::success(); + auto &R = *opts::raw::DumpBlockRange; + uint32_t Max = R.Max.getValueOr(R.Min); + + if (Max < R.Min) + return make_error( + "Invalid block range specified. Max < Min", + std::make_error_code(std::errc::bad_address)); + if (Max >= File.getBlockCount()) + return make_error( + "Invalid block range specified. Requested block out of bounds", + std::make_error_code(std::errc::bad_address)); + + DictScope D(P, "Block Data"); + for (uint32_t I = R.Min; I <= Max; ++I) { + auto ExpectedData = File.getBlockData(I, File.getBlockSize()); + if (!ExpectedData) + return ExpectedData.takeError(); + std::string Label; + llvm::raw_string_ostream S(Label); + S << "Block " << I; + S.flush(); + P.printBinaryBlock(Label, *ExpectedData); + } + + return Error::success(); +} + +static Error parseStreamSpec(StringRef Str, uint32_t &SI, uint32_t &Offset, + uint32_t &Size) { + if (Str.consumeInteger(0, SI)) + return make_error(raw_error_code::invalid_format, + "Invalid Stream Specification"); + if (Str.consume_front(":")) { + if (Str.consumeInteger(0, Offset)) + return make_error(raw_error_code::invalid_format, + "Invalid Stream Specification"); + } + if (Str.consume_front("@")) { + if (Str.consumeInteger(0, Size)) + return make_error(raw_error_code::invalid_format, + "Invalid Stream Specification"); + } + if (!Str.empty()) + return make_error(raw_error_code::invalid_format, + "Invalid Stream Specification"); + return Error::success(); +} + +Error LLVMOutputStyle::dumpStreamBytes() { + if (opts::raw::DumpStreamData.empty()) + return Error::success(); + + if (StreamPurposes.empty()) + discoverStreamPurposes(File, StreamPurposes); + + DictScope D(P, "Stream Data"); + for (auto &Str : opts::raw::DumpStreamData) { + uint32_t SI = 0; + uint32_t Begin = 0; + uint32_t Size = 0; + uint32_t End = 0; + + if (auto EC = parseStreamSpec(Str, SI, Begin, Size)) + return EC; + + if (SI >= File.getNumStreams()) + return make_error(raw_error_code::no_stream); + + auto S = MappedBlockStream::createIndexedStream( + File.getMsfLayout(), File.getMsfBuffer(), SI, File.getAllocator()); + if (!S) + continue; + DictScope DD(P, "Stream"); + if (Size == 0) + End = S->getLength(); + else { + End = Begin + Size; + if (End >= S->getLength()) + return make_error(raw_error_code::index_out_of_bounds, + "Stream is not long enough!"); + } + + P.printNumber("Index", SI); + P.printString("Type", StreamPurposes[SI]); + P.printNumber("Size", S->getLength()); + auto Blocks = File.getMsfLayout().StreamMap[SI]; + P.printList("Blocks", Blocks); + + BinaryStreamReader R(*S); + ArrayRef StreamData; + if (auto EC = R.readBytes(StreamData, S->getLength())) + return EC; + Size = End - Begin; + StreamData = StreamData.slice(Begin, Size); + P.printBinaryBlock("Data", StreamData, Begin); + } + return Error::success(); +} + +Error LLVMOutputStyle::dumpStringTable() { + if (!opts::raw::DumpStringTable) + return Error::success(); + + auto IS = File.getStringTable(); + if (!IS) + return IS.takeError(); + + DictScope D(P, "String Table"); + for (uint32_t I : IS->name_ids()) { + auto ES = IS->getStringForID(I); + if (!ES) + return ES.takeError(); + + if (ES->empty()) + continue; + llvm::SmallString<32> Str; + Str.append("'"); + Str.append(*ES); + Str.append("'"); + P.printString(Str); + } + return Error::success(); +} + +Error LLVMOutputStyle::dumpInfoStream() { + if (!opts::raw::DumpHeaders) + return Error::success(); + if (!File.hasPDBInfoStream()) { + P.printString("PDB Stream not present"); + return Error::success(); + } + auto IS = File.getPDBInfoStream(); + if (!IS) + return IS.takeError(); + + DictScope D(P, "PDB Stream"); + P.printNumber("Version", IS->getVersion()); + P.printHex("Signature", IS->getSignature()); + P.printNumber("Age", IS->getAge()); + P.printObject("Guid", IS->getGuid()); + P.printHex("Features", IS->getFeatures()); + { + DictScope DD(P, "Named Streams"); + for (const auto &S : IS->getNamedStreams().entries()) + P.printObject(S.getKey(), S.getValue()); + } + return Error::success(); +} + +namespace { +class RecordBytesVisitor : public TypeVisitorCallbacks { +public: + explicit RecordBytesVisitor(ScopedPrinter &P) : P(P) {} + + Error visitTypeEnd(CVType &Record) override { + P.printBinaryBlock("Bytes", Record.content()); + return Error::success(); + } + +private: + ScopedPrinter &P; +}; +} + +Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { + assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI); + + bool DumpRecordBytes = false; + bool DumpRecords = false; + bool DumpTpiHash = false; + StringRef Label; + StringRef VerLabel; + if (StreamIdx == StreamTPI) { + if (!File.hasPDBTpiStream()) { + P.printString("Type Info Stream (TPI) not present"); + return Error::success(); + } + DumpRecordBytes = opts::raw::DumpTpiRecordBytes; + DumpRecords = opts::raw::DumpTpiRecords; + DumpTpiHash = opts::raw::DumpTpiHash; + Label = "Type Info Stream (TPI)"; + VerLabel = "TPI Version"; + } else if (StreamIdx == StreamIPI) { + if (!File.hasPDBIpiStream()) { + P.printString("Type Info Stream (IPI) not present"); + return Error::success(); + } + DumpRecordBytes = opts::raw::DumpIpiRecordBytes; + DumpRecords = opts::raw::DumpIpiRecords; + Label = "Type Info Stream (IPI)"; + VerLabel = "IPI Version"; + } + + auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream() + : File.getPDBIpiStream(); + if (!Tpi) + return Tpi.takeError(); + + auto ExpectedTypes = initializeTypeDatabase(StreamIdx); + if (!ExpectedTypes) + return ExpectedTypes.takeError(); + auto &Types = *ExpectedTypes; + + if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash) + return Error::success(); + + std::unique_ptr StreamScope; + std::unique_ptr RecordScope; + + StreamScope = llvm::make_unique(P, Label); + P.printNumber(VerLabel, Tpi->getTpiVersion()); + P.printNumber("Record count", Tpi->getNumTypeRecords()); + + std::vector> Visitors; + + // If we're in dump mode, add a dumper with the appropriate detail level. + if (DumpRecords) { + std::unique_ptr Dumper; + if (opts::raw::CompactRecords) + Dumper = make_unique(Types, &P); + else { + assert(TpiTypes); + + auto X = make_unique(*TpiTypes, &P, false); + if (StreamIdx == StreamIPI) + X->setIpiTypes(*IpiTypes); + Dumper = std::move(X); + } + Visitors.push_back(std::move(Dumper)); + } + if (DumpRecordBytes) + Visitors.push_back(make_unique(P)); + + // We always need to deserialize and add it to the type database. This is + // true if even if we're not dumping anything, because we could need the + // type database for the purposes of dumping symbols. + TypeVisitorCallbackPipeline Pipeline; + for (const auto &V : Visitors) + Pipeline.addCallbackToPipeline(*V); + + if (DumpRecords || DumpRecordBytes) + RecordScope = llvm::make_unique(P, "Records"); + + Optional I = Types.getFirst(); + while (I) { + std::unique_ptr OneRecordScope; + + if ((DumpRecords || DumpRecordBytes) && !opts::raw::CompactRecords) + OneRecordScope = llvm::make_unique(P, ""); + + auto T = Types.getType(*I); + if (auto EC = codeview::visitTypeRecord(T, *I, Pipeline)) + return EC; + I = Types.getNext(*I); + } + + if (DumpTpiHash) { + DictScope DD(P, "Hash"); + P.printNumber("Number of Hash Buckets", Tpi->getNumHashBuckets()); + P.printNumber("Hash Key Size", Tpi->getHashKeySize()); + P.printList("Values", Tpi->getHashValues()); + + ListScope LHA(P, "Adjusters"); + auto ExpectedST = File.getStringTable(); + if (!ExpectedST) + return ExpectedST.takeError(); + const auto &ST = *ExpectedST; + for (const auto &E : Tpi->getHashAdjusters()) { + DictScope DHA(P); + auto Name = ST.getStringForID(E.first); + if (!Name) + return Name.takeError(); + + P.printString("Type", *Name); + P.printHex("TI", E.second); + } + } + + ListScope L(P, "TypeIndexOffsets"); + for (const auto &IO : Tpi->getTypeIndexOffsets()) { + P.printString(formatv("Index: {0:x}, Offset: {1:N}", IO.Type.getIndex(), + (uint32_t)IO.Offset) + .str()); + } + + P.flush(); + return Error::success(); +} + +Expected +LLVMOutputStyle::initializeTypeDatabase(uint32_t SN) { + auto &TypeCollection = (SN == StreamTPI) ? TpiTypes : IpiTypes; + auto Tpi = + (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream(); + if (!Tpi) + return Tpi.takeError(); + + if (!TypeCollection) { + // Initialize the type collection, even if we're not going to dump it. This + // way if some other part of the dumper decides it wants to use some or all + // of the records for whatever purposes, it can still access them lazily. + auto &Types = Tpi->typeArray(); + uint32_t Count = Tpi->getNumTypeRecords(); + auto Offsets = Tpi->getTypeIndexOffsets(); + TypeCollection = + llvm::make_unique(Types, Count, Offsets); + } + + return *TypeCollection; +} + +Error LLVMOutputStyle::dumpDbiStream() { + bool DumpModules = opts::shared::DumpModules || + opts::shared::DumpModuleSyms || + opts::shared::DumpModuleFiles || + !opts::shared::DumpModuleSubsections.empty(); + if (!opts::raw::DumpHeaders && !DumpModules) + return Error::success(); + if (!File.hasPDBDbiStream()) { + P.printString("DBI Stream not present"); + return Error::success(); + } + + auto DS = File.getPDBDbiStream(); + if (!DS) + return DS.takeError(); + + DictScope D(P, "DBI Stream"); + P.printNumber("Dbi Version", DS->getDbiVersion()); + P.printNumber("Age", DS->getAge()); + P.printBoolean("Incremental Linking", DS->isIncrementallyLinked()); + P.printBoolean("Has CTypes", DS->hasCTypes()); + P.printBoolean("Is Stripped", DS->isStripped()); + P.printObject("Machine Type", DS->getMachineType()); + P.printNumber("Symbol Record Stream Index", DS->getSymRecordStreamIndex()); + P.printNumber("Public Symbol Stream Index", DS->getPublicSymbolStreamIndex()); + P.printNumber("Global Symbol Stream Index", DS->getGlobalSymbolStreamIndex()); + + uint16_t Major = DS->getBuildMajorVersion(); + uint16_t Minor = DS->getBuildMinorVersion(); + P.printVersion("Toolchain Version", Major, Minor); + + std::string DllName; + raw_string_ostream DllStream(DllName); + DllStream << "mspdb" << Major << Minor << ".dll version"; + DllStream.flush(); + P.printVersion(DllName, Major, Minor, DS->getPdbDllVersion()); + + if (DumpModules) { + ListScope L(P, "Modules"); + const DbiModuleList &Modules = DS->modules(); + for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) { + const DbiModuleDescriptor &Modi = Modules.getModuleDescriptor(I); + DictScope DD(P); + P.printString("Name", Modi.getModuleName().str()); + P.printNumber("Debug Stream Index", Modi.getModuleStreamIndex()); + P.printString("Object File Name", Modi.getObjFileName().str()); + P.printNumber("Num Files", Modi.getNumberOfFiles()); + P.printNumber("Source File Name Idx", Modi.getSourceFileNameIndex()); + P.printNumber("Pdb File Name Idx", Modi.getPdbFilePathNameIndex()); + P.printNumber("Line Info Byte Size", Modi.getC11LineInfoByteSize()); + P.printNumber("C13 Line Info Byte Size", Modi.getC13LineInfoByteSize()); + P.printNumber("Symbol Byte Size", Modi.getSymbolDebugInfoByteSize()); + P.printNumber("Type Server Index", Modi.getTypeServerIndex()); + P.printBoolean("Has EC Info", Modi.hasECInfo()); + if (opts::shared::DumpModuleFiles) { + std::string FileListName = to_string(Modules.getSourceFileCount(I)) + + " Contributing Source Files"; + ListScope LL(P, FileListName); + for (auto File : Modules.source_files(I)) + P.printString(File); + } + bool HasModuleDI = (Modi.getModuleStreamIndex() < File.getNumStreams()); + bool ShouldDumpSymbols = + (opts::shared::DumpModuleSyms || opts::raw::DumpSymRecordBytes); + if (HasModuleDI && + (ShouldDumpSymbols || !opts::shared::DumpModuleSubsections.empty())) { + auto ModStreamData = MappedBlockStream::createIndexedStream( + File.getMsfLayout(), File.getMsfBuffer(), + Modi.getModuleStreamIndex(), File.getAllocator()); + + ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData)); + if (auto EC = ModS.reload()) + return EC; + + auto ExpectedTpi = initializeTypeDatabase(StreamTPI); + if (!ExpectedTpi) + return ExpectedTpi.takeError(); + auto &Tpi = *ExpectedTpi; + if (ShouldDumpSymbols) { + + ListScope SS(P, "Symbols"); + codeview::CVSymbolDumper SD(P, Tpi, CodeViewContainer::Pdb, nullptr, + false); + bool HadError = false; + for (auto S : ModS.symbols(&HadError)) { + DictScope LL(P, ""); + if (opts::shared::DumpModuleSyms) { + if (auto EC = SD.dump(S)) { + llvm::consumeError(std::move(EC)); + HadError = true; + break; + } + } + if (opts::raw::DumpSymRecordBytes) + P.printBinaryBlock("Bytes", S.content()); + } + if (HadError) + return make_error( + raw_error_code::corrupt_file, + "DBI stream contained corrupt symbol record"); + } + if (!opts::shared::DumpModuleSubsections.empty()) { + ListScope SS(P, "Subsections"); + auto ExpectedIpi = initializeTypeDatabase(StreamIPI); + if (!ExpectedIpi) + return ExpectedIpi.takeError(); + auto &Ipi = *ExpectedIpi; + auto ExpectedStrings = File.getStringTable(); + if (!ExpectedStrings) + return joinErrors( + make_error(raw_error_code::no_stream, + "Could not get string table!"), + ExpectedStrings.takeError()); + + C13RawVisitor V(P, Tpi, Ipi); + if (auto EC = codeview::visitDebugSubsections( + ModS.subsections(), V, ExpectedStrings->getStringTable())) + return EC; + } + } + } + } + return Error::success(); +} + +Error LLVMOutputStyle::dumpSectionContribs() { + if (!opts::raw::DumpSectionContribs) + return Error::success(); + if (!File.hasPDBDbiStream()) { + P.printString("DBI Stream not present"); + return Error::success(); + } + + auto Dbi = File.getPDBDbiStream(); + if (!Dbi) + return Dbi.takeError(); + + ListScope L(P, "Section Contributions"); + class Visitor : public ISectionContribVisitor { + public: + Visitor(ScopedPrinter &P, DbiStream &DS) : P(P), DS(DS) {} + void visit(const SectionContrib &SC) override { + DictScope D(P, "Contribution"); + P.printNumber("ISect", SC.ISect); + P.printNumber("Off", SC.Off); + P.printNumber("Size", SC.Size); + P.printFlags("Characteristics", SC.Characteristics, + codeview::getImageSectionCharacteristicNames(), + COFF::SectionCharacteristics(0x00F00000)); + { + DictScope DD(P, "Module"); + P.printNumber("Index", SC.Imod); + const DbiModuleList &Modules = DS.modules(); + if (Modules.getModuleCount() > SC.Imod) { + P.printString("Name", + Modules.getModuleDescriptor(SC.Imod).getModuleName()); + } + } + P.printNumber("Data CRC", SC.DataCrc); + P.printNumber("Reloc CRC", SC.RelocCrc); + P.flush(); + } + void visit(const SectionContrib2 &SC) override { + visit(SC.Base); + P.printNumber("ISect Coff", SC.ISectCoff); + P.flush(); + } + + private: + ScopedPrinter &P; + DbiStream &DS; + }; + Visitor V(P, *Dbi); + Dbi->visitSectionContributions(V); + return Error::success(); +} + +Error LLVMOutputStyle::dumpSectionMap() { + if (!opts::raw::DumpSectionMap) + return Error::success(); + if (!File.hasPDBDbiStream()) { + P.printString("DBI Stream not present"); + return Error::success(); + } + + auto Dbi = File.getPDBDbiStream(); + if (!Dbi) + return Dbi.takeError(); + + ListScope L(P, "Section Map"); + for (auto &M : Dbi->getSectionMap()) { + DictScope D(P, "Entry"); + P.printFlags("Flags", M.Flags, getOMFSegMapDescFlagNames()); + P.printNumber("Ovl", M.Ovl); + P.printNumber("Group", M.Group); + P.printNumber("Frame", M.Frame); + P.printNumber("SecName", M.SecName); + P.printNumber("ClassName", M.ClassName); + P.printNumber("Offset", M.Offset); + P.printNumber("SecByteLength", M.SecByteLength); + P.flush(); + } + return Error::success(); +} + +Error LLVMOutputStyle::dumpPublicsStream() { + if (!opts::raw::DumpPublics) + return Error::success(); + if (!File.hasPDBPublicsStream()) { + P.printString("Publics Stream not present"); + return Error::success(); + } + + auto Publics = File.getPDBPublicsStream(); + if (!Publics) + return Publics.takeError(); + DictScope D(P, "Publics Stream"); + + auto Dbi = File.getPDBDbiStream(); + if (!Dbi) + return Dbi.takeError(); + + P.printNumber("Stream number", Dbi->getPublicSymbolStreamIndex()); + P.printNumber("SymHash", Publics->getSymHash()); + P.printNumber("AddrMap", Publics->getAddrMap()); + P.printNumber("Number of buckets", Publics->getNumBuckets()); + P.printList("Hash Buckets", Publics->getHashBuckets()); + P.printList("Address Map", Publics->getAddressMap()); + P.printList("Thunk Map", Publics->getThunkMap()); + P.printList("Section Offsets", Publics->getSectionOffsets(), + printSectionOffset); + ListScope L(P, "Symbols"); + auto ExpectedTypes = initializeTypeDatabase(StreamTPI); + if (!ExpectedTypes) + return ExpectedTypes.takeError(); + auto &Tpi = *ExpectedTypes; + + codeview::CVSymbolDumper SD(P, Tpi, CodeViewContainer::Pdb, nullptr, false); + bool HadError = false; + for (auto S : Publics->getSymbols(&HadError)) { + DictScope DD(P, ""); + + if (auto EC = SD.dump(S)) { + HadError = true; + break; + } + if (opts::raw::DumpSymRecordBytes) + P.printBinaryBlock("Bytes", S.content()); + } + if (HadError) + return make_error( + raw_error_code::corrupt_file, + "Public symbol stream contained corrupt record"); + + return Error::success(); +} + +Error LLVMOutputStyle::dumpSectionHeaders() { + if (!opts::raw::DumpSectionHeaders) + return Error::success(); + if (!File.hasPDBDbiStream()) { + P.printString("DBI Stream not present"); + return Error::success(); + } + + auto Dbi = File.getPDBDbiStream(); + if (!Dbi) + return Dbi.takeError(); + + ListScope D(P, "Section Headers"); + for (const object::coff_section &Section : Dbi->getSectionHeaders()) { + DictScope DD(P, ""); + + // If a name is 8 characters long, there is no NUL character at end. + StringRef Name(Section.Name, strnlen(Section.Name, sizeof(Section.Name))); + P.printString("Name", Name); + P.printNumber("Virtual Size", Section.VirtualSize); + P.printNumber("Virtual Address", Section.VirtualAddress); + P.printNumber("Size of Raw Data", Section.SizeOfRawData); + P.printNumber("File Pointer to Raw Data", Section.PointerToRawData); + P.printNumber("File Pointer to Relocations", Section.PointerToRelocations); + P.printNumber("File Pointer to Linenumbers", Section.PointerToLinenumbers); + P.printNumber("Number of Relocations", Section.NumberOfRelocations); + P.printNumber("Number of Linenumbers", Section.NumberOfLinenumbers); + P.printFlags("Characteristics", Section.Characteristics, + getImageSectionCharacteristicNames()); + } + return Error::success(); +} + +Error LLVMOutputStyle::dumpFpoStream() { + if (!opts::raw::DumpFpo) + return Error::success(); + if (!File.hasPDBDbiStream()) { + P.printString("DBI Stream not present"); + return Error::success(); + } + + auto Dbi = File.getPDBDbiStream(); + if (!Dbi) + return Dbi.takeError(); + + ListScope D(P, "New FPO"); + for (const object::FpoData &Fpo : Dbi->getFpoRecords()) { + DictScope DD(P, ""); + P.printNumber("Offset", Fpo.Offset); + P.printNumber("Size", Fpo.Size); + P.printNumber("Number of locals", Fpo.NumLocals); + P.printNumber("Number of params", Fpo.NumParams); + P.printNumber("Size of Prolog", Fpo.getPrologSize()); + P.printNumber("Number of Saved Registers", Fpo.getNumSavedRegs()); + P.printBoolean("Has SEH", Fpo.hasSEH()); + P.printBoolean("Use BP", Fpo.useBP()); + P.printNumber("Frame Pointer", Fpo.getFP()); + } + return Error::success(); +} + +void LLVMOutputStyle::flush() { P.flush(); } diff --git a/tools/llvm-pdbutil/LLVMOutputStyle.h b/tools/llvm-pdbutil/LLVMOutputStyle.h new file mode 100644 index 000000000000..184dc4e1f44d --- /dev/null +++ b/tools/llvm-pdbutil/LLVMOutputStyle.h @@ -0,0 +1,70 @@ +//===- LLVMOutputStyle.h -------------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMOUTPUTSTYLE_H +#define LLVM_TOOLS_LLVMPDBDUMP_LLVMOUTPUTSTYLE_H + +#include "OutputStyle.h" + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/Support/ScopedPrinter.h" + +#include + +namespace llvm { +class BitVector; + +namespace codeview { +class LazyRandomTypeCollection; +} + +namespace pdb { +class LLVMOutputStyle : public OutputStyle { +public: + LLVMOutputStyle(PDBFile &File); + + Error dump() override; + +private: + Expected + initializeTypeDatabase(uint32_t SN); + + Error dumpFileHeaders(); + Error dumpStreamSummary(); + Error dumpFreePageMap(); + Error dumpBlockRanges(); + Error dumpGlobalsStream(); + Error dumpStreamBytes(); + Error dumpStreamBlocks(); + Error dumpStringTable(); + Error dumpInfoStream(); + Error dumpTpiStream(uint32_t StreamIdx); + Error dumpDbiStream(); + Error dumpSectionContribs(); + Error dumpSectionMap(); + Error dumpPublicsStream(); + Error dumpSectionHeaders(); + Error dumpFpoStream(); + + void dumpBitVector(StringRef Name, const BitVector &V); + + void flush(); + + PDBFile &File; + ScopedPrinter P; + std::unique_ptr TpiTypes; + std::unique_ptr IpiTypes; + SmallVector StreamPurposes; +}; +} +} + +#endif diff --git a/tools/llvm-pdbutil/LinePrinter.cpp b/tools/llvm-pdbutil/LinePrinter.cpp new file mode 100644 index 000000000000..ef56b5fe8e6a --- /dev/null +++ b/tools/llvm-pdbutil/LinePrinter.cpp @@ -0,0 +1,145 @@ +//===- LinePrinter.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "LinePrinter.h" + +#include "llvm-pdbutil.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/PDB/UDTLayout.h" +#include "llvm/Support/Regex.h" + +#include + +using namespace llvm; +using namespace llvm::pdb; + +namespace { +bool IsItemExcluded(llvm::StringRef Item, + std::list &IncludeFilters, + std::list &ExcludeFilters) { + if (Item.empty()) + return false; + + auto match_pred = [Item](llvm::Regex &R) { return R.match(Item); }; + + // Include takes priority over exclude. If the user specified include + // filters, and none of them include this item, them item is gone. + if (!IncludeFilters.empty() && !any_of(IncludeFilters, match_pred)) + return true; + + if (any_of(ExcludeFilters, match_pred)) + return true; + + return false; +} +} + +using namespace llvm; + +LinePrinter::LinePrinter(int Indent, bool UseColor, llvm::raw_ostream &Stream) + : OS(Stream), IndentSpaces(Indent), CurrentIndent(0), UseColor(UseColor) { + SetFilters(ExcludeTypeFilters, opts::pretty::ExcludeTypes.begin(), + opts::pretty::ExcludeTypes.end()); + SetFilters(ExcludeSymbolFilters, opts::pretty::ExcludeSymbols.begin(), + opts::pretty::ExcludeSymbols.end()); + SetFilters(ExcludeCompilandFilters, opts::pretty::ExcludeCompilands.begin(), + opts::pretty::ExcludeCompilands.end()); + + SetFilters(IncludeTypeFilters, opts::pretty::IncludeTypes.begin(), + opts::pretty::IncludeTypes.end()); + SetFilters(IncludeSymbolFilters, opts::pretty::IncludeSymbols.begin(), + opts::pretty::IncludeSymbols.end()); + SetFilters(IncludeCompilandFilters, opts::pretty::IncludeCompilands.begin(), + opts::pretty::IncludeCompilands.end()); +} + +void LinePrinter::Indent() { CurrentIndent += IndentSpaces; } + +void LinePrinter::Unindent() { + CurrentIndent = std::max(0, CurrentIndent - IndentSpaces); +} + +void LinePrinter::NewLine() { + OS << "\n"; + OS.indent(CurrentIndent); +} + +bool LinePrinter::IsClassExcluded(const ClassLayout &Class) { + if (IsTypeExcluded(Class.getName(), Class.getSize())) + return true; + if (Class.deepPaddingSize() < opts::pretty::PaddingThreshold) + return true; + return false; +} + +bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size) { + if (IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters)) + return true; + if (Size < opts::pretty::SizeThreshold) + return true; + return false; +} + +bool LinePrinter::IsSymbolExcluded(llvm::StringRef SymbolName) { + return IsItemExcluded(SymbolName, IncludeSymbolFilters, ExcludeSymbolFilters); +} + +bool LinePrinter::IsCompilandExcluded(llvm::StringRef CompilandName) { + return IsItemExcluded(CompilandName, IncludeCompilandFilters, + ExcludeCompilandFilters); +} + +WithColor::WithColor(LinePrinter &P, PDB_ColorItem C) + : OS(P.OS), UseColor(P.hasColor()) { + if (UseColor) + applyColor(C); +} + +WithColor::~WithColor() { + if (UseColor) + OS.resetColor(); +} + +void WithColor::applyColor(PDB_ColorItem C) { + switch (C) { + case PDB_ColorItem::None: + OS.resetColor(); + return; + case PDB_ColorItem::Comment: + OS.changeColor(raw_ostream::GREEN, false); + return; + case PDB_ColorItem::Address: + OS.changeColor(raw_ostream::YELLOW, /*bold=*/true); + return; + case PDB_ColorItem::Keyword: + OS.changeColor(raw_ostream::MAGENTA, true); + return; + case PDB_ColorItem::Register: + case PDB_ColorItem::Offset: + OS.changeColor(raw_ostream::YELLOW, false); + return; + case PDB_ColorItem::Type: + OS.changeColor(raw_ostream::CYAN, true); + return; + case PDB_ColorItem::Identifier: + OS.changeColor(raw_ostream::CYAN, false); + return; + case PDB_ColorItem::Path: + OS.changeColor(raw_ostream::CYAN, false); + return; + case PDB_ColorItem::Padding: + case PDB_ColorItem::SectionHeader: + OS.changeColor(raw_ostream::RED, true); + return; + case PDB_ColorItem::LiteralValue: + OS.changeColor(raw_ostream::GREEN, true); + return; + } +} diff --git a/tools/llvm-pdbutil/LinePrinter.h b/tools/llvm-pdbutil/LinePrinter.h new file mode 100644 index 000000000000..1a922feb1e62 --- /dev/null +++ b/tools/llvm-pdbutil/LinePrinter.h @@ -0,0 +1,102 @@ +//===- LinePrinter.h ------------------------------------------ *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H +#define LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Regex.h" + +#include + +namespace llvm { +namespace pdb { + +class ClassLayout; + +class LinePrinter { + friend class WithColor; + +public: + LinePrinter(int Indent, bool UseColor, raw_ostream &Stream); + + void Indent(); + void Unindent(); + void NewLine(); + + bool hasColor() const { return UseColor; } + raw_ostream &getStream() { return OS; } + int getIndentLevel() const { return CurrentIndent; } + + bool IsClassExcluded(const ClassLayout &Class); + bool IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size); + bool IsSymbolExcluded(llvm::StringRef SymbolName); + bool IsCompilandExcluded(llvm::StringRef CompilandName); + +private: + template + void SetFilters(std::list &List, Iter Begin, Iter End) { + List.clear(); + for (; Begin != End; ++Begin) + List.emplace_back(StringRef(*Begin)); + } + + raw_ostream &OS; + int IndentSpaces; + int CurrentIndent; + bool UseColor; + + std::list ExcludeCompilandFilters; + std::list ExcludeTypeFilters; + std::list ExcludeSymbolFilters; + + std::list IncludeCompilandFilters; + std::list IncludeTypeFilters; + std::list IncludeSymbolFilters; +}; + +template +inline raw_ostream &operator<<(LinePrinter &Printer, const T &Item) { + Printer.getStream() << Item; + return Printer.getStream(); +} + +enum class PDB_ColorItem { + None, + Address, + Type, + Comment, + Padding, + Keyword, + Offset, + Identifier, + Path, + SectionHeader, + LiteralValue, + Register, +}; + +class WithColor { +public: + WithColor(LinePrinter &P, PDB_ColorItem C); + ~WithColor(); + + raw_ostream &get() { return OS; } + +private: + void applyColor(PDB_ColorItem C); + raw_ostream &OS; + bool UseColor; +}; +} +} + +#endif diff --git a/tools/llvm-pdbutil/OutputStyle.h b/tools/llvm-pdbutil/OutputStyle.h new file mode 100644 index 000000000000..dfefc25a215e --- /dev/null +++ b/tools/llvm-pdbutil/OutputStyle.h @@ -0,0 +1,28 @@ +//===- OutputStyle.h ------------------------------------------ *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_OUTPUTSTYLE_H +#define LLVM_TOOLS_LLVMPDBDUMP_OUTPUTSTYLE_H + +#include "llvm/Support/Error.h" + +namespace llvm { +namespace pdb { +class PDBFile; + +class OutputStyle { +public: + virtual ~OutputStyle() {} + + virtual Error dump() = 0; +}; +} +} + +#endif diff --git a/tools/llvm-pdbutil/PdbYaml.cpp b/tools/llvm-pdbutil/PdbYaml.cpp new file mode 100644 index 000000000000..b4a41fbfdb8f --- /dev/null +++ b/tools/llvm-pdbutil/PdbYaml.cpp @@ -0,0 +1,227 @@ +//===- PdbYAML.cpp -------------------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PdbYaml.h" + +#include "llvm/ADT/StringExtras.h" +#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" +#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" +#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h" +#include "llvm/DebugInfo/CodeView/TypeSerializer.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/DebugInfo/PDB/Native/TpiHashing.h" +#include "llvm/DebugInfo/PDB/PDBExtras.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h" +#include "llvm/ObjectYAML/CodeViewYAMLTypes.h" + +using namespace llvm; +using namespace llvm::pdb; +using namespace llvm::pdb::yaml; +using namespace llvm::yaml; + +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::StringRef) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::NamedStreamMapping) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbDbiModuleInfo) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList) +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::pdb::PdbRaw_FeatureSig) + +namespace llvm { +namespace yaml { + +template <> struct ScalarTraits { + static void output(const llvm::pdb::PDB_UniqueId &S, void *, + llvm::raw_ostream &OS) { + OS << S; + } + + static StringRef input(StringRef Scalar, void *Ctx, + llvm::pdb::PDB_UniqueId &S) { + if (Scalar.size() != 38) + return "GUID strings are 38 characters long"; + if (Scalar[0] != '{' || Scalar[37] != '}') + return "GUID is not enclosed in {}"; + if (Scalar[9] != '-' || Scalar[14] != '-' || Scalar[19] != '-' || + Scalar[24] != '-') + return "GUID sections are not properly delineated with dashes"; + + uint8_t *OutBuffer = S.Guid; + for (auto Iter = Scalar.begin(); Iter != Scalar.end();) { + if (*Iter == '-' || *Iter == '{' || *Iter == '}') { + ++Iter; + continue; + } + uint8_t Value = (llvm::hexDigitValue(*Iter) << 4); + ++Iter; + Value |= llvm::hexDigitValue(*Iter); + ++Iter; + *OutBuffer++ = Value; + } + + return ""; + } + + static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &io, llvm::pdb::PDB_Machine &Value) { + io.enumCase(Value, "Invalid", PDB_Machine::Invalid); + io.enumCase(Value, "Am33", PDB_Machine::Am33); + io.enumCase(Value, "Amd64", PDB_Machine::Amd64); + io.enumCase(Value, "Arm", PDB_Machine::Arm); + io.enumCase(Value, "ArmNT", PDB_Machine::ArmNT); + io.enumCase(Value, "Ebc", PDB_Machine::Ebc); + io.enumCase(Value, "x86", PDB_Machine::x86); + io.enumCase(Value, "Ia64", PDB_Machine::Ia64); + io.enumCase(Value, "M32R", PDB_Machine::M32R); + io.enumCase(Value, "Mips16", PDB_Machine::Mips16); + io.enumCase(Value, "MipsFpu", PDB_Machine::MipsFpu); + io.enumCase(Value, "MipsFpu16", PDB_Machine::MipsFpu16); + io.enumCase(Value, "PowerPCFP", PDB_Machine::PowerPCFP); + io.enumCase(Value, "R4000", PDB_Machine::R4000); + io.enumCase(Value, "SH3", PDB_Machine::SH3); + io.enumCase(Value, "SH3DSP", PDB_Machine::SH3DSP); + io.enumCase(Value, "Thumb", PDB_Machine::Thumb); + io.enumCase(Value, "WceMipsV2", PDB_Machine::WceMipsV2); + } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &io, llvm::pdb::PdbRaw_DbiVer &Value) { + io.enumCase(Value, "V41", llvm::pdb::PdbRaw_DbiVer::PdbDbiVC41); + io.enumCase(Value, "V50", llvm::pdb::PdbRaw_DbiVer::PdbDbiV50); + io.enumCase(Value, "V60", llvm::pdb::PdbRaw_DbiVer::PdbDbiV60); + io.enumCase(Value, "V70", llvm::pdb::PdbRaw_DbiVer::PdbDbiV70); + io.enumCase(Value, "V110", llvm::pdb::PdbRaw_DbiVer::PdbDbiV110); + } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &io, llvm::pdb::PdbRaw_ImplVer &Value) { + io.enumCase(Value, "VC2", llvm::pdb::PdbRaw_ImplVer::PdbImplVC2); + io.enumCase(Value, "VC4", llvm::pdb::PdbRaw_ImplVer::PdbImplVC4); + io.enumCase(Value, "VC41", llvm::pdb::PdbRaw_ImplVer::PdbImplVC41); + io.enumCase(Value, "VC50", llvm::pdb::PdbRaw_ImplVer::PdbImplVC50); + io.enumCase(Value, "VC98", llvm::pdb::PdbRaw_ImplVer::PdbImplVC98); + io.enumCase(Value, "VC70Dep", llvm::pdb::PdbRaw_ImplVer::PdbImplVC70Dep); + io.enumCase(Value, "VC70", llvm::pdb::PdbRaw_ImplVer::PdbImplVC70); + io.enumCase(Value, "VC80", llvm::pdb::PdbRaw_ImplVer::PdbImplVC80); + io.enumCase(Value, "VC110", llvm::pdb::PdbRaw_ImplVer::PdbImplVC110); + io.enumCase(Value, "VC140", llvm::pdb::PdbRaw_ImplVer::PdbImplVC140); + } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &io, llvm::pdb::PdbRaw_TpiVer &Value) { + io.enumCase(Value, "VC40", llvm::pdb::PdbRaw_TpiVer::PdbTpiV40); + io.enumCase(Value, "VC41", llvm::pdb::PdbRaw_TpiVer::PdbTpiV41); + io.enumCase(Value, "VC50", llvm::pdb::PdbRaw_TpiVer::PdbTpiV50); + io.enumCase(Value, "VC70", llvm::pdb::PdbRaw_TpiVer::PdbTpiV70); + io.enumCase(Value, "VC80", llvm::pdb::PdbRaw_TpiVer::PdbTpiV80); + } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &io, PdbRaw_FeatureSig &Features) { + io.enumCase(Features, "MinimalDebugInfo", + PdbRaw_FeatureSig::MinimalDebugInfo); + io.enumCase(Features, "NoTypeMerge", PdbRaw_FeatureSig::NoTypeMerge); + io.enumCase(Features, "VC110", PdbRaw_FeatureSig::VC110); + io.enumCase(Features, "VC140", PdbRaw_FeatureSig::VC140); + } +}; +} +} + +void MappingTraits::mapping(IO &IO, PdbObject &Obj) { + IO.mapOptional("MSF", Obj.Headers); + IO.mapOptional("StreamSizes", Obj.StreamSizes); + IO.mapOptional("StreamMap", Obj.StreamMap); + IO.mapOptional("StringTable", Obj.StringTable); + IO.mapOptional("PdbStream", Obj.PdbStream); + IO.mapOptional("DbiStream", Obj.DbiStream); + IO.mapOptional("TpiStream", Obj.TpiStream); + IO.mapOptional("IpiStream", Obj.IpiStream); +} + +void MappingTraits::mapping(IO &IO, MSFHeaders &Obj) { + IO.mapOptional("SuperBlock", Obj.SuperBlock); + IO.mapOptional("NumDirectoryBlocks", Obj.NumDirectoryBlocks); + IO.mapOptional("DirectoryBlocks", Obj.DirectoryBlocks); + IO.mapOptional("NumStreams", Obj.NumStreams); + IO.mapOptional("FileSize", Obj.FileSize); +} + +void MappingTraits::mapping(IO &IO, msf::SuperBlock &SB) { + if (!IO.outputting()) { + ::memcpy(SB.MagicBytes, msf::Magic, sizeof(msf::Magic)); + } + + using u32 = support::ulittle32_t; + IO.mapOptional("BlockSize", SB.BlockSize, u32(4096U)); + IO.mapOptional("FreeBlockMap", SB.FreeBlockMapBlock, u32(0U)); + IO.mapOptional("NumBlocks", SB.NumBlocks, u32(0U)); + IO.mapOptional("NumDirectoryBytes", SB.NumDirectoryBytes, u32(0U)); + IO.mapOptional("Unknown1", SB.Unknown1, u32(0U)); + IO.mapOptional("BlockMapAddr", SB.BlockMapAddr, u32(0U)); +} + +void MappingTraits::mapping(IO &IO, StreamBlockList &SB) { + IO.mapRequired("Stream", SB.Blocks); +} + +void MappingTraits::mapping(IO &IO, PdbInfoStream &Obj) { + IO.mapOptional("Age", Obj.Age, 1U); + IO.mapOptional("Guid", Obj.Guid); + IO.mapOptional("Signature", Obj.Signature, 0U); + IO.mapOptional("Features", Obj.Features); + IO.mapOptional("Version", Obj.Version, PdbImplVC70); +} + +void MappingTraits::mapping(IO &IO, PdbDbiStream &Obj) { + IO.mapOptional("VerHeader", Obj.VerHeader, PdbDbiV70); + IO.mapOptional("Age", Obj.Age, 1U); + IO.mapOptional("BuildNumber", Obj.BuildNumber, uint16_t(0U)); + IO.mapOptional("PdbDllVersion", Obj.PdbDllVersion, 0U); + IO.mapOptional("PdbDllRbld", Obj.PdbDllRbld, uint16_t(0U)); + IO.mapOptional("Flags", Obj.Flags, uint16_t(1U)); + IO.mapOptional("MachineType", Obj.MachineType, PDB_Machine::x86); + IO.mapOptional("Modules", Obj.ModInfos); +} + +void MappingTraits::mapping(IO &IO, + pdb::yaml::PdbTpiStream &Obj) { + IO.mapOptional("Version", Obj.Version, PdbTpiV80); + IO.mapRequired("Records", Obj.Records); +} + +void MappingTraits::mapping(IO &IO, + NamedStreamMapping &Obj) { + IO.mapRequired("Name", Obj.StreamName); + IO.mapRequired("StreamNum", Obj.StreamNumber); +} + +void MappingTraits::mapping(IO &IO, PdbModiStream &Obj) { + IO.mapOptional("Signature", Obj.Signature, 4U); + IO.mapRequired("Records", Obj.Symbols); +} + +void MappingTraits::mapping(IO &IO, PdbDbiModuleInfo &Obj) { + IO.mapRequired("Module", Obj.Mod); + IO.mapOptional("ObjFile", Obj.Obj, Obj.Mod); + IO.mapOptional("SourceFiles", Obj.SourceFiles); + IO.mapOptional("Subsections", Obj.Subsections); + IO.mapOptional("Modi", Obj.Modi); +} diff --git a/tools/llvm-pdbutil/PdbYaml.h b/tools/llvm-pdbutil/PdbYaml.h new file mode 100644 index 000000000000..62ed608916fc --- /dev/null +++ b/tools/llvm-pdbutil/PdbYaml.h @@ -0,0 +1,125 @@ +//===- PdbYAML.h ---------------------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H +#define LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H + +#include "OutputStyle.h" + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h" +#include "llvm/ObjectYAML/CodeViewYAMLSymbols.h" +#include "llvm/ObjectYAML/CodeViewYAMLTypes.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/YAMLTraits.h" + +#include + +namespace llvm { +namespace codeview { +class DebugStringTableSubsection; +} +namespace pdb { + +namespace yaml { +struct SerializationContext; + +struct MSFHeaders { + msf::SuperBlock SuperBlock; + uint32_t NumDirectoryBlocks = 0; + std::vector DirectoryBlocks; + uint32_t NumStreams = 0; + uint32_t FileSize = 0; +}; + +struct StreamBlockList { + std::vector Blocks; +}; + +struct NamedStreamMapping { + StringRef StreamName; + uint32_t StreamNumber; +}; + +struct PdbInfoStream { + PdbRaw_ImplVer Version = PdbImplVC70; + uint32_t Signature = 0; + uint32_t Age = 1; + PDB_UniqueId Guid; + std::vector Features; + std::vector NamedStreams; +}; + +struct PdbModiStream { + uint32_t Signature; + std::vector Symbols; +}; + +struct PdbDbiModuleInfo { + StringRef Obj; + StringRef Mod; + std::vector SourceFiles; + std::vector Subsections; + Optional Modi; +}; + +struct PdbDbiStream { + PdbRaw_DbiVer VerHeader = PdbDbiV70; + uint32_t Age = 1; + uint16_t BuildNumber = 0; + uint32_t PdbDllVersion = 0; + uint16_t PdbDllRbld = 0; + uint16_t Flags = 1; + PDB_Machine MachineType = PDB_Machine::x86; + + std::vector ModInfos; +}; + +struct PdbTpiStream { + PdbRaw_TpiVer Version = PdbTpiV80; + std::vector Records; +}; + +struct PdbObject { + explicit PdbObject(BumpPtrAllocator &Allocator) : Allocator(Allocator) {} + + Optional Headers; + Optional> StreamSizes; + Optional> StreamMap; + Optional PdbStream; + Optional DbiStream; + Optional TpiStream; + Optional IpiStream; + + Optional> StringTable; + + BumpPtrAllocator &Allocator; +}; +} +} +} + +LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbObject) +LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::MSFHeaders) +LLVM_YAML_DECLARE_MAPPING_TRAITS(msf::SuperBlock) +LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::StreamBlockList) +LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbInfoStream) +LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbDbiStream) +LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbTpiStream) +LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::NamedStreamMapping) +LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbModiStream) +LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbDbiModuleInfo) + +#endif // LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H diff --git a/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp b/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp new file mode 100644 index 000000000000..fcda312e65e9 --- /dev/null +++ b/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp @@ -0,0 +1,94 @@ +//===- PrettyBuiltinDumper.cpp ---------------------------------- *- C++ *-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PrettyBuiltinDumper.h" +#include "LinePrinter.h" +#include "llvm-pdbutil.h" + +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" + +using namespace llvm; +using namespace llvm::pdb; + +BuiltinDumper::BuiltinDumper(LinePrinter &P) + : PDBSymDumper(false), Printer(P) {} + +void BuiltinDumper::start(const PDBSymbolTypeBuiltin &Symbol) { + if (Symbol.isConstType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; + if (Symbol.isVolatileType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; + WithColor(Printer, PDB_ColorItem::Type).get() << getTypeName(Symbol); +} + +StringRef BuiltinDumper::getTypeName(const PDBSymbolTypeBuiltin &Symbol) { + PDB_BuiltinType Type = Symbol.getBuiltinType(); + switch (Type) { + case PDB_BuiltinType::Float: + if (Symbol.getLength() == 4) + return "float"; + return "double"; + case PDB_BuiltinType::UInt: + switch (Symbol.getLength()) { + case 8: + return "unsigned __int64"; + case 4: + return "unsigned int"; + case 2: + return "unsigned short"; + case 1: + return "unsigned char"; + default: + return "unsigned"; + } + case PDB_BuiltinType::Int: + switch (Symbol.getLength()) { + case 8: + return "__int64"; + case 4: + return "int"; + case 2: + return "short"; + case 1: + return "char"; + default: + return "int"; + } + case PDB_BuiltinType::Char: + return "char"; + case PDB_BuiltinType::WCharT: + return "wchar_t"; + case PDB_BuiltinType::Void: + return "void"; + case PDB_BuiltinType::Long: + return "long"; + case PDB_BuiltinType::ULong: + return "unsigned long"; + case PDB_BuiltinType::Bool: + return "bool"; + case PDB_BuiltinType::Currency: + return "CURRENCY"; + case PDB_BuiltinType::Date: + return "DATE"; + case PDB_BuiltinType::Variant: + return "VARIANT"; + case PDB_BuiltinType::Complex: + return "complex"; + case PDB_BuiltinType::Bitfield: + return "bitfield"; + case PDB_BuiltinType::BSTR: + return "BSTR"; + case PDB_BuiltinType::HResult: + return "HRESULT"; + case PDB_BuiltinType::BCD: + return "HRESULT"; + default: + return "void"; + } +} diff --git a/tools/llvm-pdbutil/PrettyBuiltinDumper.h b/tools/llvm-pdbutil/PrettyBuiltinDumper.h new file mode 100644 index 000000000000..fb6b0b172e6e --- /dev/null +++ b/tools/llvm-pdbutil/PrettyBuiltinDumper.h @@ -0,0 +1,35 @@ +//===- PrettyBuiltinDumper.h ---------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYBUILTINDUMPER_H +#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYBUILTINDUMPER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/PDB/PDBSymDumper.h" + +namespace llvm { +namespace pdb { + +class LinePrinter; + +class BuiltinDumper : public PDBSymDumper { +public: + BuiltinDumper(LinePrinter &P); + + void start(const PDBSymbolTypeBuiltin &Symbol); + +private: + StringRef getTypeName(const PDBSymbolTypeBuiltin &Symbol); + + LinePrinter &Printer; +}; +} +} + +#endif diff --git a/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp b/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp new file mode 100644 index 000000000000..651cb8b7649e --- /dev/null +++ b/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp @@ -0,0 +1,108 @@ +//===- PrettyClassDefinitionDumper.cpp --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PrettyClassDefinitionDumper.h" + +#include "LinePrinter.h" +#include "PrettyClassLayoutGraphicalDumper.h" +#include "llvm-pdbutil.h" + +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" +#include "llvm/DebugInfo/PDB/UDTLayout.h" + +#include "llvm/Support/Format.h" + +using namespace llvm; +using namespace llvm::pdb; + +ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P) + : PDBSymDumper(true), Printer(P) {} + +void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) { + assert(opts::pretty::ClassFormat != + opts::pretty::ClassDefinitionFormat::None); + + ClassLayout Layout(Class); + start(Layout); +} + +void ClassDefinitionDumper::start(const ClassLayout &Layout) { + prettyPrintClassIntro(Layout); + + PrettyClassLayoutGraphicalDumper Dumper(Printer, 1, 0); + DumpedAnything |= Dumper.start(Layout); + + prettyPrintClassOutro(Layout); +} + +void ClassDefinitionDumper::prettyPrintClassIntro(const ClassLayout &Layout) { + DumpedAnything = false; + Printer.NewLine(); + + uint32_t Size = Layout.getSize(); + const PDBSymbolTypeUDT &Class = Layout.getClass(); + + WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " "; + WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName(); + WithColor(Printer, PDB_ColorItem::Comment).get() << " [sizeof = " << Size + << "]"; + uint32_t BaseCount = Layout.bases().size(); + if (BaseCount > 0) { + Printer.Indent(); + char NextSeparator = ':'; + for (auto BC : Layout.bases()) { + const auto &Base = BC->getBase(); + if (Base.isIndirectVirtualBaseClass()) + continue; + + Printer.NewLine(); + Printer << NextSeparator << " "; + WithColor(Printer, PDB_ColorItem::Keyword).get() << Base.getAccess(); + if (BC->isVirtualBase()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual"; + + WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base.getName(); + NextSeparator = ','; + } + + Printer.Unindent(); + } + + Printer << " {"; + Printer.Indent(); +} + +void ClassDefinitionDumper::prettyPrintClassOutro(const ClassLayout &Layout) { + Printer.Unindent(); + if (DumpedAnything) + Printer.NewLine(); + Printer << "}"; + Printer.NewLine(); + if (Layout.deepPaddingSize() > 0) { + APFloat Pct(100.0 * (double)Layout.deepPaddingSize() / + (double)Layout.getSize()); + SmallString<8> PctStr; + Pct.toString(PctStr, 4); + WithColor(Printer, PDB_ColorItem::Padding).get() + << "Total padding " << Layout.deepPaddingSize() << " bytes (" << PctStr + << "% of class size)"; + Printer.NewLine(); + APFloat Pct2(100.0 * (double)Layout.immediatePadding() / + (double)Layout.getSize()); + PctStr.clear(); + Pct2.toString(PctStr, 4); + WithColor(Printer, PDB_ColorItem::Padding).get() + << "Immediate padding " << Layout.immediatePadding() << " bytes (" + << PctStr << "% of class size)"; + Printer.NewLine(); + } +} diff --git a/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h b/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h new file mode 100644 index 000000000000..6569a1d304f6 --- /dev/null +++ b/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h @@ -0,0 +1,47 @@ +//===- PrettyClassDefinitionDumper.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSDEFINITIONDUMPER_H +#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSDEFINITIONDUMPER_H + +#include "llvm/ADT/BitVector.h" + +#include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" + +#include +#include +#include + +namespace llvm { +class BitVector; + +namespace pdb { + +class ClassLayout; +class LinePrinter; + +class ClassDefinitionDumper : public PDBSymDumper { +public: + ClassDefinitionDumper(LinePrinter &P); + + void start(const PDBSymbolTypeUDT &Class); + void start(const ClassLayout &Class); + +private: + void prettyPrintClassIntro(const ClassLayout &Class); + void prettyPrintClassOutro(const ClassLayout &Class); + + LinePrinter &Printer; + bool DumpedAnything = false; +}; +} +} +#endif diff --git a/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp b/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp new file mode 100644 index 000000000000..54e33683f552 --- /dev/null +++ b/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp @@ -0,0 +1,216 @@ +//===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PrettyClassLayoutGraphicalDumper.h" + +#include "LinePrinter.h" +#include "PrettyClassDefinitionDumper.h" +#include "PrettyEnumDumper.h" +#include "PrettyFunctionDumper.h" +#include "PrettyTypedefDumper.h" +#include "PrettyVariableDumper.h" +#include "PrettyVariableDumper.h" +#include "llvm-pdbutil.h" + +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" +#include "llvm/DebugInfo/PDB/UDTLayout.h" +#include "llvm/Support/Format.h" + +using namespace llvm; +using namespace llvm::pdb; + +PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper( + LinePrinter &P, uint32_t RecurseLevel, uint32_t InitialOffset) + : PDBSymDumper(true), Printer(P), RecursionLevel(RecurseLevel), + ClassOffsetZero(InitialOffset), CurrentAbsoluteOffset(InitialOffset) {} + +bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) { + + if (RecursionLevel == 1 && + opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::All) { + for (auto &Other : Layout.other_items()) + Other->dump(*this); + for (auto &Func : Layout.funcs()) + Func->dump(*this); + } + + const BitVector &UseMap = Layout.usedBytes(); + int NextPaddingByte = UseMap.find_first_unset(); + + for (auto &Item : Layout.layout_items()) { + // Calculate the absolute offset of the first byte of the next field. + uint32_t RelativeOffset = Item->getOffsetInParent(); + CurrentAbsoluteOffset = ClassOffsetZero + RelativeOffset; + + // Since there is storage there, it should be set! However, this might + // be an empty base, in which case it could extend outside the bounds of + // the parent class. + if (RelativeOffset < UseMap.size() && (Item->getSize() > 0)) { + assert(UseMap.test(RelativeOffset)); + + // If there is any remaining padding in this class, and the offset of the + // new item is after the padding, then we must have just jumped over some + // padding. Print a padding row and then look for where the next block + // of padding begins. + if ((NextPaddingByte >= 0) && + (RelativeOffset > uint32_t(NextPaddingByte))) { + printPaddingRow(RelativeOffset - NextPaddingByte); + NextPaddingByte = UseMap.find_next_unset(RelativeOffset); + } + } + + CurrentItem = Item; + if (Item->isVBPtr()) { + VTableLayoutItem &Layout = static_cast(*CurrentItem); + + VariableDumper VarDumper(Printer); + VarDumper.startVbptr(CurrentAbsoluteOffset, Layout.getSize()); + } else { + if (auto Sym = Item->getSymbol()) + Sym->dump(*this); + } + + if (Item->getLayoutSize() > 0) { + uint32_t Prev = RelativeOffset + Item->getLayoutSize() - 1; + if (Prev < UseMap.size()) + NextPaddingByte = UseMap.find_next_unset(Prev); + } + } + + auto TailPadding = Layout.tailPadding(); + if (TailPadding > 0) { + if (TailPadding != 1 || Layout.getSize() != 1) { + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::Padding).get() + << " (" << TailPadding << " bytes)"; + DumpedAnything = true; + } + } + + return DumpedAnything; +} + +void PrettyClassLayoutGraphicalDumper::printPaddingRow(uint32_t Amount) { + if (Amount == 0) + return; + + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::Padding).get() << " (" << Amount + << " bytes)"; + DumpedAnything = true; +} + +void PrettyClassLayoutGraphicalDumper::dump( + const PDBSymbolTypeBaseClass &Symbol) { + assert(CurrentItem != nullptr); + + Printer.NewLine(); + BaseClassLayout &Layout = static_cast(*CurrentItem); + + std::string Label = "base"; + if (Layout.isVirtualBase()) { + Label.insert(Label.begin(), 'v'); + if (Layout.getBase().isIndirectVirtualBaseClass()) + Label.insert(Label.begin(), 'i'); + } + Printer << Label << " "; + + uint32_t Size = Layout.isEmptyBase() ? 1 : Layout.getLayoutSize(); + + WithColor(Printer, PDB_ColorItem::Offset).get() + << "+" << format_hex(CurrentAbsoluteOffset, 4) << " [sizeof=" << Size + << "] "; + + WithColor(Printer, PDB_ColorItem::Identifier).get() << Layout.getName(); + + if (shouldRecurse()) { + Printer.Indent(); + uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent(); + PrettyClassLayoutGraphicalDumper BaseDumper(Printer, RecursionLevel + 1, + ChildOffsetZero); + DumpedAnything |= BaseDumper.start(Layout); + Printer.Unindent(); + } + + DumpedAnything = true; +} + +bool PrettyClassLayoutGraphicalDumper::shouldRecurse() const { + uint32_t Limit = opts::pretty::ClassRecursionDepth; + if (Limit == 0) + return true; + return RecursionLevel < Limit; +} + +void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) { + assert(CurrentItem != nullptr); + + DataMemberLayoutItem &Layout = + static_cast(*CurrentItem); + + VariableDumper VarDumper(Printer); + VarDumper.start(Symbol, ClassOffsetZero); + + if (Layout.hasUDTLayout() && shouldRecurse()) { + uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent(); + Printer.Indent(); + PrettyClassLayoutGraphicalDumper TypeDumper(Printer, RecursionLevel + 1, + ChildOffsetZero); + TypeDumper.start(Layout.getUDTLayout()); + Printer.Unindent(); + } + + DumpedAnything = true; +} + +void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeVTable &Symbol) { + assert(CurrentItem != nullptr); + + VariableDumper VarDumper(Printer); + VarDumper.start(Symbol, ClassOffsetZero); + + DumpedAnything = true; +} + +void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeEnum &Symbol) { + DumpedAnything = true; + Printer.NewLine(); + EnumDumper Dumper(Printer); + Dumper.start(Symbol); +} + +void PrettyClassLayoutGraphicalDumper::dump( + const PDBSymbolTypeTypedef &Symbol) { + DumpedAnything = true; + Printer.NewLine(); + TypedefDumper Dumper(Printer); + Dumper.start(Symbol); +} + +void PrettyClassLayoutGraphicalDumper::dump( + const PDBSymbolTypeBuiltin &Symbol) {} + +void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeUDT &Symbol) {} + +void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolFunc &Symbol) { + if (Printer.IsSymbolExcluded(Symbol.getName())) + return; + if (Symbol.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated) + return; + if (Symbol.getLength() == 0 && !Symbol.isPureVirtual() && + !Symbol.isIntroVirtualFunction()) + return; + + DumpedAnything = true; + Printer.NewLine(); + FunctionDumper Dumper(Printer); + Dumper.start(Symbol, FunctionDumper::PointerType::None); +} diff --git a/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h b/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h new file mode 100644 index 000000000000..f83f1a6c1b34 --- /dev/null +++ b/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h @@ -0,0 +1,58 @@ +//===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSLAYOUTGRAPHICALDUMPER_H +#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSLAYOUTGRAPHICALDUMPER_H + +#include "llvm/ADT/BitVector.h" + +#include "llvm/DebugInfo/PDB/PDBSymDumper.h" + +namespace llvm { + +namespace pdb { + +class UDTLayoutBase; +class LayoutItemBase; +class LinePrinter; + +class PrettyClassLayoutGraphicalDumper : public PDBSymDumper { +public: + PrettyClassLayoutGraphicalDumper(LinePrinter &P, uint32_t RecurseLevel, + uint32_t InitialOffset); + + bool start(const UDTLayoutBase &Layout); + + // Layout based symbol types. + void dump(const PDBSymbolTypeBaseClass &Symbol) override; + void dump(const PDBSymbolData &Symbol) override; + void dump(const PDBSymbolTypeVTable &Symbol) override; + + // Non layout-based symbol types. + void dump(const PDBSymbolTypeEnum &Symbol) override; + void dump(const PDBSymbolFunc &Symbol) override; + void dump(const PDBSymbolTypeTypedef &Symbol) override; + void dump(const PDBSymbolTypeUDT &Symbol) override; + void dump(const PDBSymbolTypeBuiltin &Symbol) override; + +private: + bool shouldRecurse() const; + void printPaddingRow(uint32_t Amount); + + LinePrinter &Printer; + + LayoutItemBase *CurrentItem = nullptr; + uint32_t RecursionLevel = 0; + uint32_t ClassOffsetZero = 0; + uint32_t CurrentAbsoluteOffset = 0; + bool DumpedAnything = false; +}; +} +} +#endif diff --git a/tools/llvm-pdbutil/PrettyCompilandDumper.cpp b/tools/llvm-pdbutil/PrettyCompilandDumper.cpp new file mode 100644 index 000000000000..65e8badbc99a --- /dev/null +++ b/tools/llvm-pdbutil/PrettyCompilandDumper.cpp @@ -0,0 +1,207 @@ +//===- PrettyCompilandDumper.cpp - llvm-pdbutil compiland dumper -*- C++ *-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PrettyCompilandDumper.h" + +#include "LinePrinter.h" +#include "PrettyFunctionDumper.h" +#include "llvm-pdbutil.h" + +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/IPDBSourceFile.h" +#include "llvm/DebugInfo/PDB/PDBExtras.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h" +#include "llvm/DebugInfo/PDB/PDBSymbolLabel.h" +#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" +#include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" + +#include + +using namespace llvm; +using namespace llvm::pdb; + +CompilandDumper::CompilandDumper(LinePrinter &P) + : PDBSymDumper(true), Printer(P) {} + +void CompilandDumper::dump(const PDBSymbolCompilandDetails &Symbol) {} + +void CompilandDumper::dump(const PDBSymbolCompilandEnv &Symbol) {} + +void CompilandDumper::start(const PDBSymbolCompiland &Symbol, + CompilandDumpFlags opts) { + std::string FullName = Symbol.getName(); + if (Printer.IsCompilandExcluded(FullName)) + return; + + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::Path).get() << FullName; + + if (opts & Flags::Lines) { + const IPDBSession &Session = Symbol.getSession(); + auto Files = Session.getSourceFilesForCompiland(Symbol); + Printer.Indent(); + while (auto File = Files->getNext()) { + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::Path).get() << File->getFileName(); + + auto Lines = Session.findLineNumbers(Symbol, *File); + Printer.Indent(); + while (auto Line = Lines->getNext()) { + Printer.NewLine(); + uint32_t LineStart = Line->getLineNumber(); + uint32_t LineEnd = Line->getLineNumberEnd(); + + Printer << "Line "; + PDB_ColorItem StatementColor = Line->isStatement() + ? PDB_ColorItem::Keyword + : PDB_ColorItem::LiteralValue; + WithColor(Printer, StatementColor).get() << LineStart; + if (LineStart != LineEnd) + WithColor(Printer, StatementColor).get() << " - " << LineEnd; + + uint32_t ColumnStart = Line->getColumnNumber(); + uint32_t ColumnEnd = Line->getColumnNumberEnd(); + if (ColumnStart != 0 || ColumnEnd != 0) { + Printer << ", Column: "; + WithColor(Printer, StatementColor).get() << ColumnStart; + if (ColumnEnd != ColumnStart) + WithColor(Printer, StatementColor).get() << " - " << ColumnEnd; + } + + Printer << ", Address: "; + if (Line->getLength() > 0) { + uint64_t AddrStart = Line->getVirtualAddress(); + uint64_t AddrEnd = AddrStart + Line->getLength() - 1; + WithColor(Printer, PDB_ColorItem::Address).get() + << "[" << format_hex(AddrStart, 10) << " - " + << format_hex(AddrEnd, 10) << "]"; + Printer << " (" << Line->getLength() << " bytes)"; + } else { + uint64_t AddrStart = Line->getVirtualAddress(); + WithColor(Printer, PDB_ColorItem::Address).get() + << "[" << format_hex(AddrStart, 10) << "] "; + Printer << "(0 bytes)"; + } + } + Printer.Unindent(); + } + Printer.Unindent(); + } + + if (opts & Flags::Children) { + auto ChildrenEnum = Symbol.findAllChildren(); + Printer.Indent(); + while (auto Child = ChildrenEnum->getNext()) + Child->dump(*this); + Printer.Unindent(); + } +} + +void CompilandDumper::dump(const PDBSymbolData &Symbol) { + if (!shouldDumpSymLevel(opts::pretty::SymLevel::Data)) + return; + if (Printer.IsSymbolExcluded(Symbol.getName())) + return; + + Printer.NewLine(); + + switch (auto LocType = Symbol.getLocationType()) { + case PDB_LocType::Static: + Printer << "data: "; + WithColor(Printer, PDB_ColorItem::Address).get() + << "[" << format_hex(Symbol.getVirtualAddress(), 10) << "]"; + + WithColor(Printer, PDB_ColorItem::Comment).get() + << " [sizeof = " << getTypeLength(Symbol) << "]"; + + break; + case PDB_LocType::Constant: + Printer << "constant: "; + WithColor(Printer, PDB_ColorItem::LiteralValue).get() + << "[" << Symbol.getValue() << "]"; + WithColor(Printer, PDB_ColorItem::Comment).get() + << " [sizeof = " << getTypeLength(Symbol) << "]"; + break; + default: + Printer << "data(unexpected type=" << LocType << ")"; + } + + Printer << " "; + WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); +} + +void CompilandDumper::dump(const PDBSymbolFunc &Symbol) { + if (!shouldDumpSymLevel(opts::pretty::SymLevel::Functions)) + return; + if (Symbol.getLength() == 0) + return; + if (Printer.IsSymbolExcluded(Symbol.getName())) + return; + + Printer.NewLine(); + FunctionDumper Dumper(Printer); + Dumper.start(Symbol, FunctionDumper::PointerType::None); +} + +void CompilandDumper::dump(const PDBSymbolLabel &Symbol) { + if (Printer.IsSymbolExcluded(Symbol.getName())) + return; + + Printer.NewLine(); + Printer << "label "; + WithColor(Printer, PDB_ColorItem::Address).get() + << "[" << format_hex(Symbol.getVirtualAddress(), 10) << "] "; + WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); +} + +void CompilandDumper::dump(const PDBSymbolThunk &Symbol) { + if (!shouldDumpSymLevel(opts::pretty::SymLevel::Thunks)) + return; + if (Printer.IsSymbolExcluded(Symbol.getName())) + return; + + Printer.NewLine(); + Printer << "thunk "; + codeview::ThunkOrdinal Ordinal = Symbol.getThunkOrdinal(); + uint64_t VA = Symbol.getVirtualAddress(); + if (Ordinal == codeview::ThunkOrdinal::TrampIncremental) { + uint64_t Target = Symbol.getTargetVirtualAddress(); + WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(VA, 10); + Printer << " -> "; + WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Target, 10); + } else { + WithColor(Printer, PDB_ColorItem::Address).get() + << "[" << format_hex(VA, 10) << " - " + << format_hex(VA + Symbol.getLength(), 10) << "]"; + } + Printer << " ("; + WithColor(Printer, PDB_ColorItem::Register).get() << Ordinal; + Printer << ") "; + std::string Name = Symbol.getName(); + if (!Name.empty()) + WithColor(Printer, PDB_ColorItem::Identifier).get() << Name; +} + +void CompilandDumper::dump(const PDBSymbolTypeTypedef &Symbol) {} + +void CompilandDumper::dump(const PDBSymbolUnknown &Symbol) { + Printer.NewLine(); + Printer << "unknown (" << Symbol.getSymTag() << ")"; +} diff --git a/tools/llvm-pdbutil/PrettyCompilandDumper.h b/tools/llvm-pdbutil/PrettyCompilandDumper.h new file mode 100644 index 000000000000..cae196e9d134 --- /dev/null +++ b/tools/llvm-pdbutil/PrettyCompilandDumper.h @@ -0,0 +1,44 @@ +//===- PrettyCompilandDumper.h - llvm-pdbutil compiland dumper -*- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYCOMPILANDDUMPER_H +#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCOMPILANDDUMPER_H + +#include "llvm/DebugInfo/PDB/PDBSymDumper.h" + +namespace llvm { +namespace pdb { + +class LinePrinter; + +typedef int CompilandDumpFlags; +class CompilandDumper : public PDBSymDumper { +public: + enum Flags { None = 0x0, Children = 0x1, Symbols = 0x2, Lines = 0x4 }; + + CompilandDumper(LinePrinter &P); + + void start(const PDBSymbolCompiland &Symbol, CompilandDumpFlags flags); + + void dump(const PDBSymbolCompilandDetails &Symbol) override; + void dump(const PDBSymbolCompilandEnv &Symbol) override; + void dump(const PDBSymbolData &Symbol) override; + void dump(const PDBSymbolFunc &Symbol) override; + void dump(const PDBSymbolLabel &Symbol) override; + void dump(const PDBSymbolThunk &Symbol) override; + void dump(const PDBSymbolTypeTypedef &Symbol) override; + void dump(const PDBSymbolUnknown &Symbol) override; + +private: + LinePrinter &Printer; +}; +} +} + +#endif diff --git a/tools/llvm-pdbutil/PrettyEnumDumper.cpp b/tools/llvm-pdbutil/PrettyEnumDumper.cpp new file mode 100644 index 000000000000..7aff5b93d986 --- /dev/null +++ b/tools/llvm-pdbutil/PrettyEnumDumper.cpp @@ -0,0 +1,53 @@ +//===- PrettyEnumDumper.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PrettyEnumDumper.h" + +#include "LinePrinter.h" +#include "PrettyBuiltinDumper.h" +#include "llvm-pdbutil.h" + +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" + +using namespace llvm; +using namespace llvm::pdb; + +EnumDumper::EnumDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {} + +void EnumDumper::start(const PDBSymbolTypeEnum &Symbol) { + WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum "; + WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); + if (!opts::pretty::NoEnumDefs) { + auto BuiltinType = Symbol.getUnderlyingType(); + if (BuiltinType->getBuiltinType() != PDB_BuiltinType::Int || + BuiltinType->getLength() != 4) { + Printer << " : "; + BuiltinDumper Dumper(Printer); + Dumper.start(*BuiltinType); + } + Printer << " {"; + Printer.Indent(); + auto EnumValues = Symbol.findAllChildren(); + while (auto EnumValue = EnumValues->getNext()) { + if (EnumValue->getDataKind() != PDB_DataKind::Constant) + continue; + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::Identifier).get() + << EnumValue->getName(); + Printer << " = "; + WithColor(Printer, PDB_ColorItem::LiteralValue).get() + << EnumValue->getValue(); + } + Printer.Unindent(); + Printer.NewLine(); + Printer << "}"; + } +} diff --git a/tools/llvm-pdbutil/PrettyEnumDumper.h b/tools/llvm-pdbutil/PrettyEnumDumper.h new file mode 100644 index 000000000000..c6e65a6d1772 --- /dev/null +++ b/tools/llvm-pdbutil/PrettyEnumDumper.h @@ -0,0 +1,31 @@ +//===- PrettyEnumDumper.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYENUMDUMPER_H +#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYENUMDUMPER_H + +#include "llvm/DebugInfo/PDB/PDBSymDumper.h" + +namespace llvm { +namespace pdb { + +class LinePrinter; + +class EnumDumper : public PDBSymDumper { +public: + EnumDumper(LinePrinter &P); + + void start(const PDBSymbolTypeEnum &Symbol); + +private: + LinePrinter &Printer; +}; +} +} +#endif diff --git a/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp b/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp new file mode 100644 index 000000000000..fc40d90cee96 --- /dev/null +++ b/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp @@ -0,0 +1,41 @@ +//===- PrettyExternalSymbolDumper.cpp -------------------------- *- C++ *-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PrettyExternalSymbolDumper.h" +#include "LinePrinter.h" + +#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" +#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h" +#include "llvm/Support/Format.h" + +using namespace llvm; +using namespace llvm::pdb; + +ExternalSymbolDumper::ExternalSymbolDumper(LinePrinter &P) + : PDBSymDumper(true), Printer(P) {} + +void ExternalSymbolDumper::start(const PDBSymbolExe &Symbol) { + auto Vars = Symbol.findAllChildren(); + while (auto Var = Vars->getNext()) + Var->dump(*this); +} + +void ExternalSymbolDumper::dump(const PDBSymbolPublicSymbol &Symbol) { + std::string LinkageName = Symbol.getName(); + if (Printer.IsSymbolExcluded(LinkageName)) + return; + + Printer.NewLine(); + uint64_t Addr = Symbol.getVirtualAddress(); + + Printer << "["; + WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Addr, 10); + Printer << "] "; + WithColor(Printer, PDB_ColorItem::Identifier).get() << LinkageName; +} diff --git a/tools/llvm-pdbutil/PrettyExternalSymbolDumper.h b/tools/llvm-pdbutil/PrettyExternalSymbolDumper.h new file mode 100644 index 000000000000..6a009862ddd4 --- /dev/null +++ b/tools/llvm-pdbutil/PrettyExternalSymbolDumper.h @@ -0,0 +1,34 @@ +//===- PrettyExternalSymbolDumper.h --------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYEXTERNALSYMBOLDUMPER_H +#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYEXTERNALSYMBOLDUMPER_H + +#include "llvm/DebugInfo/PDB/PDBSymDumper.h" + +namespace llvm { +namespace pdb { + +class LinePrinter; + +class ExternalSymbolDumper : public PDBSymDumper { +public: + ExternalSymbolDumper(LinePrinter &P); + + void start(const PDBSymbolExe &Symbol); + + void dump(const PDBSymbolPublicSymbol &Symbol) override; + +private: + LinePrinter &Printer; +}; +} +} + +#endif diff --git a/tools/llvm-pdbutil/PrettyFunctionDumper.cpp b/tools/llvm-pdbutil/PrettyFunctionDumper.cpp new file mode 100644 index 000000000000..06d72410359f --- /dev/null +++ b/tools/llvm-pdbutil/PrettyFunctionDumper.cpp @@ -0,0 +1,259 @@ +//===- PrettyFunctionDumper.cpp --------------------------------- *- C++ *-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PrettyFunctionDumper.h" +#include "LinePrinter.h" +#include "PrettyBuiltinDumper.h" +#include "llvm-pdbutil.h" + +#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/PDBExtras.h" +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/FormatVariadic.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +namespace { +template +void dumpClassParentWithScopeOperator(const T &Symbol, LinePrinter &Printer, + FunctionDumper &Dumper) { + uint32_t ClassParentId = Symbol.getClassParentId(); + auto ClassParent = + Symbol.getSession().template getConcreteSymbolById( + ClassParentId); + if (!ClassParent) + return; + + WithColor(Printer, PDB_ColorItem::Type).get() << ClassParent->getName(); + Printer << "::"; +} +} + +FunctionDumper::FunctionDumper(LinePrinter &P) + : PDBSymDumper(true), Printer(P) {} + +void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol, + const char *Name, PointerType Pointer) { + auto ReturnType = Symbol.getReturnType(); + ReturnType->dump(*this); + Printer << " "; + uint32_t ClassParentId = Symbol.getClassParentId(); + auto ClassParent = + Symbol.getSession().getConcreteSymbolById( + ClassParentId); + + PDB_CallingConv CC = Symbol.getCallingConvention(); + bool ShouldDumpCallingConvention = true; + if ((ClassParent && CC == CallingConvention::ThisCall) || + (!ClassParent && CC == CallingConvention::NearStdCall)) { + ShouldDumpCallingConvention = false; + } + + if (Pointer == PointerType::None) { + if (ShouldDumpCallingConvention) + WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " "; + if (ClassParent) { + Printer << "("; + WithColor(Printer, PDB_ColorItem::Identifier).get() + << ClassParent->getName(); + Printer << "::)"; + } + } else { + Printer << "("; + if (ShouldDumpCallingConvention) + WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " "; + if (ClassParent) { + WithColor(Printer, PDB_ColorItem::Identifier).get() + << ClassParent->getName(); + Printer << "::"; + } + if (Pointer == PointerType::Reference) + Printer << "&"; + else + Printer << "*"; + if (Name) + WithColor(Printer, PDB_ColorItem::Identifier).get() << Name; + Printer << ")"; + } + + Printer << "("; + if (auto ChildEnum = Symbol.getArguments()) { + uint32_t Index = 0; + while (auto Arg = ChildEnum->getNext()) { + Arg->dump(*this); + if (++Index < ChildEnum->getChildCount()) + Printer << ", "; + } + } + Printer << ")"; + + if (Symbol.isConstType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << " const"; + if (Symbol.isVolatileType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile"; +} + +void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) { + uint64_t FuncStart = Symbol.getVirtualAddress(); + uint64_t FuncEnd = FuncStart + Symbol.getLength(); + + Printer << "func ["; + WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10); + if (auto DebugStart = Symbol.findOneChild()) { + uint64_t Prologue = DebugStart->getVirtualAddress() - FuncStart; + WithColor(Printer, PDB_ColorItem::Offset).get() + << formatv("+{0,2}", Prologue); + } + Printer << " - "; + WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10); + if (auto DebugEnd = Symbol.findOneChild()) { + uint64_t Epilogue = FuncEnd - DebugEnd->getVirtualAddress(); + WithColor(Printer, PDB_ColorItem::Offset).get() + << formatv("-{0,2}", Epilogue); + } + + WithColor(Printer, PDB_ColorItem::Comment).get() + << formatv(" | sizeof={0,3}", Symbol.getLength()); + Printer << "] ("; + + if (Symbol.hasFramePointer()) { + WithColor(Printer, PDB_ColorItem::Register).get() + << Symbol.getLocalBasePointerRegisterId(); + } else { + WithColor(Printer, PDB_ColorItem::Register).get() << "FPO"; + } + Printer << ") "; + + if (Symbol.isVirtual() || Symbol.isPureVirtual()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual "; + + auto Signature = Symbol.getSignature(); + if (!Signature) { + WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); + if (Pointer == PointerType::Pointer) + Printer << "*"; + else if (Pointer == FunctionDumper::PointerType::Reference) + Printer << "&"; + return; + } + + auto ReturnType = Signature->getReturnType(); + ReturnType->dump(*this); + Printer << " "; + + auto ClassParent = Symbol.getClassParent(); + CallingConvention CC = Signature->getCallingConvention(); + if (Pointer != FunctionDumper::PointerType::None) + Printer << "("; + + if ((ClassParent && CC != CallingConvention::ThisCall) || + (!ClassParent && CC != CallingConvention::NearStdCall)) { + WithColor(Printer, PDB_ColorItem::Keyword).get() + << Signature->getCallingConvention() << " "; + } + WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); + if (Pointer != FunctionDumper::PointerType::None) { + if (Pointer == PointerType::Pointer) + Printer << "*"; + else if (Pointer == FunctionDumper::PointerType::Reference) + Printer << "&"; + Printer << ")"; + } + + Printer << "("; + if (auto Arguments = Symbol.getArguments()) { + uint32_t Index = 0; + while (auto Arg = Arguments->getNext()) { + auto ArgType = Arg->getType(); + ArgType->dump(*this); + WithColor(Printer, PDB_ColorItem::Identifier).get() << " " + << Arg->getName(); + if (++Index < Arguments->getChildCount()) + Printer << ", "; + } + } + Printer << ")"; + if (Symbol.isConstType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << " const"; + if (Symbol.isVolatileType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile"; + if (Symbol.isPureVirtual()) + Printer << " = 0"; +} + +void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol) { + auto ElementType = Symbol.getElementType(); + + ElementType->dump(*this); + Printer << "["; + WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getLength(); + Printer << "]"; +} + +void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol) { + BuiltinDumper Dumper(Printer); + Dumper.start(Symbol); +} + +void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol) { + dumpClassParentWithScopeOperator(Symbol, Printer, *this); + WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); +} + +void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol) { + // PDBSymbolTypeFunctionArg is just a shim over the real argument. Just drill + // through to the real thing and dump it. + uint32_t TypeId = Symbol.getTypeId(); + auto Type = Symbol.getSession().getSymbolById(TypeId); + if (!Type) + return; + Type->dump(*this); +} + +void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol) { + dumpClassParentWithScopeOperator(Symbol, Printer, *this); + WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); +} + +void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol) { + auto PointeeType = Symbol.getPointeeType(); + if (!PointeeType) + return; + + if (auto FuncSig = unique_dyn_cast(PointeeType)) { + FunctionDumper NestedDumper(Printer); + PointerType Pointer = + Symbol.isReference() ? PointerType::Reference : PointerType::Pointer; + NestedDumper.start(*FuncSig, nullptr, Pointer); + } else { + if (Symbol.isConstType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; + if (Symbol.isVolatileType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; + PointeeType->dump(*this); + Printer << (Symbol.isReference() ? "&" : "*"); + } +} + +void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol) { + WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); +} diff --git a/tools/llvm-pdbutil/PrettyFunctionDumper.h b/tools/llvm-pdbutil/PrettyFunctionDumper.h new file mode 100644 index 000000000000..1a6f5430ec5a --- /dev/null +++ b/tools/llvm-pdbutil/PrettyFunctionDumper.h @@ -0,0 +1,43 @@ +//===- PrettyFunctionDumper.h --------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYFUNCTIONDUMPER_H +#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYFUNCTIONDUMPER_H + +#include "llvm/DebugInfo/PDB/PDBSymDumper.h" + +namespace llvm { +namespace pdb { +class LinePrinter; + +class FunctionDumper : public PDBSymDumper { +public: + FunctionDumper(LinePrinter &P); + + enum class PointerType { None, Pointer, Reference }; + + void start(const PDBSymbolTypeFunctionSig &Symbol, const char *Name, + PointerType Pointer); + void start(const PDBSymbolFunc &Symbol, PointerType Pointer); + + void dump(const PDBSymbolTypeArray &Symbol) override; + void dump(const PDBSymbolTypeBuiltin &Symbol) override; + void dump(const PDBSymbolTypeEnum &Symbol) override; + void dump(const PDBSymbolTypeFunctionArg &Symbol) override; + void dump(const PDBSymbolTypePointer &Symbol) override; + void dump(const PDBSymbolTypeTypedef &Symbol) override; + void dump(const PDBSymbolTypeUDT &Symbol) override; + +private: + LinePrinter &Printer; +}; +} +} + +#endif diff --git a/tools/llvm-pdbutil/PrettyTypeDumper.cpp b/tools/llvm-pdbutil/PrettyTypeDumper.cpp new file mode 100644 index 000000000000..0f6086395ad1 --- /dev/null +++ b/tools/llvm-pdbutil/PrettyTypeDumper.cpp @@ -0,0 +1,255 @@ +//===- PrettyTypeDumper.cpp - PDBSymDumper type dumper *------------ C++ *-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PrettyTypeDumper.h" + +#include "LinePrinter.h" +#include "PrettyBuiltinDumper.h" +#include "PrettyClassDefinitionDumper.h" +#include "PrettyEnumDumper.h" +#include "PrettyTypedefDumper.h" +#include "llvm-pdbutil.h" + +#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" +#include "llvm/DebugInfo/PDB/UDTLayout.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/FormatVariadic.h" + +using namespace llvm; +using namespace llvm::pdb; + +using LayoutPtr = std::unique_ptr; + +typedef bool (*CompareFunc)(const LayoutPtr &S1, const LayoutPtr &S2); + +static bool CompareNames(const LayoutPtr &S1, const LayoutPtr &S2) { + return S1->getName() < S2->getName(); +} + +static bool CompareSizes(const LayoutPtr &S1, const LayoutPtr &S2) { + return S1->getSize() < S2->getSize(); +} + +static bool ComparePadding(const LayoutPtr &S1, const LayoutPtr &S2) { + return S1->deepPaddingSize() < S2->deepPaddingSize(); +} + +static bool ComparePaddingPct(const LayoutPtr &S1, const LayoutPtr &S2) { + double Pct1 = (double)S1->deepPaddingSize() / (double)S1->getSize(); + double Pct2 = (double)S2->deepPaddingSize() / (double)S2->getSize(); + return Pct1 < Pct2; +} + +static bool ComparePaddingImmediate(const LayoutPtr &S1, const LayoutPtr &S2) { + return S1->immediatePadding() < S2->immediatePadding(); +} + +static bool ComparePaddingPctImmediate(const LayoutPtr &S1, + const LayoutPtr &S2) { + double Pct1 = (double)S1->immediatePadding() / (double)S1->getSize(); + double Pct2 = (double)S2->immediatePadding() / (double)S2->getSize(); + return Pct1 < Pct2; +} + +static CompareFunc getComparisonFunc(opts::pretty::ClassSortMode Mode) { + switch (Mode) { + case opts::pretty::ClassSortMode::Name: + return CompareNames; + case opts::pretty::ClassSortMode::Size: + return CompareSizes; + case opts::pretty::ClassSortMode::Padding: + return ComparePadding; + case opts::pretty::ClassSortMode::PaddingPct: + return ComparePaddingPct; + case opts::pretty::ClassSortMode::PaddingImmediate: + return ComparePaddingImmediate; + case opts::pretty::ClassSortMode::PaddingPctImmediate: + return ComparePaddingPctImmediate; + default: + return nullptr; + } +} + +template +static std::vector> +filterAndSortClassDefs(LinePrinter &Printer, Enumerator &E, + uint32_t UnfilteredCount) { + std::vector> Filtered; + + Filtered.reserve(UnfilteredCount); + CompareFunc Comp = getComparisonFunc(opts::pretty::ClassOrder); + + if (UnfilteredCount > 10000) { + errs() << formatv("Filtering and sorting {0} types", UnfilteredCount); + errs().flush(); + } + uint32_t Examined = 0; + uint32_t Discarded = 0; + while (auto Class = E.getNext()) { + ++Examined; + if (Examined % 10000 == 0) { + errs() << formatv("Examined {0}/{1} items. {2} items discarded\n", + Examined, UnfilteredCount, Discarded); + errs().flush(); + } + + if (Class->getUnmodifiedTypeId() != 0) { + ++Discarded; + continue; + } + + if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) { + ++Discarded; + continue; + } + + auto Layout = llvm::make_unique(std::move(Class)); + if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold) { + ++Discarded; + continue; + } + if (Layout->immediatePadding() < opts::pretty::ImmediatePaddingThreshold) { + ++Discarded; + continue; + } + + Filtered.push_back(std::move(Layout)); + } + + if (Comp) + std::sort(Filtered.begin(), Filtered.end(), Comp); + return Filtered; +} + +TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {} + +void TypeDumper::start(const PDBSymbolExe &Exe) { + auto Children = Exe.findAllChildren(); + if (opts::pretty::Enums) { + if (auto Enums = Exe.findAllChildren()) { + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::Identifier).get() << "Enums"; + Printer << ": (" << Enums->getChildCount() << " items)"; + Printer.Indent(); + while (auto Enum = Enums->getNext()) + Enum->dump(*this); + Printer.Unindent(); + } + } + + if (opts::pretty::Typedefs) { + if (auto Typedefs = Exe.findAllChildren()) { + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::Identifier).get() << "Typedefs"; + Printer << ": (" << Typedefs->getChildCount() << " items)"; + Printer.Indent(); + while (auto Typedef = Typedefs->getNext()) + Typedef->dump(*this); + Printer.Unindent(); + } + } + + if (opts::pretty::Classes) { + if (auto Classes = Exe.findAllChildren()) { + uint32_t All = Classes->getChildCount(); + + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes"; + + bool Precompute = false; + Precompute = + (opts::pretty::ClassOrder != opts::pretty::ClassSortMode::None); + + // If we're using no sort mode, then we can start getting immediate output + // from the tool by just filtering as we go, rather than processing + // everything up front so that we can sort it. This makes the tool more + // responsive. So only precompute the filtered/sorted set of classes if + // necessary due to the specified options. + std::vector Filtered; + uint32_t Shown = All; + if (Precompute) { + Filtered = filterAndSortClassDefs(Printer, *Classes, All); + + Shown = Filtered.size(); + } + + Printer << ": (Showing " << Shown << " items"; + if (Shown < All) + Printer << ", " << (All - Shown) << " filtered"; + Printer << ")"; + Printer.Indent(); + + // If we pre-computed, iterate the filtered/sorted list, otherwise iterate + // the DIA enumerator and filter on the fly. + if (Precompute) { + for (auto &Class : Filtered) + dumpClassLayout(*Class); + } else { + while (auto Class = Classes->getNext()) { + if (Class->getUnmodifiedTypeId() != 0) + continue; + + if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) + continue; + + auto Layout = llvm::make_unique(std::move(Class)); + if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold) + continue; + + dumpClassLayout(*Layout); + } + } + + Printer.Unindent(); + } + } +} + +void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) { + assert(opts::pretty::Enums); + + if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength())) + return; + // Dump member enums when dumping their class definition. + if (nullptr != Symbol.getClassParent()) + return; + + Printer.NewLine(); + EnumDumper Dumper(Printer); + Dumper.start(Symbol); +} + +void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) { + assert(opts::pretty::Typedefs); + + if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength())) + return; + + Printer.NewLine(); + TypedefDumper Dumper(Printer); + Dumper.start(Symbol); +} + +void TypeDumper::dumpClassLayout(const ClassLayout &Class) { + assert(opts::pretty::Classes); + + if (opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::None) { + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::Keyword).get() << "class "; + WithColor(Printer, PDB_ColorItem::Identifier).get() << Class.getName(); + } else { + ClassDefinitionDumper Dumper(Printer); + Dumper.start(Class); + } +} diff --git a/tools/llvm-pdbutil/PrettyTypeDumper.h b/tools/llvm-pdbutil/PrettyTypeDumper.h new file mode 100644 index 000000000000..68a2f0246eba --- /dev/null +++ b/tools/llvm-pdbutil/PrettyTypeDumper.h @@ -0,0 +1,36 @@ +//===- PrettyTypeDumper.h - PDBSymDumper implementation for types *- C++ *-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDUMPER_H +#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDUMPER_H + +#include "llvm/DebugInfo/PDB/PDBSymDumper.h" + +namespace llvm { +namespace pdb { +class LinePrinter; +class ClassLayout; + +class TypeDumper : public PDBSymDumper { +public: + TypeDumper(LinePrinter &P); + + void start(const PDBSymbolExe &Exe); + + void dump(const PDBSymbolTypeEnum &Symbol) override; + void dump(const PDBSymbolTypeTypedef &Symbol) override; + + void dumpClassLayout(const ClassLayout &Class); + +private: + LinePrinter &Printer; +}; +} +} +#endif diff --git a/tools/llvm-pdbutil/PrettyTypedefDumper.cpp b/tools/llvm-pdbutil/PrettyTypedefDumper.cpp new file mode 100644 index 000000000000..2266e6ea2bef --- /dev/null +++ b/tools/llvm-pdbutil/PrettyTypedefDumper.cpp @@ -0,0 +1,77 @@ +//===- PrettyTypedefDumper.cpp - PDBSymDumper impl for typedefs -- * C++ *-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PrettyTypedefDumper.h" + +#include "LinePrinter.h" +#include "PrettyBuiltinDumper.h" +#include "PrettyFunctionDumper.h" +#include "llvm-pdbutil.h" + +#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/PDBExtras.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" + +using namespace llvm; +using namespace llvm::pdb; + +TypedefDumper::TypedefDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {} + +void TypedefDumper::start(const PDBSymbolTypeTypedef &Symbol) { + WithColor(Printer, PDB_ColorItem::Keyword).get() << "typedef "; + uint32_t TargetId = Symbol.getTypeId(); + if (auto TypeSymbol = Symbol.getSession().getSymbolById(TargetId)) + TypeSymbol->dump(*this); + WithColor(Printer, PDB_ColorItem::Identifier).get() << " " + << Symbol.getName(); +} + +void TypedefDumper::dump(const PDBSymbolTypeArray &Symbol) {} + +void TypedefDumper::dump(const PDBSymbolTypeBuiltin &Symbol) { + BuiltinDumper Dumper(Printer); + Dumper.start(Symbol); +} + +void TypedefDumper::dump(const PDBSymbolTypeEnum &Symbol) { + WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum "; + WithColor(Printer, PDB_ColorItem::Type).get() << " " << Symbol.getName(); +} + +void TypedefDumper::dump(const PDBSymbolTypePointer &Symbol) { + if (Symbol.isConstType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; + if (Symbol.isVolatileType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; + auto PointeeType = Symbol.getPointeeType(); + if (auto FuncSig = unique_dyn_cast(PointeeType)) { + FunctionDumper::PointerType Pointer = FunctionDumper::PointerType::Pointer; + if (Symbol.isReference()) + Pointer = FunctionDumper::PointerType::Reference; + FunctionDumper NestedDumper(Printer); + NestedDumper.start(*FuncSig, nullptr, Pointer); + } else { + PointeeType->dump(*this); + Printer << ((Symbol.isReference()) ? "&" : "*"); + } +} + +void TypedefDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) { + FunctionDumper Dumper(Printer); + Dumper.start(Symbol, nullptr, FunctionDumper::PointerType::None); +} + +void TypedefDumper::dump(const PDBSymbolTypeUDT &Symbol) { + WithColor(Printer, PDB_ColorItem::Keyword).get() << "class "; + WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); +} diff --git a/tools/llvm-pdbutil/PrettyTypedefDumper.h b/tools/llvm-pdbutil/PrettyTypedefDumper.h new file mode 100644 index 000000000000..133bbfb7db0e --- /dev/null +++ b/tools/llvm-pdbutil/PrettyTypedefDumper.h @@ -0,0 +1,39 @@ +//===- PrettyTypedefDumper.h - llvm-pdbutil typedef dumper ---*- C++ ----*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDEFDUMPER_H +#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDEFDUMPER_H + +#include "llvm/DebugInfo/PDB/PDBSymDumper.h" + +namespace llvm { +namespace pdb { + +class LinePrinter; + +class TypedefDumper : public PDBSymDumper { +public: + TypedefDumper(LinePrinter &P); + + void start(const PDBSymbolTypeTypedef &Symbol); + + void dump(const PDBSymbolTypeArray &Symbol) override; + void dump(const PDBSymbolTypeBuiltin &Symbol) override; + void dump(const PDBSymbolTypeEnum &Symbol) override; + void dump(const PDBSymbolTypeFunctionSig &Symbol) override; + void dump(const PDBSymbolTypePointer &Symbol) override; + void dump(const PDBSymbolTypeUDT &Symbol) override; + +private: + LinePrinter &Printer; +}; +} +} + +#endif diff --git a/tools/llvm-pdbutil/PrettyVariableDumper.cpp b/tools/llvm-pdbutil/PrettyVariableDumper.cpp new file mode 100644 index 000000000000..4884fc8ee5a4 --- /dev/null +++ b/tools/llvm-pdbutil/PrettyVariableDumper.cpp @@ -0,0 +1,220 @@ +//===- PrettyVariableDumper.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PrettyVariableDumper.h" + +#include "LinePrinter.h" +#include "PrettyBuiltinDumper.h" +#include "PrettyFunctionDumper.h" +#include "llvm-pdbutil.h" + +#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" + +#include "llvm/Support/Format.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +VariableDumper::VariableDumper(LinePrinter &P) + : PDBSymDumper(true), Printer(P) {} + +void VariableDumper::start(const PDBSymbolData &Var, uint32_t Offset) { + if (Var.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated) + return; + if (Printer.IsSymbolExcluded(Var.getName())) + return; + + auto VarType = Var.getType(); + + uint64_t Length = VarType->getRawSymbol().getLength(); + + switch (auto LocType = Var.getLocationType()) { + case PDB_LocType::Static: + Printer.NewLine(); + Printer << "data ["; + WithColor(Printer, PDB_ColorItem::Address).get() + << format_hex(Var.getVirtualAddress(), 10); + Printer << ", sizeof=" << Length << "] "; + WithColor(Printer, PDB_ColorItem::Keyword).get() << "static "; + dumpSymbolTypeAndName(*VarType, Var.getName()); + break; + case PDB_LocType::Constant: + if (isa(*VarType)) + break; + Printer.NewLine(); + Printer << "data [sizeof=" << Length << "] "; + dumpSymbolTypeAndName(*VarType, Var.getName()); + Printer << " = "; + WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getValue(); + break; + case PDB_LocType::ThisRel: + Printer.NewLine(); + Printer << "data "; + WithColor(Printer, PDB_ColorItem::Offset).get() + << "+" << format_hex(Offset + Var.getOffset(), 4) + << " [sizeof=" << Length << "] "; + dumpSymbolTypeAndName(*VarType, Var.getName()); + break; + case PDB_LocType::BitField: + Printer.NewLine(); + Printer << "data "; + WithColor(Printer, PDB_ColorItem::Offset).get() + << "+" << format_hex(Offset + Var.getOffset(), 4) + << " [sizeof=" << Length << "] "; + dumpSymbolTypeAndName(*VarType, Var.getName()); + Printer << " : "; + WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getLength(); + break; + default: + Printer.NewLine(); + Printer << "data [sizeof=" << Length << "] "; + Printer << "unknown(" << LocType << ") "; + WithColor(Printer, PDB_ColorItem::Identifier).get() << Var.getName(); + break; + } +} + +void VariableDumper::startVbptr(uint32_t Offset, uint32_t Size) { + Printer.NewLine(); + Printer << "vbptr "; + + WithColor(Printer, PDB_ColorItem::Offset).get() + << "+" << format_hex(Offset, 4) << " [sizeof=" << Size << "] "; +} + +void VariableDumper::start(const PDBSymbolTypeVTable &Var, uint32_t Offset) { + Printer.NewLine(); + Printer << "vfptr "; + auto VTableType = cast(Var.getType()); + uint32_t PointerSize = VTableType->getLength(); + + WithColor(Printer, PDB_ColorItem::Offset).get() + << "+" << format_hex(Offset + Var.getOffset(), 4) + << " [sizeof=" << PointerSize << "] "; +} + +void VariableDumper::dump(const PDBSymbolTypeArray &Symbol) { + auto ElementType = Symbol.getElementType(); + assert(ElementType); + if (!ElementType) + return; + ElementType->dump(*this); +} + +void VariableDumper::dumpRight(const PDBSymbolTypeArray &Symbol) { + auto ElementType = Symbol.getElementType(); + assert(ElementType); + if (!ElementType) + return; + Printer << '[' << Symbol.getCount() << ']'; + ElementType->dumpRight(*this); +} + +void VariableDumper::dump(const PDBSymbolTypeBuiltin &Symbol) { + BuiltinDumper Dumper(Printer); + Dumper.start(Symbol); +} + +void VariableDumper::dump(const PDBSymbolTypeEnum &Symbol) { + WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); +} + +void VariableDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) { + auto ReturnType = Symbol.getReturnType(); + ReturnType->dump(*this); + Printer << " "; + + uint32_t ClassParentId = Symbol.getClassParentId(); + auto ClassParent = + Symbol.getSession().getConcreteSymbolById( + ClassParentId); + + if (ClassParent) { + WithColor(Printer, PDB_ColorItem::Identifier).get() + << ClassParent->getName(); + Printer << "::"; + } +} + +void VariableDumper::dumpRight(const PDBSymbolTypeFunctionSig &Symbol) { + Printer << "("; + if (auto Arguments = Symbol.getArguments()) { + uint32_t Index = 0; + while (auto Arg = Arguments->getNext()) { + Arg->dump(*this); + if (++Index < Arguments->getChildCount()) + Printer << ", "; + } + } + Printer << ")"; + + if (Symbol.isConstType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << " const"; + if (Symbol.isVolatileType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile"; +} + +void VariableDumper::dump(const PDBSymbolTypePointer &Symbol) { + auto PointeeType = Symbol.getPointeeType(); + if (!PointeeType) + return; + PointeeType->dump(*this); + if (auto FuncSig = unique_dyn_cast(PointeeType)) { + // A hack to get the calling convention in the right spot. + Printer << " ("; + PDB_CallingConv CC = FuncSig->getCallingConvention(); + WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " "; + } else if (isa(PointeeType)) { + Printer << " ("; + } + Printer << (Symbol.isReference() ? "&" : "*"); + if (Symbol.isConstType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << " const "; + if (Symbol.isVolatileType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile "; +} + +void VariableDumper::dumpRight(const PDBSymbolTypePointer &Symbol) { + auto PointeeType = Symbol.getPointeeType(); + assert(PointeeType); + if (!PointeeType) + return; + if (isa(PointeeType) || + isa(PointeeType)) { + Printer << ")"; + } + PointeeType->dumpRight(*this); +} + +void VariableDumper::dump(const PDBSymbolTypeTypedef &Symbol) { + WithColor(Printer, PDB_ColorItem::Keyword).get() << "typedef "; + WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); +} + +void VariableDumper::dump(const PDBSymbolTypeUDT &Symbol) { + WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); +} + +void VariableDumper::dumpSymbolTypeAndName(const PDBSymbol &Type, + StringRef Name) { + Type.dump(*this); + WithColor(Printer, PDB_ColorItem::Identifier).get() << " " << Name; + Type.dumpRight(*this); +} diff --git a/tools/llvm-pdbutil/PrettyVariableDumper.h b/tools/llvm-pdbutil/PrettyVariableDumper.h new file mode 100644 index 000000000000..cacf1ce9577b --- /dev/null +++ b/tools/llvm-pdbutil/PrettyVariableDumper.h @@ -0,0 +1,50 @@ +//===- PrettyVariableDumper.h - PDBSymDumper variable dumper ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYVARIABLEDUMPER_H +#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYVARIABLEDUMPER_H + +#include "llvm/DebugInfo/PDB/PDBSymDumper.h" + +namespace llvm { + +class StringRef; + +namespace pdb { + +class LinePrinter; + +class VariableDumper : public PDBSymDumper { +public: + VariableDumper(LinePrinter &P); + + void start(const PDBSymbolData &Var, uint32_t Offset = 0); + void start(const PDBSymbolTypeVTable &Var, uint32_t Offset = 0); + void startVbptr(uint32_t Offset, uint32_t Size); + + void dump(const PDBSymbolTypeArray &Symbol) override; + void dump(const PDBSymbolTypeBuiltin &Symbol) override; + void dump(const PDBSymbolTypeEnum &Symbol) override; + void dump(const PDBSymbolTypeFunctionSig &Symbol) override; + void dump(const PDBSymbolTypePointer &Symbol) override; + void dump(const PDBSymbolTypeTypedef &Symbol) override; + void dump(const PDBSymbolTypeUDT &Symbol) override; + + void dumpRight(const PDBSymbolTypeArray &Symbol) override; + void dumpRight(const PDBSymbolTypeFunctionSig &Symbol) override; + void dumpRight(const PDBSymbolTypePointer &Symbol) override; + +private: + void dumpSymbolTypeAndName(const PDBSymbol &Type, StringRef Name); + + LinePrinter &Printer; +}; +} +} +#endif diff --git a/tools/llvm-pdbutil/StreamUtil.cpp b/tools/llvm-pdbutil/StreamUtil.cpp new file mode 100644 index 000000000000..81aa256b5002 --- /dev/null +++ b/tools/llvm-pdbutil/StreamUtil.cpp @@ -0,0 +1,139 @@ +//===- StreamUtil.cpp - PDB stream utilities --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "StreamUtil.h" + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h" +#include "llvm/DebugInfo/PDB/Native/DbiStream.h" +#include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" + +namespace llvm { +namespace pdb { +void discoverStreamPurposes(PDBFile &File, + SmallVectorImpl &Purposes) { + + // It's OK if we fail to load some of these streams, we still attempt to print + // what we can. + auto Dbi = File.getPDBDbiStream(); + auto Tpi = File.getPDBTpiStream(); + auto Ipi = File.getPDBIpiStream(); + auto Info = File.getPDBInfoStream(); + + uint32_t StreamCount = File.getNumStreams(); + DenseMap ModStreams; + DenseMap NamedStreams; + + if (Dbi) { + const DbiModuleList &Modules = Dbi->modules(); + for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) { + DbiModuleDescriptor Descriptor = Modules.getModuleDescriptor(I); + uint16_t SN = Descriptor.getModuleStreamIndex(); + if (SN != kInvalidStreamIndex) + ModStreams[SN] = Descriptor; + } + } + if (Info) { + for (auto &NSE : Info->named_streams()) { + if (NSE.second != kInvalidStreamIndex) + NamedStreams[NSE.second] = NSE.first(); + } + } + + Purposes.resize(StreamCount); + for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) { + std::string Value; + if (StreamIdx == OldMSFDirectory) + Value = "Old MSF Directory"; + else if (StreamIdx == StreamPDB) + Value = "PDB Stream"; + else if (StreamIdx == StreamDBI) + Value = "DBI Stream"; + else if (StreamIdx == StreamTPI) + Value = "TPI Stream"; + else if (StreamIdx == StreamIPI) + Value = "IPI Stream"; + else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex()) + Value = "Global Symbol Hash"; + else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex()) + Value = "Public Symbol Hash"; + else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex()) + Value = "Public Symbol Records"; + else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex()) + Value = "TPI Hash"; + else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex()) + Value = "TPI Aux Hash"; + else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex()) + Value = "IPI Hash"; + else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex()) + Value = "IPI Aux Hash"; + else if (Dbi && + StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception)) + Value = "Exception Data"; + else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup)) + Value = "Fixup Data"; + else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO)) + Value = "FPO Data"; + else if (Dbi && + StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO)) + Value = "New FPO Data"; + else if (Dbi && + StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc)) + Value = "Omap From Source Data"; + else if (Dbi && + StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc)) + Value = "Omap To Source Data"; + else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata)) + Value = "Pdata"; + else if (Dbi && + StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr)) + Value = "Section Header Data"; + else if (Dbi && + StreamIdx == + Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig)) + Value = "Section Header Original Data"; + else if (Dbi && + StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap)) + Value = "Token Rid Data"; + else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata)) + Value = "Xdata"; + else { + auto ModIter = ModStreams.find(StreamIdx); + auto NSIter = NamedStreams.find(StreamIdx); + if (ModIter != ModStreams.end()) { + Value = "Module \""; + Value += ModIter->second.getModuleName(); + Value += "\""; + } else if (NSIter != NamedStreams.end()) { + Value = "Named Stream \""; + Value += NSIter->second; + Value += "\""; + } else { + Value = "???"; + } + } + Purposes[StreamIdx] = Value; + } + + // Consume errors from missing streams. + if (!Dbi) + consumeError(Dbi.takeError()); + if (!Tpi) + consumeError(Tpi.takeError()); + if (!Ipi) + consumeError(Ipi.takeError()); + if (!Info) + consumeError(Info.takeError()); +} +} +} diff --git a/tools/llvm-pdbutil/StreamUtil.h b/tools/llvm-pdbutil/StreamUtil.h new file mode 100644 index 000000000000..b5c0beba44fe --- /dev/null +++ b/tools/llvm-pdbutil/StreamUtil.h @@ -0,0 +1,25 @@ +//===- Streamutil.h - PDB stream utilities ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_STREAMUTIL_H +#define LLVM_TOOLS_LLVMPDBDUMP_STREAMUTIL_H + +#include "llvm/ADT/SmallVector.h" + +#include + +namespace llvm { +namespace pdb { +class PDBFile; +void discoverStreamPurposes(PDBFile &File, + SmallVectorImpl &Purposes); +} +} + +#endif diff --git a/tools/llvm-pdbutil/YAMLOutputStyle.cpp b/tools/llvm-pdbutil/YAMLOutputStyle.cpp new file mode 100644 index 000000000000..58c538d968c8 --- /dev/null +++ b/tools/llvm-pdbutil/YAMLOutputStyle.cpp @@ -0,0 +1,317 @@ +//===- YAMLOutputStyle.cpp ------------------------------------ *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "YAMLOutputStyle.h" + +#include "PdbYaml.h" +#include "llvm-pdbutil.h" + +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h" +#include "llvm/DebugInfo/CodeView/Line.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/DbiStream.h" +#include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +YAMLOutputStyle::YAMLOutputStyle(PDBFile &File) + : File(File), Out(outs()), Obj(File.getAllocator()) { + Out.setWriteDefaultValues(!opts::pdb2yaml::Minimal); +} + +Error YAMLOutputStyle::dump() { + if (opts::pdb2yaml::StreamDirectory) + opts::pdb2yaml::StreamMetadata = true; + + if (auto EC = dumpFileHeaders()) + return EC; + + if (auto EC = dumpStreamMetadata()) + return EC; + + if (auto EC = dumpStreamDirectory()) + return EC; + + if (auto EC = dumpStringTable()) + return EC; + + if (auto EC = dumpPDBStream()) + return EC; + + if (auto EC = dumpDbiStream()) + return EC; + + if (auto EC = dumpTpiStream()) + return EC; + + if (auto EC = dumpIpiStream()) + return EC; + + flush(); + return Error::success(); +} + + +Error YAMLOutputStyle::dumpFileHeaders() { + if (opts::pdb2yaml::NoFileHeaders) + return Error::success(); + + yaml::MSFHeaders Headers; + Obj.Headers.emplace(); + Obj.Headers->SuperBlock.NumBlocks = File.getBlockCount(); + Obj.Headers->SuperBlock.BlockMapAddr = File.getBlockMapIndex(); + Obj.Headers->SuperBlock.BlockSize = File.getBlockSize(); + auto Blocks = File.getDirectoryBlockArray(); + Obj.Headers->DirectoryBlocks.assign(Blocks.begin(), Blocks.end()); + Obj.Headers->NumDirectoryBlocks = File.getNumDirectoryBlocks(); + Obj.Headers->SuperBlock.NumDirectoryBytes = File.getNumDirectoryBytes(); + Obj.Headers->NumStreams = + opts::pdb2yaml::StreamMetadata ? File.getNumStreams() : 0; + Obj.Headers->SuperBlock.FreeBlockMapBlock = File.getFreeBlockMapBlock(); + Obj.Headers->SuperBlock.Unknown1 = File.getUnknown1(); + Obj.Headers->FileSize = File.getFileSize(); + + return Error::success(); +} + +Error YAMLOutputStyle::dumpStringTable() { + bool RequiresStringTable = opts::shared::DumpModuleFiles || + !opts::shared::DumpModuleSubsections.empty(); + bool RequestedStringTable = opts::pdb2yaml::StringTable; + if (!RequiresStringTable && !RequestedStringTable) + return Error::success(); + + auto ExpectedST = File.getStringTable(); + if (!ExpectedST) + return ExpectedST.takeError(); + + Obj.StringTable.emplace(); + const auto &ST = ExpectedST.get(); + for (auto ID : ST.name_ids()) { + auto S = ST.getStringForID(ID); + if (!S) + return S.takeError(); + if (S->empty()) + continue; + Obj.StringTable->push_back(*S); + } + return Error::success(); +} + +Error YAMLOutputStyle::dumpStreamMetadata() { + if (!opts::pdb2yaml::StreamMetadata) + return Error::success(); + + Obj.StreamSizes.emplace(); + Obj.StreamSizes->assign(File.getStreamSizes().begin(), + File.getStreamSizes().end()); + return Error::success(); +} + +Error YAMLOutputStyle::dumpStreamDirectory() { + if (!opts::pdb2yaml::StreamDirectory) + return Error::success(); + + auto StreamMap = File.getStreamMap(); + Obj.StreamMap.emplace(); + for (auto &Stream : StreamMap) { + pdb::yaml::StreamBlockList BlockList; + BlockList.Blocks.assign(Stream.begin(), Stream.end()); + Obj.StreamMap->push_back(BlockList); + } + + return Error::success(); +} + +Error YAMLOutputStyle::dumpPDBStream() { + if (!opts::pdb2yaml::PdbStream) + return Error::success(); + + auto IS = File.getPDBInfoStream(); + if (!IS) + return IS.takeError(); + + auto &InfoS = IS.get(); + Obj.PdbStream.emplace(); + Obj.PdbStream->Age = InfoS.getAge(); + Obj.PdbStream->Guid = InfoS.getGuid(); + Obj.PdbStream->Signature = InfoS.getSignature(); + Obj.PdbStream->Version = InfoS.getVersion(); + Obj.PdbStream->Features = InfoS.getFeatureSignatures(); + + return Error::success(); +} + +static opts::ModuleSubsection convertSubsectionKind(DebugSubsectionKind K) { + switch (K) { + case DebugSubsectionKind::CrossScopeExports: + return opts::ModuleSubsection::CrossScopeExports; + case DebugSubsectionKind::CrossScopeImports: + return opts::ModuleSubsection::CrossScopeImports; + case DebugSubsectionKind::FileChecksums: + return opts::ModuleSubsection::FileChecksums; + case DebugSubsectionKind::InlineeLines: + return opts::ModuleSubsection::InlineeLines; + case DebugSubsectionKind::Lines: + return opts::ModuleSubsection::Lines; + case DebugSubsectionKind::Symbols: + return opts::ModuleSubsection::Symbols; + case DebugSubsectionKind::StringTable: + return opts::ModuleSubsection::StringTable; + case DebugSubsectionKind::FrameData: + return opts::ModuleSubsection::FrameData; + default: + return opts::ModuleSubsection::Unknown; + } + llvm_unreachable("Unreachable!"); +} + +Error YAMLOutputStyle::dumpDbiStream() { + if (!opts::pdb2yaml::DbiStream) + return Error::success(); + + auto DbiS = File.getPDBDbiStream(); + if (!DbiS) + return DbiS.takeError(); + + auto &DS = DbiS.get(); + Obj.DbiStream.emplace(); + Obj.DbiStream->Age = DS.getAge(); + Obj.DbiStream->BuildNumber = DS.getBuildNumber(); + Obj.DbiStream->Flags = DS.getFlags(); + Obj.DbiStream->MachineType = DS.getMachineType(); + Obj.DbiStream->PdbDllRbld = DS.getPdbDllRbld(); + Obj.DbiStream->PdbDllVersion = DS.getPdbDllVersion(); + Obj.DbiStream->VerHeader = DS.getDbiVersion(); + if (opts::shared::DumpModules) { + const auto &Modules = DS.modules(); + for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) { + DbiModuleDescriptor MI = Modules.getModuleDescriptor(I); + + Obj.DbiStream->ModInfos.emplace_back(); + yaml::PdbDbiModuleInfo &DMI = Obj.DbiStream->ModInfos.back(); + + DMI.Mod = MI.getModuleName(); + DMI.Obj = MI.getObjFileName(); + if (opts::shared::DumpModuleFiles) { + auto Files = Modules.source_files(I); + DMI.SourceFiles.assign(Files.begin(), Files.end()); + } + + uint16_t ModiStream = MI.getModuleStreamIndex(); + if (ModiStream == kInvalidStreamIndex) + continue; + + auto ModStreamData = msf::MappedBlockStream::createIndexedStream( + File.getMsfLayout(), File.getMsfBuffer(), ModiStream, + File.getAllocator()); + + pdb::ModuleDebugStreamRef ModS(MI, std::move(ModStreamData)); + if (auto EC = ModS.reload()) + return EC; + + auto ExpectedST = File.getStringTable(); + if (!ExpectedST) + return ExpectedST.takeError(); + if (!opts::shared::DumpModuleSubsections.empty() && + ModS.hasDebugSubsections()) { + auto ExpectedChecksums = ModS.findChecksumsSubsection(); + if (!ExpectedChecksums) + return ExpectedChecksums.takeError(); + + for (const auto &SS : ModS.subsections()) { + opts::ModuleSubsection OptionKind = convertSubsectionKind(SS.kind()); + if (!opts::checkModuleSubsection(OptionKind)) + continue; + + auto Converted = + CodeViewYAML::YAMLDebugSubsection::fromCodeViewSubection( + ExpectedST->getStringTable(), *ExpectedChecksums, SS); + if (!Converted) + return Converted.takeError(); + DMI.Subsections.push_back(*Converted); + } + } + + if (opts::shared::DumpModuleSyms) { + DMI.Modi.emplace(); + + DMI.Modi->Signature = ModS.signature(); + bool HadError = false; + for (auto &Sym : ModS.symbols(&HadError)) { + auto ES = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(Sym); + if (!ES) + return ES.takeError(); + + DMI.Modi->Symbols.push_back(*ES); + } + } + } + } + return Error::success(); +} + +Error YAMLOutputStyle::dumpTpiStream() { + if (!opts::pdb2yaml::TpiStream) + return Error::success(); + + auto TpiS = File.getPDBTpiStream(); + if (!TpiS) + return TpiS.takeError(); + + auto &TS = TpiS.get(); + Obj.TpiStream.emplace(); + Obj.TpiStream->Version = TS.getTpiVersion(); + for (auto &Record : TS.types(nullptr)) { + auto ExpectedRecord = CodeViewYAML::LeafRecord::fromCodeViewRecord(Record); + if (!ExpectedRecord) + return ExpectedRecord.takeError(); + Obj.TpiStream->Records.push_back(*ExpectedRecord); + } + + return Error::success(); +} + +Error YAMLOutputStyle::dumpIpiStream() { + if (!opts::pdb2yaml::IpiStream) + return Error::success(); + + auto IpiS = File.getPDBIpiStream(); + if (!IpiS) + return IpiS.takeError(); + + auto &IS = IpiS.get(); + Obj.IpiStream.emplace(); + Obj.IpiStream->Version = IS.getTpiVersion(); + for (auto &Record : IS.types(nullptr)) { + auto ExpectedRecord = CodeViewYAML::LeafRecord::fromCodeViewRecord(Record); + if (!ExpectedRecord) + return ExpectedRecord.takeError(); + + Obj.IpiStream->Records.push_back(*ExpectedRecord); + } + + return Error::success(); +} + +void YAMLOutputStyle::flush() { + Out << Obj; + outs().flush(); +} diff --git a/tools/llvm-pdbutil/YAMLOutputStyle.h b/tools/llvm-pdbutil/YAMLOutputStyle.h new file mode 100644 index 000000000000..3690e3529d4a --- /dev/null +++ b/tools/llvm-pdbutil/YAMLOutputStyle.h @@ -0,0 +1,49 @@ +//===- YAMLOutputStyle.h -------------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_YAMLOUTPUTSTYLE_H +#define LLVM_TOOLS_LLVMPDBDUMP_YAMLOUTPUTSTYLE_H + +#include "OutputStyle.h" +#include "PdbYaml.h" + +#include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/YAMLTraits.h" + +namespace llvm { +namespace pdb { +class ModuleDebugStreamRef; + +class YAMLOutputStyle : public OutputStyle { +public: + YAMLOutputStyle(PDBFile &File); + + Error dump() override; + +private: + Error dumpStringTable(); + Error dumpFileHeaders(); + Error dumpStreamMetadata(); + Error dumpStreamDirectory(); + Error dumpPDBStream(); + Error dumpDbiStream(); + Error dumpTpiStream(); + Error dumpIpiStream(); + + void flush(); + + PDBFile &File; + llvm::yaml::Output Out; + + yaml::PdbObject Obj; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_TOOLS_LLVMPDBDUMP_YAMLOUTPUTSTYLE_H diff --git a/tools/llvm-pdbutil/fuzzer/CMakeLists.txt b/tools/llvm-pdbutil/fuzzer/CMakeLists.txt new file mode 100644 index 000000000000..6af00476577f --- /dev/null +++ b/tools/llvm-pdbutil/fuzzer/CMakeLists.txt @@ -0,0 +1,15 @@ +set(LLVM_LINK_COMPONENTS + DebugInfoCodeView + DebugInfoPDB + Object + Support + ) + +add_llvm_executable(llvm-pdbutil-fuzzer + EXCLUDE_FROM_ALL + llvm-pdbutil-fuzzer.cpp + ) + +target_link_libraries(llvm-pdbutil-fuzzer + LLVMFuzzer + ) diff --git a/tools/llvm-pdbutil/fuzzer/llvm-pdbutil-fuzzer.cpp b/tools/llvm-pdbutil/fuzzer/llvm-pdbutil-fuzzer.cpp new file mode 100644 index 000000000000..4edb53e261ff --- /dev/null +++ b/tools/llvm-pdbutil/fuzzer/llvm-pdbutil-fuzzer.cpp @@ -0,0 +1,105 @@ +//===-- llvm-pdbutil-fuzzer.cpp - Fuzz the llvm-pdbutil tool --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file implements a function that runs llvm-pdbutil +/// on a single input. This function is then linked into the Fuzzer library. +/// +//===----------------------------------------------------------------------===// +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/CodeView/BinaryByteStream.h" +#include "llvm/DebugInfo/CodeView/SymbolDumper.h" +#include "llvm/DebugInfo/CodeView/TypeDumper.h" +#include "llvm/DebugInfo/PDB/Raw/DbiStream.h" +#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h" +#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Raw/ModuleDebugStream.h" +#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" +#include "llvm/DebugInfo/PDB/Raw/RawSession.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/ScopedPrinter.h" + +using namespace llvm; + +namespace { +// We need a class which behaves like an immutable BinaryByteStream, but whose +// data +// is backed by an llvm::MemoryBuffer. It also needs to own the underlying +// MemoryBuffer, so this simple adapter is a good way to achieve that. +class InputByteStream : public codeview::BinaryByteStream { +public: + explicit InputByteStream(std::unique_ptr Buffer) + : BinaryByteStream(ArrayRef(Buffer->getBuffer().bytes_begin(), + Buffer->getBuffer().bytes_end())), + MemBuffer(std::move(Buffer)) {} + + std::unique_ptr MemBuffer; +}; +} + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) { + std::unique_ptr Buff = MemoryBuffer::getMemBuffer( + StringRef((const char *)data, size), "", false); + + ScopedPrinter P(nulls()); + codeview::CVTypeDumper TD(&P, false); + + auto InputStream = llvm::make_unique(std::move(Buff)); + std::unique_ptr File(new pdb::PDBFile(std::move(InputStream))); + if (auto E = File->parseFileHeaders()) { + consumeError(std::move(E)); + return 0; + } + if (auto E = File->parseStreamData()) { + consumeError(std::move(E)); + return 0; + } + + auto DbiS = File->getPDBDbiStream(); + if (auto E = DbiS.takeError()) { + consumeError(std::move(E)); + return 0; + } + auto TpiS = File->getPDBTpiStream(); + if (auto E = TpiS.takeError()) { + consumeError(std::move(E)); + return 0; + } + auto IpiS = File->getPDBIpiStream(); + if (auto E = IpiS.takeError()) { + consumeError(std::move(E)); + return 0; + } + auto InfoS = File->getPDBInfoStream(); + if (auto E = InfoS.takeError()) { + consumeError(std::move(E)); + return 0; + } + pdb::DbiStream &DS = DbiS.get(); + + for (auto &Modi : DS.modules()) { + auto ModStreamData = pdb::MappedBlockStream::createIndexedStream( + Modi.Info.getModuleStreamIndex(), *File, File->getAllocator()); + if (!ModStreamData) { + consumeError(ModStreamData.takeError()); + return 0; + } + pdb::ModuleDebugStreamRef ModS(Modi.Info, std::move(*ModStreamData)); + if (auto E = ModS.reload()) { + consumeError(std::move(E)); + return 0; + } + codeview::CVSymbolDumper SD(P, TD, nullptr, false); + bool HadError = false; + for (auto &S : ModS.symbols(&HadError)) { + SD.dump(S); + } + } + return 0; +} diff --git a/tools/llvm-pdbutil/llvm-pdbutil.cpp b/tools/llvm-pdbutil/llvm-pdbutil.cpp new file mode 100644 index 000000000000..f6b6a156a767 --- /dev/null +++ b/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -0,0 +1,1025 @@ +//===- llvm-pdbutil.cpp - Dump debug info from a PDB file -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Dumps debug information present in PDB files. +// +//===----------------------------------------------------------------------===// + +#include "llvm-pdbutil.h" + +#include "Analyze.h" +#include "Diff.h" +#include "LLVMOutputStyle.h" +#include "LinePrinter.h" +#include "OutputStyle.h" +#include "PrettyCompilandDumper.h" +#include "PrettyExternalSymbolDumper.h" +#include "PrettyFunctionDumper.h" +#include "PrettyTypeDumper.h" +#include "PrettyVariableDumper.h" +#include "YAMLOutputStyle.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Config/config.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" +#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" +#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" +#include "llvm/DebugInfo/MSF/MSFBuilder.h" +#include "llvm/DebugInfo/PDB/GenericError.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" +#include "llvm/DebugInfo/PDB/Native/DbiStream.h" +#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" +#include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" +#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" +#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h" +#include "llvm/DebugInfo/PDB/PDB.h" +#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" +#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h" +#include "llvm/Support/BinaryByteStream.h" +#include "llvm/Support/COM.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Regex.h" +#include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::msf; +using namespace llvm::pdb; + +namespace opts { + +cl::SubCommand RawSubcommand("raw", "Dump raw structure of the PDB file"); +cl::SubCommand + PrettySubcommand("pretty", + "Dump semantic information about types and symbols"); + +cl::SubCommand DiffSubcommand("diff", "Diff the contents of 2 PDB files"); + +cl::SubCommand + YamlToPdbSubcommand("yaml2pdb", + "Generate a PDB file from a YAML description"); +cl::SubCommand + PdbToYamlSubcommand("pdb2yaml", + "Generate a detailed YAML description of a PDB File"); + +cl::SubCommand + AnalyzeSubcommand("analyze", + "Analyze various aspects of a PDB's structure"); + +cl::SubCommand MergeSubcommand("merge", + "Merge multiple PDBs into a single PDB"); + +cl::OptionCategory TypeCategory("Symbol Type Options"); +cl::OptionCategory FilterCategory("Filtering and Sorting Options"); +cl::OptionCategory OtherOptions("Other Options"); + +namespace pretty { +cl::list InputFilenames(cl::Positional, + cl::desc(""), + cl::OneOrMore, cl::sub(PrettySubcommand)); + +cl::opt Compilands("compilands", cl::desc("Display compilands"), + cl::cat(TypeCategory), cl::sub(PrettySubcommand)); +cl::opt Symbols("module-syms", + cl::desc("Display symbols for each compiland"), + cl::cat(TypeCategory), cl::sub(PrettySubcommand)); +cl::opt Globals("globals", cl::desc("Dump global symbols"), + cl::cat(TypeCategory), cl::sub(PrettySubcommand)); +cl::opt Externals("externals", cl::desc("Dump external symbols"), + cl::cat(TypeCategory), cl::sub(PrettySubcommand)); +cl::list SymTypes( + "sym-types", cl::desc("Type of symbols to dump (default all)"), + cl::cat(TypeCategory), cl::sub(PrettySubcommand), cl::ZeroOrMore, + cl::values( + clEnumValN(SymLevel::Thunks, "thunks", "Display thunk symbols"), + clEnumValN(SymLevel::Data, "data", "Display data symbols"), + clEnumValN(SymLevel::Functions, "funcs", "Display function symbols"), + clEnumValN(SymLevel::All, "all", "Display all symbols (default)"))); + +cl::opt + Types("types", + cl::desc("Display all types (implies -classes, -enums, -typedefs)"), + cl::cat(TypeCategory), cl::sub(PrettySubcommand)); +cl::opt Classes("classes", cl::desc("Display class types"), + cl::cat(TypeCategory), cl::sub(PrettySubcommand)); +cl::opt Enums("enums", cl::desc("Display enum types"), + cl::cat(TypeCategory), cl::sub(PrettySubcommand)); +cl::opt Typedefs("typedefs", cl::desc("Display typedef types"), + cl::cat(TypeCategory), cl::sub(PrettySubcommand)); +cl::opt SymbolOrder( + "symbol-order", cl::desc("symbol sort order"), + cl::init(SymbolSortMode::None), + cl::values(clEnumValN(SymbolSortMode::None, "none", + "Undefined / no particular sort order"), + clEnumValN(SymbolSortMode::Name, "name", "Sort symbols by name"), + clEnumValN(SymbolSortMode::Size, "size", + "Sort symbols by size")), + cl::cat(TypeCategory), cl::sub(PrettySubcommand)); + +cl::opt ClassOrder( + "class-order", cl::desc("Class sort order"), cl::init(ClassSortMode::None), + cl::values( + clEnumValN(ClassSortMode::None, "none", + "Undefined / no particular sort order"), + clEnumValN(ClassSortMode::Name, "name", "Sort classes by name"), + clEnumValN(ClassSortMode::Size, "size", "Sort classes by size"), + clEnumValN(ClassSortMode::Padding, "padding", + "Sort classes by amount of padding"), + clEnumValN(ClassSortMode::PaddingPct, "padding-pct", + "Sort classes by percentage of space consumed by padding"), + clEnumValN(ClassSortMode::PaddingImmediate, "padding-imm", + "Sort classes by amount of immediate padding"), + clEnumValN(ClassSortMode::PaddingPctImmediate, "padding-pct-imm", + "Sort classes by percentage of space consumed by immediate " + "padding")), + cl::cat(TypeCategory), cl::sub(PrettySubcommand)); + +cl::opt ClassFormat( + "class-definitions", cl::desc("Class definition format"), + cl::init(ClassDefinitionFormat::All), + cl::values( + clEnumValN(ClassDefinitionFormat::All, "all", + "Display all class members including data, constants, " + "typedefs, functions, etc"), + clEnumValN(ClassDefinitionFormat::Layout, "layout", + "Only display members that contribute to class size."), + clEnumValN(ClassDefinitionFormat::None, "none", + "Don't display class definitions")), + cl::cat(TypeCategory), cl::sub(PrettySubcommand)); +cl::opt ClassRecursionDepth( + "class-recurse-depth", cl::desc("Class recursion depth (0=no limit)"), + cl::init(0), cl::cat(TypeCategory), cl::sub(PrettySubcommand)); + +cl::opt Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory), + cl::sub(PrettySubcommand)); +cl::opt + All("all", cl::desc("Implies all other options in 'Symbol Types' category"), + cl::cat(TypeCategory), cl::sub(PrettySubcommand)); + +cl::opt LoadAddress( + "load-address", + cl::desc("Assume the module is loaded at the specified address"), + cl::cat(OtherOptions), cl::sub(PrettySubcommand)); +cl::opt Native("native", cl::desc("Use native PDB reader instead of DIA"), + cl::cat(OtherOptions), cl::sub(PrettySubcommand)); +cl::opt + ColorOutput("color-output", + cl::desc("Override use of color (default = isatty)"), + cl::cat(OtherOptions), cl::sub(PrettySubcommand)); +cl::list ExcludeTypes( + "exclude-types", cl::desc("Exclude types by regular expression"), + cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); +cl::list ExcludeSymbols( + "exclude-symbols", cl::desc("Exclude symbols by regular expression"), + cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); +cl::list ExcludeCompilands( + "exclude-compilands", cl::desc("Exclude compilands by regular expression"), + cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); + +cl::list IncludeTypes( + "include-types", + cl::desc("Include only types which match a regular expression"), + cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); +cl::list IncludeSymbols( + "include-symbols", + cl::desc("Include only symbols which match a regular expression"), + cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); +cl::list IncludeCompilands( + "include-compilands", + cl::desc("Include only compilands those which match a regular expression"), + cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand)); +cl::opt SizeThreshold( + "min-type-size", cl::desc("Displays only those types which are greater " + "than or equal to the specified size."), + cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand)); +cl::opt PaddingThreshold( + "min-class-padding", cl::desc("Displays only those classes which have at " + "least the specified amount of padding."), + cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand)); +cl::opt ImmediatePaddingThreshold( + "min-class-padding-imm", + cl::desc("Displays only those classes which have at least the specified " + "amount of immediate padding, ignoring padding internal to bases " + "and aggregates."), + cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand)); + +cl::opt ExcludeCompilerGenerated( + "no-compiler-generated", + cl::desc("Don't show compiler generated types and symbols"), + cl::cat(FilterCategory), cl::sub(PrettySubcommand)); +cl::opt + ExcludeSystemLibraries("no-system-libs", + cl::desc("Don't show symbols from system libraries"), + cl::cat(FilterCategory), cl::sub(PrettySubcommand)); + +cl::opt NoEnumDefs("no-enum-definitions", + cl::desc("Don't display full enum definitions"), + cl::cat(FilterCategory), cl::sub(PrettySubcommand)); +} + +namespace diff { +cl::opt Pedantic("pedantic", + cl::desc("Finds all differences (even structural ones " + "that produce otherwise identical PDBs)"), + cl::sub(DiffSubcommand)); + +cl::list InputFilenames(cl::Positional, + cl::desc(" "), + cl::OneOrMore, cl::sub(DiffSubcommand)); +} + +namespace raw { + +cl::OptionCategory MsfOptions("MSF Container Options"); +cl::OptionCategory TypeOptions("Type Record Options"); +cl::OptionCategory SymbolOptions("Symbol Options"); +cl::OptionCategory MiscOptions("Miscellaneous Options"); + +// MSF OPTIONS +cl::opt DumpHeaders("headers", cl::desc("dump PDB headers"), + cl::cat(MsfOptions), cl::sub(RawSubcommand)); +cl::opt DumpStreamBlocks("stream-blocks", + cl::desc("dump PDB stream blocks"), + cl::cat(MsfOptions), cl::sub(RawSubcommand)); +cl::opt DumpStreamSummary("stream-summary", + cl::desc("dump summary of the PDB streams"), + cl::cat(MsfOptions), cl::sub(RawSubcommand)); +cl::opt DumpPageStats( + "page-stats", + cl::desc("dump allocation stats of the pages in the MSF file"), + cl::cat(MsfOptions), cl::sub(RawSubcommand)); +cl::opt + DumpBlockRangeOpt("block-data", cl::value_desc("start[-end]"), + cl::desc("Dump binary data from specified range."), + cl::cat(MsfOptions), cl::sub(RawSubcommand)); +llvm::Optional DumpBlockRange; + +cl::list + DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore, + cl::desc("Dump binary data from specified streams. Format " + "is SN[:Start][@Size]"), + cl::cat(MsfOptions), cl::sub(RawSubcommand)); + +// TYPE OPTIONS +cl::opt + CompactRecords("compact-records", + cl::desc("Dump type and symbol records with less detail"), + cl::cat(TypeOptions), cl::sub(RawSubcommand)); + +cl::opt + DumpTpiRecords("tpi-records", + cl::desc("dump CodeView type records from TPI stream"), + cl::cat(TypeOptions), cl::sub(RawSubcommand)); +cl::opt DumpTpiRecordBytes( + "tpi-record-bytes", + cl::desc("dump CodeView type record raw bytes from TPI stream"), + cl::cat(TypeOptions), cl::sub(RawSubcommand)); +cl::opt DumpTpiHash("tpi-hash", cl::desc("dump CodeView TPI hash stream"), + cl::cat(TypeOptions), cl::sub(RawSubcommand)); +cl::opt + DumpIpiRecords("ipi-records", + cl::desc("dump CodeView type records from IPI stream"), + cl::cat(TypeOptions), cl::sub(RawSubcommand)); +cl::opt DumpIpiRecordBytes( + "ipi-record-bytes", + cl::desc("dump CodeView type record raw bytes from IPI stream"), + cl::cat(TypeOptions), cl::sub(RawSubcommand)); + +// SYMBOL OPTIONS +cl::opt DumpGlobals("globals", cl::desc("dump globals stream data"), + cl::cat(SymbolOptions), cl::sub(RawSubcommand)); +cl::opt DumpPublics("publics", cl::desc("dump Publics stream data"), + cl::cat(SymbolOptions), cl::sub(RawSubcommand)); +cl::opt + DumpSymRecordBytes("sym-record-bytes", + cl::desc("dump CodeView symbol record raw bytes"), + cl::cat(SymbolOptions), cl::sub(RawSubcommand)); + +// MISCELLANEOUS OPTIONS +cl::opt DumpStringTable("string-table", cl::desc("dump PDB String Table"), + cl::cat(MiscOptions), cl::sub(RawSubcommand)); + +cl::opt DumpSectionContribs("section-contribs", + cl::desc("dump section contributions"), + cl::cat(MiscOptions), cl::sub(RawSubcommand)); +cl::opt DumpSectionMap("section-map", cl::desc("dump section map"), + cl::cat(MiscOptions), cl::sub(RawSubcommand)); +cl::opt DumpSectionHeaders("section-headers", + cl::desc("dump section headers"), + cl::cat(MiscOptions), cl::sub(RawSubcommand)); +cl::opt DumpFpo("fpo", cl::desc("dump FPO records"), cl::cat(MiscOptions), + cl::sub(RawSubcommand)); + +cl::opt RawAll("all", cl::desc("Implies most other options."), + cl::cat(MiscOptions), cl::sub(RawSubcommand)); + +cl::list InputFilenames(cl::Positional, + cl::desc(""), + cl::OneOrMore, cl::sub(RawSubcommand)); +} + +namespace yaml2pdb { +cl::opt + YamlPdbOutputFile("pdb", cl::desc("the name of the PDB file to write"), + cl::sub(YamlToPdbSubcommand)); + +cl::opt InputFilename(cl::Positional, + cl::desc(""), cl::Required, + cl::sub(YamlToPdbSubcommand)); +} + +namespace pdb2yaml { +cl::opt All("all", + cl::desc("Dump everything we know how to dump."), + cl::sub(PdbToYamlSubcommand), cl::init(false)); +cl::opt NoFileHeaders("no-file-headers", + cl::desc("Do not dump MSF file headers"), + cl::sub(PdbToYamlSubcommand), cl::init(false)); +cl::opt Minimal("minimal", + cl::desc("Don't write fields with default values"), + cl::sub(PdbToYamlSubcommand), cl::init(false)); + +cl::opt StreamMetadata( + "stream-metadata", + cl::desc("Dump the number of streams and each stream's size"), + cl::sub(PdbToYamlSubcommand), cl::init(false)); +cl::opt StreamDirectory( + "stream-directory", + cl::desc("Dump each stream's block map (implies -stream-metadata)"), + cl::sub(PdbToYamlSubcommand), cl::init(false)); +cl::opt PdbStream("pdb-stream", + cl::desc("Dump the PDB Stream (Stream 1)"), + cl::sub(PdbToYamlSubcommand), cl::init(false)); + +cl::opt StringTable("string-table", cl::desc("Dump the PDB String Table"), + cl::sub(PdbToYamlSubcommand), cl::init(false)); + +cl::opt DbiStream("dbi-stream", + cl::desc("Dump the DBI Stream Headers (Stream 2)"), + cl::sub(PdbToYamlSubcommand), cl::init(false)); + +cl::opt TpiStream("tpi-stream", + cl::desc("Dump the TPI Stream (Stream 3)"), + cl::sub(PdbToYamlSubcommand), cl::init(false)); + +cl::opt IpiStream("ipi-stream", + cl::desc("Dump the IPI Stream (Stream 5)"), + cl::sub(PdbToYamlSubcommand), cl::init(false)); + +cl::list InputFilename(cl::Positional, + cl::desc(""), cl::Required, + cl::sub(PdbToYamlSubcommand)); +} + +namespace shared { +cl::OptionCategory FileOptions("Module & File Options"); + +// MODULE & FILE OPTIONS +cl::opt DumpModules("modules", cl::desc("dump compiland information"), + cl::cat(FileOptions), cl::sub(RawSubcommand), + cl::sub(PdbToYamlSubcommand)); +cl::opt DumpModuleFiles("module-files", cl::desc("dump file information"), + cl::cat(FileOptions), cl::sub(RawSubcommand), + cl::sub(PdbToYamlSubcommand)); +cl::list DumpModuleSubsections( + "subsections", cl::ZeroOrMore, cl::CommaSeparated, + cl::desc("dump subsections from each module's debug stream"), + cl::values( + clEnumValN( + ModuleSubsection::CrossScopeExports, "cme", + "Cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"), + clEnumValN( + ModuleSubsection::CrossScopeImports, "cmi", + "Cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"), + clEnumValN(ModuleSubsection::FileChecksums, "fc", + "File checksums (DEBUG_S_CHECKSUMS subsection)"), + clEnumValN(ModuleSubsection::InlineeLines, "ilines", + "Inlinee lines (DEBUG_S_INLINEELINES subsection)"), + clEnumValN(ModuleSubsection::Lines, "lines", + "Lines (DEBUG_S_LINES subsection)"), + clEnumValN(ModuleSubsection::StringTable, "strings", + "String Table (DEBUG_S_STRINGTABLE subsection) (not " + "typically present in PDB file)"), + clEnumValN(ModuleSubsection::FrameData, "frames", + "Frame Data (DEBUG_S_FRAMEDATA subsection)"), + clEnumValN(ModuleSubsection::Symbols, "symbols", + "Symbols (DEBUG_S_SYMBOLS subsection) (not typically " + "present in PDB file)"), + clEnumValN(ModuleSubsection::CoffSymbolRVAs, "rvas", + "COFF Symbol RVAs (DEBUG_S_COFF_SYMBOL_RVA subsection)"), + clEnumValN(ModuleSubsection::Unknown, "unknown", + "Any subsection not covered by another option"), + clEnumValN(ModuleSubsection::All, "all", "All known subsections")), + cl::cat(FileOptions), cl::sub(RawSubcommand), cl::sub(PdbToYamlSubcommand)); +cl::opt DumpModuleSyms("module-syms", cl::desc("dump module symbols"), + cl::cat(FileOptions), cl::sub(RawSubcommand), + cl::sub(PdbToYamlSubcommand)); +} // namespace shared + +namespace analyze { +cl::opt StringTable("hash-collisions", cl::desc("Find hash collisions"), + cl::sub(AnalyzeSubcommand), cl::init(false)); +cl::list InputFilename(cl::Positional, + cl::desc(""), cl::Required, + cl::sub(AnalyzeSubcommand)); +} + +namespace merge { +cl::list InputFilenames(cl::Positional, + cl::desc(""), + cl::OneOrMore, cl::sub(MergeSubcommand)); +cl::opt + PdbOutputFile("pdb", cl::desc("the name of the PDB file to write"), + cl::sub(MergeSubcommand)); +} +} + +static ExitOnError ExitOnErr; + +bool opts::checkModuleSubsection(opts::ModuleSubsection MS) { + return any_of(opts::shared::DumpModuleSubsections, + [=](opts::ModuleSubsection M) { + return M == MS || M == opts::ModuleSubsection::All; + }); +} + +static void yamlToPdb(StringRef Path) { + BumpPtrAllocator Allocator; + ErrorOr> ErrorOrBuffer = + MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1, + /*RequiresNullTerminator=*/false); + + if (ErrorOrBuffer.getError()) { + ExitOnErr(make_error(generic_error_code::invalid_path, Path)); + } + + std::unique_ptr &Buffer = ErrorOrBuffer.get(); + + llvm::yaml::Input In(Buffer->getBuffer()); + pdb::yaml::PdbObject YamlObj(Allocator); + In >> YamlObj; + + PDBFileBuilder Builder(Allocator); + + uint32_t BlockSize = 4096; + if (YamlObj.Headers.hasValue()) + BlockSize = YamlObj.Headers->SuperBlock.BlockSize; + ExitOnErr(Builder.initialize(BlockSize)); + // Add each of the reserved streams. We ignore stream metadata in the + // yaml, because we will reconstruct our own view of the streams. For + // example, the YAML may say that there were 20 streams in the original + // PDB, but maybe we only dump a subset of those 20 streams, so we will + // have fewer, and the ones we do have may end up with different indices + // than the ones in the original PDB. So we just start with a clean slate. + for (uint32_t I = 0; I < kSpecialStreamCount; ++I) + ExitOnErr(Builder.getMsfBuilder().addStream(0)); + + if (YamlObj.StringTable.hasValue()) { + auto &Strings = Builder.getStringTableBuilder(); + for (auto S : *YamlObj.StringTable) + Strings.insert(S); + } + + pdb::yaml::PdbInfoStream DefaultInfoStream; + pdb::yaml::PdbDbiStream DefaultDbiStream; + pdb::yaml::PdbTpiStream DefaultTpiStream; + pdb::yaml::PdbTpiStream DefaultIpiStream; + + const auto &Info = YamlObj.PdbStream.getValueOr(DefaultInfoStream); + + auto &InfoBuilder = Builder.getInfoBuilder(); + InfoBuilder.setAge(Info.Age); + InfoBuilder.setGuid(Info.Guid); + InfoBuilder.setSignature(Info.Signature); + InfoBuilder.setVersion(Info.Version); + for (auto F : Info.Features) + InfoBuilder.addFeature(F); + + auto &Strings = Builder.getStringTableBuilder().getStrings(); + + const auto &Dbi = YamlObj.DbiStream.getValueOr(DefaultDbiStream); + auto &DbiBuilder = Builder.getDbiBuilder(); + DbiBuilder.setAge(Dbi.Age); + DbiBuilder.setBuildNumber(Dbi.BuildNumber); + DbiBuilder.setFlags(Dbi.Flags); + DbiBuilder.setMachineType(Dbi.MachineType); + DbiBuilder.setPdbDllRbld(Dbi.PdbDllRbld); + DbiBuilder.setPdbDllVersion(Dbi.PdbDllVersion); + DbiBuilder.setVersionHeader(Dbi.VerHeader); + for (const auto &MI : Dbi.ModInfos) { + auto &ModiBuilder = ExitOnErr(DbiBuilder.addModuleInfo(MI.Mod)); + ModiBuilder.setObjFileName(MI.Obj); + + for (auto S : MI.SourceFiles) + ExitOnErr(DbiBuilder.addModuleSourceFile(MI.Mod, S)); + if (MI.Modi.hasValue()) { + const auto &ModiStream = *MI.Modi; + for (auto Symbol : ModiStream.Symbols) { + ModiBuilder.addSymbol( + Symbol.toCodeViewSymbol(Allocator, CodeViewContainer::Pdb)); + } + } + + auto CodeViewSubsections = ExitOnErr(CodeViewYAML::toCodeViewSubsectionList( + Allocator, MI.Subsections, Strings)); + for (auto &SS : CodeViewSubsections) { + ModiBuilder.addDebugSubsection(std::move(SS)); + } + } + + auto &TpiBuilder = Builder.getTpiBuilder(); + const auto &Tpi = YamlObj.TpiStream.getValueOr(DefaultTpiStream); + TpiBuilder.setVersionHeader(Tpi.Version); + for (const auto &R : Tpi.Records) { + CVType Type = R.toCodeViewRecord(Allocator); + TpiBuilder.addTypeRecord(Type.RecordData, None); + } + + const auto &Ipi = YamlObj.IpiStream.getValueOr(DefaultIpiStream); + auto &IpiBuilder = Builder.getIpiBuilder(); + IpiBuilder.setVersionHeader(Ipi.Version); + for (const auto &R : Ipi.Records) { + CVType Type = R.toCodeViewRecord(Allocator); + IpiBuilder.addTypeRecord(Type.RecordData, None); + } + + ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile)); +} + +static PDBFile &loadPDB(StringRef Path, std::unique_ptr &Session) { + ExitOnErr(loadDataForPDB(PDB_ReaderType::Native, Path, Session)); + + NativeSession *NS = static_cast(Session.get()); + return NS->getPDBFile(); +} + +static void pdb2Yaml(StringRef Path) { + std::unique_ptr Session; + auto &File = loadPDB(Path, Session); + + auto O = llvm::make_unique(File); + O = llvm::make_unique(File); + + ExitOnErr(O->dump()); +} + +static void dumpRaw(StringRef Path) { + std::unique_ptr Session; + auto &File = loadPDB(Path, Session); + + auto O = llvm::make_unique(File); + + ExitOnErr(O->dump()); +} + +static void dumpAnalysis(StringRef Path) { + std::unique_ptr Session; + auto &File = loadPDB(Path, Session); + auto O = llvm::make_unique(File); + + ExitOnErr(O->dump()); +} + +static void diff(StringRef Path1, StringRef Path2) { + std::unique_ptr Session1; + std::unique_ptr Session2; + + auto &File1 = loadPDB(Path1, Session1); + auto &File2 = loadPDB(Path2, Session2); + + auto O = llvm::make_unique(File1, File2); + + ExitOnErr(O->dump()); +} + +bool opts::pretty::shouldDumpSymLevel(SymLevel Search) { + if (SymTypes.empty()) + return true; + if (llvm::find(SymTypes, Search) != SymTypes.end()) + return true; + if (llvm::find(SymTypes, SymLevel::All) != SymTypes.end()) + return true; + return false; +} + +uint32_t llvm::pdb::getTypeLength(const PDBSymbolData &Symbol) { + auto SymbolType = Symbol.getType(); + const IPDBRawSymbol &RawType = SymbolType->getRawSymbol(); + + return RawType.getLength(); +} + +bool opts::pretty::compareFunctionSymbols( + const std::unique_ptr &F1, + const std::unique_ptr &F2) { + assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None); + + if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name) + return F1->getName() < F2->getName(); + + // Note that we intentionally sort in descending order on length, since + // long functions are more interesting than short functions. + return F1->getLength() > F2->getLength(); +} + +bool opts::pretty::compareDataSymbols( + const std::unique_ptr &F1, + const std::unique_ptr &F2) { + assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None); + + if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name) + return F1->getName() < F2->getName(); + + // Note that we intentionally sort in descending order on length, since + // large types are more interesting than short ones. + return getTypeLength(*F1) > getTypeLength(*F2); +} + +static void dumpPretty(StringRef Path) { + std::unique_ptr Session; + + const auto ReaderType = + opts::pretty::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA; + ExitOnErr(loadDataForPDB(ReaderType, Path, Session)); + + if (opts::pretty::LoadAddress) + Session->setLoadAddress(opts::pretty::LoadAddress); + + auto &Stream = outs(); + const bool UseColor = opts::pretty::ColorOutput == cl::BOU_UNSET + ? Stream.has_colors() + : opts::pretty::ColorOutput == cl::BOU_TRUE; + LinePrinter Printer(2, UseColor, Stream); + + auto GlobalScope(Session->getGlobalScope()); + std::string FileName(GlobalScope->getSymbolsFileName()); + + WithColor(Printer, PDB_ColorItem::None).get() << "Summary for "; + WithColor(Printer, PDB_ColorItem::Path).get() << FileName; + Printer.Indent(); + uint64_t FileSize = 0; + + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size"; + if (!sys::fs::file_size(FileName, FileSize)) { + Printer << ": " << FileSize << " bytes"; + } else { + Printer << ": (Unable to obtain file size)"; + } + + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid"; + Printer << ": " << GlobalScope->getGuid(); + + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age"; + Printer << ": " << GlobalScope->getAge(); + + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes"; + Printer << ": "; + if (GlobalScope->hasCTypes()) + outs() << "HasCTypes "; + if (GlobalScope->hasPrivateSymbols()) + outs() << "HasPrivateSymbols "; + Printer.Unindent(); + + if (opts::pretty::Compilands) { + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::SectionHeader).get() + << "---COMPILANDS---"; + Printer.Indent(); + auto Compilands = GlobalScope->findAllChildren(); + CompilandDumper Dumper(Printer); + CompilandDumpFlags options = CompilandDumper::Flags::None; + if (opts::pretty::Lines) + options = options | CompilandDumper::Flags::Lines; + while (auto Compiland = Compilands->getNext()) + Dumper.start(*Compiland, options); + Printer.Unindent(); + } + + if (opts::pretty::Classes || opts::pretty::Enums || opts::pretty::Typedefs) { + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---"; + Printer.Indent(); + TypeDumper Dumper(Printer); + Dumper.start(*GlobalScope); + Printer.Unindent(); + } + + if (opts::pretty::Symbols) { + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---"; + Printer.Indent(); + auto Compilands = GlobalScope->findAllChildren(); + CompilandDumper Dumper(Printer); + while (auto Compiland = Compilands->getNext()) + Dumper.start(*Compiland, true); + Printer.Unindent(); + } + + if (opts::pretty::Globals) { + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---"; + Printer.Indent(); + if (shouldDumpSymLevel(opts::pretty::SymLevel::Functions)) { + FunctionDumper Dumper(Printer); + auto Functions = GlobalScope->findAllChildren(); + if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) { + while (auto Function = Functions->getNext()) { + Printer.NewLine(); + Dumper.start(*Function, FunctionDumper::PointerType::None); + } + } else { + std::vector> Funcs; + while (auto Func = Functions->getNext()) + Funcs.push_back(std::move(Func)); + std::sort(Funcs.begin(), Funcs.end(), + opts::pretty::compareFunctionSymbols); + for (const auto &Func : Funcs) { + Printer.NewLine(); + Dumper.start(*Func, FunctionDumper::PointerType::None); + } + } + } + if (shouldDumpSymLevel(opts::pretty::SymLevel::Data)) { + auto Vars = GlobalScope->findAllChildren(); + VariableDumper Dumper(Printer); + if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) { + while (auto Var = Vars->getNext()) + Dumper.start(*Var); + } else { + std::vector> Datas; + while (auto Var = Vars->getNext()) + Datas.push_back(std::move(Var)); + std::sort(Datas.begin(), Datas.end(), opts::pretty::compareDataSymbols); + for (const auto &Var : Datas) + Dumper.start(*Var); + } + } + if (shouldDumpSymLevel(opts::pretty::SymLevel::Thunks)) { + auto Thunks = GlobalScope->findAllChildren(); + CompilandDumper Dumper(Printer); + while (auto Thunk = Thunks->getNext()) + Dumper.dump(*Thunk); + } + Printer.Unindent(); + } + if (opts::pretty::Externals) { + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---"; + Printer.Indent(); + ExternalSymbolDumper Dumper(Printer); + Dumper.start(*GlobalScope); + } + if (opts::pretty::Lines) { + Printer.NewLine(); + } + outs().flush(); +} + +static void mergePdbs() { + BumpPtrAllocator Allocator; + TypeTableBuilder MergedTpi(Allocator); + TypeTableBuilder MergedIpi(Allocator); + + // Create a Tpi and Ipi type table with all types from all input files. + for (const auto &Path : opts::merge::InputFilenames) { + std::unique_ptr Session; + auto &File = loadPDB(Path, Session); + SmallVector TypeMap; + SmallVector IdMap; + if (File.hasPDBTpiStream()) { + auto &Tpi = ExitOnErr(File.getPDBTpiStream()); + ExitOnErr(codeview::mergeTypeRecords(MergedTpi, TypeMap, nullptr, + Tpi.typeArray())); + } + if (File.hasPDBIpiStream()) { + auto &Ipi = ExitOnErr(File.getPDBIpiStream()); + ExitOnErr(codeview::mergeIdRecords(MergedIpi, TypeMap, IdMap, + Ipi.typeArray())); + } + } + + // Then write the PDB. + PDBFileBuilder Builder(Allocator); + ExitOnErr(Builder.initialize(4096)); + // Add each of the reserved streams. We might not put any data in them, + // but at least they have to be present. + for (uint32_t I = 0; I < kSpecialStreamCount; ++I) + ExitOnErr(Builder.getMsfBuilder().addStream(0)); + + auto &DestTpi = Builder.getTpiBuilder(); + auto &DestIpi = Builder.getIpiBuilder(); + MergedTpi.ForEachRecord([&DestTpi](TypeIndex TI, ArrayRef Data) { + DestTpi.addTypeRecord(Data, None); + }); + MergedIpi.ForEachRecord([&DestIpi](TypeIndex TI, ArrayRef Data) { + DestIpi.addTypeRecord(Data, None); + }); + + SmallString<64> OutFile(opts::merge::PdbOutputFile); + if (OutFile.empty()) { + OutFile = opts::merge::InputFilenames[0]; + llvm::sys::path::replace_extension(OutFile, "merged.pdb"); + } + ExitOnErr(Builder.commit(OutFile)); +} + +int main(int argc_, const char *argv_[]) { + // Print a stack trace if we signal out. + sys::PrintStackTraceOnErrorSignal(argv_[0]); + PrettyStackTraceProgram X(argc_, argv_); + + ExitOnErr.setBanner("llvm-pdbutil: "); + + SmallVector argv; + SpecificBumpPtrAllocator ArgAllocator; + ExitOnErr(errorCodeToError(sys::Process::GetArgumentVector( + argv, makeArrayRef(argv_, argc_), ArgAllocator))); + + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n"); + if (!opts::raw::DumpBlockRangeOpt.empty()) { + llvm::Regex R("^([0-9]+)(-([0-9]+))?$"); + llvm::SmallVector Matches; + if (!R.match(opts::raw::DumpBlockRangeOpt, &Matches)) { + errs() << "Argument '" << opts::raw::DumpBlockRangeOpt + << "' invalid format.\n"; + errs().flush(); + exit(1); + } + opts::raw::DumpBlockRange.emplace(); + Matches[1].getAsInteger(10, opts::raw::DumpBlockRange->Min); + if (!Matches[3].empty()) { + opts::raw::DumpBlockRange->Max.emplace(); + Matches[3].getAsInteger(10, *opts::raw::DumpBlockRange->Max); + } + } + + if ((opts::RawSubcommand && opts::raw::RawAll) || + (opts::PdbToYamlSubcommand && opts::pdb2yaml::All)) { + opts::shared::DumpModules = true; + opts::shared::DumpModuleFiles = true; + opts::shared::DumpModuleSyms = true; + opts::shared::DumpModuleSubsections.push_back(opts::ModuleSubsection::All); + if (llvm::is_contained(opts::shared::DumpModuleSubsections, + opts::ModuleSubsection::All)) { + opts::shared::DumpModuleSubsections.reset(); + opts::shared::DumpModuleSubsections.push_back( + opts::ModuleSubsection::All); + } + } + + if (opts::shared::DumpModuleSyms || opts::shared::DumpModuleFiles) + opts::shared::DumpModules = true; + + if (opts::shared::DumpModules) + opts::pdb2yaml::DbiStream = true; + + if (opts::RawSubcommand) { + if (opts::raw::RawAll) { + opts::raw::DumpHeaders = true; + opts::raw::DumpGlobals = true; + opts::raw::DumpPublics = true; + opts::raw::DumpSectionHeaders = true; + opts::raw::DumpStreamSummary = true; + opts::raw::DumpPageStats = true; + opts::raw::DumpStreamBlocks = true; + opts::raw::DumpTpiRecords = true; + opts::raw::DumpTpiHash = true; + opts::raw::DumpIpiRecords = true; + opts::raw::DumpSectionMap = true; + opts::raw::DumpSectionContribs = true; + opts::raw::DumpFpo = true; + opts::raw::DumpStringTable = true; + } + + if (opts::raw::CompactRecords && + (opts::raw::DumpTpiRecordBytes || opts::raw::DumpIpiRecordBytes)) { + errs() << "-compact-records is incompatible with -tpi-record-bytes and " + "-ipi-record-bytes.\n"; + exit(1); + } + } + if (opts::PdbToYamlSubcommand) { + if (opts::pdb2yaml::All) { + opts::pdb2yaml::StreamMetadata = true; + opts::pdb2yaml::StreamDirectory = true; + opts::pdb2yaml::PdbStream = true; + opts::pdb2yaml::StringTable = true; + opts::pdb2yaml::DbiStream = true; + opts::pdb2yaml::TpiStream = true; + opts::pdb2yaml::IpiStream = true; + } + } + + llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded); + + if (opts::PdbToYamlSubcommand) { + pdb2Yaml(opts::pdb2yaml::InputFilename.front()); + } else if (opts::YamlToPdbSubcommand) { + if (opts::yaml2pdb::YamlPdbOutputFile.empty()) { + SmallString<16> OutputFilename(opts::yaml2pdb::InputFilename.getValue()); + sys::path::replace_extension(OutputFilename, ".pdb"); + opts::yaml2pdb::YamlPdbOutputFile = OutputFilename.str(); + } + yamlToPdb(opts::yaml2pdb::InputFilename); + } else if (opts::AnalyzeSubcommand) { + dumpAnalysis(opts::analyze::InputFilename.front()); + } else if (opts::PrettySubcommand) { + if (opts::pretty::Lines) + opts::pretty::Compilands = true; + + if (opts::pretty::All) { + opts::pretty::Compilands = true; + opts::pretty::Symbols = true; + opts::pretty::Globals = true; + opts::pretty::Types = true; + opts::pretty::Externals = true; + opts::pretty::Lines = true; + } + + if (opts::pretty::Types) { + opts::pretty::Classes = true; + opts::pretty::Typedefs = true; + opts::pretty::Enums = true; + } + + // When adding filters for excluded compilands and types, we need to + // remember that these are regexes. So special characters such as * and \ + // need to be escaped in the regex. In the case of a literal \, this means + // it needs to be escaped again in the C++. So matching a single \ in the + // input requires 4 \es in the C++. + if (opts::pretty::ExcludeCompilerGenerated) { + opts::pretty::ExcludeTypes.push_back("__vc_attributes"); + opts::pretty::ExcludeCompilands.push_back("\\* Linker \\*"); + } + if (opts::pretty::ExcludeSystemLibraries) { + opts::pretty::ExcludeCompilands.push_back( + "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld"); + opts::pretty::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt"); + opts::pretty::ExcludeCompilands.push_back( + "d:\\\\th.obj.x86fre\\\\minkernel"); + } + std::for_each(opts::pretty::InputFilenames.begin(), + opts::pretty::InputFilenames.end(), dumpPretty); + } else if (opts::RawSubcommand) { + std::for_each(opts::raw::InputFilenames.begin(), + opts::raw::InputFilenames.end(), dumpRaw); + } else if (opts::DiffSubcommand) { + if (opts::diff::InputFilenames.size() != 2) { + errs() << "diff subcommand expects exactly 2 arguments.\n"; + exit(1); + } + diff(opts::diff::InputFilenames[0], opts::diff::InputFilenames[1]); + } else if (opts::MergeSubcommand) { + if (opts::merge::InputFilenames.size() < 2) { + errs() << "merge subcommand requires at least 2 input files.\n"; + exit(1); + } + mergePdbs(); + } + + outs().flush(); + return 0; +} diff --git a/tools/llvm-pdbutil/llvm-pdbutil.h b/tools/llvm-pdbutil/llvm-pdbutil.h new file mode 100644 index 000000000000..f1699d0bb557 --- /dev/null +++ b/tools/llvm-pdbutil/llvm-pdbutil.h @@ -0,0 +1,157 @@ +//===- llvm-pdbutil.h ----------------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H +#define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H + +#include "llvm/ADT/Optional.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include + +namespace llvm { +namespace pdb { +class PDBSymbolData; +class PDBSymbolFunc; +uint32_t getTypeLength(const PDBSymbolData &Symbol); +} +} + +namespace opts { + +enum class ModuleSubsection { + Unknown, + Lines, + FileChecksums, + InlineeLines, + CrossScopeImports, + CrossScopeExports, + StringTable, + Symbols, + FrameData, + CoffSymbolRVAs, + All +}; + +bool checkModuleSubsection(ModuleSubsection Kind); + +template +bool checkModuleSubsection(ModuleSubsection K1, ModuleSubsection K2, + Ts &&... Rest) { + return checkModuleSubsection(K1) || + checkModuleSubsection(K2, std::forward(Rest)...); +} + +namespace pretty { + +enum class ClassDefinitionFormat { None, Layout, All }; +enum class ClassSortMode { + None, + Name, + Size, + Padding, + PaddingPct, + PaddingImmediate, + PaddingPctImmediate +}; + +enum class SymbolSortMode { None, Name, Size }; + +enum class SymLevel { Functions, Data, Thunks, All }; + +bool shouldDumpSymLevel(SymLevel Level); +bool compareFunctionSymbols( + const std::unique_ptr &F1, + const std::unique_ptr &F2); +bool compareDataSymbols(const std::unique_ptr &F1, + const std::unique_ptr &F2); + +extern llvm::cl::opt Compilands; +extern llvm::cl::opt Symbols; +extern llvm::cl::opt Globals; +extern llvm::cl::opt Classes; +extern llvm::cl::opt Enums; +extern llvm::cl::opt Typedefs; +extern llvm::cl::opt All; +extern llvm::cl::opt ExcludeCompilerGenerated; + +extern llvm::cl::opt NoEnumDefs; +extern llvm::cl::list ExcludeTypes; +extern llvm::cl::list ExcludeSymbols; +extern llvm::cl::list ExcludeCompilands; +extern llvm::cl::list IncludeTypes; +extern llvm::cl::list IncludeSymbols; +extern llvm::cl::list IncludeCompilands; +extern llvm::cl::opt SymbolOrder; +extern llvm::cl::opt ClassOrder; +extern llvm::cl::opt SizeThreshold; +extern llvm::cl::opt PaddingThreshold; +extern llvm::cl::opt ImmediatePaddingThreshold; +extern llvm::cl::opt ClassFormat; +extern llvm::cl::opt ClassRecursionDepth; +} + +namespace raw { +struct BlockRange { + uint32_t Min; + llvm::Optional Max; +}; + +extern llvm::Optional DumpBlockRange; +extern llvm::cl::list DumpStreamData; + +extern llvm::cl::opt CompactRecords; +extern llvm::cl::opt DumpGlobals; +extern llvm::cl::opt DumpHeaders; +extern llvm::cl::opt DumpStreamBlocks; +extern llvm::cl::opt DumpStreamSummary; +extern llvm::cl::opt DumpPageStats; +extern llvm::cl::opt DumpTpiHash; +extern llvm::cl::opt DumpTpiRecordBytes; +extern llvm::cl::opt DumpTpiRecords; +extern llvm::cl::opt DumpIpiRecords; +extern llvm::cl::opt DumpIpiRecordBytes; +extern llvm::cl::opt DumpPublics; +extern llvm::cl::opt DumpSectionContribs; +extern llvm::cl::opt DumpSectionMap; +extern llvm::cl::opt DumpSymRecordBytes; +extern llvm::cl::opt DumpSectionHeaders; +extern llvm::cl::opt DumpFpo; +extern llvm::cl::opt DumpStringTable; +} + +namespace diff { +extern llvm::cl::opt Pedantic; +} + +namespace pdb2yaml { +extern llvm::cl::opt All; +extern llvm::cl::opt NoFileHeaders; +extern llvm::cl::opt Minimal; +extern llvm::cl::opt StreamMetadata; +extern llvm::cl::opt StreamDirectory; +extern llvm::cl::opt StringTable; +extern llvm::cl::opt PdbStream; +extern llvm::cl::opt DbiStream; +extern llvm::cl::opt TpiStream; +extern llvm::cl::opt IpiStream; +extern llvm::cl::list InputFilename; +} + +namespace shared { +extern llvm::cl::opt DumpModules; +extern llvm::cl::opt DumpModuleFiles; +extern llvm::cl::list DumpModuleSubsections; +extern llvm::cl::opt DumpModuleSyms; +} // namespace shared +} + +#endif diff --git a/tools/llvm-readobj/CMakeLists.txt b/tools/llvm-readobj/CMakeLists.txt index 0ad149538f63..bde486a5f0db 100644 --- a/tools/llvm-readobj/CMakeLists.txt +++ b/tools/llvm-readobj/CMakeLists.txt @@ -1,6 +1,7 @@ set(LLVM_LINK_COMPONENTS DebugInfoCodeView Object + BinaryFormat Support DebugInfoCodeView DebugInfoMSF diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index bc07bd296ad2..6223c09a4ded 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -21,6 +21,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" @@ -45,7 +46,6 @@ #include "llvm/Object/COFF.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/BinaryStreamReader.h" -#include "llvm/Support/COFF.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ConvertUTF.h" diff --git a/tools/llvm-readobj/COFFImportDumper.cpp b/tools/llvm-readobj/COFFImportDumper.cpp index 83715e60f057..c5b8bf758462 100644 --- a/tools/llvm-readobj/COFFImportDumper.cpp +++ b/tools/llvm-readobj/COFFImportDumper.cpp @@ -15,9 +15,9 @@ #include "Error.h" #include "ObjDumper.h" #include "llvm-readobj.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/Object/COFF.h" #include "llvm/Object/COFFImportFile.h" -#include "llvm/Support/COFF.h" using namespace llvm::object; diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 427920569042..116f02f7f154 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -1,4 +1,4 @@ -//===-- ELFDumper.cpp - ELF-specific dumper ---------------------*- C++ -*-===// +//===- ELFDumper.cpp - ELF-specific dumper --------------------------------===// // // The LLVM Compiler Infrastructure // @@ -17,19 +17,44 @@ #include "ObjDumper.h" #include "StackMapPrinter.h" #include "llvm-readobj.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/Object/ELF.h" #include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/ELFTypes.h" +#include "llvm/Object/Error.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/StackMapParser.h" #include "llvm/Support/ARMAttributeParser.h" #include "llvm/Support/ARMBuildAttributes.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MipsABIFlags.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace llvm; using namespace llvm::object; @@ -49,28 +74,28 @@ using namespace ELF; return std::string(#enum).substr(3); #define TYPEDEF_ELF_TYPES(ELFT) \ - typedef ELFFile ELFO; \ - typedef typename ELFO::Elf_Shdr Elf_Shdr; \ - typedef typename ELFO::Elf_Sym Elf_Sym; \ - typedef typename ELFO::Elf_Dyn Elf_Dyn; \ - typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range; \ - typedef typename ELFO::Elf_Rel Elf_Rel; \ - typedef typename ELFO::Elf_Rela Elf_Rela; \ - typedef typename ELFO::Elf_Rel_Range Elf_Rel_Range; \ - typedef typename ELFO::Elf_Rela_Range Elf_Rela_Range; \ - typedef typename ELFO::Elf_Phdr Elf_Phdr; \ - typedef typename ELFO::Elf_Half Elf_Half; \ - typedef typename ELFO::Elf_Ehdr Elf_Ehdr; \ - typedef typename ELFO::Elf_Word Elf_Word; \ - typedef typename ELFO::Elf_Hash Elf_Hash; \ - typedef typename ELFO::Elf_GnuHash Elf_GnuHash; \ - typedef typename ELFO::Elf_Sym_Range Elf_Sym_Range; \ - typedef typename ELFO::Elf_Versym Elf_Versym; \ - typedef typename ELFO::Elf_Verneed Elf_Verneed; \ - typedef typename ELFO::Elf_Vernaux Elf_Vernaux; \ - typedef typename ELFO::Elf_Verdef Elf_Verdef; \ - typedef typename ELFO::Elf_Verdaux Elf_Verdaux; \ - typedef typename ELFO::uintX_t uintX_t; + using ELFO = ELFFile; \ + using Elf_Shdr = typename ELFO::Elf_Shdr; \ + using Elf_Sym = typename ELFO::Elf_Sym; \ + using Elf_Dyn = typename ELFO::Elf_Dyn; \ + using Elf_Dyn_Range = typename ELFO::Elf_Dyn_Range; \ + using Elf_Rel = typename ELFO::Elf_Rel; \ + using Elf_Rela = typename ELFO::Elf_Rela; \ + using Elf_Rel_Range = typename ELFO::Elf_Rel_Range; \ + using Elf_Rela_Range = typename ELFO::Elf_Rela_Range; \ + using Elf_Phdr = typename ELFO::Elf_Phdr; \ + using Elf_Half = typename ELFO::Elf_Half; \ + using Elf_Ehdr = typename ELFO::Elf_Ehdr; \ + using Elf_Word = typename ELFO::Elf_Word; \ + using Elf_Hash = typename ELFO::Elf_Hash; \ + using Elf_GnuHash = typename ELFO::Elf_GnuHash; \ + using Elf_Sym_Range = typename ELFO::Elf_Sym_Range; \ + using Elf_Versym = typename ELFO::Elf_Versym; \ + using Elf_Verneed = typename ELFO::Elf_Verneed; \ + using Elf_Vernaux = typename ELFO::Elf_Vernaux; \ + using Elf_Verdef = typename ELFO::Elf_Verdef; \ + using Elf_Verdaux = typename ELFO::Elf_Verdaux; \ + using uintX_t = typename ELFO::uintX_t; namespace { @@ -81,15 +106,16 @@ template class DumpStyle; /// the size, entity size and virtual address are different entries in arbitrary /// order (DT_REL, DT_RELSZ, DT_RELENT for example). struct DynRegionInfo { - DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {} + DynRegionInfo() = default; DynRegionInfo(const void *A, uint64_t S, uint64_t ES) : Addr(A), Size(S), EntSize(ES) {} + /// \brief Address in current address space. - const void *Addr; + const void *Addr = nullptr; /// \brief Size in bytes of the region. - uint64_t Size; + uint64_t Size = 0; /// \brief Size of each entity in the region. - uint64_t EntSize; + uint64_t EntSize = 0; template ArrayRef getAsArrayRef() const { const Type *Start = reinterpret_cast(Addr); @@ -139,6 +165,7 @@ public: private: std::unique_ptr> ELFDumperStyle; + TYPEDEF_ELF_TYPES(ELFT) DynRegionInfo checkDRI(DynRegionInfo DRI) { @@ -196,6 +223,7 @@ private: : PointerIntPair(verdef, 0) {} VersionMapEntry(const Elf_Vernaux *vernaux) : PointerIntPair(vernaux, 1) {} + bool isNull() const { return getPointer() == nullptr; } bool isVerdef() const { return !isNull() && getInt() == 0; } bool isVernaux() const { return !isNull() && getInt() == 1; } @@ -262,10 +290,11 @@ void ELFDumper::printSymbolsHelper(bool IsDynamic) const { template class DumpStyle { public: using Elf_Shdr = typename ELFFile::Elf_Shdr; - using Elf_Sym = typename ELFFile::Elf_Sym; + using Elf_Sym = typename ELFFile::Elf_Sym; DumpStyle(ELFDumper *Dumper) : Dumper(Dumper) {} - virtual ~DumpStyle() {} + virtual ~DumpStyle() = default; + virtual void printFileHeaders(const ELFFile *Obj) = 0; virtual void printGroupSections(const ELFFile *Obj) = 0; virtual void printRelocations(const ELFFile *Obj) = 0; @@ -274,9 +303,7 @@ public: virtual void printDynamicSymbols(const ELFFile *Obj) = 0; virtual void printDynamicRelocations(const ELFFile *Obj) = 0; virtual void printSymtabMessage(const ELFFile *obj, StringRef Name, - size_t Offset) { - return; - } + size_t Offset) {} virtual void printSymbol(const ELFFile *Obj, const Elf_Sym *Symbol, const Elf_Sym *FirstSym, StringRef StrTable, bool IsDynamic) = 0; @@ -284,16 +311,20 @@ public: virtual void printHashHistogram(const ELFFile *Obj) = 0; virtual void printNotes(const ELFFile *Obj) = 0; const ELFDumper *dumper() const { return Dumper; } + private: const ELFDumper *Dumper; }; template class GNUStyle : public DumpStyle { formatted_raw_ostream OS; + public: TYPEDEF_ELF_TYPES(ELFT) + GNUStyle(ScopedPrinter &W, ELFDumper *Dumper) : DumpStyle(Dumper), OS(W.getOStream()) {} + void printFileHeaders(const ELFO *Obj) override; void printGroupSections(const ELFFile *Obj) override; void printRelocations(const ELFO *Obj) override; @@ -301,8 +332,8 @@ public: void printSymbols(const ELFO *Obj) override; void printDynamicSymbols(const ELFO *Obj) override; void printDynamicRelocations(const ELFO *Obj) override; - virtual void printSymtabMessage(const ELFO *Obj, StringRef Name, - size_t Offset) override; + void printSymtabMessage(const ELFO *Obj, StringRef Name, + size_t Offset) override; void printProgramHeaders(const ELFO *Obj) override; void printHashHistogram(const ELFFile *Obj) override; void printNotes(const ELFFile *Obj) override; @@ -311,6 +342,7 @@ private: struct Field { StringRef Str; unsigned Column; + Field(StringRef S, unsigned Col) : Str(S), Column(Col) {} Field(unsigned Col) : Str(""), Column(Col) {} }; @@ -348,6 +380,7 @@ private: template class LLVMStyle : public DumpStyle { public: TYPEDEF_ELF_TYPES(ELFT) + LLVMStyle(ScopedPrinter &W, ELFDumper *Dumper) : DumpStyle(Dumper), W(W) {} @@ -368,10 +401,11 @@ private: void printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel); void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First, StringRef StrTable, bool IsDynamic) override; + ScopedPrinter &W; }; -} // namespace +} // end anonymous namespace namespace llvm { @@ -405,7 +439,7 @@ std::error_code createELFDumper(const object::ObjectFile *Obj, return readobj_error::unsupported_obj_file_format; } -} // namespace llvm +} // end namespace llvm // Iterate through the versions needed section, and place each Elf_Vernaux // in the VersionMap according to its index. @@ -525,8 +559,8 @@ static void printVersionDefinitionSection(ELFDumper *Dumper, const ELFO *Obj, const typename ELFO::Elf_Shdr *Sec, ScopedPrinter &W) { - typedef typename ELFO::Elf_Verdef VerDef; - typedef typename ELFO::Elf_Verdaux VerdAux; + using VerDef = typename ELFO::Elf_Verdef; + using VerdAux = typename ELFO::Elf_Verdaux; DictScope SD(W, "SHT_GNU_verdef"); if (!Sec) @@ -581,8 +615,8 @@ static void printVersionDependencySection(ELFDumper *Dumper, const ELFO *Obj, const typename ELFO::Elf_Shdr *Sec, ScopedPrinter &W) { - typedef typename ELFO::Elf_Verneed VerNeed; - typedef typename ELFO::Elf_Vernaux VernAux; + using VerNeed = typename ELFO::Elf_Verneed; + using VernAux = typename ELFO::Elf_Vernaux; DictScope SD(W, "SHT_GNU_verneed"); if (!Sec) @@ -978,9 +1012,7 @@ static const EnumEntry ElfSymbolTypes[] = { {"GNU_IFunc", "IFUNC", ELF::STT_GNU_IFUNC}}; static const EnumEntry AMDGPUSymbolTypes[] = { - { "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL }, - { "AMDGPU_HSA_INDIRECT_FUNCTION", ELF::STT_AMDGPU_HSA_INDIRECT_FUNCTION }, - { "AMDGPU_HSA_METADATA", ELF::STT_AMDGPU_HSA_METADATA } + { "AMDGPU_HSA_KERNEL", ELF::STT_AMDGPU_HSA_KERNEL } }; static const char *getGroupType(uint32_t Flag) { @@ -1012,13 +1044,6 @@ static const EnumEntry ElfXCoreSectionFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, XCORE_SHF_DP_SECTION) }; -static const EnumEntry ElfAMDGPUSectionFlags[] = { - LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_GLOBAL), - LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_READONLY), - LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_CODE), - LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_AGENT) -}; - static const EnumEntry ElfARMSectionFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, SHF_ARM_PURECODE) }; @@ -1077,13 +1102,6 @@ static const char *getElfSegmentType(unsigned Arch, unsigned Type) { // Check potentially overlapped processor-specific // program header type. switch (Arch) { - case ELF::EM_AMDGPU: - switch (Type) { - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM); - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_AGENT); - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_READONLY_AGENT); - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_CODE_AGENT); - } case ELF::EM_ARM: switch (Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_ARM_EXIDX); @@ -1139,14 +1157,6 @@ static std::string getElfPtType(unsigned Arch, unsigned Type) { default: // All machine specific PT_* types switch (Arch) { - case ELF::EM_AMDGPU: - switch (Type) { - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM); - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_GLOBAL_AGENT); - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_READONLY_AGENT); - LLVM_READOBJ_ENUM_CASE(ELF, PT_AMDGPU_HSA_LOAD_CODE_AGENT); - } - return ""; case ELF::EM_ARM: if (Type == ELF::PT_ARM_EXIDX) return "EXIDX"; @@ -1262,7 +1272,6 @@ static const char *getElfMipsOptionsOdkType(unsigned Odk) { template ELFDumper::ELFDumper(const ELFFile *Obj, ScopedPrinter &Writer) : ObjDumper(Writer), Obj(Obj) { - SmallVector LoadSegments; for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { if (Phdr.p_type == ELF::PT_DYNAMIC) { @@ -1591,8 +1600,8 @@ static const EnumEntry ElfDynamicDTMipsFlags[] = { template void printFlags(T Value, ArrayRef> Flags, raw_ostream &OS) { - typedef EnumEntry FlagEntry; - typedef SmallVector FlagVector; + using FlagEntry = EnumEntry; + using FlagVector = SmallVector; FlagVector SetFlags; for (const auto &Flag : Flags) { @@ -1711,6 +1720,7 @@ void ELFDumper::printUnwindInfo() { } namespace { + template <> void ELFDumper>::printUnwindInfo() { const unsigned Machine = Obj->getHeader()->e_machine; if (Machine == EM_ARM) { @@ -1720,7 +1730,8 @@ template <> void ELFDumper>::printUnwindInfo() { } W.startLine() << "UnwindInfo not implemented.\n"; } -} + +} // end anonymous namespace template void ELFDumper::printDynamicTable() { @@ -1766,7 +1777,7 @@ template void ELFDumper::printNeededLibraries() { ListScope D(W, "NeededLibraries"); - typedef std::vector LibsTy; + using LibsTy = std::vector; LibsTy Libs; for (const auto &Entry : dynamic_table()) @@ -1820,6 +1831,7 @@ void ELFDumper::printAttributes() { } namespace { + template <> void ELFDumper>::printAttributes() { if (Obj->getHeader()->e_machine != EM_ARM) { W.startLine() << "Attributes not implemented.\n"; @@ -1845,13 +1857,12 @@ template <> void ELFDumper>::printAttributes() { ARMAttributeParser(&W).Parse(Contents, true); } } -} -namespace { template class MipsGOTParser { public: TYPEDEF_ELF_TYPES(ELFT) - typedef typename ELFO::Elf_Addr GOTEntry; + using GOTEntry = typename ELFO::Elf_Addr; + MipsGOTParser(ELFDumper *Dumper, const ELFO *Obj, Elf_Dyn_Range DynTable, ScopedPrinter &W); @@ -1862,11 +1873,11 @@ private: ELFDumper *Dumper; const ELFO *Obj; ScopedPrinter &W; - llvm::Optional DtPltGot; - llvm::Optional DtLocalGotNum; - llvm::Optional DtGotSym; - llvm::Optional DtMipsPltGot; - llvm::Optional DtJmpRel; + Optional DtPltGot; + Optional DtLocalGotNum; + Optional DtGotSym; + Optional DtMipsPltGot; + Optional DtJmpRel; std::size_t getGOTTotal(ArrayRef GOT) const; const GOTEntry *makeGOTIter(ArrayRef GOT, std::size_t EntryNum); @@ -1882,7 +1893,8 @@ private: const GOTEntry *It, StringRef StrTable, const Elf_Sym *Sym); }; -} + +} // end anonymous namespace template MipsGOTParser::MipsGOTParser(ELFDumper *Dumper, const ELFO *Obj, @@ -2353,8 +2365,8 @@ template void ELFDumper::printStackMap() const { ArrayRef StackMapContentsArray = unwrapOrError(Obj->getSectionContents(StackMapSection)); - prettyPrintStackMap(llvm::outs(), StackMapV2Parser( - StackMapContentsArray)); + prettyPrintStackMap(outs(), StackMapV2Parser( + StackMapContentsArray)); } template void ELFDumper::printGroupSections() { @@ -2455,7 +2467,7 @@ template void GNUStyle::printGroupSections(const ELFO *Obj) { template void GNUStyle::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, const Elf_Rela &R, bool IsRela) { - std::string Offset, Info, Addend = "", Value; + std::string Offset, Info, Addend, Value; SmallString<32> RelocName; StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab)); StringRef TargetName; @@ -2549,6 +2561,7 @@ template void GNUStyle::printRelocations(const ELFO *Obj) { std::string getSectionTypeString(unsigned Arch, unsigned Type) { using namespace ELF; + switch (Arch) { case EM_ARM: switch (Type) { @@ -2715,7 +2728,7 @@ template void GNUStyle::printSections(const ELFO *Obj) { template void GNUStyle::printSymtabMessage(const ELFO *Obj, StringRef Name, size_t Entries) { - if (Name.size()) + if (!Name.empty()) OS << "\nSymbol table '" << Name << "' contains " << Entries << " entries:\n"; else @@ -2870,7 +2883,7 @@ template void GNUStyle::printSymbols(const ELFO *Obj) { template void GNUStyle::printDynamicSymbols(const ELFO *Obj) { - if (this->dumper()->getDynamicStringTable().size() == 0) + if (this->dumper()->getDynamicStringTable().empty()) return; auto StringTable = this->dumper()->getDynamicStringTable(); auto DynSyms = this->dumper()->dynamic_symbols(); @@ -3084,19 +3097,19 @@ void GNUStyle::printDynamicRelocation(const ELFO *Obj, Elf_Rela R, Obj->getRelocationTypeName(R.getType(Obj->isMips64EL()), RelocName); SymbolName = unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable())); - std::string Addend = "", Info, Offset, Value; + std::string Addend, Info, Offset, Value; Offset = to_string(format_hex_no_prefix(R.r_offset, Width)); Info = to_string(format_hex_no_prefix(R.r_info, Width)); Value = to_string(format_hex_no_prefix(Sym->getValue(), Width)); int64_t RelAddend = R.r_addend; - if (SymbolName.size() && IsRela) { + if (!SymbolName.empty() && IsRela) { if (R.r_addend < 0) Addend = " - "; else Addend = " + "; } - if (!SymbolName.size() && Sym->getValue() == 0) + if (SymbolName.empty() && Sym->getValue() == 0) Value = ""; if (IsRela) @@ -3231,7 +3244,7 @@ void GNUStyle::printHashHistogram(const ELFFile *Obj) { size_t MaxChain = 1; size_t CumulativeNonZero = 0; - if (Chains.size() == 0 || NBucket == 0) + if (Chains.empty() || NBucket == 0) return; std::vector ChainLen(NBucket, 0); @@ -3562,13 +3575,13 @@ void LLVMStyle::printRelocation(const ELFO *Obj, Elf_Rela Rel, DictScope Group(W, "Relocation"); W.printHex("Offset", Rel.r_offset); W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); - W.printNumber("Symbol", TargetName.size() > 0 ? TargetName : "-", + W.printNumber("Symbol", !TargetName.empty() ? TargetName : "-", Rel.getSymbol(Obj->isMips64EL())); W.printHex("Addend", Rel.r_addend); } else { raw_ostream &OS = W.startLine(); OS << W.hex(Rel.r_offset) << " " << RelocName << " " - << (TargetName.size() > 0 ? TargetName : "-") << " " + << (!TargetName.empty() ? TargetName : "-") << " " << W.hex(Rel.r_addend) << "\n"; } } @@ -3592,10 +3605,6 @@ template void LLVMStyle::printSections(const ELFO *Obj) { std::vector> SectionFlags(std::begin(ElfSectionFlags), std::end(ElfSectionFlags)); switch (Obj->getHeader()->e_machine) { - case EM_AMDGPU: - SectionFlags.insert(SectionFlags.end(), std::begin(ElfAMDGPUSectionFlags), - std::end(ElfAMDGPUSectionFlags)); - break; case EM_ARM: SectionFlags.insert(SectionFlags.end(), std::begin(ElfARMSectionFlags), std::end(ElfARMSectionFlags)); @@ -3763,12 +3772,12 @@ void LLVMStyle::printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel) { DictScope Group(W, "Relocation"); W.printHex("Offset", Rel.r_offset); W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); - W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); + W.printString("Symbol", !SymbolName.empty() ? SymbolName : "-"); W.printHex("Addend", Rel.r_addend); } else { raw_ostream &OS = W.startLine(); OS << W.hex(Rel.r_offset) << " " << RelocName << " " - << (SymbolName.size() > 0 ? SymbolName : "-") << " " + << (!SymbolName.empty() ? SymbolName : "-") << " " << W.hex(Rel.r_addend) << "\n"; } } @@ -3801,4 +3810,3 @@ template void LLVMStyle::printNotes(const ELFFile *Obj) { W.startLine() << "printNotes not implemented!\n"; } - diff --git a/tools/llvm-readobj/LLVMBuild.txt b/tools/llvm-readobj/LLVMBuild.txt index c0ed38e18d0c..87ede1008cb3 100644 --- a/tools/llvm-readobj/LLVMBuild.txt +++ b/tools/llvm-readobj/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Tool name = llvm-readobj parent = Tools -required_libraries = all-targets BitReader Object DebugInfoCodeView DebugInfoPDB DebugInfoMSF +required_libraries = all-targets BitReader Object BinaryFormat DebugInfoCodeView DebugInfoPDB DebugInfoMSF diff --git a/tools/llvm-stress/llvm-stress.cpp b/tools/llvm-stress/llvm-stress.cpp index 74b7735f8cd1..f1cdc5fa1056 100644 --- a/tools/llvm-stress/llvm-stress.cpp +++ b/tools/llvm-stress/llvm-stress.cpp @@ -382,6 +382,7 @@ struct ConstModifier: public Modifier { switch (Ran->Rand() % 2) { case 0: if (Ty->getScalarType()->isIntegerTy()) return PT->push_back(ConstantVector::getAllOnesValue(Ty)); + llvm_unreachable("Unexpected state"); case 1: if (Ty->getScalarType()->isIntegerTy()) return PT->push_back(ConstantVector::getNullValue(Ty)); } @@ -407,9 +408,11 @@ struct ConstModifier: public Modifier { case 0: if (Ty->isIntegerTy()) return PT->push_back(ConstantInt::get(Ty, APInt::getAllOnesValue(Ty->getPrimitiveSizeInBits()))); + llvm_unreachable("Unexpected state"); case 1: if (Ty->isIntegerTy()) return PT->push_back(ConstantInt::get(Ty, APInt::getNullValue(Ty->getPrimitiveSizeInBits()))); + llvm_unreachable("Unexpected state"); case 2: case 3: case 4: case 5: case 6: if (Ty->isIntegerTy()) PT->push_back(ConstantInt::get(Ty, Ran->Rand())); diff --git a/tools/llvm-xray/xray-extract.cc b/tools/llvm-xray/xray-extract.cc index d7015a05b0f2..6b72b81ab814 100644 --- a/tools/llvm-xray/xray-extract.cc +++ b/tools/llvm-xray/xray-extract.cc @@ -18,11 +18,11 @@ #include "func-id-helper.h" #include "xray-registry.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/Object/ELF.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/DataExtractor.h" -#include "llvm/Support/ELF.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" diff --git a/tools/obj2yaml/dwarf2yaml.cpp b/tools/obj2yaml/dwarf2yaml.cpp index d41b44c06810..d97eda30c039 100644 --- a/tools/obj2yaml/dwarf2yaml.cpp +++ b/tools/obj2yaml/dwarf2yaml.cpp @@ -203,6 +203,7 @@ void dumpDebugInfo(DWARFContextInMemory &DCtx, DWARFYAML::Data &Y) { case dwarf::DW_FORM_line_strp: case dwarf::DW_FORM_strp_sup: case dwarf::DW_FORM_GNU_str_index: + case dwarf::DW_FORM_strx: if (auto Val = FormValue.getValue().getAsCStringOffset()) NewValue.Value = Val.getValue(); break; diff --git a/tools/obj2yaml/macho2yaml.cpp b/tools/obj2yaml/macho2yaml.cpp index f7b6c4748d5e..a1d107dc5afb 100644 --- a/tools/obj2yaml/macho2yaml.cpp +++ b/tools/obj2yaml/macho2yaml.cpp @@ -216,7 +216,7 @@ void MachODumper::dumpLoadCommands(std::unique_ptr &Y) { MachO::swapStruct(LC.Data.load_command_data); EndPtr = processLoadCommandData(LC, LoadCmd); break; -#include "llvm/Support/MachO.def" +#include "llvm/BinaryFormat/MachO.def" } auto RemainingBytes = LoadCmd.C.cmdsize - (EndPtr - LoadCmd.Ptr); if (!std::all_of(EndPtr, &EndPtr[RemainingBytes], diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp index 8fd2bfd16726..c89f768ed6ff 100644 --- a/tools/yaml2obj/yaml2elf.cpp +++ b/tools/yaml2obj/yaml2elf.cpp @@ -14,10 +14,10 @@ #include "yaml2obj.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/ObjectYAML/ELFYAML.h" -#include "llvm/Support/ELF.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" diff --git a/tools/yaml2obj/yaml2macho.cpp b/tools/yaml2obj/yaml2macho.cpp index 92b736e5298e..34b6ac2029fc 100644 --- a/tools/yaml2obj/yaml2macho.cpp +++ b/tools/yaml2obj/yaml2macho.cpp @@ -13,11 +13,11 @@ //===----------------------------------------------------------------------===// #include "yaml2obj.h" -#include "llvm/ObjectYAML/ObjectYAML.h" +#include "llvm/BinaryFormat/MachO.h" #include "llvm/ObjectYAML/DWARFEmitter.h" +#include "llvm/ObjectYAML/ObjectYAML.h" #include "llvm/Support/Error.h" #include "llvm/Support/LEB128.h" -#include "llvm/Support/MachO.h" #include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" @@ -239,7 +239,7 @@ Error MachOWriter::writeLoadCommands(raw_ostream &OS) { BytesWritten += writeLoadCommandData(LC, OS, Obj.IsLittleEndian); break; -#include "llvm/Support/MachO.def" +#include "llvm/BinaryFormat/MachO.def" } if (LC.PayloadBytes.size() > 0) { -- cgit v1.2.3