1*89cb50c9SDimitry Andric //===- DebugLinesSubsection.cpp -------------------------------*- C++-*-===// 2*89cb50c9SDimitry Andric // 3*89cb50c9SDimitry Andric // The LLVM Compiler Infrastructure 4*89cb50c9SDimitry Andric // 5*89cb50c9SDimitry Andric // This file is distributed under the University of Illinois Open Source 6*89cb50c9SDimitry Andric // License. See LICENSE.TXT for details. 7*89cb50c9SDimitry Andric // 8*89cb50c9SDimitry Andric //===----------------------------------------------------------------------===// 9*89cb50c9SDimitry Andric 10*89cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" 11*89cb50c9SDimitry Andric 12*89cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewError.h" 13*89cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" 14*89cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" 15*89cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" 16*89cb50c9SDimitry Andric 17*89cb50c9SDimitry Andric using namespace llvm; 18*89cb50c9SDimitry Andric using namespace llvm::codeview; 19*89cb50c9SDimitry Andric 20*89cb50c9SDimitry Andric Error LineColumnExtractor::extract(BinaryStreamRef Stream, uint32_t &Len, 21*89cb50c9SDimitry Andric LineColumnEntry &Item, 22*89cb50c9SDimitry Andric const LineFragmentHeader *Header) { 23*89cb50c9SDimitry Andric using namespace codeview; 24*89cb50c9SDimitry Andric const LineBlockFragmentHeader *BlockHeader; 25*89cb50c9SDimitry Andric BinaryStreamReader Reader(Stream); 26*89cb50c9SDimitry Andric if (auto EC = Reader.readObject(BlockHeader)) 27*89cb50c9SDimitry Andric return EC; 28*89cb50c9SDimitry Andric bool HasColumn = Header->Flags & uint16_t(LF_HaveColumns); 29*89cb50c9SDimitry Andric uint32_t LineInfoSize = 30*89cb50c9SDimitry Andric BlockHeader->NumLines * 31*89cb50c9SDimitry Andric (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0)); 32*89cb50c9SDimitry Andric if (BlockHeader->BlockSize < sizeof(LineBlockFragmentHeader)) 33*89cb50c9SDimitry Andric return make_error<CodeViewError>(cv_error_code::corrupt_record, 34*89cb50c9SDimitry Andric "Invalid line block record size"); 35*89cb50c9SDimitry Andric uint32_t Size = BlockHeader->BlockSize - sizeof(LineBlockFragmentHeader); 36*89cb50c9SDimitry Andric if (LineInfoSize > Size) 37*89cb50c9SDimitry Andric return make_error<CodeViewError>(cv_error_code::corrupt_record, 38*89cb50c9SDimitry Andric "Invalid line block record size"); 39*89cb50c9SDimitry Andric // The value recorded in BlockHeader->BlockSize includes the size of 40*89cb50c9SDimitry Andric // LineBlockFragmentHeader. 41*89cb50c9SDimitry Andric Len = BlockHeader->BlockSize; 42*89cb50c9SDimitry Andric Item.NameIndex = BlockHeader->NameIndex; 43*89cb50c9SDimitry Andric if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines)) 44*89cb50c9SDimitry Andric return EC; 45*89cb50c9SDimitry Andric if (HasColumn) { 46*89cb50c9SDimitry Andric if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines)) 47*89cb50c9SDimitry Andric return EC; 48*89cb50c9SDimitry Andric } 49*89cb50c9SDimitry Andric return Error::success(); 50*89cb50c9SDimitry Andric } 51*89cb50c9SDimitry Andric 52*89cb50c9SDimitry Andric DebugLinesSubsectionRef::DebugLinesSubsectionRef() 53*89cb50c9SDimitry Andric : DebugSubsectionRef(DebugSubsectionKind::Lines) {} 54*89cb50c9SDimitry Andric 55*89cb50c9SDimitry Andric Error DebugLinesSubsectionRef::initialize(BinaryStreamReader Reader) { 56*89cb50c9SDimitry Andric if (auto EC = Reader.readObject(Header)) 57*89cb50c9SDimitry Andric return EC; 58*89cb50c9SDimitry Andric 59*89cb50c9SDimitry Andric if (auto EC = 60*89cb50c9SDimitry Andric Reader.readArray(LinesAndColumns, Reader.bytesRemaining(), Header)) 61*89cb50c9SDimitry Andric return EC; 62*89cb50c9SDimitry Andric 63*89cb50c9SDimitry Andric return Error::success(); 64*89cb50c9SDimitry Andric } 65*89cb50c9SDimitry Andric 66*89cb50c9SDimitry Andric bool DebugLinesSubsectionRef::hasColumnInfo() const { 67*89cb50c9SDimitry Andric return !!(Header->Flags & LF_HaveColumns); 68*89cb50c9SDimitry Andric } 69*89cb50c9SDimitry Andric 70*89cb50c9SDimitry Andric DebugLinesSubsection::DebugLinesSubsection(DebugChecksumsSubsection &Checksums, 71*89cb50c9SDimitry Andric DebugStringTableSubsection &Strings) 72*89cb50c9SDimitry Andric : DebugSubsection(DebugSubsectionKind::Lines), Checksums(Checksums) {} 73*89cb50c9SDimitry Andric 74*89cb50c9SDimitry Andric void DebugLinesSubsection::createBlock(StringRef FileName) { 75*89cb50c9SDimitry Andric uint32_t Offset = Checksums.mapChecksumOffset(FileName); 76*89cb50c9SDimitry Andric 77*89cb50c9SDimitry Andric Blocks.emplace_back(Offset); 78*89cb50c9SDimitry Andric } 79*89cb50c9SDimitry Andric 80*89cb50c9SDimitry Andric void DebugLinesSubsection::addLineInfo(uint32_t Offset, const LineInfo &Line) { 81*89cb50c9SDimitry Andric Block &B = Blocks.back(); 82*89cb50c9SDimitry Andric LineNumberEntry LNE; 83*89cb50c9SDimitry Andric LNE.Flags = Line.getRawData(); 84*89cb50c9SDimitry Andric LNE.Offset = Offset; 85*89cb50c9SDimitry Andric B.Lines.push_back(LNE); 86*89cb50c9SDimitry Andric } 87*89cb50c9SDimitry Andric 88*89cb50c9SDimitry Andric void DebugLinesSubsection::addLineAndColumnInfo(uint32_t Offset, 89*89cb50c9SDimitry Andric const LineInfo &Line, 90*89cb50c9SDimitry Andric uint32_t ColStart, 91*89cb50c9SDimitry Andric uint32_t ColEnd) { 92*89cb50c9SDimitry Andric Block &B = Blocks.back(); 93*89cb50c9SDimitry Andric assert(B.Lines.size() == B.Columns.size()); 94*89cb50c9SDimitry Andric 95*89cb50c9SDimitry Andric addLineInfo(Offset, Line); 96*89cb50c9SDimitry Andric ColumnNumberEntry CNE; 97*89cb50c9SDimitry Andric CNE.StartColumn = ColStart; 98*89cb50c9SDimitry Andric CNE.EndColumn = ColEnd; 99*89cb50c9SDimitry Andric B.Columns.push_back(CNE); 100*89cb50c9SDimitry Andric } 101*89cb50c9SDimitry Andric 102*89cb50c9SDimitry Andric Error DebugLinesSubsection::commit(BinaryStreamWriter &Writer) const { 103*89cb50c9SDimitry Andric LineFragmentHeader Header; 104*89cb50c9SDimitry Andric Header.CodeSize = CodeSize; 105*89cb50c9SDimitry Andric Header.Flags = hasColumnInfo() ? LF_HaveColumns : 0; 106*89cb50c9SDimitry Andric Header.RelocOffset = RelocOffset; 107*89cb50c9SDimitry Andric Header.RelocSegment = RelocSegment; 108*89cb50c9SDimitry Andric 109*89cb50c9SDimitry Andric if (auto EC = Writer.writeObject(Header)) 110*89cb50c9SDimitry Andric return EC; 111*89cb50c9SDimitry Andric 112*89cb50c9SDimitry Andric for (const auto &B : Blocks) { 113*89cb50c9SDimitry Andric LineBlockFragmentHeader BlockHeader; 114*89cb50c9SDimitry Andric assert(B.Lines.size() == B.Columns.size() || B.Columns.empty()); 115*89cb50c9SDimitry Andric 116*89cb50c9SDimitry Andric BlockHeader.NumLines = B.Lines.size(); 117*89cb50c9SDimitry Andric BlockHeader.BlockSize = sizeof(LineBlockFragmentHeader); 118*89cb50c9SDimitry Andric BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(LineNumberEntry); 119*89cb50c9SDimitry Andric if (hasColumnInfo()) 120*89cb50c9SDimitry Andric BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(ColumnNumberEntry); 121*89cb50c9SDimitry Andric BlockHeader.NameIndex = B.ChecksumBufferOffset; 122*89cb50c9SDimitry Andric if (auto EC = Writer.writeObject(BlockHeader)) 123*89cb50c9SDimitry Andric return EC; 124*89cb50c9SDimitry Andric 125*89cb50c9SDimitry Andric if (auto EC = Writer.writeArray(makeArrayRef(B.Lines))) 126*89cb50c9SDimitry Andric return EC; 127*89cb50c9SDimitry Andric 128*89cb50c9SDimitry Andric if (hasColumnInfo()) { 129*89cb50c9SDimitry Andric if (auto EC = Writer.writeArray(makeArrayRef(B.Columns))) 130*89cb50c9SDimitry Andric return EC; 131*89cb50c9SDimitry Andric } 132*89cb50c9SDimitry Andric } 133*89cb50c9SDimitry Andric return Error::success(); 134*89cb50c9SDimitry Andric } 135*89cb50c9SDimitry Andric 136*89cb50c9SDimitry Andric uint32_t DebugLinesSubsection::calculateSerializedSize() const { 137*89cb50c9SDimitry Andric uint32_t Size = sizeof(LineFragmentHeader); 138*89cb50c9SDimitry Andric for (const auto &B : Blocks) { 139*89cb50c9SDimitry Andric Size += sizeof(LineBlockFragmentHeader); 140*89cb50c9SDimitry Andric Size += B.Lines.size() * sizeof(LineNumberEntry); 141*89cb50c9SDimitry Andric if (hasColumnInfo()) 142*89cb50c9SDimitry Andric Size += B.Columns.size() * sizeof(ColumnNumberEntry); 143*89cb50c9SDimitry Andric } 144*89cb50c9SDimitry Andric return Size; 145*89cb50c9SDimitry Andric } 146*89cb50c9SDimitry Andric 147*89cb50c9SDimitry Andric void DebugLinesSubsection::setRelocationAddress(uint16_t Segment, 148*89cb50c9SDimitry Andric uint16_t Offset) { 149*89cb50c9SDimitry Andric RelocOffset = Offset; 150*89cb50c9SDimitry Andric RelocSegment = Segment; 151*89cb50c9SDimitry Andric } 152*89cb50c9SDimitry Andric 153*89cb50c9SDimitry Andric void DebugLinesSubsection::setCodeSize(uint32_t Size) { CodeSize = Size; } 154*89cb50c9SDimitry Andric 155*89cb50c9SDimitry Andric void DebugLinesSubsection::setFlags(LineFlags Flags) { this->Flags = Flags; } 156*89cb50c9SDimitry Andric 157*89cb50c9SDimitry Andric bool DebugLinesSubsection::hasColumnInfo() const { 158*89cb50c9SDimitry Andric return Flags & LF_HaveColumns; 159*89cb50c9SDimitry Andric } 160