diff options
Diffstat (limited to 'contrib/llvm/lib/DebugInfo/PDB')
86 files changed, 4290 insertions, 1792 deletions
diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp index cae817c..f62c499 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/PDBSymbol.h" -#include "llvm/DebugInfo/PDB/DIA/DIADataStream.h" #include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h" +#include "llvm/DebugInfo/PDB/DIA/DIADataStream.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" using namespace llvm; using namespace llvm::pdb; diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp index 4741d9c..796ce21 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h" #include "llvm/DebugInfo/PDB/DIA/DIALineNumber.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" using namespace llvm; using namespace llvm::pdb; diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp index ccf8c4e..b9311d0 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h" #include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" using namespace llvm; using namespace llvm::pdb; diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp index 3c211b5..2666385 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h" #include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h" #include "llvm/DebugInfo/PDB/DIA/DIASession.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" using namespace llvm; using namespace llvm::pdb; diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp index bba5b0f..4c59d2f 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp @@ -10,9 +10,14 @@ #include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/CodeView/Formatters.h" #include "llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h" #include "llvm/DebugInfo/PDB/DIA/DIASession.h" #include "llvm/DebugInfo/PDB/PDBExtras.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/raw_ostream.h" @@ -120,16 +125,16 @@ PrivateGetDIAValue(IDiaSymbol *Symbol, return Result8; } -PDB_UniqueId +codeview::GUID PrivateGetDIAValue(IDiaSymbol *Symbol, HRESULT (__stdcall IDiaSymbol::*Method)(GUID *)) { GUID Result; if (S_OK != (Symbol->*Method)(&Result)) - return PDB_UniqueId(); + return codeview::GUID(); - static_assert(sizeof(PDB_UniqueId) == sizeof(GUID), - "PDB_UniqueId is the wrong size!"); - PDB_UniqueId IdResult; + static_assert(sizeof(codeview::GUID) == sizeof(GUID), + "GUID is the wrong size!"); + codeview::GUID IdResult; ::memcpy(&IdResult, &Result, sizeof(GUID)); return IdResult; } @@ -178,9 +183,10 @@ void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name, } namespace llvm { -raw_ostream &operator<<(raw_ostream &OS, const GUID &Guid) { - const PDB_UniqueId *Id = reinterpret_cast<const PDB_UniqueId *>(&Guid); - OS << *Id; +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const GUID &G) { + StringRef GuidBytes(reinterpret_cast<const char *>(&G), sizeof(G)); + codeview::detail::GuidAdapter A(GuidBytes); + A.format(OS, ""); return OS; } } @@ -366,8 +372,11 @@ DIARawSymbol::findChildren(PDB_SymType Type) const { enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type); CComPtr<IDiaEnumSymbols> DiaEnumerator; - if (S_OK != Symbol->findChildrenEx(EnumVal, nullptr, nsNone, &DiaEnumerator)) - return nullptr; + if (S_OK != + Symbol->findChildrenEx(EnumVal, nullptr, nsNone, &DiaEnumerator)) { + if (S_OK != Symbol->findChildren(EnumVal, nullptr, nsNone, &DiaEnumerator)) + return nullptr; + } return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); } @@ -715,6 +724,18 @@ uint32_t DIARawSymbol::getVirtualTableShapeId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualTableShapeId); } +std::unique_ptr<PDBSymbolTypeBuiltin> +DIARawSymbol::getVirtualBaseTableType() const { + CComPtr<IDiaSymbol> TableType; + if (FAILED(Symbol->get_virtualBaseTableType(&TableType)) || !TableType) + return nullptr; + + auto RawVT = llvm::make_unique<DIARawSymbol>(Session, TableType); + auto Pointer = + llvm::make_unique<PDBSymbolTypePointer>(Session, std::move(RawVT)); + return unique_dyn_cast<PDBSymbolTypeBuiltin>(Pointer->getPointeeType()); +} + PDB_DataKind DIARawSymbol::getDataKind() const { return PrivateGetDIAValue<DWORD, PDB_DataKind>(Symbol, &IDiaSymbol::get_dataKind); @@ -725,7 +746,7 @@ PDB_SymType DIARawSymbol::getSymTag() const { &IDiaSymbol::get_symTag); } -PDB_UniqueId DIARawSymbol::getGuid() const { +codeview::GUID DIARawSymbol::getGuid() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_guid); } diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp index 6ecf335..ef9390c 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp @@ -21,12 +21,22 @@ #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Format.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::pdb; -static Error ErrorFromHResult(HRESULT Result, StringRef Context) { +template <typename... Ts> +static Error ErrorFromHResult(HRESULT Result, const char *Str, Ts &&... Args) { + SmallString<64> MessageStorage; + StringRef Context; + if (sizeof...(Args) > 0) { + MessageStorage = formatv(Str, std::forward<Ts>(Args)...).str(); + Context = MessageStorage; + } else + Context = Str; + switch (Result) { case E_PDB_NOT_FOUND: return make_error<GenericError>(generic_error_code::invalid_path, Context); @@ -95,8 +105,9 @@ Error DIASession::createFromPdb(StringRef Path, const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data()); HRESULT HR; - if (FAILED(HR = DiaDataSource->loadDataFromPdb(Path16Str))) - return ErrorFromHResult(HR, "Calling loadDataFromPdb"); + if (FAILED(HR = DiaDataSource->loadDataFromPdb(Path16Str))) { + return ErrorFromHResult(HR, "Calling loadDataFromPdb {0}", Path); + } if (FAILED(HR = DiaDataSource->openSession(&DiaSession))) return ErrorFromHResult(HR, "Calling openSession"); @@ -140,7 +151,7 @@ void DIASession::setLoadAddress(uint64_t Address) { Session->put_loadAddress(Address); } -std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() const { +std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() { CComPtr<IDiaSymbol> GlobalScope; if (S_OK != Session->get_globalScope(&GlobalScope)) return nullptr; diff --git a/contrib/llvm/lib/DebugInfo/PDB/GenericError.cpp b/contrib/llvm/lib/DebugInfo/PDB/GenericError.cpp index 789f3b8..4fcecb9 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/GenericError.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/GenericError.cpp @@ -26,6 +26,8 @@ public: switch (static_cast<generic_error_code>(Condition)) { case generic_error_code::unspecified: return "An unknown error has occurred."; + case generic_error_code::type_server_not_found: + 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 " diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp new file mode 100644 index 0000000..dabcc34 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp @@ -0,0 +1,90 @@ +//===- DbiModuleDescriptor.cpp - PDB module information -------------------===// +// +// 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/Native/DbiModuleDescriptor.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MathExtras.h" +#include <cstdint> + +using namespace llvm; +using namespace llvm::pdb; +using namespace llvm::support; + +DbiModuleDescriptor::DbiModuleDescriptor() = default; + +DbiModuleDescriptor::DbiModuleDescriptor(const DbiModuleDescriptor &Info) = + default; + +DbiModuleDescriptor::~DbiModuleDescriptor() = default; + +Error DbiModuleDescriptor::initialize(BinaryStreamRef Stream, + DbiModuleDescriptor &Info) { + BinaryStreamReader Reader(Stream); + if (auto EC = Reader.readObject(Info.Layout)) + return EC; + + if (auto EC = Reader.readCString(Info.ModuleName)) + return EC; + + if (auto EC = Reader.readCString(Info.ObjFileName)) + return EC; + return Error::success(); +} + +bool DbiModuleDescriptor::hasECInfo() const { + return (Layout->Flags & ModInfoFlags::HasECFlagMask) != 0; +} + +uint16_t DbiModuleDescriptor::getTypeServerIndex() const { + return (Layout->Flags & ModInfoFlags::TypeServerIndexMask) >> + ModInfoFlags::TypeServerIndexShift; +} + +uint16_t DbiModuleDescriptor::getModuleStreamIndex() const { + return Layout->ModDiStream; +} + +uint32_t DbiModuleDescriptor::getSymbolDebugInfoByteSize() const { + return Layout->SymBytes; +} + +uint32_t DbiModuleDescriptor::getC11LineInfoByteSize() const { + return Layout->C11Bytes; +} + +uint32_t DbiModuleDescriptor::getC13LineInfoByteSize() const { + return Layout->C13Bytes; +} + +uint32_t DbiModuleDescriptor::getNumberOfFiles() const { + return Layout->NumFiles; +} + +uint32_t DbiModuleDescriptor::getSourceFileNameIndex() const { + return Layout->SrcFileNameNI; +} + +uint32_t DbiModuleDescriptor::getPdbFilePathNameIndex() const { + return Layout->PdbFilePathNI; +} + +StringRef DbiModuleDescriptor::getModuleName() const { return ModuleName; } + +StringRef DbiModuleDescriptor::getObjFileName() const { return ObjFileName; } + +uint32_t DbiModuleDescriptor::getRecordLength() const { + uint32_t M = ModuleName.str().size() + 1; + uint32_t O = ObjFileName.str().size() + 1; + uint32_t Size = sizeof(ModuleInfoHeader) + M + O; + Size = alignTo(Size, 4); + return Size; +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp new file mode 100644 index 0000000..897f78c --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -0,0 +1,196 @@ +//===- DbiModuleDescriptorBuilder.cpp - PDB Mod Info Creation ---*- 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/Native/DbiModuleDescriptorBuilder.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" +#include "llvm/DebugInfo/MSF/MSFBuilder.h" +#include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/Support/BinaryItemStream.h" +#include "llvm/Support/BinaryStreamWriter.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::msf; +using namespace llvm::pdb; + +namespace llvm { +template <> struct BinaryItemTraits<CVSymbol> { + static size_t length(const CVSymbol &Item) { return Item.RecordData.size(); } + + static ArrayRef<uint8_t> bytes(const CVSymbol &Item) { + return Item.RecordData; + } +}; +} + +static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize, + uint32_t C13Size) { + uint32_t Size = sizeof(uint32_t); // Signature + Size += alignTo(SymbolByteSize, 4); // Symbol Data + Size += 0; // TODO: Layout.C11Bytes + Size += C13Size; // C13 Debug Info Size + Size += sizeof(uint32_t); // GlobalRefs substream size (always 0) + Size += 0; // GlobalRefs substream bytes + return Size; +} + +DbiModuleDescriptorBuilder::DbiModuleDescriptorBuilder(StringRef ModuleName, + uint32_t ModIndex, + msf::MSFBuilder &Msf) + : MSF(Msf), ModuleName(ModuleName) { + ::memset(&Layout, 0, sizeof(Layout)); + Layout.Mod = ModIndex; +} + +DbiModuleDescriptorBuilder::~DbiModuleDescriptorBuilder() {} + +uint16_t DbiModuleDescriptorBuilder::getStreamIndex() const { + return Layout.ModDiStream; +} + +void DbiModuleDescriptorBuilder::setObjFileName(StringRef Name) { + ObjFileName = Name; +} + +void DbiModuleDescriptorBuilder::setPdbFilePathNI(uint32_t NI) { + PdbFilePathNI = NI; +} + +void DbiModuleDescriptorBuilder::addSymbol(CVSymbol Symbol) { + Symbols.push_back(Symbol); + // Symbols written to a PDB file are required to be 4 byte aligned. The same + // is not true of object files. + assert(Symbol.length() % alignOf(CodeViewContainer::Pdb) == 0 && + "Invalid Symbol alignment!"); + SymbolByteSize += Symbol.length(); +} + +void DbiModuleDescriptorBuilder::addSourceFile(StringRef Path) { + SourceFiles.push_back(Path); +} + +uint32_t DbiModuleDescriptorBuilder::calculateC13DebugInfoSize() const { + uint32_t Result = 0; + for (const auto &Builder : C13Builders) { + assert(Builder && "Empty C13 Fragment Builder!"); + Result += Builder->calculateSerializedLength(); + } + return Result; +} + +uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const { + uint32_t L = sizeof(Layout); + uint32_t M = ModuleName.size() + 1; + uint32_t O = ObjFileName.size() + 1; + return alignTo(L + M + O, sizeof(uint32_t)); +} + +template <typename T> struct Foo { + explicit Foo(T &&Answer) : Answer(Answer) {} + + T Answer; +}; + +template <typename T> Foo<T> makeFoo(T &&t) { return Foo<T>(std::move(t)); } + +void DbiModuleDescriptorBuilder::finalize() { + Layout.SC.ModuleIndex = Layout.Mod; + Layout.FileNameOffs = 0; // TODO: Fix this + Layout.Flags = 0; // TODO: Fix this + Layout.C11Bytes = 0; + Layout.C13Bytes = calculateC13DebugInfoSize(); + (void)Layout.Mod; // Set in constructor + (void)Layout.ModDiStream; // Set in finalizeMsfLayout + Layout.NumFiles = SourceFiles.size(); + Layout.PdbFilePathNI = PdbFilePathNI; + Layout.SrcFileNameNI = 0; + + // This value includes both the signature field as well as the record bytes + // from the symbol stream. + Layout.SymBytes = SymbolByteSize + sizeof(uint32_t); +} + +Error DbiModuleDescriptorBuilder::finalizeMsfLayout() { + this->Layout.ModDiStream = kInvalidStreamIndex; + uint32_t C13Size = calculateC13DebugInfoSize(); + auto ExpectedSN = + MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize, C13Size)); + if (!ExpectedSN) + return ExpectedSN.takeError(); + Layout.ModDiStream = *ExpectedSN; + return Error::success(); +} + +Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter, + const msf::MSFLayout &MsfLayout, + WritableBinaryStreamRef MsfBuffer) { + // We write the Modi record to the `ModiWriter`, but we additionally write its + // symbol stream to a brand new stream. + if (auto EC = ModiWriter.writeObject(Layout)) + return EC; + if (auto EC = ModiWriter.writeCString(ModuleName)) + return EC; + if (auto EC = ModiWriter.writeCString(ObjFileName)) + return EC; + if (auto EC = ModiWriter.padToAlignment(sizeof(uint32_t))) + return EC; + + if (Layout.ModDiStream != kInvalidStreamIndex) { + auto NS = WritableMappedBlockStream::createIndexedStream( + MsfLayout, MsfBuffer, Layout.ModDiStream, MSF.getAllocator()); + WritableBinaryStreamRef Ref(*NS); + BinaryStreamWriter SymbolWriter(Ref); + // Write the symbols. + if (auto EC = + SymbolWriter.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC)) + return EC; + BinaryItemStream<CVSymbol> Records(llvm::support::endianness::little); + Records.setItems(Symbols); + BinaryStreamRef RecordsRef(Records); + if (auto EC = SymbolWriter.writeStreamRef(RecordsRef)) + return EC; + if (auto EC = SymbolWriter.padToAlignment(4)) + return EC; + // TODO: Write C11 Line data + assert(SymbolWriter.getOffset() % alignOf(CodeViewContainer::Pdb) == 0 && + "Invalid debug section alignment!"); + for (const auto &Builder : C13Builders) { + assert(Builder && "Empty C13 Fragment Builder!"); + if (auto EC = Builder->commit(SymbolWriter)) + return EC; + } + + // TODO: Figure out what GlobalRefs substream actually is and populate it. + if (auto EC = SymbolWriter.writeInteger<uint32_t>(0)) + return EC; + if (SymbolWriter.bytesRemaining() > 0) + return make_error<RawError>(raw_error_code::stream_too_long); + } + return Error::success(); +} + +void DbiModuleDescriptorBuilder::addDebugSubsection( + std::shared_ptr<DebugSubsection> Subsection) { + assert(Subsection); + C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>( + std::move(Subsection), CodeViewContainer::Pdb)); +} + +void DbiModuleDescriptorBuilder::addDebugSubsection( + const DebugSubsectionRecord &SubsectionContents) { + C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>( + SubsectionContents, CodeViewContainer::Pdb)); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleList.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleList.cpp new file mode 100644 index 0000000..eea70b2 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleList.cpp @@ -0,0 +1,280 @@ +//===- DbiModuleList.cpp - PDB module information list --------------------===// +// +// 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/Native/DbiModuleList.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/Error.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> + +using namespace llvm; +using namespace llvm::pdb; + +DbiModuleSourceFilesIterator::DbiModuleSourceFilesIterator( + const DbiModuleList &Modules, uint32_t Modi, uint16_t Filei) + : Modules(&Modules), Modi(Modi), Filei(Filei) { + setValue(); +} + +bool DbiModuleSourceFilesIterator:: +operator==(const DbiModuleSourceFilesIterator &R) const { + // incompatible iterators are never equal + if (!isCompatible(R)) + return false; + + // If they're compatible, and they're both ends, then they're equal. + if (isEnd() && R.isEnd()) + return true; + + // If one is an end and the other is not, they're not equal. + if (isEnd() != R.isEnd()) + return false; + + // Now we know: + // - They're compatible + // - They're not *both* end iterators + // - Their endness is the same. + // Thus, they're compatible iterators pointing to a valid file on the same + // module. All we need to check are the file indices. + assert(Modules == R.Modules); + assert(Modi == R.Modi); + assert(!isEnd()); + assert(!R.isEnd()); + + return (Filei == R.Filei); +} + +bool DbiModuleSourceFilesIterator:: +operator<(const DbiModuleSourceFilesIterator &R) const { + assert(isCompatible(R)); + + // It's not sufficient to compare the file indices, because default + // constructed iterators could be equal to iterators with valid indices. To + // account for this, early-out if they're equal. + if (*this == R) + return false; + + return Filei < R.Filei; +} + +std::ptrdiff_t DbiModuleSourceFilesIterator:: +operator-(const DbiModuleSourceFilesIterator &R) const { + assert(isCompatible(R)); + assert(!(*this < R)); + + // If they're both end iterators, the distance is 0. + if (isEnd() && R.isEnd()) + return 0; + + assert(!R.isEnd()); + + // At this point, R cannot be end, but *this can, which means that *this + // might be a universal end iterator with none of its fields set. So in that + // case have to rely on R as the authority to figure out how many files there + // are to compute the distance. + uint32_t Thisi = Filei; + if (isEnd()) { + uint32_t RealModi = R.Modi; + Thisi = R.Modules->getSourceFileCount(RealModi); + } + + assert(Thisi >= R.Filei); + return Thisi - R.Filei; +} + +DbiModuleSourceFilesIterator &DbiModuleSourceFilesIterator:: +operator+=(std::ptrdiff_t N) { + assert(!isEnd()); + + Filei += N; + assert(Filei <= Modules->getSourceFileCount(Modi)); + setValue(); + return *this; +} + +DbiModuleSourceFilesIterator &DbiModuleSourceFilesIterator:: +operator-=(std::ptrdiff_t N) { + // Note that we can subtract from an end iterator, but not a universal end + // iterator. + assert(!isUniversalEnd()); + + assert(N <= Filei); + + Filei -= N; + return *this; +} + +void DbiModuleSourceFilesIterator::setValue() { + if (isEnd()) { + ThisValue = ""; + return; + } + + uint32_t Off = Modules->ModuleInitialFileIndex[Modi] + Filei; + auto ExpectedValue = Modules->getFileName(Off); + if (!ExpectedValue) { + consumeError(ExpectedValue.takeError()); + Filei = Modules->getSourceFileCount(Modi); + } else + ThisValue = *ExpectedValue; +} + +bool DbiModuleSourceFilesIterator::isEnd() const { + if (isUniversalEnd()) + return true; + + assert(Modules); + assert(Modi <= Modules->getModuleCount()); + assert(Filei <= Modules->getSourceFileCount(Modi)); + + if (Modi == Modules->getModuleCount()) + return true; + if (Filei == Modules->getSourceFileCount(Modi)) + return true; + return false; +} + +bool DbiModuleSourceFilesIterator::isUniversalEnd() const { return !Modules; } + +bool DbiModuleSourceFilesIterator::isCompatible( + const DbiModuleSourceFilesIterator &R) const { + // Universal iterators are compatible with any other iterator. + if (isUniversalEnd() || R.isUniversalEnd()) + return true; + + // At this point, neither iterator is a universal end iterator, although one + // or both might be non-universal end iterators. Regardless, the module index + // is valid, so they are compatible if and only if they refer to the same + // module. + return Modi == R.Modi; +} + +Error DbiModuleList::initialize(BinaryStreamRef ModInfo, + BinaryStreamRef FileInfo) { + if (auto EC = initializeModInfo(ModInfo)) + return EC; + if (auto EC = initializeFileInfo(FileInfo)) + return EC; + + return Error::success(); +} + +Error DbiModuleList::initializeModInfo(BinaryStreamRef ModInfo) { + ModInfoSubstream = ModInfo; + + if (ModInfo.getLength() == 0) + return Error::success(); + + BinaryStreamReader Reader(ModInfo); + + if (auto EC = Reader.readArray(Descriptors, ModInfo.getLength())) + return EC; + + return Error::success(); +} + +Error DbiModuleList::initializeFileInfo(BinaryStreamRef FileInfo) { + FileInfoSubstream = FileInfo; + + if (FileInfo.getLength() == 0) + return Error::success(); + + BinaryStreamReader FISR(FileInfo); + if (auto EC = FISR.readObject(FileInfoHeader)) + return EC; + + // First is an array of `NumModules` module indices. This does not seem to be + // used for anything meaningful, so we ignore it. + FixedStreamArray<support::ulittle16_t> ModuleIndices; + if (auto EC = FISR.readArray(ModuleIndices, FileInfoHeader->NumModules)) + return EC; + if (auto EC = FISR.readArray(ModFileCountArray, FileInfoHeader->NumModules)) + return EC; + + // Compute the real number of source files. We can't trust the value in + // `FileInfoHeader->NumSourceFiles` because it is a unit16, and the sum of all + // source file counts might be larger than a unit16. So we compute the real + // count by summing up the individual counts. + uint32_t NumSourceFiles = 0; + for (auto Count : ModFileCountArray) + NumSourceFiles += Count; + + // In the reference implementation, this array is where the pointer documented + // at the definition of ModuleInfoHeader::FileNameOffs points to. Note that + // although the field in ModuleInfoHeader is ignored this array is not, as it + // is the authority on where each filename begins in the names buffer. + if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles)) + return EC; + + if (auto EC = FISR.readStreamRef(NamesBuffer)) + return EC; + + auto DescriptorIter = Descriptors.begin(); + uint32_t NextFileIndex = 0; + ModuleInitialFileIndex.resize(FileInfoHeader->NumModules); + ModuleDescriptorOffsets.resize(FileInfoHeader->NumModules); + for (size_t I = 0; I < FileInfoHeader->NumModules; ++I) { + assert(DescriptorIter != Descriptors.end()); + ModuleInitialFileIndex[I] = NextFileIndex; + ModuleDescriptorOffsets[I] = DescriptorIter.offset(); + + NextFileIndex += ModFileCountArray[I]; + ++DescriptorIter; + } + + assert(DescriptorIter == Descriptors.end()); + assert(NextFileIndex == NumSourceFiles); + + return Error::success(); +} + +uint32_t DbiModuleList::getModuleCount() const { + return FileInfoHeader->NumModules; +} + +uint32_t DbiModuleList::getSourceFileCount() const { + return FileNameOffsets.size(); +} + +uint16_t DbiModuleList::getSourceFileCount(uint32_t Modi) const { + return ModFileCountArray[Modi]; +} + +DbiModuleDescriptor DbiModuleList::getModuleDescriptor(uint32_t Modi) const { + assert(Modi < getModuleCount()); + uint32_t Offset = ModuleDescriptorOffsets[Modi]; + auto Iter = Descriptors.at(Offset); + assert(Iter != Descriptors.end()); + return *Iter; +} + +iterator_range<DbiModuleSourceFilesIterator> +DbiModuleList::source_files(uint32_t Modi) const { + return make_range<DbiModuleSourceFilesIterator>( + DbiModuleSourceFilesIterator(*this, Modi, 0), + DbiModuleSourceFilesIterator()); +} + +Expected<StringRef> DbiModuleList::getFileName(uint32_t Index) const { + BinaryStreamReader Names(NamesBuffer); + if (Index >= getSourceFileCount()) + return make_error<RawError>(raw_error_code::index_out_of_bounds); + + uint32_t FileOffset = FileNameOffsets[Index]; + Names.setOffset(FileOffset); + StringRef Name; + if (auto EC = Names.readCString(Name)) + return std::move(EC); + return Name; +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp index 4f4a0cf..0eeac7e 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp @@ -7,21 +7,20 @@ // //===----------------------------------------------------------------------===// +#include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/MSF/StreamArray.h" -#include "llvm/DebugInfo/MSF/StreamReader.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" +#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h" +#include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" -#include "llvm/DebugInfo/PDB/Raw/DbiStream.h" -#include "llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h" -#include "llvm/DebugInfo/PDB/Raw/InfoStream.h" -#include "llvm/DebugInfo/PDB/Raw/ModInfo.h" -#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h" -#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" -#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" -#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" #include "llvm/Object/COFF.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Error.h" #include <algorithm> #include <cstddef> @@ -35,7 +34,7 @@ using namespace llvm::support; template <typename ContribType> static Error loadSectionContribs(FixedStreamArray<ContribType> &Output, - StreamReader &Reader) { + BinaryStreamReader &Reader) { if (Reader.bytesRemaining() % sizeof(ContribType) != 0) return make_error<RawError>( raw_error_code::corrupt_file, @@ -48,13 +47,12 @@ static Error loadSectionContribs(FixedStreamArray<ContribType> &Output, } DbiStream::DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream) - : Pdb(File), Stream(std::move(Stream)), Header(nullptr) { -} + : Pdb(File), Stream(std::move(Stream)), Header(nullptr) {} DbiStream::~DbiStream() = default; Error DbiStream::reload() { - StreamReader Reader(*Stream); + BinaryStreamReader Reader(*Stream); if (Stream->getLength() < sizeof(DbiStreamHeader)) return make_error<RawError>(raw_error_code::corrupt_file, @@ -74,14 +72,6 @@ Error DbiStream::reload() { return make_error<RawError>(raw_error_code::feature_unsupported, "Unsupported DBI version."); - auto IS = Pdb.getPDBInfoStream(); - if (!IS) - return IS.takeError(); - - if (Header->Age != IS->getAge()) - return make_error<RawError>(raw_error_code::corrupt_file, - "DBI Age does not match PDB Age."); - if (Stream->getLength() != sizeof(DbiStreamHeader) + Header->ModiSubstreamSize + Header->SecContrSubstreamSize + Header->SectionMapSize + @@ -109,26 +99,27 @@ Error DbiStream::reload() { return make_error<RawError>(raw_error_code::corrupt_file, "DBI type server substream not aligned."); - if (auto EC = - Reader.readStreamRef(ModInfoSubstream, Header->ModiSubstreamSize)) - return EC; - if (auto EC = initializeModInfoArray()) + if (auto EC = Reader.readSubstream(ModiSubstream, Header->ModiSubstreamSize)) return EC; - if (auto EC = Reader.readStreamRef(SecContrSubstream, + if (auto EC = Reader.readSubstream(SecContrSubstream, Header->SecContrSubstreamSize)) return EC; - if (auto EC = Reader.readStreamRef(SecMapSubstream, Header->SectionMapSize)) + if (auto EC = Reader.readSubstream(SecMapSubstream, Header->SectionMapSize)) return EC; - if (auto EC = Reader.readStreamRef(FileInfoSubstream, Header->FileInfoSize)) + if (auto EC = Reader.readSubstream(FileInfoSubstream, Header->FileInfoSize)) return EC; if (auto EC = - Reader.readStreamRef(TypeServerMapSubstream, Header->TypeServerSize)) + Reader.readSubstream(TypeServerMapSubstream, Header->TypeServerSize)) return EC; - if (auto EC = Reader.readStreamRef(ECSubstream, Header->ECSubstreamSize)) + if (auto EC = Reader.readSubstream(ECSubstream, Header->ECSubstreamSize)) return EC; - if (auto EC = Reader.readArray(DbgStreams, Header->OptionalDbgHdrSize / - sizeof(ulittle16_t))) + if (auto EC = Reader.readArray( + DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t))) + return EC; + + if (auto EC = Modules.initialize(ModiSubstream.StreamData, + FileInfoSubstream.StreamData)) return EC; if (auto EC = initializeSectionContributionData()) @@ -137,8 +128,6 @@ Error DbiStream::reload() { return EC; if (auto EC = initializeSectionMapData()) return EC; - if (auto EC = initializeFileInfo()) - return EC; if (auto EC = initializeFpoRecords()) return EC; @@ -146,9 +135,9 @@ Error DbiStream::reload() { return make_error<RawError>(raw_error_code::corrupt_file, "Found unexpected bytes in DBI Stream."); - if (ECSubstream.getLength() > 0) { - StreamReader ECReader(ECSubstream); - if (auto EC = ECNames.load(ECReader)) + if (!ECSubstream.empty()) { + BinaryStreamReader ECReader(ECSubstream.StreamData); + if (auto EC = ECNames.reload(ECReader)) return EC; } @@ -209,35 +198,42 @@ PDB_Machine DbiStream::getMachineType() const { return static_cast<PDB_Machine>(Machine); } -msf::FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() { +FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() { return SectionHeaders; } -msf::FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() { +FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() { return FpoRecords; } -ArrayRef<ModuleInfoEx> DbiStream::modules() const { return ModuleInfos; } -msf::FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const { +const DbiModuleList &DbiStream::modules() const { return Modules; } + +FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const { return SectionMap; } void DbiStream::visitSectionContributions( ISectionContribVisitor &Visitor) const { - if (SectionContribVersion == DbiSecContribVer60) { + if (!SectionContribs.empty()) { + assert(SectionContribVersion == DbiSecContribVer60); for (auto &SC : SectionContribs) Visitor.visit(SC); - } else if (SectionContribVersion == DbiSecContribV2) { + } else if (!SectionContribs2.empty()) { + assert(SectionContribVersion == DbiSecContribV2); for (auto &SC : SectionContribs2) Visitor.visit(SC); } } +Expected<StringRef> DbiStream::getECName(uint32_t NI) const { + return ECNames.getStringForID(NI); +} + Error DbiStream::initializeSectionContributionData() { - if (SecContrSubstream.getLength() == 0) + if (SecContrSubstream.empty()) return Error::success(); - StreamReader SCReader(SecContrSubstream); + BinaryStreamReader SCReader(SecContrSubstream.StreamData); if (auto EC = SCReader.readEnum(SectionContribVersion)) return EC; @@ -250,35 +246,20 @@ Error DbiStream::initializeSectionContributionData() { "Unsupported DBI Section Contribution version"); } -Error DbiStream::initializeModInfoArray() { - if (ModInfoSubstream.getLength() == 0) - return Error::success(); - - // Since each ModInfo in the stream is a variable length, we have to iterate - // them to know how many there actually are. - StreamReader Reader(ModInfoSubstream); - - VarStreamArray<ModInfo> ModInfoArray; - if (auto EC = Reader.readArray(ModInfoArray, ModInfoSubstream.getLength())) - return EC; - for (auto &Info : ModInfoArray) { - ModuleInfos.emplace_back(Info); - } - - return Error::success(); -} - // Initializes this->SectionHeaders. Error DbiStream::initializeSectionHeadersData() { if (DbgStreams.size() == 0) return Error::success(); uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::SectionHdr); + if (StreamNum == kInvalidStreamIndex) + return Error::success(); + if (StreamNum >= Pdb.getNumStreams()) return make_error<RawError>(raw_error_code::no_stream); auto SHS = MappedBlockStream::createIndexedStream( - Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum); + Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator()); size_t StreamLen = SHS->getLength(); if (StreamLen % sizeof(object::coff_section)) @@ -286,7 +267,7 @@ Error DbiStream::initializeSectionHeadersData() { "Corrupted section header stream."); size_t NumSections = StreamLen / sizeof(object::coff_section); - msf::StreamReader Reader(*SHS); + BinaryStreamReader Reader(*SHS); if (auto EC = Reader.readArray(SectionHeaders, NumSections)) return make_error<RawError>(raw_error_code::corrupt_file, "Could not read a bitmap."); @@ -310,7 +291,7 @@ Error DbiStream::initializeFpoRecords() { return make_error<RawError>(raw_error_code::no_stream); auto FS = MappedBlockStream::createIndexedStream( - Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum); + Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator()); size_t StreamLen = FS->getLength(); if (StreamLen % sizeof(object::FpoData)) @@ -318,7 +299,7 @@ Error DbiStream::initializeFpoRecords() { "Corrupted New FPO stream."); size_t NumRecords = StreamLen / sizeof(object::FpoData); - msf::StreamReader Reader(*FS); + BinaryStreamReader Reader(*FS); if (auto EC = Reader.readArray(FpoRecords, NumRecords)) return make_error<RawError>(raw_error_code::corrupt_file, "Corrupted New FPO stream."); @@ -326,82 +307,38 @@ Error DbiStream::initializeFpoRecords() { return Error::success(); } -Error DbiStream::initializeSectionMapData() { - if (SecMapSubstream.getLength() == 0) - return Error::success(); +BinarySubstreamRef DbiStream::getSectionContributionData() const { + return SecContrSubstream; +} - StreamReader SMReader(SecMapSubstream); - const SecMapHeader *Header; - if (auto EC = SMReader.readObject(Header)) - return EC; - if (auto EC = SMReader.readArray(SectionMap, Header->SecCount)) - return EC; - return Error::success(); +BinarySubstreamRef DbiStream::getSecMapSubstreamData() const { + return SecMapSubstream; } -Error DbiStream::initializeFileInfo() { - if (FileInfoSubstream.getLength() == 0) - return Error::success(); +BinarySubstreamRef DbiStream::getModiSubstreamData() const { + return ModiSubstream; +} - const FileInfoSubstreamHeader *FH; - StreamReader FISR(FileInfoSubstream); - if (auto EC = FISR.readObject(FH)) - return EC; +BinarySubstreamRef DbiStream::getFileInfoSubstreamData() const { + return FileInfoSubstream; +} - // The number of modules in the stream should be the same as reported by - // the FileInfoSubstreamHeader. - if (FH->NumModules != ModuleInfos.size()) - return make_error<RawError>(raw_error_code::corrupt_file, - "FileInfo substream count doesn't match DBI."); +BinarySubstreamRef DbiStream::getTypeServerMapSubstreamData() const { + return TypeServerMapSubstream; +} - FixedStreamArray<ulittle16_t> ModIndexArray; - FixedStreamArray<ulittle16_t> ModFileCountArray; +BinarySubstreamRef DbiStream::getECSubstreamData() const { return ECSubstream; } - // First is an array of `NumModules` module indices. This is not used for the - // same reason that `NumSourceFiles` is not used. It's an array of uint16's, - // but it's possible there are more than 64k source files, which would imply - // more than 64k modules (e.g. object files) as well. So we ignore this - // field. - if (auto EC = FISR.readArray(ModIndexArray, ModuleInfos.size())) - return EC; - if (auto EC = FISR.readArray(ModFileCountArray, ModuleInfos.size())) - return EC; +Error DbiStream::initializeSectionMapData() { + if (SecMapSubstream.empty()) + return Error::success(); - // Compute the real number of source files. - uint32_t NumSourceFiles = 0; - for (auto Count : ModFileCountArray) - NumSourceFiles += Count; - - // This is the array that in the reference implementation corresponds to - // `ModInfo::FileLayout::FileNameOffs`, which is commented there as being a - // pointer. Due to the mentioned problems of pointers causing difficulty - // when reading from the file on 64-bit systems, we continue to ignore that - // field in `ModInfo`, and instead build a vector of StringRefs and stores - // them in `ModuleInfoEx`. The value written to and read from the file is - // not used anyway, it is only there as a way to store the offsets for the - // purposes of later accessing the names at runtime. - if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles)) + BinaryStreamReader SMReader(SecMapSubstream.StreamData); + const SecMapHeader *Header; + if (auto EC = SMReader.readObject(Header)) return EC; - - if (auto EC = FISR.readStreamRef(NamesBuffer)) + if (auto EC = SMReader.readArray(SectionMap, Header->SecCount)) return EC; - - // We go through each ModuleInfo, determine the number N of source files for - // that module, and then get the next N offsets from the Offsets array, using - // them to get the corresponding N names from the Names buffer and associating - // each one with the corresponding module. - uint32_t NextFileIndex = 0; - for (size_t I = 0; I < ModuleInfos.size(); ++I) { - uint32_t NumFiles = ModFileCountArray[I]; - ModuleInfos[I].SourceFiles.resize(NumFiles); - for (size_t J = 0; J < NumFiles; ++J, ++NextFileIndex) { - auto ThisName = getFileNameForIndex(NextFileIndex); - if (!ThisName) - return ThisName.takeError(); - ModuleInfos[I].SourceFiles[J] = *ThisName; - } - } - return Error::success(); } @@ -411,16 +348,3 @@ uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const { return kInvalidStreamIndex; return DbgStreams[T]; } - -Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const { - StreamReader Names(NamesBuffer); - if (Index >= FileNameOffsets.size()) - return make_error<RawError>(raw_error_code::index_out_of_bounds); - - uint32_t FileOffset = FileNameOffsets[Index]; - Names.setOffset(FileOffset); - StringRef Name; - if (auto EC = Names.readZeroString(Name)) - return std::move(EC); - return Name; -} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp index 1d5b8d6..25076e4 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -7,31 +7,30 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h" +#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/MSF/StreamWriter.h" -#include "llvm/DebugInfo/PDB/Raw/DbiStream.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" +#include "llvm/DebugInfo/PDB/Native/DbiStream.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/Object/COFF.h" -#include "llvm/Support/COFF.h" +#include "llvm/Support/BinaryStreamWriter.h" using namespace llvm; using namespace llvm::codeview; using namespace llvm::msf; using namespace llvm::pdb; -namespace { -class ModiSubstreamBuilder {}; -} - 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) {} +DbiStreamBuilder::~DbiStreamBuilder() {} + void DbiStreamBuilder::setVersionHeader(PdbRaw_DbiVer V) { VerHeader = V; } void DbiStreamBuilder::setAge(uint32_t A) { Age = A; } @@ -46,17 +45,21 @@ void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; } void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; } -void DbiStreamBuilder::setSectionContribs(ArrayRef<SectionContrib> Arr) { - SectionContribs = Arr; -} - void DbiStreamBuilder::setSectionMap(ArrayRef<SecMapEntry> SecMap) { SectionMap = SecMap; } +void DbiStreamBuilder::setSymbolRecordStreamIndex(uint32_t Index) { + SymRecordStreamIndex = Index; +} + +void DbiStreamBuilder::setPublicsStreamIndex(uint32_t Index) { + PublicsStreamIndex = Index; +} + Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type, ArrayRef<uint8_t> Data) { - if (DbgStreams[(int)Type].StreamNumber) + 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()); @@ -68,46 +71,62 @@ Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type, return Error::success(); } +uint32_t DbiStreamBuilder::addECName(StringRef Name) { + return ECNamesBuilder.insert(Name); +} + uint32_t DbiStreamBuilder::calculateSerializedLength() const { // For now we only support serializing the header. return sizeof(DbiStreamHeader) + calculateFileInfoSubstreamSize() + calculateModiSubstreamSize() + calculateSectionContribsStreamSize() + - calculateSectionMapStreamSize() + calculateDbgStreamsSize(); + calculateSectionMapStreamSize() + calculateDbgStreamsSize() + + ECNamesBuilder.calculateSerializedSize(); } -Error DbiStreamBuilder::addModuleInfo(StringRef ObjFile, StringRef Module) { - auto Entry = llvm::make_unique<ModuleInfo>(); - ModuleInfo *M = Entry.get(); - Entry->Mod = Module; - Entry->Obj = ObjFile; - auto Result = ModuleInfos.insert(std::make_pair(Module, std::move(Entry))); +Expected<DbiModuleDescriptorBuilder &> +DbiStreamBuilder::addModuleInfo(StringRef ModuleName) { + uint32_t Index = ModiList.size(); + auto MIB = + llvm::make_unique<DbiModuleDescriptorBuilder>(ModuleName, Index, Msf); + auto M = MIB.get(); + auto Result = ModiMap.insert(std::make_pair(ModuleName, std::move(MIB))); + if (!Result.second) return make_error<RawError>(raw_error_code::duplicate_entry, "The specified module already exists"); - ModuleInfoList.push_back(M); - return Error::success(); + ModiList.push_back(M); + return *M; } Error DbiStreamBuilder::addModuleSourceFile(StringRef Module, StringRef File) { - auto ModIter = ModuleInfos.find(Module); - if (ModIter == ModuleInfos.end()) + auto ModIter = ModiMap.find(Module); + if (ModIter == ModiMap.end()) return make_error<RawError>(raw_error_code::no_entry, "The specified module was not found"); + return addModuleSourceFile(*ModIter->second, File); +} + +Error DbiStreamBuilder::addModuleSourceFile(DbiModuleDescriptorBuilder &Module, + StringRef File) { uint32_t Index = SourceFileNames.size(); SourceFileNames.insert(std::make_pair(File, Index)); - auto &ModEntry = *ModIter; - ModEntry.second->SourceFiles.push_back(File); + Module.addSourceFile(File); return Error::success(); } +Expected<uint32_t> DbiStreamBuilder::getSourceFileNameIndex(StringRef File) { + auto NameIter = SourceFileNames.find(File); + if (NameIter == SourceFileNames.end()) + return make_error<RawError>(raw_error_code::no_entry, + "The specified source file was not found"); + return NameIter->getValue(); +} + uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const { uint32_t Size = 0; - for (const auto &M : ModuleInfoList) { - Size += sizeof(ModuleInfoHeader); - Size += M->Mod.size() + 1; - Size += M->Obj.size() + 1; - } - return alignTo(Size, sizeof(uint32_t)); + for (const auto &M : ModiList) + Size += M->calculateSerializedLength(); + return Size; } uint32_t DbiStreamBuilder::calculateSectionContribsStreamSize() const { @@ -123,16 +142,21 @@ uint32_t DbiStreamBuilder::calculateSectionMapStreamSize() const { return sizeof(SecMapHeader) + sizeof(SecMapEntry) * SectionMap.size(); } -uint32_t DbiStreamBuilder::calculateFileInfoSubstreamSize() const { - uint32_t Size = 0; - Size += sizeof(ulittle16_t); // NumModules - Size += sizeof(ulittle16_t); // NumSourceFiles - Size += ModuleInfoList.size() * sizeof(ulittle16_t); // ModIndices - Size += ModuleInfoList.size() * sizeof(ulittle16_t); // ModFileCounts +uint32_t DbiStreamBuilder::calculateNamesOffset() const { + uint32_t Offset = 0; + Offset += sizeof(ulittle16_t); // NumModules + Offset += sizeof(ulittle16_t); // NumSourceFiles + Offset += ModiList.size() * sizeof(ulittle16_t); // ModIndices + Offset += ModiList.size() * sizeof(ulittle16_t); // ModFileCounts uint32_t NumFileInfos = 0; - for (const auto &M : ModuleInfoList) - NumFileInfos += M->SourceFiles.size(); - Size += NumFileInfos * sizeof(ulittle32_t); // FileNameOffsets + for (const auto &M : ModiList) + NumFileInfos += M->source_files().size(); + Offset += NumFileInfos * sizeof(ulittle32_t); // FileNameOffsets + return Offset; +} + +uint32_t DbiStreamBuilder::calculateFileInfoSubstreamSize() const { + uint32_t Size = calculateNamesOffset(); Size += calculateNamesBufferSize(); return alignTo(Size, sizeof(uint32_t)); } @@ -149,43 +173,19 @@ uint32_t DbiStreamBuilder::calculateDbgStreamsSize() const { return DbgStreams.size() * sizeof(uint16_t); } -Error DbiStreamBuilder::generateModiSubstream() { - uint32_t Size = calculateModiSubstreamSize(); - auto Data = Allocator.Allocate<uint8_t>(Size); - - ModInfoBuffer = MutableByteStream(MutableArrayRef<uint8_t>(Data, Size)); - - StreamWriter ModiWriter(ModInfoBuffer); - for (const auto &M : ModuleInfoList) { - ModuleInfoHeader Layout = {}; - Layout.ModDiStream = kInvalidStreamIndex; - Layout.NumFiles = M->SourceFiles.size(); - if (auto EC = ModiWriter.writeObject(Layout)) - return EC; - if (auto EC = ModiWriter.writeZeroString(M->Mod)) - return EC; - if (auto EC = ModiWriter.writeZeroString(M->Obj)) - return EC; - } - if (ModiWriter.bytesRemaining() > sizeof(uint32_t)) - return make_error<RawError>(raw_error_code::invalid_format, - "Unexpected bytes in Modi Stream Data"); - return Error::success(); -} - Error DbiStreamBuilder::generateFileInfoSubstream() { uint32_t Size = calculateFileInfoSubstreamSize(); - uint32_t NameSize = calculateNamesBufferSize(); auto Data = Allocator.Allocate<uint8_t>(Size); - uint32_t NamesOffset = Size - NameSize; + uint32_t NamesOffset = calculateNamesOffset(); - FileInfoBuffer = MutableByteStream(MutableArrayRef<uint8_t>(Data, Size)); + FileInfoBuffer = MutableBinaryByteStream(MutableArrayRef<uint8_t>(Data, Size), + llvm::support::little); - WritableStreamRef MetadataBuffer = - WritableStreamRef(FileInfoBuffer).keep_front(NamesOffset); - StreamWriter MetadataWriter(MetadataBuffer); + WritableBinaryStreamRef MetadataBuffer = + WritableBinaryStreamRef(FileInfoBuffer).keep_front(NamesOffset); + BinaryStreamWriter MetadataWriter(MetadataBuffer); - uint16_t ModiCount = std::min<uint32_t>(UINT16_MAX, ModuleInfos.size()); + uint16_t ModiCount = std::min<uint32_t>(UINT16_MAX, ModiList.size()); uint16_t FileCount = std::min<uint32_t>(UINT16_MAX, SourceFileNames.size()); if (auto EC = MetadataWriter.writeInteger(ModiCount)) // NumModules return EC; @@ -195,8 +195,8 @@ Error DbiStreamBuilder::generateFileInfoSubstream() { if (auto EC = MetadataWriter.writeInteger(I)) // Mod Indices return EC; } - for (const auto MI : ModuleInfoList) { - FileCount = static_cast<uint16_t>(MI->SourceFiles.size()); + for (const auto &MI : ModiList) { + FileCount = static_cast<uint16_t>(MI->source_files().size()); if (auto EC = MetadataWriter.writeInteger(FileCount)) // Mod File Counts return EC; } @@ -205,16 +205,16 @@ Error DbiStreamBuilder::generateFileInfoSubstream() { // A side effect of this is that this will actually compute the various // file name offsets, so we can then go back and write the FileNameOffsets // array to the other substream. - NamesBuffer = WritableStreamRef(FileInfoBuffer).drop_front(NamesOffset); - StreamWriter NameBufferWriter(NamesBuffer); + NamesBuffer = WritableBinaryStreamRef(FileInfoBuffer).drop_front(NamesOffset); + BinaryStreamWriter NameBufferWriter(NamesBuffer); for (auto &Name : SourceFileNames) { Name.second = NameBufferWriter.getOffset(); - if (auto EC = NameBufferWriter.writeZeroString(Name.getKey())) + if (auto EC = NameBufferWriter.writeCString(Name.getKey())) return EC; } - for (const auto MI : ModuleInfoList) { - for (StringRef Name : MI->SourceFiles) { + for (const auto &MI : ModiList) { + for (StringRef Name : MI->source_files()) { auto Result = SourceFileNames.find(Name); if (Result == SourceFileNames.end()) return make_error<RawError>(raw_error_code::no_entry, @@ -224,6 +224,9 @@ Error DbiStreamBuilder::generateFileInfoSubstream() { } } + if (auto EC = NameBufferWriter.padToAlignment(sizeof(uint32_t))) + return EC; + if (NameBufferWriter.bytesRemaining() > 0) return make_error<RawError>(raw_error_code::invalid_format, "The names buffer contained unexpected data."); @@ -240,13 +243,14 @@ Error DbiStreamBuilder::finalize() { if (Header) return Error::success(); - DbiStreamHeader *H = Allocator.Allocate<DbiStreamHeader>(); + for (auto &MI : ModiList) + MI->finalize(); - if (auto EC = generateModiSubstream()) - return EC; if (auto EC = generateFileInfoSubstream()) return EC; + DbiStreamHeader *H = Allocator.Allocate<DbiStreamHeader>(); + ::memset(H, 0, sizeof(DbiStreamHeader)); H->VersionHeader = *VerHeader; H->VersionSignature = -1; H->Age = Age; @@ -256,15 +260,15 @@ Error DbiStreamBuilder::finalize() { H->PdbDllVersion = PdbDllVersion; H->MachineType = static_cast<uint16_t>(MachineType); - H->ECSubstreamSize = 0; + H->ECSubstreamSize = ECNamesBuilder.calculateSerializedSize(); H->FileInfoSize = FileInfoBuffer.getLength(); - H->ModiSubstreamSize = ModInfoBuffer.getLength(); + H->ModiSubstreamSize = calculateModiSubstreamSize(); H->OptionalDbgHdrSize = DbgStreams.size() * sizeof(uint16_t); H->SecContrSubstreamSize = calculateSectionContribsStreamSize(); H->SectionMapSize = calculateSectionMapStreamSize(); H->TypeServerSize = 0; - H->SymRecordStreamIndex = kInvalidStreamIndex; - H->PublicSymbolStreamIndex = kInvalidStreamIndex; + H->SymRecordStreamIndex = SymRecordStreamIndex; + H->PublicSymbolStreamIndex = PublicsStreamIndex; H->MFCTypeServerIndex = kInvalidStreamIndex; H->GlobalSymbolStreamIndex = kInvalidStreamIndex; @@ -273,6 +277,11 @@ Error DbiStreamBuilder::finalize() { } Error DbiStreamBuilder::finalizeMsfLayout() { + for (auto &MI : ModiList) { + if (auto EC = MI->finalizeMsfLayout()) + return EC; + } + uint32_t Length = calculateSerializedLength(); if (auto EC = Msf.setStreamSize(StreamDBI, Length)) return EC; @@ -298,23 +307,17 @@ static uint16_t toSecMapFlags(uint32_t Flags) { return Ret; } -// A utility function to create Section Contributions -// for a given input sections. -std::vector<SectionContrib> DbiStreamBuilder::createSectionContribs( - ArrayRef<object::coff_section> SecHdrs) { - std::vector<SectionContrib> Ret; - - // Create a SectionContrib for each input section. - for (auto &Sec : SecHdrs) { - Ret.emplace_back(); - auto &Entry = Ret.back(); - memset(&Entry, 0, sizeof(Entry)); - - Entry.Off = Sec.PointerToRawData; - Entry.Size = Sec.SizeOfRawData; - Entry.Characteristics = Sec.Characteristics; - } - return Ret; +void DbiStreamBuilder::addSectionContrib(DbiModuleDescriptorBuilder *ModuleDbi, + const object::coff_section *SecHdr) { + SectionContrib SC; + memset(&SC, 0, sizeof(SC)); + SC.ISect = (uint16_t)~0U; // This represents nil. + SC.Off = SecHdr->PointerToRawData; + SC.Size = SecHdr->SizeOfRawData; + SC.Characteristics = SecHdr->Characteristics; + // Use the module index in the module dbi stream or nil (-1). + SC.Imod = ModuleDbi ? ModuleDbi->getModuleIndex() : (uint16_t)~0U; + SectionContribs.emplace_back(SC); } // A utility function to create a Section Map for a given list of COFF sections. @@ -358,24 +361,26 @@ std::vector<SecMapEntry> DbiStreamBuilder::createSectionMap( } Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout, - const msf::WritableStream &Buffer) { + WritableBinaryStreamRef MsfBuffer) { if (auto EC = finalize()) return EC; - auto InfoS = - WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamDBI); + auto DbiS = WritableMappedBlockStream::createIndexedStream( + Layout, MsfBuffer, StreamDBI, Allocator); - StreamWriter Writer(*InfoS); + BinaryStreamWriter Writer(*DbiS); if (auto EC = Writer.writeObject(*Header)) return EC; - if (auto EC = Writer.writeStreamRef(ModInfoBuffer)) - return EC; + for (auto &M : ModiList) { + if (auto EC = M->commit(Writer, Layout, MsfBuffer)) + return EC; + } if (!SectionContribs.empty()) { if (auto EC = Writer.writeEnum(DbiSecContribVer60)) return EC; - if (auto EC = Writer.writeArray(SectionContribs)) + if (auto EC = Writer.writeArray(makeArrayRef(SectionContribs))) return EC; } @@ -391,6 +396,9 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout, if (auto EC = Writer.writeStreamRef(FileInfoBuffer)) return EC; + if (auto EC = ECNamesBuilder.commit(Writer)) + return EC; + for (auto &Stream : DbgStreams) if (auto EC = Writer.writeInteger(Stream.StreamNumber)) return EC; @@ -399,8 +407,8 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout, if (Stream.StreamNumber == kInvalidStreamIndex) continue; auto WritableStream = WritableMappedBlockStream::createIndexedStream( - Layout, Buffer, Stream.StreamNumber); - StreamWriter DbgStreamWriter(*WritableStream); + Layout, MsfBuffer, Stream.StreamNumber, Allocator); + BinaryStreamWriter DbgStreamWriter(*WritableStream); if (auto EC = DbgStreamWriter.writeArray(Stream.Data)) return EC; } diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/EnumTables.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/EnumTables.cpp index fc9270c..b3837dc 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/EnumTables.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/EnumTables.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/Raw/EnumTables.h" -#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/EnumTables.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" using namespace llvm; using namespace llvm::pdb; diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/GSI.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/GSI.cpp index 6ecbb5c..b219fe2 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/GSI.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/GSI.cpp @@ -9,10 +9,10 @@ #include "GSI.h" -#include "llvm/DebugInfo/MSF/StreamArray.h" -#include "llvm/DebugInfo/MSF/StreamReader.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" -#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Error.h" @@ -28,9 +28,9 @@ static Error checkHashHdrVersion(const GSIHashHeader *HashHdr) { return Error::success(); } -Error readGSIHashBuckets( - msf::FixedStreamArray<support::ulittle32_t> &HashBuckets, - const GSIHashHeader *HashHdr, msf::StreamReader &Reader) { +Error readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets, + const GSIHashHeader *HashHdr, + BinaryStreamReader &Reader) { if (auto EC = checkHashHdrVersion(HashHdr)) return EC; @@ -57,7 +57,7 @@ Error readGSIHashBuckets( } Error readGSIHashHeader(const GSIHashHeader *&HashHdr, - msf::StreamReader &Reader) { + BinaryStreamReader &Reader) { if (Reader.readObject(HashHdr)) return make_error<RawError>(raw_error_code::corrupt_file, "Stream does not contain a GSIHashHeader."); @@ -70,9 +70,9 @@ Error readGSIHashHeader(const GSIHashHeader *&HashHdr, return Error::success(); } -Error readGSIHashRecords(msf::FixedStreamArray<PSHashRecord> &HashRecords, +Error readGSIHashRecords(FixedStreamArray<PSHashRecord> &HashRecords, const GSIHashHeader *HashHdr, - msf::StreamReader &Reader) { + BinaryStreamReader &Reader) { if (auto EC = checkHashHdrVersion(HashHdr)) return EC; diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/GSI.h b/contrib/llvm/lib/DebugInfo/PDB/Native/GSI.h index 82cebd9..9e63bc8 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/GSI.h +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/GSI.h @@ -25,17 +25,15 @@ #ifndef LLVM_LIB_DEBUGINFO_PDB_RAW_GSI_H #define LLVM_LIB_DEBUGINFO_PDB_RAW_GSI_H -#include "llvm/DebugInfo/MSF/StreamArray.h" -#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" namespace llvm { -namespace msf { -class StreamReader; -} +class BinaryStreamReader; namespace pdb { @@ -56,14 +54,14 @@ struct GSIHashHeader { support::ulittle32_t NumBuckets; }; -Error readGSIHashBuckets( - msf::FixedStreamArray<support::ulittle32_t> &HashBuckets, - const GSIHashHeader *HashHdr, msf::StreamReader &Reader); +Error readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets, + const GSIHashHeader *HashHdr, + BinaryStreamReader &Reader); Error readGSIHashHeader(const GSIHashHeader *&HashHdr, - msf::StreamReader &Reader); -Error readGSIHashRecords(msf::FixedStreamArray<PSHashRecord> &HashRecords, + BinaryStreamReader &Reader); +Error readGSIHashRecords(FixedStreamArray<PSHashRecord> &HashRecords, const GSIHashHeader *HashHdr, - msf::StreamReader &Reader); + BinaryStreamReader &Reader); } } diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/GlobalsStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/GlobalsStream.cpp index 31afc92..a2ee0f0 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/GlobalsStream.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/GlobalsStream.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// +#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" #include "GSI.h" -#include "llvm/DebugInfo/MSF/StreamReader.h" -#include "llvm/DebugInfo/PDB/Raw/GlobalsStream.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Error.h" #include <algorithm> @@ -23,7 +23,7 @@ GlobalsStream::GlobalsStream(std::unique_ptr<MappedBlockStream> Stream) GlobalsStream::~GlobalsStream() = default; Error GlobalsStream::reload() { - StreamReader Reader(*Stream); + BinaryStreamReader Reader(*Stream); const GSIHashHeader *HashHdr; if (auto EC = readGSIHashHeader(HashHdr, Reader)) diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/Hash.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/Hash.cpp index b9f685e..61188ec 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/Hash.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/Hash.cpp @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/Raw/Hash.h" - +#include "llvm/DebugInfo/PDB/Native/Hash.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Endian.h" #include "llvm/Support/JamCRC.h" +#include <cstdint> using namespace llvm; using namespace llvm::support; diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/HashTable.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/HashTable.cpp new file mode 100644 index 0000000..439217f --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/HashTable.cpp @@ -0,0 +1,308 @@ +//===- HashTable.cpp - PDB Hash Table -------------------------------------===// +// +// 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/Native/HashTable.h" +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MathExtras.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <utility> + +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, + SparseBitVector<> &V) { + uint32_t NumWords; + if (auto EC = Stream.readInteger(NumWords)) + return joinErrors( + std::move(EC), + make_error<RawError>(raw_error_code::corrupt_file, + "Expected hash table number of words")); + + for (uint32_t I = 0; I != NumWords; ++I) { + uint32_t Word; + if (auto EC = Stream.readInteger(Word)) + return joinErrors(std::move(EC), + make_error<RawError>(raw_error_code::corrupt_file, + "Expected hash table word")); + for (unsigned Idx = 0; Idx < 32; ++Idx) + if (Word & (1U << Idx)) + V.set((I * 32) + Idx); + } + return Error::success(); +} + +Error HashTable::writeSparseBitVector(BinaryStreamWriter &Writer, + SparseBitVector<> &Vec) { + int ReqBits = Vec.find_last() + 1; + uint32_t NumWords = alignTo(ReqBits, sizeof(uint32_t)) / sizeof(uint32_t); + if (auto EC = Writer.writeInteger(NumWords)) + 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) { + uint32_t Word = 0; + for (uint32_t WordIdx = 0; WordIdx < 32; ++WordIdx, ++Idx) { + if (Vec.test(Idx)) + Word |= (1 << WordIdx); + } + if (auto EC = Writer.writeInteger(Word)) + return joinErrors(std::move(EC), make_error<RawError>( + raw_error_code::corrupt_file, + "Could not write linear map word")); + } + 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 new file mode 100644 index 0000000..8298790 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStream.cpp @@ -0,0 +1,139 @@ +//===- InfoStream.cpp - PDB Info Stream (Stream 1) Access -------*- 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/Native/InfoStream.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamWriter.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::msf; +using namespace llvm::pdb; + +InfoStream::InfoStream(std::unique_ptr<MappedBlockStream> Stream) + : Stream(std::move(Stream)) {} + +Error InfoStream::reload() { + BinaryStreamReader Reader(*Stream); + + const InfoStreamHeader *H; + if (auto EC = Reader.readObject(H)) + return joinErrors( + std::move(EC), + make_error<RawError>(raw_error_code::corrupt_file, + "PDB Stream does not contain a header.")); + + switch (H->Version) { + case PdbImplVC70: + case PdbImplVC80: + case PdbImplVC110: + case PdbImplVC140: + break; + default: + return make_error<RawError>(raw_error_code::corrupt_file, + "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; + uint32_t NewOffset = Reader.getOffset(); + NamedStreamMapByteSize = NewOffset - Offset; + + Reader.setOffset(Offset); + if (auto EC = Reader.readSubstream(SubNamedStreams, NamedStreamMapByteSize)) + return EC; + + bool Stop = false; + while (!Stop && !Reader.empty()) { + PdbRaw_FeatureSig Sig; + if (auto EC = Reader.readEnum(Sig)) + return EC; + // Since this value comes from a file, it's possible we have some strange + // value which doesn't correspond to any value. We don't want to warn on + // -Wcovered-switch-default in this case, so switch on the integral value + // instead of the enumeration value. + switch (uint32_t(Sig)) { + case uint32_t(PdbRaw_FeatureSig::VC110): + // No other flags for VC110 PDB. + Stop = true; + LLVM_FALLTHROUGH; + case uint32_t(PdbRaw_FeatureSig::VC140): + Features |= PdbFeatureContainsIdStream; + break; + case uint32_t(PdbRaw_FeatureSig::NoTypeMerge): + Features |= PdbFeatureNoTypeMerging; + break; + case uint32_t(PdbRaw_FeatureSig::MinimalDebugInfo): + Features |= PdbFeatureMinimalDebugInfo; + break; + default: + continue; + } + FeatureSignatures.push_back(Sig); + } + return Error::success(); +} + +uint32_t InfoStream::getStreamSize() const { return Stream->getLength(); } + +uint32_t InfoStream::getNamedStreamIndex(llvm::StringRef Name) const { + uint32_t Result; + if (!NamedStreams.get(Name, Result)) + return 0; + return Result; +} + +iterator_range<StringMapConstIterator<uint32_t>> +InfoStream::named_streams() const { + return NamedStreams.entries(); +} + +bool InfoStream::containsIdStream() const { + return !!(Features & PdbFeatureContainsIdStream); +} + +PdbRaw_ImplVer InfoStream::getVersion() const { + return static_cast<PdbRaw_ImplVer>(Version); +} + +uint32_t InfoStream::getSignature() const { return Signature; } + +uint32_t InfoStream::getAge() const { return Age; } + +GUID InfoStream::getGuid() const { return Guid; } + +uint32_t InfoStream::getNamedStreamMapByteSize() const { + return NamedStreamMapByteSize; +} + +PdbRaw_Features InfoStream::getFeatures() const { return Features; } + +ArrayRef<PdbRaw_FeatureSig> InfoStream::getFeatureSignatures() const { + return FeatureSignatures; +} + +const NamedStreamMap &InfoStream::getNamedStreams() const { + return NamedStreams; +} + +BinarySubstreamRef InfoStream::getNamedStreamsBuffer() const { + return SubNamedStreams; +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp new file mode 100644 index 0000000..6450ae7 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp @@ -0,0 +1,74 @@ +//===- InfoStreamBuilder.cpp - PDB Info Stream Creation ---------*- 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/Native/InfoStreamBuilder.h" + +#include "llvm/DebugInfo/MSF/MSFBuilder.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h" +#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryStreamWriter.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::msf; +using namespace llvm::pdb; + +InfoStreamBuilder::InfoStreamBuilder(msf::MSFBuilder &Msf, + NamedStreamMap &NamedStreams) + : Msf(Msf), Ver(PdbRaw_ImplVer::PdbImplVC70), Sig(-1), Age(0), + NamedStreams(NamedStreams) {} + +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::setGuid(GUID G) { Guid = G; } + +void InfoStreamBuilder::addFeature(PdbRaw_FeatureSig Sig) { + Features.push_back(Sig); +} + +Error InfoStreamBuilder::finalizeMsfLayout() { + uint32_t Length = sizeof(InfoStreamHeader) + NamedStreams.finalize() + + (Features.size() + 1) * sizeof(uint32_t); + if (auto EC = Msf.setStreamSize(StreamPDB, Length)) + return EC; + return Error::success(); +} + +Error InfoStreamBuilder::commit(const msf::MSFLayout &Layout, + WritableBinaryStreamRef Buffer) const { + auto InfoS = WritableMappedBlockStream::createIndexedStream( + Layout, Buffer, StreamPDB, Msf.getAllocator()); + BinaryStreamWriter Writer(*InfoS); + + InfoStreamHeader H; + H.Age = Age; + H.Signature = Sig; + H.Version = Ver; + H.Guid = Guid; + if (auto EC = Writer.writeObject(H)) + return EC; + + if (auto EC = NamedStreams.commit(Writer)) + return EC; + if (auto EC = Writer.writeInteger(0)) + return EC; + for (auto E : Features) { + if (auto EC = Writer.writeEnum(E)) + return EC; + } + return Error::success(); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp new file mode 100644 index 0000000..2e1f61c --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp @@ -0,0 +1,123 @@ +//===- ModuleDebugStream.cpp - PDB Module Info Stream Access --------------===// +// +// 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/Native/ModuleDebugStream.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Error.h" +#include <algorithm> +#include <cstdint> + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::msf; +using namespace llvm::pdb; + +ModuleDebugStreamRef::ModuleDebugStreamRef( + const DbiModuleDescriptor &Module, + std::unique_ptr<MappedBlockStream> Stream) + : Mod(Module), Stream(std::move(Stream)) {} + +ModuleDebugStreamRef::~ModuleDebugStreamRef() = default; + +Error ModuleDebugStreamRef::reload() { + BinaryStreamReader Reader(*Stream); + + uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize(); + uint32_t C11Size = Mod.getC11LineInfoByteSize(); + uint32_t C13Size = Mod.getC13LineInfoByteSize(); + + if (C11Size > 0 && C13Size > 0) + return make_error<RawError>(raw_error_code::corrupt_file, + "Module has both C11 and C13 line info"); + + BinaryStreamRef S; + + if (auto EC = Reader.readInteger(Signature)) + return EC; + if (auto EC = Reader.readSubstream(SymbolsSubstream, SymbolSize - 4)) + return EC; + if (auto EC = Reader.readSubstream(C11LinesSubstream, C11Size)) + return EC; + if (auto EC = Reader.readSubstream(C13LinesSubstream, C13Size)) + return EC; + + BinaryStreamReader SymbolReader(SymbolsSubstream.StreamData); + if (auto EC = + SymbolReader.readArray(SymbolArray, SymbolReader.bytesRemaining())) + return EC; + + BinaryStreamReader SubsectionsReader(C13LinesSubstream.StreamData); + if (auto EC = SubsectionsReader.readArray(Subsections, + SubsectionsReader.bytesRemaining())) + return EC; + + uint32_t GlobalRefsSize; + if (auto EC = Reader.readInteger(GlobalRefsSize)) + return EC; + if (auto EC = Reader.readSubstream(GlobalRefsSubstream, GlobalRefsSize)) + return EC; + if (Reader.bytesRemaining() > 0) + return make_error<RawError>(raw_error_code::corrupt_file, + "Unexpected bytes in module stream."); + + return Error::success(); +} + +BinarySubstreamRef ModuleDebugStreamRef::getSymbolsSubstream() const { + return SymbolsSubstream; +} + +BinarySubstreamRef ModuleDebugStreamRef::getC11LinesSubstream() const { + return C11LinesSubstream; +} + +BinarySubstreamRef ModuleDebugStreamRef::getC13LinesSubstream() const { + return C13LinesSubstream; +} + +BinarySubstreamRef ModuleDebugStreamRef::getGlobalRefsSubstream() const { + return GlobalRefsSubstream; +} + +iterator_range<codeview::CVSymbolArray::Iterator> +ModuleDebugStreamRef::symbols(bool *HadError) const { + return make_range(SymbolArray.begin(HadError), SymbolArray.end()); +} + +iterator_range<ModuleDebugStreamRef::DebugSubsectionIterator> +ModuleDebugStreamRef::subsections() const { + return make_range(Subsections.begin(), Subsections.end()); +} + +bool ModuleDebugStreamRef::hasDebugSubsections() const { + return !C13LinesSubstream.empty(); +} + +Error ModuleDebugStreamRef::commit() { return Error::success(); } + +Expected<codeview::DebugChecksumsSubsectionRef> +ModuleDebugStreamRef::findChecksumsSubsection() const { + codeview::DebugChecksumsSubsectionRef Result; + for (const auto &SS : subsections()) { + if (SS.kind() != DebugSubsectionKind::FileChecksums) + continue; + + if (auto EC = Result.initialize(SS.getRecordData())) + return std::move(EC); + return Result; + } + return Result; +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp new file mode 100644 index 0000000..6cdf6dd --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp @@ -0,0 +1,152 @@ +//===- NamedStreamMap.cpp - PDB Named Stream Map --------------------------===// +// +// 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/Native/NamedStreamMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/DebugInfo/PDB/Native/HashTable.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <tuple> + +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"}; + +NamedStreamMap::NamedStreamMap() = default; + +Error NamedStreamMap::load(BinaryStreamReader &Stream) { + Mapping.clear(); + FinalizedHashTable.clear(); + FinalizedInfo.reset(); + + 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)) + return EC; + + 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(); +} + +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)) + 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; + } + + // And finally the Offset Index map. + if (auto EC = FinalizedHashTable.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(); + + 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; + } + + // 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; +} + +iterator_range<StringMapConstIterator<uint32_t>> +NamedStreamMap::entries() const { + return make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(), + Mapping.end()); +} + +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()) + return false; + StreamNo = Iter->second; + return true; +} + +void NamedStreamMap::set(StringRef Stream, uint32_t StreamNo) { + FinalizedInfo.reset(); + Mapping[Stream] = StreamNo; +} + +void NamedStreamMap::remove(StringRef Stream) { + FinalizedInfo.reset(); + Mapping.erase(Stream); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeBuiltinSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeBuiltinSymbol.cpp new file mode 100644 index 0000000..60416f6 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeBuiltinSymbol.cpp @@ -0,0 +1,48 @@ +//===- NativeBuiltinSymbol.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/Native/NativeBuiltinSymbol.h" + +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" + +namespace llvm { +namespace pdb { + +NativeBuiltinSymbol::NativeBuiltinSymbol(NativeSession &PDBSession, + SymIndexId Id, PDB_BuiltinType T, + uint64_t L) + : NativeRawSymbol(PDBSession, Id), Session(PDBSession), Type(T), Length(L) { +} + +NativeBuiltinSymbol::~NativeBuiltinSymbol() {} + +std::unique_ptr<NativeRawSymbol> NativeBuiltinSymbol::clone() const { + return llvm::make_unique<NativeBuiltinSymbol>(Session, SymbolId, Type, Length); +} + +void NativeBuiltinSymbol::dump(raw_ostream &OS, int Indent) const { + // TODO: Apparently nothing needs this yet. +} + +PDB_SymType NativeBuiltinSymbol::getSymTag() const { + return PDB_SymType::BuiltinType; +} + +PDB_BuiltinType NativeBuiltinSymbol::getBuiltinType() const { return Type; } + +bool NativeBuiltinSymbol::isConstType() const { return false; } + +uint64_t NativeBuiltinSymbol::getLength() const { return Length; } + +bool NativeBuiltinSymbol::isUnalignedType() const { return false; } + +bool NativeBuiltinSymbol::isVolatileType() const { return false; } + +} // namespace pdb +} // namespace llvm diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp new file mode 100644 index 0000000..7132a99 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp @@ -0,0 +1,50 @@ +//===- NativeCompilandSymbol.cpp - Native impl for compilands ---*- 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/Native/NativeCompilandSymbol.h" + +#include "llvm/ADT/STLExtras.h" + +namespace llvm { +namespace pdb { + +NativeCompilandSymbol::NativeCompilandSymbol(NativeSession &Session, + SymIndexId SymbolId, + DbiModuleDescriptor MI) + : NativeRawSymbol(Session, SymbolId), Module(MI) {} + +PDB_SymType NativeCompilandSymbol::getSymTag() const { + return PDB_SymType::Compiland; +} + +std::unique_ptr<NativeRawSymbol> NativeCompilandSymbol::clone() const { + return llvm::make_unique<NativeCompilandSymbol>(Session, SymbolId, Module); +} + +bool NativeCompilandSymbol::isEditAndContinueEnabled() const { + return Module.hasECInfo(); +} + +uint32_t NativeCompilandSymbol::getLexicalParentId() const { return 0; } + +// The usage of getObjFileName for getLibraryName and getModuleName for getName +// may seem backwards, but it is consistent with DIA, which is what this API +// was modeled after. We may rename these methods later to try to eliminate +// this potential confusion. + +std::string NativeCompilandSymbol::getLibraryName() const { + return Module.getObjFileName(); +} + +std::string NativeCompilandSymbol::getName() const { + return Module.getModuleName(); +} + +} // namespace pdb +} // namespace llvm diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp new file mode 100644 index 0000000..a65782e --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp @@ -0,0 +1,51 @@ +//==- NativeEnumModules.cpp - Native Symbol 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/Native/NativeEnumModules.h" + +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h" +#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" + +namespace llvm { +namespace pdb { + +NativeEnumModules::NativeEnumModules(NativeSession &PDBSession, + const DbiModuleList &Modules, + uint32_t Index) + : Session(PDBSession), Modules(Modules), Index(Index) {} + +uint32_t NativeEnumModules::getChildCount() const { + return static_cast<uint32_t>(Modules.getModuleCount()); +} + +std::unique_ptr<PDBSymbol> +NativeEnumModules::getChildAtIndex(uint32_t Index) const { + if (Index >= Modules.getModuleCount()) + return nullptr; + return Session.createCompilandSymbol(Modules.getModuleDescriptor(Index)); +} + +std::unique_ptr<PDBSymbol> NativeEnumModules::getNext() { + if (Index >= Modules.getModuleCount()) + return nullptr; + return getChildAtIndex(Index++); +} + +void NativeEnumModules::reset() { Index = 0; } + +NativeEnumModules *NativeEnumModules::clone() const { + return new NativeEnumModules(Session, Modules, Index); +} + +} +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp new file mode 100644 index 0000000..3241000 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp @@ -0,0 +1,84 @@ +//===- NativeExeSymbol.cpp - native impl for PDBSymbolExe -------*- 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/Native/NativeExeSymbol.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/PDB/Native/DbiStream.h" +#include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" + +namespace llvm { +namespace pdb { + +NativeExeSymbol::NativeExeSymbol(NativeSession &Session, SymIndexId SymbolId) + : NativeRawSymbol(Session, SymbolId), File(Session.getPDBFile()) {} + +std::unique_ptr<NativeRawSymbol> NativeExeSymbol::clone() const { + return llvm::make_unique<NativeExeSymbol>(Session, SymbolId); +} + +std::unique_ptr<IPDBEnumSymbols> +NativeExeSymbol::findChildren(PDB_SymType Type) const { + switch (Type) { + case PDB_SymType::Compiland: { + auto Dbi = File.getPDBDbiStream(); + if (Dbi) { + const DbiModuleList &Modules = Dbi->modules(); + return std::unique_ptr<IPDBEnumSymbols>( + new NativeEnumModules(Session, Modules)); + } + consumeError(Dbi.takeError()); + break; + } + default: + break; + } + return nullptr; +} + +uint32_t NativeExeSymbol::getAge() const { + auto IS = File.getPDBInfoStream(); + if (IS) + return IS->getAge(); + consumeError(IS.takeError()); + return 0; +} + +std::string NativeExeSymbol::getSymbolsFileName() const { + return File.getFilePath(); +} + +codeview::GUID NativeExeSymbol::getGuid() const { + auto IS = File.getPDBInfoStream(); + if (IS) + return IS->getGuid(); + consumeError(IS.takeError()); + return codeview::GUID{{0}}; +} + +bool NativeExeSymbol::hasCTypes() const { + auto Dbi = File.getPDBDbiStream(); + if (Dbi) + return Dbi->hasCTypes(); + consumeError(Dbi.takeError()); + return false; +} + +bool NativeExeSymbol::hasPrivateSymbols() const { + auto Dbi = File.getPDBDbiStream(); + if (Dbi) + return !Dbi->isStripped(); + consumeError(Dbi.takeError()); + return false; +} + +} // namespace pdb +} // namespace llvm diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp new file mode 100644 index 0000000..df3f418 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp @@ -0,0 +1,694 @@ +//===- NativeRawSymbol.cpp - Native implementation of IPDBRawSymbol -------===// +// +// 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/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" + +using namespace llvm; +using namespace llvm::pdb; + +NativeRawSymbol::NativeRawSymbol(NativeSession &PDBSession, SymIndexId SymbolId) + : Session(PDBSession), SymbolId(SymbolId) {} + +void NativeRawSymbol::dump(raw_ostream &OS, int Indent) const {} + +std::unique_ptr<IPDBEnumSymbols> +NativeRawSymbol::findChildren(PDB_SymType Type) const { + return nullptr; +} + +std::unique_ptr<IPDBEnumSymbols> +NativeRawSymbol::findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) 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::findInlineFramesByRVA(uint32_t RVA) const { + return nullptr; +} + +void NativeRawSymbol::getDataBytes(SmallVector<uint8_t, 32> &bytes) const { + bytes.clear(); +} + +PDB_MemberAccess NativeRawSymbol::getAccess() const { + return PDB_MemberAccess::Private; +} + +uint32_t NativeRawSymbol::getAddressOffset() const { + return 0; +} + +uint32_t NativeRawSymbol::getAddressSection() const { + return 0; +} + +uint32_t NativeRawSymbol::getAge() const { + return 0; +} + +uint32_t NativeRawSymbol::getArrayIndexTypeId() const { + return 0; +} + +void NativeRawSymbol::getBackEndVersion(VersionInfo &Version) const { + Version.Major = 0; + Version.Minor = 0; + Version.Build = 0; + Version.QFE = 0; +} + +uint32_t NativeRawSymbol::getBaseDataOffset() const { + return 0; +} + +uint32_t NativeRawSymbol::getBaseDataSlot() const { + return 0; +} + +uint32_t NativeRawSymbol::getBaseSymbolId() const { + return 0; +} + +PDB_BuiltinType NativeRawSymbol::getBuiltinType() const { + return PDB_BuiltinType::None; +} + +uint32_t NativeRawSymbol::getBitPosition() const { + return 0; +} + +PDB_CallingConv NativeRawSymbol::getCallingConvention() const { + return PDB_CallingConv::FarStdCall; +} + +uint32_t NativeRawSymbol::getClassParentId() const { + return 0; +} + +std::string NativeRawSymbol::getCompilerName() const { + return {}; +} + +uint32_t NativeRawSymbol::getCount() const { + return 0; +} + +uint32_t NativeRawSymbol::getCountLiveRanges() const { + return 0; +} + +void NativeRawSymbol::getFrontEndVersion(VersionInfo &Version) const { + Version.Major = 0; + Version.Minor = 0; + Version.Build = 0; + Version.QFE = 0; +} + +PDB_Lang NativeRawSymbol::getLanguage() const { + return PDB_Lang::Cobol; +} + +uint32_t NativeRawSymbol::getLexicalParentId() const { + return 0; +} + +std::string NativeRawSymbol::getLibraryName() const { + return {}; +} + +uint32_t NativeRawSymbol::getLiveRangeStartAddressOffset() const { + return 0; +} + +uint32_t NativeRawSymbol::getLiveRangeStartAddressSection() const { + return 0; +} + +uint32_t NativeRawSymbol::getLiveRangeStartRelativeVirtualAddress() const { + return 0; +} + +codeview::RegisterId NativeRawSymbol::getLocalBasePointerRegisterId() const { + return codeview::RegisterId::EAX; +} + +uint32_t NativeRawSymbol::getLowerBoundId() const { + return 0; +} + +uint32_t NativeRawSymbol::getMemorySpaceKind() const { + return 0; +} + +std::string NativeRawSymbol::getName() const { + return {}; +} + +uint32_t NativeRawSymbol::getNumberOfAcceleratorPointerTags() const { + return 0; +} + +uint32_t NativeRawSymbol::getNumberOfColumns() const { + return 0; +} + +uint32_t NativeRawSymbol::getNumberOfModifiers() const { + return 0; +} + +uint32_t NativeRawSymbol::getNumberOfRegisterIndices() const { + return 0; +} + +uint32_t NativeRawSymbol::getNumberOfRows() const { + return 0; +} + +std::string NativeRawSymbol::getObjectFileName() const { + return {}; +} + +uint32_t NativeRawSymbol::getOemId() const { + return 0; +} + +uint32_t NativeRawSymbol::getOemSymbolId() const { + return 0; +} + +uint32_t NativeRawSymbol::getOffsetInUdt() const { + return 0; +} + +PDB_Cpu NativeRawSymbol::getPlatform() const { + return PDB_Cpu::Intel8080; +} + +uint32_t NativeRawSymbol::getRank() const { + return 0; +} + +codeview::RegisterId NativeRawSymbol::getRegisterId() const { + return codeview::RegisterId::EAX; +} + +uint32_t NativeRawSymbol::getRegisterType() const { + return 0; +} + +uint32_t NativeRawSymbol::getRelativeVirtualAddress() const { + return 0; +} + +uint32_t NativeRawSymbol::getSamplerSlot() const { + return 0; +} + +uint32_t NativeRawSymbol::getSignature() const { + return 0; +} + +uint32_t NativeRawSymbol::getSizeInUdt() const { + return 0; +} + +uint32_t NativeRawSymbol::getSlot() const { + return 0; +} + +std::string NativeRawSymbol::getSourceFileName() const { + return {}; +} + +uint32_t NativeRawSymbol::getStride() const { + return 0; +} + +uint32_t NativeRawSymbol::getSubTypeId() const { + return 0; +} + +std::string NativeRawSymbol::getSymbolsFileName() const { return {}; } + +uint32_t NativeRawSymbol::getSymIndexId() const { return SymbolId; } + +uint32_t NativeRawSymbol::getTargetOffset() const { + return 0; +} + +uint32_t NativeRawSymbol::getTargetRelativeVirtualAddress() const { + return 0; +} + +uint64_t NativeRawSymbol::getTargetVirtualAddress() const { + return 0; +} + +uint32_t NativeRawSymbol::getTargetSection() const { + return 0; +} + +uint32_t NativeRawSymbol::getTextureSlot() const { + return 0; +} + +uint32_t NativeRawSymbol::getTimeStamp() const { + return 0; +} + +uint32_t NativeRawSymbol::getToken() const { + return 0; +} + +uint32_t NativeRawSymbol::getTypeId() const { + return 0; +} + +uint32_t NativeRawSymbol::getUavSlot() const { + return 0; +} + +std::string NativeRawSymbol::getUndecoratedName() const { + return {}; +} + +uint32_t NativeRawSymbol::getUnmodifiedTypeId() const { + return 0; +} + +uint32_t NativeRawSymbol::getUpperBoundId() const { + return 0; +} + +Variant NativeRawSymbol::getValue() const { + return Variant(); +} + +uint32_t NativeRawSymbol::getVirtualBaseDispIndex() const { + return 0; +} + +uint32_t NativeRawSymbol::getVirtualBaseOffset() const { + return 0; +} + +uint32_t NativeRawSymbol::getVirtualTableShapeId() const { + return 0; +} + +std::unique_ptr<PDBSymbolTypeBuiltin> +NativeRawSymbol::getVirtualBaseTableType() const { + return nullptr; +} + +PDB_DataKind NativeRawSymbol::getDataKind() const { + return PDB_DataKind::Unknown; +} + +PDB_SymType NativeRawSymbol::getSymTag() const { + return PDB_SymType::None; +} + +codeview::GUID NativeRawSymbol::getGuid() const { return codeview::GUID{{0}}; } + +int32_t NativeRawSymbol::getOffset() const { + return 0; +} + +int32_t NativeRawSymbol::getThisAdjust() const { + return 0; +} + +int32_t NativeRawSymbol::getVirtualBasePointerOffset() const { + return 0; +} + +PDB_LocType NativeRawSymbol::getLocationType() const { + return PDB_LocType::Null; +} + +PDB_Machine NativeRawSymbol::getMachineType() const { + return PDB_Machine::Invalid; +} + +codeview::ThunkOrdinal NativeRawSymbol::getThunkOrdinal() const { + return codeview::ThunkOrdinal::Standard; +} + +uint64_t NativeRawSymbol::getLength() const { + return 0; +} + +uint64_t NativeRawSymbol::getLiveRangeLength() const { + return 0; +} + +uint64_t NativeRawSymbol::getVirtualAddress() const { + return 0; +} + +PDB_UdtType NativeRawSymbol::getUdtKind() const { + return PDB_UdtType::Struct; +} + +bool NativeRawSymbol::hasConstructor() const { + return false; +} + +bool NativeRawSymbol::hasCustomCallingConvention() const { + return false; +} + +bool NativeRawSymbol::hasFarReturn() const { + return false; +} + +bool NativeRawSymbol::isCode() const { + return false; +} + +bool NativeRawSymbol::isCompilerGenerated() const { + return false; +} + +bool NativeRawSymbol::isConstType() const { + return false; +} + +bool NativeRawSymbol::isEditAndContinueEnabled() const { + return false; +} + +bool NativeRawSymbol::isFunction() const { + return false; +} + +bool NativeRawSymbol::getAddressTaken() const { + return false; +} + +bool NativeRawSymbol::getNoStackOrdering() const { + return false; +} + +bool NativeRawSymbol::hasAlloca() const { + return false; +} + +bool NativeRawSymbol::hasAssignmentOperator() const { + return false; +} + +bool NativeRawSymbol::hasCTypes() const { + return false; +} + +bool NativeRawSymbol::hasCastOperator() const { + return false; +} + +bool NativeRawSymbol::hasDebugInfo() const { + return false; +} + +bool NativeRawSymbol::hasEH() const { + return false; +} + +bool NativeRawSymbol::hasEHa() const { + return false; +} + +bool NativeRawSymbol::hasInlAsm() const { + return false; +} + +bool NativeRawSymbol::hasInlineAttribute() const { + return false; +} + +bool NativeRawSymbol::hasInterruptReturn() const { + return false; +} + +bool NativeRawSymbol::hasFramePointer() const { + return false; +} + +bool NativeRawSymbol::hasLongJump() const { + return false; +} + +bool NativeRawSymbol::hasManagedCode() const { + return false; +} + +bool NativeRawSymbol::hasNestedTypes() const { + return false; +} + +bool NativeRawSymbol::hasNoInlineAttribute() const { + return false; +} + +bool NativeRawSymbol::hasNoReturnAttribute() const { + return false; +} + +bool NativeRawSymbol::hasOptimizedCodeDebugInfo() const { + return false; +} + +bool NativeRawSymbol::hasOverloadedOperator() const { + return false; +} + +bool NativeRawSymbol::hasSEH() const { + return false; +} + +bool NativeRawSymbol::hasSecurityChecks() const { + return false; +} + +bool NativeRawSymbol::hasSetJump() const { + return false; +} + +bool NativeRawSymbol::hasStrictGSCheck() const { + return false; +} + +bool NativeRawSymbol::isAcceleratorGroupSharedLocal() const { + return false; +} + +bool NativeRawSymbol::isAcceleratorPointerTagLiveRange() const { + return false; +} + +bool NativeRawSymbol::isAcceleratorStubFunction() const { + return false; +} + +bool NativeRawSymbol::isAggregated() const { + return false; +} + +bool NativeRawSymbol::isIntroVirtualFunction() const { + return false; +} + +bool NativeRawSymbol::isCVTCIL() const { + return false; +} + +bool NativeRawSymbol::isConstructorVirtualBase() const { + return false; +} + +bool NativeRawSymbol::isCxxReturnUdt() const { + return false; +} + +bool NativeRawSymbol::isDataAligned() const { + return false; +} + +bool NativeRawSymbol::isHLSLData() const { + return false; +} + +bool NativeRawSymbol::isHotpatchable() const { + return false; +} + +bool NativeRawSymbol::isIndirectVirtualBaseClass() const { + return false; +} + +bool NativeRawSymbol::isInterfaceUdt() const { + return false; +} + +bool NativeRawSymbol::isIntrinsic() const { + return false; +} + +bool NativeRawSymbol::isLTCG() const { + return false; +} + +bool NativeRawSymbol::isLocationControlFlowDependent() const { + return false; +} + +bool NativeRawSymbol::isMSILNetmodule() const { + return false; +} + +bool NativeRawSymbol::isMatrixRowMajor() const { + return false; +} + +bool NativeRawSymbol::isManagedCode() const { + return false; +} + +bool NativeRawSymbol::isMSILCode() const { + return false; +} + +bool NativeRawSymbol::isMultipleInheritance() const { + return false; +} + +bool NativeRawSymbol::isNaked() const { + return false; +} + +bool NativeRawSymbol::isNested() const { + return false; +} + +bool NativeRawSymbol::isOptimizedAway() const { + return false; +} + +bool NativeRawSymbol::isPacked() const { + return false; +} + +bool NativeRawSymbol::isPointerBasedOnSymbolValue() const { + return false; +} + +bool NativeRawSymbol::isPointerToDataMember() const { + return false; +} + +bool NativeRawSymbol::isPointerToMemberFunction() const { + return false; +} + +bool NativeRawSymbol::isPureVirtual() const { + return false; +} + +bool NativeRawSymbol::isRValueReference() const { + return false; +} + +bool NativeRawSymbol::isRefUdt() const { + return false; +} + +bool NativeRawSymbol::isReference() const { + return false; +} + +bool NativeRawSymbol::isRestrictedType() const { + return false; +} + +bool NativeRawSymbol::isReturnValue() const { + return false; +} + +bool NativeRawSymbol::isSafeBuffers() const { + return false; +} + +bool NativeRawSymbol::isScoped() const { + return false; +} + +bool NativeRawSymbol::isSdl() const { + return false; +} + +bool NativeRawSymbol::isSingleInheritance() const { + return false; +} + +bool NativeRawSymbol::isSplitted() const { + return false; +} + +bool NativeRawSymbol::isStatic() const { + return false; +} + +bool NativeRawSymbol::hasPrivateSymbols() const { + return false; +} + +bool NativeRawSymbol::isUnalignedType() const { + return false; +} + +bool NativeRawSymbol::isUnreached() const { + return false; +} + +bool NativeRawSymbol::isValueUdt() const { + return false; +} + +bool NativeRawSymbol::isVirtual() const { + return false; +} + +bool NativeRawSymbol::isVirtualBaseClass() const { + return false; +} + +bool NativeRawSymbol::isVirtualInheritance() const { + return false; +} + +bool NativeRawSymbol::isVolatileType() const { + return false; +} + +bool NativeRawSymbol::wasInlined() const { + return false; +} + +std::string NativeRawSymbol::getUnused() const { + return {}; +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp new file mode 100644 index 0000000..76de0d8 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -0,0 +1,218 @@ +//===- NativeSession.cpp - Native implementation of IPDBSession -*- 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/Native/NativeSession.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/PDB/GenericError.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBSourceFile.h" +#include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" +#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/BinaryByteStream.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/MemoryBuffer.h" + +#include <algorithm> +#include <memory> +#include <utility> + +using namespace llvm; +using namespace llvm::msf; +using namespace llvm::pdb; + +namespace { +// Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary +// to instantiate a NativeBuiltinSymbol for that type. +static const struct BuiltinTypeEntry { + codeview::SimpleTypeKind Kind; + PDB_BuiltinType Type; + uint32_t Size; +} BuiltinTypes[] = { + {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4}, + {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4}, + {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4}, + {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8}, + {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1}, + {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1}, + {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1}, + {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2}, + {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1} + // This table can be grown as necessary, but these are the only types we've + // needed so far. +}; +} // namespace + +NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile, + std::unique_ptr<BumpPtrAllocator> Allocator) + : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)) {} + +NativeSession::~NativeSession() = default; + +Error NativeSession::createFromPdb(StringRef Path, + std::unique_ptr<IPDBSession> &Session) { + ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer = + MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1, + /*RequiresNullTerminator=*/false); + if (!ErrorOrBuffer) + return make_error<GenericError>(generic_error_code::invalid_path); + + std::unique_ptr<MemoryBuffer> Buffer = std::move(*ErrorOrBuffer); + auto Stream = llvm::make_unique<MemoryBufferByteStream>( + std::move(Buffer), llvm::support::little); + + auto Allocator = llvm::make_unique<BumpPtrAllocator>(); + auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), *Allocator); + if (auto EC = File->parseFileHeaders()) + return EC; + if (auto EC = File->parseStreamData()) + return EC; + + Session = + llvm::make_unique<NativeSession>(std::move(File), std::move(Allocator)); + + return Error::success(); +} + +Error NativeSession::createFromExe(StringRef Path, + std::unique_ptr<IPDBSession> &Session) { + return make_error<RawError>(raw_error_code::feature_unsupported); +} + +std::unique_ptr<PDBSymbolCompiland> +NativeSession::createCompilandSymbol(DbiModuleDescriptor MI) { + const auto Id = static_cast<SymIndexId>(SymbolCache.size()); + SymbolCache.push_back( + llvm::make_unique<NativeCompilandSymbol>(*this, Id, MI)); + return llvm::make_unique<PDBSymbolCompiland>( + *this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone())); +} + +SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) { + // First see if it's already in our cache. + const auto Entry = TypeIndexToSymbolId.find(Index); + if (Entry != TypeIndexToSymbolId.end()) + return Entry->second; + + // Symbols for built-in types are created on the fly. + if (Index.isSimple()) { + // FIXME: We will eventually need to handle pointers to other simple types, + // which are still simple types in the world of CodeView TypeIndexes. + if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct) + return 0; + const auto Kind = Index.getSimpleKind(); + const auto It = + std::find_if(std::begin(BuiltinTypes), std::end(BuiltinTypes), + [Kind](const BuiltinTypeEntry &Builtin) { + return Builtin.Kind == Kind; + }); + if (It == std::end(BuiltinTypes)) + return 0; + SymIndexId Id = SymbolCache.size(); + SymbolCache.emplace_back( + llvm::make_unique<NativeBuiltinSymbol>(*this, Id, It->Type, It->Size)); + TypeIndexToSymbolId[Index] = Id; + return Id; + } + + // TODO: Look up PDB type by type index + + return 0; +} + +uint64_t NativeSession::getLoadAddress() const { return 0; } + +void NativeSession::setLoadAddress(uint64_t Address) {} + +std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() { + const auto Id = static_cast<SymIndexId>(SymbolCache.size()); + SymbolCache.push_back(llvm::make_unique<NativeExeSymbol>(*this, Id)); + auto RawSymbol = SymbolCache[Id]->clone(); + auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol))); + std::unique_ptr<PDBSymbolExe> ExeSymbol( + static_cast<PDBSymbolExe *>(PdbSymbol.release())); + return ExeSymbol; +} + +std::unique_ptr<PDBSymbol> +NativeSession::getSymbolById(uint32_t SymbolId) const { + // If the caller has a SymbolId, it'd better be in our SymbolCache. + return SymbolId < SymbolCache.size() + ? PDBSymbol::create(*this, SymbolCache[SymbolId]->clone()) + : nullptr; +} + +std::unique_ptr<PDBSymbol> +NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const { + return nullptr; +} + +std::unique_ptr<IPDBEnumLineNumbers> +NativeSession::findLineNumbers(const PDBSymbolCompiland &Compiland, + const IPDBSourceFile &File) const { + return nullptr; +} + +std::unique_ptr<IPDBEnumLineNumbers> +NativeSession::findLineNumbersByAddress(uint64_t Address, + uint32_t Length) const { + return nullptr; +} + +std::unique_ptr<IPDBEnumSourceFiles> +NativeSession::findSourceFiles(const PDBSymbolCompiland *Compiland, + StringRef Pattern, + PDB_NameSearchFlags Flags) const { + return nullptr; +} + +std::unique_ptr<IPDBSourceFile> +NativeSession::findOneSourceFile(const PDBSymbolCompiland *Compiland, + StringRef Pattern, + PDB_NameSearchFlags Flags) const { + return nullptr; +} + +std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>> +NativeSession::findCompilandsForSourceFile(StringRef Pattern, + PDB_NameSearchFlags Flags) const { + return nullptr; +} + +std::unique_ptr<PDBSymbolCompiland> +NativeSession::findOneCompilandForSourceFile(StringRef Pattern, + PDB_NameSearchFlags Flags) const { + return nullptr; +} + +std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getAllSourceFiles() const { + return nullptr; +} + +std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getSourceFilesForCompiland( + const PDBSymbolCompiland &Compiland) const { + return nullptr; +} + +std::unique_ptr<IPDBSourceFile> +NativeSession::getSourceFileById(uint32_t FileId) const { + return nullptr; +} + +std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const { + return nullptr; +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp index 5349151..0b6492e 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp @@ -7,24 +7,25 @@ // //===----------------------------------------------------------------------===// +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/MSF/MSFCommon.h" -#include "llvm/DebugInfo/MSF/StreamArray.h" -#include "llvm/DebugInfo/MSF/StreamInterface.h" -#include "llvm/DebugInfo/MSF/StreamReader.h" -#include "llvm/DebugInfo/PDB/Raw/DbiStream.h" -#include "llvm/DebugInfo/PDB/Raw/GlobalsStream.h" -#include "llvm/DebugInfo/PDB/Raw/InfoStream.h" -#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h" -#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" -#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" -#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h" -#include "llvm/DebugInfo/PDB/Raw/TpiStream.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/DbiStream.h" +#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" +#include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" +#include "llvm/DebugInfo/PDB/Native/PublicsStream.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/SymbolStream.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" +#include "llvm/Support/BinaryStream.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" +#include "llvm/Support/Path.h" #include <algorithm> #include <cassert> #include <cstdint> @@ -38,12 +39,18 @@ namespace { typedef FixedStreamArray<support::ulittle32_t> ulittle_array; } // end anonymous namespace -PDBFile::PDBFile(std::unique_ptr<ReadableStream> PdbFileBuffer, +PDBFile::PDBFile(StringRef Path, std::unique_ptr<BinaryStream> PdbFileBuffer, BumpPtrAllocator &Allocator) - : Allocator(Allocator), Buffer(std::move(PdbFileBuffer)) {} + : FilePath(Path), Allocator(Allocator), Buffer(std::move(PdbFileBuffer)) {} PDBFile::~PDBFile() = default; +StringRef PDBFile::getFilePath() const { return FilePath; } + +StringRef PDBFile::getFileDirectory() const { + return sys::path::parent_path(FilePath); +} + uint32_t PDBFile::getBlockSize() const { return ContainerLayout.SB->BlockSize; } uint32_t PDBFile::getFreeBlockMapBlock() const { @@ -106,7 +113,7 @@ Error PDBFile::setBlockData(uint32_t BlockIndex, uint32_t Offset, } Error PDBFile::parseFileHeaders() { - StreamReader Reader(*Buffer); + BinaryStreamReader Reader(*Buffer); // Initialize SB. const msf::SuperBlock *SB = nullptr; @@ -139,8 +146,9 @@ Error PDBFile::parseFileHeaders() { // at getBlockSize() intervals, so we have to be compatible. // See the function fpmPn() for more information: // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/msf/msf.cpp#L489 - auto FpmStream = MappedBlockStream::createFpmStream(ContainerLayout, *Buffer); - StreamReader FpmReader(*FpmStream); + auto FpmStream = + MappedBlockStream::createFpmStream(ContainerLayout, *Buffer, Allocator); + BinaryStreamReader FpmReader(*FpmStream); ArrayRef<uint8_t> FpmBytes; if (auto EC = FpmReader.readBytes(FpmBytes, msf::getFullFpmByteSize(ContainerLayout))) @@ -177,8 +185,9 @@ Error PDBFile::parseStreamData() { // is exactly what we are attempting to parse. By specifying a custom // subclass of IPDBStreamData which only accesses the fields that have already // been parsed, we can avoid this and reuse MappedBlockStream. - auto DS = MappedBlockStream::createDirectoryStream(ContainerLayout, *Buffer); - StreamReader Reader(*DS); + auto DS = MappedBlockStream::createDirectoryStream(ContainerLayout, *Buffer, + Allocator); + BinaryStreamReader Reader(*DS); if (auto EC = Reader.readInteger(NumStreams)) return EC; @@ -221,6 +230,14 @@ ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const { return ContainerLayout.DirectoryBlocks; } +MSFStreamLayout PDBFile::getStreamLayout(uint32_t StreamIdx) const { + MSFStreamLayout Result; + auto Blocks = getStreamBlockList(StreamIdx); + Result.Blocks.assign(Blocks.begin(), Blocks.end()); + Result.Length = getStreamByteSize(StreamIdx); + return Result; +} + Expected<GlobalsStream &> PDBFile::getPDBGlobalsStream() { if (!Globals) { auto DbiS = getPDBDbiStream(); @@ -229,7 +246,8 @@ Expected<GlobalsStream &> PDBFile::getPDBGlobalsStream() { auto GlobalS = safelyCreateIndexedStream( ContainerLayout, *Buffer, DbiS->getGlobalSymbolStreamIndex()); - if (!GlobalS) return GlobalS.takeError(); + if (!GlobalS) + return GlobalS.takeError(); auto TempGlobals = llvm::make_unique<GlobalsStream>(std::move(*GlobalS)); if (auto EC = TempGlobals->reload()) return std::move(EC); @@ -241,7 +259,8 @@ Expected<GlobalsStream &> PDBFile::getPDBGlobalsStream() { Expected<InfoStream &> PDBFile::getPDBInfoStream() { if (!Info) { auto InfoS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamPDB); - if (!InfoS) return InfoS.takeError(); + if (!InfoS) + return InfoS.takeError(); auto TempInfo = llvm::make_unique<InfoStream>(std::move(*InfoS)); if (auto EC = TempInfo->reload()) return std::move(EC); @@ -253,7 +272,8 @@ Expected<InfoStream &> PDBFile::getPDBInfoStream() { Expected<DbiStream &> PDBFile::getPDBDbiStream() { if (!Dbi) { auto DbiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamDBI); - if (!DbiS) return DbiS.takeError(); + if (!DbiS) + return DbiS.takeError(); auto TempDbi = llvm::make_unique<DbiStream>(*this, std::move(*DbiS)); if (auto EC = TempDbi->reload()) return std::move(EC); @@ -265,7 +285,8 @@ Expected<DbiStream &> PDBFile::getPDBDbiStream() { Expected<TpiStream &> PDBFile::getPDBTpiStream() { if (!Tpi) { auto TpiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamTPI); - if (!TpiS) return TpiS.takeError(); + if (!TpiS) + return TpiS.takeError(); auto TempTpi = llvm::make_unique<TpiStream>(*this, std::move(*TpiS)); if (auto EC = TempTpi->reload()) return std::move(EC); @@ -277,7 +298,8 @@ Expected<TpiStream &> PDBFile::getPDBTpiStream() { Expected<TpiStream &> PDBFile::getPDBIpiStream() { if (!Ipi) { auto IpiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamIPI); - if (!IpiS) return IpiS.takeError(); + if (!IpiS) + return IpiS.takeError(); auto TempIpi = llvm::make_unique<TpiStream>(*this, std::move(*IpiS)); if (auto EC = TempIpi->reload()) return std::move(EC); @@ -294,7 +316,8 @@ Expected<PublicsStream &> PDBFile::getPDBPublicsStream() { auto PublicS = safelyCreateIndexedStream( ContainerLayout, *Buffer, DbiS->getPublicSymbolStreamIndex()); - if (!PublicS) return PublicS.takeError(); + if (!PublicS) + return PublicS.takeError(); auto TempPublics = llvm::make_unique<PublicsStream>(*this, std::move(*PublicS)); if (auto EC = TempPublics->reload()) @@ -313,7 +336,8 @@ Expected<SymbolStream &> PDBFile::getPDBSymbolStream() { uint32_t SymbolStreamNum = DbiS->getSymRecordStreamIndex(); auto SymbolS = safelyCreateIndexedStream(ContainerLayout, *Buffer, SymbolStreamNum); - if (!SymbolS) return SymbolS.takeError(); + if (!SymbolS) + return SymbolS.takeError(); auto TempSymbols = llvm::make_unique<SymbolStream>(std::move(*SymbolS)); if (auto EC = TempSymbols->reload()) @@ -323,8 +347,8 @@ Expected<SymbolStream &> PDBFile::getPDBSymbolStream() { return *Symbols; } -Expected<NameHashTable &> PDBFile::getStringTable() { - if (!StringTable || !StringTableStream) { +Expected<PDBStringTable &> PDBFile::getStringTable() { + if (!Strings) { auto IS = getPDBInfoStream(); if (!IS) return IS.takeError(); @@ -333,23 +357,39 @@ Expected<NameHashTable &> PDBFile::getStringTable() { auto NS = safelyCreateIndexedStream(ContainerLayout, *Buffer, NameStreamIndex); - if (!NS) return NS.takeError(); + if (!NS) + return NS.takeError(); - StreamReader Reader(**NS); - auto N = llvm::make_unique<NameHashTable>(); - if (auto EC = N->load(Reader)) + auto N = llvm::make_unique<PDBStringTable>(); + BinaryStreamReader Reader(**NS); + if (auto EC = N->reload(Reader)) return std::move(EC); - StringTable = std::move(N); + assert(Reader.bytesRemaining() == 0); StringTableStream = std::move(*NS); + Strings = std::move(N); } - return *StringTable; + return *Strings; +} + +uint32_t PDBFile::getPointerSize() { + auto DbiS = getPDBDbiStream(); + if (!DbiS) + return 0; + PDB_Machine Machine = DbiS->getMachineType(); + if (Machine == PDB_Machine::Amd64) + return 8; + return 4; } bool PDBFile::hasPDBDbiStream() const { return StreamDBI < getNumStreams(); } bool PDBFile::hasPDBGlobalsStream() { auto DbiS = getPDBDbiStream(); - if (!DbiS) return false; + if (!DbiS) { + consumeError(DbiS.takeError()); + return false; + } + return DbiS->getGlobalSymbolStreamIndex() < getNumStreams(); } @@ -359,33 +399,39 @@ bool PDBFile::hasPDBIpiStream() const { return StreamIPI < getNumStreams(); } bool PDBFile::hasPDBPublicsStream() { auto DbiS = getPDBDbiStream(); - if (!DbiS) return false; + if (!DbiS) { + consumeError(DbiS.takeError()); + return false; + } return DbiS->getPublicSymbolStreamIndex() < getNumStreams(); } bool PDBFile::hasPDBSymbolStream() { auto DbiS = getPDBDbiStream(); - if (!DbiS) return false; + if (!DbiS) + return false; return DbiS->getSymRecordStreamIndex() < getNumStreams(); } bool PDBFile::hasPDBTpiStream() const { return StreamTPI < getNumStreams(); } -bool PDBFile::hasStringTable() { +bool PDBFile::hasPDBStringTable() { auto IS = getPDBInfoStream(); - if (!IS) return false; + if (!IS) + return false; return IS->getNamedStreamIndex("/names") < getNumStreams(); } -/// Wrapper around MappedBlockStream::createIndexedStream() -/// that checks if a stream with that index actually exists. -/// If it does not, the return value will have an MSFError with -/// code msf_error_code::no_stream. Else, the return value will -/// contain the stream returned by createIndexedStream(). -Expected<std::unique_ptr<MappedBlockStream>> PDBFile::safelyCreateIndexedStream( - const MSFLayout &Layout, const ReadableStream &MsfData, - uint32_t StreamIndex) const { +/// Wrapper around MappedBlockStream::createIndexedStream() that checks if a +/// stream with that index actually exists. If it does not, the return value +/// will have an MSFError with code msf_error_code::no_stream. Else, the return +/// value will contain the stream returned by createIndexedStream(). +Expected<std::unique_ptr<MappedBlockStream>> +PDBFile::safelyCreateIndexedStream(const MSFLayout &Layout, + BinaryStreamRef MsfData, + uint32_t StreamIndex) const { if (StreamIndex >= getNumStreams()) return make_error<RawError>(raw_error_code::no_stream); - return MappedBlockStream::createIndexedStream(Layout, MsfData, StreamIndex); + return MappedBlockStream::createIndexedStream(Layout, MsfData, StreamIndex, + Allocator); } diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp new file mode 100644 index 0000000..9f35fd7 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp @@ -0,0 +1,221 @@ +//===- PDBFileBuilder.cpp - PDB File Creation -------------------*- 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/Native/PDBFileBuilder.h" + +#include "llvm/ADT/BitVector.h" + +#include "llvm/DebugInfo/MSF/MSFBuilder.h" +#include "llvm/DebugInfo/PDB/GenericError.h" +#include "llvm/DebugInfo/PDB/Native/DbiStream.h" +#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" +#include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" +#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" +#include "llvm/DebugInfo/PDB/Native/PublicsStreamBuilder.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" +#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h" +#include "llvm/Support/BinaryStream.h" +#include "llvm/Support/BinaryStreamWriter.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::msf; +using namespace llvm::pdb; +using namespace llvm::support; + +PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator) + : Allocator(Allocator) {} + +PDBFileBuilder::~PDBFileBuilder() {} + +Error PDBFileBuilder::initialize(uint32_t BlockSize) { + auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize); + if (!ExpectedMsf) + return ExpectedMsf.takeError(); + Msf = llvm::make_unique<MSFBuilder>(std::move(*ExpectedMsf)); + return Error::success(); +} + +MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; } + +InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() { + if (!Info) + Info = llvm::make_unique<InfoStreamBuilder>(*Msf, NamedStreams); + return *Info; +} + +DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() { + if (!Dbi) + Dbi = llvm::make_unique<DbiStreamBuilder>(*Msf); + return *Dbi; +} + +TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() { + if (!Tpi) + Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI); + return *Tpi; +} + +TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() { + if (!Ipi) + Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI); + return *Ipi; +} + +PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() { + return Strings; +} + +PublicsStreamBuilder &PDBFileBuilder::getPublicsBuilder() { + if (!Publics) + Publics = llvm::make_unique<PublicsStreamBuilder>(*Msf); + return *Publics; +} + +Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) { + auto ExpectedStream = Msf->addStream(Size); + if (!ExpectedStream) + return ExpectedStream.takeError(); + NamedStreams.set(Name, *ExpectedStream); + return Error::success(); +} + +Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() { + + if (Ipi && Ipi->getRecordCount() > 0) { + // In theory newer PDBs always have an ID stream, but by saying that we're + // only going to *really* have an ID stream if there is at least one ID + // record, we leave open the opportunity to test older PDBs such as those + // that don't have an ID stream. + auto &Info = getInfoBuilder(); + Info.addFeature(PdbRaw_FeatureSig::VC140); + } + + 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); + + if (Info) { + if (auto EC = Info->finalizeMsfLayout()) + return std::move(EC); + } + if (Dbi) { + if (auto EC = Dbi->finalizeMsfLayout()) + return std::move(EC); + } + if (Tpi) { + if (auto EC = Tpi->finalizeMsfLayout()) + return std::move(EC); + } + if (Ipi) { + if (auto EC = Ipi->finalizeMsfLayout()) + return std::move(EC); + } + if (Publics) { + if (auto EC = Publics->finalizeMsfLayout()) + return std::move(EC); + if (Dbi) { + Dbi->setPublicsStreamIndex(Publics->getStreamIndex()); + Dbi->setSymbolRecordStreamIndex(Publics->getRecordStreamIdx()); + } + } + + return Msf->build(); +} + +Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const { + uint32_t SN = 0; + if (!NamedStreams.get(Name, SN)) + return llvm::make_error<pdb::RawError>(raw_error_code::no_stream); + return SN; +} + +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 (OutFileOrError.getError()) + return llvm::make_error<pdb::GenericError>(generic_error_code::invalid_path, + Filename); + FileBufferByteStream Buffer(std::move(*OutFileOrError), + llvm::support::little); + BinaryStreamWriter Writer(Buffer); + + if (auto EC = Writer.writeObject(*Layout.SB)) + return EC; + uint32_t BlockMapOffset = + msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize); + Writer.setOffset(BlockMapOffset); + if (auto EC = Writer.writeArray(Layout.DirectoryBlocks)) + return EC; + + auto DirStream = WritableMappedBlockStream::createDirectoryStream( + Layout, Buffer, Allocator); + BinaryStreamWriter DW(*DirStream); + if (auto EC = DW.writeInteger<uint32_t>(Layout.StreamSizes.size())) + return EC; + + if (auto EC = DW.writeArray(Layout.StreamSizes)) + return EC; + + for (const auto &Blocks : Layout.StreamMap) { + if (auto EC = DW.writeArray(Blocks)) + return EC; + } + + auto ExpectedSN = getNamedStreamIndex("/names"); + if (!ExpectedSN) + return ExpectedSN.takeError(); + + auto NS = WritableMappedBlockStream::createIndexedStream( + Layout, Buffer, *ExpectedSN, Allocator); + BinaryStreamWriter NSWriter(*NS); + if (auto EC = Strings.commit(NSWriter)) + return EC; + + if (Info) { + if (auto EC = Info->commit(Layout, Buffer)) + return EC; + } + + if (Dbi) { + if (auto EC = Dbi->commit(Layout, Buffer)) + return EC; + } + + if (Tpi) { + if (auto EC = Tpi->commit(Layout, Buffer)) + return EC; + } + + if (Ipi) { + if (auto EC = Ipi->commit(Layout, Buffer)) + return EC; + } + + if (Publics) { + auto PS = WritableMappedBlockStream::createIndexedStream( + Layout, Buffer, Publics->getStreamIndex(), Allocator); + BinaryStreamWriter PSWriter(*PS); + if (auto EC = Publics->commit(PSWriter)) + return EC; + } + + return Buffer.commit(); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp new file mode 100644 index 0000000..acd45f7 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp @@ -0,0 +1,139 @@ +//===- PDBStringTable.cpp - PDB String Table ---------------------*- 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/Native/PDBStringTable.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/Hash.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::support; +using namespace llvm::pdb; + +uint32_t PDBStringTable::getByteSize() const { return Header->ByteSize; } +uint32_t PDBStringTable::getNameCount() const { return NameCount; } +uint32_t PDBStringTable::getHashVersion() const { return Header->HashVersion; } +uint32_t PDBStringTable::getSignature() const { return Header->Signature; } + +Error PDBStringTable::readHeader(BinaryStreamReader &Reader) { + if (auto EC = Reader.readObject(Header)) + return EC; + + if (Header->Signature != PDBStringTableSignature) + return make_error<RawError>(raw_error_code::corrupt_file, + "Invalid hash table signature"); + if (Header->HashVersion != 1 && Header->HashVersion != 2) + return make_error<RawError>(raw_error_code::corrupt_file, + "Unsupported hash version"); + + assert(Reader.bytesRemaining() == 0); + return Error::success(); +} + +Error PDBStringTable::readStrings(BinaryStreamReader &Reader) { + BinaryStreamRef Stream; + if (auto EC = Reader.readStreamRef(Stream)) + return EC; + + if (auto EC = Strings.initialize(Stream)) { + return joinErrors(std::move(EC), + make_error<RawError>(raw_error_code::corrupt_file, + "Invalid hash table byte length")); + } + + assert(Reader.bytesRemaining() == 0); + return Error::success(); +} + +const codeview::DebugStringTableSubsectionRef & +PDBStringTable::getStringTable() const { + return Strings; +} + +Error PDBStringTable::readHashTable(BinaryStreamReader &Reader) { + const support::ulittle32_t *HashCount; + if (auto EC = Reader.readObject(HashCount)) + return EC; + + if (auto EC = Reader.readArray(IDs, *HashCount)) { + return joinErrors(std::move(EC), + make_error<RawError>(raw_error_code::corrupt_file, + "Could not read bucket array")); + } + + return Error::success(); +} + +Error PDBStringTable::readEpilogue(BinaryStreamReader &Reader) { + if (auto EC = Reader.readInteger(NameCount)) + return EC; + + assert(Reader.bytesRemaining() == 0); + return Error::success(); +} + +Error PDBStringTable::reload(BinaryStreamReader &Reader) { + + BinaryStreamReader SectionReader; + + std::tie(SectionReader, Reader) = Reader.split(sizeof(PDBStringTableHeader)); + if (auto EC = readHeader(SectionReader)) + return EC; + + std::tie(SectionReader, Reader) = Reader.split(Header->ByteSize); + if (auto EC = readStrings(SectionReader)) + return EC; + + // We don't know how long the hash table is until we parse it, so let the + // function responsible for doing that figure it out. + if (auto EC = readHashTable(Reader)) + return EC; + + std::tie(SectionReader, Reader) = Reader.split(sizeof(uint32_t)); + if (auto EC = readEpilogue(SectionReader)) + return EC; + + assert(Reader.bytesRemaining() == 0); + return Error::success(); +} + +Expected<StringRef> PDBStringTable::getStringForID(uint32_t ID) const { + return Strings.getString(ID); +} + +Expected<uint32_t> PDBStringTable::getIDForString(StringRef Str) const { + uint32_t Hash = + (Header->HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str); + size_t Count = IDs.size(); + uint32_t Start = Hash % Count; + for (size_t I = 0; I < Count; ++I) { + // The hash is just a starting point for the search, but if it + // doesn't work we should find the string no matter what, because + // we iterate the entire array. + uint32_t Index = (Start + I) % Count; + + uint32_t ID = IDs[Index]; + auto ExpectedStr = getStringForID(ID); + if (!ExpectedStr) + return ExpectedStr.takeError(); + + if (*ExpectedStr == Str) + return ID; + } + return make_error<RawError>(raw_error_code::no_entry); +} + +FixedStreamArray<support::ulittle32_t> PDBStringTable::name_ids() const { + return IDs; +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp new file mode 100644 index 0000000..90acfad --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp @@ -0,0 +1,138 @@ +//===- PDBStringTableBuilder.cpp - PDB String Table -------------*- 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/Native/PDBStringTableBuilder.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/Hash.h" +#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::msf; +using namespace llvm::support; +using namespace llvm::support::endian; +using namespace llvm::pdb; + +uint32_t PDBStringTableBuilder::insert(StringRef S) { + return Strings.insert(S); +} + +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; +} + +uint32_t PDBStringTableBuilder::calculateHashTableSize() const { + uint32_t Size = sizeof(uint32_t); // Hash table begins with 4-byte size field. + Size += sizeof(uint32_t) * computeBucketCount(Strings.size()); + + return Size; +} + +uint32_t PDBStringTableBuilder::calculateSerializedSize() const { + uint32_t Size = 0; + Size += sizeof(PDBStringTableHeader); + Size += Strings.calculateSerializedSize(); + Size += calculateHashTableSize(); + Size += sizeof(uint32_t); // The /names stream ends with the string count. + return Size; +} + +void PDBStringTableBuilder::setStrings( + const codeview::DebugStringTableSubsection &Strings) { + this->Strings = Strings; +} + +Error PDBStringTableBuilder::writeHeader(BinaryStreamWriter &Writer) const { + // Write a header + PDBStringTableHeader H; + H.Signature = PDBStringTableSignature; + H.HashVersion = 1; + H.ByteSize = Strings.calculateSerializedSize(); + if (auto EC = Writer.writeObject(H)) + return EC; + assert(Writer.bytesRemaining() == 0); + return Error::success(); +} + +Error PDBStringTableBuilder::writeStrings(BinaryStreamWriter &Writer) const { + if (auto EC = Strings.commit(Writer)) + return EC; + + assert(Writer.bytesRemaining() == 0); + return Error::success(); +} + +Error PDBStringTableBuilder::writeHashTable(BinaryStreamWriter &Writer) const { + // Write a hash table. + uint32_t BucketCount = computeBucketCount(Strings.size()); + if (auto EC = Writer.writeInteger(BucketCount)) + return EC; + std::vector<ulittle32_t> Buckets(BucketCount); + + for (auto &Pair : Strings) { + StringRef S = Pair.getKey(); + uint32_t Offset = Pair.getValue(); + uint32_t Hash = hashStringV1(S); + + 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; + break; + } + } + + if (auto EC = Writer.writeArray(ArrayRef<ulittle32_t>(Buckets))) + return EC; + + assert(Writer.bytesRemaining() == 0); + return Error::success(); +} + +Error PDBStringTableBuilder::writeEpilogue(BinaryStreamWriter &Writer) const { + if (auto EC = Writer.writeInteger<uint32_t>(Strings.size())) + return EC; + assert(Writer.bytesRemaining() == 0); + return Error::success(); +} + +Error PDBStringTableBuilder::commit(BinaryStreamWriter &Writer) const { + BinaryStreamWriter SectionWriter; + + std::tie(SectionWriter, Writer) = Writer.split(sizeof(PDBStringTableHeader)); + if (auto EC = writeHeader(SectionWriter)) + return EC; + + std::tie(SectionWriter, Writer) = + Writer.split(Strings.calculateSerializedSize()); + if (auto EC = writeStrings(SectionWriter)) + return EC; + + std::tie(SectionWriter, Writer) = Writer.split(calculateHashTableSize()); + if (auto EC = writeHashTable(SectionWriter)) + return EC; + + std::tie(SectionWriter, Writer) = Writer.split(sizeof(uint32_t)); + if (auto EC = writeEpilogue(SectionWriter)) + return EC; + + return Error::success(); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp index b31f605..9c3e654 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp @@ -22,15 +22,15 @@ // //===----------------------------------------------------------------------===// +#include "llvm/DebugInfo/PDB/Native/PublicsStream.h" #include "GSI.h" #include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/MSF/StreamReader.h" -#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" -#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" -#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/SymbolStream.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include <algorithm> @@ -41,19 +41,6 @@ using namespace llvm::msf; using namespace llvm::support; using namespace llvm::pdb; -// This is PSGSIHDR struct defined in -// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h -struct PublicsStream::HeaderInfo { - ulittle32_t SymHash; - ulittle32_t AddrMap; - ulittle32_t NumThunks; - ulittle32_t SizeOfThunk; - ulittle16_t ISectThunkTable; - char Padding[2]; - ulittle32_t OffThunkTable; - ulittle32_t NumSections; -}; - PublicsStream::PublicsStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream) : Pdb(File), Stream(std::move(Stream)) {} @@ -69,10 +56,11 @@ uint32_t PublicsStream::getAddrMap() const { return Header->AddrMap; } // we skip over the hash table which we believe contains information about // public symbols. Error PublicsStream::reload() { - StreamReader Reader(*Stream); + BinaryStreamReader Reader(*Stream); // Check stream size. - if (Reader.bytesRemaining() < sizeof(HeaderInfo) + sizeof(GSIHashHeader)) + if (Reader.bytesRemaining() < + sizeof(PublicsStreamHeader) + sizeof(GSIHashHeader)) return make_error<RawError>(raw_error_code::corrupt_file, "Publics Stream does not contain a header."); @@ -105,10 +93,12 @@ Error PublicsStream::reload() { "Could not read a thunk map.")); // Something called "section map" follows. - if (auto EC = Reader.readArray(SectionOffsets, Header->NumSections)) - return joinErrors(std::move(EC), - make_error<RawError>(raw_error_code::corrupt_file, - "Could not read a section map.")); + if (Reader.bytesRemaining() > 0) { + if (auto EC = Reader.readArray(SectionOffsets, Header->NumSections)) + return joinErrors(std::move(EC), + make_error<RawError>(raw_error_code::corrupt_file, + "Could not read a section map.")); + } if (Reader.bytesRemaining() > 0) return make_error<RawError>(raw_error_code::corrupt_file, @@ -128,4 +118,13 @@ PublicsStream::getSymbols(bool *HadError) const { return SS.getSymbols(HadError); } +Expected<const codeview::CVSymbolArray &> +PublicsStream::getSymbolArray() const { + auto SymbolS = Pdb.getPDBSymbolStream(); + if (!SymbolS) + return SymbolS.takeError(); + + return SymbolS->getSymbolArray(); +} + Error PublicsStream::commit() { return Error::success(); } diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PublicsStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PublicsStreamBuilder.cpp new file mode 100644 index 0000000..28c4a8f --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PublicsStreamBuilder.cpp @@ -0,0 +1,89 @@ +//===- DbiStreamBuilder.cpp - PDB Dbi Stream Creation -----------*- 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/Native/PublicsStreamBuilder.h" + +#include "llvm/DebugInfo/MSF/MSFBuilder.h" +#include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" + +#include "GSI.h" + +using namespace llvm; +using namespace llvm::msf; +using namespace llvm::pdb; + +PublicsStreamBuilder::PublicsStreamBuilder(msf::MSFBuilder &Msf) : Msf(Msf) {} + +PublicsStreamBuilder::~PublicsStreamBuilder() {} + +uint32_t PublicsStreamBuilder::calculateSerializedLength() const { + uint32_t Size = 0; + Size += sizeof(PublicsStreamHeader); + Size += sizeof(GSIHashHeader); + Size += HashRecords.size() * sizeof(PSHashRecord); + size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32); + uint32_t NumBitmapEntries = BitmapSizeInBits / 8; + Size += NumBitmapEntries; + + // FIXME: Account for hash buckets. For now since we we write a zero-bitmap + // indicating that no hash buckets are valid, we also write zero byets of hash + // bucket data. + Size += 0; + return Size; +} + +Error PublicsStreamBuilder::finalizeMsfLayout() { + Expected<uint32_t> Idx = Msf.addStream(calculateSerializedLength()); + if (!Idx) + return Idx.takeError(); + StreamIdx = *Idx; + + Expected<uint32_t> RecordIdx = Msf.addStream(0); + if (!RecordIdx) + return RecordIdx.takeError(); + RecordStreamIdx = *RecordIdx; + return Error::success(); +} + +Error PublicsStreamBuilder::commit(BinaryStreamWriter &PublicsWriter) { + PublicsStreamHeader PSH; + GSIHashHeader GSH; + + // FIXME: Figure out what to put for these values. + PSH.AddrMap = 0; + PSH.ISectThunkTable = 0; + PSH.NumSections = 0; + PSH.NumThunks = 0; + PSH.OffThunkTable = 0; + PSH.SizeOfThunk = 0; + PSH.SymHash = 0; + + GSH.VerSignature = GSIHashHeader::HdrSignature; + GSH.VerHdr = GSIHashHeader::HdrVersion; + GSH.HrSize = 0; + GSH.NumBuckets = 0; + + if (auto EC = PublicsWriter.writeObject(PSH)) + return EC; + if (auto EC = PublicsWriter.writeObject(GSH)) + return EC; + if (auto EC = PublicsWriter.writeArray(makeArrayRef(HashRecords))) + return EC; + + size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32); + uint32_t NumBitmapEntries = BitmapSizeInBits / 8; + std::vector<uint8_t> BitmapData(NumBitmapEntries); + // FIXME: Build an actual bitmap + if (auto EC = PublicsWriter.writeBytes(makeArrayRef(BitmapData))) + return EC; + + // FIXME: Write actual hash buckets. + return Error::success(); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/RawError.cpp index f4a5057..548289f 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/RawError.cpp @@ -1,4 +1,4 @@ -#include "llvm/DebugInfo/PDB/Raw/RawError.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" @@ -38,6 +38,8 @@ public: return "The entry does not exist."; case raw_error_code::not_writable: return "The PDB does not support writing."; + case raw_error_code::stream_too_long: + return "The stream was longer than expected."; case raw_error_code::invalid_tpi_hash: return "The Type record has an invalid hash value."; } diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/SymbolStream.cpp index 2f3ac34..9e9ebd1 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/SymbolStream.cpp @@ -7,16 +7,15 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h" +#include "llvm/DebugInfo/PDB/Native/SymbolStream.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/MSF/StreamReader.h" -#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" -#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" - +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Endian.h" using namespace llvm; @@ -30,7 +29,7 @@ SymbolStream::SymbolStream(std::unique_ptr<MappedBlockStream> Stream) SymbolStream::~SymbolStream() {} Error SymbolStream::reload() { - StreamReader Reader(*Stream); + BinaryStreamReader Reader(*Stream); if (auto EC = Reader.readArray(SymbolRecords, Stream->getLength())) return EC; diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/TpiHashing.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/TpiHashing.cpp new file mode 100644 index 0000000..77a2d57 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/TpiHashing.cpp @@ -0,0 +1,89 @@ +//===- TpiHashing.cpp -----------------------------------------------------===// +// +// 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/Native/TpiHashing.h" + +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/PDB/Native/Hash.h" +#include "llvm/Support/JamCRC.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +// Corresponds to `fUDTAnon`. +static bool isAnonymous(StringRef Name) { + return Name == "<unnamed-tag>" || Name == "__unnamed" || + Name.endswith("::<unnamed-tag>") || Name.endswith("::__unnamed"); +} + +// Computes the hash for a user-defined type record. This could be a struct, +// class, union, or enum. +static uint32_t getHashForUdt(const TagRecord &Rec, + ArrayRef<uint8_t> FullRecord) { + ClassOptions Opts = Rec.getOptions(); + bool ForwardRef = bool(Opts & ClassOptions::ForwardReference); + bool Scoped = bool(Opts & ClassOptions::Scoped); + bool HasUniqueName = bool(Opts & ClassOptions::HasUniqueName); + bool IsAnon = HasUniqueName && isAnonymous(Rec.getName()); + + if (!ForwardRef && !Scoped && !IsAnon) + return hashStringV1(Rec.getName()); + if (!ForwardRef && HasUniqueName && !IsAnon) + return hashStringV1(Rec.getUniqueName()); + return hashBufferV8(FullRecord); +} + +template <typename T> +static Expected<uint32_t> getHashForUdt(const CVType &Rec) { + T Deserialized; + if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec), + Deserialized)) + return std::move(E); + return getHashForUdt(Deserialized, Rec.data()); +} + +template <typename T> +static Expected<uint32_t> getSourceLineHash(const CVType &Rec) { + T Deserialized; + if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec), + Deserialized)) + return std::move(E); + char Buf[4]; + support::endian::write32le(Buf, Deserialized.getUDT().getIndex()); + return hashStringV1(StringRef(Buf, 4)); +} + +Expected<uint32_t> llvm::pdb::hashTypeRecord(const CVType &Rec) { + switch (Rec.kind()) { + case LF_CLASS: + case LF_STRUCTURE: + case LF_INTERFACE: + return getHashForUdt<ClassRecord>(Rec); + case LF_UNION: + return getHashForUdt<UnionRecord>(Rec); + case LF_ENUM: + return getHashForUdt<EnumRecord>(Rec); + + case LF_UDT_SRC_LINE: + return getSourceLineHash<UdtSourceLineRecord>(Rec); + case LF_UDT_MOD_SRC_LINE: + return getSourceLineHash<UdtModSourceLineRecord>(Rec); + + default: + break; + } + + // Run CRC32 over the bytes. This corresponds to `hashBufv8`. + JamCRC JC(/*Init=*/0U); + ArrayRef<char> Bytes(reinterpret_cast<const char *>(Rec.data().data()), + Rec.data().size()); + JC.update(Bytes); + return JC.getCRC(); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp index a1167cd..d3ef87d 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp @@ -7,19 +7,18 @@ // //===----------------------------------------------------------------------===// +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" + #include "llvm/ADT/iterator_range.h" -#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/MSF/StreamReader.h" -#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" -#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" -#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" -#include "llvm/DebugInfo/PDB/Raw/TpiHashing.h" -#include "llvm/DebugInfo/PDB/Raw/TpiStream.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/DebugInfo/PDB/Native/TpiHashing.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include <algorithm> @@ -32,28 +31,13 @@ using namespace llvm::support; using namespace llvm::msf; using namespace llvm::pdb; -TpiStream::TpiStream(const PDBFile &File, - std::unique_ptr<MappedBlockStream> Stream) +TpiStream::TpiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream) : Pdb(File), Stream(std::move(Stream)) {} TpiStream::~TpiStream() = default; -// Verifies that a given type record matches with a given hash value. -// Currently we only verify SRC_LINE records. -Error TpiStream::verifyHashValues() { - TpiHashVerifier Verifier(HashValues, Header->NumHashBuckets); - TypeDeserializer Deserializer; - - TypeVisitorCallbackPipeline Pipeline; - Pipeline.addCallbackToPipeline(Deserializer); - Pipeline.addCallbackToPipeline(Verifier); - - CVTypeVisitor Visitor(Pipeline); - return Visitor.visitTypeStream(TypeRecords); -} - Error TpiStream::reload() { - StreamReader Reader(*Stream); + BinaryStreamReader Reader(*Stream); if (Reader.bytesRemaining() < sizeof(TpiStreamHeader)) return make_error<RawError>(raw_error_code::corrupt_file, @@ -81,7 +65,13 @@ Error TpiStream::reload() { "TPI Stream Invalid number of hash buckets."); // The actual type records themselves come from this stream - if (auto EC = Reader.readArray(TypeRecords, Header->TypeRecordBytes)) + if (auto EC = + Reader.readSubstream(TypeRecordsSubstream, Header->TypeRecordBytes)) + return EC; + + BinaryStreamReader RecordReader(TypeRecordsSubstream.StreamData); + if (auto EC = + RecordReader.readArray(TypeRecords, TypeRecordsSubstream.size())) return EC; // Hash indices, hash values, etc come from the hash stream. @@ -91,21 +81,20 @@ Error TpiStream::reload() { "Invalid TPI hash stream index."); auto HS = MappedBlockStream::createIndexedStream( - Pdb.getMsfLayout(), Pdb.getMsfBuffer(), Header->HashStreamIndex); - StreamReader HSR(*HS); + Pdb.getMsfLayout(), Pdb.getMsfBuffer(), Header->HashStreamIndex, + Pdb.getAllocator()); + BinaryStreamReader HSR(*HS); + // There should be a hash value for every type record, or no hashes at all. uint32_t NumHashValues = Header->HashValueBuffer.Length / sizeof(ulittle32_t); - if (NumHashValues != NumTypeRecords()) + if (NumHashValues != getNumTypeRecords() && NumHashValues != 0) return make_error<RawError>( raw_error_code::corrupt_file, "TPI hash count does not match with the number of type records."); HSR.setOffset(Header->HashValueBuffer.Off); if (auto EC = HSR.readArray(HashValues, NumHashValues)) return EC; - std::vector<ulittle32_t> HashValueList; - for (auto I : HashValues) - HashValueList.push_back(I); HSR.setOffset(Header->IndexOffsetBuffer.Off); uint32_t NumTypeIndexOffsets = @@ -113,20 +102,17 @@ Error TpiStream::reload() { if (auto EC = HSR.readArray(TypeIndexOffsets, NumTypeIndexOffsets)) return EC; - HSR.setOffset(Header->HashAdjBuffer.Off); - uint32_t NumHashAdjustments = - Header->HashAdjBuffer.Length / sizeof(TypeIndexOffset); - if (auto EC = HSR.readArray(HashAdjustments, NumHashAdjustments)) - return EC; + if (Header->HashAdjBuffer.Length > 0) { + HSR.setOffset(Header->HashAdjBuffer.Off); + if (auto EC = HashAdjusters.load(HSR)) + return EC; + } HashStream = std::move(HS); - - // TPI hash table is a parallel array for the type records. - // Verify that the hash values match with type records. - if (auto EC = verifyHashValues()) - return EC; } + Types = llvm::make_unique<LazyRandomTypeCollection>( + TypeRecords, getNumTypeRecords(), getTypeIndexOffsets()); return Error::success(); } @@ -139,7 +125,7 @@ uint32_t TpiStream::TypeIndexBegin() const { return Header->TypeIndexBegin; } uint32_t TpiStream::TypeIndexEnd() const { return Header->TypeIndexEnd; } -uint32_t TpiStream::NumTypeRecords() const { +uint32_t TpiStream::getNumTypeRecords() const { return TypeIndexEnd() - TypeIndexBegin(); } @@ -151,26 +137,24 @@ uint16_t TpiStream::getTypeHashStreamAuxIndex() const { return Header->HashAuxStreamIndex; } -uint32_t TpiStream::NumHashBuckets() const { return Header->NumHashBuckets; } +uint32_t TpiStream::getNumHashBuckets() const { return Header->NumHashBuckets; } uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; } -FixedStreamArray<support::ulittle32_t> -TpiStream::getHashValues() const { +BinarySubstreamRef TpiStream::getTypeRecordsSubstream() const { + return TypeRecordsSubstream; +} + +FixedStreamArray<support::ulittle32_t> TpiStream::getHashValues() const { return HashValues; } -FixedStreamArray<TypeIndexOffset> -TpiStream::getTypeIndexOffsets() const { +FixedStreamArray<TypeIndexOffset> TpiStream::getTypeIndexOffsets() const { return TypeIndexOffsets; } -FixedStreamArray<TypeIndexOffset> -TpiStream::getHashAdjustments() const { - return HashAdjustments; -} +HashTable &TpiStream::getHashAdjusters() { return HashAdjusters; } -iterator_range<CVTypeArray::Iterator> -TpiStream::types(bool *HadError) const { +CVTypeRange TpiStream::types(bool *HadError) const { return make_range(TypeRecords.begin(HadError), TypeRecords.end()); } diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp new file mode 100644 index 0000000..9e943c7 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp @@ -0,0 +1,177 @@ +//===- TpiStreamBuilder.cpp - -------------------------------------------===// +// +// 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/Native/TpiStreamBuilder.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/MSF/MSFBuilder.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/BinaryByteStream.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <algorithm> +#include <cstdint> + +using namespace llvm; +using namespace llvm::msf; +using namespace llvm::pdb; +using namespace llvm::support; + +TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf, uint32_t StreamIdx) + : Msf(Msf), Allocator(Msf.getAllocator()), Header(nullptr), Idx(StreamIdx) { +} + +TpiStreamBuilder::~TpiStreamBuilder() = default; + +void TpiStreamBuilder::setVersionHeader(PdbRaw_TpiVer Version) { + VerHeader = Version; +} + +void TpiStreamBuilder::addTypeRecord(ArrayRef<uint8_t> Record, + Optional<uint32_t> Hash) { + // If we just crossed an 8KB threshold, add a type index offset. + size_t NewSize = TypeRecordBytes + Record.size(); + constexpr size_t EightKB = 8 * 1024; + if (NewSize / EightKB > TypeRecordBytes / EightKB || TypeRecords.empty()) { + TypeIndexOffsets.push_back( + {codeview::TypeIndex(codeview::TypeIndex::FirstNonSimpleIndex + + TypeRecords.size()), + ulittle32_t(TypeRecordBytes)}); + } + TypeRecordBytes = NewSize; + + TypeRecords.push_back(Record); + if (Hash) + TypeHashes.push_back(*Hash); +} + +Error TpiStreamBuilder::finalize() { + if (Header) + return Error::success(); + + TpiStreamHeader *H = Allocator.Allocate<TpiStreamHeader>(); + + uint32_t Count = TypeRecords.size(); + + H->Version = VerHeader; + H->HeaderSize = sizeof(TpiStreamHeader); + H->TypeIndexBegin = codeview::TypeIndex::FirstNonSimpleIndex; + H->TypeIndexEnd = H->TypeIndexBegin + Count; + H->TypeRecordBytes = TypeRecordBytes; + + H->HashStreamIndex = HashStreamIndex; + H->HashAuxStreamIndex = kInvalidStreamIndex; + H->HashKeySize = sizeof(ulittle32_t); + H->NumHashBuckets = MinTpiHashBuckets; + + // Recall that hash values go into a completely different stream identified by + // the `HashStreamIndex` field of the `TpiStreamHeader`. Therefore, the data + // begins at offset 0 of this independent stream. + H->HashValueBuffer.Off = 0; + H->HashValueBuffer.Length = calculateHashBufferSize(); + + // We never write any adjustments into our PDBs, so this is usually some + // offset with zero length. + H->HashAdjBuffer.Off = H->HashValueBuffer.Off + H->HashValueBuffer.Length; + H->HashAdjBuffer.Length = 0; + + H->IndexOffsetBuffer.Off = H->HashAdjBuffer.Off + H->HashAdjBuffer.Length; + H->IndexOffsetBuffer.Length = calculateIndexOffsetSize(); + + Header = H; + return Error::success(); +} + +uint32_t TpiStreamBuilder::calculateSerializedLength() { + return sizeof(TpiStreamHeader) + TypeRecordBytes; +} + +uint32_t TpiStreamBuilder::calculateHashBufferSize() const { + assert((TypeRecords.size() == TypeHashes.size() || TypeHashes.empty()) && + "either all or no type records should have hashes"); + return TypeHashes.size() * sizeof(ulittle32_t); +} + +uint32_t TpiStreamBuilder::calculateIndexOffsetSize() const { + return TypeIndexOffsets.size() * sizeof(codeview::TypeIndexOffset); +} + +Error TpiStreamBuilder::finalizeMsfLayout() { + uint32_t Length = calculateSerializedLength(); + if (auto EC = Msf.setStreamSize(Idx, Length)) + return EC; + + uint32_t HashStreamSize = + calculateHashBufferSize() + calculateIndexOffsetSize(); + + if (HashStreamSize == 0) + return Error::success(); + + auto ExpectedIndex = Msf.addStream(HashStreamSize); + if (!ExpectedIndex) + return ExpectedIndex.takeError(); + HashStreamIndex = *ExpectedIndex; + if (!TypeHashes.empty()) { + ulittle32_t *H = Allocator.Allocate<ulittle32_t>(TypeHashes.size()); + MutableArrayRef<ulittle32_t> HashBuffer(H, TypeHashes.size()); + for (uint32_t I = 0; I < TypeHashes.size(); ++I) { + HashBuffer[I] = TypeHashes[I] % MinTpiHashBuckets; + } + ArrayRef<uint8_t> Bytes( + reinterpret_cast<const uint8_t *>(HashBuffer.data()), + calculateHashBufferSize()); + HashValueStream = + llvm::make_unique<BinaryByteStream>(Bytes, llvm::support::little); + } + return Error::success(); +} + +Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout, + WritableBinaryStreamRef Buffer) { + if (auto EC = finalize()) + return EC; + + auto InfoS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer, + Idx, Allocator); + + BinaryStreamWriter Writer(*InfoS); + if (auto EC = Writer.writeObject(*Header)) + return EC; + + for (auto Rec : TypeRecords) + if (auto EC = Writer.writeBytes(Rec)) + return EC; + + if (HashStreamIndex != kInvalidStreamIndex) { + auto HVS = WritableMappedBlockStream::createIndexedStream( + Layout, Buffer, HashStreamIndex, Allocator); + BinaryStreamWriter HW(*HVS); + if (HashValueStream) { + if (auto EC = HW.writeStreamRef(*HashValueStream)) + return EC; + } + + for (auto &IndexOffset : TypeIndexOffsets) { + if (auto EC = HW.writeObject(IndexOffset)) + return EC; + } + } + + return Error::success(); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDB.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDB.cpp index 0d72059..501d4f5 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDB.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDB.cpp @@ -1,4 +1,4 @@ -//===- PDB.cpp - base header file for creating a PDB reader -----*- C++ -*-===// +//===- PDB.cpp - base header file for creating a PDB reader ---------------===// // // The LLVM Compiler Infrastructure // @@ -8,18 +8,14 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/PDB.h" - #include "llvm/ADT/StringRef.h" #include "llvm/Config/config.h" #include "llvm/DebugInfo/PDB/GenericError.h" -#include "llvm/DebugInfo/PDB/IPDBSession.h" -#include "llvm/DebugInfo/PDB/PDB.h" #if LLVM_ENABLE_DIA_SDK #include "llvm/DebugInfo/PDB/DIA/DIASession.h" #endif -#include "llvm/DebugInfo/PDB/Raw/RawSession.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/ManagedStatic.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/Support/Error.h" using namespace llvm; using namespace llvm::pdb; @@ -27,25 +23,25 @@ using namespace llvm::pdb; Error llvm::pdb::loadDataForPDB(PDB_ReaderType Type, StringRef Path, std::unique_ptr<IPDBSession> &Session) { // Create the correct concrete instance type based on the value of Type. - if (Type == PDB_ReaderType::Raw) - return RawSession::createFromPdb(Path, Session); + if (Type == PDB_ReaderType::Native) + return NativeSession::createFromPdb(Path, Session); #if LLVM_ENABLE_DIA_SDK return DIASession::createFromPdb(Path, Session); #else - return llvm::make_error<GenericError>("DIA is not installed on the system"); + return make_error<GenericError>("DIA is not installed on the system"); #endif } Error llvm::pdb::loadDataForEXE(PDB_ReaderType Type, StringRef Path, std::unique_ptr<IPDBSession> &Session) { // Create the correct concrete instance type based on the value of Type. - if (Type == PDB_ReaderType::Raw) - return RawSession::createFromExe(Path, Session); + if (Type == PDB_ReaderType::Native) + return NativeSession::createFromExe(Path, Session); #if LLVM_ENABLE_DIA_SDK return DIASession::createFromExe(Path, Session); #else - return llvm::make_error<GenericError>("DIA is not installed on the system"); + return make_error<GenericError>("DIA is not installed on the system"); #endif } diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBContext.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBContext.cpp index 94b81ec..df0feac 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBContext.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBContext.cpp @@ -12,8 +12,8 @@ #include "llvm/DebugInfo/PDB/IPDBLineNumber.h" #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" -#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" #include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h" #include "llvm/Object/COFF.h" @@ -29,8 +29,7 @@ PDBContext::PDBContext(const COFFObjectFile &Object, Session->setLoadAddress(ImageBase.get()); } -void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH, - bool SummarizeTypes) {} +void PDBContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){} DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier) { diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBExtras.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBExtras.cpp index b7eee6e..c291185 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBExtras.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBExtras.cpp @@ -1,4 +1,4 @@ -//===- PDBExtras.cpp - helper functions and classes for PDBs -----*- C++-*-===// +//===- PDBExtras.cpp - helper functions and classes for PDBs --------------===// // // The LLVM Compiler Infrastructure // @@ -8,8 +8,9 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/PDBExtras.h" - #include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/CodeView/Formatters.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::pdb; @@ -269,25 +270,6 @@ raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_UdtType &Type) { return OS; } -raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_UniqueId &Id) { - static const char *Lookup = "0123456789ABCDEF"; - - static_assert(sizeof(PDB_UniqueId) == 16, "Expected 16-byte GUID"); - ArrayRef<uint8_t> GuidBytes(reinterpret_cast<const uint8_t*>(&Id), 16); - OS << "{"; - for (int i=0; i < 16;) { - uint8_t Byte = GuidBytes[i]; - uint8_t HighNibble = (Byte >> 4) & 0xF; - uint8_t LowNibble = Byte & 0xF; - OS << Lookup[HighNibble] << Lookup[LowNibble]; - ++i; - if (i>=4 && i<=10 && i%2==0) - OS << "-"; - } - OS << "}"; - return OS; -} - raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_Machine &Machine) { switch (Machine) { diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp index 633e11a..74010c2 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp @@ -10,6 +10,7 @@ #include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDBExtras.h" #include "llvm/DebugInfo/PDB/PDBSymbolAnnotation.h" #include "llvm/DebugInfo/PDB/PDBSymbolBlock.h" @@ -53,6 +54,9 @@ PDBSymbol::PDBSymbol(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) : Session(PDBSession), RawSymbol(std::move(Symbol)) {} +PDBSymbol::PDBSymbol(PDBSymbol &Symbol) + : Session(Symbol.Session), RawSymbol(std::move(Symbol.RawSymbol)) {} + PDBSymbol::~PDBSymbol() = default; #define FACTORY_SYMTAG_CASE(Tag, Type) \ @@ -99,16 +103,30 @@ PDBSymbol::create(const IPDBSession &PDBSession, } } -#define TRY_DUMP_TYPE(Type) \ - if (const Type *DerivedThis = dyn_cast<Type>(this)) \ - Dumper.dump(OS, Indent, *DerivedThis); - -#define ELSE_TRY_DUMP_TYPE(Type, Dumper) else TRY_DUMP_TYPE(Type, Dumper) - void PDBSymbol::defaultDump(raw_ostream &OS, int Indent) const { RawSymbol->dump(OS, Indent); } +void PDBSymbol::dumpProperties() const { + outs() << "\n"; + defaultDump(outs(), 0); + outs().flush(); +} + +void PDBSymbol::dumpChildStats() const { + TagStats Stats; + getChildStats(Stats); + outs() << "\n"; + for (auto &Stat : Stats) { + outs() << Stat.first << ": " << Stat.second << "\n"; + } + outs().flush(); +} + +std::unique_ptr<PDBSymbol> PDBSymbol::clone() const { + return Session.getSymbolById(getSymIndexId()); +} + PDB_SymType PDBSymbol::getSymTag() const { return RawSymbol->getSymTag(); } uint32_t PDBSymbol::getSymIndexId() const { return RawSymbol->getSymIndexId(); } @@ -141,6 +159,8 @@ PDBSymbol::findInlineFramesByRVA(uint32_t RVA) const { std::unique_ptr<IPDBEnumSymbols> PDBSymbol::getChildStats(TagStats &Stats) const { std::unique_ptr<IPDBEnumSymbols> Result(findAllChildren()); + if (!Result) + return nullptr; Stats.clear(); while (auto Child = Result->getNext()) { ++Stats[Child->getSymTag()]; @@ -148,3 +168,7 @@ PDBSymbol::getChildStats(TagStats &Stats) const { Result->reset(); return Result; } + +std::unique_ptr<PDBSymbol> PDBSymbol::getSymbolByIdHelper(uint32_t Id) const { + return Session.getSymbolById(Id); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp index cdb167b..3648272 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp @@ -18,7 +18,9 @@ using namespace llvm::pdb; PDBSymbolAnnotation::PDBSymbolAnnotation(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::Annotation); +} void PDBSymbolAnnotation::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp index fd5dc94..7076b4a 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp @@ -9,8 +9,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolBlock.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include <utility> @@ -19,6 +19,8 @@ using namespace llvm::pdb; PDBSymbolBlock::PDBSymbolBlock(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::Block); +} void PDBSymbolBlock::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp index ebff088..854cf42 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp @@ -19,7 +19,9 @@ using namespace llvm::pdb; PDBSymbolCompiland::PDBSymbolCompiland(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::Compiland); +} void PDBSymbolCompiland::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp index 6dbd522..f73cd36 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp @@ -9,8 +9,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include <utility> @@ -19,7 +19,9 @@ using namespace llvm::pdb; PDBSymbolCompilandDetails::PDBSymbolCompilandDetails( const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::CompilandDetails); +} void PDBSymbolCompilandDetails::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp index 9c7f0b1..df696fa 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp @@ -10,8 +10,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h" #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include <utility> @@ -20,7 +20,9 @@ using namespace llvm::pdb; PDBSymbolCompilandEnv::PDBSymbolCompilandEnv( const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::CompilandEnv); +} std::string PDBSymbolCompilandEnv::getValue() const { Variant Value = RawSymbol->getValue(); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp index 0ea387a..a7b69a7 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp @@ -10,8 +10,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolCustom.h" #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include <utility> @@ -20,7 +20,9 @@ using namespace llvm::pdb; PDBSymbolCustom::PDBSymbolCustom(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> CustomSymbol) - : PDBSymbol(PDBSession, std::move(CustomSymbol)) {} + : PDBSymbol(PDBSession, std::move(CustomSymbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::Custom); +} void PDBSymbolCustom::getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) { RawSymbol->getDataBytes(bytes); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp index 62bb6f3..6002668 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp @@ -19,10 +19,8 @@ using namespace llvm::pdb; PDBSymbolData::PDBSymbolData(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> DataSymbol) - : PDBSymbol(PDBSession, std::move(DataSymbol)) {} - -std::unique_ptr<PDBSymbol> PDBSymbolData::getType() const { - return Session.getSymbolById(getTypeId()); + : PDBSymbol(PDBSession, std::move(DataSymbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::Data); } void PDBSymbolData::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp index 60101c1..7417167 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp @@ -10,6 +10,7 @@ #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" #include <utility> @@ -18,6 +19,18 @@ using namespace llvm::pdb; PDBSymbolExe::PDBSymbolExe(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::Exe); +} void PDBSymbolExe::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } + +uint32_t PDBSymbolExe::getPointerByteSize() const { + auto Pointer = findOneChild<PDBSymbolTypePointer>(); + if (Pointer) + return Pointer->getLength(); + + if (getMachineType() == PDB_Machine::x86) + return 4; + return 8; +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp index 35251c0..5a5cb4c 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp @@ -12,10 +12,10 @@ #include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/PDBSymDumper.h" #include "llvm/DebugInfo/PDB/PDBSymbolData.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" -#include "llvm/DebugInfo/PDB/PDBSymDumper.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" #include <unordered_set> @@ -85,10 +85,8 @@ private: PDBSymbolFunc::PDBSymbolFunc(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} - -std::unique_ptr<PDBSymbolTypeFunctionSig> PDBSymbolFunc::getSignature() const { - return Session.getConcreteSymbolById<PDBSymbolTypeFunctionSig>(getTypeId()); + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::Function); } std::unique_ptr<IPDBEnumChildren<PDBSymbolData>> @@ -96,8 +94,15 @@ PDBSymbolFunc::getArguments() const { return llvm::make_unique<FunctionArgEnumerator>(Session, *this); } -std::unique_ptr<PDBSymbolTypeUDT> PDBSymbolFunc::getClassParent() const { - return Session.getConcreteSymbolById<PDBSymbolTypeUDT>(getClassParentId()); -} - void PDBSymbolFunc::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } + +bool PDBSymbolFunc::isDestructor() const { + std::string Name = getName(); + if (Name.empty()) + return false; + if (Name[0] == '~') + return true; + if (Name == "__vecDelDtor") + return true; + return false; +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp index 77e996f..4a4195b 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp @@ -9,8 +9,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include <utility> @@ -19,7 +19,9 @@ using namespace llvm::pdb; PDBSymbolFuncDebugEnd::PDBSymbolFuncDebugEnd( const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::FuncDebugEnd); +} void PDBSymbolFuncDebugEnd::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp index 9c65387..a448a40 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp @@ -9,8 +9,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include <utility> @@ -19,7 +19,9 @@ using namespace llvm::pdb; PDBSymbolFuncDebugStart::PDBSymbolFuncDebugStart( const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::FuncDebugStart); +} void PDBSymbolFuncDebugStart::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp index d2cfd11..a67a20d 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp @@ -18,6 +18,8 @@ using namespace llvm::pdb; PDBSymbolLabel::PDBSymbolLabel(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::Label); +} void PDBSymbolLabel::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp index 97d6687..dbec16f 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp @@ -9,8 +9,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include <utility> @@ -19,7 +19,9 @@ using namespace llvm::pdb; PDBSymbolPublicSymbol::PDBSymbolPublicSymbol( const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::PublicSymbol); +} void PDBSymbolPublicSymbol::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp index ef8897d..b264819 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp @@ -18,6 +18,8 @@ using namespace llvm::pdb; PDBSymbolThunk::PDBSymbolThunk(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::Thunk); +} void PDBSymbolThunk::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp index c010cc5..a8054a4 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp @@ -19,12 +19,14 @@ using namespace llvm::pdb; PDBSymbolTypeArray::PDBSymbolTypeArray(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} - -std::unique_ptr<PDBSymbol> PDBSymbolTypeArray::getElementType() const { - return Session.getSymbolById(getTypeId()); + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::ArrayType); } void PDBSymbolTypeArray::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } + +void PDBSymbolTypeArray::dumpRight(PDBSymDumper &Dumper) const { + Dumper.dumpRight(*this); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp index 382c397..0fdf8b6 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp @@ -9,8 +9,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include <utility> @@ -19,7 +19,9 @@ using namespace llvm::pdb; PDBSymbolTypeBaseClass::PDBSymbolTypeBaseClass( const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::BaseClass); +} void PDBSymbolTypeBaseClass::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp index e5d65bf..0bf563a 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp @@ -18,7 +18,9 @@ using namespace llvm::pdb; PDBSymbolTypeBuiltin::PDBSymbolTypeBuiltin( const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::BuiltinType); +} void PDBSymbolTypeBuiltin::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp index 1d80c97..726e7e1 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp @@ -9,8 +9,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include <utility> @@ -19,7 +19,9 @@ using namespace llvm::pdb; PDBSymbolTypeCustom::PDBSymbolTypeCustom(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::CustomType); +} void PDBSymbolTypeCustom::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp index 535d97d..6c84b98 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp @@ -10,8 +10,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include <utility> @@ -20,7 +20,9 @@ using namespace llvm::pdb; PDBSymbolTypeDimension::PDBSymbolTypeDimension( const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::Dimension); +} void PDBSymbolTypeDimension::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp index 788f2b7..2addea0 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp @@ -21,15 +21,8 @@ using namespace llvm::pdb; PDBSymbolTypeEnum::PDBSymbolTypeEnum(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} - -std::unique_ptr<PDBSymbolTypeUDT> PDBSymbolTypeEnum::getClassParent() const { - return Session.getConcreteSymbolById<PDBSymbolTypeUDT>(getClassParentId()); -} - -std::unique_ptr<PDBSymbolTypeBuiltin> -PDBSymbolTypeEnum::getUnderlyingType() const { - return Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(getTypeId()); + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::Enum); } void PDBSymbolTypeEnum::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp index 5831bae..c018772 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp @@ -9,8 +9,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include <utility> @@ -19,7 +19,9 @@ using namespace llvm::pdb; PDBSymbolTypeFriend::PDBSymbolTypeFriend(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::Friend); +} void PDBSymbolTypeFriend::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp index c6f586d..4d5cd63 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp @@ -18,7 +18,9 @@ using namespace llvm::pdb; PDBSymbolTypeFunctionArg::PDBSymbolTypeFunctionArg( const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::FunctionArg); +} void PDBSymbolTypeFunctionArg::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp index 057ae26..0304c62 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp @@ -12,9 +12,9 @@ #include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/PDBSymDumper.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h" -#include "llvm/DebugInfo/PDB/PDBSymDumper.h" #include <utility> @@ -68,10 +68,8 @@ private: PDBSymbolTypeFunctionSig::PDBSymbolTypeFunctionSig( const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} - -std::unique_ptr<PDBSymbol> PDBSymbolTypeFunctionSig::getReturnType() const { - return Session.getSymbolById(getTypeId()); + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::FunctionSig); } std::unique_ptr<IPDBEnumSymbols> @@ -79,13 +77,10 @@ PDBSymbolTypeFunctionSig::getArguments() const { return llvm::make_unique<FunctionArgEnumerator>(Session, *this); } -std::unique_ptr<PDBSymbol> PDBSymbolTypeFunctionSig::getClassParent() const { - uint32_t ClassId = getClassParentId(); - if (ClassId == 0) - return nullptr; - return Session.getSymbolById(ClassId); -} - void PDBSymbolTypeFunctionSig::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } + +void PDBSymbolTypeFunctionSig::dumpRight(PDBSymDumper &Dumper) const { + Dumper.dumpRight(*this); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp index 072d2cf..7cfba82 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp @@ -9,8 +9,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include <utility> @@ -19,7 +19,9 @@ using namespace llvm::pdb; PDBSymbolTypeManaged::PDBSymbolTypeManaged( const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::ManagedType); +} void PDBSymbolTypeManaged::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp index 6997714..6981981 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp @@ -19,12 +19,14 @@ using namespace llvm::pdb; PDBSymbolTypePointer::PDBSymbolTypePointer( const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} - -std::unique_ptr<PDBSymbol> PDBSymbolTypePointer::getPointeeType() const { - return Session.getSymbolById(getTypeId()); + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::PointerType); } void PDBSymbolTypePointer::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } + +void PDBSymbolTypePointer::dumpRight(PDBSymDumper &Dumper) const { + Dumper.dumpRight(*this); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp index 0f283b9..102b540 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp @@ -18,7 +18,9 @@ using namespace llvm::pdb; PDBSymbolTypeTypedef::PDBSymbolTypeTypedef( const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::Typedef); +} void PDBSymbolTypeTypedef::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp index c71838c..15dc153 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp @@ -9,7 +9,15 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h" +#include "llvm/DebugInfo/PDB/UDTLayout.h" #include <utility> @@ -18,6 +26,8 @@ using namespace llvm::pdb; PDBSymbolTypeUDT::PDBSymbolTypeUDT(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::UDT); +} void PDBSymbolTypeUDT::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp index 6b76db5..9a21855 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp @@ -18,7 +18,9 @@ using namespace llvm::pdb; PDBSymbolTypeVTable::PDBSymbolTypeVTable(const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::VTable); +} void PDBSymbolTypeVTable::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp index ef509d6..ddc0574 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp @@ -9,8 +9,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include <utility> @@ -19,7 +19,9 @@ using namespace llvm::pdb; PDBSymbolTypeVTableShape::PDBSymbolTypeVTableShape( const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::VTableShape); +} void PDBSymbolTypeVTableShape::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp index dbbea9c..fdbe845 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp @@ -9,8 +9,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include <utility> diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp index 6a62d55..f40578f 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp @@ -9,8 +9,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include <utility> @@ -19,7 +19,9 @@ using namespace llvm::pdb; PDBSymbolUsingNamespace::PDBSymbolUsingNamespace( const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} + : PDBSymbol(PDBSession, std::move(Symbol)) { + assert(RawSymbol->getSymTag() == PDB_SymType::UsingNamespace); +} void PDBSymbolUsingNamespace::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp deleted file mode 100644 index f19535d..0000000 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp +++ /dev/null @@ -1,77 +0,0 @@ -//===- InfoStream.cpp - PDB Info Stream (Stream 1) Access -------*- 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/Raw/InfoStream.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/DebugInfo/MSF/StreamReader.h" -#include "llvm/DebugInfo/MSF/StreamWriter.h" -#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" -#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" -#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" - -using namespace llvm; -using namespace llvm::codeview; -using namespace llvm::msf; -using namespace llvm::pdb; - -InfoStream::InfoStream(std::unique_ptr<MappedBlockStream> Stream) - : Stream(std::move(Stream)) {} - -Error InfoStream::reload() { - StreamReader Reader(*Stream); - - const InfoStreamHeader *H; - if (auto EC = Reader.readObject(H)) - return joinErrors( - std::move(EC), - make_error<RawError>(raw_error_code::corrupt_file, - "PDB Stream does not contain a header.")); - - switch (H->Version) { - case PdbImplVC70: - case PdbImplVC80: - case PdbImplVC110: - case PdbImplVC140: - break; - default: - return make_error<RawError>(raw_error_code::corrupt_file, - "Unsupported PDB stream version."); - } - - Version = H->Version; - Signature = H->Signature; - Age = H->Age; - Guid = H->Guid; - - return NamedStreams.load(Reader); -} - -uint32_t InfoStream::getNamedStreamIndex(llvm::StringRef Name) const { - uint32_t Result; - if (!NamedStreams.tryGetValue(Name, Result)) - return 0; - return Result; -} - -iterator_range<StringMapConstIterator<uint32_t>> -InfoStream::named_streams() const { - return NamedStreams.entries(); -} - -PdbRaw_ImplVer InfoStream::getVersion() const { - return static_cast<PdbRaw_ImplVer>(Version); -} - -uint32_t InfoStream::getSignature() const { return Signature; } - -uint32_t InfoStream::getAge() const { return Age; } - -PDB_UniqueId InfoStream::getGuid() const { return Guid; } diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp deleted file mode 100644 index 73fbf85..0000000 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp +++ /dev/null @@ -1,65 +0,0 @@ -//===- InfoStreamBuilder.cpp - PDB Info Stream Creation ---------*- 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/Raw/InfoStreamBuilder.h" - -#include "llvm/DebugInfo/MSF/MSFBuilder.h" -#include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/MSF/StreamWriter.h" -#include "llvm/DebugInfo/PDB/Raw/InfoStream.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" -#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" - -using namespace llvm; -using namespace llvm::codeview; -using namespace llvm::msf; -using namespace llvm::pdb; - -InfoStreamBuilder::InfoStreamBuilder(msf::MSFBuilder &Msf) - : Msf(Msf), Ver(PdbRaw_ImplVer::PdbImplVC70), Sig(-1), Age(0) {} - -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::setGuid(PDB_UniqueId G) { Guid = G; } - -NameMapBuilder &InfoStreamBuilder::getNamedStreamsBuilder() { - return NamedStreams; -} - -uint32_t InfoStreamBuilder::calculateSerializedLength() const { - return sizeof(InfoStreamHeader) + NamedStreams.calculateSerializedLength(); -} - -Error InfoStreamBuilder::finalizeMsfLayout() { - uint32_t Length = calculateSerializedLength(); - if (auto EC = Msf.setStreamSize(StreamPDB, Length)) - return EC; - return Error::success(); -} - -Error InfoStreamBuilder::commit(const msf::MSFLayout &Layout, - const msf::WritableStream &Buffer) const { - auto InfoS = - WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamPDB); - StreamWriter Writer(*InfoS); - - InfoStreamHeader H; - H.Age = Age; - H.Signature = Sig; - H.Version = Ver; - H.Guid = Guid; - if (auto EC = Writer.writeObject(H)) - return EC; - - return NamedStreams.commit(Writer); -} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp deleted file mode 100644 index b34d770..0000000 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp +++ /dev/null @@ -1,81 +0,0 @@ -//===- ModInfo.cpp - PDB module information -------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/MSF/StreamReader.h" -#include "llvm/DebugInfo/PDB/Raw/ModInfo.h" -#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MathExtras.h" -#include <cstdint> - -using namespace llvm; -using namespace llvm::msf; -using namespace llvm::pdb; -using namespace llvm::support; - -ModInfo::ModInfo() = default; - -ModInfo::ModInfo(const ModInfo &Info) = default; - -ModInfo::~ModInfo() = default; - -Error ModInfo::initialize(ReadableStreamRef Stream, ModInfo &Info) { - StreamReader Reader(Stream); - if (auto EC = Reader.readObject(Info.Layout)) - return EC; - - if (auto EC = Reader.readZeroString(Info.ModuleName)) - return EC; - - if (auto EC = Reader.readZeroString(Info.ObjFileName)) - return EC; - return Error::success(); -} - -bool ModInfo::hasECInfo() const { - return (Layout->Flags & ModInfoFlags::HasECFlagMask) != 0; -} - -uint16_t ModInfo::getTypeServerIndex() const { - return (Layout->Flags & ModInfoFlags::TypeServerIndexMask) >> - ModInfoFlags::TypeServerIndexShift; -} - -uint16_t ModInfo::getModuleStreamIndex() const { return Layout->ModDiStream; } - -uint32_t ModInfo::getSymbolDebugInfoByteSize() const { - return Layout->SymBytes; -} - -uint32_t ModInfo::getLineInfoByteSize() const { return Layout->LineBytes; } - -uint32_t ModInfo::getC13LineInfoByteSize() const { return Layout->C13Bytes; } - -uint32_t ModInfo::getNumberOfFiles() const { return Layout->NumFiles; } - -uint32_t ModInfo::getSourceFileNameIndex() const { - return Layout->SrcFileNameNI; -} - -uint32_t ModInfo::getPdbFilePathNameIndex() const { - return Layout->PdbFilePathNI; -} - -StringRef ModInfo::getModuleName() const { return ModuleName; } - -StringRef ModInfo::getObjFileName() const { return ObjFileName; } - -uint32_t ModInfo::getRecordLength() const { - uint32_t M = ModuleName.str().size() + 1; - uint32_t O = ObjFileName.str().size() + 1; - uint32_t Size = sizeof(ModuleInfoHeader) + M + O; - Size = alignTo(Size, 4); - return Size; -} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp deleted file mode 100644 index 0ffc5b7..0000000 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp +++ /dev/null @@ -1,85 +0,0 @@ -//===- ModStream.cpp - PDB Module Info Stream Access ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/iterator_range.h" -#include "llvm/DebugInfo/CodeView/SymbolRecord.h" -#include "llvm/DebugInfo/MSF/StreamReader.h" -#include "llvm/DebugInfo/MSF/StreamRef.h" -#include "llvm/DebugInfo/PDB/Raw/ModInfo.h" -#include "llvm/DebugInfo/PDB/Raw/ModStream.h" -#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" -#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" -#include "llvm/Support/Error.h" -#include <algorithm> -#include <cstdint> - -using namespace llvm; -using namespace llvm::msf; -using namespace llvm::pdb; - -ModStream::ModStream(const ModInfo &Module, - std::unique_ptr<MappedBlockStream> Stream) - : Mod(Module), Stream(std::move(Stream)) {} - -ModStream::~ModStream() = default; - -Error ModStream::reload() { - StreamReader Reader(*Stream); - - uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize(); - uint32_t C11Size = Mod.getLineInfoByteSize(); - uint32_t C13Size = Mod.getC13LineInfoByteSize(); - - if (C11Size > 0 && C13Size > 0) - return make_error<RawError>(raw_error_code::corrupt_file, - "Module has both C11 and C13 line info"); - - ReadableStreamRef S; - - if (auto EC = Reader.readInteger(Signature)) - return EC; - if (auto EC = Reader.readArray(SymbolsSubstream, SymbolSize - 4)) - return EC; - - if (auto EC = Reader.readStreamRef(LinesSubstream, C11Size)) - return EC; - if (auto EC = Reader.readStreamRef(C13LinesSubstream, C13Size)) - return EC; - - StreamReader LineReader(C13LinesSubstream); - if (auto EC = LineReader.readArray(LineInfo, LineReader.bytesRemaining())) - return EC; - - uint32_t GlobalRefsSize; - if (auto EC = Reader.readInteger(GlobalRefsSize)) - return EC; - if (auto EC = Reader.readStreamRef(GlobalRefsSubstream, GlobalRefsSize)) - return EC; - if (Reader.bytesRemaining() > 0) - return make_error<RawError>(raw_error_code::corrupt_file, - "Unexpected bytes in module stream."); - - return Error::success(); -} - -iterator_range<codeview::CVSymbolArray::Iterator> -ModStream::symbols(bool *HadError) const { - // It's OK if the stream is empty. - if (SymbolsSubstream.getUnderlyingStream().getLength() == 0) - return make_range(SymbolsSubstream.end(), SymbolsSubstream.end()); - return make_range(SymbolsSubstream.begin(HadError), SymbolsSubstream.end()); -} - -iterator_range<codeview::ModuleSubstreamArray::Iterator> -ModStream::lines(bool *HadError) const { - return make_range(LineInfo.begin(HadError), LineInfo.end()); -} - -Error ModStream::commit() { return Error::success(); } diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/NameHashTable.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/NameHashTable.cpp deleted file mode 100644 index 84cccb35..0000000 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/NameHashTable.cpp +++ /dev/null @@ -1,104 +0,0 @@ -//===- NameHashTable.cpp - PDB Name Hash Table ------------------*- 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/Raw/NameHashTable.h" - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/DebugInfo/MSF/StreamReader.h" -#include "llvm/DebugInfo/PDB/Raw/Hash.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" -#include "llvm/Support/Endian.h" - -using namespace llvm; -using namespace llvm::msf; -using namespace llvm::support; -using namespace llvm::pdb; - -NameHashTable::NameHashTable() : Signature(0), HashVersion(0), NameCount(0) {} - -Error NameHashTable::load(StreamReader &Stream) { - struct Header { - support::ulittle32_t Signature; - support::ulittle32_t HashVersion; - support::ulittle32_t ByteSize; - }; - - const Header *H; - if (auto EC = Stream.readObject(H)) - return EC; - - if (H->Signature != 0xEFFEEFFE) - return make_error<RawError>(raw_error_code::corrupt_file, - "Invalid hash table signature"); - if (H->HashVersion != 1 && H->HashVersion != 2) - return make_error<RawError>(raw_error_code::corrupt_file, - "Unsupported hash version"); - - Signature = H->Signature; - HashVersion = H->HashVersion; - if (auto EC = Stream.readStreamRef(NamesBuffer, H->ByteSize)) - return joinErrors(std::move(EC), - make_error<RawError>(raw_error_code::corrupt_file, - "Invalid hash table byte length")); - - const support::ulittle32_t *HashCount; - if (auto EC = Stream.readObject(HashCount)) - return EC; - - if (auto EC = Stream.readArray(IDs, *HashCount)) - return joinErrors(std::move(EC), - make_error<RawError>(raw_error_code::corrupt_file, - "Could not read bucket array")); - - if (Stream.bytesRemaining() < sizeof(support::ulittle32_t)) - return make_error<RawError>(raw_error_code::corrupt_file, - "Missing name count"); - - if (auto EC = Stream.readInteger(NameCount)) - return EC; - return Error::success(); -} - -StringRef NameHashTable::getStringForID(uint32_t ID) const { - if (ID == IDs[0]) - return StringRef(); - - // NamesBuffer is a buffer of null terminated strings back to back. ID is - // the starting offset of the string we're looking for. So just seek into - // the desired offset and a read a null terminated stream from that offset. - StringRef Result; - StreamReader NameReader(NamesBuffer); - NameReader.setOffset(ID); - if (auto EC = NameReader.readZeroString(Result)) - consumeError(std::move(EC)); - return Result; -} - -uint32_t NameHashTable::getIDForString(StringRef Str) const { - uint32_t Hash = (HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str); - size_t Count = IDs.size(); - uint32_t Start = Hash % Count; - for (size_t I = 0; I < Count; ++I) { - // The hash is just a starting point for the search, but if it - // doesn't work we should find the string no matter what, because - // we iterate the entire array. - uint32_t Index = (Start + I) % Count; - - uint32_t ID = IDs[Index]; - StringRef S = getStringForID(ID); - if (S == Str) - return ID; - } - // IDs[0] contains the ID of the "invalid" entry. - return IDs[0]; -} - -FixedStreamArray<support::ulittle32_t> NameHashTable::name_ids() const { - return IDs; -} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp deleted file mode 100644 index 0f55f58..0000000 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp +++ /dev/null @@ -1,163 +0,0 @@ -//===- NameMap.cpp - PDB Name Map -------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/SparseBitVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/DebugInfo/MSF/StreamReader.h" -#include "llvm/DebugInfo/PDB/Raw/NameMap.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" -#include "llvm/Support/Error.h" -#include <algorithm> -#include <cstdint> - -using namespace llvm; -using namespace llvm::msf; -using namespace llvm::pdb; - -NameMap::NameMap() = default; - -Error NameMap::load(StreamReader &Stream) { - // This is some sort of weird string-set/hash table encoded in the stream. - // It starts with the number of bytes in the table. - uint32_t NumberOfBytes; - if (auto EC = Stream.readInteger(NumberOfBytes)) - return joinErrors(std::move(EC), - make_error<RawError>(raw_error_code::corrupt_file, - "Expected name map length")); - if (Stream.bytesRemaining() < NumberOfBytes) - return make_error<RawError>(raw_error_code::corrupt_file, - "Invalid name map length"); - - // Following that field is the starting offset of strings in the name table. - uint32_t StringsOffset = Stream.getOffset(); - Stream.setOffset(StringsOffset + NumberOfBytes); - - // This appears to be equivalent to the total number of strings *actually* - // in the name table. - uint32_t HashSize; - if (auto EC = Stream.readInteger(HashSize)) - return joinErrors(std::move(EC), - make_error<RawError>(raw_error_code::corrupt_file, - "Expected name map hash size")); - - // This appears to be an upper bound on the number of strings in the name - // table. - uint32_t MaxNumberOfStrings; - if (auto EC = Stream.readInteger(MaxNumberOfStrings)) - return joinErrors(std::move(EC), - make_error<RawError>(raw_error_code::corrupt_file, - "Expected name map max strings")); - - if (MaxNumberOfStrings > (UINT32_MAX / sizeof(uint32_t))) - return make_error<RawError>(raw_error_code::corrupt_file, - "Implausible number of strings"); - - const uint32_t MaxNumberOfWords = UINT32_MAX / (sizeof(uint32_t) * 8); - - // This appears to be a hash table which uses bitfields to determine whether - // or not a bucket is 'present'. - uint32_t NumPresentWords; - if (auto EC = Stream.readInteger(NumPresentWords)) - return joinErrors(std::move(EC), - make_error<RawError>(raw_error_code::corrupt_file, - "Expected name map num words")); - - if (NumPresentWords > MaxNumberOfWords) - return make_error<RawError>(raw_error_code::corrupt_file, - "Number of present words is too large"); - - SparseBitVector<> Present; - for (uint32_t I = 0; I != NumPresentWords; ++I) { - uint32_t Word; - if (auto EC = Stream.readInteger(Word)) - return joinErrors(std::move(EC), - make_error<RawError>(raw_error_code::corrupt_file, - "Expected name map word")); - for (unsigned Idx = 0; Idx < 32; ++Idx) - if (Word & (1U << Idx)) - Present.set((I * 32) + Idx); - } - - // This appears to be a hash table which uses bitfields to determine whether - // or not a bucket is 'deleted'. - uint32_t NumDeletedWords; - if (auto EC = Stream.readInteger(NumDeletedWords)) - return joinErrors( - std::move(EC), - make_error<RawError>(raw_error_code::corrupt_file, - "Expected name map num deleted words")); - - if (NumDeletedWords > MaxNumberOfWords) - return make_error<RawError>(raw_error_code::corrupt_file, - "Number of deleted words is too large"); - - SparseBitVector<> Deleted; - for (uint32_t I = 0; I != NumDeletedWords; ++I) { - uint32_t Word; - if (auto EC = Stream.readInteger(Word)) - return joinErrors(std::move(EC), - make_error<RawError>(raw_error_code::corrupt_file, - "Expected name map word")); - for (unsigned Idx = 0; Idx < 32; ++Idx) - if (Word & (1U << Idx)) - Deleted.set((I * 32) + Idx); - } - - for (unsigned I : Present) { - // For all present entries, dump out their mapping. - (void)I; - - // This appears to be an offset relative to the start of the strings. - // It tells us where the null-terminated string begins. - uint32_t NameOffset; - if (auto EC = Stream.readInteger(NameOffset)) - return joinErrors(std::move(EC), - make_error<RawError>(raw_error_code::corrupt_file, - "Expected name map name offset")); - - // This appears to be a stream number into the stream directory. - uint32_t NameIndex; - if (auto EC = Stream.readInteger(NameIndex)) - return joinErrors(std::move(EC), - make_error<RawError>(raw_error_code::corrupt_file, - "Expected name map name index")); - - // Compute the offset of the start of the string relative to the stream. - uint32_t StringOffset = StringsOffset + NameOffset; - uint32_t OldOffset = Stream.getOffset(); - // Pump out our c-string from the stream. - StringRef Str; - Stream.setOffset(StringOffset); - if (auto EC = Stream.readZeroString(Str)) - return joinErrors(std::move(EC), - make_error<RawError>(raw_error_code::corrupt_file, - "Expected name map name")); - - Stream.setOffset(OldOffset); - // Add this to a string-map from name to stream number. - Mapping.insert({Str, NameIndex}); - } - - return Error::success(); -} - -iterator_range<StringMapConstIterator<uint32_t>> NameMap::entries() const { - return make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(), - Mapping.end()); -} - -bool NameMap::tryGetValue(StringRef Name, uint32_t &Value) const { - auto Iter = Mapping.find(Name); - if (Iter == Mapping.end()) - return false; - Value = Iter->second; - return true; -} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp deleted file mode 100644 index f570d59..0000000 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp +++ /dev/null @@ -1,108 +0,0 @@ -//===- NameMapBuilder.cpp - PDB Name Map Builder ----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/STLExtras.h" -#include "llvm/DebugInfo/MSF/StreamWriter.h" -#include "llvm/DebugInfo/PDB/Raw/NameMap.h" -#include "llvm/DebugInfo/PDB/Raw/NameMapBuilder.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include <algorithm> -#include <cstdint> - -using namespace llvm; -using namespace llvm::pdb; - -NameMapBuilder::NameMapBuilder() = default; - -void NameMapBuilder::addMapping(StringRef Name, uint32_t Mapping) { - StringDataBytes += Name.size() + 1; - Map.insert({Name, Mapping}); -} - -Expected<std::unique_ptr<NameMap>> NameMapBuilder::build() { - auto Result = llvm::make_unique<NameMap>(); - Result->Mapping = Map; - return std::move(Result); -} - -uint32_t NameMapBuilder::calculateSerializedLength() const { - uint32_t TotalLength = 0; - - TotalLength += sizeof(support::ulittle32_t); // StringDataBytes value - TotalLength += StringDataBytes; // actual string data - - TotalLength += sizeof(support::ulittle32_t); // Hash Size - TotalLength += sizeof(support::ulittle32_t); // Max Number of Strings - TotalLength += sizeof(support::ulittle32_t); // Num Present Words - // One bitmask word for each present entry - TotalLength += Map.size() * sizeof(support::ulittle32_t); - TotalLength += sizeof(support::ulittle32_t); // Num Deleted Words - - // For each present word, which we are treating as equivalent to the number of - // entries in the table, we have a pair of integers. An offset into the - // string data, and a corresponding stream number. - TotalLength += Map.size() * 2 * sizeof(support::ulittle32_t); - - return TotalLength; -} - -Error NameMapBuilder::commit(msf::StreamWriter &Writer) const { - // The first field is the number of bytes of string data. So add - // up the length of all strings plus a null terminator for each - // one. - uint32_t NumBytes = 0; - for (auto B = Map.begin(), E = Map.end(); B != E; ++B) { - NumBytes += B->getKeyLength() + 1; - } - - if (auto EC = Writer.writeInteger(NumBytes)) // Number of bytes of string data - return EC; - // Now all of the string data itself. - for (auto B = Map.begin(), E = Map.end(); B != E; ++B) { - if (auto EC = Writer.writeZeroString(B->getKey())) - return EC; - } - - if (auto EC = Writer.writeInteger(Map.size())) // Hash Size - return EC; - - if (auto EC = Writer.writeInteger(Map.size())) // Max Number of Strings - return EC; - - if (auto EC = Writer.writeInteger(Map.size())) // Num Present Words - return EC; - - // For each entry in the mapping, write a bit mask which represents a bucket - // to store it in. We don't use this, so the value we write isn't important - // to us, it just has to be there. - for (auto B = Map.begin(), E = Map.end(); B != E; ++B) { - if (auto EC = Writer.writeInteger(1U)) - return EC; - } - - if (auto EC = Writer.writeInteger(0U)) // Num Deleted Words - return EC; - - // Mappings of each word. - uint32_t OffsetSoFar = 0; - for (auto B = Map.begin(), E = Map.end(); B != E; ++B) { - // This is a list of key value pairs where the key is the offset into the - // strings buffer, and the value is a stream number. Write each pair. - if (auto EC = Writer.writeInteger(OffsetSoFar)) - return EC; - - if (auto EC = Writer.writeInteger(B->second)) - return EC; - - OffsetSoFar += B->getKeyLength() + 1; - } - - return Error::success(); -} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp deleted file mode 100644 index 6fec0e3..0000000 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp +++ /dev/null @@ -1,148 +0,0 @@ -//===- PDBFileBuilder.cpp - PDB File Creation -------------------*- 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/Raw/PDBFileBuilder.h" - -#include "llvm/ADT/BitVector.h" - -#include "llvm/DebugInfo/MSF/MSFBuilder.h" -#include "llvm/DebugInfo/MSF/StreamInterface.h" -#include "llvm/DebugInfo/MSF/StreamWriter.h" -#include "llvm/DebugInfo/PDB/GenericError.h" -#include "llvm/DebugInfo/PDB/Raw/DbiStream.h" -#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h" -#include "llvm/DebugInfo/PDB/Raw/InfoStream.h" -#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" -#include "llvm/DebugInfo/PDB/Raw/TpiStream.h" -#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h" - -using namespace llvm; -using namespace llvm::codeview; -using namespace llvm::msf; -using namespace llvm::pdb; -using namespace llvm::support; - -PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator) - : Allocator(Allocator) {} - -Error PDBFileBuilder::initialize(uint32_t BlockSize) { - auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize); - if (!ExpectedMsf) - return ExpectedMsf.takeError(); - Msf = llvm::make_unique<MSFBuilder>(std::move(*ExpectedMsf)); - return Error::success(); -} - -MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; } - -InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() { - if (!Info) - Info = llvm::make_unique<InfoStreamBuilder>(*Msf); - return *Info; -} - -DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() { - if (!Dbi) - Dbi = llvm::make_unique<DbiStreamBuilder>(*Msf); - return *Dbi; -} - -TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() { - if (!Tpi) - Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI); - return *Tpi; -} - -TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() { - if (!Ipi) - Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI); - return *Ipi; -} - -Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() const { - if (Info) { - if (auto EC = Info->finalizeMsfLayout()) - return std::move(EC); - } - if (Dbi) { - if (auto EC = Dbi->finalizeMsfLayout()) - return std::move(EC); - } - if (Tpi) { - if (auto EC = Tpi->finalizeMsfLayout()) - return std::move(EC); - } - if (Ipi) { - if (auto EC = Ipi->finalizeMsfLayout()) - return std::move(EC); - } - - return Msf->build(); -} - -Error PDBFileBuilder::commit(StringRef Filename) { - 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 (OutFileOrError.getError()) - return llvm::make_error<pdb::GenericError>(generic_error_code::invalid_path, - Filename); - FileBufferByteStream Buffer(std::move(*OutFileOrError)); - StreamWriter Writer(Buffer); - - if (auto EC = Writer.writeObject(*Layout.SB)) - return EC; - uint32_t BlockMapOffset = - msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize); - Writer.setOffset(BlockMapOffset); - if (auto EC = Writer.writeArray(Layout.DirectoryBlocks)) - return EC; - - auto DirStream = - WritableMappedBlockStream::createDirectoryStream(Layout, Buffer); - StreamWriter DW(*DirStream); - if (auto EC = - DW.writeInteger(static_cast<uint32_t>(Layout.StreamSizes.size()))) - return EC; - - if (auto EC = DW.writeArray(Layout.StreamSizes)) - return EC; - - for (const auto &Blocks : Layout.StreamMap) { - if (auto EC = DW.writeArray(Blocks)) - return EC; - } - - if (Info) { - if (auto EC = Info->commit(Layout, Buffer)) - return EC; - } - - if (Dbi) { - if (auto EC = Dbi->commit(Layout, Buffer)) - return EC; - } - - if (Tpi) { - if (auto EC = Tpi->commit(Layout, Buffer)) - return EC; - } - - if (Ipi) { - if (auto EC = Ipi->commit(Layout, Buffer)) - return EC; - } - - return Buffer.commit(); -} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/RawSession.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/RawSession.cpp deleted file mode 100644 index cd3a206..0000000 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/RawSession.cpp +++ /dev/null @@ -1,136 +0,0 @@ -//===- RawSession.cpp - Raw implementation of IPDBSession -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/STLExtras.h" -#include "llvm/DebugInfo/MSF/ByteStream.h" -#include "llvm/DebugInfo/PDB/GenericError.h" -#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" -#include "llvm/DebugInfo/PDB/IPDBSourceFile.h" -#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" -#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" -#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" -#include "llvm/DebugInfo/PDB/Raw/RawSession.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/ErrorOr.h" -#include "llvm/Support/MemoryBuffer.h" -#include <algorithm> -#include <memory> - -using namespace llvm; -using namespace llvm::msf; -using namespace llvm::pdb; - -RawSession::RawSession(std::unique_ptr<PDBFile> PdbFile, - std::unique_ptr<BumpPtrAllocator> Allocator) - : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)) {} - -RawSession::~RawSession() = default; - -Error RawSession::createFromPdb(StringRef Path, - std::unique_ptr<IPDBSession> &Session) { - ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer = - MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1, - /*RequiresNullTerminator=*/false); - if (!ErrorOrBuffer) - return make_error<GenericError>(generic_error_code::invalid_path); - - std::unique_ptr<MemoryBuffer> Buffer = std::move(*ErrorOrBuffer); - auto Stream = llvm::make_unique<MemoryBufferByteStream>(std::move(Buffer)); - - auto Allocator = llvm::make_unique<BumpPtrAllocator>(); - auto File = llvm::make_unique<PDBFile>(std::move(Stream), *Allocator); - if (auto EC = File->parseFileHeaders()) - return EC; - if (auto EC = File->parseStreamData()) - return EC; - - Session = - llvm::make_unique<RawSession>(std::move(File), std::move(Allocator)); - - return Error::success(); -} - -Error RawSession::createFromExe(StringRef Path, - std::unique_ptr<IPDBSession> &Session) { - return make_error<RawError>(raw_error_code::feature_unsupported); -} - -uint64_t RawSession::getLoadAddress() const { return 0; } - -void RawSession::setLoadAddress(uint64_t Address) {} - -std::unique_ptr<PDBSymbolExe> RawSession::getGlobalScope() const { - return nullptr; -} - -std::unique_ptr<PDBSymbol> RawSession::getSymbolById(uint32_t SymbolId) const { - return nullptr; -} - -std::unique_ptr<PDBSymbol> -RawSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const { - return nullptr; -} - -std::unique_ptr<IPDBEnumLineNumbers> -RawSession::findLineNumbers(const PDBSymbolCompiland &Compiland, - const IPDBSourceFile &File) const { - return nullptr; -} - -std::unique_ptr<IPDBEnumLineNumbers> -RawSession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const { - return nullptr; -} - -std::unique_ptr<IPDBEnumSourceFiles> -RawSession::findSourceFiles(const PDBSymbolCompiland *Compiland, - StringRef Pattern, - PDB_NameSearchFlags Flags) const { - return nullptr; -} - -std::unique_ptr<IPDBSourceFile> -RawSession::findOneSourceFile(const PDBSymbolCompiland *Compiland, - StringRef Pattern, - PDB_NameSearchFlags Flags) const { - return nullptr; -} - -std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>> -RawSession::findCompilandsForSourceFile(StringRef Pattern, - PDB_NameSearchFlags Flags) const { - return nullptr; -} - -std::unique_ptr<PDBSymbolCompiland> -RawSession::findOneCompilandForSourceFile(StringRef Pattern, - PDB_NameSearchFlags Flags) const { - return nullptr; -} - -std::unique_ptr<IPDBEnumSourceFiles> RawSession::getAllSourceFiles() const { - return nullptr; -} - -std::unique_ptr<IPDBEnumSourceFiles> RawSession::getSourceFilesForCompiland( - const PDBSymbolCompiland &Compiland) const { - return nullptr; -} - -std::unique_ptr<IPDBSourceFile> -RawSession::getSourceFileById(uint32_t FileId) const { - return nullptr; -} - -std::unique_ptr<IPDBEnumDataStreams> RawSession::getDebugStreams() const { - return nullptr; -} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiHashing.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiHashing.cpp deleted file mode 100644 index 6c3ddb3..0000000 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiHashing.cpp +++ /dev/null @@ -1,110 +0,0 @@ -//===- TpiHashing.cpp -----------------------------------------------------===// -// -// 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/Raw/TpiHashing.h" - -#include "llvm/DebugInfo/PDB/Raw/Hash.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" - -using namespace llvm; -using namespace llvm::codeview; -using namespace llvm::pdb; - -// Corresponds to `fUDTAnon`. -template <typename T> static bool isAnonymous(T &Rec) { - StringRef Name = Rec.getName(); - return Name == "<unnamed-tag>" || Name == "__unnamed" || - Name.endswith("::<unnamed-tag>") || Name.endswith("::__unnamed"); -} - -// Computes a hash for a given TPI record. -template <typename T> -static uint32_t getTpiHash(T &Rec, ArrayRef<uint8_t> FullRecord) { - auto Opts = static_cast<uint16_t>(Rec.getOptions()); - - bool ForwardRef = - Opts & static_cast<uint16_t>(ClassOptions::ForwardReference); - bool Scoped = Opts & static_cast<uint16_t>(ClassOptions::Scoped); - bool UniqueName = Opts & static_cast<uint16_t>(ClassOptions::HasUniqueName); - bool IsAnon = UniqueName && isAnonymous(Rec); - - if (!ForwardRef && !Scoped && !IsAnon) - return hashStringV1(Rec.getName()); - if (!ForwardRef && UniqueName && !IsAnon) - return hashStringV1(Rec.getUniqueName()); - return hashBufferV8(FullRecord); -} - -template <typename T> static uint32_t getSourceLineHash(T &Rec) { - char Buf[4]; - support::endian::write32le(Buf, Rec.getUDT().getIndex()); - return hashStringV1(StringRef(Buf, 4)); -} - -void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, - UdtSourceLineRecord &Rec) { - CVR.Hash = getSourceLineHash(Rec); -} - -void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, - UdtModSourceLineRecord &Rec) { - CVR.Hash = getSourceLineHash(Rec); -} - -void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, ClassRecord &Rec) { - CVR.Hash = getTpiHash(Rec, CVR.data()); -} - -void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, EnumRecord &Rec) { - CVR.Hash = getTpiHash(Rec, CVR.data()); -} - -void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, UnionRecord &Rec) { - CVR.Hash = getTpiHash(Rec, CVR.data()); -} - -Error TpiHashVerifier::visitKnownRecord(CVType &CVR, UdtSourceLineRecord &Rec) { - return verifySourceLine(Rec.getUDT()); -} - -Error TpiHashVerifier::visitKnownRecord(CVType &CVR, - UdtModSourceLineRecord &Rec) { - return verifySourceLine(Rec.getUDT()); -} - -Error TpiHashVerifier::visitKnownRecord(CVType &CVR, ClassRecord &Rec) { - if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index]) - return errorInvalidHash(); - return Error::success(); -} -Error TpiHashVerifier::visitKnownRecord(CVType &CVR, EnumRecord &Rec) { - if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index]) - return errorInvalidHash(); - return Error::success(); -} -Error TpiHashVerifier::visitKnownRecord(CVType &CVR, UnionRecord &Rec) { - if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index]) - return errorInvalidHash(); - return Error::success(); -} - -Error TpiHashVerifier::verifySourceLine(codeview::TypeIndex TI) { - char Buf[4]; - support::endian::write32le(Buf, TI.getIndex()); - uint32_t Hash = hashStringV1(StringRef(Buf, 4)); - if (Hash % NumHashBuckets != HashValues[Index]) - return errorInvalidHash(); - return Error::success(); -} - -Error TpiHashVerifier::visitTypeBegin(CVType &Rec) { - ++Index; - RawRecord = Rec; - return Error::success(); -} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp deleted file mode 100644 index c769321..0000000 --- a/contrib/llvm/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp +++ /dev/null @@ -1,145 +0,0 @@ -//===- TpiStreamBuilder.cpp - -------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/MSF/ByteStream.h" -#include "llvm/DebugInfo/MSF/MSFBuilder.h" -#include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/MSF/StreamArray.h" -#include "llvm/DebugInfo/MSF/StreamReader.h" -#include "llvm/DebugInfo/MSF/StreamWriter.h" -#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" -#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" -#include "llvm/DebugInfo/PDB/Raw/TpiStream.h" -#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include <algorithm> -#include <cstdint> - -using namespace llvm; -using namespace llvm::msf; -using namespace llvm::pdb; -using namespace llvm::support; - -TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf, uint32_t StreamIdx) - : Msf(Msf), Allocator(Msf.getAllocator()), Header(nullptr), Idx(StreamIdx) { -} - -TpiStreamBuilder::~TpiStreamBuilder() = default; - -void TpiStreamBuilder::setVersionHeader(PdbRaw_TpiVer Version) { - VerHeader = Version; -} - -void TpiStreamBuilder::addTypeRecord(const codeview::CVType &Record) { - TypeRecords.push_back(Record); - TypeRecordStream.setItems(TypeRecords); -} - -Error TpiStreamBuilder::finalize() { - if (Header) - return Error::success(); - - TpiStreamHeader *H = Allocator.Allocate<TpiStreamHeader>(); - - uint32_t Count = TypeRecords.size(); - uint32_t HashBufferSize = calculateHashBufferSize(); - - H->Version = *VerHeader; - H->HeaderSize = sizeof(TpiStreamHeader); - H->TypeIndexBegin = codeview::TypeIndex::FirstNonSimpleIndex; - H->TypeIndexEnd = H->TypeIndexBegin + Count; - H->TypeRecordBytes = TypeRecordStream.getLength(); - - H->HashStreamIndex = HashStreamIndex; - H->HashAuxStreamIndex = kInvalidStreamIndex; - H->HashKeySize = sizeof(ulittle32_t); - H->NumHashBuckets = MinTpiHashBuckets; - - // Recall that hash values go into a completely different stream identified by - // the `HashStreamIndex` field of the `TpiStreamHeader`. Therefore, the data - // begins at offset 0 of this independent stream. - H->HashValueBuffer.Off = 0; - H->HashValueBuffer.Length = HashBufferSize; - H->HashAdjBuffer.Off = H->HashValueBuffer.Off + H->HashValueBuffer.Length; - H->HashAdjBuffer.Length = 0; - H->IndexOffsetBuffer.Off = H->HashAdjBuffer.Off + H->HashAdjBuffer.Length; - H->IndexOffsetBuffer.Length = 0; - - Header = H; - return Error::success(); -} - -uint32_t TpiStreamBuilder::calculateSerializedLength() const { - return sizeof(TpiStreamHeader) + TypeRecordStream.getLength(); -} - -uint32_t TpiStreamBuilder::calculateHashBufferSize() const { - if (TypeRecords.empty() || !TypeRecords[0].Hash.hasValue()) - return 0; - return TypeRecords.size() * sizeof(ulittle32_t); -} - -Error TpiStreamBuilder::finalizeMsfLayout() { - uint32_t Length = calculateSerializedLength(); - if (auto EC = Msf.setStreamSize(Idx, Length)) - return EC; - - uint32_t HashBufferSize = calculateHashBufferSize(); - - if (HashBufferSize == 0) - return Error::success(); - - auto ExpectedIndex = Msf.addStream(HashBufferSize); - if (!ExpectedIndex) - return ExpectedIndex.takeError(); - HashStreamIndex = *ExpectedIndex; - ulittle32_t *H = Allocator.Allocate<ulittle32_t>(TypeRecords.size()); - MutableArrayRef<ulittle32_t> HashBuffer(H, TypeRecords.size()); - for (uint32_t I = 0; I < TypeRecords.size(); ++I) { - HashBuffer[I] = *TypeRecords[I].Hash % MinTpiHashBuckets; - } - ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(HashBuffer.data()), - HashBufferSize); - HashValueStream = llvm::make_unique<ByteStream>(Bytes); - return Error::success(); -} - -Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout, - const msf::WritableStream &Buffer) { - if (auto EC = finalize()) - return EC; - - auto InfoS = - WritableMappedBlockStream::createIndexedStream(Layout, Buffer, Idx); - - StreamWriter Writer(*InfoS); - if (auto EC = Writer.writeObject(*Header)) - return EC; - - auto RecordArray = VarStreamArray<codeview::CVType>(TypeRecordStream); - if (auto EC = Writer.writeArray(RecordArray)) - return EC; - - if (HashStreamIndex != kInvalidStreamIndex) { - auto HVS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer, - HashStreamIndex); - StreamWriter HW(*HVS); - if (auto EC = HW.writeStreamRef(*HashValueStream)) - return EC; - } - - return Error::success(); -} diff --git a/contrib/llvm/lib/DebugInfo/PDB/UDTLayout.cpp b/contrib/llvm/lib/DebugInfo/PDB/UDTLayout.cpp new file mode 100644 index 0000000..5f4390b --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/UDTLayout.cpp @@ -0,0 +1,303 @@ +//===- UDTLayout.cpp ------------------------------------------------------===// +// +// 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/UDTLayout.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/Support/Casting.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <memory> + +using namespace llvm; +using namespace llvm::pdb; + +static std::unique_ptr<PDBSymbol> getSymbolType(const PDBSymbol &Symbol) { + const IPDBSession &Session = Symbol.getSession(); + const IPDBRawSymbol &RawSymbol = Symbol.getRawSymbol(); + uint32_t TypeId = RawSymbol.getTypeId(); + return Session.getSymbolById(TypeId); +} + +static uint32_t getTypeLength(const PDBSymbol &Symbol) { + auto SymbolType = getSymbolType(Symbol); + const IPDBRawSymbol &RawType = SymbolType->getRawSymbol(); + + return RawType.getLength(); +} + +LayoutItemBase::LayoutItemBase(const UDTLayoutBase *Parent, + const PDBSymbol *Symbol, const std::string &Name, + uint32_t OffsetInParent, uint32_t Size, + bool IsElided) + : Symbol(Symbol), Parent(Parent), Name(Name), + OffsetInParent(OffsetInParent), SizeOf(Size), LayoutSize(Size), + IsElided(IsElided) { + UsedBytes.resize(SizeOf, true); +} + +uint32_t LayoutItemBase::deepPaddingSize() const { + return UsedBytes.size() - UsedBytes.count(); +} + +uint32_t LayoutItemBase::tailPadding() const { + int Last = UsedBytes.find_last(); + + return UsedBytes.size() - (Last + 1); +} + +DataMemberLayoutItem::DataMemberLayoutItem( + const UDTLayoutBase &Parent, std::unique_ptr<PDBSymbolData> Member) + : LayoutItemBase(&Parent, Member.get(), Member->getName(), + Member->getOffset(), getTypeLength(*Member), false), + DataMember(std::move(Member)) { + auto Type = DataMember->getType(); + if (auto UDT = unique_dyn_cast<PDBSymbolTypeUDT>(Type)) { + UdtLayout = llvm::make_unique<ClassLayout>(std::move(UDT)); + UsedBytes = UdtLayout->usedBytes(); + } +} + +VBPtrLayoutItem::VBPtrLayoutItem(const UDTLayoutBase &Parent, + std::unique_ptr<PDBSymbolTypeBuiltin> Sym, + uint32_t Offset, uint32_t Size) + : LayoutItemBase(&Parent, Sym.get(), "<vbptr>", Offset, Size, false), + Type(std::move(Sym)) { +} + +const PDBSymbolData &DataMemberLayoutItem::getDataMember() { + return *dyn_cast<PDBSymbolData>(Symbol); +} + +bool DataMemberLayoutItem::hasUDTLayout() const { return UdtLayout != nullptr; } + +const ClassLayout &DataMemberLayoutItem::getUDTLayout() const { + return *UdtLayout; +} + +VTableLayoutItem::VTableLayoutItem(const UDTLayoutBase &Parent, + std::unique_ptr<PDBSymbolTypeVTable> VT) + : LayoutItemBase(&Parent, VT.get(), "<vtbl>", 0, getTypeLength(*VT), false), + VTable(std::move(VT)) { + auto VTableType = cast<PDBSymbolTypePointer>(VTable->getType()); + ElementSize = VTableType->getLength(); +} + +UDTLayoutBase::UDTLayoutBase(const UDTLayoutBase *Parent, const PDBSymbol &Sym, + const std::string &Name, uint32_t OffsetInParent, + uint32_t Size, bool IsElided) + : LayoutItemBase(Parent, &Sym, Name, OffsetInParent, Size, IsElided) { + // UDT storage comes from a union of all the children's storage, so start out + // uninitialized. + UsedBytes.reset(0, Size); + + initializeChildren(Sym); + if (LayoutSize < Size) + UsedBytes.resize(LayoutSize); +} + +uint32_t UDTLayoutBase::tailPadding() const { + uint32_t Abs = LayoutItemBase::tailPadding(); + if (!LayoutItems.empty()) { + const LayoutItemBase *Back = LayoutItems.back(); + uint32_t ChildPadding = Back->LayoutItemBase::tailPadding(); + if (Abs < ChildPadding) + Abs = 0; + else + Abs -= ChildPadding; + } + return Abs; +} + +ClassLayout::ClassLayout(const PDBSymbolTypeUDT &UDT) + : UDTLayoutBase(nullptr, UDT, UDT.getName(), 0, UDT.getLength(), false), + UDT(UDT) { + ImmediateUsedBytes.resize(SizeOf, false); + for (auto &LI : LayoutItems) { + uint32_t Begin = LI->getOffsetInParent(); + uint32_t End = Begin + LI->getLayoutSize(); + End = std::min(SizeOf, End); + ImmediateUsedBytes.set(Begin, End); + } +} + +ClassLayout::ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT) + : ClassLayout(*UDT) { + OwnedStorage = std::move(UDT); +} + +uint32_t ClassLayout::immediatePadding() const { + return SizeOf - ImmediateUsedBytes.count(); +} + +BaseClassLayout::BaseClassLayout(const UDTLayoutBase &Parent, + uint32_t OffsetInParent, bool Elide, + std::unique_ptr<PDBSymbolTypeBaseClass> B) + : UDTLayoutBase(&Parent, *B, B->getName(), OffsetInParent, B->getLength(), + Elide), + Base(std::move(B)) { + if (isEmptyBase()) { + // Special case an empty base so that it doesn't get treated as padding. + UsedBytes.resize(1); + UsedBytes.set(0); + } + IsVirtualBase = Base->isVirtualBaseClass(); +} + +void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) { + // Handled bases first, followed by VTables, followed by data members, + // followed by functions, followed by other. This ordering is necessary + // so that bases and vtables get initialized before any functions which + // may override them. + UniquePtrVector<PDBSymbolTypeBaseClass> Bases; + UniquePtrVector<PDBSymbolTypeVTable> VTables; + UniquePtrVector<PDBSymbolData> Members; + UniquePtrVector<PDBSymbolTypeBaseClass> VirtualBaseSyms; + + auto Children = Sym.findAllChildren(); + while (auto Child = Children->getNext()) { + if (auto Base = unique_dyn_cast<PDBSymbolTypeBaseClass>(Child)) { + if (Base->isVirtualBaseClass()) + VirtualBaseSyms.push_back(std::move(Base)); + else + Bases.push_back(std::move(Base)); + } + else if (auto Data = unique_dyn_cast<PDBSymbolData>(Child)) { + if (Data->getDataKind() == PDB_DataKind::Member) + Members.push_back(std::move(Data)); + else + Other.push_back(std::move(Data)); + } else if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child)) + VTables.push_back(std::move(VT)); + else if (auto Func = unique_dyn_cast<PDBSymbolFunc>(Child)) + Funcs.push_back(std::move(Func)); + else { + Other.push_back(std::move(Child)); + } + } + + // We don't want to have any re-allocations in the list of bases, so make + // sure to reserve enough space so that our ArrayRefs don't get invalidated. + AllBases.reserve(Bases.size() + VirtualBaseSyms.size()); + + // Only add non-virtual bases to the class first. Only at the end of the + // class, after all non-virtual bases and data members have been added do we + // add virtual bases. This way the offsets are correctly aligned when we go + // to lay out virtual bases. + for (auto &Base : Bases) { + uint32_t Offset = Base->getOffset(); + // Non-virtual bases never get elided. + auto BL = llvm::make_unique<BaseClassLayout>(*this, Offset, false, + std::move(Base)); + + AllBases.push_back(BL.get()); + addChildToLayout(std::move(BL)); + } + NonVirtualBases = AllBases; + + assert(VTables.size() <= 1); + if (!VTables.empty()) { + auto VTLayout = + llvm::make_unique<VTableLayoutItem>(*this, std::move(VTables[0])); + + VTable = VTLayout.get(); + + addChildToLayout(std::move(VTLayout)); + } + + for (auto &Data : Members) { + auto DM = llvm::make_unique<DataMemberLayoutItem>(*this, std::move(Data)); + + addChildToLayout(std::move(DM)); + } + + // Make sure add virtual bases before adding functions, since functions may be + // overrides of virtual functions declared in a virtual base, so the VTables + // and virtual intros need to be correctly initialized. + for (auto &VB : VirtualBaseSyms) { + int VBPO = VB->getVirtualBasePointerOffset(); + if (!hasVBPtrAtOffset(VBPO)) { + if (auto VBP = VB->getRawSymbol().getVirtualBaseTableType()) { + auto VBPL = llvm::make_unique<VBPtrLayoutItem>(*this, std::move(VBP), + VBPO, VBP->getLength()); + VBPtr = VBPL.get(); + addChildToLayout(std::move(VBPL)); + } + } + + // Virtual bases always go at the end. So just look for the last place we + // ended when writing something, and put our virtual base there. + // Note that virtual bases get elided unless this is a top-most derived + // class. + uint32_t Offset = UsedBytes.find_last() + 1; + bool Elide = (Parent != nullptr); + auto BL = + llvm::make_unique<BaseClassLayout>(*this, Offset, Elide, std::move(VB)); + AllBases.push_back(BL.get()); + + // Only lay this virtual base out directly inside of *this* class if this + // is a top-most derived class. Keep track of it regardless, but only + // physically lay it out if it's a topmost derived class. + addChildToLayout(std::move(BL)); + } + VirtualBases = makeArrayRef(AllBases).drop_front(NonVirtualBases.size()); + + if (Parent != nullptr) + LayoutSize = UsedBytes.find_last() + 1; +} + +bool UDTLayoutBase::hasVBPtrAtOffset(uint32_t Off) const { + if (VBPtr && VBPtr->getOffsetInParent() == Off) + return true; + for (BaseClassLayout *BL : AllBases) { + if (BL->hasVBPtrAtOffset(Off - BL->getOffsetInParent())) + return true; + } + return false; +} + +void UDTLayoutBase::addChildToLayout(std::unique_ptr<LayoutItemBase> Child) { + uint32_t Begin = Child->getOffsetInParent(); + + if (!Child->isElided()) { + BitVector ChildBytes = Child->usedBytes(); + + // Suppose the child occupies 4 bytes starting at offset 12 in a 32 byte + // class. When we call ChildBytes.resize(32), the Child's storage will + // still begin at offset 0, so we need to shift it left by offset bytes + // to get it into the right position. + ChildBytes.resize(UsedBytes.size()); + ChildBytes <<= Child->getOffsetInParent(); + UsedBytes |= ChildBytes; + + if (ChildBytes.count() > 0) { + auto Loc = std::upper_bound(LayoutItems.begin(), LayoutItems.end(), Begin, + [](uint32_t Off, const LayoutItemBase *Item) { + return (Off < Item->getOffsetInParent()); + }); + + LayoutItems.insert(Loc, Child.get()); + } + } + + ChildStorage.push_back(std::move(Child)); +} |