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