From 679aeadda116f1d87ba65fd524f5b901afbeeafb Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Tue, 13 Mar 2018 17:46:06 +0000 Subject: [PATCH] [PDB] Support dumping injected sources via the DIA reader. Injected sources are basically a way to add actual source file content to your PDB. Presumably you could use this for shipping your source code with your debug information, but in practice I can only find this being used for embedding natvis files inside of PDBs. In order to effectively test LLVM's natvis file injection, we need a way to dump the injected sources of a PDB in a way that is authoritative (i.e. based on Microsoft's understanding of the PDB format, and not LLVM's). To this end, I've added support for dumping injected sources via DIA. I made a PDB file that used the /natvis option to generate a test case. Differential Revision: https://reviews.llvm.org/D44405 llvm-svn: 327428 --- .../DebugInfo/PDB/DIA/DIAEnumInjectedSources.h | 40 +++++++++++ .../llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h | 40 +++++++++++ llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h | 3 + llvm/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h | 31 ++++++++ .../llvm/DebugInfo/PDB/IPDBInjectedSource.h | 42 +++++++++++ llvm/include/llvm/DebugInfo/PDB/IPDBSession.h | 3 + .../llvm/DebugInfo/PDB/Native/NativeSession.h | 2 + llvm/include/llvm/DebugInfo/PDB/PDBExtras.h | 2 + llvm/include/llvm/DebugInfo/PDB/PDBTypes.h | 9 +++ llvm/lib/DebugInfo/PDB/CMakeLists.txt | 2 + .../DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp | 54 ++++++++++++++ llvm/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp | 64 +++++++++++++++++ llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp | 29 ++++++++ llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp | 5 ++ llvm/lib/DebugInfo/PDB/PDBExtras.cpp | 12 ++++ llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp | 3 + .../tools/llvm-pdbdump/Inputs/InjectedSource.pdb | Bin 0 -> 126975 bytes llvm/test/tools/llvm-pdbdump/injected-sources.test | 16 +++++ llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp | 78 +++++++++++++++++++++ 19 files changed, 435 insertions(+) create mode 100644 llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h create mode 100644 llvm/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h create mode 100644 llvm/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h create mode 100644 llvm/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h create mode 100644 llvm/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp create mode 100644 llvm/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp create mode 100644 llvm/test/tools/llvm-pdbdump/Inputs/InjectedSource.pdb create mode 100644 llvm/test/tools/llvm-pdbdump/injected-sources.test diff --git a/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h b/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h new file mode 100644 index 0000000..39490a4 --- /dev/null +++ b/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h @@ -0,0 +1,40 @@ +//==- DIAEnumInjectedSources.h - DIA Injected Sources Enumerator -*- 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_PDB_DIA_DIAENUMINJECTEDSOURCES_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMINJECTEDSOURCES_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h" + +namespace llvm { +namespace pdb { +class DIASession; + +class DIAEnumInjectedSources : public IPDBEnumChildren { +public: + explicit DIAEnumInjectedSources( + const DIASession &PDBSession, + CComPtr DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + DIAEnumInjectedSources *clone() const override; + +private: + const DIASession &Session; + CComPtr Enumerator; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIAENUMINJECTEDSOURCES_H diff --git a/llvm/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h b/llvm/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h new file mode 100644 index 0000000..1fc4a3a --- /dev/null +++ b/llvm/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h @@ -0,0 +1,40 @@ +//===- DIAInjectedSource.h - DIA impl for IPDBInjectedSource ----*- 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_PDB_DIA_DIAINJECTEDSOURCE_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAINJECTEDSOURCE_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h" + +namespace llvm { +namespace pdb { +class DIASession; + +class DIAInjectedSource : public IPDBInjectedSource { +public: + explicit DIAInjectedSource(const DIASession &Session, + CComPtr DiaSourceFile); + + uint32_t getCrc32() const override; + uint64_t getCodeByteSize() const override; + std::string getFileName() const override; + std::string getObjectFileName() const override; + std::string getVirtualFileName() const override; + PDB_SourceCompression getCompression() const override; + std::string getCode() const override; + +private: + const DIASession &Session; + CComPtr SourceFile; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIAINJECTEDSOURCE_H diff --git a/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h index 9aeb8bf..3a380d6 100644 --- a/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h +++ b/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h @@ -65,6 +65,9 @@ public: std::unique_ptr getDebugStreams() const override; std::unique_ptr getEnumTables() const override; + + std::unique_ptr getInjectedSources() const override; + private: CComPtr Session; }; diff --git a/llvm/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h b/llvm/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h new file mode 100644 index 0000000..aa843e0 --- /dev/null +++ b/llvm/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h @@ -0,0 +1,31 @@ +//===- DIAUtils.h - Utility functions for working with DIA ------*- 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_PDB_DIA_DIAUTILS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAUTILS_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/ConvertUTF.h" + +template +std::string invokeBstrMethod(Obj &Object, + HRESULT (__stdcall Obj::*Func)(BSTR *)) { + CComBSTR Str16; + HRESULT Result = (Object.*Func)(&Str16); + if (S_OK != Result) + return std::string(); + + std::string Str8; + llvm::ArrayRef StrBytes(reinterpret_cast(Str16.m_str), + Str16.ByteLength()); + llvm::convertUTF16ToUTF8String(StrBytes, Str8); + return Str8; +} + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIAUTILS_H diff --git a/llvm/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h b/llvm/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h new file mode 100644 index 0000000..e75d64a --- /dev/null +++ b/llvm/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h @@ -0,0 +1,42 @@ +//===- IPDBInjectedSource.h - base class for PDB injected file --*- 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_PDB_IPDBINJECTEDSOURCE_H +#define LLVM_DEBUGINFO_PDB_IPDBINJECTEDSOURCE_H + +#include "PDBTypes.h" +#include "llvm/Support/raw_ostream.h" +#include +#include + +namespace llvm { +class raw_ostream; + +namespace pdb { + +/// IPDBInjectedSource defines an interface used to represent source files +/// which were injected directly into the PDB file during the compilation +/// process. This is used, for example, to add natvis files to a PDB, but +/// in theory could be used to add arbitrary source code. +class IPDBInjectedSource { +public: + virtual ~IPDBInjectedSource(); + + virtual uint32_t getCrc32() const = 0; + virtual uint64_t getCodeByteSize() const = 0; + virtual std::string getFileName() const = 0; + virtual std::string getObjectFileName() const = 0; + virtual std::string getVirtualFileName() const = 0; + virtual PDB_SourceCompression getCompression() const = 0; + virtual std::string getCode() const = 0; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_IPDBINJECTEDSOURCE_H diff --git a/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h b/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h index ce7dec5..3e9f2df 100644 --- a/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h +++ b/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h @@ -69,6 +69,9 @@ public: virtual std::unique_ptr getDebugStreams() const = 0; virtual std::unique_ptr getEnumTables() const = 0; + + virtual std::unique_ptr + getInjectedSources() const = 0; }; } } diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h index 24f01d4..bb85d13 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h @@ -85,6 +85,8 @@ public: std::unique_ptr getEnumTables() const override; + std::unique_ptr getInjectedSources() const override; + PDBFile &getPDBFile() { return *Pdb; } const PDBFile &getPDBFile() const { return *Pdb; } diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h b/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h index 778121c..3c9a198 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h @@ -34,6 +34,8 @@ raw_ostream &operator<<(raw_ostream &OS, const PDB_SymType &Tag); raw_ostream &operator<<(raw_ostream &OS, const PDB_MemberAccess &Access); raw_ostream &operator<<(raw_ostream &OS, const PDB_UdtType &Type); raw_ostream &operator<<(raw_ostream &OS, const PDB_Machine &Machine); +raw_ostream &operator<<(raw_ostream &OS, + const PDB_SourceCompression &Compression); raw_ostream &operator<<(raw_ostream &OS, const Variant &Value); raw_ostream &operator<<(raw_ostream &OS, const VersionInfo &Version); diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h b/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h index 15b01d9..9d59c09 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h @@ -23,6 +23,7 @@ namespace llvm { namespace pdb { class IPDBDataStream; +class IPDBInjectedSource; class IPDBLineNumber; class IPDBSourceFile; class IPDBTable; @@ -65,6 +66,7 @@ using IPDBEnumSourceFiles = IPDBEnumChildren; using IPDBEnumDataStreams = IPDBEnumChildren; using IPDBEnumLineNumbers = IPDBEnumChildren; using IPDBEnumTables = IPDBEnumChildren; +using IPDBEnumInjectedSources = IPDBEnumChildren; /// Specifies which PDB reader implementation is to be used. Only a value /// of PDB_ReaderType::DIA is currently supported, but Native is in the works. @@ -133,6 +135,13 @@ enum class PDB_Machine { WceMipsV2 = 0x169 }; +enum class PDB_SourceCompression { + None, + RunLengthEncoded, + Huffman, + LZ, +}; + /// These values correspond to the CV_call_e enumeration, and are documented /// at the following locations: /// https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt index 0be05e9..3762b97 100644 --- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt +++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt @@ -14,11 +14,13 @@ if(LLVM_ENABLE_DIA_SDK) add_pdb_impl_folder(DIA DIA/DIADataStream.cpp DIA/DIAEnumDebugStreams.cpp + DIA/DIAEnumInjectedSources.cpp DIA/DIAEnumLineNumbers.cpp DIA/DIAEnumSourceFiles.cpp DIA/DIAEnumSymbols.cpp DIA/DIAEnumTables.cpp DIA/DIAError.cpp + DIA/DIAInjectedSource.cpp DIA/DIALineNumber.cpp DIA/DIARawSymbol.cpp DIA/DIASession.cpp diff --git a/llvm/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp b/llvm/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp new file mode 100644 index 0000000..873f4a0 --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp @@ -0,0 +1,54 @@ +//==- DIAEnumSourceFiles.cpp - DIA Source File Enumerator impl ---*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h" +#include "llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" + +using namespace llvm; +using namespace llvm::pdb; + +DIAEnumInjectedSources::DIAEnumInjectedSources( + const DIASession &PDBSession, + CComPtr DiaEnumerator) + : Session(PDBSession), Enumerator(DiaEnumerator) {} + +uint32_t DIAEnumInjectedSources::getChildCount() const { + LONG Count = 0; + return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0; +} + +std::unique_ptr +DIAEnumInjectedSources::getChildAtIndex(uint32_t Index) const { + CComPtr Item; + if (S_OK != Enumerator->Item(Index, &Item)) + return nullptr; + + return std::unique_ptr( + new DIAInjectedSource(Session, Item)); +} + +std::unique_ptr DIAEnumInjectedSources::getNext() { + CComPtr Item; + ULONG NumFetched = 0; + if (S_OK != Enumerator->Next(1, &Item, &NumFetched)) + return nullptr; + + return std::unique_ptr( + new DIAInjectedSource(Session, Item)); +} + +void DIAEnumInjectedSources::reset() { Enumerator->Reset(); } + +DIAEnumInjectedSources *DIAEnumInjectedSources::clone() const { + CComPtr EnumeratorClone; + if (S_OK != Enumerator->Clone(&EnumeratorClone)) + return nullptr; + return new DIAEnumInjectedSources(Session, EnumeratorClone); +} diff --git a/llvm/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp b/llvm/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp new file mode 100644 index 0000000..fbd1695 --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp @@ -0,0 +1,64 @@ +//===- DIAInjectedSource.cpp - DIA impl for IPDBInjectedSource --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h" +#include "llvm/DebugInfo/PDB/DIA/DIASession.h" +#include "llvm/DebugInfo/PDB/DIA/DIAUtils.h" + +using namespace llvm; +using namespace llvm::pdb; + +DIAInjectedSource::DIAInjectedSource(const DIASession &Session, + CComPtr DiaSourceFile) + : Session(Session), SourceFile(DiaSourceFile) {} + +uint32_t DIAInjectedSource::getCrc32() const { + DWORD Crc; + return (S_OK == SourceFile->get_crc(&Crc)) ? Crc : 0; +} + +uint64_t DIAInjectedSource::getCodeByteSize() const { + ULONGLONG Size; + return (S_OK == SourceFile->get_length(&Size)) ? Size : 0; +} + +std::string DIAInjectedSource::getFileName() const { + return invokeBstrMethod(*SourceFile, &IDiaInjectedSource::get_filename); +} + +std::string DIAInjectedSource::getObjectFileName() const { + return invokeBstrMethod(*SourceFile, &IDiaInjectedSource::get_objectFilename); +} + +std::string DIAInjectedSource::getVirtualFileName() const { + return invokeBstrMethod(*SourceFile, + &IDiaInjectedSource::get_virtualFilename); +} + +PDB_SourceCompression DIAInjectedSource::getCompression() const { + DWORD Compression = 0; + if (S_OK != SourceFile->get_sourceCompression(&Compression)) + return PDB_SourceCompression::None; + return static_cast(Compression); +} + +std::string DIAInjectedSource::getCode() const { + DWORD DataSize; + if (S_OK != SourceFile->get_source(0, &DataSize, nullptr)) + return ""; + + std::vector Buffer(DataSize); + if (S_OK != SourceFile->get_source(DataSize, &DataSize, Buffer.data())) + return ""; + assert(Buffer.size() == DataSize); + return std::string(reinterpret_cast(Buffer.data()), + Buffer.size()); +} diff --git a/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp b/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp index dcf29a5..a6bbf6f 100644 --- a/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp +++ b/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/PDB/DIA/DIASession.h" #include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h" +#include "llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h" #include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h" #include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h" #include "llvm/DebugInfo/PDB/DIA/DIAEnumTables.h" @@ -310,3 +311,31 @@ std::unique_ptr DIASession::getEnumTables() const { return llvm::make_unique(DiaEnumerator); } + +static CComPtr +getEnumInjectedSources(IDiaSession &Session) { + CComPtr EIS; + CComPtr ET; + CComPtr Table; + ULONG Count = 0; + + if (Session.getEnumTables(&ET) != S_OK) + return nullptr; + + while (ET->Next(1, &Table, &Count) == S_OK && Count == 1) { + // There is only one table that matches the given iid + if (S_OK == + Table->QueryInterface(__uuidof(IDiaEnumInjectedSources), (void **)&EIS)) + break; + Table.Release(); + } + return EIS; +} +std::unique_ptr +DIASession::getInjectedSources() const { + CComPtr Files = getEnumInjectedSources(*Session); + if (!Files) + return nullptr; + + return llvm::make_unique(*this, Files); +} diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp index b5875a0..481eb77 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -249,3 +249,8 @@ std::unique_ptr NativeSession::getDebugStreams() const { std::unique_ptr NativeSession::getEnumTables() const { return nullptr; } + +std::unique_ptr +NativeSession::getInjectedSources() const { + return nullptr; +} diff --git a/llvm/lib/DebugInfo/PDB/PDBExtras.cpp b/llvm/lib/DebugInfo/PDB/PDBExtras.cpp index ee752cd..bb172ec 100644 --- a/llvm/lib/DebugInfo/PDB/PDBExtras.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBExtras.cpp @@ -254,6 +254,18 @@ raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, return OS; } +raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, + const PDB_SourceCompression &Compression) { + switch (Compression) { + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SourceCompression, None, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SourceCompression, Huffman, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SourceCompression, LZ, OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_SourceCompression, RunLengthEncoded, "RLE", + OS) + } + return OS; +} + raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const Variant &Value) { switch (Value.Type) { case PDB_VariantType::Bool: diff --git a/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp b/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp index b2b03fb..b66cbdc 100644 --- a/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/IPDBDataStream.h" +#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h" #include "llvm/DebugInfo/PDB/IPDBLineNumber.h" #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" @@ -29,3 +30,5 @@ IPDBRawSymbol::~IPDBRawSymbol() = default; IPDBLineNumber::~IPDBLineNumber() = default; IPDBTable::~IPDBTable() = default; + +IPDBInjectedSource::~IPDBInjectedSource() = default; diff --git a/llvm/test/tools/llvm-pdbdump/Inputs/InjectedSource.pdb b/llvm/test/tools/llvm-pdbdump/Inputs/InjectedSource.pdb new file mode 100644 index 0000000000000000000000000000000000000000..518a8f43f1472a4eed8f370671646fa67b27b4ad GIT binary patch literal 126975 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 F`2QkpXjA|I literal 0 HcmV?d00001 diff --git a/llvm/test/tools/llvm-pdbdump/injected-sources.test b/llvm/test/tools/llvm-pdbdump/injected-sources.test new file mode 100644 index 0000000..d9d71ef3 --- /dev/null +++ b/llvm/test/tools/llvm-pdbdump/injected-sources.test @@ -0,0 +1,16 @@ +; RUN: llvm-pdbutil pretty -injected-sources -injected-source-content \ +; RUN: %p/Inputs/InjectedSource.pdb | FileCheck %s +; RUN: llvm-pdbutil pretty -injected-sources -injected-source-content \ +; RUN: %p/Inputs/ClassLayoutTest.pdb | FileCheck --check-prefix=NEGATIVE %s + +; CHECK: ---INJECTED SOURCES--- +; CHECK-NEXT: d:\sandbox\natvistest\natvistest\test.natvis (220 bytes): obj=, vname=d:\sandbox\natvistest\natvistest\test.natvis, crc=2374979362, compression=None +; CHECK-NEXT: +; CHECK-NEXT: +; CHECK-NEXT: +; CHECK-NEXT: This is a test +; CHECK-NEXT: +; CHECK-NEXT: + +; NEGATIVE: ---INJECTED SOURCES--- +; NEGATIVE-NEXT: There are no injected sources. diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp index a2a9759..25e0ddf 100644 --- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp +++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -45,6 +45,7 @@ #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/PDB/GenericError.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h" #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" @@ -147,6 +148,14 @@ cl::list InputFilenames(cl::Positional, cl::desc(""), cl::OneOrMore, cl::sub(PrettySubcommand)); +cl::opt InjectedSources("injected-sources", + cl::desc("Display injected sources"), + cl::cat(OtherOptions), cl::sub(PrettySubcommand)); +cl::opt ShowInjectedSourceContent( + "injected-source-content", + cl::desc("When displaying an injected source, display the file content"), + cl::cat(OtherOptions), cl::sub(PrettySubcommand)); + cl::opt Compilands("compilands", cl::desc("Display compilands"), cl::cat(TypeCategory), cl::sub(PrettySubcommand)); cl::opt Symbols("module-syms", @@ -840,6 +849,62 @@ bool opts::pretty::compareDataSymbols( return getTypeLength(*F1) > getTypeLength(*F2); } +static std::string stringOr(std::string Str, std::string IfEmpty) { + return (Str.empty()) ? IfEmpty : Str; +} + +static void dumpInjectedSources(LinePrinter &Printer, IPDBSession &Session) { + auto Sources = Session.getInjectedSources(); + if (0 == Sources->getChildCount()) { + Printer.printLine("There are no injected sources."); + return; + } + + while (auto IS = Sources->getNext()) { + Printer.NewLine(); + std::string File = stringOr(IS->getFileName(), ""); + uint64_t Size = IS->getCodeByteSize(); + std::string Obj = stringOr(IS->getObjectFileName(), ""); + std::string VFName = stringOr(IS->getVirtualFileName(), ""); + uint32_t CRC = IS->getCrc32(); + + std::string CompressionStr; + llvm::raw_string_ostream Stream(CompressionStr); + Stream << IS->getCompression(); + WithColor(Printer, PDB_ColorItem::Path).get() << File; + Printer << " ("; + WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Size; + Printer << " bytes): "; + WithColor(Printer, PDB_ColorItem::Keyword).get() << "obj"; + Printer << "="; + WithColor(Printer, PDB_ColorItem::Path).get() << Obj; + Printer << ", "; + WithColor(Printer, PDB_ColorItem::Keyword).get() << "vname"; + Printer << "="; + WithColor(Printer, PDB_ColorItem::Path).get() << VFName; + Printer << ", "; + WithColor(Printer, PDB_ColorItem::Keyword).get() << "crc"; + Printer << "="; + WithColor(Printer, PDB_ColorItem::LiteralValue).get() << CRC; + Printer << ", "; + WithColor(Printer, PDB_ColorItem::Keyword).get() << "compression"; + Printer << "="; + WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Stream.str(); + + if (!opts::pretty::ShowInjectedSourceContent) + continue; + + // Set the indent level to 0 when printing file content. + int Indent = Printer.getIndentLevel(); + Printer.Unindent(Indent); + + Printer.printLine(IS->getCode()); + + // Re-indent back to the original level. + Printer.Indent(Indent); + } +} + static void dumpPretty(StringRef Path) { std::unique_ptr Session; @@ -989,6 +1054,19 @@ static void dumpPretty(StringRef Path) { if (opts::pretty::Lines) { Printer.NewLine(); } + if (opts::pretty::InjectedSources) { + Printer.NewLine(); + WithColor(Printer, PDB_ColorItem::SectionHeader).get() + << "---INJECTED SOURCES---"; + AutoIndent Indent1(Printer); + + if (ReaderType == PDB_ReaderType::Native) + Printer.printLine( + "Injected sources are not supported with the native reader."); + else + dumpInjectedSources(Printer, *Session); + } + outs().flush(); } -- 2.7.4