Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/CodeView/DebugLinesSubsection.cpp
35271 views
//===- DebugLinesSubsection.cpp -------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"9#include "llvm/ADT/ArrayRef.h"10#include "llvm/DebugInfo/CodeView/CodeView.h"11#include "llvm/DebugInfo/CodeView/CodeViewError.h"12#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"13#include "llvm/Support/BinaryStreamReader.h"14#include "llvm/Support/BinaryStreamWriter.h"15#include "llvm/Support/Error.h"16#include <cassert>17#include <cstdint>1819using namespace llvm;20using namespace llvm::codeview;2122Error LineColumnExtractor::operator()(BinaryStreamRef Stream, uint32_t &Len,23LineColumnEntry &Item) {24const LineBlockFragmentHeader *BlockHeader;25BinaryStreamReader Reader(Stream);26if (auto EC = Reader.readObject(BlockHeader))27return EC;28bool HasColumn = Header->Flags & uint16_t(LF_HaveColumns);29uint32_t LineInfoSize =30BlockHeader->NumLines *31(sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0));32if (BlockHeader->BlockSize < sizeof(LineBlockFragmentHeader))33return make_error<CodeViewError>(cv_error_code::corrupt_record,34"Invalid line block record size");35uint32_t Size = BlockHeader->BlockSize - sizeof(LineBlockFragmentHeader);36if (LineInfoSize > Size)37return make_error<CodeViewError>(cv_error_code::corrupt_record,38"Invalid line block record size");39// The value recorded in BlockHeader->BlockSize includes the size of40// LineBlockFragmentHeader.41Len = BlockHeader->BlockSize;42Item.NameIndex = BlockHeader->NameIndex;43if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines))44return EC;45if (HasColumn) {46if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines))47return EC;48}49return Error::success();50}5152DebugLinesSubsectionRef::DebugLinesSubsectionRef()53: DebugSubsectionRef(DebugSubsectionKind::Lines) {}5455Error DebugLinesSubsectionRef::initialize(BinaryStreamReader Reader) {56if (auto EC = Reader.readObject(Header))57return EC;5859LinesAndColumns.getExtractor().Header = Header;60if (auto EC = Reader.readArray(LinesAndColumns, Reader.bytesRemaining()))61return EC;6263return Error::success();64}6566bool DebugLinesSubsectionRef::hasColumnInfo() const {67return !!(Header->Flags & LF_HaveColumns);68}6970DebugLinesSubsection::DebugLinesSubsection(DebugChecksumsSubsection &Checksums,71DebugStringTableSubsection &Strings)72: DebugSubsection(DebugSubsectionKind::Lines), Checksums(Checksums) {}7374void DebugLinesSubsection::createBlock(StringRef FileName) {75uint32_t Offset = Checksums.mapChecksumOffset(FileName);7677Blocks.emplace_back(Offset);78}7980void DebugLinesSubsection::addLineInfo(uint32_t Offset, const LineInfo &Line) {81Block &B = Blocks.back();82LineNumberEntry LNE;83LNE.Flags = Line.getRawData();84LNE.Offset = Offset;85B.Lines.push_back(LNE);86}8788void DebugLinesSubsection::addLineAndColumnInfo(uint32_t Offset,89const LineInfo &Line,90uint32_t ColStart,91uint32_t ColEnd) {92Block &B = Blocks.back();93assert(B.Lines.size() == B.Columns.size());9495addLineInfo(Offset, Line);96ColumnNumberEntry CNE;97CNE.StartColumn = ColStart;98CNE.EndColumn = ColEnd;99B.Columns.push_back(CNE);100}101102Error DebugLinesSubsection::commit(BinaryStreamWriter &Writer) const {103LineFragmentHeader Header;104Header.CodeSize = CodeSize;105Header.Flags = hasColumnInfo() ? LF_HaveColumns : 0;106Header.RelocOffset = RelocOffset;107Header.RelocSegment = RelocSegment;108109if (auto EC = Writer.writeObject(Header))110return EC;111112for (const auto &B : Blocks) {113LineBlockFragmentHeader BlockHeader;114assert(B.Lines.size() == B.Columns.size() || B.Columns.empty());115116BlockHeader.NumLines = B.Lines.size();117BlockHeader.BlockSize = sizeof(LineBlockFragmentHeader);118BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(LineNumberEntry);119if (hasColumnInfo())120BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(ColumnNumberEntry);121BlockHeader.NameIndex = B.ChecksumBufferOffset;122if (auto EC = Writer.writeObject(BlockHeader))123return EC;124125if (auto EC = Writer.writeArray(ArrayRef(B.Lines)))126return EC;127128if (hasColumnInfo()) {129if (auto EC = Writer.writeArray(ArrayRef(B.Columns)))130return EC;131}132}133return Error::success();134}135136uint32_t DebugLinesSubsection::calculateSerializedSize() const {137uint32_t Size = sizeof(LineFragmentHeader);138for (const auto &B : Blocks) {139Size += sizeof(LineBlockFragmentHeader);140Size += B.Lines.size() * sizeof(LineNumberEntry);141if (hasColumnInfo())142Size += B.Columns.size() * sizeof(ColumnNumberEntry);143}144return Size;145}146147void DebugLinesSubsection::setRelocationAddress(uint16_t Segment,148uint32_t Offset) {149RelocOffset = Offset;150RelocSegment = Segment;151}152153void DebugLinesSubsection::setCodeSize(uint32_t Size) { CodeSize = Size; }154155void DebugLinesSubsection::setFlags(LineFlags Flags) { this->Flags = Flags; }156157bool DebugLinesSubsection::hasColumnInfo() const {158return Flags & LF_HaveColumns;159}160161162