diff options
Diffstat (limited to 'llvm/lib')
9 files changed, 246 insertions, 7 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp b/llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp index 4bbfe285423..79e5b9d690d 100644 --- a/llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp +++ b/llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp @@ -48,3 +48,50 @@ Error ModuleDebugFileChecksumFragmentRef::initialize( return Error::success(); } + +ModuleDebugFileChecksumFragment::ModuleDebugFileChecksumFragment() + : ModuleDebugFragment(ModuleDebugFragmentKind::FileChecksums) {} + +void ModuleDebugFileChecksumFragment::addChecksum(uint32_t StringTableOffset, + FileChecksumKind Kind, + ArrayRef<uint8_t> Bytes) { + FileChecksumEntry Entry; + if (!Bytes.empty()) { + uint8_t *Copy = Storage.Allocate<uint8_t>(Bytes.size()); + ::memcpy(Copy, Bytes.data(), Bytes.size()); + Entry.Checksum = makeArrayRef(Copy, Bytes.size()); + } + Entry.FileNameOffset = StringTableOffset; + Entry.Kind = Kind; + Checksums.push_back(Entry); + + // This maps the offset of this string in the string table to the offset + // of this checksum entry in the checksum buffer. + OffsetMap[StringTableOffset] = SerializedSize; + SerializedSize += sizeof(FileChecksumEntryHeader) + Bytes.size(); +} + +uint32_t ModuleDebugFileChecksumFragment::calculateSerializedLength() { + return SerializedSize; +} + +Error ModuleDebugFileChecksumFragment::commit(BinaryStreamWriter &Writer) { + for (const auto &FC : Checksums) { + FileChecksumEntryHeader Header; + Header.ChecksumKind = uint8_t(FC.Kind); + Header.ChecksumSize = FC.Checksum.size(); + Header.FileNameOffset = FC.FileNameOffset; + if (auto EC = Writer.writeObject(Header)) + return EC; + if (auto EC = Writer.writeArray(makeArrayRef(FC.Checksum))) + return EC; + } + return Error::success(); +} + +uint32_t ModuleDebugFileChecksumFragment::mapChecksumOffset( + uint32_t StringTableOffset) const { + auto Iter = OffsetMap.find(StringTableOffset); + assert(Iter != OffsetMap.end()); + return Iter->second; +} diff --git a/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp b/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp index 36f86cbbdf6..2af1917413d 100644 --- a/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp +++ b/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp @@ -12,3 +12,5 @@ using namespace llvm::codeview; ModuleDebugFragmentRef::~ModuleDebugFragmentRef() {} + +ModuleDebugFragment::~ModuleDebugFragment() {} diff --git a/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp b/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp index 20c06e9bebe..263b632da3f 100644 --- a/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp +++ b/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" #include "llvm/Support/BinaryStreamReader.h" @@ -30,6 +31,13 @@ Error ModuleDebugFragmentRecord::initialize(BinaryStreamRef Stream, ModuleDebugFragmentKind Kind = static_cast<ModuleDebugFragmentKind>(uint32_t(Header->Kind)); + switch (Kind) { + case ModuleDebugFragmentKind::FileChecksums: + case ModuleDebugFragmentKind::Lines: + break; + default: + llvm_unreachable("Unexpected debug fragment kind!"); + } if (auto EC = Reader.readStreamRef(Info.Data, Header->Length)) return EC; Info.Kind = Kind; @@ -37,7 +45,9 @@ Error ModuleDebugFragmentRecord::initialize(BinaryStreamRef Stream, } uint32_t ModuleDebugFragmentRecord::getRecordLength() const { - return sizeof(ModuleDebugFragmentHeader) + Data.getLength(); + uint32_t Result = sizeof(ModuleDebugFragmentHeader) + Data.getLength(); + assert(Result % 4 == 0); + return Result; } ModuleDebugFragmentKind ModuleDebugFragmentRecord::kind() const { return Kind; } @@ -45,3 +55,29 @@ ModuleDebugFragmentKind ModuleDebugFragmentRecord::kind() const { return Kind; } BinaryStreamRef ModuleDebugFragmentRecord::getRecordData() const { return Data; } + +ModuleDebugFragmentRecordBuilder::ModuleDebugFragmentRecordBuilder( + ModuleDebugFragmentKind Kind, ModuleDebugFragment &Frag) + : Kind(Kind), Frag(Frag) {} + +uint32_t ModuleDebugFragmentRecordBuilder::calculateSerializedLength() { + uint32_t Size = sizeof(ModuleDebugFragmentHeader) + + alignTo(Frag.calculateSerializedLength(), 4); + return Size; +} + +Error ModuleDebugFragmentRecordBuilder::commit(BinaryStreamWriter &Writer) { + ModuleDebugFragmentHeader Header; + Header.Kind = uint32_t(Kind); + Header.Length = + calculateSerializedLength() - sizeof(ModuleDebugFragmentHeader); + + if (auto EC = Writer.writeObject(Header)) + return EC; + if (auto EC = Frag.commit(Writer)) + return EC; + if (auto EC = Writer.padToAlignment(4)) + return EC; + + return Error::success(); +} diff --git a/llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp b/llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp index 6a9751c1257..103010ca283 100644 --- a/llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp +++ b/llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp @@ -64,3 +64,92 @@ Error ModuleDebugLineFragmentRef::initialize(BinaryStreamReader Reader) { bool ModuleDebugLineFragmentRef::hasColumnInfo() const { return !!(Header->Flags & LF_HaveColumns); } + +ModuleDebugLineFragment::ModuleDebugLineFragment() + : ModuleDebugFragment(ModuleDebugFragmentKind::Lines) {} + +void ModuleDebugLineFragment::createBlock(uint32_t ChecksumBufferOffset) { + Blocks.emplace_back(ChecksumBufferOffset); +} + +void ModuleDebugLineFragment::addLineInfo(uint32_t Offset, + const LineInfo &Line) { + Block &B = Blocks.back(); + LineNumberEntry LNE; + LNE.Flags = Line.getRawData(); + LNE.Offset = Offset; + B.Lines.push_back(LNE); +} + +void ModuleDebugLineFragment::addLineAndColumnInfo(uint32_t Offset, + const LineInfo &Line, + uint32_t ColStart, + uint32_t ColEnd) { + Block &B = Blocks.back(); + assert(B.Lines.size() == B.Columns.size()); + + addLineInfo(Offset, Line); + ColumnNumberEntry CNE; + CNE.StartColumn = ColStart; + CNE.EndColumn = ColEnd; + B.Columns.push_back(CNE); +} + +Error ModuleDebugLineFragment::commit(BinaryStreamWriter &Writer) { + LineFragmentHeader Header; + Header.CodeSize = CodeSize; + Header.Flags = hasColumnInfo() ? LF_HaveColumns : 0; + Header.RelocOffset = RelocOffset; + Header.RelocSegment = RelocSegment; + + if (auto EC = Writer.writeObject(Header)) + return EC; + + for (const auto &B : Blocks) { + LineBlockFragmentHeader BlockHeader; + assert(B.Lines.size() == B.Columns.size() || B.Columns.empty()); + + BlockHeader.NumLines = B.Lines.size(); + BlockHeader.BlockSize = sizeof(LineBlockFragmentHeader); + BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(LineNumberEntry); + if (hasColumnInfo()) + BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(ColumnNumberEntry); + BlockHeader.NameIndex = B.ChecksumBufferOffset; + if (auto EC = Writer.writeObject(BlockHeader)) + return EC; + + if (auto EC = Writer.writeArray(makeArrayRef(B.Lines))) + return EC; + + if (hasColumnInfo()) { + if (auto EC = Writer.writeArray(makeArrayRef(B.Columns))) + return EC; + } + } + return Error::success(); +} + +uint32_t ModuleDebugLineFragment::calculateSerializedLength() { + uint32_t Size = sizeof(LineFragmentHeader); + for (const auto &B : Blocks) { + Size += sizeof(LineBlockFragmentHeader); + Size += B.Lines.size() * sizeof(LineNumberEntry); + if (hasColumnInfo()) + Size += B.Columns.size() * sizeof(ColumnNumberEntry); + } + return Size; +} + +void ModuleDebugLineFragment::setRelocationAddress(uint16_t Segment, + uint16_t Offset) { + RelocOffset = Offset; + RelocSegment = Segment; +} + +void ModuleDebugLineFragment::setCodeSize(uint32_t Size) { CodeSize = Size; } + +void ModuleDebugLineFragment::setFlags(LineFlags Flags) { this->Flags = Flags; } + +bool ModuleDebugLineFragment::hasColumnInfo() const { + return Flags & LF_HaveColumns; +} diff --git a/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp b/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp index f9ded6ce2a8..efaba4646ff 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp @@ -110,6 +110,10 @@ const CVType &TypeDatabase::getTypeRecord(TypeIndex Index) const { return TypeRecords[Index.getIndex() - TypeIndex::FirstNonSimpleIndex]; } +CVType &TypeDatabase::getTypeRecord(TypeIndex Index) { + return TypeRecords[Index.getIndex() - TypeIndex::FirstNonSimpleIndex]; +} + bool TypeDatabase::containsTypeIndex(TypeIndex Index) const { uint32_t I = Index.getIndex() - TypeIndex::FirstNonSimpleIndex; return I < CVUDTNames.size(); diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index 8920dd9bbea..41cb23a188f 100644 --- a/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -10,6 +10,7 @@ #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MSFCommon.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" @@ -35,11 +36,12 @@ template <> struct BinaryItemTraits<CVSymbol> { }; } -static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize) { +static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize, + uint32_t C13Size) { uint32_t Size = sizeof(uint32_t); // Signature Size += SymbolByteSize; // Symbol Data - Size += 0; // TODO: Layout.LineBytes - Size += 0; // TODO: Layout.C13Bytes + Size += 0; // TODO: Layout.C11Bytes + Size += C13Size; // C13 Debug Info Size Size += sizeof(uint32_t); // GlobalRefs substream size (always 0) Size += 0; // GlobalRefs substream bytes return Size; @@ -52,6 +54,8 @@ DbiModuleDescriptorBuilder::DbiModuleDescriptorBuilder(StringRef ModuleName, Layout.Mod = ModIndex; } +DbiModuleDescriptorBuilder::~DbiModuleDescriptorBuilder() {} + uint16_t DbiModuleDescriptorBuilder::getStreamIndex() const { return Layout.ModDiStream; } @@ -69,6 +73,15 @@ void DbiModuleDescriptorBuilder::addSourceFile(StringRef Path) { SourceFiles.push_back(Path); } +uint32_t DbiModuleDescriptorBuilder::calculateC13DebugInfoSize() const { + uint32_t Result = 0; + for (const auto &Builder : C13Builders) { + assert(Builder && "Empty C13 Fragment Builder!"); + Result += Builder->calculateSerializedLength(); + } + return Result; +} + uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const { uint32_t L = sizeof(Layout); uint32_t M = ModuleName.size() + 1; @@ -80,7 +93,7 @@ void DbiModuleDescriptorBuilder::finalize() { Layout.FileNameOffs = 0; // TODO: Fix this Layout.Flags = 0; // TODO: Fix this Layout.C11Bytes = 0; - Layout.C13Bytes = 0; + Layout.C13Bytes = calculateC13DebugInfoSize(); (void)Layout.Mod; // Set in constructor (void)Layout.ModDiStream; // Set in finalizeMsfLayout Layout.NumFiles = SourceFiles.size(); @@ -94,7 +107,9 @@ void DbiModuleDescriptorBuilder::finalize() { Error DbiModuleDescriptorBuilder::finalizeMsfLayout() { this->Layout.ModDiStream = kInvalidStreamIndex; - auto ExpectedSN = MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize)); + uint32_t C13Size = calculateC13DebugInfoSize(); + auto ExpectedSN = + MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize, C13Size)); if (!ExpectedSN) return ExpectedSN.takeError(); Layout.ModDiStream = *ExpectedSN; @@ -130,7 +145,13 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter, if (auto EC = SymbolWriter.writeStreamRef(RecordsRef)) return EC; // TODO: Write C11 Line data - // TODO: Write C13 Line data + + for (const auto &Builder : C13Builders) { + assert(Builder && "Empty C13 Fragment Builder!"); + if (auto EC = Builder->commit(SymbolWriter)) + return EC; + } + // TODO: Figure out what GlobalRefs substream actually is and populate it. if (auto EC = SymbolWriter.writeInteger<uint32_t>(0)) return EC; @@ -139,3 +160,29 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter, } return Error::success(); } + +void DbiModuleDescriptorBuilder::addC13LineFragment( + std::unique_ptr<ModuleDebugLineFragment> Lines) { + ModuleDebugLineFragment &Frag = *Lines; + + // File Checksums have to come first, so push an empty entry on if this + // is the first. + if (C13Builders.empty()) + C13Builders.push_back(nullptr); + + this->LineInfo.push_back(std::move(Lines)); + C13Builders.push_back( + llvm::make_unique<ModuleDebugFragmentRecordBuilder>(Frag.kind(), Frag)); +} + +void DbiModuleDescriptorBuilder::setC13FileChecksums( + std::unique_ptr<ModuleDebugFileChecksumFragment> Checksums) { + assert(!ChecksumInfo && "Can't have more than one checksum info!"); + + if (C13Builders.empty()) + C13Builders.push_back(nullptr); + + ChecksumInfo = std::move(Checksums); + C13Builders[0] = llvm::make_unique<ModuleDebugFragmentRecordBuilder>( + ChecksumInfo->kind(), *ChecksumInfo); +} diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp index 62bda65cd99..c19a2f0d311 100644 --- a/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -101,6 +101,14 @@ Error DbiStreamBuilder::addModuleSourceFile(StringRef Module, StringRef 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) diff --git a/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStreamBuilder.cpp new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStreamBuilder.cpp diff --git a/llvm/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp index e0f8370ab60..40dc8e1bfcb 100644 --- a/llvm/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp @@ -29,6 +29,12 @@ uint32_t StringTableBuilder::insert(StringRef S) { return P.first->second; } +uint32_t StringTableBuilder::getStringIndex(StringRef S) { + auto Iter = Strings.find(S); + assert(Iter != Strings.end()); + return Iter->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 |