Home | History | Annotate | Line # | Download | only in CodeView
      1 //===- DebugLinesSubsection.h -----------------------------------*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H
     10 #define LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H
     11 
     12 #include "llvm/ADT/StringRef.h"
     13 #include "llvm/DebugInfo/CodeView/CodeView.h"
     14 #include "llvm/DebugInfo/CodeView/DebugSubsection.h"
     15 #include "llvm/DebugInfo/CodeView/Line.h"
     16 #include "llvm/Support/BinaryStreamArray.h"
     17 #include "llvm/Support/BinaryStreamReader.h"
     18 #include "llvm/Support/BinaryStreamRef.h"
     19 #include "llvm/Support/Endian.h"
     20 #include "llvm/Support/Error.h"
     21 #include <cstdint>
     22 #include <vector>
     23 
     24 namespace llvm {
     25 namespace codeview {
     26 
     27 class DebugChecksumsSubsection;
     28 class DebugStringTableSubsection;
     29 
     30 // Corresponds to the `CV_DebugSLinesHeader_t` structure.
     31 struct LineFragmentHeader {
     32   support::ulittle32_t RelocOffset;  // Code offset of line contribution.
     33   support::ulittle16_t RelocSegment; // Code segment of line contribution.
     34   support::ulittle16_t Flags;        // See LineFlags enumeration.
     35   support::ulittle32_t CodeSize;     // Code size of this line contribution.
     36 };
     37 
     38 // Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure.
     39 struct LineBlockFragmentHeader {
     40   support::ulittle32_t NameIndex; // Offset of FileChecksum entry in File
     41                                   // checksums buffer.  The checksum entry then
     42                                   // contains another offset into the string
     43                                   // table of the actual name.
     44   support::ulittle32_t NumLines;  // Number of lines
     45   support::ulittle32_t BlockSize; // Code size of block, in bytes.
     46   // The following two variable length arrays appear immediately after the
     47   // header.  The structure definitions follow.
     48   // LineNumberEntry   Lines[NumLines];
     49   // ColumnNumberEntry Columns[NumLines];
     50 };
     51 
     52 // Corresponds to `CV_Line_t` structure
     53 struct LineNumberEntry {
     54   support::ulittle32_t Offset; // Offset to start of code bytes for line number
     55   support::ulittle32_t Flags;  // Start:24, End:7, IsStatement:1
     56 };
     57 
     58 // Corresponds to `CV_Column_t` structure
     59 struct ColumnNumberEntry {
     60   support::ulittle16_t StartColumn;
     61   support::ulittle16_t EndColumn;
     62 };
     63 
     64 struct LineColumnEntry {
     65   support::ulittle32_t NameIndex;
     66   FixedStreamArray<LineNumberEntry> LineNumbers;
     67   FixedStreamArray<ColumnNumberEntry> Columns;
     68 };
     69 
     70 class LineColumnExtractor {
     71 public:
     72   Error operator()(BinaryStreamRef Stream, uint32_t &Len,
     73                    LineColumnEntry &Item);
     74 
     75   const LineFragmentHeader *Header = nullptr;
     76 };
     77 
     78 class DebugLinesSubsectionRef final : public DebugSubsectionRef {
     79   friend class LineColumnExtractor;
     80 
     81   using LineInfoArray = VarStreamArray<LineColumnEntry, LineColumnExtractor>;
     82   using Iterator = LineInfoArray::Iterator;
     83 
     84 public:
     85   DebugLinesSubsectionRef();
     86 
     87   static bool classof(const DebugSubsectionRef *S) {
     88     return S->kind() == DebugSubsectionKind::Lines;
     89   }
     90 
     91   Error initialize(BinaryStreamReader Reader);
     92 
     93   Iterator begin() const { return LinesAndColumns.begin(); }
     94   Iterator end() const { return LinesAndColumns.end(); }
     95 
     96   const LineFragmentHeader *header() const { return Header; }
     97 
     98   bool hasColumnInfo() const;
     99 
    100 private:
    101   const LineFragmentHeader *Header = nullptr;
    102   LineInfoArray LinesAndColumns;
    103 };
    104 
    105 class DebugLinesSubsection final : public DebugSubsection {
    106   struct Block {
    107     Block(uint32_t ChecksumBufferOffset)
    108         : ChecksumBufferOffset(ChecksumBufferOffset) {}
    109 
    110     uint32_t ChecksumBufferOffset;
    111     std::vector<LineNumberEntry> Lines;
    112     std::vector<ColumnNumberEntry> Columns;
    113   };
    114 
    115 public:
    116   DebugLinesSubsection(DebugChecksumsSubsection &Checksums,
    117                        DebugStringTableSubsection &Strings);
    118 
    119   static bool classof(const DebugSubsection *S) {
    120     return S->kind() == DebugSubsectionKind::Lines;
    121   }
    122 
    123   void createBlock(StringRef FileName);
    124   void addLineInfo(uint32_t Offset, const LineInfo &Line);
    125   void addLineAndColumnInfo(uint32_t Offset, const LineInfo &Line,
    126                             uint32_t ColStart, uint32_t ColEnd);
    127 
    128   uint32_t calculateSerializedSize() const override;
    129   Error commit(BinaryStreamWriter &Writer) const override;
    130 
    131   void setRelocationAddress(uint16_t Segment, uint32_t Offset);
    132   void setCodeSize(uint32_t Size);
    133   void setFlags(LineFlags Flags);
    134 
    135   bool hasColumnInfo() const;
    136 
    137 private:
    138   DebugChecksumsSubsection &Checksums;
    139   uint32_t RelocOffset = 0;
    140   uint16_t RelocSegment = 0;
    141   uint32_t CodeSize = 0;
    142   LineFlags Flags = LF_None;
    143   std::vector<Block> Blocks;
    144 };
    145 
    146 } // end namespace codeview
    147 } // end namespace llvm
    148 
    149 #endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H
    150