18c099fe0SZachary Turner //===- DebugLinesSubsection.cpp -------------------------------*- C++-*-===// 28c099fe0SZachary Turner // 38c099fe0SZachary Turner // The LLVM Compiler Infrastructure 48c099fe0SZachary Turner // 58c099fe0SZachary Turner // This file is distributed under the University of Illinois Open Source 68c099fe0SZachary Turner // License. See LICENSE.TXT for details. 78c099fe0SZachary Turner // 88c099fe0SZachary Turner //===----------------------------------------------------------------------===// 98c099fe0SZachary Turner 108c099fe0SZachary Turner #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" 118c099fe0SZachary Turner 128c099fe0SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewError.h" 138c099fe0SZachary Turner #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" 14591312c5SZachary Turner #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" 158c099fe0SZachary Turner #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" 168c099fe0SZachary Turner 178c099fe0SZachary Turner using namespace llvm; 188c099fe0SZachary Turner using namespace llvm::codeview; 198c099fe0SZachary Turner 208c099fe0SZachary Turner Error LineColumnExtractor::extract(BinaryStreamRef Stream, uint32_t &Len, 218c099fe0SZachary Turner LineColumnEntry &Item, 228c099fe0SZachary Turner const LineFragmentHeader *Header) { 238c099fe0SZachary Turner using namespace codeview; 248c099fe0SZachary Turner const LineBlockFragmentHeader *BlockHeader; 258c099fe0SZachary Turner BinaryStreamReader Reader(Stream); 268c099fe0SZachary Turner if (auto EC = Reader.readObject(BlockHeader)) 278c099fe0SZachary Turner return EC; 288c099fe0SZachary Turner bool HasColumn = Header->Flags & uint16_t(LF_HaveColumns); 298c099fe0SZachary Turner uint32_t LineInfoSize = 308c099fe0SZachary Turner BlockHeader->NumLines * 318c099fe0SZachary Turner (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0)); 328c099fe0SZachary Turner if (BlockHeader->BlockSize < sizeof(LineBlockFragmentHeader)) 338c099fe0SZachary Turner return make_error<CodeViewError>(cv_error_code::corrupt_record, 348c099fe0SZachary Turner "Invalid line block record size"); 358c099fe0SZachary Turner uint32_t Size = BlockHeader->BlockSize - sizeof(LineBlockFragmentHeader); 368c099fe0SZachary Turner if (LineInfoSize > Size) 378c099fe0SZachary Turner return make_error<CodeViewError>(cv_error_code::corrupt_record, 388c099fe0SZachary Turner "Invalid line block record size"); 398c099fe0SZachary Turner // The value recorded in BlockHeader->BlockSize includes the size of 408c099fe0SZachary Turner // LineBlockFragmentHeader. 418c099fe0SZachary Turner Len = BlockHeader->BlockSize; 428c099fe0SZachary Turner Item.NameIndex = BlockHeader->NameIndex; 438c099fe0SZachary Turner if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines)) 448c099fe0SZachary Turner return EC; 458c099fe0SZachary Turner if (HasColumn) { 468c099fe0SZachary Turner if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines)) 478c099fe0SZachary Turner return EC; 488c099fe0SZachary Turner } 498c099fe0SZachary Turner return Error::success(); 508c099fe0SZachary Turner } 518c099fe0SZachary Turner 528c099fe0SZachary Turner DebugLinesSubsectionRef::DebugLinesSubsectionRef() 538c099fe0SZachary Turner : DebugSubsectionRef(DebugSubsectionKind::Lines) {} 548c099fe0SZachary Turner 558c099fe0SZachary Turner Error DebugLinesSubsectionRef::initialize(BinaryStreamReader Reader) { 568c099fe0SZachary Turner if (auto EC = Reader.readObject(Header)) 578c099fe0SZachary Turner return EC; 588c099fe0SZachary Turner 598c099fe0SZachary Turner if (auto EC = 608c099fe0SZachary Turner Reader.readArray(LinesAndColumns, Reader.bytesRemaining(), Header)) 618c099fe0SZachary Turner return EC; 628c099fe0SZachary Turner 638c099fe0SZachary Turner return Error::success(); 648c099fe0SZachary Turner } 658c099fe0SZachary Turner 668c099fe0SZachary Turner bool DebugLinesSubsectionRef::hasColumnInfo() const { 678c099fe0SZachary Turner return !!(Header->Flags & LF_HaveColumns); 688c099fe0SZachary Turner } 698c099fe0SZachary Turner 708c099fe0SZachary Turner DebugLinesSubsection::DebugLinesSubsection(DebugChecksumsSubsection &Checksums, 71591312c5SZachary Turner DebugStringTableSubsection &Strings) 728c099fe0SZachary Turner : DebugSubsection(DebugSubsectionKind::Lines), Checksums(Checksums) {} 738c099fe0SZachary Turner 748c099fe0SZachary Turner void DebugLinesSubsection::createBlock(StringRef FileName) { 758c099fe0SZachary Turner uint32_t Offset = Checksums.mapChecksumOffset(FileName); 768c099fe0SZachary Turner 778c099fe0SZachary Turner Blocks.emplace_back(Offset); 788c099fe0SZachary Turner } 798c099fe0SZachary Turner 808c099fe0SZachary Turner void DebugLinesSubsection::addLineInfo(uint32_t Offset, const LineInfo &Line) { 818c099fe0SZachary Turner Block &B = Blocks.back(); 828c099fe0SZachary Turner LineNumberEntry LNE; 838c099fe0SZachary Turner LNE.Flags = Line.getRawData(); 848c099fe0SZachary Turner LNE.Offset = Offset; 858c099fe0SZachary Turner B.Lines.push_back(LNE); 868c099fe0SZachary Turner } 878c099fe0SZachary Turner 888c099fe0SZachary Turner void DebugLinesSubsection::addLineAndColumnInfo(uint32_t Offset, 898c099fe0SZachary Turner const LineInfo &Line, 908c099fe0SZachary Turner uint32_t ColStart, 918c099fe0SZachary Turner uint32_t ColEnd) { 928c099fe0SZachary Turner Block &B = Blocks.back(); 938c099fe0SZachary Turner assert(B.Lines.size() == B.Columns.size()); 948c099fe0SZachary Turner 958c099fe0SZachary Turner addLineInfo(Offset, Line); 968c099fe0SZachary Turner ColumnNumberEntry CNE; 978c099fe0SZachary Turner CNE.StartColumn = ColStart; 988c099fe0SZachary Turner CNE.EndColumn = ColEnd; 998c099fe0SZachary Turner B.Columns.push_back(CNE); 1008c099fe0SZachary Turner } 1018c099fe0SZachary Turner 102591312c5SZachary Turner Error DebugLinesSubsection::commit(BinaryStreamWriter &Writer) const { 1038c099fe0SZachary Turner LineFragmentHeader Header; 1048c099fe0SZachary Turner Header.CodeSize = CodeSize; 1058c099fe0SZachary Turner Header.Flags = hasColumnInfo() ? LF_HaveColumns : 0; 1068c099fe0SZachary Turner Header.RelocOffset = RelocOffset; 1078c099fe0SZachary Turner Header.RelocSegment = RelocSegment; 1088c099fe0SZachary Turner 1098c099fe0SZachary Turner if (auto EC = Writer.writeObject(Header)) 1108c099fe0SZachary Turner return EC; 1118c099fe0SZachary Turner 1128c099fe0SZachary Turner for (const auto &B : Blocks) { 1138c099fe0SZachary Turner LineBlockFragmentHeader BlockHeader; 1148c099fe0SZachary Turner assert(B.Lines.size() == B.Columns.size() || B.Columns.empty()); 1158c099fe0SZachary Turner 1168c099fe0SZachary Turner BlockHeader.NumLines = B.Lines.size(); 1178c099fe0SZachary Turner BlockHeader.BlockSize = sizeof(LineBlockFragmentHeader); 1188c099fe0SZachary Turner BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(LineNumberEntry); 1198c099fe0SZachary Turner if (hasColumnInfo()) 1208c099fe0SZachary Turner BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(ColumnNumberEntry); 1218c099fe0SZachary Turner BlockHeader.NameIndex = B.ChecksumBufferOffset; 1228c099fe0SZachary Turner if (auto EC = Writer.writeObject(BlockHeader)) 1238c099fe0SZachary Turner return EC; 1248c099fe0SZachary Turner 1258c099fe0SZachary Turner if (auto EC = Writer.writeArray(makeArrayRef(B.Lines))) 1268c099fe0SZachary Turner return EC; 1278c099fe0SZachary Turner 1288c099fe0SZachary Turner if (hasColumnInfo()) { 1298c099fe0SZachary Turner if (auto EC = Writer.writeArray(makeArrayRef(B.Columns))) 1308c099fe0SZachary Turner return EC; 1318c099fe0SZachary Turner } 1328c099fe0SZachary Turner } 1338c099fe0SZachary Turner return Error::success(); 1348c099fe0SZachary Turner } 1358c099fe0SZachary Turner 136591312c5SZachary Turner uint32_t DebugLinesSubsection::calculateSerializedSize() const { 1378c099fe0SZachary Turner uint32_t Size = sizeof(LineFragmentHeader); 1388c099fe0SZachary Turner for (const auto &B : Blocks) { 1398c099fe0SZachary Turner Size += sizeof(LineBlockFragmentHeader); 1408c099fe0SZachary Turner Size += B.Lines.size() * sizeof(LineNumberEntry); 1418c099fe0SZachary Turner if (hasColumnInfo()) 1428c099fe0SZachary Turner Size += B.Columns.size() * sizeof(ColumnNumberEntry); 1438c099fe0SZachary Turner } 1448c099fe0SZachary Turner return Size; 1458c099fe0SZachary Turner } 1468c099fe0SZachary Turner 1478c099fe0SZachary Turner void DebugLinesSubsection::setRelocationAddress(uint16_t Segment, 148*fdf499bfSBob Haarman uint32_t Offset) { 1498c099fe0SZachary Turner RelocOffset = Offset; 1508c099fe0SZachary Turner RelocSegment = Segment; 1518c099fe0SZachary Turner } 1528c099fe0SZachary Turner 1538c099fe0SZachary Turner void DebugLinesSubsection::setCodeSize(uint32_t Size) { CodeSize = Size; } 1548c099fe0SZachary Turner 1558c099fe0SZachary Turner void DebugLinesSubsection::setFlags(LineFlags Flags) { this->Flags = Flags; } 1568c099fe0SZachary Turner 1578c099fe0SZachary Turner bool DebugLinesSubsection::hasColumnInfo() const { 1588c099fe0SZachary Turner return Flags & LF_HaveColumns; 1598c099fe0SZachary Turner } 160