summaryrefslogtreecommitdiff
path: root/lib/DebugInfo/PDB
diff options
context:
space:
mode:
Diffstat (limited to 'lib/DebugInfo/PDB')
-rw-r--r--lib/DebugInfo/PDB/CMakeLists.txt7
-rw-r--r--lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp52
-rw-r--r--lib/DebugInfo/PDB/DIA/DIAEnumSectionContribs.cpp54
-rw-r--r--lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp63
-rw-r--r--lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp108
-rw-r--r--lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp126
-rw-r--r--lib/DebugInfo/PDB/DIA/DIASession.cpp123
-rw-r--r--lib/DebugInfo/PDB/GenericError.cpp2
-rw-r--r--lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp4
-rw-r--r--lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp7
-rw-r--r--lib/DebugInfo/PDB/Native/DbiStream.cpp28
-rw-r--r--lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp53
-rw-r--r--lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp51
-rw-r--r--lib/DebugInfo/PDB/Native/HashTable.cpp250
-rw-r--r--lib/DebugInfo/PDB/Native/InfoStream.cpp31
-rw-r--r--lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp20
-rw-r--r--lib/DebugInfo/PDB/Native/NamedStreamMap.cpp147
-rw-r--r--lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp54
-rw-r--r--lib/DebugInfo/PDB/Native/NativeSession.cpp44
-rw-r--r--lib/DebugInfo/PDB/Native/PDBFile.cpp17
-rw-r--r--lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp260
-rw-r--r--lib/DebugInfo/PDB/Native/PDBStringTable.cpp3
-rw-r--r--lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp92
-rw-r--r--lib/DebugInfo/PDB/Native/TpiStream.cpp4
-rw-r--r--lib/DebugInfo/PDB/PDBExtras.cpp15
-rw-r--r--lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp6
-rw-r--r--lib/DebugInfo/PDB/PDBSymbolCompiland.cpp102
-rw-r--r--lib/DebugInfo/PDB/PDBSymbolData.cpp51
-rw-r--r--lib/DebugInfo/PDB/PDBSymbolFunc.cpp15
-rw-r--r--lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp19
30 files changed, 1290 insertions, 518 deletions
diff --git a/lib/DebugInfo/PDB/CMakeLists.txt b/lib/DebugInfo/PDB/CMakeLists.txt
index 0be05e9bda5e..f6a529a69a8b 100644
--- a/lib/DebugInfo/PDB/CMakeLists.txt
+++ b/lib/DebugInfo/PDB/CMakeLists.txt
@@ -14,13 +14,17 @@ if(LLVM_ENABLE_DIA_SDK)
add_pdb_impl_folder(DIA
DIA/DIADataStream.cpp
DIA/DIAEnumDebugStreams.cpp
+ DIA/DIAEnumInjectedSources.cpp
DIA/DIAEnumLineNumbers.cpp
+ DIA/DIAEnumSectionContribs.cpp
DIA/DIAEnumSourceFiles.cpp
DIA/DIAEnumSymbols.cpp
DIA/DIAEnumTables.cpp
DIA/DIAError.cpp
+ DIA/DIAInjectedSource.cpp
DIA/DIALineNumber.cpp
DIA/DIARawSymbol.cpp
+ DIA/DIASectionContrib.cpp
DIA/DIASession.cpp
DIA/DIASourceFile.cpp
DIA/DIATable.cpp
@@ -61,7 +65,8 @@ add_pdb_impl_folder(Native
Native/SymbolStream.cpp
Native/TpiHashing.cpp
Native/TpiStream.cpp
- Native/TpiStreamBuilder.cpp)
+ Native/TpiStreamBuilder.cpp
+ )
list(APPEND LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB/Native")
list(APPEND LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB")
diff --git a/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp b/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp
new file mode 100644
index 000000000000..d7c908e04593
--- /dev/null
+++ b/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp
@@ -0,0 +1,52 @@
+//==- 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<IDiaEnumInjectedSources> 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<IPDBInjectedSource>
+DIAEnumInjectedSources::getChildAtIndex(uint32_t Index) const {
+ CComPtr<IDiaInjectedSource> Item;
+ if (S_OK != Enumerator->Item(Index, &Item))
+ return nullptr;
+
+ return std::unique_ptr<IPDBInjectedSource>(new DIAInjectedSource(Item));
+}
+
+std::unique_ptr<IPDBInjectedSource> DIAEnumInjectedSources::getNext() {
+ CComPtr<IDiaInjectedSource> Item;
+ ULONG NumFetched = 0;
+ if (S_OK != Enumerator->Next(1, &Item, &NumFetched))
+ return nullptr;
+
+ return std::unique_ptr<IPDBInjectedSource>(new DIAInjectedSource(Item));
+}
+
+void DIAEnumInjectedSources::reset() { Enumerator->Reset(); }
+
+DIAEnumInjectedSources *DIAEnumInjectedSources::clone() const {
+ CComPtr<IDiaEnumInjectedSources> EnumeratorClone;
+ if (S_OK != Enumerator->Clone(&EnumeratorClone))
+ return nullptr;
+ return new DIAEnumInjectedSources(Session, EnumeratorClone);
+}
diff --git a/lib/DebugInfo/PDB/DIA/DIAEnumSectionContribs.cpp b/lib/DebugInfo/PDB/DIA/DIAEnumSectionContribs.cpp
new file mode 100644
index 000000000000..1f405f049198
--- /dev/null
+++ b/lib/DebugInfo/PDB/DIA/DIAEnumSectionContribs.cpp
@@ -0,0 +1,54 @@
+//==- DIAEnumSectionContribs.cpp ---------------------------------*- 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/DIAEnumSectionContribs.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASectionContrib.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DIAEnumSectionContribs::DIAEnumSectionContribs(
+ const DIASession &PDBSession,
+ CComPtr<IDiaEnumSectionContribs> DiaEnumerator)
+ : Session(PDBSession), Enumerator(DiaEnumerator) {}
+
+uint32_t DIAEnumSectionContribs::getChildCount() const {
+ LONG Count = 0;
+ return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0;
+}
+
+std::unique_ptr<IPDBSectionContrib>
+DIAEnumSectionContribs::getChildAtIndex(uint32_t Index) const {
+ CComPtr<IDiaSectionContrib> Item;
+ if (S_OK != Enumerator->Item(Index, &Item))
+ return nullptr;
+
+ return std::unique_ptr<IPDBSectionContrib>(
+ new DIASectionContrib(Session, Item));
+}
+
+std::unique_ptr<IPDBSectionContrib> DIAEnumSectionContribs::getNext() {
+ CComPtr<IDiaSectionContrib> Item;
+ ULONG NumFetched = 0;
+ if (S_OK != Enumerator->Next(1, &Item, &NumFetched))
+ return nullptr;
+
+ return std::unique_ptr<IPDBSectionContrib>(
+ new DIASectionContrib(Session, Item));
+}
+
+void DIAEnumSectionContribs::reset() { Enumerator->Reset(); }
+
+DIAEnumSectionContribs *DIAEnumSectionContribs::clone() const {
+ CComPtr<IDiaEnumSectionContribs> EnumeratorClone;
+ if (S_OK != Enumerator->Clone(&EnumeratorClone))
+ return nullptr;
+ return new DIAEnumSectionContribs(Session, EnumeratorClone);
+}
diff --git a/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp b/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp
new file mode 100644
index 000000000000..1d642f221d79
--- /dev/null
+++ b/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp
@@ -0,0 +1,63 @@
+//===- 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(CComPtr<IDiaInjectedSource> DiaSourceFile)
+ : 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<PDB_SourceCompression>(Compression);
+}
+
+std::string DIAInjectedSource::getCode() const {
+ DWORD DataSize;
+ if (S_OK != SourceFile->get_source(0, &DataSize, nullptr))
+ return "";
+
+ std::vector<uint8_t> Buffer(DataSize);
+ if (S_OK != SourceFile->get_source(DataSize, &DataSize, Buffer.data()))
+ return "";
+ assert(Buffer.size() == DataSize);
+ return std::string(reinterpret_cast<const char *>(Buffer.data()),
+ Buffer.size());
+}
diff --git a/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
index 8e4b1f8aa8c9..7d6cb254e1d1 100644
--- a/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
+++ b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
@@ -11,7 +11,9 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/DebugInfo/CodeView/Formatters.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h"
#include "llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h"
+#include "llvm/DebugInfo/PDB/DIA/DIALineNumber.h"
#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
#include "llvm/DebugInfo/PDB/PDBExtras.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
@@ -178,7 +180,7 @@ void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name,
OS << "\n";
OS.indent(Indent);
Variant V = VariantFromVARIANT(Value);
- OS << V;
+ OS << Name << ": " << V;
}
}
@@ -400,6 +402,47 @@ DIARawSymbol::findChildren(PDB_SymType Type, StringRef Name,
}
std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findChildrenByAddr(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags, uint32_t Section,
+ uint32_t Offset) const {
+ llvm::SmallVector<UTF16, 32> Name16;
+ llvm::convertUTF8ToUTF16String(Name, Name16);
+
+ enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+
+ DWORD CompareFlags = static_cast<DWORD>(Flags);
+ wchar_t *Name16Str = reinterpret_cast<wchar_t *>(Name16.data());
+
+ CComPtr<IDiaEnumSymbols> DiaEnumerator;
+ if (S_OK !=
+ Symbol->findChildrenExByAddr(EnumVal, Name16Str, CompareFlags, Section,
+ Offset, &DiaEnumerator))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findChildrenByVA(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags, uint64_t VA) const {
+ llvm::SmallVector<UTF16, 32> Name16;
+ llvm::convertUTF8ToUTF16String(Name, Name16);
+
+ enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+
+ DWORD CompareFlags = static_cast<DWORD>(Flags);
+ wchar_t *Name16Str = reinterpret_cast<wchar_t *>(Name16.data());
+
+ CComPtr<IDiaEnumSymbols> DiaEnumerator;
+ if (S_OK !=
+ Symbol->findChildrenExByVA(EnumVal, Name16Str, CompareFlags, VA,
+ &DiaEnumerator))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
DIARawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name,
PDB_NameSearchFlags Flags, uint32_t RVA) const {
llvm::SmallVector<UTF16, 32> Name16;
@@ -419,6 +462,15 @@ DIARawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name,
}
std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const {
+ CComPtr<IDiaEnumSymbols> DiaEnumerator;
+ if (S_OK != Symbol->findInlineFramesByAddr(Section, Offset, &DiaEnumerator))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
DIARawSymbol::findInlineFramesByRVA(uint32_t RVA) const {
CComPtr<IDiaEnumSymbols> DiaEnumerator;
if (S_OK != Symbol->findInlineFramesByRVA(RVA, &DiaEnumerator))
@@ -427,6 +479,51 @@ DIARawSymbol::findInlineFramesByRVA(uint32_t RVA) const {
return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
}
+std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findInlineFramesByVA(uint64_t VA) const {
+ CComPtr<IDiaEnumSymbols> DiaEnumerator;
+ if (S_OK != Symbol->findInlineFramesByVA(VA, &DiaEnumerator))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers> DIARawSymbol::findInlineeLines() const {
+ CComPtr<IDiaEnumLineNumbers> DiaEnumerator;
+ if (S_OK != Symbol->findInlineeLines(&DiaEnumerator))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumLineNumbers>(DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+DIARawSymbol::findInlineeLinesByAddr(uint32_t Section, uint32_t Offset,
+ uint32_t Length) const {
+ CComPtr<IDiaEnumLineNumbers> DiaEnumerator;
+ if (S_OK != Symbol->findInlineeLinesByAddr(Section, Offset, Length, &DiaEnumerator))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumLineNumbers>(DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+DIARawSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const {
+ CComPtr<IDiaEnumLineNumbers> DiaEnumerator;
+ if (S_OK != Symbol->findInlineeLinesByRVA(RVA, Length, &DiaEnumerator))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumLineNumbers>(DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+DIARawSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const {
+ CComPtr<IDiaEnumLineNumbers> DiaEnumerator;
+ if (S_OK != Symbol->findInlineeLinesByVA(VA, Length, &DiaEnumerator))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumLineNumbers>(DiaEnumerator);
+}
+
void DIARawSymbol::getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const {
bytes.clear();
@@ -652,6 +749,15 @@ std::string DIARawSymbol::getSourceFileName() const {
return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_sourceFileName);
}
+std::unique_ptr<IPDBLineNumber>
+DIARawSymbol::getSrcLineOnTypeDefn() const {
+ CComPtr<IDiaLineNumber> LineNumber;
+ if (FAILED(Symbol->getSrcLineOnTypeDefn(&LineNumber)) || !LineNumber)
+ return nullptr;
+
+ return llvm::make_unique<DIALineNumber>(LineNumber);
+}
+
uint32_t DIARawSymbol::getStride() const {
return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_stride);
}
diff --git a/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp b/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp
new file mode 100644
index 000000000000..b7dc49f53e23
--- /dev/null
+++ b/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp
@@ -0,0 +1,126 @@
+//===- DIASectionContrib.cpp - DIA impl. of IPDBSectionContrib ---- 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/DIASectionContrib.h"
+#include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DIASectionContrib::DIASectionContrib(const DIASession &PDBSession,
+ CComPtr<IDiaSectionContrib> DiaSection)
+ : Session(PDBSession), Section(DiaSection) {}
+
+std::unique_ptr<PDBSymbolCompiland> DIASectionContrib::getCompiland() const {
+ CComPtr<IDiaSymbol> Symbol;
+ if (FAILED(Section->get_compiland(&Symbol)))
+ return nullptr;
+
+ auto RawSymbol = llvm::make_unique<DIARawSymbol>(Session, Symbol);
+ return llvm::make_unique<PDBSymbolCompiland>(Session, std::move(RawSymbol));
+}
+
+template <typename ArgType>
+ArgType
+PrivateGetDIAValue(IDiaSectionContrib *Section,
+ HRESULT (__stdcall IDiaSectionContrib::*Method)(ArgType *)) {
+ ArgType Value;
+ if (S_OK == (Section->*Method)(&Value))
+ return static_cast<ArgType>(Value);
+
+ return ArgType();
+}
+
+uint32_t DIASectionContrib::getAddressSection() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_addressSection);
+}
+
+uint32_t DIASectionContrib::getAddressOffset() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_addressOffset);
+}
+
+uint64_t DIASectionContrib::getVirtualAddress() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_virtualAddress);
+}
+
+uint32_t DIASectionContrib::getRelativeVirtualAddress() const {
+ return PrivateGetDIAValue(Section,
+ &IDiaSectionContrib::get_relativeVirtualAddress);
+}
+
+uint32_t DIASectionContrib::getLength() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_length);
+}
+
+bool DIASectionContrib::isNotPaged() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_notPaged);
+}
+
+bool DIASectionContrib::hasCode() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_code);
+}
+
+bool DIASectionContrib::hasCode16Bit() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_code16bit);
+}
+
+bool DIASectionContrib::hasInitializedData() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_initializedData);
+}
+
+bool DIASectionContrib::hasUninitializedData() const {
+ return PrivateGetDIAValue(Section,
+ &IDiaSectionContrib::get_uninitializedData);
+}
+
+bool DIASectionContrib::isRemoved() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_remove);
+}
+
+bool DIASectionContrib::hasComdat() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_comdat);
+}
+
+bool DIASectionContrib::isDiscardable() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_discardable);
+}
+
+bool DIASectionContrib::isNotCached() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_notCached);
+}
+
+bool DIASectionContrib::isShared() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_share);
+}
+
+bool DIASectionContrib::isExecutable() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_execute);
+}
+
+bool DIASectionContrib::isReadable() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_read);
+}
+
+bool DIASectionContrib::isWritable() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_write);
+}
+
+uint32_t DIASectionContrib::getDataCrc32() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_dataCrc);
+}
+
+uint32_t DIASectionContrib::getRelocationsCrc32() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_relocationsCrc);
+}
+
+uint32_t DIASectionContrib::getCompilandId() const {
+ return PrivateGetDIAValue(Section, &IDiaSectionContrib::get_compilandId);
+}
diff --git a/lib/DebugInfo/PDB/DIA/DIASession.cpp b/lib/DebugInfo/PDB/DIA/DIASession.cpp
index b8aaebbf7380..d81f59400eb3 100644
--- a/lib/DebugInfo/PDB/DIA/DIASession.cpp
+++ b/lib/DebugInfo/PDB/DIA/DIASession.cpp
@@ -9,7 +9,9 @@
#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/DIAEnumSectionContribs.h"
#include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
#include "llvm/DebugInfo/PDB/DIA/DIAEnumTables.h"
#include "llvm/DebugInfo/PDB/DIA/DIAError.h"
@@ -104,7 +106,7 @@ Error DIASession::createFromPdb(StringRef Path,
if (!llvm::convertUTF8ToUTF16String(Path, Path16))
return make_error<GenericError>(generic_error_code::invalid_path);
- const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data());
+ const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data());
HRESULT HR;
if (FAILED(HR = DiaDataSource->loadDataFromPdb(Path16Str))) {
return ErrorFromHResult(HR, "Calling loadDataFromPdb {0}", Path);
@@ -148,8 +150,8 @@ uint64_t DIASession::getLoadAddress() const {
return (success) ? LoadAddress : 0;
}
-void DIASession::setLoadAddress(uint64_t Address) {
- Session->put_loadAddress(Address);
+bool DIASession::setLoadAddress(uint64_t Address) {
+ return (S_OK == Session->put_loadAddress(Address));
}
std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() {
@@ -164,6 +166,28 @@ std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() {
return ExeSymbol;
}
+bool DIASession::addressForVA(uint64_t VA, uint32_t &Section,
+ uint32_t &Offset) const {
+ DWORD ArgSection, ArgOffset = 0;
+ if (S_OK == Session->addressForVA(VA, &ArgSection, &ArgOffset)) {
+ Section = static_cast<uint32_t>(ArgSection);
+ Offset = static_cast<uint32_t>(ArgOffset);
+ return true;
+ }
+ return false;
+}
+
+bool DIASession::addressForRVA(uint32_t RVA, uint32_t &Section,
+ uint32_t &Offset) const {
+ DWORD ArgSection, ArgOffset = 0;
+ if (S_OK == Session->addressForRVA(RVA, &ArgSection, &ArgOffset)) {
+ Section = static_cast<uint32_t>(ArgSection);
+ Offset = static_cast<uint32_t>(ArgOffset);
+ return true;
+ }
+ return false;
+}
+
std::unique_ptr<PDBSymbol> DIASession::getSymbolById(uint32_t SymbolId) const {
CComPtr<IDiaSymbol> LocatedSymbol;
if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol))
@@ -190,6 +214,31 @@ DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
return PDBSymbol::create(*this, std::move(RawSymbol));
}
+std::unique_ptr<PDBSymbol> DIASession::findSymbolByRVA(uint32_t RVA,
+ PDB_SymType Type) const {
+ enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+
+ CComPtr<IDiaSymbol> Symbol;
+ if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol))
+ return nullptr;
+
+ auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol);
+ return PDBSymbol::create(*this, std::move(RawSymbol));
+}
+
+std::unique_ptr<PDBSymbol>
+DIASession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
+ PDB_SymType Type) const {
+ enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+
+ CComPtr<IDiaSymbol> Symbol;
+ if (S_OK != Session->findSymbolByAddr(Sect, Offset, EnumVal, &Symbol))
+ return nullptr;
+
+ auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol);
+ return PDBSymbol::create(*this, std::move(RawSymbol));
+}
+
std::unique_ptr<IPDBEnumLineNumbers>
DIASession::findLineNumbers(const PDBSymbolCompiland &Compiland,
const IPDBSourceFile &File) const {
@@ -198,9 +247,8 @@ DIASession::findLineNumbers(const PDBSymbolCompiland &Compiland,
const DIASourceFile &RawFile = static_cast<const DIASourceFile &>(File);
CComPtr<IDiaEnumLineNumbers> LineNumbers;
- if (S_OK !=
- Session->findLines(RawCompiland.getDiaSymbol(), RawFile.getDiaFile(),
- &LineNumbers))
+ if (S_OK != Session->findLines(RawCompiland.getDiaSymbol(),
+ RawFile.getDiaFile(), &LineNumbers))
return nullptr;
return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
@@ -209,7 +257,31 @@ DIASession::findLineNumbers(const PDBSymbolCompiland &Compiland,
std::unique_ptr<IPDBEnumLineNumbers>
DIASession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const {
CComPtr<IDiaEnumLineNumbers> LineNumbers;
- if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers))
+ if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers)) {
+ ULONGLONG LoadAddr = 0;
+ if (S_OK != Session->get_loadAddress(&LoadAddr))
+ return nullptr;
+ DWORD RVA = static_cast<DWORD>(Address - LoadAddr);
+ if (S_OK != Session->findLinesByRVA(RVA, Length, &LineNumbers))
+ return nullptr;
+ }
+ return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+DIASession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const {
+ CComPtr<IDiaEnumLineNumbers> LineNumbers;
+ if (S_OK != Session->findLinesByRVA(RVA, Length, &LineNumbers))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+DIASession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset,
+ uint32_t Length) const {
+ CComPtr<IDiaEnumLineNumbers> LineNumbers;
+ if (S_OK != Session->findLinesByAddr(Section, Offset, Length, &LineNumbers))
return nullptr;
return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
@@ -310,3 +382,40 @@ std::unique_ptr<IPDBEnumTables> DIASession::getEnumTables() const {
return llvm::make_unique<DIAEnumTables>(DiaEnumerator);
}
+
+template <class T> static CComPtr<T> getTableEnumerator(IDiaSession &Session) {
+ CComPtr<T> Enumerator;
+ CComPtr<IDiaEnumTables> ET;
+ CComPtr<IDiaTable> 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(T), (void **)&Enumerator))
+ break;
+ Table.Release();
+ }
+ return Enumerator;
+}
+std::unique_ptr<IPDBEnumInjectedSources>
+DIASession::getInjectedSources() const {
+ CComPtr<IDiaEnumInjectedSources> Files =
+ getTableEnumerator<IDiaEnumInjectedSources>(*Session);
+ if (!Files)
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumInjectedSources>(*this, Files);
+}
+
+std::unique_ptr<IPDBEnumSectionContribs>
+DIASession::getSectionContribs() const {
+ CComPtr<IDiaEnumSectionContribs> Sections =
+ getTableEnumerator<IDiaEnumSectionContribs>(*Session);
+ if (!Sections)
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumSectionContribs>(*this, Sections);
+}
diff --git a/lib/DebugInfo/PDB/GenericError.cpp b/lib/DebugInfo/PDB/GenericError.cpp
index 4fcecb92fd15..2a677b9abe2d 100644
--- a/lib/DebugInfo/PDB/GenericError.cpp
+++ b/lib/DebugInfo/PDB/GenericError.cpp
@@ -30,7 +30,7 @@ public:
return "Type server PDB was not found.";
case generic_error_code::dia_sdk_not_present:
return "LLVM was not compiled with support for DIA. This usually means "
- "that you are are not using MSVC, or your Visual Studio "
+ "that you are not using MSVC, or your Visual Studio "
"installation "
"is corrupt.";
case generic_error_code::invalid_path:
diff --git a/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp b/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp
index dabcc3447ee5..931ac7bb81db 100644
--- a/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp
+++ b/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp
@@ -49,6 +49,10 @@ uint16_t DbiModuleDescriptor::getTypeServerIndex() const {
ModInfoFlags::TypeServerIndexShift;
}
+const SectionContrib &DbiModuleDescriptor::getSectionContrib() const {
+ return Layout->SC;
+}
+
uint16_t DbiModuleDescriptor::getModuleStreamIndex() const {
return Layout->ModDiStream;
}
diff --git a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
index d765485bdb6d..b97f1e90bcf8 100644
--- a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
@@ -60,6 +60,11 @@ void DbiModuleDescriptorBuilder::setPdbFilePathNI(uint32_t NI) {
PdbFilePathNI = NI;
}
+void DbiModuleDescriptorBuilder::setFirstSectionContrib(
+ const SectionContrib &SC) {
+ Layout.SC = SC;
+}
+
void DbiModuleDescriptorBuilder::addSymbol(CVSymbol Symbol) {
Symbols.push_back(Symbol);
// Symbols written to a PDB file are required to be 4 byte aligned. The same
@@ -90,7 +95,7 @@ uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const {
}
void DbiModuleDescriptorBuilder::finalize() {
- Layout.SC.ModuleIndex = Layout.Mod;
+ Layout.SC.Imod = Layout.Mod;
Layout.FileNameOffs = 0; // TODO: Fix this
Layout.Flags = 0; // TODO: Fix this
Layout.C11Bytes = 0;
diff --git a/lib/DebugInfo/PDB/Native/DbiStream.cpp b/lib/DebugInfo/PDB/Native/DbiStream.cpp
index 04e6664c68db..edaa783398ca 100644
--- a/lib/DebugInfo/PDB/Native/DbiStream.cpp
+++ b/lib/DebugInfo/PDB/Native/DbiStream.cpp
@@ -45,12 +45,12 @@ static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
return Error::success();
}
-DbiStream::DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
- : Pdb(File), Stream(std::move(Stream)), Header(nullptr) {}
+DbiStream::DbiStream(std::unique_ptr<BinaryStream> Stream)
+ : Stream(std::move(Stream)), Header(nullptr) {}
DbiStream::~DbiStream() = default;
-Error DbiStream::reload() {
+Error DbiStream::reload(PDBFile *Pdb) {
BinaryStreamReader Reader(*Stream);
if (Stream->getLength() < sizeof(DbiStreamHeader))
@@ -123,11 +123,11 @@ Error DbiStream::reload() {
if (auto EC = initializeSectionContributionData())
return EC;
- if (auto EC = initializeSectionHeadersData())
+ if (auto EC = initializeSectionHeadersData(Pdb))
return EC;
if (auto EC = initializeSectionMapData())
return EC;
- if (auto EC = initializeFpoRecords())
+ if (auto EC = initializeFpoRecords(Pdb))
return EC;
if (Reader.bytesRemaining() > 0)
@@ -246,7 +246,10 @@ Error DbiStream::initializeSectionContributionData() {
}
// Initializes this->SectionHeaders.
-Error DbiStream::initializeSectionHeadersData() {
+Error DbiStream::initializeSectionHeadersData(PDBFile *Pdb) {
+ if (!Pdb)
+ return Error::success();
+
if (DbgStreams.size() == 0)
return Error::success();
@@ -254,11 +257,11 @@ Error DbiStream::initializeSectionHeadersData() {
if (StreamNum == kInvalidStreamIndex)
return Error::success();
- if (StreamNum >= Pdb.getNumStreams())
+ if (StreamNum >= Pdb->getNumStreams())
return make_error<RawError>(raw_error_code::no_stream);
auto SHS = MappedBlockStream::createIndexedStream(
- Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator());
+ Pdb->getMsfLayout(), Pdb->getMsfBuffer(), StreamNum, Pdb->getAllocator());
size_t StreamLen = SHS->getLength();
if (StreamLen % sizeof(object::coff_section))
@@ -276,7 +279,10 @@ Error DbiStream::initializeSectionHeadersData() {
}
// Initializes this->Fpos.
-Error DbiStream::initializeFpoRecords() {
+Error DbiStream::initializeFpoRecords(PDBFile *Pdb) {
+ if (!Pdb)
+ return Error::success();
+
if (DbgStreams.size() == 0)
return Error::success();
@@ -286,11 +292,11 @@ Error DbiStream::initializeFpoRecords() {
if (StreamNum == kInvalidStreamIndex)
return Error::success();
- if (StreamNum >= Pdb.getNumStreams())
+ if (StreamNum >= Pdb->getNumStreams())
return make_error<RawError>(raw_error_code::no_stream);
auto FS = MappedBlockStream::createIndexedStream(
- Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator());
+ Pdb->getMsfLayout(), Pdb->getMsfBuffer(), StreamNum, Pdb->getAllocator());
size_t StreamLen = FS->getLength();
if (StreamLen % sizeof(object::FpoData))
diff --git a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
index c96553ff9b16..f6043bfd7cf9 100644
--- a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
@@ -27,7 +27,7 @@ using namespace llvm::pdb;
DbiStreamBuilder::DbiStreamBuilder(msf::MSFBuilder &Msf)
: Msf(Msf), Allocator(Msf.getAllocator()), Age(1), BuildNumber(0),
PdbDllVersion(0), PdbDllRbld(0), Flags(0), MachineType(PDB_Machine::x86),
- Header(nullptr), DbgStreams((int)DbgHeaderType::Max) {}
+ Header(nullptr) {}
DbiStreamBuilder::~DbiStreamBuilder() {}
@@ -37,6 +37,14 @@ void DbiStreamBuilder::setAge(uint32_t A) { Age = A; }
void DbiStreamBuilder::setBuildNumber(uint16_t B) { BuildNumber = B; }
+void DbiStreamBuilder::setBuildNumber(uint8_t Major, uint8_t Minor) {
+ BuildNumber = (uint16_t(Major) << DbiBuildNo::BuildMajorShift) &
+ DbiBuildNo::BuildMajorMask;
+ BuildNumber |= (uint16_t(Minor) << DbiBuildNo::BuildMinorShift) &
+ DbiBuildNo::BuildMinorMask;
+ BuildNumber |= DbiBuildNo::NewVersionFormatMask;
+}
+
void DbiStreamBuilder::setPdbDllVersion(uint16_t V) { PdbDllVersion = V; }
void DbiStreamBuilder::setPdbDllRbld(uint16_t R) { PdbDllRbld = R; }
@@ -45,6 +53,11 @@ void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; }
void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; }
+void DbiStreamBuilder::setMachineType(COFF::MachineTypes M) {
+ // These enums are mirrors of each other, so we can just cast the value.
+ MachineType = static_cast<pdb::PDB_Machine>(static_cast<unsigned>(M));
+}
+
void DbiStreamBuilder::setSectionMap(ArrayRef<SecMapEntry> SecMap) {
SectionMap = SecMap;
}
@@ -63,15 +76,8 @@ void DbiStreamBuilder::setPublicsStreamIndex(uint32_t Index) {
Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type,
ArrayRef<uint8_t> Data) {
- if (DbgStreams[(int)Type].StreamNumber != kInvalidStreamIndex)
- return make_error<RawError>(raw_error_code::duplicate_entry,
- "The specified stream type already exists");
- auto ExpectedIndex = Msf.addStream(Data.size());
- if (!ExpectedIndex)
- return ExpectedIndex.takeError();
- uint32_t Index = std::move(*ExpectedIndex);
- DbgStreams[(int)Type].Data = Data;
- DbgStreams[(int)Type].StreamNumber = Index;
+ DbgStreams[(int)Type].emplace();
+ DbgStreams[(int)Type]->Data = Data;
return Error::success();
}
@@ -258,7 +264,7 @@ Error DbiStreamBuilder::finalize() {
H->TypeServerSize = 0;
H->SymRecordStreamIndex = SymRecordStreamIndex;
H->PublicSymbolStreamIndex = PublicsStreamIndex;
- H->MFCTypeServerIndex = kInvalidStreamIndex;
+ H->MFCTypeServerIndex = 0; // Not sure what this is, but link.exe writes 0.
H->GlobalSymbolStreamIndex = GlobalsStreamIndex;
Header = H;
@@ -266,6 +272,15 @@ Error DbiStreamBuilder::finalize() {
}
Error DbiStreamBuilder::finalizeMsfLayout() {
+ for (auto &S : DbgStreams) {
+ if (!S.hasValue())
+ continue;
+ auto ExpectedIndex = Msf.addStream(S->Data.size());
+ if (!ExpectedIndex)
+ return ExpectedIndex.takeError();
+ S->StreamNumber = *ExpectedIndex;
+ }
+
for (auto &MI : ModiList) {
if (auto EC = MI->finalizeMsfLayout())
return EC;
@@ -375,17 +390,23 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
if (auto EC = ECNamesBuilder.commit(Writer))
return EC;
- for (auto &Stream : DbgStreams)
- if (auto EC = Writer.writeInteger(Stream.StreamNumber))
+ for (auto &Stream : DbgStreams) {
+ uint16_t StreamNumber = kInvalidStreamIndex;
+ if (Stream.hasValue())
+ StreamNumber = Stream->StreamNumber;
+ if (auto EC = Writer.writeInteger(StreamNumber))
return EC;
+ }
for (auto &Stream : DbgStreams) {
- if (Stream.StreamNumber == kInvalidStreamIndex)
+ if (!Stream.hasValue())
continue;
+ assert(Stream->StreamNumber != kInvalidStreamIndex);
+
auto WritableStream = WritableMappedBlockStream::createIndexedStream(
- Layout, MsfBuffer, Stream.StreamNumber, Allocator);
+ Layout, MsfBuffer, Stream->StreamNumber, Allocator);
BinaryStreamWriter DbgStreamWriter(*WritableStream);
- if (auto EC = DbgStreamWriter.writeArray(Stream.Data))
+ if (auto EC = DbgStreamWriter.writeArray(Stream->Data))
return EC;
}
diff --git a/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
index e84f25dfeefa..58efc2256ae1 100644
--- a/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
@@ -82,8 +82,29 @@ Error GSIHashStreamBuilder::commit(BinaryStreamWriter &Writer) {
return Error::success();
}
+static bool isAsciiString(StringRef S) {
+ return llvm::all_of(S, [](char C) { return unsigned(C) < 0x80; });
+}
+
+// See `caseInsensitiveComparePchPchCchCch` in gsi.cpp
+static bool gsiRecordLess(StringRef S1, StringRef S2) {
+ size_t LS = S1.size();
+ size_t RS = S2.size();
+ // Shorter strings always compare less than longer strings.
+ if (LS != RS)
+ return LS < RS;
+
+ // If either string contains non ascii characters, memcmp them.
+ if (LLVM_UNLIKELY(!isAsciiString(S1) || !isAsciiString(S2)))
+ return memcmp(S1.data(), S2.data(), LS) < 0;
+
+ // Both strings are ascii, perform a case-insenstive comparison.
+ return S1.compare_lower(S2.data()) < 0;
+}
+
void GSIHashStreamBuilder::finalizeBuckets(uint32_t RecordZeroOffset) {
- std::array<std::vector<PSHashRecord>, IPHR_HASH + 1> TmpBuckets;
+ std::array<std::vector<std::pair<StringRef, PSHashRecord>>, IPHR_HASH + 1>
+ TmpBuckets;
uint32_t SymOffset = RecordZeroOffset;
for (const CVSymbol &Sym : Records) {
PSHashRecord HR;
@@ -94,8 +115,7 @@ void GSIHashStreamBuilder::finalizeBuckets(uint32_t RecordZeroOffset) {
// Hash the name to figure out which bucket this goes into.
StringRef Name = getSymbolName(Sym);
size_t BucketIdx = hashStringV1(Name) % IPHR_HASH;
- TmpBuckets[BucketIdx].push_back(HR); // FIXME: Does order matter?
-
+ TmpBuckets[BucketIdx].push_back(std::make_pair(Name, HR));
SymOffset += Sym.length();
}
@@ -117,8 +137,21 @@ void GSIHashStreamBuilder::finalizeBuckets(uint32_t RecordZeroOffset) {
ulittle32_t ChainStartOff =
ulittle32_t(HashRecords.size() * SizeOfHROffsetCalc);
HashBuckets.push_back(ChainStartOff);
- for (const auto &HR : Bucket)
- HashRecords.push_back(HR);
+
+ // Sort each bucket by memcmp of the symbol's name. It's important that
+ // we use the same sorting algorithm as is used by the reference
+ // implementation to ensure that the search for a record within a bucket
+ // can properly early-out when it detects the record won't be found. The
+ // algorithm used here corredsponds to the function
+ // caseInsensitiveComparePchPchCchCch in the reference implementation.
+ llvm::sort(Bucket.begin(), Bucket.end(),
+ [](const std::pair<StringRef, PSHashRecord> &Left,
+ const std::pair<StringRef, PSHashRecord> &Right) {
+ return gsiRecordLess(Left.first, Right.first);
+ });
+
+ for (const auto &Entry : Bucket)
+ HashRecords.push_back(Entry.second);
}
}
@@ -150,14 +183,14 @@ Error GSIStreamBuilder::finalizeMsfLayout() {
PSH->finalizeBuckets(PSHZero);
GSH->finalizeBuckets(GSHZero);
- Expected<uint32_t> Idx = Msf.addStream(calculatePublicsHashStreamSize());
+ Expected<uint32_t> Idx = Msf.addStream(calculateGlobalsHashStreamSize());
if (!Idx)
return Idx.takeError();
- PSH->StreamIndex = *Idx;
- Idx = Msf.addStream(calculateGlobalsHashStreamSize());
+ GSH->StreamIndex = *Idx;
+ Idx = Msf.addStream(calculatePublicsHashStreamSize());
if (!Idx)
return Idx.takeError();
- GSH->StreamIndex = *Idx;
+ PSH->StreamIndex = *Idx;
uint32_t RecordBytes =
GSH->calculateRecordByteSize() + PSH->calculateRecordByteSize();
diff --git a/lib/DebugInfo/PDB/Native/HashTable.cpp b/lib/DebugInfo/PDB/Native/HashTable.cpp
index 439217f91d04..cfabc9cd1ad8 100644
--- a/lib/DebugInfo/PDB/Native/HashTable.cpp
+++ b/lib/DebugInfo/PDB/Native/HashTable.cpp
@@ -22,200 +22,7 @@
using namespace llvm;
using namespace llvm::pdb;
-HashTable::HashTable() : HashTable(8) {}
-
-HashTable::HashTable(uint32_t Capacity) { Buckets.resize(Capacity); }
-
-Error HashTable::load(BinaryStreamReader &Stream) {
- const Header *H;
- if (auto EC = Stream.readObject(H))
- return EC;
- if (H->Capacity == 0)
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Invalid Hash Table Capacity");
- if (H->Size > maxLoad(H->Capacity))
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Invalid Hash Table Size");
-
- Buckets.resize(H->Capacity);
-
- if (auto EC = readSparseBitVector(Stream, Present))
- return EC;
- if (Present.count() != H->Size)
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Present bit vector does not match size!");
-
- if (auto EC = readSparseBitVector(Stream, Deleted))
- return EC;
- if (Present.intersects(Deleted))
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Present bit vector interesects deleted!");
-
- for (uint32_t P : Present) {
- if (auto EC = Stream.readInteger(Buckets[P].first))
- return EC;
- if (auto EC = Stream.readInteger(Buckets[P].second))
- return EC;
- }
-
- return Error::success();
-}
-
-uint32_t HashTable::calculateSerializedLength() const {
- uint32_t Size = sizeof(Header);
-
- int NumBitsP = Present.find_last() + 1;
- int NumBitsD = Deleted.find_last() + 1;
-
- // Present bit set number of words, followed by that many actual words.
- Size += sizeof(uint32_t);
- Size += alignTo(NumBitsP, sizeof(uint32_t));
-
- // Deleted bit set number of words, followed by that many actual words.
- Size += sizeof(uint32_t);
- Size += alignTo(NumBitsD, sizeof(uint32_t));
-
- // One (Key, Value) pair for each entry Present.
- Size += 2 * sizeof(uint32_t) * size();
-
- return Size;
-}
-
-Error HashTable::commit(BinaryStreamWriter &Writer) const {
- Header H;
- H.Size = size();
- H.Capacity = capacity();
- if (auto EC = Writer.writeObject(H))
- return EC;
-
- if (auto EC = writeSparseBitVector(Writer, Present))
- return EC;
-
- if (auto EC = writeSparseBitVector(Writer, Deleted))
- return EC;
-
- for (const auto &Entry : *this) {
- if (auto EC = Writer.writeInteger(Entry.first))
- return EC;
- if (auto EC = Writer.writeInteger(Entry.second))
- return EC;
- }
- return Error::success();
-}
-
-void HashTable::clear() {
- Buckets.resize(8);
- Present.clear();
- Deleted.clear();
-}
-
-uint32_t HashTable::capacity() const { return Buckets.size(); }
-
-uint32_t HashTable::size() const { return Present.count(); }
-
-HashTableIterator HashTable::begin() const { return HashTableIterator(*this); }
-
-HashTableIterator HashTable::end() const {
- return HashTableIterator(*this, 0, true);
-}
-
-HashTableIterator HashTable::find(uint32_t K) {
- uint32_t H = K % capacity();
- uint32_t I = H;
- Optional<uint32_t> FirstUnused;
- do {
- if (isPresent(I)) {
- if (Buckets[I].first == K)
- return HashTableIterator(*this, I, false);
- } else {
- if (!FirstUnused)
- FirstUnused = I;
- // Insertion occurs via linear probing from the slot hint, and will be
- // inserted at the first empty / deleted location. Therefore, if we are
- // probing and find a location that is neither present nor deleted, then
- // nothing must have EVER been inserted at this location, and thus it is
- // not possible for a matching value to occur later.
- if (!isDeleted(I))
- break;
- }
- I = (I + 1) % capacity();
- } while (I != H);
-
- // The only way FirstUnused would not be set is if every single entry in the
- // table were Present. But this would violate the load factor constraints
- // that we impose, so it should never happen.
- assert(FirstUnused);
- return HashTableIterator(*this, *FirstUnused, true);
-}
-
-void HashTable::set(uint32_t K, uint32_t V) {
- auto Entry = find(K);
- if (Entry != end()) {
- assert(isPresent(Entry.index()));
- assert(Buckets[Entry.index()].first == K);
- // We're updating, no need to do anything special.
- Buckets[Entry.index()].second = V;
- return;
- }
-
- auto &B = Buckets[Entry.index()];
- assert(!isPresent(Entry.index()));
- assert(Entry.isEnd());
- B.first = K;
- B.second = V;
- Present.set(Entry.index());
- Deleted.reset(Entry.index());
-
- grow();
-
- assert(find(K) != end());
-}
-
-void HashTable::remove(uint32_t K) {
- auto Iter = find(K);
- // It wasn't here to begin with, just exit.
- if (Iter == end())
- return;
-
- assert(Present.test(Iter.index()));
- assert(!Deleted.test(Iter.index()));
- Deleted.set(Iter.index());
- Present.reset(Iter.index());
-}
-
-uint32_t HashTable::get(uint32_t K) {
- auto I = find(K);
- assert(I != end());
- return (*I).second;
-}
-
-uint32_t HashTable::maxLoad(uint32_t capacity) { return capacity * 2 / 3 + 1; }
-
-void HashTable::grow() {
- uint32_t S = size();
- if (S < maxLoad(capacity()))
- return;
- assert(capacity() != UINT32_MAX && "Can't grow Hash table!");
-
- uint32_t NewCapacity =
- (capacity() <= INT32_MAX) ? capacity() * 2 : UINT32_MAX;
-
- // Growing requires rebuilding the table and re-hashing every item. Make a
- // copy with a larger capacity, insert everything into the copy, then swap
- // it in.
- HashTable NewMap(NewCapacity);
- for (auto I : Present) {
- NewMap.set(Buckets[I].first, Buckets[I].second);
- }
-
- Buckets.swap(NewMap.Buckets);
- std::swap(Present, NewMap.Present);
- std::swap(Deleted, NewMap.Deleted);
- assert(capacity() == NewCapacity);
- assert(size() == S);
-}
-
-Error HashTable::readSparseBitVector(BinaryStreamReader &Stream,
+Error llvm::pdb::readSparseBitVector(BinaryStreamReader &Stream,
SparseBitVector<> &V) {
uint32_t NumWords;
if (auto EC = Stream.readInteger(NumWords))
@@ -237,18 +44,20 @@ Error HashTable::readSparseBitVector(BinaryStreamReader &Stream,
return Error::success();
}
-Error HashTable::writeSparseBitVector(BinaryStreamWriter &Writer,
+Error llvm::pdb::writeSparseBitVector(BinaryStreamWriter &Writer,
SparseBitVector<> &Vec) {
+ constexpr int BitsPerWord = 8 * sizeof(uint32_t);
+
int ReqBits = Vec.find_last() + 1;
- uint32_t NumWords = alignTo(ReqBits, sizeof(uint32_t)) / sizeof(uint32_t);
- if (auto EC = Writer.writeInteger(NumWords))
+ uint32_t ReqWords = alignTo(ReqBits, BitsPerWord) / BitsPerWord;
+ if (auto EC = Writer.writeInteger(ReqWords))
return joinErrors(
std::move(EC),
make_error<RawError>(raw_error_code::corrupt_file,
"Could not write linear map number of words"));
uint32_t Idx = 0;
- for (uint32_t I = 0; I != NumWords; ++I) {
+ for (uint32_t I = 0; I != ReqWords; ++I) {
uint32_t Word = 0;
for (uint32_t WordIdx = 0; WordIdx < 32; ++WordIdx, ++Idx) {
if (Vec.test(Idx))
@@ -261,48 +70,3 @@ Error HashTable::writeSparseBitVector(BinaryStreamWriter &Writer,
}
return Error::success();
}
-
-HashTableIterator::HashTableIterator(const HashTable &Map, uint32_t Index,
- bool IsEnd)
- : Map(&Map), Index(Index), IsEnd(IsEnd) {}
-
-HashTableIterator::HashTableIterator(const HashTable &Map) : Map(&Map) {
- int I = Map.Present.find_first();
- if (I == -1) {
- Index = 0;
- IsEnd = true;
- } else {
- Index = static_cast<uint32_t>(I);
- IsEnd = false;
- }
-}
-
-HashTableIterator &HashTableIterator::operator=(const HashTableIterator &R) {
- Map = R.Map;
- return *this;
-}
-
-bool HashTableIterator::operator==(const HashTableIterator &R) const {
- if (IsEnd && R.IsEnd)
- return true;
- if (IsEnd != R.IsEnd)
- return false;
-
- return (Map == R.Map) && (Index == R.Index);
-}
-
-const std::pair<uint32_t, uint32_t> &HashTableIterator::operator*() const {
- assert(Map->Present.test(Index));
- return Map->Buckets[Index];
-}
-
-HashTableIterator &HashTableIterator::operator++() {
- while (Index < Map->Buckets.size()) {
- ++Index;
- if (Map->Present.test(Index))
- return *this;
- }
-
- IsEnd = true;
- return *this;
-}
diff --git a/lib/DebugInfo/PDB/Native/InfoStream.cpp b/lib/DebugInfo/PDB/Native/InfoStream.cpp
index 17c9392a9dd5..973a520ffca9 100644
--- a/lib/DebugInfo/PDB/Native/InfoStream.cpp
+++ b/lib/DebugInfo/PDB/Native/InfoStream.cpp
@@ -20,20 +20,19 @@ using namespace llvm::codeview;
using namespace llvm::msf;
using namespace llvm::pdb;
-InfoStream::InfoStream(std::unique_ptr<MappedBlockStream> Stream)
- : Stream(std::move(Stream)) {}
+InfoStream::InfoStream(std::unique_ptr<BinaryStream> Stream)
+ : Stream(std::move(Stream)), Header(nullptr) {}
Error InfoStream::reload() {
BinaryStreamReader Reader(*Stream);
- const InfoStreamHeader *H;
- if (auto EC = Reader.readObject(H))
+ if (auto EC = Reader.readObject(Header))
return joinErrors(
std::move(EC),
make_error<RawError>(raw_error_code::corrupt_file,
"PDB Stream does not contain a header."));
- switch (H->Version) {
+ switch (Header->Version) {
case PdbImplVC70:
case PdbImplVC80:
case PdbImplVC110:
@@ -44,11 +43,6 @@ Error InfoStream::reload() {
"Unsupported PDB stream version.");
}
- Version = H->Version;
- Signature = H->Signature;
- Age = H->Age;
- Guid = H->Guid;
-
uint32_t Offset = Reader.getOffset();
if (auto EC = NamedStreams.load(Reader))
return EC;
@@ -92,15 +86,14 @@ Error InfoStream::reload() {
uint32_t InfoStream::getStreamSize() const { return Stream->getLength(); }
-uint32_t InfoStream::getNamedStreamIndex(llvm::StringRef Name) const {
+Expected<uint32_t> InfoStream::getNamedStreamIndex(llvm::StringRef Name) const {
uint32_t Result;
if (!NamedStreams.get(Name, Result))
- return 0;
+ return make_error<RawError>(raw_error_code::no_stream);
return Result;
}
-iterator_range<StringMapConstIterator<uint32_t>>
-InfoStream::named_streams() const {
+StringMap<uint32_t> InfoStream::named_streams() const {
return NamedStreams.entries();
}
@@ -109,14 +102,16 @@ bool InfoStream::containsIdStream() const {
}
PdbRaw_ImplVer InfoStream::getVersion() const {
- return static_cast<PdbRaw_ImplVer>(Version);
+ return static_cast<PdbRaw_ImplVer>(uint32_t(Header->Version));
}
-uint32_t InfoStream::getSignature() const { return Signature; }
+uint32_t InfoStream::getSignature() const {
+ return uint32_t(Header->Signature);
+}
-uint32_t InfoStream::getAge() const { return Age; }
+uint32_t InfoStream::getAge() const { return uint32_t(Header->Age); }
-GUID InfoStream::getGuid() const { return Guid; }
+GUID InfoStream::getGuid() const { return Header->Guid; }
uint32_t InfoStream::getNamedStreamMapByteSize() const {
return NamedStreamMapByteSize;
diff --git a/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
index 6450ae752f96..54d6835f1121 100644
--- a/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
@@ -25,15 +25,17 @@ using namespace llvm::pdb;
InfoStreamBuilder::InfoStreamBuilder(msf::MSFBuilder &Msf,
NamedStreamMap &NamedStreams)
- : Msf(Msf), Ver(PdbRaw_ImplVer::PdbImplVC70), Sig(-1), Age(0),
- NamedStreams(NamedStreams) {}
+ : Msf(Msf), Ver(PdbRaw_ImplVer::PdbImplVC70), Age(0),
+ NamedStreams(NamedStreams) {
+ ::memset(&Guid, 0, sizeof(Guid));
+}
void InfoStreamBuilder::setVersion(PdbRaw_ImplVer V) { Ver = V; }
-void InfoStreamBuilder::setSignature(uint32_t S) { Sig = S; }
-
void InfoStreamBuilder::setAge(uint32_t A) { Age = A; }
+void InfoStreamBuilder::setSignature(uint32_t S) { Signature = S; }
+
void InfoStreamBuilder::setGuid(GUID G) { Guid = G; }
void InfoStreamBuilder::addFeature(PdbRaw_FeatureSig Sig) {
@@ -41,7 +43,8 @@ void InfoStreamBuilder::addFeature(PdbRaw_FeatureSig Sig) {
}
Error InfoStreamBuilder::finalizeMsfLayout() {
- uint32_t Length = sizeof(InfoStreamHeader) + NamedStreams.finalize() +
+ uint32_t Length = sizeof(InfoStreamHeader) +
+ NamedStreams.calculateSerializedLength() +
(Features.size() + 1) * sizeof(uint32_t);
if (auto EC = Msf.setStreamSize(StreamPDB, Length))
return EC;
@@ -55,10 +58,10 @@ Error InfoStreamBuilder::commit(const msf::MSFLayout &Layout,
BinaryStreamWriter Writer(*InfoS);
InfoStreamHeader H;
- H.Age = Age;
- H.Signature = Sig;
+ // Leave the build id fields 0 so they can be set as the last step before
+ // committing the file to disk.
+ ::memset(&H, 0, sizeof(H));
H.Version = Ver;
- H.Guid = Guid;
if (auto EC = Writer.writeObject(H))
return EC;
@@ -70,5 +73,6 @@ Error InfoStreamBuilder::commit(const msf::MSFLayout &Layout,
if (auto EC = Writer.writeEnum(E))
return EC;
}
+ assert(Writer.bytesRemaining() == 0);
return Error::success();
}
diff --git a/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp b/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp
index 6cdf6dde04d9..a4eaed90837d 100644
--- a/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp
+++ b/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp
@@ -11,6 +11,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
#include "llvm/DebugInfo/PDB/Native/HashTable.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
#include "llvm/Support/BinaryStreamReader.h"
@@ -26,127 +27,101 @@
using namespace llvm;
using namespace llvm::pdb;
-// FIXME: This shouldn't be necessary, but if we insert the strings in any
-// other order, cvdump cannot read the generated name map. This suggests that
-// we may be using the wrong hash function. A closer inspection of the cvdump
-// source code may reveal something, but for now this at least makes us work,
-// even if only by accident.
-static constexpr const char *OrderedStreamNames[] = {"/LinkInfo", "/names",
- "/src/headerblock"};
+NamedStreamMapTraits::NamedStreamMapTraits(NamedStreamMap &NS) : NS(&NS) {}
-NamedStreamMap::NamedStreamMap() = default;
+uint16_t NamedStreamMapTraits::hashLookupKey(StringRef S) const {
+ // In the reference implementation, this uses
+ // HASH Hasher<ULONG*, USHORT*>::hashPbCb(PB pb, size_t cb, ULONG ulMod).
+ // Here, the type HASH is a typedef of unsigned short.
+ // ** It is not a bug that we truncate the result of hashStringV1, in fact
+ // it is a bug if we do not! **
+ return static_cast<uint16_t>(hashStringV1(S));
+}
-Error NamedStreamMap::load(BinaryStreamReader &Stream) {
- Mapping.clear();
- FinalizedHashTable.clear();
- FinalizedInfo.reset();
+StringRef NamedStreamMapTraits::storageKeyToLookupKey(uint32_t Offset) const {
+ return NS->getString(Offset);
+}
+uint32_t NamedStreamMapTraits::lookupKeyToStorageKey(StringRef S) {
+ return NS->appendStringData(S);
+}
+
+NamedStreamMap::NamedStreamMap()
+ : HashTraits(*this), OffsetIndexMap(1, HashTraits) {}
+
+Error NamedStreamMap::load(BinaryStreamReader &Stream) {
uint32_t StringBufferSize;
if (auto EC = Stream.readInteger(StringBufferSize))
return joinErrors(std::move(EC),
make_error<RawError>(raw_error_code::corrupt_file,
"Expected string buffer size"));
- BinaryStreamRef StringsBuffer;
- if (auto EC = Stream.readStreamRef(StringsBuffer, StringBufferSize))
+ StringRef Buffer;
+ if (auto EC = Stream.readFixedString(Buffer, StringBufferSize))
return EC;
+ NamesBuffer.assign(Buffer.begin(), Buffer.end());
- HashTable OffsetIndexMap;
- if (auto EC = OffsetIndexMap.load(Stream))
- return EC;
-
- uint32_t NameOffset;
- uint32_t NameIndex;
- for (const auto &Entry : OffsetIndexMap) {
- std::tie(NameOffset, NameIndex) = Entry;
-
- // Compute the offset of the start of the string relative to the stream.
- BinaryStreamReader NameReader(StringsBuffer);
- NameReader.setOffset(NameOffset);
- // Pump out our c-string from the stream.
- StringRef Str;
- if (auto EC = NameReader.readCString(Str))
- return joinErrors(std::move(EC),
- make_error<RawError>(raw_error_code::corrupt_file,
- "Expected name map name"));
-
- // Add this to a string-map from name to stream number.
- Mapping.insert({Str, NameIndex});
- }
-
- return Error::success();
+ return OffsetIndexMap.load(Stream);
}
Error NamedStreamMap::commit(BinaryStreamWriter &Writer) const {
- assert(FinalizedInfo.hasValue());
-
// The first field is the number of bytes of string data.
- if (auto EC = Writer.writeInteger(FinalizedInfo->StringDataBytes))
+ if (auto EC = Writer.writeInteger<uint32_t>(NamesBuffer.size()))
return EC;
- for (const auto &Name : OrderedStreamNames) {
- auto Item = Mapping.find(Name);
- if (Item == Mapping.end())
- continue;
- if (auto EC = Writer.writeCString(Item->getKey()))
- return EC;
- }
+ // Then the actual string data.
+ StringRef Data(NamesBuffer.data(), NamesBuffer.size());
+ if (auto EC = Writer.writeFixedString(Data))
+ return EC;
// And finally the Offset Index map.
- if (auto EC = FinalizedHashTable.commit(Writer))
+ if (auto EC = OffsetIndexMap.commit(Writer))
return EC;
return Error::success();
}
-uint32_t NamedStreamMap::finalize() {
- if (FinalizedInfo.hasValue())
- return FinalizedInfo->SerializedLength;
-
- // Build the finalized hash table.
- FinalizedHashTable.clear();
- FinalizedInfo.emplace();
+uint32_t NamedStreamMap::calculateSerializedLength() const {
+ return sizeof(uint32_t) // String data size
+ + NamesBuffer.size() // String data
+ + OffsetIndexMap.calculateSerializedLength(); // Offset Index Map
+}
- for (const auto &Name : OrderedStreamNames) {
- auto Item = Mapping.find(Name);
- if (Item == Mapping.end())
- continue;
- FinalizedHashTable.set(FinalizedInfo->StringDataBytes, Item->getValue());
- FinalizedInfo->StringDataBytes += Item->getKeyLength() + 1;
- }
+uint32_t NamedStreamMap::size() const { return OffsetIndexMap.size(); }
- // Number of bytes of string data.
- FinalizedInfo->SerializedLength += sizeof(support::ulittle32_t);
- // Followed by that many actual bytes of string data.
- FinalizedInfo->SerializedLength += FinalizedInfo->StringDataBytes;
- // Followed by the mapping from Offset to Index.
- FinalizedInfo->SerializedLength +=
- FinalizedHashTable.calculateSerializedLength();
- return FinalizedInfo->SerializedLength;
+StringRef NamedStreamMap::getString(uint32_t Offset) const {
+ assert(NamesBuffer.size() > Offset);
+ return StringRef(NamesBuffer.data() + Offset);
}
-iterator_range<StringMapConstIterator<uint32_t>>
-NamedStreamMap::entries() const {
- return make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(),
- Mapping.end());
+uint32_t NamedStreamMap::hashString(uint32_t Offset) const {
+ return hashStringV1(getString(Offset));
}
-uint32_t NamedStreamMap::size() const { return Mapping.size(); }
-
bool NamedStreamMap::get(StringRef Stream, uint32_t &StreamNo) const {
- auto Iter = Mapping.find(Stream);
- if (Iter == Mapping.end())
+ auto Iter = OffsetIndexMap.find_as(Stream);
+ if (Iter == OffsetIndexMap.end())
return false;
- StreamNo = Iter->second;
+ StreamNo = (*Iter).second;
return true;
}
-void NamedStreamMap::set(StringRef Stream, uint32_t StreamNo) {
- FinalizedInfo.reset();
- Mapping[Stream] = StreamNo;
+StringMap<uint32_t> NamedStreamMap::entries() const {
+ StringMap<uint32_t> Result;
+ for (const auto &Entry : OffsetIndexMap) {
+ StringRef Stream(NamesBuffer.data() + Entry.first);
+ Result.try_emplace(Stream, Entry.second);
+ }
+ return Result;
}
-void NamedStreamMap::remove(StringRef Stream) {
- FinalizedInfo.reset();
- Mapping.erase(Stream);
+uint32_t NamedStreamMap::appendStringData(StringRef S) {
+ uint32_t Offset = NamesBuffer.size();
+ NamesBuffer.insert(NamesBuffer.end(), S.begin(), S.end());
+ NamesBuffer.push_back('\0');
+ return Offset;
+}
+
+void NamedStreamMap::set(StringRef Stream, uint32_t StreamNo) {
+ OffsetIndexMap.set_as(Stream, support::ulittle32_t(StreamNo));
}
diff --git a/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
index d23ee0a09196..a4b029596314 100644
--- a/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
+++ b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
@@ -30,16 +31,60 @@ NativeRawSymbol::findChildren(PDB_SymType Type, StringRef Name,
}
std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findChildrenByAddr(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags, uint32_t Section, uint32_t Offset) const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findChildrenByVA(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags, uint64_t VA) const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumSymbols>
NativeRawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name,
PDB_NameSearchFlags Flags, uint32_t RVA) const {
return nullptr;
}
std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findInlineFramesByAddr(uint32_t Section,
+ uint32_t Offset) const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumSymbols>
NativeRawSymbol::findInlineFramesByRVA(uint32_t RVA) const {
return nullptr;
}
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findInlineFramesByVA(uint64_t VA) const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeRawSymbol::findInlineeLines() const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeRawSymbol::findInlineeLinesByAddr(uint32_t Section, uint32_t Offset,
+ uint32_t Length) const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeRawSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeRawSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const {
+ return nullptr;
+}
+
void NativeRawSymbol::getDataBytes(SmallVector<uint8_t, 32> &bytes) const {
bytes.clear();
}
@@ -143,7 +188,7 @@ uint32_t NativeRawSymbol::getLiveRangeStartRelativeVirtualAddress() const {
}
codeview::RegisterId NativeRawSymbol::getLocalBasePointerRegisterId() const {
- return codeview::RegisterId::EAX;
+ return codeview::RegisterId::CVRegEAX;
}
uint32_t NativeRawSymbol::getLowerBoundId() const {
@@ -203,7 +248,7 @@ uint32_t NativeRawSymbol::getRank() const {
}
codeview::RegisterId NativeRawSymbol::getRegisterId() const {
- return codeview::RegisterId::EAX;
+ return codeview::RegisterId::CVRegEAX;
}
uint32_t NativeRawSymbol::getRegisterType() const {
@@ -234,6 +279,11 @@ std::string NativeRawSymbol::getSourceFileName() const {
return {};
}
+std::unique_ptr<IPDBLineNumber>
+NativeRawSymbol::getSrcLineOnTypeDefn() const {
+ return nullptr;
+}
+
uint32_t NativeRawSymbol::getStride() const {
return 0;
}
diff --git a/lib/DebugInfo/PDB/Native/NativeSession.cpp b/lib/DebugInfo/PDB/Native/NativeSession.cpp
index b01c2b54796c..086da13135c5 100644
--- a/lib/DebugInfo/PDB/Native/NativeSession.cpp
+++ b/lib/DebugInfo/PDB/Native/NativeSession.cpp
@@ -165,7 +165,7 @@ SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) {
uint64_t NativeSession::getLoadAddress() const { return 0; }
-void NativeSession::setLoadAddress(uint64_t Address) {}
+bool NativeSession::setLoadAddress(uint64_t Address) { return false; }
std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() {
const auto Id = static_cast<SymIndexId>(SymbolCache.size());
@@ -185,11 +185,32 @@ NativeSession::getSymbolById(uint32_t SymbolId) const {
: nullptr;
}
+bool NativeSession::addressForVA(uint64_t VA, uint32_t &Section,
+ uint32_t &Offset) const {
+ return false;
+}
+
+bool NativeSession::addressForRVA(uint32_t VA, uint32_t &Section,
+ uint32_t &Offset) const {
+ return false;
+}
+
std::unique_ptr<PDBSymbol>
NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
return nullptr;
}
+std::unique_ptr<PDBSymbol>
+NativeSession::findSymbolByRVA(uint32_t RVA, PDB_SymType Type) const {
+ return nullptr;
+}
+
+std::unique_ptr<PDBSymbol>
+NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
+ PDB_SymType Type) const {
+ return nullptr;
+}
+
std::unique_ptr<IPDBEnumLineNumbers>
NativeSession::findLineNumbers(const PDBSymbolCompiland &Compiland,
const IPDBSourceFile &File) const {
@@ -202,6 +223,17 @@ NativeSession::findLineNumbersByAddress(uint64_t Address,
return nullptr;
}
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeSession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeSession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset,
+ uint32_t Length) const {
+ return nullptr;
+}
+
std::unique_ptr<IPDBEnumSourceFiles>
NativeSession::findSourceFiles(const PDBSymbolCompiland *Compiland,
StringRef Pattern,
@@ -249,3 +281,13 @@ std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const {
std::unique_ptr<IPDBEnumTables> NativeSession::getEnumTables() const {
return nullptr;
}
+
+std::unique_ptr<IPDBEnumInjectedSources>
+NativeSession::getInjectedSources() const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumSectionContribs>
+NativeSession::getSectionContribs() const {
+ return nullptr;
+}
diff --git a/lib/DebugInfo/PDB/Native/PDBFile.cpp b/lib/DebugInfo/PDB/Native/PDBFile.cpp
index 15b31d821b1c..78b11937f051 100644
--- a/lib/DebugInfo/PDB/Native/PDBFile.cpp
+++ b/lib/DebugInfo/PDB/Native/PDBFile.cpp
@@ -289,8 +289,8 @@ Expected<DbiStream &> PDBFile::getPDBDbiStream() {
auto DbiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamDBI);
if (!DbiS)
return DbiS.takeError();
- auto TempDbi = llvm::make_unique<DbiStream>(*this, std::move(*DbiS));
- if (auto EC = TempDbi->reload())
+ auto TempDbi = llvm::make_unique<DbiStream>(std::move(*DbiS));
+ if (auto EC = TempDbi->reload(this))
return std::move(EC);
Dbi = std::move(TempDbi);
}
@@ -370,7 +370,10 @@ Expected<PDBStringTable &> PDBFile::getStringTable() {
if (!IS)
return IS.takeError();
- uint32_t NameStreamIndex = IS->getNamedStreamIndex("/names");
+ Expected<uint32_t> ExpectedNSI = IS->getNamedStreamIndex("/names");
+ if (!ExpectedNSI)
+ return ExpectedNSI.takeError();
+ uint32_t NameStreamIndex = *ExpectedNSI;
auto NS =
safelyCreateIndexedStream(ContainerLayout, *Buffer, NameStreamIndex);
@@ -445,7 +448,13 @@ bool PDBFile::hasPDBStringTable() {
auto IS = getPDBInfoStream();
if (!IS)
return false;
- return IS->getNamedStreamIndex("/names") < getNumStreams();
+ Expected<uint32_t> ExpectedNSI = IS->getNamedStreamIndex("/names");
+ if (!ExpectedNSI) {
+ consumeError(ExpectedNSI.takeError());
+ return false;
+ }
+ assert(*ExpectedNSI < getNumStreams());
+ return true;
}
/// Wrapper around MappedBlockStream::createIndexedStream() that checks if a
diff --git a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
index dee27c621fac..e164e7cf1c52 100644
--- a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
@@ -24,6 +24,8 @@
#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
#include "llvm/Support/BinaryStream.h"
#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/JamCRC.h"
+#include "llvm/Support/Path.h"
using namespace llvm;
using namespace llvm::codeview;
@@ -32,7 +34,8 @@ using namespace llvm::pdb;
using namespace llvm::support;
PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
- : Allocator(Allocator) {}
+ : Allocator(Allocator), InjectedSourceHashTraits(Strings),
+ InjectedSourceTable(2, InjectedSourceHashTraits) {}
PDBFileBuilder::~PDBFileBuilder() {}
@@ -80,15 +83,46 @@ GSIStreamBuilder &PDBFileBuilder::getGsiBuilder() {
return *Gsi;
}
-Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) {
+Expected<uint32_t> PDBFileBuilder::allocateNamedStream(StringRef Name,
+ uint32_t Size) {
auto ExpectedStream = Msf->addStream(Size);
- if (!ExpectedStream)
- return ExpectedStream.takeError();
- NamedStreams.set(Name, *ExpectedStream);
+ if (ExpectedStream)
+ NamedStreams.set(Name, *ExpectedStream);
+ return ExpectedStream;
+}
+
+Error PDBFileBuilder::addNamedStream(StringRef Name, StringRef Data) {
+ Expected<uint32_t> ExpectedIndex = allocateNamedStream(Name, Data.size());
+ if (!ExpectedIndex)
+ return ExpectedIndex.takeError();
+ assert(NamedStreamData.count(*ExpectedIndex) == 0);
+ NamedStreamData[*ExpectedIndex] = Data;
return Error::success();
}
-Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
+void PDBFileBuilder::addInjectedSource(StringRef Name,
+ std::unique_ptr<MemoryBuffer> Buffer) {
+ // Stream names must be exact matches, since they get looked up in a hash
+ // table and the hash value is dependent on the exact contents of the string.
+ // link.exe lowercases a path and converts / to \, so we must do the same.
+ SmallString<64> VName;
+ sys::path::native(Name.lower(), VName);
+
+ uint32_t NI = getStringTableBuilder().insert(Name);
+ uint32_t VNI = getStringTableBuilder().insert(VName);
+
+ InjectedSourceDescriptor Desc;
+ Desc.Content = std::move(Buffer);
+ Desc.NameIndex = NI;
+ Desc.VNameIndex = VNI;
+ Desc.StreamName = "/src/files/";
+
+ Desc.StreamName += VName;
+
+ InjectedSources.push_back(std::move(Desc));
+}
+
+Error PDBFileBuilder::finalizeMsfLayout() {
if (Ipi && Ipi->getRecordCount() > 0) {
// In theory newer PDBs always have an ID stream, but by saying that we're
@@ -101,38 +135,85 @@ Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
uint32_t StringsLen = Strings.calculateSerializedSize();
- if (auto EC = addNamedStream("/names", StringsLen))
- return std::move(EC);
- if (auto EC = addNamedStream("/LinkInfo", 0))
- return std::move(EC);
+ Expected<uint32_t> SN = allocateNamedStream("/LinkInfo", 0);
+ if (!SN)
+ return SN.takeError();
- if (Info) {
- if (auto EC = Info->finalizeMsfLayout())
- return std::move(EC);
- }
- if (Dbi) {
- if (auto EC = Dbi->finalizeMsfLayout())
- return std::move(EC);
+ if (Gsi) {
+ if (auto EC = Gsi->finalizeMsfLayout())
+ return EC;
+ if (Dbi) {
+ Dbi->setPublicsStreamIndex(Gsi->getPublicsStreamIndex());
+ Dbi->setGlobalsStreamIndex(Gsi->getGlobalsStreamIndex());
+ Dbi->setSymbolRecordStreamIndex(Gsi->getRecordStreamIdx());
+ }
}
if (Tpi) {
if (auto EC = Tpi->finalizeMsfLayout())
- return std::move(EC);
+ return EC;
}
+ if (Dbi) {
+ if (auto EC = Dbi->finalizeMsfLayout())
+ return EC;
+ }
+ SN = allocateNamedStream("/names", StringsLen);
+ if (!SN)
+ return SN.takeError();
+
if (Ipi) {
if (auto EC = Ipi->finalizeMsfLayout())
- return std::move(EC);
+ return EC;
}
- if (Gsi) {
- if (auto EC = Gsi->finalizeMsfLayout())
- return std::move(EC);
- if (Dbi) {
- Dbi->setPublicsStreamIndex(Gsi->getPublicsStreamIndex());
- Dbi->setGlobalsStreamIndex(Gsi->getGlobalsStreamIndex());
- Dbi->setSymbolRecordStreamIndex(Gsi->getRecordStreamIdx());
+
+ // Do this last, since it relies on the named stream map being complete, and
+ // that can be updated by previous steps in the finalization.
+ if (Info) {
+ if (auto EC = Info->finalizeMsfLayout())
+ return EC;
+ }
+
+ if (!InjectedSources.empty()) {
+ for (const auto &IS : InjectedSources) {
+ JamCRC CRC(0);
+ CRC.update(makeArrayRef(IS.Content->getBufferStart(),
+ IS.Content->getBufferSize()));
+
+ SrcHeaderBlockEntry Entry;
+ ::memset(&Entry, 0, sizeof(SrcHeaderBlockEntry));
+ Entry.Size = sizeof(SrcHeaderBlockEntry);
+ Entry.FileSize = IS.Content->getBufferSize();
+ Entry.FileNI = IS.NameIndex;
+ Entry.VFileNI = IS.VNameIndex;
+ Entry.ObjNI = 1;
+ Entry.IsVirtual = 0;
+ Entry.Version =
+ static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne);
+ Entry.CRC = CRC.getCRC();
+ StringRef VName = getStringTableBuilder().getStringForId(IS.VNameIndex);
+ InjectedSourceTable.set_as(VName, std::move(Entry));
}
+
+ uint32_t SrcHeaderBlockSize =
+ sizeof(SrcHeaderBlockHeader) +
+ InjectedSourceTable.calculateSerializedLength();
+ SN = allocateNamedStream("/src/headerblock", SrcHeaderBlockSize);
+ if (!SN)
+ return SN.takeError();
+ for (const auto &IS : InjectedSources) {
+ SN = allocateNamedStream(IS.StreamName, IS.Content->getBufferSize());
+ if (!SN)
+ return SN.takeError();
+ }
+ }
+
+ // Do this last, since it relies on the named stream map being complete, and
+ // that can be updated by previous steps in the finalization.
+ if (Info) {
+ if (auto EC = Info->finalizeMsfLayout())
+ return EC;
}
- return Msf->build();
+ return Error::success();
}
Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {
@@ -142,70 +223,55 @@ Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {
return SN;
}
-void PDBFileBuilder::commitFpm(WritableBinaryStream &MsfBuffer,
- const MSFLayout &Layout) {
- auto FpmStream =
- WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator);
-
- // We only need to create the alt fpm stream so that it gets initialized.
- WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator,
- true);
-
- uint32_t BI = 0;
- BinaryStreamWriter FpmWriter(*FpmStream);
- while (BI < Layout.SB->NumBlocks) {
- uint8_t ThisByte = 0;
- for (uint32_t I = 0; I < 8; ++I) {
- bool IsFree =
- (BI < Layout.SB->NumBlocks) ? Layout.FreePageMap.test(BI) : true;
- uint8_t Mask = uint8_t(IsFree) << I;
- ThisByte |= Mask;
- ++BI;
- }
- cantFail(FpmWriter.writeObject(ThisByte));
- }
- assert(FpmWriter.bytesRemaining() == 0);
+void PDBFileBuilder::commitSrcHeaderBlock(WritableBinaryStream &MsfBuffer,
+ const msf::MSFLayout &Layout) {
+ assert(!InjectedSourceTable.empty());
+
+ uint32_t SN = cantFail(getNamedStreamIndex("/src/headerblock"));
+ auto Stream = WritableMappedBlockStream::createIndexedStream(
+ Layout, MsfBuffer, SN, Allocator);
+ BinaryStreamWriter Writer(*Stream);
+
+ SrcHeaderBlockHeader Header;
+ ::memset(&Header, 0, sizeof(Header));
+ Header.Version = static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne);
+ Header.Size = Writer.bytesRemaining();
+
+ cantFail(Writer.writeObject(Header));
+ cantFail(InjectedSourceTable.commit(Writer));
+
+ assert(Writer.bytesRemaining() == 0);
}
-Error PDBFileBuilder::commit(StringRef Filename) {
- assert(!Filename.empty());
- auto ExpectedLayout = finalizeMsfLayout();
- if (!ExpectedLayout)
- return ExpectedLayout.takeError();
- auto &Layout = *ExpectedLayout;
-
- uint64_t Filesize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
- auto OutFileOrError = FileOutputBuffer::create(Filename, Filesize);
- if (auto E = OutFileOrError.takeError())
- return E;
- FileBufferByteStream Buffer(std::move(*OutFileOrError),
- llvm::support::little);
- BinaryStreamWriter Writer(Buffer);
-
- if (auto EC = Writer.writeObject(*Layout.SB))
- return EC;
+void PDBFileBuilder::commitInjectedSources(WritableBinaryStream &MsfBuffer,
+ const msf::MSFLayout &Layout) {
+ if (InjectedSourceTable.empty())
+ return;
- commitFpm(Buffer, Layout);
+ commitSrcHeaderBlock(MsfBuffer, Layout);
- uint32_t BlockMapOffset =
- msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
- Writer.setOffset(BlockMapOffset);
- if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
- return EC;
+ for (const auto &IS : InjectedSources) {
+ uint32_t SN = cantFail(getNamedStreamIndex(IS.StreamName));
- auto DirStream = WritableMappedBlockStream::createDirectoryStream(
- Layout, Buffer, Allocator);
- BinaryStreamWriter DW(*DirStream);
- if (auto EC = DW.writeInteger<uint32_t>(Layout.StreamSizes.size()))
- return EC;
+ auto SourceStream = WritableMappedBlockStream::createIndexedStream(
+ Layout, MsfBuffer, SN, Allocator);
+ BinaryStreamWriter SourceWriter(*SourceStream);
+ assert(SourceWriter.bytesRemaining() == IS.Content->getBufferSize());
+ cantFail(SourceWriter.writeBytes(
+ arrayRefFromStringRef(IS.Content->getBuffer())));
+ }
+}
- if (auto EC = DW.writeArray(Layout.StreamSizes))
+Error PDBFileBuilder::commit(StringRef Filename) {
+ assert(!Filename.empty());
+ if (auto EC = finalizeMsfLayout())
return EC;
- for (const auto &Blocks : Layout.StreamMap) {
- if (auto EC = DW.writeArray(Blocks))
- return EC;
- }
+ MSFLayout Layout;
+ auto ExpectedMsfBuffer = Msf->commit(Filename, Layout);
+ if (!ExpectedMsfBuffer)
+ return ExpectedMsfBuffer.takeError();
+ FileBufferByteStream Buffer = std::move(*ExpectedMsfBuffer);
auto ExpectedSN = getNamedStreamIndex("/names");
if (!ExpectedSN)
@@ -217,6 +283,17 @@ Error PDBFileBuilder::commit(StringRef Filename) {
if (auto EC = Strings.commit(NSWriter))
return EC;
+ for (const auto &NSE : NamedStreamData) {
+ if (NSE.second.empty())
+ continue;
+
+ auto NS = WritableMappedBlockStream::createIndexedStream(
+ Layout, Buffer, NSE.first, Allocator);
+ BinaryStreamWriter NSW(*NS);
+ if (auto EC = NSW.writeBytes(arrayRefFromStringRef(NSE.second)))
+ return EC;
+ }
+
if (Info) {
if (auto EC = Info->commit(Layout, Buffer))
return EC;
@@ -242,5 +319,22 @@ Error PDBFileBuilder::commit(StringRef Filename) {
return EC;
}
+ auto InfoStreamBlocks = Layout.StreamMap[StreamPDB];
+ assert(!InfoStreamBlocks.empty());
+ uint64_t InfoStreamFileOffset =
+ blockToOffset(InfoStreamBlocks.front(), Layout.SB->BlockSize);
+ InfoStreamHeader *H = reinterpret_cast<InfoStreamHeader *>(
+ Buffer.getBufferStart() + InfoStreamFileOffset);
+
+ commitInjectedSources(Buffer, Layout);
+
+ // Set the build id at the very end, after every other byte of the PDB
+ // has been written.
+ // FIXME: Use a hash of the PDB rather than time(nullptr) for the signature.
+ H->Age = Info->getAge();
+ H->Guid = Info->getGuid();
+ Optional<uint32_t> Sig = Info->getSignature();
+ H->Signature = Sig.hasValue() ? *Sig : time(nullptr);
+
return Buffer.commit();
}
diff --git a/lib/DebugInfo/PDB/Native/PDBStringTable.cpp b/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
index f1c10357132b..afeea32043dd 100644
--- a/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
+++ b/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
@@ -122,7 +122,10 @@ Expected<uint32_t> PDBStringTable::getIDForString(StringRef Str) const {
// we iterate the entire array.
uint32_t Index = (Start + I) % Count;
+ // If we find 0, it means the item isn't in the hash table.
uint32_t ID = IDs[Index];
+ if (ID == 0)
+ return make_error<RawError>(raw_error_code::no_entry);
auto ExpectedStr = getStringForID(ID);
if (!ExpectedStr)
return ExpectedStr.takeError();
diff --git a/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp b/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
index ece3e00b1a87..d9dcabf3d958 100644
--- a/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
@@ -15,23 +15,101 @@
#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/Endian.h"
+#include <map>
+
using namespace llvm;
using namespace llvm::msf;
using namespace llvm::support;
using namespace llvm::support::endian;
using namespace llvm::pdb;
+StringTableHashTraits::StringTableHashTraits(PDBStringTableBuilder &Table)
+ : Table(&Table) {}
+
+uint32_t StringTableHashTraits::hashLookupKey(StringRef S) const {
+ return Table->getIdForString(S);
+}
+
+StringRef StringTableHashTraits::storageKeyToLookupKey(uint32_t Offset) const {
+ return Table->getStringForId(Offset);
+}
+
+uint32_t StringTableHashTraits::lookupKeyToStorageKey(StringRef S) {
+ return Table->insert(S);
+}
+
uint32_t PDBStringTableBuilder::insert(StringRef S) {
return Strings.insert(S);
}
+uint32_t PDBStringTableBuilder::getIdForString(StringRef S) const {
+ return Strings.getIdForString(S);
+}
+
+StringRef PDBStringTableBuilder::getStringForId(uint32_t Id) const {
+ return Strings.getStringForId(Id);
+}
+
+// This is a precomputed list of Buckets given the specified number of
+// strings. Matching the reference algorithm exactly is not strictly
+// necessary for correctness, but it helps when comparing LLD's PDBs with
+// Microsoft's PDBs so as to eliminate superfluous differences.
+static std::map<uint32_t, uint32_t> StringsToBuckets = {
+ {1, 2},
+ {2, 4},
+ {4, 7},
+ {6, 11},
+ {9, 17},
+ {13, 26},
+ {20, 40},
+ {31, 61},
+ {46, 92},
+ {70, 139},
+ {105, 209},
+ {157, 314},
+ {236, 472},
+ {355, 709},
+ {532, 1064},
+ {799, 1597},
+ {1198, 2396},
+ {1798, 3595},
+ {2697, 5393},
+ {4045, 8090},
+ {6068, 12136},
+ {9103, 18205},
+ {13654, 27308},
+ {20482, 40963},
+ {30723, 61445},
+ {46084, 92168},
+ {69127, 138253},
+ {103690, 207380},
+ {155536, 311071},
+ {233304, 466607},
+ {349956, 699911},
+ {524934, 1049867},
+ {787401, 1574801},
+ {1181101, 2362202},
+ {1771652, 3543304},
+ {2657479, 5314957},
+ {3986218, 7972436},
+ {5979328, 11958655},
+ {8968992, 17937983},
+ {13453488, 26906975},
+ {20180232, 40360463},
+ {30270348, 60540695},
+ {45405522, 90811043},
+ {68108283, 136216565},
+ {102162424, 204324848},
+ {153243637, 306487273},
+ {229865455, 459730910},
+ {344798183, 689596366},
+ {517197275, 1034394550},
+ {775795913, 1551591826}};
+
static uint32_t computeBucketCount(uint32_t NumStrings) {
- // The /names stream is basically an on-disk open-addressing hash table.
- // Hash collisions are resolved by linear probing. We cannot make
- // utilization 100% because it will make the linear probing extremely
- // slow. But lower utilization wastes disk space. As a reasonable
- // load factor, we choose 80%. We need +1 because slot 0 is reserved.
- return (NumStrings + 1) * 1.25;
+ auto Entry = StringsToBuckets.lower_bound(NumStrings);
+ assert(Entry != StringsToBuckets.end());
+ return Entry->second;
}
uint32_t PDBStringTableBuilder::calculateHashTableSize() const {
@@ -89,8 +167,6 @@ Error PDBStringTableBuilder::writeHashTable(BinaryStreamWriter &Writer) const {
for (uint32_t I = 0; I != BucketCount; ++I) {
uint32_t Slot = (Hash + I) % BucketCount;
- if (Slot == 0)
- continue; // Skip reserved slot
if (Buckets[Slot] != 0)
continue;
Buckets[Slot] = Offset;
diff --git a/lib/DebugInfo/PDB/Native/TpiStream.cpp b/lib/DebugInfo/PDB/Native/TpiStream.cpp
index d3ef87d9009d..0680b673380a 100644
--- a/lib/DebugInfo/PDB/Native/TpiStream.cpp
+++ b/lib/DebugInfo/PDB/Native/TpiStream.cpp
@@ -152,7 +152,9 @@ FixedStreamArray<TypeIndexOffset> TpiStream::getTypeIndexOffsets() const {
return TypeIndexOffsets;
}
-HashTable &TpiStream::getHashAdjusters() { return HashAdjusters; }
+HashTable<support::ulittle32_t> &TpiStream::getHashAdjusters() {
+ return HashAdjusters;
+}
CVTypeRange TpiStream::types(bool *HadError) const {
return make_range(TypeRecords.begin(HadError), TypeRecords.end());
diff --git a/lib/DebugInfo/PDB/PDBExtras.cpp b/lib/DebugInfo/PDB/PDBExtras.cpp
index ee752cda346e..a4e316417f96 100644
--- a/lib/DebugInfo/PDB/PDBExtras.cpp
+++ b/lib/DebugInfo/PDB/PDBExtras.cpp
@@ -113,6 +113,8 @@ raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_LocType &Loc) {
CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, IlRel, "IL rel", OS)
CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, MetaData, "metadata", OS)
CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, Constant, "constant", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, RegRelAliasIndir,
+ "regrelaliasindir", OS)
default:
OS << "Unknown";
}
@@ -139,6 +141,7 @@ raw_ostream &llvm::pdb::operator<<(raw_ostream &OS,
CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Checksum, None, OS)
CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Checksum, MD5, OS)
CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Checksum, SHA1, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Checksum, SHA256, OS)
}
return OS;
}
@@ -254,6 +257,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/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp b/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp
index b2b03fbe167b..c62796507a01 100644
--- a/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp
+++ b/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp
@@ -12,8 +12,10 @@
//===----------------------------------------------------------------------===//
#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/IPDBSectionContrib.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/IPDBTable.h"
@@ -29,3 +31,7 @@ IPDBRawSymbol::~IPDBRawSymbol() = default;
IPDBLineNumber::~IPDBLineNumber() = default;
IPDBTable::~IPDBTable() = default;
+
+IPDBInjectedSource::~IPDBInjectedSource() = default;
+
+IPDBSectionContrib::~IPDBSectionContrib() = default;
diff --git a/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp b/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp
index 854cf42d1bae..8798c7b9db88 100644
--- a/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp
+++ b/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp
@@ -1,4 +1,4 @@
-//===- PDBSymbolCompiland.cpp - compiland details --------*- C++ -*-===//
+//===- PDBSymbolCompiland.cpp - compiland details ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,11 +7,16 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
+
#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"
#include "llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h"
-
#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Path.h"
#include <utility>
using namespace llvm;
@@ -27,20 +32,85 @@ void PDBSymbolCompiland::dump(PDBSymDumper &Dumper) const {
Dumper.dump(*this);
}
-std::string PDBSymbolCompiland::getSourceFileName() const
-{
- std::string Result = RawSymbol->getSourceFileName();
- if (!Result.empty())
- return Result;
- auto Envs = findAllChildren<PDBSymbolCompilandEnv>();
- if (!Envs)
- return std::string();
- while (auto Env = Envs->getNext()) {
+std::string PDBSymbolCompiland::getSourceFileName() const {
+ return sys::path::filename(getSourceFileFullPath()).str();
+}
+
+std::string PDBSymbolCompiland::getSourceFileFullPath() const {
+ std::string SourceFileFullPath;
+
+ // RecordedResult could be the basename, relative path or full path of the
+ // source file. Usually it is retrieved and recorded from the command that
+ // compiles this compiland.
+ //
+ // cmd FileName -> RecordedResult = .\\FileName
+ // cmd (Path)\\FileName -> RecordedResult = (Path)\\FileName
+ //
+ std::string RecordedResult = RawSymbol->getSourceFileName();
+
+ if (RecordedResult.empty()) {
+ if (auto Envs = findAllChildren<PDBSymbolCompilandEnv>()) {
+ std::string EnvWorkingDir, EnvSrc;
+
+ while (auto Env = Envs->getNext()) {
std::string Var = Env->getName();
- if (Var != "src")
- continue;
- std::string Value = Env->getValue();
- return Value;
+ if (Var == "cwd") {
+ EnvWorkingDir = Env->getValue();
+ continue;
+ }
+ if (Var == "src") {
+ EnvSrc = Env->getValue();
+ if (sys::path::is_absolute(EnvSrc))
+ return EnvSrc;
+ RecordedResult = EnvSrc;
+ continue;
+ }
+ }
+ if (!EnvWorkingDir.empty() && !EnvSrc.empty()) {
+ auto Len = EnvWorkingDir.length();
+ if (EnvWorkingDir[Len - 1] != '/' && EnvWorkingDir[Len - 1] != '\\') {
+ std::string Path = EnvWorkingDir + "\\" + EnvSrc;
+ std::replace(Path.begin(), Path.end(), '/', '\\');
+ // We will return it as full path if we can't find a better one.
+ if (sys::path::is_absolute(Path))
+ SourceFileFullPath = Path;
+ }
+ }
+ }
+ }
+
+ if (!RecordedResult.empty()) {
+ if (sys::path::is_absolute(RecordedResult))
+ return RecordedResult;
+
+ // This searches name that has same basename as the one in RecordedResult.
+ auto OneSrcFile = Session.findOneSourceFile(
+ this, RecordedResult, PDB_NameSearchFlags::NS_CaseInsensitive);
+ if (OneSrcFile)
+ return OneSrcFile->getFileName();
+ }
+
+ // At this point, we have to walk through all source files of this compiland,
+ // and determine the right source file if any that is used to generate this
+ // compiland based on language indicated in compilanddetails language field.
+ auto Details = findOneChild<PDBSymbolCompilandDetails>();
+ PDB_Lang Lang = Details ? Details->getLanguage() : PDB_Lang::Cpp;
+ auto SrcFiles = Session.getSourceFilesForCompiland(*this);
+ if (SrcFiles) {
+ bool LangC = (Lang == PDB_Lang::Cpp || Lang == PDB_Lang::C);
+ while (auto File = SrcFiles->getNext()) {
+ std::string FileName = File->getFileName();
+ auto file_extension = sys::path::extension(FileName);
+ if (StringSwitch<bool>(file_extension.lower())
+ .Case(".cpp", LangC)
+ .Case(".c", LangC)
+ .Case(".cc", LangC)
+ .Case(".cxx", LangC)
+ .Case(".asm", Lang == PDB_Lang::Masm)
+ .Default(false))
+ return File->getFileName();
}
- return std::string();
+ }
+
+ return SourceFileFullPath;
}
diff --git a/lib/DebugInfo/PDB/PDBSymbolData.cpp b/lib/DebugInfo/PDB/PDBSymbolData.cpp
index 60026689c6f1..ae4a8038ccd7 100644
--- a/lib/DebugInfo/PDB/PDBSymbolData.cpp
+++ b/lib/DebugInfo/PDB/PDBSymbolData.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
-
+#include "llvm/DebugInfo/PDB/IPDBSectionContrib.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
@@ -24,3 +24,52 @@ PDBSymbolData::PDBSymbolData(const IPDBSession &PDBSession,
}
void PDBSymbolData::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
+
+std::unique_ptr<IPDBEnumLineNumbers> PDBSymbolData::getLineNumbers() const {
+ auto Len = RawSymbol->getLength();
+ Len = Len ? Len : 1;
+ if (auto RVA = RawSymbol->getRelativeVirtualAddress())
+ return Session.findLineNumbersByRVA(RVA, Len);
+
+ if (auto Section = RawSymbol->getAddressSection())
+ return Session.findLineNumbersBySectOffset(
+ Section, RawSymbol->getAddressOffset(), Len);
+
+ return nullptr;
+}
+
+uint32_t PDBSymbolData::getCompilandId() const {
+ if (auto Lines = getLineNumbers()) {
+ if (auto FirstLine = Lines->getNext())
+ return FirstLine->getCompilandId();
+ }
+
+ uint32_t DataSection = RawSymbol->getAddressSection();
+ uint32_t DataOffset = RawSymbol->getAddressOffset();
+ if (DataSection == 0) {
+ if (auto RVA = RawSymbol->getRelativeVirtualAddress())
+ Session.addressForRVA(RVA, DataSection, DataOffset);
+ }
+
+ if (DataSection) {
+ if (auto SecContribs = Session.getSectionContribs()) {
+ while (auto Section = SecContribs->getNext()) {
+ if (Section->getAddressSection() == DataSection &&
+ Section->getAddressOffset() <= DataOffset &&
+ (Section->getAddressOffset() + Section->getLength()) > DataOffset)
+ return Section->getCompilandId();
+ }
+ }
+ } else {
+ auto LexParentId = RawSymbol->getLexicalParentId();
+ while (auto LexParent = Session.getSymbolById(LexParentId)) {
+ if (LexParent->getSymTag() == PDB_SymType::Exe)
+ break;
+ if (LexParent->getSymTag() == PDB_SymType::Compiland)
+ return LexParentId;
+ LexParentId = LexParent->getRawSymbol().getLexicalParentId();
+ }
+ }
+
+ return 0;
+}
diff --git a/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
index c8c44d97e2f7..37ca1abe86e9 100644
--- a/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
+++ b/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
@@ -105,3 +105,18 @@ bool PDBSymbolFunc::isDestructor() const {
return true;
return false;
}
+
+std::unique_ptr<IPDBEnumLineNumbers> PDBSymbolFunc::getLineNumbers() const {
+ auto Len = RawSymbol->getLength();
+ return Session.findLineNumbersByAddress(RawSymbol->getVirtualAddress(),
+ Len ? Len : 1);
+}
+
+uint32_t PDBSymbolFunc::getCompilandId() const {
+ if (auto Lines = getLineNumbers()) {
+ if (auto FirstLine = Lines->getNext()) {
+ return FirstLine->getCompilandId();
+ }
+ }
+ return 0;
+}
diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp
index 0304c6286c8f..8fd3b49155c9 100644
--- a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp
+++ b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp
@@ -14,6 +14,7 @@
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
#include <utility>
@@ -84,3 +85,21 @@ void PDBSymbolTypeFunctionSig::dump(PDBSymDumper &Dumper) const {
void PDBSymbolTypeFunctionSig::dumpRight(PDBSymDumper &Dumper) const {
Dumper.dumpRight(*this);
}
+
+bool PDBSymbolTypeFunctionSig::isCVarArgs() const {
+ auto SigArguments = getArguments();
+ if (!SigArguments)
+ return false;
+ uint32_t NumArgs = SigArguments->getChildCount();
+ if (NumArgs == 0)
+ return false;
+ auto Last = SigArguments->getChildAtIndex(NumArgs - 1);
+ if (auto Builtin = llvm::dyn_cast_or_null<PDBSymbolTypeBuiltin>(Last.get())) {
+ if (Builtin->getBuiltinType() == PDB_BuiltinType::None)
+ return true;
+ }
+
+ // Note that for a variadic template signature, this method always returns
+ // false since the parameters of the template are specialized.
+ return false;
+}