From d89466b34c1c8426b2367735ad2cbbff84fea614 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Mon, 19 Jun 2017 17:21:45 +0000 Subject: [PATCH] [PDB] Start emitting source file and line information Summary: This is a first step towards getting line info to show up in VS and windbg. So far, only llvm-pdbutil can parse the PDBs that we produce. cvdump doesn't like something about our file checksum tables. I'll have to dig into that next. This patch adds a new DebugSubsectionRecordBuilder which takes bytes directly from some other producer, such as a linker, and sticks it into the PDB. Line tables only need to be relocated. No data needs to be rewritten. File checksums and string tables, on the other hand, need to be re-done. Reviewers: zturner, ruiu Subscribers: llvm-commits, hiraditya Differential Revision: https://reviews.llvm.org/D34257 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305713 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../CodeView/DebugSubsectionRecord.h | 12 ++++++++ .../PDB/Native/DbiModuleDescriptorBuilder.h | 4 +++ .../DebugInfo/PDB/Native/DbiStreamBuilder.h | 1 + .../CodeView/DebugSubsectionRecord.cpp | 30 ++++++++++++------- .../PDB/Native/DbiModuleDescriptorBuilder.cpp | 6 ++++ lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp | 8 +++-- 6 files changed, 49 insertions(+), 12 deletions(-) diff --git a/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h b/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h index 69473174206..ee17b47d8e6 100644 --- a/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h +++ b/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h @@ -51,11 +51,23 @@ class DebugSubsectionRecordBuilder { public: DebugSubsectionRecordBuilder(std::shared_ptr Subsection, CodeViewContainer Container); + + /// Use this to copy existing subsections directly from source to destination. + /// For example, line table subsections in an object file only need to be + /// relocated before being copied into the PDB. + DebugSubsectionRecordBuilder(const DebugSubsectionRecord &Contents, + CodeViewContainer Container); + uint32_t calculateSerializedLength(); Error commit(BinaryStreamWriter &Writer) const; private: + /// The subsection to build. Will be null if Contents is non-empty. std::shared_ptr Subsection; + + /// The bytes of the subsection. Only non-empty if Subsection is null. + DebugSubsectionRecord Contents; + CodeViewContainer Container; }; diff --git a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h index a89e26ae943..e4cb1b24e30 100644 --- a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h @@ -14,6 +14,7 @@ #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include "llvm/Support/Error.h" @@ -52,6 +53,9 @@ public: void addDebugSubsection(std::shared_ptr Subsection); + void + addDebugSubsection(const codeview::DebugSubsectionRecord &SubsectionContents); + uint16_t getStreamIndex() const; StringRef getModuleName() const { return ModuleName; } StringRef getObjFileName() const { return ObjFileName; } diff --git a/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h index aeb2e2ab026..74441185418 100644 --- a/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h @@ -58,6 +58,7 @@ public: Expected addModuleInfo(StringRef ModuleName); Error addModuleSourceFile(StringRef Module, StringRef File); + Error addModuleSourceFile(DbiModuleDescriptorBuilder &Module, StringRef File); Expected getSourceFileNameIndex(StringRef FileName); Error finalizeMsfLayout(); diff --git a/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp b/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp index 334c5e002bb..d69eca018e0 100644 --- a/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp +++ b/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp @@ -53,12 +53,16 @@ DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( std::shared_ptr Subsection, CodeViewContainer Container) : Subsection(std::move(Subsection)), Container(Container) {} +DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( + const DebugSubsectionRecord &Contents, CodeViewContainer Container) + : Contents(Contents), Container(Container) {} + uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() { - // The length of the entire subsection is always padded to 4 bytes, regardless - // of the container kind. - uint32_t Size = sizeof(DebugSubsectionHeader) + - alignTo(Subsection->calculateSerializedSize(), 4); - return Size; + uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize() + : Contents.getRecordData().getLength(); + // The length of the entire subsection is always padded to 4 bytes, + // regardless of the container kind. + return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4); } Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const { @@ -66,16 +70,22 @@ Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const { "Debug Subsection not properly aligned"); DebugSubsectionHeader Header; - Header.Kind = uint32_t(Subsection->kind()); + Header.Kind = uint32_t(Subsection ? Subsection->kind() : Contents.kind()); // The value written into the Header's Length field is only padded to the // container's alignment - Header.Length = - alignTo(Subsection->calculateSerializedSize(), alignOf(Container)); + uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize() + : Contents.getRecordData().getLength(); + Header.Length = alignTo(DataSize, alignOf(Container)); if (auto EC = Writer.writeObject(Header)) return EC; - if (auto EC = Subsection->commit(Writer)) - return EC; + if (Subsection) { + if (auto EC = Subsection->commit(Writer)) + return EC; + } else { + if (auto EC = Writer.writeStreamRef(Contents.getRecordData())) + return EC; + } if (auto EC = Writer.padToAlignment(4)) return EC; diff --git a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index 81a9d3eeec6..59ecbb50143 100644 --- a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -182,3 +182,9 @@ void DbiModuleDescriptorBuilder::addDebugSubsection( C13Builders.push_back(llvm::make_unique( std::move(Subsection), CodeViewContainer::Pdb)); } + +void DbiModuleDescriptorBuilder::addDebugSubsection( + const DebugSubsectionRecord &SubsectionContents) { + C13Builders.push_back(llvm::make_unique( + SubsectionContents, CodeViewContainer::Pdb)); +} diff --git a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp index e7304b444f2..0ad461546d7 100644 --- a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -90,10 +90,14 @@ Error DbiStreamBuilder::addModuleSourceFile(StringRef Module, StringRef File) { if (ModIter == ModiMap.end()) return make_error(raw_error_code::no_entry, "The specified module was not found"); + return addModuleSourceFile(*ModIter->second, File); +} + +Error DbiStreamBuilder::addModuleSourceFile(DbiModuleDescriptorBuilder &Module, + StringRef File) { uint32_t Index = SourceFileNames.size(); SourceFileNames.insert(std::make_pair(File, Index)); - auto &ModEntry = *ModIter; - ModEntry.second->addSourceFile(File); + Module.addSourceFile(File); return Error::success(); } -- 2.40.0