diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:01:22 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:01:22 +0000 |
commit | 71d5a2540a98c81f5bcaeb48805e0e2881f530ef (patch) | |
tree | 5343938942df402b49ec7300a1c25a2d4ccd5821 /lib/DebugInfo/PDB | |
parent | 31bbf64f3a4974a2d6c8b3b27ad2f519caf74057 (diff) |
Diffstat (limited to 'lib/DebugInfo/PDB')
70 files changed, 2901 insertions, 936 deletions
diff --git a/lib/DebugInfo/PDB/CMakeLists.txt b/lib/DebugInfo/PDB/CMakeLists.txt index 599f01eaf74f..f87a0b0a72e2 100644 --- a/lib/DebugInfo/PDB/CMakeLists.txt +++ b/lib/DebugInfo/PDB/CMakeLists.txt @@ -27,31 +27,38 @@ if(LLVM_ENABLE_DIA_SDK) set(LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB/DIA") endif() -add_pdb_impl_folder(Raw - Raw/DbiStream.cpp - Raw/DbiStreamBuilder.cpp - Raw/EnumTables.cpp - Raw/GlobalsStream.cpp - Raw/GSI.cpp - Raw/Hash.cpp - Raw/InfoStream.cpp - Raw/InfoStreamBuilder.cpp - Raw/ModInfo.cpp - Raw/ModStream.cpp - Raw/NameHashTable.cpp - Raw/NameMap.cpp - Raw/NameMapBuilder.cpp - Raw/PDBFile.cpp - Raw/PDBFileBuilder.cpp - Raw/PublicsStream.cpp - Raw/RawError.cpp - Raw/RawSession.cpp - Raw/SymbolStream.cpp - Raw/TpiHashing.cpp - Raw/TpiStream.cpp - Raw/TpiStreamBuilder.cpp) +add_pdb_impl_folder(Native + Native/DbiStream.cpp + Native/DbiStreamBuilder.cpp + Native/EnumTables.cpp + Native/GlobalsStream.cpp + Native/GSI.cpp + Native/Hash.cpp + Native/HashTable.cpp + Native/InfoStream.cpp + Native/InfoStreamBuilder.cpp + Native/ModInfo.cpp + Native/ModInfoBuilder.cpp + Native/ModStream.cpp + Native/NativeCompilandSymbol.cpp + Native/NativeEnumModules.cpp + Native/NativeExeSymbol.cpp + Native/NativeRawSymbol.cpp + Native/NamedStreamMap.cpp + Native/NativeSession.cpp + Native/PDBFile.cpp + Native/PDBFileBuilder.cpp + Native/PDBTypeServerHandler.cpp + Native/PublicsStream.cpp + Native/RawError.cpp + Native/StringTable.cpp + Native/StringTableBuilder.cpp + Native/SymbolStream.cpp + Native/TpiHashing.cpp + Native/TpiStream.cpp + Native/TpiStreamBuilder.cpp) -list(APPEND LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB/Raw") +list(APPEND LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB/Native") list(APPEND LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB") add_llvm_library(LLVMDebugInfoPDB @@ -94,6 +101,7 @@ add_llvm_library(LLVMDebugInfoPDB PDBSymbolUnknown.cpp PDBSymbolUsingNamespace.cpp PDBSymDumper.cpp + UDTLayout.cpp ${PDB_IMPL_SOURCES} ADDITIONAL_HEADER_DIRS diff --git a/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp index bba5b0f94dca..5e8c0bdc171d 100644 --- a/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp +++ b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp @@ -10,9 +10,13 @@ #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/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" @@ -178,9 +182,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; } } @@ -715,6 +720,18 @@ uint32_t DIARawSymbol::getVirtualTableShapeId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualTableShapeId); } +std::unique_ptr<PDBSymbolTypeVTable> +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<PDBSymbolTypeVTable>(Pointer->getPointeeType()); +} + PDB_DataKind DIARawSymbol::getDataKind() const { return PrivateGetDIAValue<DWORD, PDB_DataKind>(Symbol, &IDiaSymbol::get_dataKind); diff --git a/lib/DebugInfo/PDB/Raw/DbiStream.cpp b/lib/DebugInfo/PDB/Native/DbiStream.cpp index 4f4a0cf65785..b9f53578d326 100644 --- a/lib/DebugInfo/PDB/Raw/DbiStream.cpp +++ b/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/ISectionContribVisitor.h" +#include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/ModInfo.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, @@ -127,8 +125,8 @@ Error DbiStream::reload() { return EC; if (auto EC = Reader.readStreamRef(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 = initializeSectionContributionData()) @@ -147,7 +145,7 @@ Error DbiStream::reload() { "Found unexpected bytes in DBI Stream."); if (ECSubstream.getLength() > 0) { - StreamReader ECReader(ECSubstream); + BinaryStreamReader ECReader(ECSubstream); if (auto EC = ECNames.load(ECReader)) return EC; } @@ -209,16 +207,16 @@ 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 { +FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const { return SectionMap; } @@ -237,7 +235,7 @@ Error DbiStream::initializeSectionContributionData() { if (SecContrSubstream.getLength() == 0) return Error::success(); - StreamReader SCReader(SecContrSubstream); + BinaryStreamReader SCReader(SecContrSubstream); if (auto EC = SCReader.readEnum(SectionContribVersion)) return EC; @@ -256,7 +254,7 @@ Error DbiStream::initializeModInfoArray() { // 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); + BinaryStreamReader Reader(ModInfoSubstream); VarStreamArray<ModInfo> ModInfoArray; if (auto EC = Reader.readArray(ModInfoArray, ModInfoSubstream.getLength())) @@ -286,7 +284,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."); @@ -318,7 +316,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."); @@ -330,7 +328,7 @@ Error DbiStream::initializeSectionMapData() { if (SecMapSubstream.getLength() == 0) return Error::success(); - StreamReader SMReader(SecMapSubstream); + BinaryStreamReader SMReader(SecMapSubstream); const SecMapHeader *Header; if (auto EC = SMReader.readObject(Header)) return EC; @@ -344,7 +342,7 @@ Error DbiStream::initializeFileInfo() { return Error::success(); const FileInfoSubstreamHeader *FH; - StreamReader FISR(FileInfoSubstream); + BinaryStreamReader FISR(FileInfoSubstream); if (auto EC = FISR.readObject(FH)) return EC; @@ -413,14 +411,14 @@ uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const { } Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const { - StreamReader Names(NamesBuffer); + BinaryStreamReader 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)) + if (auto EC = Names.readCString(Name)) return std::move(EC); return Name; } diff --git a/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp index 1d5b8d693b1e..a203aea60fe7 100644 --- a/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -7,15 +7,16 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h" +#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" #include "llvm/ADT/ArrayRef.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/DbiStream.h" +#include "llvm/DebugInfo/PDB/Native/ModInfoBuilder.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/Object/COFF.h" +#include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/COFF.h" using namespace llvm; @@ -23,15 +24,13 @@ 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; } @@ -75,39 +74,37 @@ uint32_t DbiStreamBuilder::calculateSerializedLength() const { calculateSectionMapStreamSize() + calculateDbgStreamsSize(); } -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<ModInfoBuilder &> +DbiStreamBuilder::addModuleInfo(StringRef ModuleName) { + uint32_t Index = ModiList.size(); + auto MIB = llvm::make_unique<ModInfoBuilder>(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"); uint32_t Index = SourceFileNames.size(); SourceFileNames.insert(std::make_pair(File, Index)); auto &ModEntry = *ModIter; - ModEntry.second->SourceFiles.push_back(File); + ModEntry.second->addSourceFile(File); return Error::success(); } 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 { @@ -127,11 +124,11 @@ 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 + Size += ModiList.size() * sizeof(ulittle16_t); // ModIndices + Size += ModiList.size() * sizeof(ulittle16_t); // ModFileCounts uint32_t NumFileInfos = 0; - for (const auto &M : ModuleInfoList) - NumFileInfos += M->SourceFiles.size(); + for (const auto &M : ModiList) + NumFileInfos += M->source_files().size(); Size += NumFileInfos * sizeof(ulittle32_t); // FileNameOffsets Size += calculateNamesBufferSize(); return alignTo(Size, sizeof(uint32_t)); @@ -149,43 +146,20 @@ 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; - 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 +169,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 +179,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, @@ -240,13 +214,13 @@ 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>(); H->VersionHeader = *VerHeader; H->VersionSignature = -1; H->Age = Age; @@ -258,7 +232,7 @@ Error DbiStreamBuilder::finalize() { H->ECSubstreamSize = 0; H->FileInfoSize = FileInfoBuffer.getLength(); - H->ModiSubstreamSize = ModInfoBuffer.getLength(); + H->ModiSubstreamSize = calculateModiSubstreamSize(); H->OptionalDbgHdrSize = DbgStreams.size() * sizeof(uint16_t); H->SecContrSubstreamSize = calculateSectionContribsStreamSize(); H->SectionMapSize = calculateSectionMapStreamSize(); @@ -273,6 +247,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; @@ -358,19 +337,21 @@ 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); - 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)) @@ -399,8 +380,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); + BinaryStreamWriter DbgStreamWriter(*WritableStream); if (auto EC = DbgStreamWriter.writeArray(Stream.Data)) return EC; } diff --git a/lib/DebugInfo/PDB/Raw/EnumTables.cpp b/lib/DebugInfo/PDB/Native/EnumTables.cpp index fc9270c69947..b3837dc72e5b 100644 --- a/lib/DebugInfo/PDB/Raw/EnumTables.cpp +++ b/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/lib/DebugInfo/PDB/Raw/GSI.cpp b/lib/DebugInfo/PDB/Native/GSI.cpp index 6ecbb5c8cfad..b219fe275f73 100644 --- a/lib/DebugInfo/PDB/Raw/GSI.cpp +++ b/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/lib/DebugInfo/PDB/Raw/GSI.h b/lib/DebugInfo/PDB/Native/GSI.h index 82cebd946538..9e63bc83548f 100644 --- a/lib/DebugInfo/PDB/Raw/GSI.h +++ b/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/lib/DebugInfo/PDB/Raw/GlobalsStream.cpp b/lib/DebugInfo/PDB/Native/GlobalsStream.cpp index 31afc9200b1b..a2ee0f047c58 100644 --- a/lib/DebugInfo/PDB/Raw/GlobalsStream.cpp +++ b/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/lib/DebugInfo/PDB/Raw/Hash.cpp b/lib/DebugInfo/PDB/Native/Hash.cpp index b9f685ec69d4..2ad3f55dc5c3 100644 --- a/lib/DebugInfo/PDB/Raw/Hash.cpp +++ b/lib/DebugInfo/PDB/Native/Hash.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/Raw/Hash.h" +#include "llvm/DebugInfo/PDB/Native/Hash.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Endian.h" diff --git a/lib/DebugInfo/PDB/Native/HashTable.cpp b/lib/DebugInfo/PDB/Native/HashTable.cpp new file mode 100644 index 000000000000..ebf8c9c04db1 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/HashTable.cpp @@ -0,0 +1,302 @@ +//===- HashTable.cpp - PDB 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/Native/HashTable.h" + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SparseBitVector.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" + +#include <assert.h> + +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/lib/DebugInfo/PDB/Native/InfoStream.cpp b/lib/DebugInfo/PDB/Native/InfoStream.cpp new file mode 100644 index 000000000000..2a1d12e82390 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/InfoStream.cpp @@ -0,0 +1,126 @@ +//===- 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; + + 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; + 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(); +} + +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; } + +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; +} diff --git a/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp index 73fbf853b4f7..f019d410328a 100644 --- a/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp @@ -7,22 +7,26 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h" +#include "llvm/DebugInfo/PDB/Native/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" +#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) - : Msf(Msf), Ver(PdbRaw_ImplVer::PdbImplVC70), Sig(-1), Age(0) {} +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; } @@ -32,26 +36,23 @@ 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(); +void InfoStreamBuilder::addFeature(PdbRaw_FeatureSig Sig) { + Features.push_back(Sig); } Error InfoStreamBuilder::finalizeMsfLayout() { - uint32_t Length = calculateSerializedLength(); + 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, - const msf::WritableStream &Buffer) const { + WritableBinaryStreamRef Buffer) const { auto InfoS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamPDB); - StreamWriter Writer(*InfoS); + BinaryStreamWriter Writer(*InfoS); InfoStreamHeader H; H.Age = Age; @@ -61,5 +62,13 @@ Error InfoStreamBuilder::commit(const msf::MSFLayout &Layout, if (auto EC = Writer.writeObject(H)) return EC; - return NamedStreams.commit(Writer); + 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/lib/DebugInfo/PDB/Raw/ModInfo.cpp b/lib/DebugInfo/PDB/Native/ModInfo.cpp index b34d7700d036..1405286fd088 100644 --- a/lib/DebugInfo/PDB/Raw/ModInfo.cpp +++ b/lib/DebugInfo/PDB/Native/ModInfo.cpp @@ -7,16 +7,15 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/MSF/StreamReader.h" -#include "llvm/DebugInfo/PDB/Raw/ModInfo.h" -#include "llvm/DebugInfo/PDB/Raw/RawTypes.h" +#include "llvm/DebugInfo/PDB/Native/ModInfo.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::msf; using namespace llvm::pdb; using namespace llvm::support; @@ -26,15 +25,15 @@ ModInfo::ModInfo(const ModInfo &Info) = default; ModInfo::~ModInfo() = default; -Error ModInfo::initialize(ReadableStreamRef Stream, ModInfo &Info) { - StreamReader Reader(Stream); +Error ModInfo::initialize(BinaryStreamRef Stream, ModInfo &Info) { + BinaryStreamReader Reader(Stream); if (auto EC = Reader.readObject(Info.Layout)) return EC; - if (auto EC = Reader.readZeroString(Info.ModuleName)) + if (auto EC = Reader.readCString(Info.ModuleName)) return EC; - if (auto EC = Reader.readZeroString(Info.ObjFileName)) + if (auto EC = Reader.readCString(Info.ObjFileName)) return EC; return Error::success(); } diff --git a/lib/DebugInfo/PDB/Native/ModInfoBuilder.cpp b/lib/DebugInfo/PDB/Native/ModInfoBuilder.cpp new file mode 100644 index 000000000000..73c45a953520 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/ModInfoBuilder.cpp @@ -0,0 +1,136 @@ +//===- ModInfoBuilder.cpp - PDB Module 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/ModInfoBuilder.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/MSF/MSFBuilder.h" +#include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/ModInfo.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" +#include "llvm/Support/COFF.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 Size = sizeof(uint32_t); // Signature + Size += SymbolByteSize; // Symbol Data + Size += 0; // TODO: Layout.LineBytes + Size += 0; // TODO: Layout.C13Bytes + Size += sizeof(uint32_t); // GlobalRefs substream size (always 0) + Size += 0; // GlobalRefs substream bytes + return Size; +} + +ModInfoBuilder::ModInfoBuilder(StringRef ModuleName, uint32_t ModIndex, + msf::MSFBuilder &Msf) + : MSF(Msf), ModuleName(ModuleName) { + Layout.Mod = ModIndex; +} + +uint16_t ModInfoBuilder::getStreamIndex() const { return Layout.ModDiStream; } + +void ModInfoBuilder::setObjFileName(StringRef Name) { ObjFileName = Name; } + +void ModInfoBuilder::addSymbol(CVSymbol Symbol) { + Symbols.push_back(Symbol); + SymbolByteSize += Symbol.data().size(); +} + +void ModInfoBuilder::addSourceFile(StringRef Path) { + SourceFiles.push_back(Path); +} + +uint32_t ModInfoBuilder::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)); +} + +void ModInfoBuilder::finalize() { + Layout.C13Bytes = 0; + Layout.FileNameOffs = 0; // TODO: Fix this + Layout.Flags = 0; // TODO: Fix this + Layout.LineBytes = 0; + (void)Layout.Mod; // Set in constructor + (void)Layout.ModDiStream; // Set in finalizeMsfLayout + Layout.NumFiles = SourceFiles.size(); + Layout.PdbFilePathNI = 0; + 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 ModInfoBuilder::finalizeMsfLayout() { + this->Layout.ModDiStream = kInvalidStreamIndex; + auto ExpectedSN = MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize)); + if (!ExpectedSN) + return ExpectedSN.takeError(); + Layout.ModDiStream = *ExpectedSN; + return Error::success(); +} + +Error ModInfoBuilder::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); + 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; + // TODO: Write C11 Line data + // TODO: Write C13 Line data + // 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(); +} diff --git a/lib/DebugInfo/PDB/Raw/ModStream.cpp b/lib/DebugInfo/PDB/Native/ModStream.cpp index 0ffc5b7d44aa..08798cf0ed28 100644 --- a/lib/DebugInfo/PDB/Raw/ModStream.cpp +++ b/lib/DebugInfo/PDB/Native/ModStream.cpp @@ -7,15 +7,15 @@ // //===----------------------------------------------------------------------===// +#include "llvm/DebugInfo/PDB/Native/ModStream.h" #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/DebugInfo/PDB/Native/ModInfo.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/Error.h" #include <algorithm> #include <cstdint> @@ -31,7 +31,7 @@ ModStream::ModStream(const ModInfo &Module, ModStream::~ModStream() = default; Error ModStream::reload() { - StreamReader Reader(*Stream); + BinaryStreamReader Reader(*Stream); uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize(); uint32_t C11Size = Mod.getLineInfoByteSize(); @@ -41,7 +41,7 @@ Error ModStream::reload() { return make_error<RawError>(raw_error_code::corrupt_file, "Module has both C11 and C13 line info"); - ReadableStreamRef S; + BinaryStreamRef S; if (auto EC = Reader.readInteger(Signature)) return EC; @@ -53,7 +53,7 @@ Error ModStream::reload() { if (auto EC = Reader.readStreamRef(C13LinesSubstream, C13Size)) return EC; - StreamReader LineReader(C13LinesSubstream); + BinaryStreamReader LineReader(C13LinesSubstream); if (auto EC = LineReader.readArray(LineInfo, LineReader.bytesRemaining())) return EC; diff --git a/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp b/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp new file mode 100644 index 000000000000..c7ba32b82bc6 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp @@ -0,0 +1,135 @@ +//===- NamedStreamMap.cpp - PDB Named Stream 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/DebugInfo/PDB/Native/NamedStreamMap.h" + +#include "llvm/ADT/SparseBitVector.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/Error.h" +#include <algorithm> +#include <cstdint> + +using namespace llvm; +using namespace llvm::pdb; + +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; + + // Now all of the string data itself. + for (const auto &Item : Mapping) { + 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 &Item : Mapping) { + 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/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp new file mode 100644 index 000000000000..9c0cc0bf8233 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp @@ -0,0 +1,43 @@ +//===- 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" + +namespace llvm { +namespace pdb { + +NativeCompilandSymbol::NativeCompilandSymbol(NativeSession &Session, + const ModuleInfoEx &MI) + : NativeRawSymbol(Session), Module(MI) {} + +PDB_SymType NativeCompilandSymbol::getSymTag() const { + return PDB_SymType::Compiland; +} + +bool NativeCompilandSymbol::isEditAndContinueEnabled() const { + return Module.Info.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.Info.getObjFileName(); +} + +std::string NativeCompilandSymbol::getName() const { + return Module.Info.getModuleName(); +} + +} // namespace pdb +} // namespace llvm diff --git a/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp b/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp new file mode 100644 index 000000000000..7532110d005c --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp @@ -0,0 +1,52 @@ +//==- 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/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, + ArrayRef<ModuleInfoEx> Modules, + uint32_t Index) + : Session(PDBSession), Modules(Modules), Index(Index) {} + +uint32_t NativeEnumModules::getChildCount() const { + return static_cast<uint32_t>(Modules.size()); +} + +std::unique_ptr<PDBSymbol> +NativeEnumModules::getChildAtIndex(uint32_t Index) const { + if (Index >= Modules.size()) + return nullptr; + return std::unique_ptr<PDBSymbol>(new PDBSymbolCompiland(Session, + std::unique_ptr<IPDBRawSymbol>( + new NativeCompilandSymbol(Session, Modules[Index])))); +} + +std::unique_ptr<PDBSymbol> NativeEnumModules::getNext() { + if (Index >= Modules.size()) + return nullptr; + return getChildAtIndex(Index++); +} + +void NativeEnumModules::reset() { Index = 0; } + +NativeEnumModules *NativeEnumModules::clone() const { + return new NativeEnumModules(Session, Modules, Index); +} + +} +} diff --git a/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp new file mode 100644 index 000000000000..ec2a4b87457c --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp @@ -0,0 +1,79 @@ +//===- 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/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) + : NativeRawSymbol(Session), File(Session.getPDBFile()) {} + +std::unique_ptr<IPDBEnumSymbols> +NativeExeSymbol::findChildren(PDB_SymType Type) const { + switch (Type) { + case PDB_SymType::Compiland: { + auto Dbi = File.getPDBDbiStream(); + if (Dbi) { + const auto 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(); +} + +PDB_UniqueId NativeExeSymbol::getGuid() const { + auto IS = File.getPDBInfoStream(); + if (IS) + return IS->getGuid(); + consumeError(IS.takeError()); + return PDB_UniqueId{{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/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp new file mode 100644 index 000000000000..3aba35adb53f --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp @@ -0,0 +1,706 @@ +//===- NativeRawSymbol.cpp - Native implementation of IPDBRawSymbol -*- 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/NativeRawSymbol.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/PDBExtras.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h" +#include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; +using namespace llvm::pdb; + +NativeRawSymbol::NativeRawSymbol(NativeSession &PDBSession) + : Session(PDBSession) {} + +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(llvm::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 0; +} + +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 0; +} + +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 0; +} + +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 0; +} + +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 0; +} + +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<PDBSymbolTypeVTable> +NativeRawSymbol::getVirtualBaseTableType() const { + return nullptr; +} + +PDB_DataKind NativeRawSymbol::getDataKind() const { + return PDB_DataKind::Unknown; +} + +PDB_SymType NativeRawSymbol::getSymTag() const { + return PDB_SymType::None; +} + +PDB_UniqueId NativeRawSymbol::getGuid() const { + return PDB_UniqueId{{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/lib/DebugInfo/PDB/Native/NativeSession.cpp b/lib/DebugInfo/PDB/Native/NativeSession.cpp new file mode 100644 index 000000000000..7e6843bceb7d --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -0,0 +1,146 @@ +//===- 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/PDB/GenericError.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBSourceFile.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> + +using namespace llvm; +using namespace llvm::msf; +using namespace llvm::pdb; + +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); +} + +uint64_t NativeSession::getLoadAddress() const { return 0; } + +void NativeSession::setLoadAddress(uint64_t Address) {} + +std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() const { + auto RawSymbol = + llvm::make_unique<NativeExeSymbol>(const_cast<NativeSession &>(*this)); + 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 { + return 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/lib/DebugInfo/PDB/Raw/PDBFile.cpp b/lib/DebugInfo/PDB/Native/PDBFile.cpp index 53491518b8c7..943e7fa13ab7 100644 --- a/lib/DebugInfo/PDB/Raw/PDBFile.cpp +++ b/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/PublicsStream.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/StringTable.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; @@ -140,7 +147,7 @@ Error PDBFile::parseFileHeaders() { // 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); + BinaryStreamReader FpmReader(*FpmStream); ArrayRef<uint8_t> FpmBytes; if (auto EC = FpmReader.readBytes(FpmBytes, msf::getFullFpmByteSize(ContainerLayout))) @@ -178,7 +185,7 @@ Error PDBFile::parseStreamData() { // 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); + BinaryStreamReader Reader(*DS); if (auto EC = Reader.readInteger(NumStreams)) return EC; @@ -229,7 +236,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 +249,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 +262,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 +275,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 +288,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 +306,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 +326,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 +337,8 @@ Expected<SymbolStream &> PDBFile::getPDBSymbolStream() { return *Symbols; } -Expected<NameHashTable &> PDBFile::getStringTable() { - if (!StringTable || !StringTableStream) { +Expected<StringTable &> PDBFile::getStringTable() { + if (!Strings || !StringTableStream) { auto IS = getPDBInfoStream(); if (!IS) return IS.takeError(); @@ -333,23 +347,25 @@ 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>(); + BinaryStreamReader Reader(**NS); + auto N = llvm::make_unique<StringTable>(); if (auto EC = N->load(Reader)) return std::move(EC); - StringTable = std::move(N); + Strings = std::move(N); StringTableStream = std::move(*NS); } - return *StringTable; + return *Strings; } bool PDBFile::hasPDBDbiStream() const { return StreamDBI < getNumStreams(); } bool PDBFile::hasPDBGlobalsStream() { auto DbiS = getPDBDbiStream(); - if (!DbiS) return false; + if (!DbiS) + return false; return DbiS->getGlobalSymbolStreamIndex() < getNumStreams(); } @@ -359,13 +375,15 @@ bool PDBFile::hasPDBIpiStream() const { return StreamIPI < getNumStreams(); } bool PDBFile::hasPDBPublicsStream() { auto DbiS = getPDBDbiStream(); - if (!DbiS) return false; + if (!DbiS) + return false; return DbiS->getPublicSymbolStreamIndex() < getNumStreams(); } bool PDBFile::hasPDBSymbolStream() { auto DbiS = getPDBDbiStream(); - if (!DbiS) return false; + if (!DbiS) + return false; return DbiS->getSymRecordStreamIndex() < getNumStreams(); } @@ -373,18 +391,19 @@ bool PDBFile::hasPDBTpiStream() const { return StreamTPI < getNumStreams(); } bool PDBFile::hasStringTable() { 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); diff --git a/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp index 6fec0e32a8ae..b3c84903bc7e 100644 --- a/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp @@ -7,21 +7,22 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h" +#include "llvm/DebugInfo/PDB/Native/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" +#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/RawError.h" +#include "llvm/DebugInfo/PDB/Native/StringTableBuilder.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; @@ -44,7 +45,7 @@ MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; } InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() { if (!Info) - Info = llvm::make_unique<InfoStreamBuilder>(*Msf); + Info = llvm::make_unique<InfoStreamBuilder>(*Msf, NamedStreams); return *Info; } @@ -66,7 +67,26 @@ TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() { return *Ipi; } -Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() const { +StringTableBuilder &PDBFileBuilder::getStringTableBuilder() { return Strings; } + +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() { + uint32_t StringTableSize = Strings.finalize(); + + if (auto EC = addNamedStream("/names", StringTableSize)) + return std::move(EC); + if (auto EC = addNamedStream("/LinkInfo", 0)) + return std::move(EC); + if (auto EC = addNamedStream("/src/headerblock", 0)) + return std::move(EC); + if (Info) { if (auto EC = Info->finalizeMsfLayout()) return std::move(EC); @@ -98,8 +118,9 @@ Error PDBFileBuilder::commit(StringRef Filename) { if (OutFileOrError.getError()) return llvm::make_error<pdb::GenericError>(generic_error_code::invalid_path, Filename); - FileBufferByteStream Buffer(std::move(*OutFileOrError)); - StreamWriter Writer(Buffer); + FileBufferByteStream Buffer(std::move(*OutFileOrError), + llvm::support::little); + BinaryStreamWriter Writer(Buffer); if (auto EC = Writer.writeObject(*Layout.SB)) return EC; @@ -111,9 +132,8 @@ Error PDBFileBuilder::commit(StringRef Filename) { auto DirStream = WritableMappedBlockStream::createDirectoryStream(Layout, Buffer); - StreamWriter DW(*DirStream); - if (auto EC = - DW.writeInteger(static_cast<uint32_t>(Layout.StreamSizes.size()))) + BinaryStreamWriter DW(*DirStream); + if (auto EC = DW.writeInteger<uint32_t>(Layout.StreamSizes.size())) return EC; if (auto EC = DW.writeArray(Layout.StreamSizes)) @@ -124,6 +144,16 @@ Error PDBFileBuilder::commit(StringRef Filename) { return EC; } + uint32_t StringTableStreamNo = 0; + if (!NamedStreams.get("/names", StringTableStreamNo)) + return llvm::make_error<pdb::RawError>(raw_error_code::no_stream); + + auto NS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer, + StringTableStreamNo); + BinaryStreamWriter NSWriter(*NS); + if (auto EC = Strings.commit(NSWriter)) + return EC; + if (Info) { if (auto EC = Info->commit(Layout, Buffer)) return EC; diff --git a/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp b/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp new file mode 100644 index 000000000000..629f3e80b0ed --- /dev/null +++ b/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp @@ -0,0 +1,119 @@ +//===- PDBTypeServerHandler.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Handles CodeView LF_TYPESERVER2 records by attempting to locate a matching +// PDB file, then loading the PDB file and visiting all types from the +// referenced PDB using the original supplied visitor. +// +// The net effect of this is that when visiting a PDB containing a TypeServer +// record, the TypeServer record is "replaced" with all of the records in +// the referenced PDB file. If a single instance of PDBTypeServerHandler +// encounters the same TypeServer multiple times (for example reusing one +// PDBTypeServerHandler across multiple visitations of distinct object files or +// PDB files), PDBTypeServerHandler will optionally revisit all the records +// again, or simply consume the record and do nothing. +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h" + +#include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/DebugInfo/PDB/GenericError.h" +#include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" +#include "llvm/DebugInfo/PDB/PDB.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +static void ignoreErrors(Error EC) { + llvm::handleAllErrors(std::move(EC), [&](ErrorInfoBase &EIB) {}); +} + +PDBTypeServerHandler::PDBTypeServerHandler(bool RevisitAlways) + : RevisitAlways(RevisitAlways) {} + +void PDBTypeServerHandler::addSearchPath(StringRef Path) { + if (Path.empty() || !sys::fs::is_directory(Path)) + return; + + SearchPaths.push_back(Path); +} + +Expected<bool> +PDBTypeServerHandler::handleInternal(PDBFile &File, + TypeVisitorCallbacks &Callbacks) { + auto ExpectedTpi = File.getPDBTpiStream(); + if (!ExpectedTpi) + return ExpectedTpi.takeError(); + CVTypeVisitor Visitor(Callbacks); + + if (auto EC = Visitor.visitTypeStream(ExpectedTpi->types(nullptr))) + return std::move(EC); + + return true; +} + +Expected<bool> PDBTypeServerHandler::handle(TypeServer2Record &TS, + TypeVisitorCallbacks &Callbacks) { + if (Session) { + // If we've already handled this TypeServer and we only want to handle each + // TypeServer once, consume the record without doing anything. + if (!RevisitAlways) + return true; + + return handleInternal(Session->getPDBFile(), Callbacks); + } + + StringRef File = sys::path::filename(TS.Name); + if (File.empty()) + return make_error<CodeViewError>( + cv_error_code::corrupt_record, + "TypeServer2Record does not contain filename!"); + + for (auto Path : SearchPaths) { + sys::path::append(Path, File); + if (!sys::fs::exists(Path)) + continue; + + std::unique_ptr<IPDBSession> ThisSession; + if (auto EC = loadDataForPDB(PDB_ReaderType::Native, Path, ThisSession)) { + // It is not an error if this PDB fails to load, it just means that it + // doesn't match and we should continue searching. + ignoreErrors(std::move(EC)); + continue; + } + + std::unique_ptr<NativeSession> NS( + static_cast<NativeSession *>(ThisSession.release())); + PDBFile &File = NS->getPDBFile(); + auto ExpectedInfo = File.getPDBInfoStream(); + // All PDB Files should have an Info stream. + if (!ExpectedInfo) + return ExpectedInfo.takeError(); + + // Just because a file with a matching name was found and it was an actual + // PDB file doesn't mean it matches. For it to match the InfoStream's GUID + // must match the GUID specified in the TypeServer2 record. + ArrayRef<uint8_t> GuidBytes(ExpectedInfo->getGuid().Guid); + StringRef GuidStr(reinterpret_cast<const char *>(GuidBytes.begin()), + GuidBytes.size()); + if (GuidStr != TS.Guid) + continue; + + Session = std::move(NS); + return handleInternal(File, Callbacks); + } + + // We couldn't find a matching PDB, so let it be handled by someone else. + return false; +} diff --git a/lib/DebugInfo/PDB/Raw/PublicsStream.cpp b/lib/DebugInfo/PDB/Native/PublicsStream.cpp index b31f605a078c..58202577672a 100644 --- a/lib/DebugInfo/PDB/Raw/PublicsStream.cpp +++ b/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> @@ -69,7 +69,7 @@ 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)) diff --git a/lib/DebugInfo/PDB/Raw/RawError.cpp b/lib/DebugInfo/PDB/Native/RawError.cpp index f4a5057509eb..548289fff3df 100644 --- a/lib/DebugInfo/PDB/Raw/RawError.cpp +++ b/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/lib/DebugInfo/PDB/Raw/NameHashTable.cpp b/lib/DebugInfo/PDB/Native/StringTable.cpp index 84cccb354bd8..7e28389b8383 100644 --- a/lib/DebugInfo/PDB/Raw/NameHashTable.cpp +++ b/lib/DebugInfo/PDB/Native/StringTable.cpp @@ -1,4 +1,4 @@ -//===- NameHashTable.cpp - PDB Name Hash Table ------------------*- C++ -*-===// +//===- StringTable.cpp - PDB String Table -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,33 +7,29 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h" +#include "llvm/DebugInfo/PDB/Native/StringTable.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/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::msf; using namespace llvm::support; using namespace llvm::pdb; -NameHashTable::NameHashTable() : Signature(0), HashVersion(0), NameCount(0) {} +StringTable::StringTable() {} -Error NameHashTable::load(StreamReader &Stream) { - struct Header { - support::ulittle32_t Signature; - support::ulittle32_t HashVersion; - support::ulittle32_t ByteSize; - }; +Error StringTable::load(BinaryStreamReader &Stream) { + ByteSize = Stream.getLength(); - const Header *H; + const StringTableHeader *H; if (auto EC = Stream.readObject(H)) return EC; - if (H->Signature != 0xEFFEEFFE) + if (H->Signature != StringTableSignature) return make_error<RawError>(raw_error_code::corrupt_file, "Invalid hash table signature"); if (H->HashVersion != 1 && H->HashVersion != 2) @@ -62,10 +58,19 @@ Error NameHashTable::load(StreamReader &Stream) { if (auto EC = Stream.readInteger(NameCount)) return EC; + + if (Stream.bytesRemaining() > 0) + return make_error<RawError>(raw_error_code::stream_too_long, + "Unexpected bytes found in string table"); + return Error::success(); } -StringRef NameHashTable::getStringForID(uint32_t ID) const { +uint32_t StringTable::getByteSize() const { + return ByteSize; +} + +StringRef StringTable::getStringForID(uint32_t ID) const { if (ID == IDs[0]) return StringRef(); @@ -73,14 +78,14 @@ StringRef NameHashTable::getStringForID(uint32_t ID) const { // 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); + BinaryStreamReader NameReader(NamesBuffer); NameReader.setOffset(ID); - if (auto EC = NameReader.readZeroString(Result)) + if (auto EC = NameReader.readCString(Result)) consumeError(std::move(EC)); return Result; } -uint32_t NameHashTable::getIDForString(StringRef Str) const { +uint32_t StringTable::getIDForString(StringRef Str) const { uint32_t Hash = (HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str); size_t Count = IDs.size(); uint32_t Start = Hash % Count; @@ -99,6 +104,6 @@ uint32_t NameHashTable::getIDForString(StringRef Str) const { return IDs[0]; } -FixedStreamArray<support::ulittle32_t> NameHashTable::name_ids() const { +FixedStreamArray<support::ulittle32_t> StringTable::name_ids() const { return IDs; } diff --git a/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp b/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp new file mode 100644 index 000000000000..e0f8370ab608 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp @@ -0,0 +1,102 @@ +//===- StringTableBuilder.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/StringTableBuilder.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/PDB/Native/Hash.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::support; +using namespace llvm::support::endian; +using namespace llvm::pdb; + +uint32_t StringTableBuilder::insert(StringRef S) { + auto P = Strings.insert({S, StringSize}); + + // If a given string didn't exist in the string table, we want to increment + // the string table size. + if (P.second) + StringSize += S.size() + 1; // +1 for '\0' + return P.first->second; +} + +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 StringTableBuilder::finalize() { + uint32_t Size = 0; + Size += sizeof(StringTableHeader); + Size += StringSize; + Size += sizeof(uint32_t); // Hash table begins with 4-byte size field. + + uint32_t BucketCount = computeBucketCount(Strings.size()); + Size += BucketCount * sizeof(uint32_t); + + Size += + sizeof(uint32_t); // The /names stream ends with the number of strings. + return Size; +} + +Error StringTableBuilder::commit(BinaryStreamWriter &Writer) const { + // Write a header + StringTableHeader H; + H.Signature = StringTableSignature; + H.HashVersion = 1; + H.ByteSize = StringSize; + if (auto EC = Writer.writeObject(H)) + return EC; + + // Write a string table. + uint32_t StringStart = Writer.getOffset(); + for (auto Pair : Strings) { + StringRef S = Pair.first; + uint32_t Offset = Pair.second; + Writer.setOffset(StringStart + Offset); + if (auto EC = Writer.writeCString(S)) + return EC; + } + Writer.setOffset(StringStart + StringSize); + + // 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.first; + uint32_t Offset = Pair.second; + 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; + if (auto EC = Writer.writeInteger(static_cast<uint32_t>(Strings.size()))) + return EC; + return Error::success(); +} diff --git a/lib/DebugInfo/PDB/Raw/SymbolStream.cpp b/lib/DebugInfo/PDB/Native/SymbolStream.cpp index 2f3ac3497f39..9e9ebd11495b 100644 --- a/lib/DebugInfo/PDB/Raw/SymbolStream.cpp +++ b/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/lib/DebugInfo/PDB/Raw/TpiHashing.cpp b/lib/DebugInfo/PDB/Native/TpiHashing.cpp index 6c3ddb3d57af..16904a5a27ed 100644 --- a/lib/DebugInfo/PDB/Raw/TpiHashing.cpp +++ b/lib/DebugInfo/PDB/Native/TpiHashing.cpp @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/Raw/TpiHashing.h" +#include "llvm/DebugInfo/PDB/Native/TpiHashing.h" -#include "llvm/DebugInfo/PDB/Raw/Hash.h" -#include "llvm/DebugInfo/PDB/Raw/RawError.h" +#include "llvm/DebugInfo/PDB/Native/Hash.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" using namespace llvm; using namespace llvm::codeview; diff --git a/lib/DebugInfo/PDB/Raw/TpiStream.cpp b/lib/DebugInfo/PDB/Native/TpiStream.cpp index a1167cd98454..5fef3edf8c2d 100644 --- a/lib/DebugInfo/PDB/Raw/TpiStream.cpp +++ b/lib/DebugInfo/PDB/Native/TpiStream.cpp @@ -7,19 +7,20 @@ // //===----------------------------------------------------------------------===// +#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/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/PDBTypeServerHandler.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> @@ -53,7 +54,7 @@ Error TpiStream::verifyHashValues() { } Error TpiStream::reload() { - StreamReader Reader(*Stream); + BinaryStreamReader Reader(*Stream); if (Reader.bytesRemaining() < sizeof(TpiStreamHeader)) return make_error<RawError>(raw_error_code::corrupt_file, @@ -92,11 +93,12 @@ Error TpiStream::reload() { auto HS = MappedBlockStream::createIndexedStream( Pdb.getMsfLayout(), Pdb.getMsfBuffer(), Header->HashStreamIndex); - StreamReader HSR(*HS); + 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 != NumTypeRecords() && NumHashValues != 0) return make_error<RawError>( raw_error_code::corrupt_file, "TPI hash count does not match with the number of type records."); @@ -113,18 +115,19 @@ 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; + if (NumHashValues > 0) + if (auto EC = verifyHashValues()) + return EC; } return Error::success(); @@ -154,23 +157,17 @@ uint16_t TpiStream::getTypeHashStreamAuxIndex() const { uint32_t TpiStream::NumHashBuckets() const { return Header->NumHashBuckets; } uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; } -FixedStreamArray<support::ulittle32_t> -TpiStream::getHashValues() const { +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/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp index c769321f18c1..375c35b11145 100644 --- a/lib/DebugInfo/PDB/Raw/TpiStreamBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp @@ -7,22 +7,22 @@ // //===----------------------------------------------------------------------===// +#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/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/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> @@ -43,9 +43,22 @@ void TpiStreamBuilder::setVersionHeader(PdbRaw_TpiVer Version) { VerHeader = Version; } -void TpiStreamBuilder::addTypeRecord(const codeview::CVType &Record) { +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); - TypeRecordStream.setItems(TypeRecords); + if (Hash) + TypeHashes.push_back(*Hash); } Error TpiStreamBuilder::finalize() { @@ -55,13 +68,12 @@ Error TpiStreamBuilder::finalize() { 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->TypeRecordBytes = TypeRecordBytes; H->HashStreamIndex = HashStreamIndex; H->HashAuxStreamIndex = kInvalidStreamIndex; @@ -72,24 +84,32 @@ Error TpiStreamBuilder::finalize() { // 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->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 = 0; + H->IndexOffsetBuffer.Length = calculateIndexOffsetSize(); Header = H; return Error::success(); } -uint32_t TpiStreamBuilder::calculateSerializedLength() const { - return sizeof(TpiStreamHeader) + TypeRecordStream.getLength(); +uint32_t TpiStreamBuilder::calculateSerializedLength() { + return sizeof(TpiStreamHeader) + TypeRecordBytes; } uint32_t TpiStreamBuilder::calculateHashBufferSize() const { - if (TypeRecords.empty() || !TypeRecords[0].Hash.hasValue()) - return 0; - return TypeRecords.size() * sizeof(ulittle32_t); + 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(TypeIndexOffset); } Error TpiStreamBuilder::finalizeMsfLayout() { @@ -97,48 +117,60 @@ Error TpiStreamBuilder::finalizeMsfLayout() { if (auto EC = Msf.setStreamSize(Idx, Length)) return EC; - uint32_t HashBufferSize = calculateHashBufferSize(); + uint32_t HashStreamSize = + calculateHashBufferSize() + calculateIndexOffsetSize(); - if (HashBufferSize == 0) + if (HashStreamSize == 0) return Error::success(); - auto ExpectedIndex = Msf.addStream(HashBufferSize); + auto ExpectedIndex = Msf.addStream(HashStreamSize); 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; + 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); } - 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) { + WritableBinaryStreamRef Buffer) { if (auto EC = finalize()) return EC; auto InfoS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer, Idx); - StreamWriter Writer(*InfoS); + BinaryStreamWriter Writer(*InfoS); if (auto EC = Writer.writeObject(*Header)) return EC; - auto RecordArray = VarStreamArray<codeview::CVType>(TypeRecordStream); - if (auto EC = Writer.writeArray(RecordArray)) - return EC; + for (auto Rec : TypeRecords) + if (auto EC = Writer.writeBytes(Rec)) + return EC; if (HashStreamIndex != kInvalidStreamIndex) { auto HVS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer, HashStreamIndex); - StreamWriter HW(*HVS); - if (auto EC = HW.writeStreamRef(*HashValueStream)) - return EC; + 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/lib/DebugInfo/PDB/PDB.cpp b/lib/DebugInfo/PDB/PDB.cpp index 0d720591b81d..7e3acc1165f3 100644 --- a/lib/DebugInfo/PDB/PDB.cpp +++ b/lib/DebugInfo/PDB/PDB.cpp @@ -17,7 +17,7 @@ #if LLVM_ENABLE_DIA_SDK #include "llvm/DebugInfo/PDB/DIA/DIASession.h" #endif -#include "llvm/DebugInfo/PDB/Raw/RawSession.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" @@ -27,8 +27,8 @@ 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); @@ -40,8 +40,8 @@ Error llvm::pdb::loadDataForPDB(PDB_ReaderType Type, StringRef Path, 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); diff --git a/lib/DebugInfo/PDB/PDBExtras.cpp b/lib/DebugInfo/PDB/PDBExtras.cpp index b7eee6e53941..dc22a30facab 100644 --- a/lib/DebugInfo/PDB/PDBExtras.cpp +++ b/lib/DebugInfo/PDB/PDBExtras.cpp @@ -10,6 +10,7 @@ #include "llvm/DebugInfo/PDB/PDBExtras.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/CodeView/Formatters.h" using namespace llvm; using namespace llvm::pdb; @@ -259,6 +260,12 @@ raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, return OS; } +raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_UniqueId &Guid) { + codeview::detail::GuidAdapter A(Guid.Guid); + A.format(OS, ""); + return OS; +} + raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_UdtType &Type) { switch (Type) { CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Class, "class", OS) @@ -269,25 +276,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/lib/DebugInfo/PDB/PDBSymbol.cpp b/lib/DebugInfo/PDB/PDBSymbol.cpp index 633e11aacf12..74010c2dd7dd 100644 --- a/lib/DebugInfo/PDB/PDBSymbol.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp b/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp index cdb167b6191c..3648272e1d0e 100644 --- a/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolBlock.cpp b/lib/DebugInfo/PDB/PDBSymbolBlock.cpp index fd5dc9427abf..7385d3ba1489 100644 --- a/lib/DebugInfo/PDB/PDBSymbolBlock.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolBlock.cpp @@ -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/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp b/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp index ebff08846cac..854cf42d1bae 100644 --- a/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp b/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp index 6dbd5228f2cd..e08450e0ad0c 100644 --- a/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp @@ -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/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp b/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp index 9c7f0b1be56f..2f1c43666ae5 100644 --- a/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp @@ -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/lib/DebugInfo/PDB/PDBSymbolCustom.cpp b/lib/DebugInfo/PDB/PDBSymbolCustom.cpp index 0ea387a0eabb..9ec20bb62d75 100644 --- a/lib/DebugInfo/PDB/PDBSymbolCustom.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolCustom.cpp @@ -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/lib/DebugInfo/PDB/PDBSymbolData.cpp b/lib/DebugInfo/PDB/PDBSymbolData.cpp index 62bb6f3f41e2..60026689c6f1 100644 --- a/lib/DebugInfo/PDB/PDBSymbolData.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolExe.cpp b/lib/DebugInfo/PDB/PDBSymbolExe.cpp index 60101c168a79..7417167b61ad 100644 --- a/lib/DebugInfo/PDB/PDBSymbolExe.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/lib/DebugInfo/PDB/PDBSymbolFunc.cpp index 35251c0cc1c1..0734a1f8314a 100644 --- a/lib/DebugInfo/PDB/PDBSymbolFunc.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolFunc.cpp @@ -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/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp b/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp index 77e996f651df..482c95e3a850 100644 --- a/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp @@ -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/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp b/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp index 9c653879176b..ae23c7619e2a 100644 --- a/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp @@ -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/lib/DebugInfo/PDB/PDBSymbolLabel.cpp b/lib/DebugInfo/PDB/PDBSymbolLabel.cpp index d2cfd11c35e4..a67a20d8e352 100644 --- a/lib/DebugInfo/PDB/PDBSymbolLabel.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp b/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp index 97d668740818..87bb4044216b 100644 --- a/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp @@ -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/lib/DebugInfo/PDB/PDBSymbolThunk.cpp b/lib/DebugInfo/PDB/PDBSymbolThunk.cpp index ef8897d12af4..b2648197f9cc 100644 --- a/lib/DebugInfo/PDB/PDBSymbolThunk.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp index c010cc5d7678..a8054a42d866 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp index 382c397b24d2..0ee18d471624 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp @@ -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/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp index e5d65bf5d1fd..0bf563af7df5 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp index 1d80c97f9ede..f617d8d0c2df 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp @@ -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/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp index 535d97dcd21e..68ba87c1cdf8 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp @@ -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/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp index 788f2b732aaa..2addea072c88 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp index 5831baebb993..ec27985e91d1 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp @@ -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/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp index c6f586db9e57..4d5cd63f6857 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp index 057ae260885f..473529d1b043 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp @@ -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/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp index 072d2cfd42fb..86e0ec4f8565 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp @@ -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/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp b/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp index 699771450a5d..69819811d61f 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp index 0f283b9e21a4..102b540e0fef 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp index c71838cc7a6f..15dc15352165 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp index 6b76db5912ce..9a21855f57f0 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp +++ b/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/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp index ef509d64bf60..a516a4d2c429 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp @@ -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/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp b/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp index 6a62d554f42c..020aec9e98a8 100644 --- a/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp @@ -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/lib/DebugInfo/PDB/Raw/InfoStream.cpp b/lib/DebugInfo/PDB/Raw/InfoStream.cpp deleted file mode 100644 index f19535d11806..000000000000 --- a/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/lib/DebugInfo/PDB/Raw/NameMap.cpp b/lib/DebugInfo/PDB/Raw/NameMap.cpp deleted file mode 100644 index 0f55f58da381..000000000000 --- a/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/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp b/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp deleted file mode 100644 index f570d5931b0f..000000000000 --- a/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/lib/DebugInfo/PDB/Raw/RawSession.cpp b/lib/DebugInfo/PDB/Raw/RawSession.cpp deleted file mode 100644 index cd3a2064c717..000000000000 --- a/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/lib/DebugInfo/PDB/UDTLayout.cpp b/lib/DebugInfo/PDB/UDTLayout.cpp new file mode 100644 index 000000000000..61cef093d4ce --- /dev/null +++ b/lib/DebugInfo/PDB/UDTLayout.cpp @@ -0,0 +1,335 @@ +//===- UDTLayout.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/UDTLayout.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" + +#include <utility> + +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(); +} + +StorageItemBase::StorageItemBase(const UDTLayoutBase &Parent, + const PDBSymbol &Symbol, + const std::string &Name, + uint32_t OffsetInParent, uint32_t Size) + : Parent(Parent), Symbol(Symbol), Name(Name), + OffsetInParent(OffsetInParent), SizeOf(Size) { + UsedBytes.resize(SizeOf, true); +} + +uint32_t StorageItemBase::deepPaddingSize() const { + // sizeof(Field) - sizeof(typeof(Field)) is trailing padding. + return SizeOf - getTypeLength(Symbol); +} + +DataMemberLayoutItem::DataMemberLayoutItem( + const UDTLayoutBase &Parent, std::unique_ptr<PDBSymbolData> DataMember) + : StorageItemBase(Parent, *DataMember, DataMember->getName(), + DataMember->getOffset(), getTypeLength(*DataMember)), + DataMember(std::move(DataMember)) { + auto Type = this->DataMember->getType(); + if (auto UDT = unique_dyn_cast<PDBSymbolTypeUDT>(Type)) { + // UDT data members might have padding in between fields, but otherwise + // a member should occupy its entire storage. + UsedBytes.resize(SizeOf, false); + UdtLayout = llvm::make_unique<ClassLayout>(std::move(UDT)); + } +} + +const PDBSymbolData &DataMemberLayoutItem::getDataMember() { + return *dyn_cast<PDBSymbolData>(&Symbol); +} + +bool DataMemberLayoutItem::hasUDTLayout() const { return UdtLayout != nullptr; } + +const ClassLayout &DataMemberLayoutItem::getUDTLayout() const { + return *UdtLayout; +} + +uint32_t DataMemberLayoutItem::deepPaddingSize() const { + uint32_t Result = StorageItemBase::deepPaddingSize(); + if (UdtLayout) + Result += UdtLayout->deepPaddingSize(); + return Result; +} + +VTableLayoutItem::VTableLayoutItem(const UDTLayoutBase &Parent, + std::unique_ptr<PDBSymbolTypeVTable> VTable) + : StorageItemBase(Parent, *VTable, "<vtbl>", 0, getTypeLength(*VTable)), + VTable(std::move(VTable)) { + auto VTableType = cast<PDBSymbolTypePointer>(this->VTable->getType()); + ElementSize = VTableType->getLength(); + + Shape = + unique_dyn_cast<PDBSymbolTypeVTableShape>(VTableType->getPointeeType()); + if (Shape) + VTableFuncs.resize(Shape->getCount()); +} + +UDTLayoutBase::UDTLayoutBase(const PDBSymbol &Symbol, const std::string &Name, + uint32_t Size) + : SymbolBase(Symbol), Name(Name), SizeOf(Size) { + UsedBytes.resize(Size); + ChildrenPerByte.resize(Size); + initializeChildren(Symbol); +} + +ClassLayout::ClassLayout(const PDBSymbolTypeUDT &UDT) + : UDTLayoutBase(UDT, UDT.getName(), UDT.getLength()), UDT(UDT) {} + +ClassLayout::ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT) + : ClassLayout(*UDT) { + OwnedStorage = std::move(UDT); +} + +BaseClassLayout::BaseClassLayout(const UDTLayoutBase &Parent, + std::unique_ptr<PDBSymbolTypeBaseClass> Base) + : UDTLayoutBase(*Base, Base->getName(), Base->getLength()), + StorageItemBase(Parent, *Base, Base->getName(), Base->getOffset(), + Base->getLength()), + Base(std::move(Base)) { + IsVirtualBase = this->Base->isVirtualBaseClass(); +} + +uint32_t UDTLayoutBase::shallowPaddingSize() const { + return UsedBytes.size() - UsedBytes.count(); +} + +uint32_t UDTLayoutBase::deepPaddingSize() const { + uint32_t Result = shallowPaddingSize(); + for (auto &Child : ChildStorage) + Result += Child->deepPaddingSize(); + return Result; +} + +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; + auto Children = Sym.findAllChildren(); + while (auto Child = Children->getNext()) { + if (auto Base = unique_dyn_cast<PDBSymbolTypeBaseClass>(Child)) { + if (Base->isVirtualBaseClass()) + VirtualBases.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(Child)); + } 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)); + } + + for (auto &Base : Bases) { + auto BL = llvm::make_unique<BaseClassLayout>(*this, std::move(Base)); + BaseClasses.push_back(BL.get()); + + addChildToLayout(std::move(BL)); + } + + for (auto &VT : VTables) { + auto VTLayout = llvm::make_unique<VTableLayoutItem>(*this, std::move(VT)); + + VTable = VTLayout.get(); + + addChildToLayout(std::move(VTLayout)); + continue; + } + + for (auto &Data : Members) { + auto DM = llvm::make_unique<DataMemberLayoutItem>(*this, std::move(Data)); + + addChildToLayout(std::move(DM)); + } + + for (auto &Func : Funcs) { + if (!Func->isVirtual()) + continue; + + if (Func->isIntroVirtualFunction()) + addVirtualIntro(*Func); + else + addVirtualOverride(*Func); + } +} + +void UDTLayoutBase::addVirtualIntro(PDBSymbolFunc &Func) { + // Kind of a hack, but we prefer the more common destructor name that people + // are familiar with, e.g. ~ClassName. It seems there are always both and + // the vector deleting destructor overwrites the nice destructor, so just + // ignore the vector deleting destructor. + if (Func.getName() == "__vecDelDtor") + return; + + if (!VTable) { + // FIXME: Handle this. What's most likely happening is we have an intro + // virtual in a derived class where the base also has an intro virtual. + // In this case the vtable lives in the base. What we really need is + // for each UDTLayoutBase to contain a list of all its vtables, and + // then propagate this list up the hierarchy so that derived classes have + // direct access to their bases' vtables. + return; + } + + uint32_t Stride = VTable->getElementSize(); + + uint32_t Index = Func.getVirtualBaseOffset(); + assert(Index % Stride == 0); + Index /= Stride; + + VTable->setFunction(Index, Func); +} + +VTableLayoutItem *UDTLayoutBase::findVTableAtOffset(uint32_t RelativeOffset) { + if (VTable && VTable->getOffsetInParent() == RelativeOffset) + return VTable; + for (auto Base : BaseClasses) { + uint32_t Begin = Base->getOffsetInParent(); + uint32_t End = Begin + Base->getSize(); + if (RelativeOffset < Begin || RelativeOffset >= End) + continue; + + return Base->findVTableAtOffset(RelativeOffset - Begin); + } + + return nullptr; +} + +void UDTLayoutBase::addVirtualOverride(PDBSymbolFunc &Func) { + auto Signature = Func.getSignature(); + auto ThisAdjust = Signature->getThisAdjust(); + // ThisAdjust tells us which VTable we're looking for. Specifically, it's + // the offset into the current class of the VTable we're looking for. So + // look through the base hierarchy until we find one such that + // AbsoluteOffset(VT) == ThisAdjust + VTableLayoutItem *VT = findVTableAtOffset(ThisAdjust); + if (!VT) { + // FIXME: There really should be a vtable here. If there's not it probably + // means that the vtable is in a virtual base, which we don't yet support. + assert(!VirtualBases.empty()); + return; + } + int32_t OverrideIndex = -1; + // Now we've found the VTable. Func will not have a virtual base offset set, + // so instead we need to compare names and signatures. We iterate each item + // in the VTable. All items should already have non null entries because they + // were initialized by the intro virtual, which was guaranteed to come before. + for (auto ItemAndIndex : enumerate(VT->funcs())) { + auto Item = ItemAndIndex.value(); + assert(Item); + // If the name doesn't match, this isn't an override. Note that it's ok + // for the return type to not match (e.g. co-variant return). + if (Item->getName() != Func.getName()) { + if (Item->isDestructor() && Func.isDestructor()) { + OverrideIndex = ItemAndIndex.index(); + break; + } + continue; + } + // Now make sure it's the right overload. Get the signature of the existing + // vtable method and make sure it has the same arglist and the same cv-ness. + auto ExistingSig = Item->getSignature(); + if (ExistingSig->isConstType() != Signature->isConstType()) + continue; + if (ExistingSig->isVolatileType() != Signature->isVolatileType()) + continue; + + // Now compare arguments. Using the raw bytes of the PDB this would be + // trivial + // because there is an ArgListId and they should be identical. But DIA + // doesn't + // expose this, so the best we can do is iterate each argument and confirm + // that + // each one is identical. + if (ExistingSig->getCount() != Signature->getCount()) + continue; + bool IsMatch = true; + auto ExistingEnumerator = ExistingSig->getArguments(); + auto NewEnumerator = Signature->getArguments(); + for (uint32_t I = 0; I < ExistingEnumerator->getChildCount(); ++I) { + auto ExistingArg = ExistingEnumerator->getNext(); + auto NewArg = NewEnumerator->getNext(); + if (ExistingArg->getSymIndexId() != NewArg->getSymIndexId()) { + IsMatch = false; + break; + } + } + if (!IsMatch) + continue; + + // It's a match! Stick the new function into the VTable. + OverrideIndex = ItemAndIndex.index(); + break; + } + if (OverrideIndex == -1) { + // FIXME: This is probably due to one of the other FIXMEs in this file. + return; + } + VT->setFunction(OverrideIndex, Func); +} + +void UDTLayoutBase::addChildToLayout(std::unique_ptr<StorageItemBase> Child) { + uint32_t Begin = Child->getOffsetInParent(); + uint32_t End = Begin + Child->getSize(); + // Due to the empty base optimization, End might point outside the bounds of + // the parent class. If that happens, just clamp the value. + End = std::min(End, getClassSize()); + + UsedBytes.set(Begin, End); + while (Begin != End) { + ChildrenPerByte[Begin].push_back(Child.get()); + ++Begin; + } + + auto Loc = std::upper_bound( + ChildStorage.begin(), ChildStorage.end(), Begin, + [](uint32_t Off, const std::unique_ptr<StorageItemBase> &Item) { + return Off < Item->getOffsetInParent(); + }); + + ChildStorage.insert(Loc, std::move(Child)); +}
\ No newline at end of file |