1//===-- LVCodeViewReader.cpp ----------------------------------------------===//
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
7//===----------------------------------------------------------------------===//
9// This implements the LVCodeViewReader class.
11//===----------------------------------------------------------------------===//
43 #define DEBUG_TYPE "CodeViewReader"
47#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
50#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
59#define RETURN_CASE(Enum, X, Ret) \
65#define CV_REGISTERS_ARM
66#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
67#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
69#undef CV_REGISTERS_ARM
76#define CV_REGISTERS_ARM64
77#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
78#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
80#undef CV_REGISTERS_ARM64
87#define CV_REGISTERS_X86
88#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
89#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
91#undef CV_REGISTERS_X86
97 return "formatUnknownEnum(Id)";
106 StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
107 if (!resolveSymbolName(CoffSection, RelocOffset, Symbol))
117 StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
118 if (resolveSymbolName(CoffSection, RelocOffset, Symbol))
123LVCodeViewReader::getFileNameForFileOffset(
uint32_t FileOffset,
134 // The file checksum subsection should precede all references to it.
135 if (!CVFileChecksumTable.
valid() || !CVStringTable.
valid())
139 CVFileChecksumTable.
getArray().
at(FileOffset);
141 // Check if the file checksum table offset is valid.
142 if (Iter == CVFileChecksumTable.
end())
151Error LVCodeViewReader::printFileNameForOffset(StringRef
Label,
153 const SymbolGroup *SG) {
154 Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset, SG);
157 W.printHex(
Label, *NameOrErr, FileOffset);
161void LVCodeViewReader::cacheRelocations() {
162 for (
const SectionRef &Section : getObj().
sections()) {
163 const coff_section *CoffSection = getObj().getCOFFSection(Section);
165 auto &
RM = RelocMap[CoffSection];
168 // Sort relocations by address.
169 llvm::sort(RM, [](RelocationRef L, RelocationRef R) {
170 return L.getOffset() <
R.getOffset();
175// Given a section and an offset into this section the function returns the
176// symbol used for the relocation at the offset.
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();
184 if (RelocationOffset ==
Offset) {
185 SymI = Relocation.getSymbol();
189 if (SymI == getObj().symbol_end())
192 return ErrorSuccess();
195// Given a section and an offset into this section the function returns the
196// name of the symbol used for the relocation at the offset.
197Error LVCodeViewReader::resolveSymbolName(
const coff_section *CoffSection,
200 if (
Error E = resolveSymbol(CoffSection,
Offset, Symbol))
202 Expected<StringRef> NameOrErr =
Symbol.getName();
206 return ErrorSuccess();
209// CodeView and DWARF can have references to compiler generated elements,
210// used for initialization. The MSVC includes in the PDBs, internal compile
211// units, associated with the MS runtime support. We mark them as 'system'
212// and they are printed only if the command line option 'internal=system'.
216 auto Starts = [=](
const char *
Pattern) ->
bool {
219 auto CheckExclude = [&]() ->
bool {
220 if (Starts(
"__") || Starts(
"_PMD") || Starts(
"_PMFN"))
224 if (
Find(
"_CatchableType") ||
Find(
"_TypeDescriptor"))
226 if (
Find(
"Intermediate\\vctools"))
228 if (
Find(
"$initializer$") ||
Find(
"dynamic initializer"))
230 if (
Find(
"`vftable'") ||
Find(
"_GLOBAL__sub"))
234 bool Excluded = CheckExclude();
236 Element->setIsSystem();
241Error LVCodeViewReader::collectInlineeInfo(
250 if (
Error Err = printFileNameForOffset(
"FileID", FileOffset, SG))
254 if (
Lines.hasExtraFiles()) {
258 if (
Error Err = printFileNameForOffset(
"FileID", FID, SG))
264 return NameOrErr.takeError();
271Error LVCodeViewReader::traverseInlineeLines(StringRef Subsection) {
273 DebugInlineeLinesSubsectionRef Lines;
274 if (
Error E = Lines.initialize(SR))
277 return collectInlineeInfo(Lines);
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);
293 LineInfo LI(
Line.Flags);
297 "{0} {1:x-8}\n",
utostr(LI.getStartLine()),
301 // The 'processLines()' function will move each created logical line
302 // to its enclosing logical scope, using the debug ranges information
303 // and they will be released when its scope parent is deleted.
304 LVLineDebug *LineDebug = createLineDebug();
307 LineDebug->setAddress(
Address + Addendum);
309 if (LI.isAlwaysStepInto())
310 LineDebug->setIsAlwaysStepInto();
311 else if (LI.isNeverStepInto())
312 LineDebug->setIsNeverStepInto();
314 LineDebug->setLineNumber(LI.getStartLine());
316 if (LI.isStatement())
317 LineDebug->setIsNewStatement();
319 Expected<StringRef> NameOrErr = getFileNameForFileOffset(NameIndex, SG);
322 LineDebug->setFilename(*NameOrErr);
328Error LVCodeViewReader::initializeFileAndStringTables(
329 BinaryStreamReader &Reader) {
331 (!CVFileChecksumTable.valid() || !CVStringTable.valid())) {
332 // The section consists of a number of subsection in the following format:
333 // |SubSectionType|SubSectionSize|Contents...|
334 uint32_t SubType, SubSectionSize;
347 case DebugSubsectionKind::FileChecksums:
348 if (
Error E = CVFileChecksumTable.initialize(ST))
351 case DebugSubsectionKind::StringTable:
352 if (
Error E = CVStringTable.initialize(ST))
359 uint32_t PaddedSize =
alignTo(SubSectionSize, 4);
360 if (
Error E = Reader.
skip(PaddedSize - SubSectionSize))
370 W.printNumber(
"Age", TS.
getAge());
371 W.printString(
"Name", TS.
getName());
374 SmallString<128> ServerName(TS.
getName());
376 if (BuffOrErr.getError()) {
377 // The server name does not exist. Try in the same directory as the
381 if (BuffOrErr.getError()) {
382 // For the error message, use the original type server name.
384 "File '%s' does not exist.",
388 MemBuffer = std::move(BuffOrErr.get());
390 // Check if the buffer corresponds to a PDB file.
392 "Invalid PDB file.");
398 PdbSession.reset(
static_cast<NativeSession *
>(Session.release()));
399 PDBFile &
Pdb = PdbSession->getPDBFile();
401 // Just because a file with a matching name was found and it was an actual
402 // PDB file doesn't mean it matches. For it to match the InfoStream's GUID
403 // must match the GUID specified in the TypeServer2 record.
404 Expected<InfoStream &> expectedInfo =
Pdb.getPDBInfoStream();
405 if (!expectedInfo || expectedInfo->getGuid() != TS.
getGuid())
408 // The reader needs to switch to a type server, to process the types from
409 // the server. We need to keep the original input source, as reading other
410 // sections will require the input associated with the loaded object file.
411 TypeServer = std::make_shared<InputFile>(&
Pdb);
412 LogicalVisitor.setInput(TypeServer);
414 LazyRandomTypeCollection &Types = types();
415 LazyRandomTypeCollection &Ids = ids();
416 if (
Error Err = traverseTypes(
Pdb, Types, Ids))
432 if (BuffOrErr.getError()) {
433 // The server name does not exist. Try in the directory as the input file.
435 if (BuffOrErr.getError()) {
436 // For the error message, use the original type server name.
438 "File '%s' does not exist.",
442 MemBuffer = std::move(BuffOrErr.get());
444 Expected<std::unique_ptr<Binary>> BinOrErr =
createBinary(*MemBuffer);
447 "Binary object format in '%s' is not supported.",
455 Builder = std::make_unique<AppendingTypeTableBuilder>(BuilderAllocator);
457 // The MSVC precompiled header object file, should contain just a single
458 // ".debug$P" section.
460 for (
const SectionRef &Section : Obj.
sections()) {
461 Expected<StringRef> SectionNameOrErr =
Section.getName();
462 if (!SectionNameOrErr)
464 if (*SectionNameOrErr ==
".debug$P") {
465 Expected<StringRef> DataOrErr =
Section.getContents();
474 ReaderPrecomp = std::make_unique<BinaryStreamReader>(
477 ReaderPrecomp->readArray(CVTypesPrecomp, ReaderPrecomp->getLength()));
479 // Append all the type records up to the LF_ENDPRECOMP marker and
480 // check if the signatures match.
482 ArrayRef<uint8_t> TypeData =
Type.data();
483 if (
Type.kind() == LF_ENDPRECOMP) {
484 EndPrecompRecord EndPrecomp =
cantFail(
490 Builder->insertRecordBytes(TypeData);
492 // Done processing .debug$P, break out of section loop.
497 // Append all the type records, skipping the first record which is the
498 // reference to the precompiled header object information.
500 ArrayRef<uint8_t> TypeData =
Type.
data();
501 if (
Type.kind() != LF_PRECOMP)
502 Builder->insertRecordBytes(TypeData);
505 // Set up a type stream that refers to the added type records.
506 Builder->ForEachRecord(
507 [&](TypeIndex TI,
const CVType &
Type) { TypeArray.push_back(
Type); });
511 ItemStream->setItems(TypeArray);
512 TypeStream.setUnderlyingStream(*ItemStream);
515 std::make_shared<LazyRandomTypeCollection>(TypeStream, TypeArray.size());
517 // Change the original input source to use the collected type records.
518 LogicalVisitor.setInput(PrecompHeader);
520 LazyRandomTypeCollection &Types = types();
521 LazyRandomTypeCollection &Ids = ids();
523 LogicalVisitor.getShared());
527Error LVCodeViewReader::traverseTypeSection(StringRef SectionName,
528 const SectionRef &Section) {
530 ListScope
D(
W,
"CodeViewTypes");
531 W.printNumber(
"Section", SectionName, getObj().
getSectionID(Section));
534 Expected<StringRef> DataOrErr =
Section.getContents();
536 return DataOrErr.takeError();
543 // Get the first type record. It will indicate if this object uses a type
544 // server (/Zi) or a PCH file (/Yu).
550 // The object was compiled with /Zi. It uses types from a type server PDB.
551 if (FirstType->kind() == LF_TYPESERVER2) {
554 return loadTypeServer(TS);
557 // The object was compiled with /Yc or /Yu. It uses types from another
558 // object file with a matching signature.
559 if (FirstType->kind() == LF_PRECOMP) {
562 return loadPrecompiledObject(Precomp, CVTypes);
565 LazyRandomTypeCollection &Types = types();
566 LazyRandomTypeCollection &Ids = ids();
567 Types.reset(*DataOrErr, 100);
569 LogicalVisitor.getShared());
573Error LVCodeViewReader::traverseTypes(PDBFile &
Pdb,
576 // Traverse types (TPI and IPI).
577 auto VisitTypes = [&](LazyRandomTypeCollection &Types,
578 LazyRandomTypeCollection &Ids,
581 LogicalVisitor.getShared());
585 Expected<TpiStream &> StreamTpiOrErr =
Pdb.getPDBTpiStream();
588 TpiStream &StreamTpi = *StreamTpiOrErr;
591 W.getOStream() <<
formatv(
"Showing {0:N} TPI records\n",
597 Expected<TpiStream &> StreamIpiOrErr =
Pdb.getPDBIpiStream();
600 TpiStream &StreamIpi = *StreamIpiOrErr;
603 W.getOStream() <<
formatv(
"Showing {0:N} IPI records\n",
609Error LVCodeViewReader::traverseSymbolsSubsection(StringRef Subsection,
610 const SectionRef &Section,
611 StringRef SectionContents) {
612 ArrayRef<uint8_t> BinaryData(Subsection.
bytes_begin(),
621 LazyRandomTypeCollection &Types = types();
622 LazyRandomTypeCollection &Ids = ids();
623 SymbolVisitorCallbackPipeline Pipeline;
624 SymbolDeserializer Deserializer(&VisitorDelegate,
625 CodeViewContainer::ObjectFile);
626 // As we are processing a COFF format, use TPI as IPI, so the generic code
627 // to process the CodeView format does not contain any additional checks.
629 &VisitorDelegate, LogicalVisitor.getShared());
633 CVSymbolVisitor Visitor(Pipeline);
634 return Visitor.visitSymbolStream(Symbols);
637Error LVCodeViewReader::traverseSymbolSection(StringRef SectionName,
638 const SectionRef &Section) {
640 ListScope
D(
W,
"CodeViewDebugInfo");
641 W.printNumber(
"Section", SectionName, getObj().
getSectionID(Section));
644 Expected<StringRef> SectionOrErr =
Section.getContents();
646 return SectionOrErr.takeError();
647 StringRef SectionContents = *SectionOrErr;
648 StringRef
Data = SectionContents;
651 StringMap<StringRef> FunctionLineTables;
661 if (
Error Err = initializeFileAndStringTables(FSReader))
664 while (!
Data.empty()) {
665 // The section consists of a number of subsection in the following format:
666 // |SubSectionType|SubSectionSize|Contents...|
667 uint32_t SubType, SubSectionSize;
673 // Process the subsection as normal even if the ignore bit is set.
674 SubType &= ~SubsectionIgnoreFlag;
676 // Get the contents of the subsection.
677 if (SubSectionSize >
Data.size())
679 StringRef Contents =
Data.substr(0, SubSectionSize);
681 // Add SubSectionSize to the current offset and align that offset
682 // to find the next subsection.
683 size_t SectionOffset =
Data.data() - SectionContents.
data();
684 size_t NextOffset = SectionOffset + SubSectionSize;
685 NextOffset =
alignTo(NextOffset, 4);
686 if (NextOffset > SectionContents.
size())
691 case DebugSubsectionKind::Symbols:
693 traverseSymbolsSubsection(Contents, Section, SectionContents))
697 case DebugSubsectionKind::InlineeLines:
698 if (
Error Err = traverseInlineeLines(Contents))
702 case DebugSubsectionKind::Lines:
703 // Holds a PC to file:line table. Some data to parse this subsection
704 // is stored in the other subsections, so just check sanity and store
705 // the pointers for deferred processing.
707 // Collect function and ranges only if we need to print logical lines.
708 if (
options().getGeneralCollectRanges()) {
710 if (SubSectionSize < 12) {
711 // There should be at least three words to store two function
712 // relocations and size of the code.
717 if (
Error Err = resolveSymbolName(getObj().getCOFFSection(Section),
718 SectionOffset, SymbolName))
722 LLVM_DEBUG({
W.printString(
"Symbol Name", SymbolName); });
723 if (!FunctionLineTables.
try_emplace(SymbolName, Contents).second) {
724 // Saw debug info for this function already?
732 // Do nothing for unrecognized subsections.
739 // Traverse the line tables now that we've read all the subsections and
740 // know all the required information.
741 for (StringRef SymbolName : SymbolNames) {
743 ListScope S(
W,
"FunctionLineTable");
744 W.printString(
"Symbol Name", SymbolName);
747 BinaryStreamReader Reader(FunctionLineTables[SymbolName],
750 DebugLinesSubsectionRef Lines;
751 if (
Error E = Lines.initialize(Reader))
754 // Find the associated symbol table information.
763 // The given scope represents the function that contains the line numbers.
764 // Collect all generated debug lines associated with the function.
767 // For the given scope, collect all scopes ranges.
769 ScopesWithRanges->
clear();
770 Function->getRanges(*ScopesWithRanges);
771 ScopesWithRanges->
sort();
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,
781 // Include lines from any inlined functions within the current function.
799void LVCodeViewReader::mapRangeAddress(
const ObjectFile &Obj,
807 for (
const SymbolRef &Sym : Object->symbols()) {
808 if (!Section.containsSymbol(Sym))
818 W.
startLine() <<
"Invalid symbol name: " << Symbol.getSectionNumber()
823 SymbolName = *SymNameOrErr;
827 Object->getSection(Symbol.getSectionNumber());
829 W.
startLine() <<
"Invalid section number: " << Symbol.getSectionNumber()
839 // Record the symbol name (linkage) and its loading address.
846 if (
Error Err = loadTargetInfo(Obj))
849 // Initialization required when processing a COFF file:
850 // Cache the symbols relocations.
851 // Create a mapping for virtual addresses.
852 // Get the functions entry points.
856 for (
const SectionRef &Section : Obj.
sections()) {
857 Expected<StringRef> SectionNameOrErr =
Section.getName();
858 if (!SectionNameOrErr)
860 // .debug$T is a standard CodeView type section, while .debug$P is the
861 // same format but used for MSVC precompiled header object files.
862 if (*SectionNameOrErr ==
".debug$T" || *SectionNameOrErr ==
".debug$P")
863 if (
Error Err = traverseTypeSection(*SectionNameOrErr, Section))
867 // Process collected namespaces.
868 LogicalVisitor.processNamespaces();
870 for (
const SectionRef &Section : Obj.
sections()) {
871 Expected<StringRef> SectionNameOrErr =
Section.getName();
872 if (!SectionNameOrErr)
874 if (*SectionNameOrErr ==
".debug$S")
875 if (
Error Err = traverseSymbolSection(*SectionNameOrErr, Section))
879 // Check if we have to close the Compile Unit scope.
880 LogicalVisitor.closeScope();
882 // Traverse the strings recorded and transform them into filenames.
883 LogicalVisitor.processFiles();
885 // Process collected element lines.
886 LogicalVisitor.processLines();
888 // Translate composite names into a single component.
889 Root->transformScopedName();
894 if (
Error Err = loadTargetInfo(
Pdb))
897 if (!
Pdb.hasPDBTpiStream() || !
Pdb.hasPDBDbiStream())
900 // Open the executable associated with the PDB file and get the section
901 // addresses used to calculate linear addresses for CodeView Symbols.
902 if (!ExePath.empty()) {
903 ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
905 if (BuffOrErr.getError()) {
907 "File '%s' does not exist.", ExePath.c_str());
909 BinaryBuffer = std::move(BuffOrErr.get());
911 // Check if the buffer corresponds to a PECOFF executable.
914 "Invalid PECOFF executable file.");
916 Expected<std::unique_ptr<Binary>> BinOrErr =
920 "Binary object format in '%s' is not supported.",
923 BinaryExecutable = std::move(*BinOrErr);
924 if (COFFObjectFile *COFFObject =
929 // In order to generate a full logical view, we have to traverse both
930 // streams TPI and IPI if they are present. The following table gives
931 // the stream where a specified type is located. If the IPI stream is
932 // not present, all the types are located in the TPI stream.
935 // LF_POINTER LF_MODIFIER LF_PROCEDURE LF_MFUNCTION
936 // LF_LABEL LF_ARGLIST LF_FIELDLIST LF_ARRAY
937 // LF_CLASS LF_STRUCTURE LF_INTERFACE LF_UNION
938 // LF_ENUM LF_TYPESERVER2 LF_VFTABLE LF_VTSHAPE
939 // LF_BITFIELD LF_METHODLIST LF_PRECOMP LF_ENDPRECOMP
942 // LF_FUNC_ID LF_MFUNC_ID LF_BUILDINFO
943 // LF_SUBSTR_LIST LF_STRING_ID LF_UDT_SRC_LINE
944 // LF_UDT_MOD_SRC_LINE
946 LazyRandomTypeCollection &Types = types();
947 LazyRandomTypeCollection &Ids = ids();
948 if (
Error Err = traverseTypes(
Pdb, Types, Ids))
951 // Process collected namespaces.
952 LogicalVisitor.processNamespaces();
954 LLVM_DEBUG({
W.getOStream() <<
"Traversing inlined lines\n"; });
956 auto VisitInlineeLines = [&](int32_t Modi,
const SymbolGroup &SG,
957 DebugInlineeLinesSubsectionRef &Lines) ->
Error {
958 return collectInlineeInfo(Lines, &SG);
961 FilterOptions Filters = {};
962 LinePrinter
Printer(
/*Indent=*/2,
false,
nulls(), Filters);
963 const PrintScope HeaderScope(
Printer,
/*IndentLevel=*/2);
965 Input, HeaderScope, VisitInlineeLines))
968 // Traverse global symbols.
969 LLVM_DEBUG({
W.getOStream() <<
"Traversing global symbols\n"; });
970 if (
Pdb.hasPDBGlobalsStream()) {
971 Expected<GlobalsStream &> GlobalsOrErr =
Pdb.getPDBGlobalsStream();
974 GlobalsStream &Globals = *GlobalsOrErr;
976 Expected<SymbolStream &> ExpectedSyms =
Pdb.getPDBSymbolStream();
979 SymbolVisitorCallbackPipeline Pipeline;
980 SymbolDeserializer Deserializer(
nullptr, CodeViewContainer::Pdb);
982 LogicalVisitor.getShared());
984 // As the global symbols do not have an associated Compile Unit, create
985 // one, as the container for all global symbols.
986 RecordPrefix
Prefix(SymbolKind::S_COMPILE3);
989 if (
Error Err = Traverser.visitSymbolBegin(Symbol,
Offset))
992 // The CodeView compile unit containing the global symbols does not
993 // have a name; generate one using its parent name (object filename)
994 // follow by the '_global' string.
1000 CVSymbolVisitor Visitor(Pipeline);
1002 BinaryStreamRef SymStream =
1003 ExpectedSyms->getSymbolArray().getUnderlyingStream();
1004 for (uint32_t PubSymOff : Table) {
1007 if (
Error Err = Visitor.visitSymbolRecord(*Sym, PubSymOff))
1016 LogicalVisitor.closeScope();
1022 // Traverse symbols (DBI).
1023 LLVM_DEBUG({
W.getOStream() <<
"Traversing symbol groups\n"; });
1025 auto VisitSymbolGroup = [&](uint32_t Modi,
const SymbolGroup &SG) ->
Error {
1026 Expected<ModuleDebugStreamRef> ExpectedModS =
1029 ModuleDebugStreamRef &ModS = *ExpectedModS;
1032 W.getOStream() <<
formatv(
"Traversing Group: Mod {0:4}\n", Modi);
1035 SymbolVisitorCallbackPipeline Pipeline;
1036 SymbolDeserializer Deserializer(
nullptr, CodeViewContainer::Pdb);
1038 LogicalVisitor.getShared());
1040 Pipeline.addCallbackToPipeline(Deserializer);
1041 Pipeline.addCallbackToPipeline(Traverser);
1042 CVSymbolVisitor Visitor(Pipeline);
1049 // If the module stream does not exist, it is not an error condition.
1059 // At this stage, the logical view contains all scopes, symbols and types.
1060 // For PDBs we can use the module id, to access its specific compile unit.
1061 // The line record addresses has been already resolved, so we can apply the
1062 // flow as when processing DWARF.
1064 LLVM_DEBUG({
W.getOStream() <<
"Traversing lines\n"; });
1066 // Record all line records for a Compile Unit.
1069 auto VisitDebugLines = [
this](int32_t Modi,
const SymbolGroup &SG,
1070 DebugLinesSubsectionRef &Lines) ->
Error {
1071 if (!
options().getPrintLines())
1074 uint16_t Segment = Lines.header()->RelocSegment;
1075 uint32_t Begin = Lines.header()->RelocOffset;
1076 uint32_t
Size = Lines.header()->CodeSize;
1080 // We have line information for a new module; finish processing the
1081 // collected information for the current module. Once it is done, start
1082 // recording the line information for the new module.
1083 if (CurrentModule != Modi) {
1084 if (
Error Err = processModule())
1087 CurrentModule = Modi;
1090 for (
const LineColumnEntry &
Block : Lines)
1091 if (
Error Err = createLines(
Block.LineNumbers,
/*Addendum=*/0, Segment,
1099 Input, HeaderScope, VisitDebugLines))
1102 // Check if we have to close the Compile Unit scope.
1103 LogicalVisitor.closeScope();
1105 // Process collected element lines.
1106 LogicalVisitor.processLines();
1108 // Translate composite names into a single component.
1109 Root->transformScopedName();
1113Error LVCodeViewReader::processModule() {
1119 // For the given compile unit, collect all scopes ranges.
1120 // For a complete ranges and lines mapping, the logical view support
1121 // needs for the compile unit to have a low and high pc values. We
1122 // can traverse the 'Modules' section and get the information for the
1123 // specific module. Another option, is from all the ranges collected
1124 // to take the first and last values.
1127 ScopesWithRanges->
clear();
1129 if (!ScopesWithRanges->
empty())
1132 ScopesWithRanges->
sort();
1137 // Include lines from any inlined functions within the current function.
1146// In order to create the scopes, the CodeView Reader will:
1147// = Traverse the TPI/IPI stream (Type visitor):
1148// Collect forward references, scoped names, type indexes that will represent
1149// a logical element, strings, line records, linkage names.
1150// = Traverse the symbols section (Symbol visitor):
1151// Create the scopes tree and creates the required logical elements, by
1152// using the collected indexes from the type visitor.
1155 W.startLine() <<
"\n";
1156 W.printString(
"File", getFileName().str());
1157 W.printString(
"Exe", ExePath);
1164 LogicalVisitor.setRoot(
Root);
1178 // Detect the architecture from the object file. We usually don't need OS
1179 // info to lookup a target and create register info.
1185 // Features to be passed to target/subtarget
1192 FeaturesValue = *Features;
1215 // Get Compilation Unit CPU Type.
1217 // For CodeView the register always is in Operands[0];
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)
void print(raw_ostream &OS) const
static std::string formatRegisterId(RegisterId Register, CPUType CPU)
std::string getRegisterName(LVSmall Opcode, ArrayRef< uint64_t > Operands) override
friend class LVTypeVisitor
LVScope * getScopeForModule(uint32_t Modi)
Error createScopes() override
static StringRef getSymbolKindName(SymbolKind Kind)
friend class LVSymbolVisitor
friend class LVSymbolVisitorDelegate
bool isSystemEntry(LVElement *Element, StringRef Name) const override
void sortScopes() override
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()
virtual Expected< SubtargetFeatures > getFeatures() const =0
section_iterator_range sections() const
virtual Triple::ArchType getArch() const =0
virtual std::optional< StringRef > tryGetCPUName() const
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<X> - 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<X> - 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