diff options
Diffstat (limited to 'contrib/llvm/lib/DebugInfo/PDB')
29 files changed, 1284 insertions, 517 deletions
diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp new file mode 100644 index 000000000000..d7c908e04593 --- /dev/null +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSectionContribs.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSectionContribs.cpp new file mode 100644 index 000000000000..1f405f049198 --- /dev/null +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp new file mode 100644 index 000000000000..1d642f221d79 --- /dev/null +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp index 8e4b1f8aa8c9..7d6cb254e1d1 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp new file mode 100644 index 000000000000..b7dc49f53e23 --- /dev/null +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp index b8aaebbf7380..d81f59400eb3 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/GenericError.cpp b/contrib/llvm/lib/DebugInfo/PDB/GenericError.cpp index 4fcecb92fd15..2a677b9abe2d 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/GenericError.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp index dabcc3447ee5..931ac7bb81db 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index d765485bdb6d..b97f1e90bcf8 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp index 04e6664c68db..edaa783398ca 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp index c96553ff9b16..f6043bfd7cf9 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp index e84f25dfeefa..58efc2256ae1 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/HashTable.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/HashTable.cpp index 439217f91d04..cfabc9cd1ad8 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/HashTable.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStream.cpp index 17c9392a9dd5..973a520ffca9 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStream.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp index 6450ae752f96..54d6835f1121 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp index 6cdf6dde04d9..a4eaed90837d 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp index d23ee0a09196..a4b029596314 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp index b01c2b54796c..086da13135c5 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp index 15b31d821b1c..78b11937f051 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp index dee27c621fac..e164e7cf1c52 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp index f1c10357132b..afeea32043dd 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp index ece3e00b1a87..d9dcabf3d958 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp index d3ef87d9009d..0680b673380a 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/PDBExtras.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBExtras.cpp index ee752cda346e..a4e316417f96 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBExtras.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp index b2b03fbe167b..c62796507a01 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp index 854cf42d1bae..8798c7b9db88 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp index 60026689c6f1..ae4a8038ccd7 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp index c8c44d97e2f7..37ca1abe86e9 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp +++ b/contrib/llvm/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/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp index 0304c6286c8f..8fd3b49155c9 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp +++ b/contrib/llvm/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; +}  | 
