From e32b7636e7e2fb85ba737abb1224681776d0afc8 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Wed, 28 Jan 2015 00:33:00 +0000 Subject: [PATCH] [llvm-pdbdump] Add support for printing source files and compilands. This adds two command line options to llvm-pdbdump. --source-files prints a flat list of all source files in the PDB. --compilands prints a list of all compilands (e.g. object files) that the PDB knows about, and for each one, a list of source files that the compiland is composed of as well as a hash of the original source file. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@227276 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/llvm-pdbdump/DIAExtras.cpp | 13 +++ tools/llvm-pdbdump/DIAExtras.h | 4 + tools/llvm-pdbdump/llvm-pdbdump.cpp | 137 +++++++++++++++++++++++++++- 3 files changed, 149 insertions(+), 5 deletions(-) diff --git a/tools/llvm-pdbdump/DIAExtras.cpp b/tools/llvm-pdbdump/DIAExtras.cpp index 68c7e57faed..f08c42efc72 100644 --- a/tools/llvm-pdbdump/DIAExtras.cpp +++ b/tools/llvm-pdbdump/DIAExtras.cpp @@ -174,3 +174,16 @@ raw_ostream &llvm::operator<<(raw_ostream &Stream, outs() << " {" << llvm::format_hex((DWORD)MachineType, 2, true) << "}"; return Stream; } + +raw_ostream &llvm::operator<<(raw_ostream &Stream, HashAlgorithm Algorithm) { + switch (Algorithm) { + PRINT_ENUM_VALUE_CASE(HashNone, "None") + PRINT_ENUM_VALUE_CASE(HashMD5, "MD5") + PRINT_ENUM_VALUE_CASE(HashSHA1, "SHA-1") + default: + outs() << "(Unknown)"; + break; + } + outs() << " {" << (DWORD)Algorithm << "}"; + return Stream; +} diff --git a/tools/llvm-pdbdump/DIAExtras.h b/tools/llvm-pdbdump/DIAExtras.h index 6561a09b74f..aeef1972dc2 100644 --- a/tools/llvm-pdbdump/DIAExtras.h +++ b/tools/llvm-pdbdump/DIAExtras.h @@ -102,6 +102,8 @@ enum MachineTypeEnum { MachineTypeCEE = IMAGE_FILE_MACHINE_CEE, }; +enum HashAlgorithm { HashNone = 0, HashMD5 = 1, HashSHA1 = 2 }; + // SymTagEnum has the unfortunate property that it is not only the name of // the enum, but also the name of one of the values of the enum. So that we // don't have to always type "enum SymTagEnum", we typedef this to a different @@ -122,6 +124,8 @@ raw_ostream &operator<<(raw_ostream &Stream, raw_ostream &operator<<(raw_ostream &Stream, CV_CPU_TYPE_e CpuType); raw_ostream &operator<<(raw_ostream &Stream, llvm::sys::windows::MachineTypeEnum CpuType); +raw_ostream &operator<<(raw_ostream &Stream, + llvm::sys::windows::HashAlgorithm Algorithm); } #endif diff --git a/tools/llvm-pdbdump/llvm-pdbdump.cpp b/tools/llvm-pdbdump/llvm-pdbdump.cpp index 855691ce255..89f885b574e 100644 --- a/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -51,6 +51,37 @@ cl::opt Tables("tables", "debug tables in the input file")); cl::alias TablesShort("t", cl::desc("Alias for --tables"), cl::aliasopt(Tables)); + +cl::opt SourceFiles("source-files", + cl::desc("Display a list of the source files " + "contained in the PDB")); +cl::alias SourceFilesShort("f", cl::desc("Alias for --source-files"), + cl::aliasopt(SourceFiles)); + +cl::opt Compilands("compilands", + cl::desc("Display a list of compilands (e.g. object " + "files) and their source file composition")); +cl::alias CompilandsShort("c", cl::desc("Alias for --compilands"), + cl::aliasopt(Compilands)); +} + +template +static HRESULT GetDiaTable(IDiaSession *Session, TableType **Table) { + CComPtr EnumTables = nullptr; + HRESULT Error = S_OK; + if (FAILED(Error = Session->getEnumTables(&EnumTables))) + return Error; + + for (auto CurTable : make_com_enumerator(EnumTables)) { + TableType *ResultTable = nullptr; + if (FAILED(CurTable->QueryInterface( + __uuidof(TableType), reinterpret_cast(&ResultTable)))) + continue; + + *Table = ResultTable; + return S_OK; + } + return E_FAIL; } static void dumpBasicFileInfo(StringRef Path, IDiaSession *Session) { @@ -161,6 +192,94 @@ static void dumpDebugTables(IDiaSession *Session) { outs().flush(); } +static void dumpSourceFiles(IDiaSession *Session) { + CComPtr EnumSourceFileList; + if (FAILED(GetDiaTable(Session, &EnumSourceFileList))) + return; + + LONG SourceFileCount = 0; + EnumSourceFileList->get_Count(&SourceFileCount); + + outs() << "Dumping source files [" << SourceFileCount << " files]\n"; + for (auto SourceFile : make_com_enumerator(EnumSourceFileList)) { + CComBSTR SourceFileName; + if (S_OK != SourceFile->get_fileName(&SourceFileName)) + continue; + outs().indent(2); + std::string SourceFileName8; + BSTRToUTF8(SourceFileName, SourceFileName8); + outs() << SourceFileName8 << "\n"; + } + outs() << "\n"; + outs().flush(); +} + +static void dumpCompilands(IDiaSession *Session) { + CComPtr EnumSourceFileList; + if (FAILED(GetDiaTable(Session, &EnumSourceFileList))) + return; + + LONG SourceFileCount = 0; + EnumSourceFileList->get_Count(&SourceFileCount); + + CComPtr GlobalScope; + HRESULT hr = Session->get_globalScope(&GlobalScope); + DIASymbol GlobalScopeSymbol(GlobalScope); + if (S_OK != hr) + return; + + CComPtr EnumCompilands; + if (S_OK != + GlobalScope->findChildren(SymTagCompiland, nullptr, nsNone, + &EnumCompilands)) + return; + + LONG CompilandCount = 0; + EnumCompilands->get_Count(&CompilandCount); + outs() << "Dumping compilands [" << CompilandCount + << " compilands containing " << SourceFileCount << " source files]\n"; + + for (auto Compiland : make_com_enumerator(EnumCompilands)) { + DIASymbol CompilandSymbol(Compiland); + outs().indent(2); + outs() << CompilandSymbol.getName().value() << "\n"; + + CComPtr EnumFiles; + if (S_OK != Session->findFile(Compiland, nullptr, nsNone, &EnumFiles)) + continue; + + for (auto SourceFile : make_com_enumerator(EnumFiles)) { + DWORD ChecksumType = 0; + DWORD ChecksumSize = 0; + std::vector Checksum; + outs().indent(4); + SourceFile->get_checksumType(&ChecksumType); + if (S_OK == SourceFile->get_checksum(0, &ChecksumSize, nullptr)) { + Checksum.resize(ChecksumSize); + if (S_OK == + SourceFile->get_checksum(ChecksumSize, &ChecksumSize, + &Checksum[0])) { + outs() << "[" << ((ChecksumType == HashMD5) ? "MD5 " : "SHA-1") + << ": "; + for (auto byte : Checksum) + outs() << format_hex_no_prefix(byte, 2, true); + outs() << "] "; + } + } + CComBSTR SourceFileName; + if (S_OK != SourceFile->get_fileName(&SourceFileName)) + continue; + + std::string SourceFileName8; + BSTRToUTF8(SourceFileName, SourceFileName8); + outs() << SourceFileName8 << "\n"; + } + } + + outs() << "\n"; + outs().flush(); +} + static void dumpInput(StringRef Path) { SmallVector Path16String; llvm::convertUTF8ToUTF16String(Path, Path16String); @@ -173,17 +292,25 @@ static void dumpInput(StringRef Path) { return; if (FAILED(source->loadDataFromPdb(Path16))) return; - CComPtr session; - if (FAILED(source->openSession(&session))) + CComPtr Session; + if (FAILED(source->openSession(&Session))) return; - dumpBasicFileInfo(Path, session); + dumpBasicFileInfo(Path, Session); if (opts::Streams || opts::StreamData) { - dumpDataStreams(session); + dumpDataStreams(Session); } if (opts::Tables) { - dumpDebugTables(session); + dumpDebugTables(Session); + } + + if (opts::SourceFiles) { + dumpSourceFiles(Session); + } + + if (opts::Compilands) { + dumpCompilands(Session); } } -- 2.34.1