diff options
Diffstat (limited to 'llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp')
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp | 178 |
1 files changed, 172 insertions, 6 deletions
diff --git a/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp index 34ff8ae3a90..bbb0876380d 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp @@ -18,9 +18,13 @@ using namespace llvm; using namespace llvm::codeview; using namespace llvm::pdb; -DbiStreamBuilder::DbiStreamBuilder() - : Age(1), BuildNumber(0), PdbDllVersion(0), PdbDllRbld(0), Flags(0), - MachineType(PDB_Machine::x86) {} +namespace { +class ModiSubstreamBuilder {}; +} + +DbiStreamBuilder::DbiStreamBuilder(BumpPtrAllocator &Allocator) + : Allocator(Allocator), Age(1), BuildNumber(0), PdbDllVersion(0), + PdbDllRbld(0), Flags(0), MachineType(PDB_Machine::x86) {} void DbiStreamBuilder::setVersionHeader(PdbRaw_DbiVer V) { VerHeader = V; } @@ -38,7 +42,157 @@ void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; } uint32_t DbiStreamBuilder::calculateSerializedLength() const { // For now we only support serializing the header. - return sizeof(DbiStream::HeaderInfo); + return sizeof(DbiStream::HeaderInfo) + calculateFileInfoSubstreamSize() + + calculateModiSubstreamSize(); +} + +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))); + if (!Result.second) + return make_error<RawError>(raw_error_code::duplicate_entry, + "The specified module already exists"); + ModuleInfoList.push_back(M); + return Error::success(); +} + +Error DbiStreamBuilder::addModuleSourceFile(StringRef Module, StringRef File) { + auto ModIter = ModuleInfos.find(Module); + if (ModIter == ModuleInfos.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); + return Error::success(); +} + +uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const { + uint32_t Size = 0; + for (const auto &M : ModuleInfoList) { + Size += sizeof(ModInfo::FileLayout); + Size += M->Mod.size() + 1; + Size += M->Obj.size() + 1; + } + return Size; +} + +uint32_t DbiStreamBuilder::calculateFileInfoSubstreamSize() const { + // ulittle16_t NumModules; + // ulittle16_t NumSourceFiles; + // ulittle16_t ModIndices[NumModules]; + // ulittle16_t ModFileCounts[NumModules]; + // ulittle32_t FileNameOffsets[NumSourceFiles]; + // char Names[NumSourceFiles][]; + uint32_t Size = 0; + Size += sizeof(ulittle16_t); // NumModules + Size += sizeof(ulittle16_t); // NumSourceFiles + Size += ModuleInfoList.size() * sizeof(ulittle16_t); // ModIndices + Size += ModuleInfoList.size() * sizeof(ulittle16_t); // ModFileCounts + uint32_t NumFileInfos = 0; + for (const auto &M : ModuleInfoList) + NumFileInfos += M->SourceFiles.size(); + Size += NumFileInfos * sizeof(ulittle32_t); // FileNameOffsets + Size += calculateNamesBufferSize(); + return Size; +} + +uint32_t DbiStreamBuilder::calculateNamesBufferSize() const { + uint32_t Size = 0; + for (const auto &F : SourceFileNames) { + Size += F.getKeyLength() + 1; // Names[I]; + } + return Size; +} + +Error DbiStreamBuilder::generateModiSubstream() { + uint32_t Size = calculateModiSubstreamSize(); + auto Data = Allocator.Allocate<uint8_t>(Size); + + ModInfoBuffer = ByteStream<true>(MutableArrayRef<uint8_t>(Data, Size)); + + StreamWriter ModiWriter(ModInfoBuffer); + for (const auto &M : ModuleInfoList) { + ModInfo::FileLayout Layout = {}; + Layout.ModDiStream = DbiStream::InvalidStreamIndex; + 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() != 0) + 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 = ByteStream<true>(MutableArrayRef<uint8_t>(Data, Size)); + + StreamRef MetadataBuffer = StreamRef(FileInfoBuffer).keep_front(NamesOffset); + StreamWriter MetadataWriter(MetadataBuffer); + + uint16_t ModiCount = std::min<uint16_t>(UINT16_MAX, ModuleInfos.size()); + uint16_t FileCount = std::min<uint16_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 : ModuleInfoList) { + FileCount = static_cast<uint16_t>(MI->SourceFiles.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 = StreamRef(FileInfoBuffer).drop_front(NamesOffset); + StreamWriter NameBufferWriter(NamesBuffer); + for (auto &Name : SourceFileNames) { + Name.second = NameBufferWriter.getOffset(); + if (auto EC = NameBufferWriter.writeZeroString(Name.getKey())) + return EC; + } + + for (const auto MI : ModuleInfoList) { + for (StringRef Name : MI->SourceFiles) { + 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 (NameBufferWriter.bytesRemaining() > 0) + return make_error<RawError>(raw_error_code::invalid_format, + "The names buffer contained unexpected data."); + + if (MetadataWriter.bytesRemaining() > 0) + return make_error<RawError>( + raw_error_code::invalid_format, + "The metadata buffer contained unexpected data."); + + return Error::success(); } Expected<std::unique_ptr<DbiStream>> DbiStreamBuilder::build(PDBFile &File) { @@ -54,6 +208,12 @@ Expected<std::unique_ptr<DbiStream>> DbiStreamBuilder::build(PDBFile &File) { static_cast<DbiStream::HeaderInfo *>(DS->getAllocator().Allocate( sizeof(DbiStream::HeaderInfo), llvm::AlignOf<DbiStream::HeaderInfo>::Alignment)); + + if (auto EC = generateModiSubstream()) + return std::move(EC); + if (auto EC = generateFileInfoSubstream()) + return std::move(EC); + H->VersionHeader = *VerHeader; H->VersionSignature = -1; H->Age = Age; @@ -64,8 +224,8 @@ Expected<std::unique_ptr<DbiStream>> DbiStreamBuilder::build(PDBFile &File) { H->MachineType = static_cast<uint16_t>(MachineType); H->ECSubstreamSize = 0; - H->FileInfoSize = 0; - H->ModiSubstreamSize = 0; + H->FileInfoSize = FileInfoBuffer.getLength(); + H->ModiSubstreamSize = ModInfoBuffer.getLength(); H->OptionalDbgHdrSize = 0; H->SecContrSubstreamSize = 0; H->SectionMapSize = 0; @@ -77,5 +237,11 @@ Expected<std::unique_ptr<DbiStream>> DbiStreamBuilder::build(PDBFile &File) { auto Dbi = llvm::make_unique<DbiStream>(File, std::move(DS)); Dbi->Header = H; + Dbi->FileInfoSubstream = StreamRef(FileInfoBuffer); + Dbi->ModInfoSubstream = StreamRef(ModInfoBuffer); + if (auto EC = Dbi->initializeModInfoArray()) + return std::move(EC); + if (auto EC = Dbi->initializeFileInfo()) + return std::move(EC); return std::move(Dbi); } |

