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