LLVM 24.0.0git
SymbolRecord.h
Go to the documentation of this file.
1//===- SymbolRecord.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_SYMBOLRECORD_H
10#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
11
12#include "llvm/ADT/APSInt.h"
13#include "llvm/ADT/ArrayRef.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/ADT/iterator.h"
23#include "llvm/Support/Endian.h"
24#include <cstdint>
25#include <vector>
26
27namespace llvm {
28namespace codeview {
29
31protected:
33
34public:
35 SymbolRecordKind getKind() const { return Kind; }
36
38};
39
40// S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or
41// S_LPROC32_DPC_ID
68
69// S_THUNK32
88
89// S_TRAMPOLINE
105
106// S_SECTION
122
123// S_COFFGROUP
138
147
168
179
181public:
186
187 // This is an ItemID in the IPI stream, which points to an LF_FUNC_ID or
188 // LF_MFUNC_ID record.
191
193};
194
203
205 : public iterator_facade_base<BinaryAnnotationIterator,
206 std::forward_iterator_tag,
207 DecodedAnnotation> {
212
214 return Data == Other.Data;
215 }
216
218 Data = Other.Data;
219 return *this;
220 }
221
223 if (!ParseCurrentAnnotation()) {
224 *this = BinaryAnnotationIterator();
225 return *this;
226 }
227 Data = Next;
228 Next = ArrayRef<uint8_t>();
229 Current.reset();
230 return *this;
231 }
232
234 ParseCurrentAnnotation();
235 return *Current;
236 }
237
238private:
239 static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
240 if (Annotations.empty())
241 return -1;
242
243 uint8_t FirstByte = Annotations.consume_front();
244
245 if ((FirstByte & 0x80) == 0x00)
246 return FirstByte;
247
248 if (Annotations.empty())
249 return -1;
250
251 uint8_t SecondByte = Annotations.consume_front();
252
253 if ((FirstByte & 0xC0) == 0x80)
254 return ((FirstByte & 0x3F) << 8) | SecondByte;
255
256 if (Annotations.empty())
257 return -1;
258
259 uint8_t ThirdByte = Annotations.consume_front();
260
261 if (Annotations.empty())
262 return -1;
263
264 uint8_t FourthByte = Annotations.consume_front();
265
266 if ((FirstByte & 0xE0) == 0xC0)
267 return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
268 (ThirdByte << 8) | FourthByte;
269
270 return -1;
271 }
272
273 static int32_t DecodeSignedOperand(uint32_t Operand) {
274 if (Operand & 1)
275 return -(Operand >> 1);
276 return Operand >> 1;
277 }
278
279 static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
280 return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
281 }
282
283 bool ParseCurrentAnnotation() {
284 if (Current)
285 return true;
286
287 Next = Data;
288 uint32_t Op = GetCompressedAnnotation(Next);
289 DecodedAnnotation Result;
290 Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
291 switch (Result.OpCode) {
293 Result.Name = "Invalid";
294 Next = ArrayRef<uint8_t>();
295 break;
297 Result.Name = "CodeOffset";
298 Result.U1 = GetCompressedAnnotation(Next);
299 break;
301 Result.Name = "ChangeCodeOffsetBase";
302 Result.U1 = GetCompressedAnnotation(Next);
303 break;
305 Result.Name = "ChangeCodeOffset";
306 Result.U1 = GetCompressedAnnotation(Next);
307 break;
309 Result.Name = "ChangeCodeLength";
310 Result.U1 = GetCompressedAnnotation(Next);
311 break;
313 Result.Name = "ChangeFile";
314 Result.U1 = GetCompressedAnnotation(Next);
315 break;
317 Result.Name = "ChangeLineEndDelta";
318 Result.U1 = GetCompressedAnnotation(Next);
319 break;
321 Result.Name = "ChangeRangeKind";
322 Result.U1 = GetCompressedAnnotation(Next);
323 break;
325 Result.Name = "ChangeColumnStart";
326 Result.U1 = GetCompressedAnnotation(Next);
327 break;
329 Result.Name = "ChangeColumnEnd";
330 Result.U1 = GetCompressedAnnotation(Next);
331 break;
333 Result.Name = "ChangeLineOffset";
334 Result.S1 = DecodeSignedOperand(Next);
335 break;
337 Result.Name = "ChangeColumnEndDelta";
338 Result.S1 = DecodeSignedOperand(Next);
339 break;
341 Result.Name = "ChangeCodeOffsetAndLineOffset";
342 uint32_t Annotation = GetCompressedAnnotation(Next);
343 Result.S1 = DecodeSignedOperand(Annotation >> 4);
344 Result.U1 = Annotation & 0xf;
345 break;
346 }
348 Result.Name = "ChangeCodeLengthAndCodeOffset";
349 Result.U1 = GetCompressedAnnotation(Next);
350 Result.U2 = GetCompressedAnnotation(Next);
351 break;
352 }
353 }
354 Result.Bytes = Data.take_front(Data.size() - Next.size());
355 Current = Result;
356 return true;
357 }
358
359 std::optional<DecodedAnnotation> Current;
360 ArrayRef<uint8_t> Data;
361 ArrayRef<uint8_t> Next;
362};
363
364// S_INLINESITE
384
391
392// S_PUB32
408
409// S_REGISTER
423
424// S_PROCREF, S_LPROCREF
440
441// S_LOCAL
454
460
465
466enum : uint16_t { MaxDefRange = 0xf000 };
467
468// S_DEFRANGE
469class DefRangeSym : public SymbolRecord {
470 static constexpr uint32_t RelocationOffset = 8;
471
472public:
477
479 return RecordOffset + RelocationOffset;
480 }
481
484 std::vector<LocalVariableAddrGap> Gaps;
485
487};
488
489// S_DEFRANGE_SUBFIELD
491 static constexpr uint32_t RelocationOffset = 12;
492
493public:
498
500 return RecordOffset + RelocationOffset;
501 }
502
506 std::vector<LocalVariableAddrGap> Gaps;
507
509};
510
515
516// S_DEFRANGE_REGISTER
532
538
539// S_DEFRANGE_SUBFIELD_REGISTER
556
560
561// S_DEFRANGE_FRAMEPOINTER_REL
582
588
589// S_DEFRANGE_REGISTER_REL
591public:
596
597 // The flags implement this notional bitfield:
598 // uint16_t IsSubfield : 1;
599 // uint16_t Padding : 3;
600 // uint16_t OffsetInParent : 12;
601 enum : uint16_t {
604 };
605
606 bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
607 uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
608
610
613 std::vector<LocalVariableAddrGap> Gaps;
614
616};
617
618// S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
631
636 /// Offset to add after dereferencing `Register + BasePointerOffset`.
638};
639
640/// S_DEFRANGE_REGISTER_REL_INDIR
641///
642/// The local is located at `*(Register + BasePointerOffset) + OffsetInUDT`.
644public:
650
651 // These flags are the same as in DefRangeRegisterRelSym.
652 // The flags implement this notional bitfield:
653 // uint16_t IsSubfield : 1;
654 // uint16_t Padding : 3;
655 // uint16_t OffsetInParent : 12;
656 enum : uint16_t {
659 };
660
661 bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
662 uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
663
667
670 std::vector<LocalVariableAddrGap> Gaps;
671
673};
674
675// S_BLOCK32
676class BlockSym : public SymbolRecord {
677 static constexpr uint32_t RelocationOffset = 16;
678
679public:
683
685 return RecordOffset + RelocationOffset;
686 }
687
694
696};
697
698// S_LABEL32
699class LabelSym : public SymbolRecord {
700 static constexpr uint32_t RelocationOffset = 4;
701
702public:
706
708 return RecordOffset + RelocationOffset;
709 }
710
715
717};
718
719// S_OBJNAME
733
734// S_ENVBLOCK
746
747// S_EXPORT
760
761// S_FILESTATIC
776
777// S_COMPILE2
801
802// S_COMPILE3
841
842// S_FRAMEPROC
844public:
849
857
861
866
868 FrameProcedureOptions RegFlags{(static_cast<uint32_t>(R) & 3U) << 14U};
870 RegFlags;
871 }
872
876
878 FrameProcedureOptions RegFlags{(static_cast<uint32_t>(R) & 3U) << 16U};
880 RegFlags;
881 }
882
886
890
891 /// Extract the register this frame uses to refer to local variables.
895
899
900 /// Extract the register this frame uses to refer to parameters.
904
906
907private:
908};
909
910// S_CALLSITEINFO
912 static constexpr uint32_t RelocationOffset = 4;
913
914public:
918
920 return RecordOffset + RelocationOffset;
921 }
922
926
928};
929
930// S_HEAPALLOCSITE
951
952// S_FRAMECOOKIE
954 static constexpr uint32_t RelocationOffset = 4;
955
956public:
960
962 return RecordOffset + RelocationOffset;
963 }
964
969
971};
972
973// S_UDT, S_COBOLUDT
985
986// S_BUILDINFO
998
999// S_BPREL32
1013
1014// S_REGREL32
1029
1030/// S_REGREL32_INDIR
1031///
1032/// \p Name is located at `*($Register + Offset) + OffsetInUDT` with type
1033/// \p Type.
1049
1050// S_CONSTANT, S_MANCONSTANT
1064
1065// S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
1066class DataSym : public SymbolRecord {
1067 static constexpr uint32_t RelocationOffset = 8;
1068
1069public:
1073
1075 return RecordOffset + RelocationOffset;
1076 }
1077
1082
1084};
1085
1086// S_LTHREAD32, S_GTHREAD32
1107
1108// S_UNAMESPACE
1120
1121// S_ANNOTATION
1135
1136/// `S_ASSOCIATION` - Associates a symbol with another one.
1137///
1138/// For coroutines, the associated symbol is the primary coroutine function in
1139/// case this symbol is contained in an init/resume/destroy coroutine. It's also
1140/// present in the primary coroutine function where it points to one of the
1141/// generated init/resume/destroy symbols.
1155
1158
1159} // end namespace codeview
1160} // end namespace llvm
1161
1162#endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS, uint64_t Address=0, const MCDisassembler *Decoder=nullptr)
Lightweight arrays that are backed by an arbitrary BinaryStream.
#define LLVM_ABI
Definition Compiler.h:215
Register Reg
An arbitrary precision integer that knows its signedness.
Definition APSInt.h:24
Annotations lets you mark points and ranges inside source code, for tests:
Definition Annotations.h:67
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.
Tagged union holding either a T or a Error.
Definition Error.h:485
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::vector< StringRef > Strings
AnnotationSym(uint32_t RecordOffset)
AnnotationSym(SymbolRecordKind Kind)
AssociationSym(SymbolRecordKind Kind)
AssociationSym(uint32_t RecordOffset)
BPRelativeSym(uint32_t RecordOffset)
BPRelativeSym(SymbolRecordKind Kind)
uint32_t getRelocationOffset() const
BlockSym(uint32_t RecordOffset)
BlockSym(SymbolRecordKind Kind)
BuildInfoSym(SymbolRecordKind Kind)
BuildInfoSym(uint32_t RecordOffset)
uint32_t getRelocationOffset() const
CallSiteInfoSym(SymbolRecordKind Kind)
CallSiteInfoSym(uint32_t RecordOffset)
CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset)
std::vector< TypeIndex > Indices
CallerSym(SymbolRecordKind Kind)
CoffGroupSym(SymbolRecordKind Kind)
CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset)
Compile2Sym(uint32_t RecordOffset)
Compile2Sym(SymbolRecordKind Kind)
std::vector< StringRef > ExtraStrings
CompileSym3Flags getFlags() const
Compile3Sym(SymbolRecordKind Kind)
Compile3Sym(uint32_t RecordOffset)
SourceLanguage getLanguage() const
void setLanguage(SourceLanguage Lang)
ConstantSym(SymbolRecordKind Kind)
ConstantSym(uint32_t RecordOffset)
DataSym(uint32_t RecordOffset)
DataSym(SymbolRecordKind Kind)
uint32_t getRelocationOffset() const
DefRangeFramePointerRelSym(SymbolRecordKind Kind)
DefRangeFramePointerRelSym(uint32_t RecordOffset)
DefRangeFramePointerRelHeader Hdr
std::vector< LocalVariableAddrGap > Gaps
DefRangeRegisterRelIndirSym(uint32_t RecordOffset)
std::vector< LocalVariableAddrGap > Gaps
DefRangeRegisterRelIndirSym(SymbolRecordKind Kind)
DefRangeRegisterRelIndirHeader Hdr
std::vector< LocalVariableAddrGap > Gaps
DefRangeRegisterRelSym(uint32_t RecordOffset)
DefRangeRegisterRelSym(SymbolRecordKind Kind)
DefRangeRegisterSym(SymbolRecordKind Kind)
std::vector< LocalVariableAddrGap > Gaps
DefRangeRegisterSym(uint32_t RecordOffset)
DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
std::vector< LocalVariableAddrGap > Gaps
DefRangeSubfieldRegisterHeader Hdr
DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
DefRangeSubfieldSym(SymbolRecordKind Kind)
std::vector< LocalVariableAddrGap > Gaps
DefRangeSubfieldSym(uint32_t RecordOffset)
DefRangeSym(SymbolRecordKind Kind)
std::vector< LocalVariableAddrGap > Gaps
uint32_t getRelocationOffset() const
DefRangeSym(uint32_t RecordOffset)
LocalVariableAddrRange Range
EnvBlockSym(SymbolRecordKind Kind)
std::vector< StringRef > Fields
EnvBlockSym(uint32_t RecordOffset)
ExportSym(SymbolRecordKind Kind)
ExportSym(uint32_t RecordOffset)
FileStaticSym(uint32_t RecordOffset)
FileStaticSym(SymbolRecordKind Kind)
FrameCookieSym(SymbolRecordKind Kind)
uint32_t getRelocationOffset() const
FrameCookieSym(uint32_t RecordOffset)
void setEncodedParamFramePtrReg(EncodedFramePtrReg R)
FrameProcSym(SymbolRecordKind Kind)
FrameProcSym(uint32_t RecordOffset)
RegisterId getLocalFramePtrReg(CPUType CPU) const
Extract the register this frame uses to refer to local variables.
void setFlags(FrameProcedureOptions O)
EncodedFramePtrReg getEncodedParamFramePtrReg() const
RegisterId getParamFramePtrReg(CPUType CPU) const
Extract the register this frame uses to refer to parameters.
void setEncodedLocalFramePtrReg(EncodedFramePtrReg R)
void setLocalFramePtrReg(RegisterId Reg, CPUType CPU)
FrameProcedureOptions getFlags() const
FrameProcedureOptions Flags
void setParamFramePtrReg(RegisterId Reg, CPUType CPU)
EncodedFramePtrReg getEncodedLocalFramePtrReg() const
HeapAllocationSiteSym(uint32_t RecordOffset)
HeapAllocationSiteSym(SymbolRecordKind Kind)
HotPatchFuncSym(SymbolRecordKind Kind)
HotPatchFuncSym(uint32_t RecordOffset)
std::vector< uint8_t > AnnotationData
InlineSiteSym(SymbolRecordKind Kind)
iterator_range< BinaryAnnotationIterator > annotations() const
InlineSiteSym(uint32_t RecordOffset)
JumpTableSym(SymbolRecordKind Kind)
JumpTableEntrySize SwitchType
JumpTableSym(uint32_t RecordOffset)
uint32_t getRelocationOffset() const
LabelSym(SymbolRecordKind Kind)
LabelSym(uint32_t RecordOffset)
LocalSym(SymbolRecordKind Kind)
LocalSym(uint32_t RecordOffset)
ObjNameSym(SymbolRecordKind Kind)
ObjNameSym(uint32_t RecordOffset)
ProcRefSym(uint32_t RecordOffset)
ProcRefSym(SymbolRecordKind Kind)
ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset)
uint32_t getRelocationOffset() const
ProcSym(SymbolRecordKind Kind)
PublicSym32(SymbolRecordKind Kind)
PublicSym32(uint32_t RecordOffset)
RegRelativeIndirSym(SymbolRecordKind Kind)
RegRelativeIndirSym(uint32_t RecordOffset)
RegRelativeSym(SymbolRecordKind Kind)
RegRelativeSym(uint32_t RecordOffset)
RegisterSym(uint32_t RecordOffset)
RegisterSym(SymbolRecordKind Kind)
ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
ScopeEndSym(SymbolRecordKind Kind)
SectionSym(SymbolRecordKind Kind)
SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset)
SymbolRecord(SymbolRecordKind Kind)
SymbolRecordKind getKind() const
ThreadLocalDataSym(uint32_t RecordOffset)
ThreadLocalDataSym(SymbolRecordKind Kind)
ArrayRef< uint8_t > VariantData
Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset)
Thunk32Sym(SymbolRecordKind Kind)
TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset)
TrampolineSym(SymbolRecordKind Kind)
A 32-bit type reference.
Definition TypeIndex.h:97
UDTSym(SymbolRecordKind Kind)
UDTSym(uint32_t RecordOffset)
UsingNamespaceSym(uint32_t RecordOffset)
UsingNamespaceSym(SymbolRecordKind Kind)
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
Definition iterator.h:80
A range adaptor for a pair of iterators.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
ProcSymFlags
Corresponds to the CV_PROCFLAGS bitfield.
Definition CodeView.h:417
LocalSymFlags
Corresponds to CV_LVARFLAGS bitfield.
Definition CodeView.h:390
CompileSym2Flags
Corresponds to COMPILESYM2::Flags bitfield.
Definition CodeView.h:431
CPUType
These values correspond to the CV_CPU_TYPE_e enumeration, and are documented here: https://msdn....
Definition CodeView.h:76
CompileSym3Flags
Corresponds to COMPILESYM3::Flags bitfield.
Definition CodeView.h:447
SymbolRecordKind
Distinguishes individual records in the Symbols subsection of a .debug$S section.
Definition CodeView.h:41
AssociationKind
Type of associated symbol in S_ASSOCIATION.
Definition CodeView.h:628
ThunkOrdinal
These values correspond to the THUNK_ORDINAL enumeration.
Definition CodeView.h:538
EncodedFramePtrReg
Two-bit value indicating which register is the designated frame pointer register.
Definition CodeView.h:525
LLVM_ABI RegisterId decodeFramePtrReg(EncodedFramePtrReg EncodedReg, CPUType CPU)
PublicSymFlags
Corresponds to the CV_PUBSYMFLAGS bitfield.
Definition CodeView.h:407
LLVM_ABI EncodedFramePtrReg encodeFramePtrReg(RegisterId Reg, CPUType CPU)
SourceLanguage
These values correspond to the CV_CFL_LANG enumeration in the Microsoft Debug Interface Access SDK,...
Definition CodeView.h:146
LLVM_ABI Expected< CVSymbol > readSymbolFromStream(BinaryStreamRef Stream, uint32_t Offset)
detail::packed_endian_specific_integral< uint32_t, llvm::endianness::little, unaligned > ulittle32_t
Definition Endian.h:270
detail::packed_endian_specific_integral< uint16_t, llvm::endianness::little, unaligned > ulittle16_t
Definition Endian.h:267
detail::packed_endian_specific_integral< int32_t, llvm::endianness::little, unaligned > little32_t
Definition Endian.h:280
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
DWARFExpression::Operation Op
BinaryAnnotationIterator & operator=(const BinaryAnnotationIterator Other)
BinaryAnnotationIterator & operator++()
BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
const DecodedAnnotation & operator*()
bool operator==(BinaryAnnotationIterator Other) const
BinaryAnnotationIterator(ArrayRef< uint8_t > Annotations)
BinaryAnnotationsOpCode OpCode
little32_t OffsetInUdt
Offset to add after dereferencing Register + BasePointerOffset.