mirror of
https://github.com/RPCSX/llvm.git
synced 2026-01-31 01:05:23 +01:00
Previously this change was submitted from a Windows machine, so changes made to the case of filenames and directory names did not survive the commit, and as a result the CMake source file names and the on-disk file names did not match on case-sensitive file systems. I'm resubmitting this patch from a Linux system, which hopefully allows the case changes to make it through unfettered. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@277213 91177308-0d34-0410-b5e6-96231b3b80d8
1452 lines
42 KiB
C++
1452 lines
42 KiB
C++
//===- SymbolRecord.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_SYMBOLRECORD_H
|
|
#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
|
|
|
|
#include "llvm/ADT/APSInt.h"
|
|
#include "llvm/ADT/Optional.h"
|
|
#include "llvm/DebugInfo/CodeView/CVRecord.h"
|
|
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
|
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
|
|
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
|
#include "llvm/DebugInfo/MSF/StreamArray.h"
|
|
#include "llvm/Support/Endian.h"
|
|
#include "llvm/Support/Error.h"
|
|
|
|
namespace llvm {
|
|
namespace codeview {
|
|
|
|
using support::ulittle16_t;
|
|
using support::ulittle32_t;
|
|
using support::little32_t;
|
|
|
|
class SymbolRecord {
|
|
protected:
|
|
explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
|
|
|
|
public:
|
|
SymbolRecordKind getKind() const { return Kind; }
|
|
|
|
private:
|
|
SymbolRecordKind Kind;
|
|
};
|
|
|
|
// S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or
|
|
// S_LPROC32_DPC_ID
|
|
class ProcSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t PtrParent;
|
|
ulittle32_t PtrEnd;
|
|
ulittle32_t PtrNext;
|
|
ulittle32_t CodeSize;
|
|
ulittle32_t DbgStart;
|
|
ulittle32_t DbgEnd;
|
|
TypeIndex FunctionType;
|
|
ulittle32_t CodeOffset;
|
|
ulittle16_t Segment;
|
|
uint8_t Flags; // ProcSymFlags enum
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
|
|
StringRef Name)
|
|
: SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
|
|
}
|
|
|
|
static ErrorOr<ProcSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return ProcSym(Kind, RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t getRelocationOffset() const {
|
|
return RecordOffset + offsetof(Hdr, CodeOffset);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
// S_THUNK32
|
|
class Thunk32Sym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t Parent;
|
|
ulittle32_t End;
|
|
ulittle32_t Next;
|
|
ulittle32_t Off;
|
|
ulittle16_t Seg;
|
|
ulittle16_t Len;
|
|
uint8_t Ord; // ThunkOrdinal enumeration
|
|
// Name: The null-terminated name follows.
|
|
// Variant portion of thunk
|
|
};
|
|
|
|
Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
|
|
StringRef Name, ArrayRef<uint8_t> VariantData)
|
|
: SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name),
|
|
VariantData(VariantData) {}
|
|
|
|
static ErrorOr<Thunk32Sym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
ArrayRef<uint8_t> VariantData;
|
|
|
|
CV_DESERIALIZE(Data, H, Name, CV_ARRAY_FIELD_TAIL(VariantData));
|
|
|
|
return Thunk32Sym(Kind, RecordOffset, H, Name, VariantData);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
ArrayRef<uint8_t> VariantData;
|
|
};
|
|
|
|
// S_TRAMPOLINE
|
|
class TrampolineSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle16_t Type; // TrampolineType enum
|
|
ulittle16_t Size;
|
|
ulittle32_t ThunkOff;
|
|
ulittle32_t TargetOff;
|
|
ulittle16_t ThunkSection;
|
|
ulittle16_t TargetSection;
|
|
};
|
|
|
|
TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H)
|
|
: SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H) {}
|
|
|
|
static ErrorOr<TrampolineSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
|
|
CV_DESERIALIZE(Data, H);
|
|
|
|
return TrampolineSym(Kind, RecordOffset, H);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
};
|
|
|
|
// S_SECTION
|
|
class SectionSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle16_t SectionNumber;
|
|
uint8_t Alignment;
|
|
uint8_t Reserved; // Must be 0
|
|
ulittle32_t Rva;
|
|
ulittle32_t Length;
|
|
ulittle32_t Characteristics;
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
|
|
StringRef Name)
|
|
: SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
|
|
}
|
|
|
|
static ErrorOr<SectionSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return SectionSym(Kind, RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
// S_COFFGROUP
|
|
class CoffGroupSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t Size;
|
|
ulittle32_t Characteristics;
|
|
ulittle32_t Offset;
|
|
ulittle16_t Segment;
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
|
|
StringRef Name)
|
|
: SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
|
|
}
|
|
|
|
static ErrorOr<CoffGroupSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return CoffGroupSym(Kind, RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
class ScopeEndSym : public SymbolRecord {
|
|
public:
|
|
ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
|
|
: SymbolRecord(Kind), RecordOffset(RecordOffset) {}
|
|
|
|
static ErrorOr<ScopeEndSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
return ScopeEndSym(Kind, RecordOffset);
|
|
}
|
|
uint32_t RecordOffset;
|
|
};
|
|
|
|
class CallerSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t Count;
|
|
};
|
|
|
|
CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *Header,
|
|
ArrayRef<TypeIndex> Indices)
|
|
: SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*Header),
|
|
Indices(Indices) {}
|
|
|
|
static ErrorOr<CallerSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *Header;
|
|
ArrayRef<TypeIndex> Indices;
|
|
|
|
CV_DESERIALIZE(Data, Header, CV_ARRAY_FIELD_N(Indices, Header->Count));
|
|
|
|
return CallerSym(Kind, RecordOffset, Header, Indices);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
ArrayRef<TypeIndex> Indices;
|
|
};
|
|
|
|
struct BinaryAnnotationIterator {
|
|
struct AnnotationData {
|
|
BinaryAnnotationsOpCode OpCode;
|
|
StringRef Name;
|
|
uint32_t U1;
|
|
uint32_t U2;
|
|
int32_t S1;
|
|
};
|
|
|
|
BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
|
|
BinaryAnnotationIterator() {}
|
|
BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
|
|
: Data(Other.Data) {}
|
|
|
|
bool operator==(BinaryAnnotationIterator Other) const {
|
|
return Data == Other.Data;
|
|
}
|
|
|
|
bool operator!=(BinaryAnnotationIterator Other) const {
|
|
return !(*this == Other);
|
|
}
|
|
|
|
BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) {
|
|
Data = Other.Data;
|
|
return *this;
|
|
}
|
|
|
|
BinaryAnnotationIterator &operator++() {
|
|
if (!ParseCurrentAnnotation()) {
|
|
*this = BinaryAnnotationIterator();
|
|
return *this;
|
|
}
|
|
Data = Next;
|
|
Next = ArrayRef<uint8_t>();
|
|
Current.reset();
|
|
return *this;
|
|
}
|
|
|
|
BinaryAnnotationIterator operator++(int) {
|
|
BinaryAnnotationIterator Orig(*this);
|
|
++(*this);
|
|
return Orig;
|
|
}
|
|
|
|
const AnnotationData &operator*() {
|
|
ParseCurrentAnnotation();
|
|
return Current.getValue();
|
|
}
|
|
|
|
private:
|
|
static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
|
|
if (Annotations.empty())
|
|
return -1;
|
|
|
|
uint8_t FirstByte = Annotations.front();
|
|
Annotations = Annotations.drop_front();
|
|
|
|
if ((FirstByte & 0x80) == 0x00)
|
|
return FirstByte;
|
|
|
|
if (Annotations.empty())
|
|
return -1;
|
|
|
|
uint8_t SecondByte = Annotations.front();
|
|
Annotations = Annotations.drop_front();
|
|
|
|
if ((FirstByte & 0xC0) == 0x80)
|
|
return ((FirstByte & 0x3F) << 8) | SecondByte;
|
|
|
|
if (Annotations.empty())
|
|
return -1;
|
|
|
|
uint8_t ThirdByte = Annotations.front();
|
|
Annotations = Annotations.drop_front();
|
|
|
|
if (Annotations.empty())
|
|
return -1;
|
|
|
|
uint8_t FourthByte = Annotations.front();
|
|
Annotations = Annotations.drop_front();
|
|
|
|
if ((FirstByte & 0xE0) == 0xC0)
|
|
return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
|
|
(ThirdByte << 8) | FourthByte;
|
|
|
|
return -1;
|
|
};
|
|
|
|
static int32_t DecodeSignedOperand(uint32_t Operand) {
|
|
if (Operand & 1)
|
|
return -(Operand >> 1);
|
|
return Operand >> 1;
|
|
};
|
|
|
|
static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
|
|
return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
|
|
};
|
|
|
|
bool ParseCurrentAnnotation() {
|
|
if (Current.hasValue())
|
|
return true;
|
|
|
|
Next = Data;
|
|
uint32_t Op = GetCompressedAnnotation(Next);
|
|
AnnotationData Result;
|
|
Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
|
|
switch (Result.OpCode) {
|
|
case BinaryAnnotationsOpCode::Invalid:
|
|
Result.Name = "Invalid";
|
|
Next = ArrayRef<uint8_t>();
|
|
break;
|
|
case BinaryAnnotationsOpCode::CodeOffset:
|
|
Result.Name = "CodeOffset";
|
|
Result.U1 = GetCompressedAnnotation(Next);
|
|
break;
|
|
case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
|
|
Result.Name = "ChangeCodeOffsetBase";
|
|
Result.U1 = GetCompressedAnnotation(Next);
|
|
break;
|
|
case BinaryAnnotationsOpCode::ChangeCodeOffset:
|
|
Result.Name = "ChangeCodeOffset";
|
|
Result.U1 = GetCompressedAnnotation(Next);
|
|
break;
|
|
case BinaryAnnotationsOpCode::ChangeCodeLength:
|
|
Result.Name = "ChangeCodeLength";
|
|
Result.U1 = GetCompressedAnnotation(Next);
|
|
break;
|
|
case BinaryAnnotationsOpCode::ChangeFile:
|
|
Result.Name = "ChangeFile";
|
|
Result.U1 = GetCompressedAnnotation(Next);
|
|
break;
|
|
case BinaryAnnotationsOpCode::ChangeLineEndDelta:
|
|
Result.Name = "ChangeLineEndDelta";
|
|
Result.U1 = GetCompressedAnnotation(Next);
|
|
break;
|
|
case BinaryAnnotationsOpCode::ChangeRangeKind:
|
|
Result.Name = "ChangeRangeKind";
|
|
Result.U1 = GetCompressedAnnotation(Next);
|
|
break;
|
|
case BinaryAnnotationsOpCode::ChangeColumnStart:
|
|
Result.Name = "ChangeColumnStart";
|
|
Result.U1 = GetCompressedAnnotation(Next);
|
|
break;
|
|
case BinaryAnnotationsOpCode::ChangeColumnEnd:
|
|
Result.Name = "ChangeColumnEnd";
|
|
Result.U1 = GetCompressedAnnotation(Next);
|
|
break;
|
|
case BinaryAnnotationsOpCode::ChangeLineOffset:
|
|
Result.Name = "ChangeLineOffset";
|
|
Result.S1 = DecodeSignedOperand(Next);
|
|
break;
|
|
case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
|
|
Result.Name = "ChangeColumnEndDelta";
|
|
Result.S1 = DecodeSignedOperand(Next);
|
|
break;
|
|
case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
|
|
Result.Name = "ChangeCodeOffsetAndLineOffset";
|
|
uint32_t Annotation = GetCompressedAnnotation(Next);
|
|
Result.S1 = DecodeSignedOperand(Annotation >> 4);
|
|
Result.U1 = Annotation & 0xf;
|
|
break;
|
|
}
|
|
case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
|
|
Result.Name = "ChangeCodeLengthAndCodeOffset";
|
|
Result.U1 = GetCompressedAnnotation(Next);
|
|
Result.U2 = GetCompressedAnnotation(Next);
|
|
break;
|
|
}
|
|
}
|
|
Current = Result;
|
|
return true;
|
|
}
|
|
|
|
Optional<AnnotationData> Current;
|
|
ArrayRef<uint8_t> Data;
|
|
ArrayRef<uint8_t> Next;
|
|
};
|
|
|
|
// S_INLINESITE
|
|
class InlineSiteSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t PtrParent;
|
|
ulittle32_t PtrEnd;
|
|
TypeIndex Inlinee;
|
|
// BinaryAnnotations
|
|
};
|
|
|
|
InlineSiteSym(uint32_t RecordOffset, const Hdr *H,
|
|
ArrayRef<uint8_t> Annotations)
|
|
: SymbolRecord(SymbolRecordKind::InlineSiteSym),
|
|
RecordOffset(RecordOffset), Header(*H), Annotations(Annotations) {}
|
|
|
|
static ErrorOr<InlineSiteSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
ArrayRef<uint8_t> Annotations;
|
|
CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Annotations));
|
|
|
|
return InlineSiteSym(RecordOffset, H, Annotations);
|
|
}
|
|
|
|
llvm::iterator_range<BinaryAnnotationIterator> annotations() const {
|
|
return llvm::make_range(BinaryAnnotationIterator(Annotations),
|
|
BinaryAnnotationIterator());
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
|
|
private:
|
|
ArrayRef<uint8_t> Annotations;
|
|
};
|
|
|
|
// S_PUB32
|
|
class PublicSym32 : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t Index; // Type index, or Metadata token if a managed symbol
|
|
ulittle32_t Off;
|
|
ulittle16_t Seg;
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
PublicSym32(uint32_t RecordOffset, const Hdr *H, StringRef Name)
|
|
: SymbolRecord(SymbolRecordKind::PublicSym32), RecordOffset(RecordOffset),
|
|
Header(*H), Name(Name) {}
|
|
|
|
static ErrorOr<PublicSym32> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return PublicSym32(RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
// S_REGISTER
|
|
class RegisterSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t Index; // Type index or Metadata token
|
|
ulittle16_t Register; // RegisterId enumeration
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
RegisterSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
|
|
: SymbolRecord(SymbolRecordKind::RegisterSym), RecordOffset(RecordOffset),
|
|
Header(*H), Name(Name) {}
|
|
|
|
static ErrorOr<RegisterSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return RegisterSym(RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
// S_PROCREF, S_LPROCREF
|
|
class ProcRefSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t SumName; // SUC of the name (?)
|
|
ulittle32_t SymOffset; // Offset of actual symbol in $$Symbols
|
|
ulittle16_t Mod; // Module containing the actual symbol
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
ProcRefSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
|
|
: SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset),
|
|
Header(*H), Name(Name) {}
|
|
|
|
static ErrorOr<ProcRefSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return ProcRefSym(RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
// S_LOCAL
|
|
class LocalSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
TypeIndex Type;
|
|
ulittle16_t Flags; // LocalSymFlags enum
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
LocalSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
|
|
: SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset),
|
|
Header(*H), Name(Name) {}
|
|
|
|
static ErrorOr<LocalSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return LocalSym(RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
struct LocalVariableAddrRange {
|
|
ulittle32_t OffsetStart;
|
|
ulittle16_t ISectStart;
|
|
ulittle16_t Range;
|
|
};
|
|
|
|
struct LocalVariableAddrGap {
|
|
ulittle16_t GapStartOffset;
|
|
ulittle16_t Range;
|
|
};
|
|
|
|
enum : uint16_t { MaxDefRange = 0xf000 };
|
|
|
|
// S_DEFRANGE
|
|
class DefRangeSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t Program;
|
|
LocalVariableAddrRange Range;
|
|
// LocalVariableAddrGap Gaps[];
|
|
};
|
|
|
|
DefRangeSym(uint32_t RecordOffset, const Hdr *H,
|
|
ArrayRef<LocalVariableAddrGap> Gaps)
|
|
: SymbolRecord(SymbolRecordKind::DefRangeSym), RecordOffset(RecordOffset),
|
|
Header(*H), Gaps(Gaps) {}
|
|
|
|
static ErrorOr<DefRangeSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
ArrayRef<LocalVariableAddrGap> Gaps;
|
|
CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
|
|
|
return DefRangeSym(RecordOffset, H, Gaps);
|
|
}
|
|
|
|
uint32_t getRelocationOffset() const {
|
|
return RecordOffset + offsetof(Hdr, Range);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
ArrayRef<LocalVariableAddrGap> Gaps;
|
|
};
|
|
|
|
// S_DEFRANGE_SUBFIELD
|
|
class DefRangeSubfieldSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t Program;
|
|
ulittle16_t OffsetInParent;
|
|
LocalVariableAddrRange Range;
|
|
// LocalVariableAddrGap Gaps[];
|
|
};
|
|
DefRangeSubfieldSym(uint32_t RecordOffset, const Hdr *H,
|
|
ArrayRef<LocalVariableAddrGap> Gaps)
|
|
: SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
|
|
RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
|
|
|
|
static ErrorOr<DefRangeSubfieldSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
ArrayRef<LocalVariableAddrGap> Gaps;
|
|
CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
|
|
|
return DefRangeSubfieldSym(RecordOffset, H, Gaps);
|
|
}
|
|
|
|
uint32_t getRelocationOffset() const {
|
|
return RecordOffset + offsetof(Hdr, Range);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
ArrayRef<LocalVariableAddrGap> Gaps;
|
|
};
|
|
|
|
// S_DEFRANGE_REGISTER
|
|
class DefRangeRegisterSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle16_t Register;
|
|
ulittle16_t MayHaveNoName;
|
|
LocalVariableAddrRange Range;
|
|
// LocalVariableAddrGap Gaps[];
|
|
};
|
|
|
|
DefRangeRegisterSym(uint32_t RecordOffset, const Hdr *H,
|
|
ArrayRef<LocalVariableAddrGap> Gaps)
|
|
: SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
|
|
RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
|
|
|
|
DefRangeRegisterSym(uint16_t Register, uint16_t MayHaveNoName,
|
|
uint32_t OffsetStart, uint16_t ISectStart, uint16_t Range,
|
|
ArrayRef<LocalVariableAddrGap> Gaps)
|
|
: SymbolRecord(SymbolRecordKind::DefRangeRegisterSym), RecordOffset(0),
|
|
Gaps(Gaps) {
|
|
Header.Register = Register;
|
|
Header.MayHaveNoName = MayHaveNoName;
|
|
Header.Range.OffsetStart = OffsetStart;
|
|
Header.Range.ISectStart = ISectStart;
|
|
Header.Range.Range = Range;
|
|
}
|
|
|
|
static ErrorOr<DefRangeRegisterSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
ArrayRef<LocalVariableAddrGap> Gaps;
|
|
CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
|
|
|
return DefRangeRegisterSym(RecordOffset, H, Gaps);
|
|
}
|
|
|
|
uint32_t getRelocationOffset() const {
|
|
return RecordOffset + offsetof(Hdr, Range);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
ArrayRef<LocalVariableAddrGap> Gaps;
|
|
};
|
|
|
|
// S_DEFRANGE_SUBFIELD_REGISTER
|
|
class DefRangeSubfieldRegisterSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle16_t Register; // Register to which the variable is relative
|
|
ulittle16_t MayHaveNoName;
|
|
ulittle32_t OffsetInParent;
|
|
LocalVariableAddrRange Range;
|
|
// LocalVariableAddrGap Gaps[];
|
|
};
|
|
|
|
DefRangeSubfieldRegisterSym(uint32_t RecordOffset, const Hdr *H,
|
|
ArrayRef<LocalVariableAddrGap> Gaps)
|
|
: SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
|
|
RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
|
|
|
|
DefRangeSubfieldRegisterSym(uint16_t Register, uint16_t MayHaveNoName,
|
|
uint32_t OffsetInParent,
|
|
ArrayRef<LocalVariableAddrGap> Gaps)
|
|
: SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
|
|
RecordOffset(0), Gaps(Gaps) {
|
|
Header.Register = Register;
|
|
Header.MayHaveNoName = MayHaveNoName;
|
|
Header.OffsetInParent = OffsetInParent;
|
|
}
|
|
|
|
static ErrorOr<DefRangeSubfieldRegisterSym>
|
|
deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
ArrayRef<LocalVariableAddrGap> Gaps;
|
|
CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
|
|
|
return DefRangeSubfieldRegisterSym(RecordOffset, H, Gaps);
|
|
}
|
|
|
|
uint32_t getRelocationOffset() const {
|
|
return RecordOffset + offsetof(Hdr, Range);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
ArrayRef<LocalVariableAddrGap> Gaps;
|
|
};
|
|
|
|
// S_DEFRANGE_FRAMEPOINTER_REL
|
|
class DefRangeFramePointerRelSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
little32_t Offset; // Offset from the frame pointer register
|
|
LocalVariableAddrRange Range;
|
|
// LocalVariableAddrGap Gaps[];
|
|
};
|
|
|
|
DefRangeFramePointerRelSym(uint32_t RecordOffset, const Hdr *H,
|
|
ArrayRef<LocalVariableAddrGap> Gaps)
|
|
: SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
|
|
RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
|
|
|
|
static ErrorOr<DefRangeFramePointerRelSym>
|
|
deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
ArrayRef<LocalVariableAddrGap> Gaps;
|
|
CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
|
|
|
return DefRangeFramePointerRelSym(RecordOffset, H, Gaps);
|
|
}
|
|
|
|
uint32_t getRelocationOffset() const {
|
|
return RecordOffset + offsetof(Hdr, Range);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
ArrayRef<LocalVariableAddrGap> Gaps;
|
|
};
|
|
|
|
// S_DEFRANGE_REGISTER_REL
|
|
class DefRangeRegisterRelSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle16_t BaseRegister;
|
|
ulittle16_t Flags;
|
|
little32_t BasePointerOffset;
|
|
LocalVariableAddrRange Range;
|
|
// LocalVariableAddrGap Gaps[];
|
|
};
|
|
|
|
DefRangeRegisterRelSym(uint32_t RecordOffset, const Hdr *H,
|
|
ArrayRef<LocalVariableAddrGap> Gaps)
|
|
: SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
|
|
RecordOffset(RecordOffset), Header(*H), Gaps(Gaps) {}
|
|
|
|
DefRangeRegisterRelSym(uint16_t BaseRegister, uint16_t Flags,
|
|
int32_t BasePointerOffset, uint32_t OffsetStart,
|
|
uint16_t ISectStart, uint16_t Range,
|
|
ArrayRef<LocalVariableAddrGap> Gaps)
|
|
: SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym), RecordOffset(0),
|
|
Gaps(Gaps) {
|
|
Header.BaseRegister = BaseRegister;
|
|
Header.Flags = Flags;
|
|
Header.BasePointerOffset = BasePointerOffset;
|
|
Header.Range.OffsetStart = OffsetStart;
|
|
Header.Range.ISectStart = ISectStart;
|
|
Header.Range.Range = Range;
|
|
}
|
|
|
|
static ErrorOr<DefRangeRegisterRelSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
ArrayRef<LocalVariableAddrGap> Gaps;
|
|
CV_DESERIALIZE(Data, H, CV_ARRAY_FIELD_TAIL(Gaps));
|
|
|
|
return DefRangeRegisterRelSym(RecordOffset, H, Gaps);
|
|
}
|
|
|
|
bool hasSpilledUDTMember() const { return Header.Flags & 1; }
|
|
uint16_t offsetInParent() const { return Header.Flags >> 4; }
|
|
|
|
uint32_t getRelocationOffset() const {
|
|
return RecordOffset + offsetof(Hdr, Range);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
ArrayRef<LocalVariableAddrGap> Gaps;
|
|
};
|
|
|
|
// S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
|
|
class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
little32_t Offset; // Offset from the frame pointer register
|
|
};
|
|
|
|
DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset, const Hdr *H)
|
|
: SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
|
|
RecordOffset(RecordOffset), Header(*H) {}
|
|
|
|
static ErrorOr<DefRangeFramePointerRelFullScopeSym>
|
|
deserialize(SymbolRecordKind Kind, uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
CV_DESERIALIZE(Data, H);
|
|
|
|
return DefRangeFramePointerRelFullScopeSym(RecordOffset, H);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
};
|
|
|
|
// S_BLOCK32
|
|
class BlockSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t PtrParent;
|
|
ulittle32_t PtrEnd;
|
|
ulittle32_t CodeSize;
|
|
ulittle32_t CodeOffset;
|
|
ulittle16_t Segment;
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
BlockSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
|
|
: SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset),
|
|
Header(*H), Name(Name) {}
|
|
|
|
static ErrorOr<BlockSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return BlockSym(RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t getRelocationOffset() const {
|
|
return RecordOffset + offsetof(Hdr, CodeOffset);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
// S_LABEL32
|
|
class LabelSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t CodeOffset;
|
|
ulittle16_t Segment;
|
|
uint8_t Flags; // CV_PROCFLAGS
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
LabelSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
|
|
: SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset),
|
|
Header(*H), Name(Name) {}
|
|
|
|
static ErrorOr<LabelSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return LabelSym(RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t getRelocationOffset() const {
|
|
return RecordOffset + offsetof(Hdr, CodeOffset);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
// S_OBJNAME
|
|
class ObjNameSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t Signature;
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
ObjNameSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
|
|
: SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset),
|
|
Header(*H), Name(Name) {}
|
|
|
|
static ErrorOr<ObjNameSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return ObjNameSym(RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
// S_ENVBLOCK
|
|
class EnvBlockSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
uint8_t Reserved;
|
|
// Sequence of zero terminated strings.
|
|
};
|
|
|
|
EnvBlockSym(uint32_t RecordOffset, const Hdr *H,
|
|
const std::vector<StringRef> &Fields)
|
|
: SymbolRecord(SymbolRecordKind::EnvBlockSym), RecordOffset(RecordOffset),
|
|
Header(*H), Fields(Fields) {}
|
|
|
|
static ErrorOr<EnvBlockSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
std::vector<StringRef> Fields;
|
|
CV_DESERIALIZE(Data, H, CV_STRING_ARRAY_NULL_TERM(Fields));
|
|
|
|
return EnvBlockSym(RecordOffset, H, Fields);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
std::vector<StringRef> Fields;
|
|
};
|
|
|
|
// S_EXPORT
|
|
class ExportSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle16_t Ordinal;
|
|
ulittle16_t Flags; // ExportFlags
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
ExportSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
|
|
: SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset),
|
|
Header(*H), Name(Name) {}
|
|
|
|
static ErrorOr<ExportSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return ExportSym(RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
// S_FILESTATIC
|
|
class FileStaticSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t Index; // Type Index
|
|
ulittle32_t ModFilenameOffset; // Index of mod filename in string table
|
|
ulittle16_t Flags; // LocalSymFlags enum
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
FileStaticSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
|
|
: SymbolRecord(SymbolRecordKind::FileStaticSym),
|
|
RecordOffset(RecordOffset), Header(*H), Name(Name) {}
|
|
|
|
static ErrorOr<FileStaticSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return FileStaticSym(RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
// S_COMPILE2
|
|
class Compile2Sym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t flags; // CompileSym2Flags enum
|
|
uint8_t getLanguage() const { return flags & 0xFF; }
|
|
unsigned short Machine; // CPUType enum
|
|
unsigned short VersionFrontendMajor;
|
|
unsigned short VersionFrontendMinor;
|
|
unsigned short VersionFrontendBuild;
|
|
unsigned short VersionBackendMajor;
|
|
unsigned short VersionBackendMinor;
|
|
unsigned short VersionBackendBuild;
|
|
// Version: The null-terminated version string follows.
|
|
// Optional block of zero terminated strings terminated with a double zero.
|
|
};
|
|
|
|
Compile2Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version)
|
|
: SymbolRecord(SymbolRecordKind::Compile2Sym), RecordOffset(RecordOffset),
|
|
Header(*H), Version(Version) {}
|
|
|
|
static ErrorOr<Compile2Sym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Version;
|
|
CV_DESERIALIZE(Data, H, Version);
|
|
|
|
return Compile2Sym(RecordOffset, H, Version);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Version;
|
|
};
|
|
|
|
// S_COMPILE3
|
|
class Compile3Sym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t flags; // CompileSym3Flags enum
|
|
uint8_t getLanguage() const { return flags & 0xff; }
|
|
ulittle16_t Machine; // CPUType enum
|
|
ulittle16_t VersionFrontendMajor;
|
|
ulittle16_t VersionFrontendMinor;
|
|
ulittle16_t VersionFrontendBuild;
|
|
ulittle16_t VersionFrontendQFE;
|
|
ulittle16_t VersionBackendMajor;
|
|
ulittle16_t VersionBackendMinor;
|
|
ulittle16_t VersionBackendBuild;
|
|
ulittle16_t VersionBackendQFE;
|
|
// VersionString: The null-terminated version string follows.
|
|
};
|
|
|
|
Compile3Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version)
|
|
: SymbolRecord(SymbolRecordKind::Compile3Sym), RecordOffset(RecordOffset),
|
|
Header(*H), Version(Version) {}
|
|
|
|
static ErrorOr<Compile3Sym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Version;
|
|
CV_DESERIALIZE(Data, H, Version);
|
|
|
|
return Compile3Sym(RecordOffset, H, Version);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Version;
|
|
};
|
|
|
|
// S_FRAMEPROC
|
|
class FrameProcSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t TotalFrameBytes;
|
|
ulittle32_t PaddingFrameBytes;
|
|
ulittle32_t OffsetToPadding;
|
|
ulittle32_t BytesOfCalleeSavedRegisters;
|
|
ulittle32_t OffsetOfExceptionHandler;
|
|
ulittle16_t SectionIdOfExceptionHandler;
|
|
ulittle32_t Flags;
|
|
};
|
|
|
|
FrameProcSym(uint32_t RecordOffset, const Hdr *H)
|
|
: SymbolRecord(SymbolRecordKind::FrameProcSym),
|
|
RecordOffset(RecordOffset), Header(*H) {}
|
|
|
|
static ErrorOr<FrameProcSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
CV_DESERIALIZE(Data, H);
|
|
|
|
return FrameProcSym(RecordOffset, H);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
};
|
|
|
|
// S_CALLSITEINFO
|
|
class CallSiteInfoSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t CodeOffset;
|
|
ulittle16_t Segment;
|
|
ulittle16_t Reserved;
|
|
TypeIndex Type;
|
|
};
|
|
|
|
CallSiteInfoSym(uint32_t RecordOffset, const Hdr *H)
|
|
: SymbolRecord(SymbolRecordKind::CallSiteInfoSym),
|
|
RecordOffset(RecordOffset), Header(*H) {}
|
|
|
|
static ErrorOr<CallSiteInfoSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
CV_DESERIALIZE(Data, H);
|
|
|
|
return CallSiteInfoSym(RecordOffset, H);
|
|
}
|
|
|
|
uint32_t getRelocationOffset() const {
|
|
return RecordOffset + offsetof(Hdr, CodeOffset);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
};
|
|
|
|
// S_HEAPALLOCSITE
|
|
class HeapAllocationSiteSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t CodeOffset;
|
|
ulittle16_t Segment;
|
|
ulittle16_t CallInstructionSize;
|
|
TypeIndex Type;
|
|
};
|
|
|
|
HeapAllocationSiteSym(uint32_t RecordOffset, const Hdr *H)
|
|
: SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
|
|
RecordOffset(RecordOffset), Header(*H) {}
|
|
|
|
static ErrorOr<HeapAllocationSiteSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
CV_DESERIALIZE(Data, H);
|
|
|
|
return HeapAllocationSiteSym(RecordOffset, H);
|
|
}
|
|
|
|
uint32_t getRelocationOffset() const {
|
|
return RecordOffset + offsetof(Hdr, CodeOffset);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
};
|
|
|
|
// S_FRAMECOOKIE
|
|
class FrameCookieSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t CodeOffset;
|
|
ulittle16_t Register;
|
|
uint8_t CookieKind;
|
|
uint8_t Flags;
|
|
};
|
|
|
|
FrameCookieSym(uint32_t RecordOffset, const Hdr *H)
|
|
: SymbolRecord(SymbolRecordKind::FrameCookieSym),
|
|
RecordOffset(RecordOffset), Header(*H) {}
|
|
|
|
static ErrorOr<FrameCookieSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
CV_DESERIALIZE(Data, H);
|
|
|
|
return FrameCookieSym(RecordOffset, H);
|
|
}
|
|
|
|
uint32_t getRelocationOffset() const {
|
|
return RecordOffset + offsetof(Hdr, CodeOffset);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
};
|
|
|
|
// S_UDT, S_COBOLUDT
|
|
class UDTSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
TypeIndex Type; // Type of the UDT
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
UDTSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
|
|
: SymbolRecord(SymbolRecordKind::UDTSym), RecordOffset(RecordOffset),
|
|
Header(*H), Name(Name) {}
|
|
|
|
static ErrorOr<UDTSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return UDTSym(RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
// S_BUILDINFO
|
|
class BuildInfoSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t BuildId;
|
|
};
|
|
|
|
BuildInfoSym(uint32_t RecordOffset, const Hdr *H)
|
|
: SymbolRecord(SymbolRecordKind::BuildInfoSym),
|
|
RecordOffset(RecordOffset), Header(*H) {}
|
|
|
|
static ErrorOr<BuildInfoSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
CV_DESERIALIZE(Data, H);
|
|
|
|
return BuildInfoSym(RecordOffset, H);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
};
|
|
|
|
// S_BPREL32
|
|
class BPRelativeSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
little32_t Offset; // Offset from the base pointer register
|
|
TypeIndex Type; // Type of the variable
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
BPRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
|
|
: SymbolRecord(SymbolRecordKind::BPRelativeSym),
|
|
RecordOffset(RecordOffset), Header(*H), Name(Name) {}
|
|
|
|
static ErrorOr<BPRelativeSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return BPRelativeSym(RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
// S_REGREL32
|
|
class RegRelativeSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
ulittle32_t Offset; // Offset from the register
|
|
TypeIndex Type; // Type of the variable
|
|
ulittle16_t Register; // Register to which the variable is relative
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
RegRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
|
|
: SymbolRecord(SymbolRecordKind::RegRelativeSym),
|
|
RecordOffset(RecordOffset), Header(*H), Name(Name) {}
|
|
|
|
static ErrorOr<RegRelativeSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return RegRelativeSym(RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
// S_CONSTANT, S_MANCONSTANT
|
|
class ConstantSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
TypeIndex Type;
|
|
// Value: The value of the constant.
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
ConstantSym(uint32_t RecordOffset, const Hdr *H, const APSInt &Value,
|
|
StringRef Name)
|
|
: SymbolRecord(SymbolRecordKind::ConstantSym), RecordOffset(RecordOffset),
|
|
Header(*H), Value(Value), Name(Name) {}
|
|
|
|
static ErrorOr<ConstantSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
APSInt Value;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Value, Name);
|
|
|
|
return ConstantSym(RecordOffset, H, Value, Name);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
APSInt Value;
|
|
StringRef Name;
|
|
};
|
|
|
|
// S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
|
|
class DataSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
TypeIndex Type;
|
|
ulittle32_t DataOffset;
|
|
ulittle16_t Segment;
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
DataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
|
|
: SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset),
|
|
Header(*H), Name(Name) {}
|
|
|
|
static ErrorOr<DataSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return DataSym(RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t getRelocationOffset() const {
|
|
return RecordOffset + offsetof(Hdr, DataOffset);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
// S_LTHREAD32, S_GTHREAD32
|
|
class ThreadLocalDataSym : public SymbolRecord {
|
|
public:
|
|
struct Hdr {
|
|
TypeIndex Type;
|
|
ulittle32_t DataOffset;
|
|
ulittle16_t Segment;
|
|
// Name: The null-terminated name follows.
|
|
};
|
|
|
|
ThreadLocalDataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
|
|
: SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
|
|
RecordOffset(RecordOffset), Header(*H), Name(Name) {}
|
|
|
|
static ErrorOr<ThreadLocalDataSym> deserialize(SymbolRecordKind Kind,
|
|
uint32_t RecordOffset,
|
|
ArrayRef<uint8_t> &Data) {
|
|
const Hdr *H = nullptr;
|
|
StringRef Name;
|
|
CV_DESERIALIZE(Data, H, Name);
|
|
|
|
return ThreadLocalDataSym(RecordOffset, H, Name);
|
|
}
|
|
|
|
uint32_t getRelocationOffset() const {
|
|
return RecordOffset + offsetof(Hdr, DataOffset);
|
|
}
|
|
|
|
uint32_t RecordOffset;
|
|
Hdr Header;
|
|
StringRef Name;
|
|
};
|
|
|
|
typedef CVRecord<SymbolKind> CVSymbol;
|
|
typedef msf::VarStreamArray<CVSymbol> CVSymbolArray;
|
|
|
|
} // namespace codeview
|
|
} // namespace llvm
|
|
|
|
#endif
|