LLVM: lib/DebugInfo/LogicalView/Readers/LVCodeViewReader.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
35
36using namespace llvm;
42
43#define DEBUG_TYPE "CodeViewReader"
44
46 switch (Kind) {
47#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
48 case EnumName: \
49 return #EnumName;
50#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
51 default:
52 return "UnknownSym";
53 }
55}
56
59#define RETURN_CASE(Enum, X, Ret) \
60 case Enum::X: \
61 return Ret;
62
65#define CV_REGISTERS_ARM
66#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
67#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
68#undef CV_REGISTER
69#undef CV_REGISTERS_ARM
70
71 default:
72 break;
73 }
76#define CV_REGISTERS_ARM64
77#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
78#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
79#undef CV_REGISTER
80#undef CV_REGISTERS_ARM64
81
82 default:
83 break;
84 }
85 } else {
87#define CV_REGISTERS_X86
88#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
89#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
90#undef CV_REGISTER
91#undef CV_REGISTERS_X86
92
93 default:
94 break;
95 }
96 }
97 return "formatUnknownEnum(Id)";
98}
99
100void LVCodeViewReader::printRelocatedField(StringRef Label,
106 StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
107 if (!resolveSymbolName(CoffSection, RelocOffset, Symbol))
109 else
111}
112
117 StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
118 if (resolveSymbolName(CoffSection, RelocOffset, Symbol))
119 Symbol = "";
120}
121
123LVCodeViewReader::getFileNameForFileOffset(uint32_t FileOffset,
125 if (SG) {
130 }
132 }
133
134
135 if (!CVFileChecksumTable.valid() || !CVStringTable.valid())
137
139 CVFileChecksumTable.getArray().at(FileOffset);
140
141
142 if (Iter == CVFileChecksumTable.end())
144
146 if (!NameOrErr)
148 return *NameOrErr;
149}
150
151Error LVCodeViewReader::printFileNameForOffset(StringRef Label,
152 uint32_t FileOffset,
153 const SymbolGroup *SG) {
154 Expected NameOrErr = getFileNameForFileOffset(FileOffset, SG);
155 if (!NameOrErr)
157 W.printHex(Label, *NameOrErr, FileOffset);
159}
160
161void LVCodeViewReader::cacheRelocations() {
162 for (const SectionRef &Section : getObj().sections()) {
163 const coff_section *CoffSection = getObj().getCOFFSection(Section);
164
165 auto &RM = RelocMap[CoffSection];
167
168
169 llvm::sort(RM, [](RelocationRef L, RelocationRef R) {
170 return L.getOffset() < R.getOffset();
171 });
172 }
173}
174
175
176
177Error LVCodeViewReader::resolveSymbol(const coff_section *CoffSection,
178 uint64_t Offset, SymbolRef &Sym) {
179 const auto &Relocations = RelocMap[CoffSection];
181 for (const RelocationRef &Relocation : Relocations) {
182 uint64_t RelocationOffset = Relocation.getOffset();
183
184 if (RelocationOffset == Offset) {
185 SymI = Relocation.getSymbol();
186 break;
187 }
188 }
189 if (SymI == getObj().symbol_end())
191 Sym = *SymI;
192 return ErrorSuccess();
193}
194
195
196
197Error LVCodeViewReader::resolveSymbolName(const coff_section *CoffSection,
200 if (Error E = resolveSymbol(CoffSection, Offset, Symbol))
201 return E;
202 Expected NameOrErr = Symbol.getName();
203 if (!NameOrErr)
205 Name = *NameOrErr;
206 return ErrorSuccess();
207}
208
209
210
211
212
215 auto Find = [=](const char *String) -> bool { return Name.contains(String); };
216 auto Starts = [=](const char *Pattern) -> bool {
218 };
219 auto CheckExclude = [&]() -> bool {
220 if (Starts("__") || Starts("_PMD") || Starts("_PMFN"))
221 return true;
222 if (Find("_s__"))
223 return true;
224 if (Find("_CatchableType") || Find("_TypeDescriptor"))
225 return true;
226 if (Find("Intermediate\\vctools"))
227 return true;
228 if (Find("$initializer$") || Find("dynamic initializer"))
229 return true;
230 if (Find("`vftable'") || Find("_GLOBAL__sub"))
231 return true;
232 return false;
233 };
234 bool Excluded = CheckExclude();
235 if (Excluded)
236 Element->setIsSystem();
237
238 return Excluded;
239}
240
241Error LVCodeViewReader::collectInlineeInfo(
245 uint32_t LineNumber = Line.Header->SourceLineNum;
250 if (Error Err = printFileNameForOffset("FileID", FileOffset, SG))
251 return Err;
253
254 if (Lines.hasExtraFiles()) {
258 if (Error Err = printFileNameForOffset("FileID", FID, SG))
259 return Err;
260 }
261 });
262 Expected NameOrErr = getFileNameForFileOffset(FileOffset, SG);
263 if (!NameOrErr)
264 return NameOrErr.takeError();
265 LogicalVisitor.addInlineeInfo(TIInlinee, LineNumber, *NameOrErr);
266 }
267
269}
270
271Error LVCodeViewReader::traverseInlineeLines(StringRef Subsection) {
273 DebugInlineeLinesSubsectionRef Lines;
274 if (Error E = Lines.initialize(SR))
276
277 return collectInlineeInfo(Lines);
278}
279
280Error LVCodeViewReader::createLines(
282 uint32_t Segment, uint32_t Begin, uint32_t Size, uint32_t NameIndex,
283 const SymbolGroup *SG) {
285 uint32_t End = Begin + Size;
286 W.getOStream() << formatv("{0:x-4}:{1:x-8}-{2:x-8}\n", Segment, Begin, End);
287 });
288
291 return createStringError(object_error::parse_failed, getFileName());
292
293 LineInfo LI(Line.Flags);
294
297 "{0} {1:x-8}\n", utostr(LI.getStartLine()),
299 });
300
301
302
303
304 LVLineDebug *LineDebug = createLineDebug();
305 CULines.push_back(LineDebug);
307 LineDebug->setAddress(Address + Addendum);
308
309 if (LI.isAlwaysStepInto())
310 LineDebug->setIsAlwaysStepInto();
311 else if (LI.isNeverStepInto())
312 LineDebug->setIsNeverStepInto();
313 else
314 LineDebug->setLineNumber(LI.getStartLine());
315
316 if (LI.isStatement())
317 LineDebug->setIsNewStatement();
318
319 Expected NameOrErr = getFileNameForFileOffset(NameIndex, SG);
320 if (!NameOrErr)
322 LineDebug->setFilename(*NameOrErr);
323 }
324
326}
327
328Error LVCodeViewReader::initializeFileAndStringTables(
329 BinaryStreamReader &Reader) {
331 (!CVFileChecksumTable.valid() || !CVStringTable.valid())) {
332
333
334 uint32_t SubType, SubSectionSize;
335
340
341 StringRef Contents;
344
347 case DebugSubsectionKind::FileChecksums:
348 if (Error E = CVFileChecksumTable.initialize(ST))
350 break;
351 case DebugSubsectionKind::StringTable:
352 if (Error E = CVStringTable.initialize(ST))
354 break;
355 default:
356 break;
357 }
358
359 uint32_t PaddedSize = alignTo(SubSectionSize, 4);
360 if (Error E = Reader.skip(PaddedSize - SubSectionSize))
362 }
363
365}
366
369 W.printString("Guid", formatv("{0}", TS.getGuid()).str());
370 W.printNumber("Age", TS.getAge());
371 W.printString("Name", TS.getName());
372 });
373
374 SmallString<128> ServerName(TS.getName());
376 if (BuffOrErr.getError()) {
377
378
381 if (BuffOrErr.getError()) {
382
384 "File '%s' does not exist.",
386 }
387 }
388 MemBuffer = std::move(BuffOrErr.get());
389
390
392 "Invalid PDB file.");
393
394 if (Error Err = loadDataForPDB(PDB_ReaderType::Native, ServerName, Session))
396 ServerName.c_str());
397
398 PdbSession.reset(static_cast<NativeSession *>(Session.release()));
399 PDBFile &Pdb = PdbSession->getPDBFile();
400
401
402
403
404 Expected<InfoStream &> expectedInfo = Pdb.getPDBInfoStream();
405 if (!expectedInfo || expectedInfo->getGuid() != TS.getGuid())
407
408
409
410
411 TypeServer = std::make_shared(&Pdb);
412 LogicalVisitor.setInput(TypeServer);
413
414 LazyRandomTypeCollection &Types = types();
415 LazyRandomTypeCollection &Ids = ids();
416 if (Error Err = traverseTypes(Pdb, Types, Ids))
417 return Err;
418
420}
421
428 });
429
432 if (BuffOrErr.getError()) {
433
435 if (BuffOrErr.getError()) {
436
438 "File '%s' does not exist.",
440 }
441 }
442 MemBuffer = std::move(BuffOrErr.get());
443
444 Expected<std::unique_ptr> BinOrErr = createBinary(*MemBuffer);
447 "Binary object format in '%s' is not supported.",
448 ServerName.c_str());
449
450 Binary &BinaryObj = *BinOrErr.get();
451 if (!BinaryObj.isCOFF())
453 ServerName.c_str());
454
455 Builder = std::make_unique(BuilderAllocator);
456
457
458
460 for (const SectionRef &Section : Obj.sections()) {
461 Expected SectionNameOrErr = Section.getName();
462 if (!SectionNameOrErr)
463 return SectionNameOrErr.takeError();
464 if (*SectionNameOrErr == ".debug$P") {
465 Expected DataOrErr = Section.getContents();
466 if (!DataOrErr)
470 return Err;
473
474 ReaderPrecomp = std::make_unique(
477 ReaderPrecomp->readArray(CVTypesPrecomp, ReaderPrecomp->getLength()));
478
479
480
481 for (const CVType &Type : CVTypesPrecomp) {
482 ArrayRef<uint8_t> TypeData = Type.data();
483 if (Type.kind() == LF_ENDPRECOMP) {
484 EndPrecompRecord EndPrecomp = cantFail(
488 break;
489 }
490 Builder->insertRecordBytes(TypeData);
491 }
492
493 break;
494 }
495 }
496
497
498
499 for (const CVType &Type : CVTypesObj) {
500 ArrayRef<uint8_t> TypeData = Type.data();
501 if (Type.kind() != LF_PRECOMP)
502 Builder->insertRecordBytes(TypeData);
503 }
504
505
506 Builder->ForEachRecord(
507 [&](TypeIndex TI, const CVType &Type) { TypeArray.push_back(Type); });
508
509 ItemStream =
511 ItemStream->setItems(TypeArray);
512 TypeStream.setUnderlyingStream(*ItemStream);
513
514 PrecompHeader =
515 std::make_shared(TypeStream, TypeArray.size());
516
517
518 LogicalVisitor.setInput(PrecompHeader);
519
520 LazyRandomTypeCollection &Types = types();
521 LazyRandomTypeCollection &Ids = ids();
523 LogicalVisitor.getShared());
525}
526
527Error LVCodeViewReader::traverseTypeSection(StringRef SectionName,
528 const SectionRef &Section) {
530 ListScope D(W, "CodeViewTypes");
531 W.printNumber("Section", SectionName, getObj().getSectionID(Section));
532 });
533
534 Expected DataOrErr = Section.getContents();
535 if (!DataOrErr)
536 return DataOrErr.takeError();
539 return Err;
542
543
544
549
550
551 if (FirstType->kind() == LF_TYPESERVER2) {
552 TypeServer2Record TS = cantFail(
554 return loadTypeServer(TS);
555 }
556
557
558
559 if (FirstType->kind() == LF_PRECOMP) {
560 PrecompRecord Precomp = cantFail(
562 return loadPrecompiledObject(Precomp, CVTypes);
563 }
564
565 LazyRandomTypeCollection &Types = types();
566 LazyRandomTypeCollection &Ids = ids();
567 Types.reset(*DataOrErr, 100);
569 LogicalVisitor.getShared());
571}
572
573Error LVCodeViewReader::traverseTypes(PDBFile &Pdb,
576
577 auto VisitTypes = [&](LazyRandomTypeCollection &Types,
578 LazyRandomTypeCollection &Ids,
580 LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamIdx,
581 LogicalVisitor.getShared());
583 };
584
585 Expected<TpiStream &> StreamTpiOrErr = Pdb.getPDBTpiStream();
586 if (!StreamTpiOrErr)
587 return StreamTpiOrErr.takeError();
588 TpiStream &StreamTpi = *StreamTpiOrErr;
591 W.getOStream() << formatv("Showing {0:N} TPI records\n",
593 });
595 return Err;
596
597 Expected<TpiStream &> StreamIpiOrErr = Pdb.getPDBIpiStream();
598 if (!StreamIpiOrErr)
599 return StreamIpiOrErr.takeError();
600 TpiStream &StreamIpi = *StreamIpiOrErr;
603 W.getOStream() << formatv("Showing {0:N} IPI records\n",
605 });
606 return VisitTypes(Ids, Ids, StreamIPI);
607}
608
609Error LVCodeViewReader::traverseSymbolsSubsection(StringRef Subsection,
610 const SectionRef &Section,
611 StringRef SectionContents) {
612 ArrayRef<uint8_t> BinaryData(Subsection.bytes_begin(),
615 SectionContents);
620
621 LazyRandomTypeCollection &Types = types();
622 LazyRandomTypeCollection &Ids = ids();
623 SymbolVisitorCallbackPipeline Pipeline;
624 SymbolDeserializer Deserializer(&VisitorDelegate,
625 CodeViewContainer::ObjectFile);
626
627
628 LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids,
629 &VisitorDelegate, LogicalVisitor.getShared());
630
633 CVSymbolVisitor Visitor(Pipeline);
634 return Visitor.visitSymbolStream(Symbols);
635}
636
637Error LVCodeViewReader::traverseSymbolSection(StringRef SectionName,
638 const SectionRef &Section) {
640 ListScope D(W, "CodeViewDebugInfo");
641 W.printNumber("Section", SectionName, getObj().getSectionID(Section));
642 });
643
644 Expected SectionOrErr = Section.getContents();
645 if (!SectionOrErr)
646 return SectionOrErr.takeError();
647 StringRef SectionContents = *SectionOrErr;
648 StringRef Data = SectionContents;
649
651 StringMap FunctionLineTables;
652
656
658 return createStringError(object_error::parse_failed, getFileName());
659
661 if (Error Err = initializeFileAndStringTables(FSReader))
662 return Err;
663
664 while (.empty()) {
665
666
667 uint32_t SubType, SubSectionSize;
672
673
674 SubType &= ~SubsectionIgnoreFlag;
675
676
677 if (SubSectionSize > Data.size())
678 return createStringError(object_error::parse_failed, getFileName());
679 StringRef Contents = Data.substr(0, SubSectionSize);
680
681
682
683 size_t SectionOffset = Data.data() - SectionContents.data();
684 size_t NextOffset = SectionOffset + SubSectionSize;
685 NextOffset = alignTo(NextOffset, 4);
686 if (NextOffset > SectionContents.size())
687 return createStringError(object_error::parse_failed, getFileName());
689
691 case DebugSubsectionKind::Symbols:
693 traverseSymbolsSubsection(Contents, Section, SectionContents))
694 return Err;
695 break;
696
697 case DebugSubsectionKind::InlineeLines:
698 if (Error Err = traverseInlineeLines(Contents))
699 return Err;
700 break;
701
702 case DebugSubsectionKind::Lines:
703
704
705
706
707
708 if (options().getGeneralCollectRanges()) {
709
710 if (SubSectionSize < 12) {
711
712
713 return createStringError(object_error::parse_failed, getFileName());
714 }
715
717 if (Error Err = resolveSymbolName(getObj().getCOFFSection(Section),
718 SectionOffset, SymbolName))
720 getFileName());
721
722 LLVM_DEBUG({ W.printString("Symbol Name", SymbolName); });
723 if (!FunctionLineTables.try_emplace(SymbolName, Contents).second) {
724
725 return createStringError(object_error::parse_failed, getFileName());
726 }
727
728 SymbolNames.push_back(SymbolName);
729 }
730 break;
731
732
733 default:
734 break;
735 }
736 W.flush();
737 }
738
739
740
741 for (StringRef SymbolName : SymbolNames) {
743 ListScope S(W, "FunctionLineTable");
744 W.printString("Symbol Name", SymbolName);
745 });
746
747 BinaryStreamReader Reader(FunctionLineTables[SymbolName],
749
750 DebugLinesSubsectionRef Lines;
751 if (Error E = Lines.initialize(Reader))
753
754
758 continue;
759
762
763
764
766
767
769 ScopesWithRanges->clear();
770 Function->getRanges(*ScopesWithRanges);
771 ScopesWithRanges->sort();
772
773 uint16_t Segment = Lines.header()->RelocSegment;
774 uint32_t Begin = Lines.header()->RelocOffset;
775 uint32_t Size = Lines.header()->CodeSize;
776 for (const LineColumnEntry &Block : Lines)
777 if (Error Err = createLines(Block.LineNumbers, Addendum, Segment, Begin,
779 return Err;
780
781
783
785 return Err;
786
788 }
789
791}
792
794
798
799void LVCodeViewReader::mapRangeAddress(const ObjectFile &Obj,
801 bool IsComdat) {
802 if (!Obj.isCOFF())
803 return;
804
806
807 for (const SymbolRef &Sym : Object->symbols()) {
808 if (!Section.containsSymbol(Sym))
809 continue;
810
811 COFFSymbolRef Symbol = Object->getCOFFSymbol(Sym);
813 continue;
814
817 if (!SymNameOrErr) {
818 W.startLine() << "Invalid symbol name: " << Symbol.getSectionNumber()
819 << "\n";
821 continue;
822 }
823 SymbolName = *SymNameOrErr;
824
827 Object->getSection(Symbol.getSectionNumber());
828 if (!SectionOrErr) {
829 W.startLine() << "Invalid section number: " << Symbol.getSectionNumber()
830 << "\n";
832 return;
833 }
834 W.printNumber("Section #", Symbol.getSectionNumber());
836 W.printHex("Value", Symbol.getValue());
837 });
838
839
841 IsComdat);
842 }
843}
844
846 if (Error Err = loadTargetInfo(Obj))
847 return Err;
848
849
850
851
852
853 cacheRelocations();
855
856 for (const SectionRef &Section : Obj.sections()) {
857 Expected SectionNameOrErr = Section.getName();
858 if (!SectionNameOrErr)
859 return SectionNameOrErr.takeError();
860
861
862 if (*SectionNameOrErr == ".debug$T" || *SectionNameOrErr == ".debug$P")
863 if (Error Err = traverseTypeSection(*SectionNameOrErr, Section))
864 return Err;
865 }
866
867
868 LogicalVisitor.processNamespaces();
869
870 for (const SectionRef &Section : Obj.sections()) {
871 Expected SectionNameOrErr = Section.getName();
872 if (!SectionNameOrErr)
873 return SectionNameOrErr.takeError();
874 if (*SectionNameOrErr == ".debug$S")
875 if (Error Err = traverseSymbolSection(*SectionNameOrErr, Section))
876 return Err;
877 }
878
879
880 LogicalVisitor.closeScope();
881
882
883 LogicalVisitor.processFiles();
884
885
886 LogicalVisitor.processLines();
887
888
889 Root->transformScopedName();
891}
892
894 if (Error Err = loadTargetInfo(Pdb))
895 return Err;
896
897 if (.hasPDBTpiStream() ||
.hasPDBDbiStream())
899
900
901
902 if (!ExePath.empty()) {
903 ErrorOr<std::unique_ptr> BuffOrErr =
905 if (BuffOrErr.getError()) {
907 "File '%s' does not exist.", ExePath.c_str());
908 }
909 BinaryBuffer = std::move(BuffOrErr.get());
910
911
914 "Invalid PECOFF executable file.");
915
916 Expected<std::unique_ptr> BinOrErr =
917 createBinary(BinaryBuffer->getMemBufferRef());
920 "Binary object format in '%s' is not supported.",
921 ExePath.c_str());
922 }
923 BinaryExecutable = std::move(*BinOrErr);
924 if (COFFObjectFile *COFFObject =
927 }
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946 LazyRandomTypeCollection &Types = types();
947 LazyRandomTypeCollection &Ids = ids();
948 if (Error Err = traverseTypes(Pdb, Types, Ids))
949 return Err;
950
951
952 LogicalVisitor.processNamespaces();
953
954 LLVM_DEBUG({ W.getOStream() << "Traversing inlined lines\n"; });
955
956 auto VisitInlineeLines = [&](int32_t Modi, const SymbolGroup &SG,
957 DebugInlineeLinesSubsectionRef &Lines) -> Error {
958 return collectInlineeInfo(Lines, &SG);
959 };
960
961 FilterOptions Filters = {};
962 LinePrinter Printer(2, false, nulls(), Filters);
963 const PrintScope HeaderScope(Printer, 2);
965 Input, HeaderScope, VisitInlineeLines))
966 return Err;
967
968
969 LLVM_DEBUG({ W.getOStream() << "Traversing global symbols\n"; });
970 if (Pdb.hasPDBGlobalsStream()) {
971 Expected<GlobalsStream &> GlobalsOrErr = Pdb.getPDBGlobalsStream();
972 if (!GlobalsOrErr)
974 GlobalsStream &Globals = *GlobalsOrErr;
976 Expected<SymbolStream &> ExpectedSyms = Pdb.getPDBSymbolStream();
977 if (ExpectedSyms) {
978
979 SymbolVisitorCallbackPipeline Pipeline;
980 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
981 LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr,
982 LogicalVisitor.getShared());
983
984
985
986 RecordPrefix Prefix(SymbolKind::S_COMPILE3);
989 if (Error Err = Traverser.visitSymbolBegin(Symbol, Offset))
991 else {
992
993
994
995 std::string Name(CompileUnit->getParentScope()->getName());
997
1000 CVSymbolVisitor Visitor(Pipeline);
1001
1002 BinaryStreamRef SymStream =
1003 ExpectedSyms->getSymbolArray().getUnderlyingStream();
1004 for (uint32_t PubSymOff : Table) {
1006 if (Sym) {
1007 if (Error Err = Visitor.visitSymbolRecord(*Sym, PubSymOff))
1009 getFileName());
1010 } else {
1012 }
1013 }
1014 }
1015
1016 LogicalVisitor.closeScope();
1017 } else {
1019 }
1020 }
1021
1022
1023 LLVM_DEBUG({ W.getOStream() << "Traversing symbol groups\n"; });
1024
1025 auto VisitSymbolGroup = [&](uint32_t Modi, const SymbolGroup &SG) -> Error {
1026 Expected ExpectedModS =
1028 if (ExpectedModS) {
1029 ModuleDebugStreamRef &ModS = *ExpectedModS;
1030
1032 W.getOStream() << formatv("Traversing Group: Mod {0:4}\n", Modi);
1033 });
1034
1035 SymbolVisitorCallbackPipeline Pipeline;
1036 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
1037 LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr,
1038 LogicalVisitor.getShared());
1039
1040 Pipeline.addCallbackToPipeline(Deserializer);
1041 Pipeline.addCallbackToPipeline(Traverser);
1042 CVSymbolVisitor Visitor(Pipeline);
1045 Visitor.visitSymbolStream(ModS.getSymbolArray(), SS.Offset))
1047 getFileName());
1048 } else {
1049
1051 }
1052
1054 };
1055
1057 return Err;
1058
1059
1060
1061
1062
1063
1064 LLVM_DEBUG({ W.getOStream() << "Traversing lines\n"; });
1065
1066
1068
1069 auto VisitDebugLines = [this](int32_t Modi, const SymbolGroup &SG,
1070 DebugLinesSubsectionRef &Lines) -> Error {
1071 if (().getPrintLines())
1073
1074 uint16_t Segment = Lines.header()->RelocSegment;
1075 uint32_t Begin = Lines.header()->RelocOffset;
1076 uint32_t Size = Lines.header()->CodeSize;
1077
1079
1080
1081
1082
1083 if (CurrentModule != Modi) {
1084 if (Error Err = processModule())
1085 return Err;
1087 CurrentModule = Modi;
1088 }
1089
1090 for (const LineColumnEntry &Block : Lines)
1091 if (Error Err = createLines(Block.LineNumbers, 0, Segment,
1092 Begin, Size, Block.NameIndex, &SG))
1093 return Err;
1094
1096 };
1097
1099 Input, HeaderScope, VisitDebugLines))
1100 return Err;
1101
1102
1103 LogicalVisitor.closeScope();
1104
1105
1106 LogicalVisitor.processLines();
1107
1108
1109 Root->transformScopedName();
1111}
1112
1113Error LVCodeViewReader::processModule() {
1116
1117 LLVM_DEBUG({ dbgs() << "Processing Scope: " << Scope->getName() << "\n"; });
1118
1119
1120
1121
1122
1123
1124
1127 ScopesWithRanges->clear();
1128 CompileUnit->getRanges(*ScopesWithRanges);
1129 if (!ScopesWithRanges->empty())
1131 ScopesWithRanges->getUpper());
1132 ScopesWithRanges->sort();
1133
1135 return Err;
1136
1137
1139
1141 }
1142
1144}
1145
1146
1147
1148
1149
1150
1151
1152
1155 W.startLine() << "\n";
1156 W.printString("File", getFileName().str());
1157 W.printString("Exe", ExePath);
1159 });
1160
1162 return Err;
1163
1164 LogicalVisitor.setRoot(Root);
1165
1166 if (isObj()) {
1168 return Err;
1169 } else {
1171 return Err;
1172 }
1173
1175}
1176
1177Error LVCodeViewReader::loadTargetInfo(const ObjectFile &Obj) {
1178
1179
1184
1185
1188 if (!Features) {
1191 }
1192 FeaturesValue = *Features;
1193
1195 if (auto OptCPU = Obj.tryGetCPUName())
1196 CPU = *OptCPU;
1197
1199}
1200
1201Error LVCodeViewReader::loadTargetInfo(const PDBFile &Pdb) {
1206
1209
1211}
1212
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
bbsections Prepares for basic block sections
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static Expected< StringRef > getFileName(const DebugStringTableSubsectionRef &Strings, const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID)
dxil pretty DXIL Metadata Pretty Printer
static const T * Find(StringRef S, ArrayRef< T > A)
Find KV in array using binary search.
static unsigned getSectionID(const ObjectFile &O, SectionRef Sec)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
uint64_t getLength() const
Error readInteger(T &Dest)
Read an integer of the specified endianness into Dest and update the stream's offset.
uint64_t bytesRemaining() const
LLVM_ABI Error readFixedString(StringRef &Dest, uint32_t Length)
Read a Length byte string into Dest.
Error readArray(ArrayRef< T > &Array, uint32_t NumElements)
Get a reference to a NumElements element array of objects of type T from the underlying stream as if ...
LLVM_ABI Error skip(uint64_t Amount)
Advance the stream's offset by Amount bytes.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
virtual void printString(StringRef Value)
virtual raw_ostream & startLine()
virtual void printNumber(StringRef Label, char Value)
void printHex(StringRef Label, T Value)
void printSymbolOffset(StringRef Label, StringRef Symbol, T Value)
void push_back(const T &Elt)
std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&...Args)
Emplace a new element for the specified key into the map if the key isn't already in the map.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
const unsigned char * bytes_end() const
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
const unsigned char * bytes_begin() const
Manages the enabling and disabling of subtarget specific features.
LLVM_ABI std::string getString() const
Returns features as a string.
Triple - Helper class for working with autoconf configuration names.
Iterator at(uint32_t Offset) const
given an offset into the array's underlying stream, return an iterator to the record at that offset.
Iterator begin(bool *HadError=nullptr) const
VarStreamArrayIterator< ValueType, Extractor > Iterator
const FileChecksumArray & getArray() const
LLVM_ABI Expected< StringRef > getString(uint32_t Offset) const
uint32_t getSignature() const
Provides amortized O(1) random access to a CodeView type stream.
uint32_t getSignature() const
StringRef getPrecompFilePath() const
uint32_t getTypesCount() const
void addCallbackToPipeline(SymbolVisitorCallbacks &Callbacks)
static Error deserializeAs(CVType &CVT, T &Record)
StringRef getName() const
const GUID & getGuid() const
const LVSymbolTableEntry & getSymbolTableEntry(StringRef Name)
void includeInlineeLines(LVSectionIndex SectionIndex, LVScope *Function)
Error loadGenericTargetInfo(StringRef TheTriple, StringRef TheFeatures, StringRef TheCPU)
LVAddress linearAddress(uint16_t Segment, uint32_t Offset, LVAddress Addendum=0)
void addToSymbolTable(StringRef Name, LVScope *Function, LVSectionIndex SectionIndex=0)
void processLines(LVLines *DebugLines, LVSectionIndex SectionIndex)
void mapVirtualAddress(const object::ObjectFile &Obj)
Error createInstructions()
void getLinkageName(const llvm::object::coff_section *CoffSection, uint32_t RelocOffset, uint32_t Offset, StringRef *RelocSym)
Definition LVCodeViewReader.cpp:113
void print(raw_ostream &OS) const
Definition LVCodeViewReader.cpp:795
static std::string formatRegisterId(RegisterId Register, CPUType CPU)
Definition LVCodeViewReader.cpp:57
std::string getRegisterName(LVSmall Opcode, ArrayRef< uint64_t > Operands) override
Definition LVCodeViewReader.cpp:1213
friend class LVTypeVisitor
LVScope * getScopeForModule(uint32_t Modi)
Error createScopes() override
Definition LVCodeViewReader.cpp:1153
static StringRef getSymbolKindName(SymbolKind Kind)
Definition LVCodeViewReader.cpp:45
friend class LVSymbolVisitor
friend class LVSymbolVisitorDelegate
bool isSystemEntry(LVElement *Element, StringRef Name) const override
Definition LVCodeViewReader.cpp:213
void sortScopes() override
Definition LVCodeViewReader.cpp:793
StringRef getName() const override
void addInlineeInfo(TypeIndex TI, uint32_t LineNumber, StringRef Filename)
void printTypeIndex(StringRef FieldName, TypeIndex TI, uint32_t StreamIdx)
LVAddress getLower() const
LVAddress getUpper() const
LVRange * getSectionRanges(LVSectionIndex SectionIndex)
std::string FileFormatName
codeview::CPUType getCompileUnitCPUType()
std::string createAlternativePath(StringRef From)
LVScopeCompileUnit * CompileUnit
LVSectionIndex DotTextSectionIndex
virtual Error createScopes()
This is a value type class that represents a single section in the list of sections in the object fil...
This is a value type class that represents a single symbol in the list of symbols in the object file.
const GSIHashTable & getGlobalsTable() const
LLVM_ABI BinarySubstreamRef getSymbolsSubstream() const
const codeview::CVSymbolArray & getSymbolArray() const
LLVM_ABI Expected< StringRef > getNameFromChecksums(uint32_t Offset) const
LLVM_ABI void buildHashMap()
LLVM_ABI uint32_t getNumTypeRecords() const
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
@ IMAGE_SYM_DTYPE_FUNCTION
A function that returns a base type.
CVRecord< TypeLeafKind > CVType
VarStreamArray< CVSymbol > CVSymbolArray
CPUType
These values correspond to the CV_CPU_TYPE_e enumeration, and are documented here: https://msdn....
VarStreamArray< CVType > CVTypeArray
CVRecord< SymbolKind > CVSymbol
LLVM_ABI Error visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source=VDS_BytesPresent)
SymbolKind
Duplicate copy of the above enum, but using the official CV names.
LLVM_ABI Expected< CVSymbol > readSymbolFromStream(BinaryStreamRef Stream, uint32_t Offset)
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
static const char Magic[]
content_iterator< BasicSymbolRef > basic_symbol_iterator
LLVM_ABI Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr, bool InitContent=true)
Create a Binary from Source, autodetecting the file type.
LLVM_ABI Expected< ModuleDebugStreamRef > getModuleDebugStream(PDBFile &File, StringRef &ModuleName, uint32_t Index)
Error iterateModuleSubsections(InputFile &File, const PrintScope &HeaderScope, llvm::function_ref< Error(uint32_t, const SymbolGroup &, SubsectionT &)> Callback)
LLVM_ABI Error loadDataForPDB(PDB_ReaderType Type, StringRef Path, std::unique_ptr< IPDBSession > &Session)
Error iterateSymbolGroups(InputFile &Input, const PrintScope &HeaderScope, CallbackT Callback)
detail::packed_endian_specific_integral< uint32_t, llvm::endianness::little, unaligned > ulittle32_t
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
std::string utostr(uint64_t X, bool isNeg=false)
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI raw_ostream & nulls()
This returns a reference to a raw_ostream which simply discards output.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
support::detail::AlignAdapter< T > fmt_align(T &&Item, AlignStyle Where, size_t Amount, char Fill=' ')
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
LLVM_ABI std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
void consumeError(Error Err)
Consume a Error without doing anything.
@ pdb
Windows PDB debug info file.
@ pecoff_executable
PECOFF executable file.
LVSectionIndex SectionIndex