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 20*7e62cd17SZachary Turner Error LineColumnExtractor::operator()(BinaryStreamRef Stream, uint32_t &Len, 21*7e62cd17SZachary Turner LineColumnEntry &Item) { 228c099fe0SZachary Turner using namespace codeview; 238c099fe0SZachary Turner const LineBlockFragmentHeader *BlockHeader; 248c099fe0SZachary Turner BinaryStreamReader Reader(Stream); 258c099fe0SZachary Turner if (auto EC = Reader.readObject(BlockHeader)) 268c099fe0SZachary Turner return EC; 278c099fe0SZachary Turner bool HasColumn = Header->Flags & uint16_t(LF_HaveColumns); 288c099fe0SZachary Turner uint32_t LineInfoSize = 298c099fe0SZachary Turner BlockHeader->NumLines * 308c099fe0SZachary Turner (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0)); 318c099fe0SZachary Turner if (BlockHeader->BlockSize < sizeof(LineBlockFragmentHeader)) 328c099fe0SZachary Turner return make_error<CodeViewError>(cv_error_code::corrupt_record, 338c099fe0SZachary Turner "Invalid line block record size"); 348c099fe0SZachary Turner uint32_t Size = BlockHeader->BlockSize - sizeof(LineBlockFragmentHeader); 358c099fe0SZachary Turner if (LineInfoSize > Size) 368c099fe0SZachary Turner return make_error<CodeViewError>(cv_error_code::corrupt_record, 378c099fe0SZachary Turner "Invalid line block record size"); 388c099fe0SZachary Turner // The value recorded in BlockHeader->BlockSize includes the size of 398c099fe0SZachary Turner // LineBlockFragmentHeader. 408c099fe0SZachary Turner Len = BlockHeader->BlockSize; 418c099fe0SZachary Turner Item.NameIndex = BlockHeader->NameIndex; 428c099fe0SZachary Turner if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines)) 438c099fe0SZachary Turner return EC; 448c099fe0SZachary Turner if (HasColumn) { 458c099fe0SZachary Turner if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines)) 468c099fe0SZachary Turner return EC; 478c099fe0SZachary Turner } 488c099fe0SZachary Turner return Error::success(); 498c099fe0SZachary Turner } 508c099fe0SZachary Turner 518c099fe0SZachary Turner DebugLinesSubsectionRef::DebugLinesSubsectionRef() 528c099fe0SZachary Turner : DebugSubsectionRef(DebugSubsectionKind::Lines) {} 538c099fe0SZachary Turner 548c099fe0SZachary Turner Error DebugLinesSubsectionRef::initialize(BinaryStreamReader Reader) { 558c099fe0SZachary Turner if (auto EC = Reader.readObject(Header)) 568c099fe0SZachary Turner return EC; 578c099fe0SZachary Turner 58*7e62cd17SZachary Turner LinesAndColumns.getExtractor().Header = Header; 59*7e62cd17SZachary Turner if (auto EC = Reader.readArray(LinesAndColumns, Reader.bytesRemaining())) 608c099fe0SZachary Turner return EC; 618c099fe0SZachary Turner 628c099fe0SZachary Turner return Error::success(); 638c099fe0SZachary Turner } 648c099fe0SZachary Turner 658c099fe0SZachary Turner bool DebugLinesSubsectionRef::hasColumnInfo() const { 668c099fe0SZachary Turner return !!(Header->Flags & LF_HaveColumns); 678c099fe0SZachary Turner } 688c099fe0SZachary Turner 698c099fe0SZachary Turner DebugLinesSubsection::DebugLinesSubsection(DebugChecksumsSubsection &Checksums, 70591312c5SZachary Turner DebugStringTableSubsection &Strings) 718c099fe0SZachary Turner : DebugSubsection(DebugSubsectionKind::Lines), Checksums(Checksums) {} 728c099fe0SZachary Turner 738c099fe0SZachary Turner void DebugLinesSubsection::createBlock(StringRef FileName) { 748c099fe0SZachary Turner uint32_t Offset = Checksums.mapChecksumOffset(FileName); 758c099fe0SZachary Turner 768c099fe0SZachary Turner Blocks.emplace_back(Offset); 778c099fe0SZachary Turner } 788c099fe0SZachary Turner 798c099fe0SZachary Turner void DebugLinesSubsection::addLineInfo(uint32_t Offset, const LineInfo &Line) { 808c099fe0SZachary Turner Block &B = Blocks.back(); 818c099fe0SZachary Turner LineNumberEntry LNE; 828c099fe0SZachary Turner LNE.Flags = Line.getRawData(); 838c099fe0SZachary Turner LNE.Offset = Offset; 848c099fe0SZachary Turner B.Lines.push_back(LNE); 858c099fe0SZachary Turner } 868c099fe0SZachary Turner 878c099fe0SZachary Turner void DebugLinesSubsection::addLineAndColumnInfo(uint32_t Offset, 888c099fe0SZachary Turner const LineInfo &Line, 898c099fe0SZachary Turner uint32_t ColStart, 908c099fe0SZachary Turner uint32_t ColEnd) { 918c099fe0SZachary Turner Block &B = Blocks.back(); 928c099fe0SZachary Turner assert(B.Lines.size() == B.Columns.size()); 938c099fe0SZachary Turner 948c099fe0SZachary Turner addLineInfo(Offset, Line); 958c099fe0SZachary Turner ColumnNumberEntry CNE; 968c099fe0SZachary Turner CNE.StartColumn = ColStart; 978c099fe0SZachary Turner CNE.EndColumn = ColEnd; 988c099fe0SZachary Turner B.Columns.push_back(CNE); 998c099fe0SZachary Turner } 1008c099fe0SZachary Turner 101591312c5SZachary Turner Error DebugLinesSubsection::commit(BinaryStreamWriter &Writer) const { 1028c099fe0SZachary Turner LineFragmentHeader Header; 1038c099fe0SZachary Turner Header.CodeSize = CodeSize; 1048c099fe0SZachary Turner Header.Flags = hasColumnInfo() ? LF_HaveColumns : 0; 1058c099fe0SZachary Turner Header.RelocOffset = RelocOffset; 1068c099fe0SZachary Turner Header.RelocSegment = RelocSegment; 1078c099fe0SZachary Turner 1088c099fe0SZachary Turner if (auto EC = Writer.writeObject(Header)) 1098c099fe0SZachary Turner return EC; 1108c099fe0SZachary Turner 1118c099fe0SZachary Turner for (const auto &B : Blocks) { 1128c099fe0SZachary Turner LineBlockFragmentHeader BlockHeader; 1138c099fe0SZachary Turner assert(B.Lines.size() == B.Columns.size() || B.Columns.empty()); 1148c099fe0SZachary Turner 1158c099fe0SZachary Turner BlockHeader.NumLines = B.Lines.size(); 1168c099fe0SZachary Turner BlockHeader.BlockSize = sizeof(LineBlockFragmentHeader); 1178c099fe0SZachary Turner BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(LineNumberEntry); 1188c099fe0SZachary Turner if (hasColumnInfo()) 1198c099fe0SZachary Turner BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(ColumnNumberEntry); 1208c099fe0SZachary Turner BlockHeader.NameIndex = B.ChecksumBufferOffset; 1218c099fe0SZachary Turner if (auto EC = Writer.writeObject(BlockHeader)) 1228c099fe0SZachary Turner return EC; 1238c099fe0SZachary Turner 1248c099fe0SZachary Turner if (auto EC = Writer.writeArray(makeArrayRef(B.Lines))) 1258c099fe0SZachary Turner return EC; 1268c099fe0SZachary Turner 1278c099fe0SZachary Turner if (hasColumnInfo()) { 1288c099fe0SZachary Turner if (auto EC = Writer.writeArray(makeArrayRef(B.Columns))) 1298c099fe0SZachary Turner return EC; 1308c099fe0SZachary Turner } 1318c099fe0SZachary Turner } 1328c099fe0SZachary Turner return Error::success(); 1338c099fe0SZachary Turner } 1348c099fe0SZachary Turner 135591312c5SZachary Turner uint32_t DebugLinesSubsection::calculateSerializedSize() const { 1368c099fe0SZachary Turner uint32_t Size = sizeof(LineFragmentHeader); 1378c099fe0SZachary Turner for (const auto &B : Blocks) { 1388c099fe0SZachary Turner Size += sizeof(LineBlockFragmentHeader); 1398c099fe0SZachary Turner Size += B.Lines.size() * sizeof(LineNumberEntry); 1408c099fe0SZachary Turner if (hasColumnInfo()) 1418c099fe0SZachary Turner Size += B.Columns.size() * sizeof(ColumnNumberEntry); 1428c099fe0SZachary Turner } 1438c099fe0SZachary Turner return Size; 1448c099fe0SZachary Turner } 1458c099fe0SZachary Turner 1468c099fe0SZachary Turner void DebugLinesSubsection::setRelocationAddress(uint16_t Segment, 147fdf499bfSBob Haarman uint32_t Offset) { 1488c099fe0SZachary Turner RelocOffset = Offset; 1498c099fe0SZachary Turner RelocSegment = Segment; 1508c099fe0SZachary Turner } 1518c099fe0SZachary Turner 1528c099fe0SZachary Turner void DebugLinesSubsection::setCodeSize(uint32_t Size) { CodeSize = Size; } 1538c099fe0SZachary Turner 1548c099fe0SZachary Turner void DebugLinesSubsection::setFlags(LineFlags Flags) { this->Flags = Flags; } 1558c099fe0SZachary Turner 1568c099fe0SZachary Turner bool DebugLinesSubsection::hasColumnInfo() const { 1578c099fe0SZachary Turner return Flags & LF_HaveColumns; 1588c099fe0SZachary Turner } 159