[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
This commit is contained in:
Zachary Turner 2015-01-28 00:33:00 +00:00
parent 63f47de72c
commit e32b7636e7
3 changed files with 149 additions and 5 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -51,6 +51,37 @@ cl::opt<bool> Tables("tables",
"debug tables in the input file"));
cl::alias TablesShort("t", cl::desc("Alias for --tables"),
cl::aliasopt(Tables));
cl::opt<bool> 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<bool> 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 <typename TableType>
static HRESULT GetDiaTable(IDiaSession *Session, TableType **Table) {
CComPtr<IDiaEnumTables> 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<void **>(&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<IDiaEnumSourceFiles> 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<IDiaEnumSourceFiles> EnumSourceFileList;
if (FAILED(GetDiaTable(Session, &EnumSourceFileList)))
return;
LONG SourceFileCount = 0;
EnumSourceFileList->get_Count(&SourceFileCount);
CComPtr<IDiaSymbol> GlobalScope;
HRESULT hr = Session->get_globalScope(&GlobalScope);
DIASymbol GlobalScopeSymbol(GlobalScope);
if (S_OK != hr)
return;
CComPtr<IDiaEnumSymbols> 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<IDiaEnumSourceFiles> 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<uint8_t> 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<UTF16, 128> Path16String;
llvm::convertUTF8ToUTF16String(Path, Path16String);
@ -173,17 +292,25 @@ static void dumpInput(StringRef Path) {
return;
if (FAILED(source->loadDataFromPdb(Path16)))
return;
CComPtr<IDiaSession> session;
if (FAILED(source->openSession(&session)))
CComPtr<IDiaSession> 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);
}
}