//===- DebugLinesSubsection.h -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H
#define LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <vector>
namespace llvm {
namespace codeview {
class DebugChecksumsSubsection;
class DebugStringTableSubsection;
// Corresponds to the `CV_DebugSLinesHeader_t` structure.
struct LineFragmentHeader {
support::ulittle32_t RelocOffset; // Code offset of line contribution.
support::ulittle16_t RelocSegment; // Code segment of line contribution.
support::ulittle16_t Flags; // See LineFlags enumeration.
support::ulittle32_t CodeSize; // Code size of this line contribution.
};
// Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure.
struct LineBlockFragmentHeader {
support::ulittle32_t NameIndex; // Offset of FileChecksum entry in File
// checksums buffer. The checksum entry then
// contains another offset into the string
// table of the actual name.
support::ulittle32_t NumLines; // Number of lines
support::ulittle32_t BlockSize; // Code size of block, in bytes.
// The following two variable length arrays appear immediately after the
// header. The structure definitions follow.
// LineNumberEntry Lines[NumLines];
// ColumnNumberEntry Columns[NumLines];
};
// Corresponds to `CV_Line_t` structure
struct LineNumberEntry {
support::ulittle32_t Offset; // Offset to start of code bytes for line number
support::ulittle32_t Flags; // Start:24, End:7, IsStatement:1
};
// Corresponds to `CV_Column_t` structure
struct ColumnNumberEntry {
support::ulittle16_t StartColumn;
support::ulittle16_t EndColumn;
};
struct LineColumnEntry {
support::ulittle32_t NameIndex;
FixedStreamArray<LineNumberEntry> LineNumbers;
FixedStreamArray<ColumnNumberEntry> Columns;
};
class LineColumnExtractor {
public:
Error operator()(BinaryStreamRef Stream, uint32_t &Len,
LineColumnEntry &Item);
const LineFragmentHeader *Header = nullptr;
};
class DebugLinesSubsectionRef final : public DebugSubsectionRef {
friend class LineColumnExtractor;
using LineInfoArray = VarStreamArray<LineColumnEntry, LineColumnExtractor>;
using Iterator = LineInfoArray::Iterator;
public:
DebugLinesSubsectionRef();
static bool classof(const DebugSubsectionRef *S) {
return S->kind() == DebugSubsectionKind::Lines;
}
Error initialize(BinaryStreamReader Reader);
Iterator begin() const { return LinesAndColumns.begin(); }
Iterator end() const { return LinesAndColumns.end(); }
const LineFragmentHeader *header() const { return Header; }
bool hasColumnInfo() const;
private:
const LineFragmentHeader *Header = nullptr;
LineInfoArray LinesAndColumns;
};
class DebugLinesSubsection final : public DebugSubsection {
struct Block {
Block(uint32_t ChecksumBufferOffset)
: ChecksumBufferOffset(ChecksumBufferOffset) {}
uint32_t ChecksumBufferOffset;
std::vector<LineNumberEntry> Lines;
std::vector<ColumnNumberEntry> Columns;
};
public:
DebugLinesSubsection(DebugChecksumsSubsection &Checksums,
DebugStringTableSubsection &Strings);
static bool classof(const DebugSubsection *S) {
return S->kind() == DebugSubsectionKind::Lines;
}
void createBlock(StringRef FileName);
void addLineInfo(uint32_t Offset, const LineInfo &Line);
void addLineAndColumnInfo(uint32_t Offset, const LineInfo &Line,
uint32_t ColStart, uint32_t ColEnd);
uint32_t calculateSerializedSize() const override;
Error commit(BinaryStreamWriter &Writer) const override;
void setRelocationAddress(uint16_t Segment, uint32_t Offset);
void setCodeSize(uint32_t Size);
void setFlags(LineFlags Flags);
bool hasColumnInfo() const;
private:
DebugChecksumsSubsection &Checksums;
uint32_t RelocOffset = 0;
uint16_t RelocSegment = 0;
uint32_t CodeSize = 0;
LineFlags Flags = LF_None;
std::vector<Block> Blocks;
};
} // end namespace codeview
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H