003 File Manager
Current Path:
/usr/src/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native
usr
/
src
/
contrib
/
llvm-project
/
llvm
/
lib
/
DebugInfo
/
PDB
/
Native
/
📁
..
📄
DbiModuleDescriptor.cpp
(2.5 KB)
📄
DbiModuleDescriptorBuilder.cpp
(6.63 KB)
📄
DbiModuleList.cpp
(8.3 KB)
📄
DbiStream.cpp
(12.8 KB)
📄
DbiStreamBuilder.cpp
(14.82 KB)
📄
EnumTables.cpp
(1.33 KB)
📄
GSIStreamBuilder.cpp
(17.23 KB)
📄
GlobalsStream.cpp
(6.56 KB)
📄
Hash.cpp
(2.39 KB)
📄
HashTable.cpp
(2.55 KB)
📄
InfoStream.cpp
(3.94 KB)
📄
InfoStreamBuilder.cpp
(2.67 KB)
📄
InjectedSourceStream.cpp
(2.31 KB)
📄
ModuleDebugStream.cpp
(4.74 KB)
📄
NamedStreamMap.cpp
(4.2 KB)
📄
NativeCompilandSymbol.cpp
(2.22 KB)
📄
NativeEnumGlobals.cpp
(1.87 KB)
📄
NativeEnumInjectedSources.cpp
(4.05 KB)
📄
NativeEnumLineNumbers.cpp
(1.44 KB)
📄
NativeEnumModules.cpp
(1.36 KB)
📄
NativeEnumTypes.cpp
(2.62 KB)
📄
NativeExeSymbol.cpp
(3.25 KB)
📄
NativeFunctionSymbol.cpp
(2.12 KB)
📄
NativeLineNumber.cpp
(1.88 KB)
📄
NativePublicSymbol.cpp
(1.92 KB)
📄
NativeRawSymbol.cpp
(14.98 KB)
📄
NativeSession.cpp
(12.36 KB)
📄
NativeSourceFile.cpp
(1.47 KB)
📄
NativeSymbolEnumerator.cpp
(4.24 KB)
📄
NativeTypeArray.cpp
(2.6 KB)
📄
NativeTypeBuiltin.cpp
(1.67 KB)
📄
NativeTypeEnum.cpp
(12.55 KB)
📄
NativeTypeFunctionSig.cpp
(7.3 KB)
📄
NativeTypePointer.cpp
(6.41 KB)
📄
NativeTypeTypedef.cpp
(1.05 KB)
📄
NativeTypeUDT.cpp
(6.93 KB)
📄
NativeTypeVTShape.cpp
(1.42 KB)
📄
PDBFile.cpp
(16.2 KB)
📄
PDBFileBuilder.cpp
(11 KB)
📄
PDBStringTable.cpp
(4.53 KB)
📄
PDBStringTableBuilder.cpp
(6.88 KB)
📄
PublicsStream.cpp
(3.89 KB)
📄
RawError.cpp
(2.13 KB)
📄
SymbolCache.cpp
(22.39 KB)
📄
SymbolStream.cpp
(1.4 KB)
📄
TpiHashing.cpp
(4.32 KB)
📄
TpiStream.cpp
(7.85 KB)
📄
TpiStreamBuilder.cpp
(6.32 KB)
Editing: DbiStreamBuilder.cpp
//===- DbiStreamBuilder.cpp - PDB Dbi Stream Creation -----------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/Object/COFF.h" #include "llvm/Support/BinaryStreamWriter.h" using namespace llvm; using namespace llvm::codeview; using namespace llvm::msf; using namespace llvm::pdb; DbiStreamBuilder::DbiStreamBuilder(msf::MSFBuilder &Msf) : Msf(Msf), Allocator(Msf.getAllocator()), Age(1), BuildNumber(0), PdbDllVersion(0), PdbDllRbld(0), Flags(0), MachineType(PDB_Machine::x86), Header(nullptr) {} DbiStreamBuilder::~DbiStreamBuilder() {} void DbiStreamBuilder::setVersionHeader(PdbRaw_DbiVer V) { VerHeader = V; } void DbiStreamBuilder::setAge(uint32_t A) { Age = A; } void DbiStreamBuilder::setBuildNumber(uint16_t B) { BuildNumber = B; } void DbiStreamBuilder::setBuildNumber(uint8_t Major, uint8_t Minor) { BuildNumber = (uint16_t(Major) << DbiBuildNo::BuildMajorShift) & DbiBuildNo::BuildMajorMask; BuildNumber |= (uint16_t(Minor) << DbiBuildNo::BuildMinorShift) & DbiBuildNo::BuildMinorMask; BuildNumber |= DbiBuildNo::NewVersionFormatMask; } void DbiStreamBuilder::setPdbDllVersion(uint16_t V) { PdbDllVersion = V; } void DbiStreamBuilder::setPdbDllRbld(uint16_t R) { PdbDllRbld = R; } void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; } void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; } void DbiStreamBuilder::setMachineType(COFF::MachineTypes M) { // These enums are mirrors of each other, so we can just cast the value. MachineType = static_cast<pdb::PDB_Machine>(static_cast<unsigned>(M)); } void DbiStreamBuilder::setGlobalsStreamIndex(uint32_t Index) { GlobalsStreamIndex = Index; } void DbiStreamBuilder::setSymbolRecordStreamIndex(uint32_t Index) { SymRecordStreamIndex = Index; } void DbiStreamBuilder::setPublicsStreamIndex(uint32_t Index) { PublicsStreamIndex = Index; } void DbiStreamBuilder::addNewFpoData(const codeview::FrameData &FD) { if (!NewFpoData.hasValue()) NewFpoData.emplace(false); NewFpoData->addFrameData(FD); } void DbiStreamBuilder::addOldFpoData(const object::FpoData &FD) { OldFpoData.push_back(FD); } Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type, ArrayRef<uint8_t> Data) { assert(Type != DbgHeaderType::NewFPO && "NewFPO data should be written via addFrameData()!"); DbgStreams[(int)Type].emplace(); DbgStreams[(int)Type]->Size = Data.size(); DbgStreams[(int)Type]->WriteFn = [Data](BinaryStreamWriter &Writer) { return Writer.writeArray(Data); }; return Error::success(); } uint32_t DbiStreamBuilder::addECName(StringRef Name) { return ECNamesBuilder.insert(Name); } uint32_t DbiStreamBuilder::calculateSerializedLength() const { // For now we only support serializing the header. return sizeof(DbiStreamHeader) + calculateFileInfoSubstreamSize() + calculateModiSubstreamSize() + calculateSectionContribsStreamSize() + calculateSectionMapStreamSize() + calculateDbgStreamsSize() + ECNamesBuilder.calculateSerializedSize(); } Expected<DbiModuleDescriptorBuilder &> DbiStreamBuilder::addModuleInfo(StringRef ModuleName) { uint32_t Index = ModiList.size(); ModiList.push_back( std::make_unique<DbiModuleDescriptorBuilder>(ModuleName, Index, Msf)); return *ModiList.back(); } Error DbiStreamBuilder::addModuleSourceFile(DbiModuleDescriptorBuilder &Module, StringRef File) { uint32_t Index = SourceFileNames.size(); SourceFileNames.insert(std::make_pair(File, Index)); Module.addSourceFile(File); return Error::success(); } Expected<uint32_t> DbiStreamBuilder::getSourceFileNameIndex(StringRef File) { auto NameIter = SourceFileNames.find(File); if (NameIter == SourceFileNames.end()) return make_error<RawError>(raw_error_code::no_entry, "The specified source file was not found"); return NameIter->getValue(); } uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const { uint32_t Size = 0; for (const auto &M : ModiList) Size += M->calculateSerializedLength(); return Size; } uint32_t DbiStreamBuilder::calculateSectionContribsStreamSize() const { if (SectionContribs.empty()) return 0; return sizeof(enum PdbRaw_DbiSecContribVer) + sizeof(SectionContribs[0]) * SectionContribs.size(); } uint32_t DbiStreamBuilder::calculateSectionMapStreamSize() const { if (SectionMap.empty()) return 0; return sizeof(SecMapHeader) + sizeof(SecMapEntry) * SectionMap.size(); } uint32_t DbiStreamBuilder::calculateNamesOffset() const { uint32_t Offset = 0; Offset += sizeof(ulittle16_t); // NumModules Offset += sizeof(ulittle16_t); // NumSourceFiles Offset += ModiList.size() * sizeof(ulittle16_t); // ModIndices Offset += ModiList.size() * sizeof(ulittle16_t); // ModFileCounts uint32_t NumFileInfos = 0; for (const auto &M : ModiList) NumFileInfos += M->source_files().size(); Offset += NumFileInfos * sizeof(ulittle32_t); // FileNameOffsets return Offset; } uint32_t DbiStreamBuilder::calculateFileInfoSubstreamSize() const { uint32_t Size = calculateNamesOffset(); Size += calculateNamesBufferSize(); return alignTo(Size, sizeof(uint32_t)); } uint32_t DbiStreamBuilder::calculateNamesBufferSize() const { uint32_t Size = 0; for (const auto &F : SourceFileNames) { Size += F.getKeyLength() + 1; // Names[I]; } return Size; } uint32_t DbiStreamBuilder::calculateDbgStreamsSize() const { return DbgStreams.size() * sizeof(uint16_t); } Error DbiStreamBuilder::generateFileInfoSubstream() { uint32_t Size = calculateFileInfoSubstreamSize(); auto Data = Allocator.Allocate<uint8_t>(Size); uint32_t NamesOffset = calculateNamesOffset(); FileInfoBuffer = MutableBinaryByteStream(MutableArrayRef<uint8_t>(Data, Size), llvm::support::little); WritableBinaryStreamRef MetadataBuffer = WritableBinaryStreamRef(FileInfoBuffer).keep_front(NamesOffset); BinaryStreamWriter MetadataWriter(MetadataBuffer); 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; if (auto EC = MetadataWriter.writeInteger(FileCount)) // NumSourceFiles return EC; for (uint16_t I = 0; I < ModiCount; ++I) { if (auto EC = MetadataWriter.writeInteger(I)) // Mod Indices return EC; } 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; } // Before writing the FileNameOffsets array, write the NamesBuffer array. // 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 = WritableBinaryStreamRef(FileInfoBuffer).drop_front(NamesOffset); BinaryStreamWriter NameBufferWriter(NamesBuffer); for (auto &Name : SourceFileNames) { Name.second = NameBufferWriter.getOffset(); if (auto EC = NameBufferWriter.writeCString(Name.getKey())) return EC; } 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, "The source file was not found."); if (auto EC = MetadataWriter.writeInteger(Result->second)) return EC; } } if (auto EC = NameBufferWriter.padToAlignment(sizeof(uint32_t))) return EC; if (NameBufferWriter.bytesRemaining() > 0) return make_error<RawError>(raw_error_code::invalid_format, "The names buffer contained unexpected data."); if (MetadataWriter.bytesRemaining() > sizeof(uint32_t)) return make_error<RawError>( raw_error_code::invalid_format, "The metadata buffer contained unexpected data."); return Error::success(); } Error DbiStreamBuilder::finalize() { if (Header) return Error::success(); for (auto &MI : ModiList) MI->finalize(); if (auto EC = generateFileInfoSubstream()) return EC; DbiStreamHeader *H = Allocator.Allocate<DbiStreamHeader>(); ::memset(H, 0, sizeof(DbiStreamHeader)); H->VersionHeader = *VerHeader; H->VersionSignature = -1; H->Age = Age; H->BuildNumber = BuildNumber; H->Flags = Flags; H->PdbDllRbld = PdbDllRbld; H->PdbDllVersion = PdbDllVersion; H->MachineType = static_cast<uint16_t>(MachineType); H->ECSubstreamSize = ECNamesBuilder.calculateSerializedSize(); H->FileInfoSize = FileInfoBuffer.getLength(); H->ModiSubstreamSize = calculateModiSubstreamSize(); H->OptionalDbgHdrSize = DbgStreams.size() * sizeof(uint16_t); H->SecContrSubstreamSize = calculateSectionContribsStreamSize(); H->SectionMapSize = calculateSectionMapStreamSize(); H->TypeServerSize = 0; H->SymRecordStreamIndex = SymRecordStreamIndex; H->PublicSymbolStreamIndex = PublicsStreamIndex; H->MFCTypeServerIndex = 0; // Not sure what this is, but link.exe writes 0. H->GlobalSymbolStreamIndex = GlobalsStreamIndex; Header = H; return Error::success(); } Error DbiStreamBuilder::finalizeMsfLayout() { if (NewFpoData.hasValue()) { DbgStreams[(int)DbgHeaderType::NewFPO].emplace(); DbgStreams[(int)DbgHeaderType::NewFPO]->Size = NewFpoData->calculateSerializedSize(); DbgStreams[(int)DbgHeaderType::NewFPO]->WriteFn = [this](BinaryStreamWriter &Writer) { return NewFpoData->commit(Writer); }; } if (!OldFpoData.empty()) { DbgStreams[(int)DbgHeaderType::FPO].emplace(); DbgStreams[(int)DbgHeaderType::FPO]->Size = sizeof(object::FpoData) * OldFpoData.size(); DbgStreams[(int)DbgHeaderType::FPO]->WriteFn = [this](BinaryStreamWriter &Writer) { return Writer.writeArray(makeArrayRef(OldFpoData)); }; } for (auto &S : DbgStreams) { if (!S.hasValue()) continue; auto ExpectedIndex = Msf.addStream(S->Size); if (!ExpectedIndex) return ExpectedIndex.takeError(); S->StreamNumber = *ExpectedIndex; } for (auto &MI : ModiList) { if (auto EC = MI->finalizeMsfLayout()) return EC; } uint32_t Length = calculateSerializedLength(); if (auto EC = Msf.setStreamSize(StreamDBI, Length)) return EC; return Error::success(); } static uint16_t toSecMapFlags(uint32_t Flags) { uint16_t Ret = 0; if (Flags & COFF::IMAGE_SCN_MEM_READ) Ret |= static_cast<uint16_t>(OMFSegDescFlags::Read); if (Flags & COFF::IMAGE_SCN_MEM_WRITE) Ret |= static_cast<uint16_t>(OMFSegDescFlags::Write); if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) Ret |= static_cast<uint16_t>(OMFSegDescFlags::Execute); if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) Ret |= static_cast<uint16_t>(OMFSegDescFlags::Execute); if (!(Flags & COFF::IMAGE_SCN_MEM_16BIT)) Ret |= static_cast<uint16_t>(OMFSegDescFlags::AddressIs32Bit); // This seems always 1. Ret |= static_cast<uint16_t>(OMFSegDescFlags::IsSelector); return Ret; } // Populate the Section Map from COFF section headers. // // A Section Map seem to be a copy of a COFF section list in other format. // I don't know why a PDB file contains both a COFF section header and // a Section Map, but it seems it must be present in a PDB. void DbiStreamBuilder::createSectionMap( ArrayRef<llvm::object::coff_section> SecHdrs) { int Idx = 0; auto Add = [&]() -> SecMapEntry & { SectionMap.emplace_back(); auto &Entry = SectionMap.back(); memset(&Entry, 0, sizeof(Entry)); Entry.Frame = Idx + 1; // We don't know the meaning of these fields yet. Entry.SecName = UINT16_MAX; Entry.ClassName = UINT16_MAX; return Entry; }; for (auto &Hdr : SecHdrs) { auto &Entry = Add(); Entry.Flags = toSecMapFlags(Hdr.Characteristics); Entry.SecByteLength = Hdr.VirtualSize; ++Idx; } // The last entry is for absolute symbols. auto &Entry = Add(); Entry.Flags = static_cast<uint16_t>(OMFSegDescFlags::AddressIs32Bit) | static_cast<uint16_t>(OMFSegDescFlags::IsAbsoluteAddress); Entry.SecByteLength = UINT32_MAX; } Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef MsfBuffer) { if (auto EC = finalize()) return EC; auto DbiS = WritableMappedBlockStream::createIndexedStream( Layout, MsfBuffer, StreamDBI, Allocator); BinaryStreamWriter Writer(*DbiS); if (auto EC = Writer.writeObject(*Header)) return EC; for (auto &M : ModiList) { if (auto EC = M->commit(Writer, Layout, MsfBuffer)) return EC; } if (!SectionContribs.empty()) { if (auto EC = Writer.writeEnum(DbiSecContribVer60)) return EC; if (auto EC = Writer.writeArray(makeArrayRef(SectionContribs))) return EC; } if (!SectionMap.empty()) { ulittle16_t Size = static_cast<ulittle16_t>(SectionMap.size()); SecMapHeader SMHeader = {Size, Size}; if (auto EC = Writer.writeObject(SMHeader)) return EC; if (auto EC = Writer.writeArray(makeArrayRef(SectionMap))) return EC; } if (auto EC = Writer.writeStreamRef(FileInfoBuffer)) return EC; if (auto EC = ECNamesBuilder.commit(Writer)) return EC; for (auto &Stream : DbgStreams) { uint16_t StreamNumber = kInvalidStreamIndex; if (Stream.hasValue()) StreamNumber = Stream->StreamNumber; if (auto EC = Writer.writeInteger(StreamNumber)) return EC; } for (auto &Stream : DbgStreams) { if (!Stream.hasValue()) continue; assert(Stream->StreamNumber != kInvalidStreamIndex); auto WritableStream = WritableMappedBlockStream::createIndexedStream( Layout, MsfBuffer, Stream->StreamNumber, Allocator); BinaryStreamWriter DbgStreamWriter(*WritableStream); if (auto EC = Stream->WriteFn(DbgStreamWriter)) return EC; } if (Writer.bytesRemaining() > 0) return make_error<RawError>(raw_error_code::invalid_format, "Unexpected bytes found in DBI Stream"); return Error::success(); }
Upload File
Create Folder