25 #include <system_error>
28 using namespace llvm::codeview;
37 : TypeDB(TypeDB), ObjDelegate(ObjDelegate), W(W),
38 PrintRecordBytes(PrintRecordBytes), InFunctionScope(
false) {}
41 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \
42 Error visitKnownRecord(CVSymbol &CVR, Name &Record) override;
43 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
44 #include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
60 bool PrintRecordBytes;
65 void CVSymbolDumperImpl::printLocalVariableAddrRange(
69 ObjDelegate->printRelocatedField(
"OffsetStart", RelocationOffset,
72 W.printHex(
"Range", Range.
Range);
75 void CVSymbolDumperImpl::printLocalVariableAddrGap(
77 for (
auto &Gap : Gaps) {
79 W.printHex(
"GapStartOffset", Gap.GapStartOffset);
80 W.printHex(
"Range", Gap.Range);
93 if (PrintRecordBytes && ObjDelegate)
94 ObjDelegate->printBinaryBlockWithRelocs(
"SymData", CVR.
content());
102 W.printHex(
"PtrParent", Block.
Parent);
103 W.printHex(
"PtrEnd", Block.
End);
104 W.printHex(
"CodeSize", Block.
CodeSize);
109 W.printHex(
"Segment", Block.
Segment);
110 W.printString(
"BlockName", Block.
Name);
111 W.printString(
"LinkageName", LinkageName);
117 W.printNumber(
"Parent", Thunk.
Parent);
118 W.printNumber(
"End", Thunk.
End);
119 W.printNumber(
"Next", Thunk.
Next);
120 W.printNumber(
"Off", Thunk.
Offset);
121 W.printNumber(
"Seg", Thunk.
Segment);
122 W.printNumber(
"Len", Thunk.
Length);
131 W.printNumber(
"Size", Tramp.
Size);
142 W.printNumber(
"Alignment", Section.
Alignment);
143 W.printNumber(
"Rva", Section.
Rva);
144 W.printNumber(
"Length", Section.
Length);
149 W.printString(
"Name", Section.
Name);
156 W.printNumber(
"Size", CoffGroup.
Size);
160 W.printNumber(
"Offset", CoffGroup.
Offset);
161 W.printNumber(
"Segment", CoffGroup.
Segment);
162 W.printString(
"Name", CoffGroup.
Name);
170 W.printNumber(
"Offset", BPRel.
Offset);
171 printTypeIndex(
"Type", BPRel.
Type);
172 W.printString(
"VarName", BPRel.
Name);
180 W.printNumber(
"BuildId", BuildInfo.
BuildId);
190 ObjDelegate->printRelocatedField(
"CodeOffset",
194 W.printHex(
"Segment", CallSiteInfo.
Segment);
195 printTypeIndex(
"Type", CallSiteInfo.
Type);
196 if (!LinkageName.
empty())
197 W.printString(
"LinkageName", LinkageName);
206 for (
auto Entry : EnvBlock.
Fields) {
207 W.printString(Entry);
215 W.printNumber(
"Index", FileStatic.
Index);
218 W.printString(
"Name", FileStatic.
Name);
224 W.printNumber(
"Ordinal", Export.
Ordinal);
226 W.printString(
"Name", Export.
Name);
237 std::string FrontendVersion;
243 std::string BackendVersion;
249 W.printString(
"FrontendVersion", FrontendVersion);
250 W.printString(
"BackendVersion", BackendVersion);
251 W.printString(
"VersionName", Compile2.
Version);
262 std::string FrontendVersion;
269 std::string BackendVersion;
276 W.printString(
"FrontendVersion", FrontendVersion);
277 W.printString(
"BackendVersion", BackendVersion);
278 W.printString(
"VersionName", Compile3.
Version);
286 printTypeIndex(
"Type", Constant.
Type);
287 W.printNumber(
"Value", Constant.
Value);
288 W.printString(
"Name", Constant.
Name);
301 printTypeIndex(
"Type", Data.
Type);
302 W.printString(
"DisplayName", Data.
Name);
303 if (!LinkageName.
empty())
304 W.printString(
"LinkageName", LinkageName);
311 DictScope S(W,
"DefRangeFramePointerRelFullScope");
312 W.printNumber(
"Offset", DefRangeFramePointerRelFullScope.
Offset);
318 DictScope S(W,
"DefRangeFramePointerRel");
320 W.printNumber(
"Offset", DefRangeFramePointerRel.
Offset);
321 printLocalVariableAddrRange(DefRangeFramePointerRel.
Range,
323 printLocalVariableAddrGap(DefRangeFramePointerRel.
Gaps);
331 W.printNumber(
"BaseRegister", DefRangeRegisterRel.
Hdr.
Register);
332 W.printBoolean(
"HasSpilledUDTMember",
334 W.printNumber(
"OffsetInParent", DefRangeRegisterRel.
offsetInParent());
336 printLocalVariableAddrRange(DefRangeRegisterRel.
Range,
338 printLocalVariableAddrGap(DefRangeRegisterRel.
Gaps);
346 W.printNumber(
"Register", DefRangeRegister.
Hdr.
Register);
348 printLocalVariableAddrRange(DefRangeRegister.
Range,
350 printLocalVariableAddrGap(DefRangeRegister.
Gaps);
356 DictScope S(W,
"DefRangeSubfieldRegister");
358 W.printNumber(
"Register", DefRangeSubfieldRegister.
Hdr.
Register);
361 printLocalVariableAddrRange(DefRangeSubfieldRegister.
Range,
363 printLocalVariableAddrGap(DefRangeSubfieldRegister.
Gaps);
373 auto ProgramStringTableOffset = DefRangeSubfield.
Program;
374 if (ProgramStringTableOffset >= StringTable.
size())
375 return llvm::make_error<CodeViewError>(
376 "String table offset outside of bounds of String Table!");
379 W.printString(
"Program", Program);
382 printLocalVariableAddrRange(DefRangeSubfield.
Range,
384 printLocalVariableAddrGap(DefRangeSubfield.
Gaps);
393 StringRef StringTable = ObjDelegate->getStringTable();
394 auto ProgramStringTableOffset = DefRange.
Program;
395 if (ProgramStringTableOffset >= StringTable.
size())
396 return llvm::make_error<CodeViewError>(
397 "String table offset outside of bounds of String Table!");
400 W.printString(
"Program", Program);
403 printLocalVariableAddrGap(DefRange.
Gaps);
413 ObjDelegate->printRelocatedField(
"CodeOffset",
417 W.printHex(
"Register", FrameCookie.
Register);
418 W.printEnum(
"CookieKind", uint16_t(FrameCookie.
CookieKind),
420 W.printHex(
"Flags", FrameCookie.
Flags);
431 W.printHex(
"BytesOfCalleeSavedRegisters",
434 W.printHex(
"SectionIdOfExceptionHandler",
436 W.printFlags(
"Flags", static_cast<uint32_t>(FrameProc.
Flags),
447 ObjDelegate->printRelocatedField(
"CodeOffset",
451 W.printHex(
"Segment", HeapAllocSite.
Segment);
453 printTypeIndex(
"Type", HeapAllocSite.
Type);
454 if (!LinkageName.
empty())
455 W.printString(
"LinkageName", LinkageName);
463 W.printHex(
"PtrParent", InlineSite.
Parent);
464 W.printHex(
"PtrEnd", InlineSite.
End);
465 printTypeIndex(
"Inlinee", InlineSite.
Inlinee);
467 ListScope BinaryAnnotations(W,
"BinaryAnnotations");
468 for (
auto &Annotation : InlineSite.
annotations()) {
471 return llvm::make_error<CodeViewError>(
472 "Invalid binary annotation opcode!");
491 W.printHex(
"ChangeFile",
492 ObjDelegate->getFileNameForFileOffset(
Annotation.U1),
500 W.startLine() <<
"ChangeCodeOffsetAndLineOffset: {CodeOffset: "
506 W.startLine() <<
"ChangeCodeLengthAndCodeOffset: {CodeOffset: "
508 <<
", Length: " << W.hex(
Annotation.U1) <<
"}\n";
519 W.printNumber(
"Type", Register.
Index);
521 W.printString(
"Name", Register.
Name);
527 W.printNumber(
"Type", Public.
Index);
528 W.printNumber(
"Seg", Public.
Segment);
529 W.printNumber(
"Off", Public.
Offset);
530 W.printString(
"Name", Public.
Name);
536 W.printNumber(
"SumName", ProcRef.
SumName);
537 W.printNumber(
"SymOffset", ProcRef.
SymOffset);
538 W.printNumber(
"Mod", ProcRef.
Module);
539 W.printString(
"Name", ProcRef.
Name);
551 W.printHex(
"Segment", Label.
Segment);
552 W.printHex(
"Flags", uint8_t(Label.
Flags));
554 W.printString(
"DisplayName", Label.
Name);
555 if (!LinkageName.
empty())
556 W.printString(
"LinkageName", LinkageName);
563 printTypeIndex(
"Type", Local.
Type);
565 W.printString(
"VarName", Local.
Name);
572 W.printHex(
"Signature", ObjName.
Signature);
573 W.printString(
"ObjectName", ObjName.
Name);
581 return llvm::make_error<CodeViewError>(
582 "Visiting a ProcSym while inside function scope!");
584 InFunctionScope =
true;
588 W.printHex(
"PtrParent", Proc.
Parent);
589 W.printHex(
"PtrEnd", Proc.
End);
590 W.printHex(
"PtrNext", Proc.
Next);
591 W.printHex(
"CodeSize", Proc.
CodeSize);
592 W.printHex(
"DbgStart", Proc.
DbgStart);
593 W.printHex(
"DbgEnd", Proc.
DbgEnd);
599 W.printHex(
"Segment", Proc.
Segment);
600 W.printFlags(
"Flags", static_cast<uint8_t>(Proc.
Flags),
602 W.printString(
"DisplayName", Proc.
Name);
603 if (!LinkageName.
empty())
604 W.printString(
"LinkageName", LinkageName);
610 if (CVR.
kind() == SymbolKind::S_END)
612 else if (CVR.
kind() == SymbolKind::S_PROC_ID_END)
614 else if (CVR.
kind() == SymbolKind::S_INLINESITE_END)
617 InFunctionScope =
false;
622 ListScope S(W, CVR.
kind() == S_CALLEES ?
"Callees" :
"Callers");
623 for (
auto FuncID : Caller.
Indices)
624 printTypeIndex(
"FuncID", FuncID);
632 W.printHex(
"Offset", RegRel.
Offset);
633 printTypeIndex(
"Type", RegRel.
Type);
634 W.printHex(
"Register", RegRel.
Register);
635 W.printString(
"VarName", RegRel.
Name);
648 printTypeIndex(
"Type", Data.
Type);
649 W.printString(
"DisplayName", Data.
Name);
650 if (!LinkageName.
empty())
651 W.printString(
"LinkageName", LinkageName);
657 printTypeIndex(
"Type", UDT.
Type);
658 W.printString(
"UDTName", UDT.
Name);
662 Error CVSymbolDumperImpl::visitUnknownSymbol(
CVSymbol &CVR) {
665 W.printNumber(
"Length", CVR.
length());
672 CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes);
683 CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes);
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
uint32_t getRelocationOffset() const
uint32_t ModFilenameOffset
uint32_t OffsetOfExceptionHandler
ArrayRef< EnumEntry< uint16_t > > getExportSymFlagNames()
ArrayRef< EnumEntry< uint32_t > > getCompileSym3FlagNames()
uint32_t getRelocationOffset() const
uint16_t SectionIdOfExceptionHandler
FrameProcedureOptions Flags
uint32_t getRelocationOffset() const
uint32_t BytesOfCalleeSavedRegisters
ArrayRef< EnumEntry< uint16_t > > getRegisterNames()
uint32_t getRelocationOffset() const
Error visitSymbolRecord(CVSymbol &Record)
uint16_t VersionBackendMinor
bool hasSpilledUDTMember() const
uint16_t VersionFrontendMajor
llvm::iterator_range< BinaryAnnotationIterator > annotations() const
std::vector< LocalVariableAddrGap > Gaps
uint16_t VersionBackendBuild
std::vector< LocalVariableAddrGap > Gaps
uint16_t VersionFrontendMajor
ArrayRef< EnumEntry< uint8_t > > getThunkOrdinalNames()
uint16_t VersionFrontendQFE
uint16_t VersionBackendMajor
ArrayRef< EnumEntry< uint8_t > > getFrameCookieKindNames()
static Error visitKnownRecord(CVSymbol &Record, SymbolVisitorCallbacks &Callbacks)
Function Alias Analysis false
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
uint32_t getRelocationOffset() const
uint16_t CallInstructionSize
uint32_t getRelocationOffset() const
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
ArrayRef< EnumEntry< COFF::SectionCharacteristics > > getImageSectionCharacteristicNames()
uint32_t getRelocationOffset() const
uint16_t VersionFrontendBuild
ArrayRef< EnumEntry< unsigned > > getCPUTypeNames()
std::vector< LocalVariableAddrGap > Gaps
void addCallbackToPipeline(SymbolVisitorCallbacks &Callbacks)
This is an important base class in LLVM.
std::vector< StringRef > Fields
LocalVariableAddrRange Range
LocalVariableAddrRange Range
uint32_t getRelocationOffset() const
uint32_t getRelocationOffset() const
uint16_t offsetInParent() const
uint16_t VersionBackendMajor
uint32_t getRelocationOffset() const
std::vector< TypeIndex > Indices
LocalVariableAddrRange Range
std::vector< LocalVariableAddrGap > Gaps
LocalVariableAddrRange Range
uint16_t VersionFrontendMinor
uint16_t VersionFrontendMinor
uint32_t getFlags() const
Error dump(CVRecord< SymbolKind > &Record)
Dumps one type record.
ArrayRef< EnumEntry< uint32_t > > getFrameProcSymFlagNames()
static ErrorSuccess success()
Create a success value.
ArrayRef< EnumEntry< SymbolKind > > getSymbolTypeNames()
LocalVariableAddrRange Range
uint16_t VersionBackendMinor
ArrayRef< uint8_t > content() const
Promote Memory to Register
ArrayRef< EnumEntry< uint8_t > > getProcSymFlagNames()
LocalVariableAddrRange Range
uint8_t getLanguage() const
ArrayRef< EnumEntry< SourceLanguage > > getSourceLanguageNames()
uint32_t PaddingFrameBytes
uint8_t getLanguage() const
ArrayRef< EnumEntry< uint32_t > > getCompileSym2FlagNames()
LLVM_NODISCARD std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
ArrayRef< EnumEntry< uint16_t > > getTrampolineNames()
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
Error visitSymbolStream(const CVSymbolArray &Symbols)
std::vector< LocalVariableAddrGap > Gaps
uint16_t VersionBackendBuild
uint32_t getRelocationOffset() const
static void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, TypeIndex TI, TypeDatabase &DB)
uint32_t getRelocationOffset() const
uint32_t getFlags() const
std::vector< LocalVariableAddrGap > Gaps
uint16_t VersionBackendQFE
A raw_ostream that writes to an std::string.
uint32_t getRelocationOffset() const
Lightweight error class with error context and mandatory checking.
ArrayRef< EnumEntry< uint16_t > > getLocalFlagNames()
uint32_t getRelocationOffset() const
StringRef - Represent a constant reference to a string, i.e.
uint16_t VersionFrontendBuild