189cb50c9SDimitry Andric //===- DebugLinesSubsection.cpp -------------------------------*- C++-*-===// 289cb50c9SDimitry Andric // 389cb50c9SDimitry Andric // The LLVM Compiler Infrastructure 489cb50c9SDimitry Andric // 589cb50c9SDimitry Andric // This file is distributed under the University of Illinois Open Source 689cb50c9SDimitry Andric // License. See LICENSE.TXT for details. 789cb50c9SDimitry Andric // 889cb50c9SDimitry Andric //===----------------------------------------------------------------------===// 989cb50c9SDimitry Andric 1089cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" 1189cb50c9SDimitry Andric 1289cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewError.h" 1389cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" 1489cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" 1589cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" 1689cb50c9SDimitry Andric 1789cb50c9SDimitry Andric using namespace llvm; 1889cb50c9SDimitry Andric using namespace llvm::codeview; 1989cb50c9SDimitry Andric 20*db17bf38SDimitry Andric Error LineColumnExtractor::operator()(BinaryStreamRef Stream, uint32_t &Len, 21*db17bf38SDimitry Andric LineColumnEntry &Item) { 2289cb50c9SDimitry Andric using namespace codeview; 2389cb50c9SDimitry Andric const LineBlockFragmentHeader *BlockHeader; 2489cb50c9SDimitry Andric BinaryStreamReader Reader(Stream); 2589cb50c9SDimitry Andric if (auto EC = Reader.readObject(BlockHeader)) 2689cb50c9SDimitry Andric return EC; 2789cb50c9SDimitry Andric bool HasColumn = Header->Flags & uint16_t(LF_HaveColumns); 2889cb50c9SDimitry Andric uint32_t LineInfoSize = 2989cb50c9SDimitry Andric BlockHeader->NumLines * 3089cb50c9SDimitry Andric (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0)); 3189cb50c9SDimitry Andric if (BlockHeader->BlockSize < sizeof(LineBlockFragmentHeader)) 3289cb50c9SDimitry Andric return make_error<CodeViewError>(cv_error_code::corrupt_record, 3389cb50c9SDimitry Andric "Invalid line block record size"); 3489cb50c9SDimitry Andric uint32_t Size = BlockHeader->BlockSize - sizeof(LineBlockFragmentHeader); 3589cb50c9SDimitry Andric if (LineInfoSize > Size) 3689cb50c9SDimitry Andric return make_error<CodeViewError>(cv_error_code::corrupt_record, 3789cb50c9SDimitry Andric "Invalid line block record size"); 3889cb50c9SDimitry Andric // The value recorded in BlockHeader->BlockSize includes the size of 3989cb50c9SDimitry Andric // LineBlockFragmentHeader. 4089cb50c9SDimitry Andric Len = BlockHeader->BlockSize; 4189cb50c9SDimitry Andric Item.NameIndex = BlockHeader->NameIndex; 4289cb50c9SDimitry Andric if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines)) 4389cb50c9SDimitry Andric return EC; 4489cb50c9SDimitry Andric if (HasColumn) { 4589cb50c9SDimitry Andric if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines)) 4689cb50c9SDimitry Andric return EC; 4789cb50c9SDimitry Andric } 4889cb50c9SDimitry Andric return Error::success(); 4989cb50c9SDimitry Andric } 5089cb50c9SDimitry Andric 5189cb50c9SDimitry Andric DebugLinesSubsectionRef::DebugLinesSubsectionRef() 5289cb50c9SDimitry Andric : DebugSubsectionRef(DebugSubsectionKind::Lines) {} 5389cb50c9SDimitry Andric 5489cb50c9SDimitry Andric Error DebugLinesSubsectionRef::initialize(BinaryStreamReader Reader) { 5589cb50c9SDimitry Andric if (auto EC = Reader.readObject(Header)) 5689cb50c9SDimitry Andric return EC; 5789cb50c9SDimitry Andric 58*db17bf38SDimitry Andric LinesAndColumns.getExtractor().Header = Header; 59*db17bf38SDimitry Andric if (auto EC = Reader.readArray(LinesAndColumns, Reader.bytesRemaining())) 6089cb50c9SDimitry Andric return EC; 6189cb50c9SDimitry Andric 6289cb50c9SDimitry Andric return Error::success(); 6389cb50c9SDimitry Andric } 6489cb50c9SDimitry Andric 6589cb50c9SDimitry Andric bool DebugLinesSubsectionRef::hasColumnInfo() const { 6689cb50c9SDimitry Andric return !!(Header->Flags & LF_HaveColumns); 6789cb50c9SDimitry Andric } 6889cb50c9SDimitry Andric 6989cb50c9SDimitry Andric DebugLinesSubsection::DebugLinesSubsection(DebugChecksumsSubsection &Checksums, 7089cb50c9SDimitry Andric DebugStringTableSubsection &Strings) 7189cb50c9SDimitry Andric : DebugSubsection(DebugSubsectionKind::Lines), Checksums(Checksums) {} 7289cb50c9SDimitry Andric 7389cb50c9SDimitry Andric void DebugLinesSubsection::createBlock(StringRef FileName) { 7489cb50c9SDimitry Andric uint32_t Offset = Checksums.mapChecksumOffset(FileName); 7589cb50c9SDimitry Andric 7689cb50c9SDimitry Andric Blocks.emplace_back(Offset); 7789cb50c9SDimitry Andric } 7889cb50c9SDimitry Andric 7989cb50c9SDimitry Andric void DebugLinesSubsection::addLineInfo(uint32_t Offset, const LineInfo &Line) { 8089cb50c9SDimitry Andric Block &B = Blocks.back(); 8189cb50c9SDimitry Andric LineNumberEntry LNE; 8289cb50c9SDimitry Andric LNE.Flags = Line.getRawData(); 8389cb50c9SDimitry Andric LNE.Offset = Offset; 8489cb50c9SDimitry Andric B.Lines.push_back(LNE); 8589cb50c9SDimitry Andric } 8689cb50c9SDimitry Andric 8789cb50c9SDimitry Andric void DebugLinesSubsection::addLineAndColumnInfo(uint32_t Offset, 8889cb50c9SDimitry Andric const LineInfo &Line, 8989cb50c9SDimitry Andric uint32_t ColStart, 9089cb50c9SDimitry Andric uint32_t ColEnd) { 9189cb50c9SDimitry Andric Block &B = Blocks.back(); 9289cb50c9SDimitry Andric assert(B.Lines.size() == B.Columns.size()); 9389cb50c9SDimitry Andric 9489cb50c9SDimitry Andric addLineInfo(Offset, Line); 9589cb50c9SDimitry Andric ColumnNumberEntry CNE; 9689cb50c9SDimitry Andric CNE.StartColumn = ColStart; 9789cb50c9SDimitry Andric CNE.EndColumn = ColEnd; 9889cb50c9SDimitry Andric B.Columns.push_back(CNE); 9989cb50c9SDimitry Andric } 10089cb50c9SDimitry Andric 10189cb50c9SDimitry Andric Error DebugLinesSubsection::commit(BinaryStreamWriter &Writer) const { 10289cb50c9SDimitry Andric LineFragmentHeader Header; 10389cb50c9SDimitry Andric Header.CodeSize = CodeSize; 10489cb50c9SDimitry Andric Header.Flags = hasColumnInfo() ? LF_HaveColumns : 0; 10589cb50c9SDimitry Andric Header.RelocOffset = RelocOffset; 10689cb50c9SDimitry Andric Header.RelocSegment = RelocSegment; 10789cb50c9SDimitry Andric 10889cb50c9SDimitry Andric if (auto EC = Writer.writeObject(Header)) 10989cb50c9SDimitry Andric return EC; 11089cb50c9SDimitry Andric 11189cb50c9SDimitry Andric for (const auto &B : Blocks) { 11289cb50c9SDimitry Andric LineBlockFragmentHeader BlockHeader; 11389cb50c9SDimitry Andric assert(B.Lines.size() == B.Columns.size() || B.Columns.empty()); 11489cb50c9SDimitry Andric 11589cb50c9SDimitry Andric BlockHeader.NumLines = B.Lines.size(); 11689cb50c9SDimitry Andric BlockHeader.BlockSize = sizeof(LineBlockFragmentHeader); 11789cb50c9SDimitry Andric BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(LineNumberEntry); 11889cb50c9SDimitry Andric if (hasColumnInfo()) 11989cb50c9SDimitry Andric BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(ColumnNumberEntry); 12089cb50c9SDimitry Andric BlockHeader.NameIndex = B.ChecksumBufferOffset; 12189cb50c9SDimitry Andric if (auto EC = Writer.writeObject(BlockHeader)) 12289cb50c9SDimitry Andric return EC; 12389cb50c9SDimitry Andric 12489cb50c9SDimitry Andric if (auto EC = Writer.writeArray(makeArrayRef(B.Lines))) 12589cb50c9SDimitry Andric return EC; 12689cb50c9SDimitry Andric 12789cb50c9SDimitry Andric if (hasColumnInfo()) { 12889cb50c9SDimitry Andric if (auto EC = Writer.writeArray(makeArrayRef(B.Columns))) 12989cb50c9SDimitry Andric return EC; 13089cb50c9SDimitry Andric } 13189cb50c9SDimitry Andric } 13289cb50c9SDimitry Andric return Error::success(); 13389cb50c9SDimitry Andric } 13489cb50c9SDimitry Andric 13589cb50c9SDimitry Andric uint32_t DebugLinesSubsection::calculateSerializedSize() const { 13689cb50c9SDimitry Andric uint32_t Size = sizeof(LineFragmentHeader); 13789cb50c9SDimitry Andric for (const auto &B : Blocks) { 13889cb50c9SDimitry Andric Size += sizeof(LineBlockFragmentHeader); 13989cb50c9SDimitry Andric Size += B.Lines.size() * sizeof(LineNumberEntry); 14089cb50c9SDimitry Andric if (hasColumnInfo()) 14189cb50c9SDimitry Andric Size += B.Columns.size() * sizeof(ColumnNumberEntry); 14289cb50c9SDimitry Andric } 14389cb50c9SDimitry Andric return Size; 14489cb50c9SDimitry Andric } 14589cb50c9SDimitry Andric 14689cb50c9SDimitry Andric void DebugLinesSubsection::setRelocationAddress(uint16_t Segment, 147*db17bf38SDimitry Andric uint32_t Offset) { 14889cb50c9SDimitry Andric RelocOffset = Offset; 14989cb50c9SDimitry Andric RelocSegment = Segment; 15089cb50c9SDimitry Andric } 15189cb50c9SDimitry Andric 15289cb50c9SDimitry Andric void DebugLinesSubsection::setCodeSize(uint32_t Size) { CodeSize = Size; } 15389cb50c9SDimitry Andric 15489cb50c9SDimitry Andric void DebugLinesSubsection::setFlags(LineFlags Flags) { this->Flags = Flags; } 15589cb50c9SDimitry Andric 15689cb50c9SDimitry Andric bool DebugLinesSubsection::hasColumnInfo() const { 15789cb50c9SDimitry Andric return Flags & LF_HaveColumns; 15889cb50c9SDimitry Andric } 159