xref: /freebsd-src/contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewReader.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
106c3fb27SDimitry Andric //===-- LVCodeViewReader.cpp ----------------------------------------------===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric //
906c3fb27SDimitry Andric // This implements the LVCodeViewReader class.
1006c3fb27SDimitry Andric //
1106c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
1206c3fb27SDimitry Andric 
1306c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h"
1406c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
1506c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
1606c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/EnumTables.h"
1706c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
1806c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
1906c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
2006c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
2106c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
2206c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
2306c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVType.h"
2406c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/GenericError.h"
2506c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
2606c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
2706c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
2806c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
2906c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
3006c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
3106c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
3206c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
3306c3fb27SDimitry Andric #include "llvm/Demangle/Demangle.h"
3406c3fb27SDimitry Andric #include "llvm/Object/COFF.h"
3506c3fb27SDimitry Andric #include "llvm/Support/Errc.h"
3606c3fb27SDimitry Andric #include "llvm/Support/Error.h"
3706c3fb27SDimitry Andric #include "llvm/Support/FormatAdapters.h"
3806c3fb27SDimitry Andric #include "llvm/Support/FormatVariadic.h"
3906c3fb27SDimitry Andric #include "llvm/Support/WithColor.h"
4006c3fb27SDimitry Andric 
4106c3fb27SDimitry Andric using namespace llvm;
4206c3fb27SDimitry Andric using namespace llvm::codeview;
4306c3fb27SDimitry Andric using namespace llvm::logicalview;
4406c3fb27SDimitry Andric using namespace llvm::msf;
4506c3fb27SDimitry Andric using namespace llvm::object;
4606c3fb27SDimitry Andric using namespace llvm::pdb;
4706c3fb27SDimitry Andric 
4806c3fb27SDimitry Andric #define DEBUG_TYPE "CodeViewReader"
4906c3fb27SDimitry Andric 
5006c3fb27SDimitry Andric StringRef LVCodeViewReader::getSymbolKindName(SymbolKind Kind) {
5106c3fb27SDimitry Andric   switch (Kind) {
5206c3fb27SDimitry Andric #define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
5306c3fb27SDimitry Andric   case EnumName:                                                               \
5406c3fb27SDimitry Andric     return #EnumName;
5506c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
5606c3fb27SDimitry Andric   default:
5706c3fb27SDimitry Andric     return "UnknownSym";
5806c3fb27SDimitry Andric   }
5906c3fb27SDimitry Andric   llvm_unreachable("Unknown SymbolKind::Kind");
6006c3fb27SDimitry Andric }
6106c3fb27SDimitry Andric 
6206c3fb27SDimitry Andric std::string LVCodeViewReader::formatRegisterId(RegisterId Register,
6306c3fb27SDimitry Andric                                                CPUType CPU) {
6406c3fb27SDimitry Andric #define RETURN_CASE(Enum, X, Ret)                                              \
6506c3fb27SDimitry Andric   case Enum::X:                                                                \
6606c3fb27SDimitry Andric     return Ret;
6706c3fb27SDimitry Andric 
6806c3fb27SDimitry Andric   if (CPU == CPUType::ARMNT) {
6906c3fb27SDimitry Andric     switch (Register) {
7006c3fb27SDimitry Andric #define CV_REGISTERS_ARM
7106c3fb27SDimitry Andric #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
7206c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
7306c3fb27SDimitry Andric #undef CV_REGISTER
7406c3fb27SDimitry Andric #undef CV_REGISTERS_ARM
7506c3fb27SDimitry Andric 
7606c3fb27SDimitry Andric     default:
7706c3fb27SDimitry Andric       break;
7806c3fb27SDimitry Andric     }
7906c3fb27SDimitry Andric   } else if (CPU == CPUType::ARM64) {
8006c3fb27SDimitry Andric     switch (Register) {
8106c3fb27SDimitry Andric #define CV_REGISTERS_ARM64
8206c3fb27SDimitry Andric #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
8306c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
8406c3fb27SDimitry Andric #undef CV_REGISTER
8506c3fb27SDimitry Andric #undef CV_REGISTERS_ARM64
8606c3fb27SDimitry Andric 
8706c3fb27SDimitry Andric     default:
8806c3fb27SDimitry Andric       break;
8906c3fb27SDimitry Andric     }
9006c3fb27SDimitry Andric   } else {
9106c3fb27SDimitry Andric     switch (Register) {
9206c3fb27SDimitry Andric #define CV_REGISTERS_X86
9306c3fb27SDimitry Andric #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
9406c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
9506c3fb27SDimitry Andric #undef CV_REGISTER
9606c3fb27SDimitry Andric #undef CV_REGISTERS_X86
9706c3fb27SDimitry Andric 
9806c3fb27SDimitry Andric     default:
9906c3fb27SDimitry Andric       break;
10006c3fb27SDimitry Andric     }
10106c3fb27SDimitry Andric   }
10206c3fb27SDimitry Andric   return "formatUnknownEnum(Id)";
10306c3fb27SDimitry Andric }
10406c3fb27SDimitry Andric 
10506c3fb27SDimitry Andric void LVCodeViewReader::printRelocatedField(StringRef Label,
10606c3fb27SDimitry Andric                                            const coff_section *CoffSection,
10706c3fb27SDimitry Andric                                            uint32_t RelocOffset,
10806c3fb27SDimitry Andric                                            uint32_t Offset,
10906c3fb27SDimitry Andric                                            StringRef *RelocSym) {
11006c3fb27SDimitry Andric   StringRef SymStorage;
11106c3fb27SDimitry Andric   StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
11206c3fb27SDimitry Andric   if (!resolveSymbolName(CoffSection, RelocOffset, Symbol))
11306c3fb27SDimitry Andric     W.printSymbolOffset(Label, Symbol, Offset);
11406c3fb27SDimitry Andric   else
11506c3fb27SDimitry Andric     W.printHex(Label, RelocOffset);
11606c3fb27SDimitry Andric }
11706c3fb27SDimitry Andric 
11806c3fb27SDimitry Andric void LVCodeViewReader::getLinkageName(const coff_section *CoffSection,
11906c3fb27SDimitry Andric                                       uint32_t RelocOffset, uint32_t Offset,
12006c3fb27SDimitry Andric                                       StringRef *RelocSym) {
12106c3fb27SDimitry Andric   StringRef SymStorage;
12206c3fb27SDimitry Andric   StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
12306c3fb27SDimitry Andric   if (resolveSymbolName(CoffSection, RelocOffset, Symbol))
12406c3fb27SDimitry Andric     Symbol = "";
12506c3fb27SDimitry Andric }
12606c3fb27SDimitry Andric 
12706c3fb27SDimitry Andric Expected<StringRef>
12806c3fb27SDimitry Andric LVCodeViewReader::getFileNameForFileOffset(uint32_t FileOffset,
12906c3fb27SDimitry Andric                                            const SymbolGroup *SG) {
13006c3fb27SDimitry Andric   if (SG) {
13106c3fb27SDimitry Andric     Expected<StringRef> Filename = SG->getNameFromChecksums(FileOffset);
13206c3fb27SDimitry Andric     if (!Filename) {
13306c3fb27SDimitry Andric       consumeError(Filename.takeError());
13406c3fb27SDimitry Andric       return StringRef("");
13506c3fb27SDimitry Andric     }
13606c3fb27SDimitry Andric     return *Filename;
13706c3fb27SDimitry Andric   }
13806c3fb27SDimitry Andric 
13906c3fb27SDimitry Andric   // The file checksum subsection should precede all references to it.
14006c3fb27SDimitry Andric   if (!CVFileChecksumTable.valid() || !CVStringTable.valid())
14106c3fb27SDimitry Andric     return createStringError(object_error::parse_failed, getFileName());
14206c3fb27SDimitry Andric 
14306c3fb27SDimitry Andric   VarStreamArray<FileChecksumEntry>::Iterator Iter =
14406c3fb27SDimitry Andric       CVFileChecksumTable.getArray().at(FileOffset);
14506c3fb27SDimitry Andric 
14606c3fb27SDimitry Andric   // Check if the file checksum table offset is valid.
14706c3fb27SDimitry Andric   if (Iter == CVFileChecksumTable.end())
14806c3fb27SDimitry Andric     return createStringError(object_error::parse_failed, getFileName());
14906c3fb27SDimitry Andric 
15006c3fb27SDimitry Andric   Expected<StringRef> NameOrErr = CVStringTable.getString(Iter->FileNameOffset);
15106c3fb27SDimitry Andric   if (!NameOrErr)
15206c3fb27SDimitry Andric     return createStringError(object_error::parse_failed, getFileName());
15306c3fb27SDimitry Andric   return *NameOrErr;
15406c3fb27SDimitry Andric }
15506c3fb27SDimitry Andric 
15606c3fb27SDimitry Andric Error LVCodeViewReader::printFileNameForOffset(StringRef Label,
15706c3fb27SDimitry Andric                                                uint32_t FileOffset,
15806c3fb27SDimitry Andric                                                const SymbolGroup *SG) {
15906c3fb27SDimitry Andric   Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset, SG);
16006c3fb27SDimitry Andric   if (!NameOrErr)
16106c3fb27SDimitry Andric     return NameOrErr.takeError();
16206c3fb27SDimitry Andric   W.printHex(Label, *NameOrErr, FileOffset);
16306c3fb27SDimitry Andric   return Error::success();
16406c3fb27SDimitry Andric }
16506c3fb27SDimitry Andric 
16606c3fb27SDimitry Andric void LVCodeViewReader::cacheRelocations() {
16706c3fb27SDimitry Andric   for (const SectionRef &Section : getObj().sections()) {
16806c3fb27SDimitry Andric     const coff_section *CoffSection = getObj().getCOFFSection(Section);
16906c3fb27SDimitry Andric 
17006c3fb27SDimitry Andric     for (const RelocationRef &Relocacion : Section.relocations())
17106c3fb27SDimitry Andric       RelocMap[CoffSection].push_back(Relocacion);
17206c3fb27SDimitry Andric 
17306c3fb27SDimitry Andric     // Sort relocations by address.
17406c3fb27SDimitry Andric     llvm::sort(RelocMap[CoffSection], [](RelocationRef L, RelocationRef R) {
17506c3fb27SDimitry Andric       return L.getOffset() < R.getOffset();
17606c3fb27SDimitry Andric     });
17706c3fb27SDimitry Andric   }
17806c3fb27SDimitry Andric }
17906c3fb27SDimitry Andric 
18006c3fb27SDimitry Andric // Given a section and an offset into this section the function returns the
18106c3fb27SDimitry Andric // symbol used for the relocation at the offset.
18206c3fb27SDimitry Andric Error LVCodeViewReader::resolveSymbol(const coff_section *CoffSection,
18306c3fb27SDimitry Andric                                       uint64_t Offset, SymbolRef &Sym) {
18406c3fb27SDimitry Andric   const auto &Relocations = RelocMap[CoffSection];
18506c3fb27SDimitry Andric   basic_symbol_iterator SymI = getObj().symbol_end();
18606c3fb27SDimitry Andric   for (const RelocationRef &Relocation : Relocations) {
18706c3fb27SDimitry Andric     uint64_t RelocationOffset = Relocation.getOffset();
18806c3fb27SDimitry Andric 
18906c3fb27SDimitry Andric     if (RelocationOffset == Offset) {
19006c3fb27SDimitry Andric       SymI = Relocation.getSymbol();
19106c3fb27SDimitry Andric       break;
19206c3fb27SDimitry Andric     }
19306c3fb27SDimitry Andric   }
19406c3fb27SDimitry Andric   if (SymI == getObj().symbol_end())
19506c3fb27SDimitry Andric     return make_error<StringError>("Unknown Symbol", inconvertibleErrorCode());
19606c3fb27SDimitry Andric   Sym = *SymI;
19706c3fb27SDimitry Andric   return ErrorSuccess();
19806c3fb27SDimitry Andric }
19906c3fb27SDimitry Andric 
20006c3fb27SDimitry Andric // Given a section and an offset into this section the function returns the
20106c3fb27SDimitry Andric // name of the symbol used for the relocation at the offset.
20206c3fb27SDimitry Andric Error LVCodeViewReader::resolveSymbolName(const coff_section *CoffSection,
20306c3fb27SDimitry Andric                                           uint64_t Offset, StringRef &Name) {
20406c3fb27SDimitry Andric   SymbolRef Symbol;
20506c3fb27SDimitry Andric   if (Error E = resolveSymbol(CoffSection, Offset, Symbol))
20606c3fb27SDimitry Andric     return E;
20706c3fb27SDimitry Andric   Expected<StringRef> NameOrErr = Symbol.getName();
20806c3fb27SDimitry Andric   if (!NameOrErr)
20906c3fb27SDimitry Andric     return NameOrErr.takeError();
21006c3fb27SDimitry Andric   Name = *NameOrErr;
21106c3fb27SDimitry Andric   return ErrorSuccess();
21206c3fb27SDimitry Andric }
21306c3fb27SDimitry Andric 
21406c3fb27SDimitry Andric // CodeView and DWARF can have references to compiler generated elements,
21506c3fb27SDimitry Andric // used for initialization. The MSVC includes in the PDBs, internal compile
21606c3fb27SDimitry Andric // units, associated with the MS runtime support. We mark them as 'system'
21706c3fb27SDimitry Andric // and they are printed only if the command line option 'internal=system'.
21806c3fb27SDimitry Andric bool LVCodeViewReader::isSystemEntry(LVElement *Element, StringRef Name) const {
21906c3fb27SDimitry Andric   Name = Name.empty() ? Element->getName() : Name;
22006c3fb27SDimitry Andric   auto Find = [=](const char *String) -> bool {
22106c3fb27SDimitry Andric     return StringRef::npos != Name.find(String);
22206c3fb27SDimitry Andric   };
22306c3fb27SDimitry Andric   auto Starts = [=](const char *Pattern) -> bool {
224*5f757f3fSDimitry Andric     return Name.starts_with(Pattern);
22506c3fb27SDimitry Andric   };
22606c3fb27SDimitry Andric   auto CheckExclude = [&]() -> bool {
22706c3fb27SDimitry Andric     if (Starts("__") || Starts("_PMD") || Starts("_PMFN"))
22806c3fb27SDimitry Andric       return true;
22906c3fb27SDimitry Andric     if (Find("_s__"))
23006c3fb27SDimitry Andric       return true;
23106c3fb27SDimitry Andric     if (Find("_CatchableType") || Find("_TypeDescriptor"))
23206c3fb27SDimitry Andric       return true;
23306c3fb27SDimitry Andric     if (Find("Intermediate\\vctools"))
23406c3fb27SDimitry Andric       return true;
23506c3fb27SDimitry Andric     if (Find("$initializer$") || Find("dynamic initializer"))
23606c3fb27SDimitry Andric       return true;
23706c3fb27SDimitry Andric     if (Find("`vftable'") || Find("_GLOBAL__sub"))
23806c3fb27SDimitry Andric       return true;
23906c3fb27SDimitry Andric     return false;
24006c3fb27SDimitry Andric   };
24106c3fb27SDimitry Andric   bool Excluded = CheckExclude();
24206c3fb27SDimitry Andric   if (Excluded)
24306c3fb27SDimitry Andric     Element->setIsSystem();
24406c3fb27SDimitry Andric 
24506c3fb27SDimitry Andric   return Excluded;
24606c3fb27SDimitry Andric }
24706c3fb27SDimitry Andric 
24806c3fb27SDimitry Andric Error LVCodeViewReader::collectInlineeInfo(
24906c3fb27SDimitry Andric     DebugInlineeLinesSubsectionRef &Lines, const llvm::pdb::SymbolGroup *SG) {
25006c3fb27SDimitry Andric   for (const InlineeSourceLine &Line : Lines) {
25106c3fb27SDimitry Andric     TypeIndex TIInlinee = Line.Header->Inlinee;
25206c3fb27SDimitry Andric     uint32_t LineNumber = Line.Header->SourceLineNum;
25306c3fb27SDimitry Andric     uint32_t FileOffset = Line.Header->FileID;
25406c3fb27SDimitry Andric     LLVM_DEBUG({
25506c3fb27SDimitry Andric       DictScope S(W, "InlineeSourceLine");
25606c3fb27SDimitry Andric       LogicalVisitor.printTypeIndex("Inlinee", TIInlinee, StreamTPI);
25706c3fb27SDimitry Andric       if (Error Err = printFileNameForOffset("FileID", FileOffset, SG))
25806c3fb27SDimitry Andric         return Err;
25906c3fb27SDimitry Andric       W.printNumber("SourceLineNum", LineNumber);
26006c3fb27SDimitry Andric 
26106c3fb27SDimitry Andric       if (Lines.hasExtraFiles()) {
26206c3fb27SDimitry Andric         W.printNumber("ExtraFileCount", Line.ExtraFiles.size());
26306c3fb27SDimitry Andric         ListScope ExtraFiles(W, "ExtraFiles");
26406c3fb27SDimitry Andric         for (const ulittle32_t &FID : Line.ExtraFiles)
26506c3fb27SDimitry Andric           if (Error Err = printFileNameForOffset("FileID", FID, SG))
26606c3fb27SDimitry Andric             return Err;
26706c3fb27SDimitry Andric       }
26806c3fb27SDimitry Andric     });
26906c3fb27SDimitry Andric     Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset, SG);
27006c3fb27SDimitry Andric     if (!NameOrErr)
27106c3fb27SDimitry Andric       return NameOrErr.takeError();
27206c3fb27SDimitry Andric     LogicalVisitor.addInlineeInfo(TIInlinee, LineNumber, *NameOrErr);
27306c3fb27SDimitry Andric   }
27406c3fb27SDimitry Andric 
27506c3fb27SDimitry Andric   return Error::success();
27606c3fb27SDimitry Andric }
27706c3fb27SDimitry Andric 
27806c3fb27SDimitry Andric Error LVCodeViewReader::traverseInlineeLines(StringRef Subsection) {
279*5f757f3fSDimitry Andric   BinaryStreamReader SR(Subsection, llvm::endianness::little);
28006c3fb27SDimitry Andric   DebugInlineeLinesSubsectionRef Lines;
28106c3fb27SDimitry Andric   if (Error E = Lines.initialize(SR))
28206c3fb27SDimitry Andric     return createStringError(errorToErrorCode(std::move(E)), getFileName());
28306c3fb27SDimitry Andric 
28406c3fb27SDimitry Andric   return collectInlineeInfo(Lines);
28506c3fb27SDimitry Andric }
28606c3fb27SDimitry Andric 
28706c3fb27SDimitry Andric Error LVCodeViewReader::createLines(
28806c3fb27SDimitry Andric     const FixedStreamArray<LineNumberEntry> &LineNumbers, LVAddress Addendum,
28906c3fb27SDimitry Andric     uint32_t Segment, uint32_t Begin, uint32_t Size, uint32_t NameIndex,
29006c3fb27SDimitry Andric     const SymbolGroup *SG) {
29106c3fb27SDimitry Andric   LLVM_DEBUG({
29206c3fb27SDimitry Andric     uint32_t End = Begin + Size;
29306c3fb27SDimitry Andric     W.getOStream() << formatv("{0:x-4}:{1:x-8}-{2:x-8}\n", Segment, Begin, End);
29406c3fb27SDimitry Andric   });
29506c3fb27SDimitry Andric 
29606c3fb27SDimitry Andric   for (const LineNumberEntry &Line : LineNumbers) {
29706c3fb27SDimitry Andric     if (Line.Offset >= Size)
29806c3fb27SDimitry Andric       return createStringError(object_error::parse_failed, getFileName());
29906c3fb27SDimitry Andric 
30006c3fb27SDimitry Andric     LineInfo LI(Line.Flags);
30106c3fb27SDimitry Andric 
30206c3fb27SDimitry Andric     LLVM_DEBUG({
30306c3fb27SDimitry Andric       W.getOStream() << formatv(
30406c3fb27SDimitry Andric           "{0} {1:x-8}\n", utostr(LI.getStartLine()),
30506c3fb27SDimitry Andric           fmt_align(Begin + Line.Offset, AlignStyle::Right, 8, '0'));
30606c3fb27SDimitry Andric     });
30706c3fb27SDimitry Andric 
30806c3fb27SDimitry Andric     // The 'processLines()' function will move each created logical line
30906c3fb27SDimitry Andric     // to its enclosing logical scope, using the debug ranges information
31006c3fb27SDimitry Andric     // and they will be released when its scope parent is deleted.
31106c3fb27SDimitry Andric     LVLineDebug *LineDebug = createLineDebug();
31206c3fb27SDimitry Andric     CULines.push_back(LineDebug);
31306c3fb27SDimitry Andric     LVAddress Address = linearAddress(Segment, Begin + Line.Offset);
31406c3fb27SDimitry Andric     LineDebug->setAddress(Address + Addendum);
31506c3fb27SDimitry Andric 
31606c3fb27SDimitry Andric     if (LI.isAlwaysStepInto())
31706c3fb27SDimitry Andric       LineDebug->setIsAlwaysStepInto();
31806c3fb27SDimitry Andric     else if (LI.isNeverStepInto())
31906c3fb27SDimitry Andric       LineDebug->setIsNeverStepInto();
32006c3fb27SDimitry Andric     else
32106c3fb27SDimitry Andric       LineDebug->setLineNumber(LI.getStartLine());
32206c3fb27SDimitry Andric 
32306c3fb27SDimitry Andric     if (LI.isStatement())
32406c3fb27SDimitry Andric       LineDebug->setIsNewStatement();
32506c3fb27SDimitry Andric 
32606c3fb27SDimitry Andric     Expected<StringRef> NameOrErr = getFileNameForFileOffset(NameIndex, SG);
32706c3fb27SDimitry Andric     if (!NameOrErr)
32806c3fb27SDimitry Andric       return NameOrErr.takeError();
32906c3fb27SDimitry Andric     LineDebug->setFilename(*NameOrErr);
33006c3fb27SDimitry Andric   }
33106c3fb27SDimitry Andric 
33206c3fb27SDimitry Andric   return Error::success();
33306c3fb27SDimitry Andric }
33406c3fb27SDimitry Andric 
33506c3fb27SDimitry Andric Error LVCodeViewReader::initializeFileAndStringTables(
33606c3fb27SDimitry Andric     BinaryStreamReader &Reader) {
33706c3fb27SDimitry Andric   while (Reader.bytesRemaining() > 0 &&
33806c3fb27SDimitry Andric          (!CVFileChecksumTable.valid() || !CVStringTable.valid())) {
33906c3fb27SDimitry Andric     // The section consists of a number of subsection in the following format:
34006c3fb27SDimitry Andric     // |SubSectionType|SubSectionSize|Contents...|
34106c3fb27SDimitry Andric     uint32_t SubType, SubSectionSize;
34206c3fb27SDimitry Andric 
34306c3fb27SDimitry Andric     if (Error E = Reader.readInteger(SubType))
34406c3fb27SDimitry Andric       return createStringError(errorToErrorCode(std::move(E)), getFileName());
34506c3fb27SDimitry Andric     if (Error E = Reader.readInteger(SubSectionSize))
34606c3fb27SDimitry Andric       return createStringError(errorToErrorCode(std::move(E)), getFileName());
34706c3fb27SDimitry Andric 
34806c3fb27SDimitry Andric     StringRef Contents;
34906c3fb27SDimitry Andric     if (Error E = Reader.readFixedString(Contents, SubSectionSize))
35006c3fb27SDimitry Andric       return createStringError(errorToErrorCode(std::move(E)), getFileName());
35106c3fb27SDimitry Andric 
352*5f757f3fSDimitry Andric     BinaryStreamRef ST(Contents, llvm::endianness::little);
35306c3fb27SDimitry Andric     switch (DebugSubsectionKind(SubType)) {
35406c3fb27SDimitry Andric     case DebugSubsectionKind::FileChecksums:
35506c3fb27SDimitry Andric       if (Error E = CVFileChecksumTable.initialize(ST))
35606c3fb27SDimitry Andric         return createStringError(errorToErrorCode(std::move(E)), getFileName());
35706c3fb27SDimitry Andric       break;
35806c3fb27SDimitry Andric     case DebugSubsectionKind::StringTable:
35906c3fb27SDimitry Andric       if (Error E = CVStringTable.initialize(ST))
36006c3fb27SDimitry Andric         return createStringError(errorToErrorCode(std::move(E)), getFileName());
36106c3fb27SDimitry Andric       break;
36206c3fb27SDimitry Andric     default:
36306c3fb27SDimitry Andric       break;
36406c3fb27SDimitry Andric     }
36506c3fb27SDimitry Andric 
36606c3fb27SDimitry Andric     uint32_t PaddedSize = alignTo(SubSectionSize, 4);
36706c3fb27SDimitry Andric     if (Error E = Reader.skip(PaddedSize - SubSectionSize))
36806c3fb27SDimitry Andric       return createStringError(errorToErrorCode(std::move(E)), getFileName());
36906c3fb27SDimitry Andric   }
37006c3fb27SDimitry Andric 
37106c3fb27SDimitry Andric   return Error::success();
37206c3fb27SDimitry Andric }
37306c3fb27SDimitry Andric 
37406c3fb27SDimitry Andric Error LVCodeViewReader::loadTypeServer(TypeServer2Record &TS) {
37506c3fb27SDimitry Andric   LLVM_DEBUG({
37606c3fb27SDimitry Andric     W.printString("Guid", formatv("{0}", TS.getGuid()).str());
37706c3fb27SDimitry Andric     W.printNumber("Age", TS.getAge());
37806c3fb27SDimitry Andric     W.printString("Name", TS.getName());
37906c3fb27SDimitry Andric   });
38006c3fb27SDimitry Andric 
38106c3fb27SDimitry Andric   SmallString<128> ServerName(TS.getName());
38206c3fb27SDimitry Andric   BuffOrErr = MemoryBuffer::getFile(ServerName);
38306c3fb27SDimitry Andric   if (BuffOrErr.getError()) {
38406c3fb27SDimitry Andric     // The server name does not exist. Try in the same directory as the
38506c3fb27SDimitry Andric     // input file.
38606c3fb27SDimitry Andric     ServerName = createAlternativePath(ServerName);
38706c3fb27SDimitry Andric     BuffOrErr = MemoryBuffer::getFile(ServerName);
38806c3fb27SDimitry Andric     if (BuffOrErr.getError()) {
38906c3fb27SDimitry Andric       // For the error message, use the original type server name.
39006c3fb27SDimitry Andric       return createStringError(errc::bad_file_descriptor,
39106c3fb27SDimitry Andric                                "File '%s' does not exist.",
39206c3fb27SDimitry Andric                                TS.getName().str().c_str());
39306c3fb27SDimitry Andric     }
39406c3fb27SDimitry Andric   }
39506c3fb27SDimitry Andric   MemBuffer = std::move(BuffOrErr.get());
39606c3fb27SDimitry Andric 
39706c3fb27SDimitry Andric   // Check if the buffer corresponds to a PDB file.
39806c3fb27SDimitry Andric   assert(identify_magic((*MemBuffer).getBuffer()) == file_magic::pdb &&
39906c3fb27SDimitry Andric          "Invalid PDB file.");
40006c3fb27SDimitry Andric 
40106c3fb27SDimitry Andric   if (Error Err = loadDataForPDB(PDB_ReaderType::Native, ServerName, Session))
40206c3fb27SDimitry Andric     return createStringError(errorToErrorCode(std::move(Err)), "%s",
40306c3fb27SDimitry Andric                              ServerName.c_str());
40406c3fb27SDimitry Andric 
40506c3fb27SDimitry Andric   PdbSession.reset(static_cast<NativeSession *>(Session.release()));
40606c3fb27SDimitry Andric   PDBFile &Pdb = PdbSession->getPDBFile();
40706c3fb27SDimitry Andric 
40806c3fb27SDimitry Andric   // Just because a file with a matching name was found and it was an actual
40906c3fb27SDimitry Andric   // PDB file doesn't mean it matches. For it to match the InfoStream's GUID
41006c3fb27SDimitry Andric   // must match the GUID specified in the TypeServer2 record.
41106c3fb27SDimitry Andric   Expected<InfoStream &> expectedInfo = Pdb.getPDBInfoStream();
41206c3fb27SDimitry Andric   if (!expectedInfo || expectedInfo->getGuid() != TS.getGuid())
41306c3fb27SDimitry Andric     return createStringError(errc::invalid_argument, "signature_out_of_date");
41406c3fb27SDimitry Andric 
41506c3fb27SDimitry Andric   // The reader needs to switch to a type server, to process the types from
41606c3fb27SDimitry Andric   // the server. We need to keep the original input source, as reading other
41706c3fb27SDimitry Andric   // sections will require the input associated with the loaded object file.
41806c3fb27SDimitry Andric   TypeServer = std::make_shared<InputFile>(&Pdb);
41906c3fb27SDimitry Andric   LogicalVisitor.setInput(TypeServer);
42006c3fb27SDimitry Andric 
42106c3fb27SDimitry Andric   LazyRandomTypeCollection &Types = types();
42206c3fb27SDimitry Andric   LazyRandomTypeCollection &Ids = ids();
42306c3fb27SDimitry Andric   if (Error Err = traverseTypes(Pdb, Types, Ids))
42406c3fb27SDimitry Andric     return Err;
42506c3fb27SDimitry Andric 
42606c3fb27SDimitry Andric   return Error::success();
42706c3fb27SDimitry Andric }
42806c3fb27SDimitry Andric 
42906c3fb27SDimitry Andric Error LVCodeViewReader::loadPrecompiledObject(PrecompRecord &Precomp,
43006c3fb27SDimitry Andric                                               CVTypeArray &CVTypesObj) {
43106c3fb27SDimitry Andric   LLVM_DEBUG({
43206c3fb27SDimitry Andric     W.printHex("Count", Precomp.getTypesCount());
43306c3fb27SDimitry Andric     W.printHex("Signature", Precomp.getSignature());
43406c3fb27SDimitry Andric     W.printString("PrecompFile", Precomp.getPrecompFilePath());
43506c3fb27SDimitry Andric   });
43606c3fb27SDimitry Andric 
43706c3fb27SDimitry Andric   SmallString<128> ServerName(Precomp.getPrecompFilePath());
43806c3fb27SDimitry Andric   BuffOrErr = MemoryBuffer::getFile(ServerName);
43906c3fb27SDimitry Andric   if (BuffOrErr.getError()) {
44006c3fb27SDimitry Andric     // The server name does not exist. Try in the directory as the input file.
44106c3fb27SDimitry Andric     ServerName = createAlternativePath(ServerName);
44206c3fb27SDimitry Andric     if (BuffOrErr.getError()) {
44306c3fb27SDimitry Andric       // For the error message, use the original type server name.
44406c3fb27SDimitry Andric       return createStringError(errc::bad_file_descriptor,
44506c3fb27SDimitry Andric                                "File '%s' does not exist.",
44606c3fb27SDimitry Andric                                Precomp.getPrecompFilePath().str().c_str());
44706c3fb27SDimitry Andric     }
44806c3fb27SDimitry Andric   }
44906c3fb27SDimitry Andric   MemBuffer = std::move(BuffOrErr.get());
45006c3fb27SDimitry Andric 
45106c3fb27SDimitry Andric   Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(*MemBuffer);
45206c3fb27SDimitry Andric   if (errorToErrorCode(BinOrErr.takeError()))
45306c3fb27SDimitry Andric     return createStringError(errc::not_supported,
45406c3fb27SDimitry Andric                              "Binary object format in '%s' is not supported.",
45506c3fb27SDimitry Andric                              ServerName.c_str());
45606c3fb27SDimitry Andric 
45706c3fb27SDimitry Andric   Binary &BinaryObj = *BinOrErr.get();
45806c3fb27SDimitry Andric   if (!BinaryObj.isCOFF())
45906c3fb27SDimitry Andric     return createStringError(errc::not_supported, "'%s' is not a COFF object.",
46006c3fb27SDimitry Andric                              ServerName.c_str());
46106c3fb27SDimitry Andric 
46206c3fb27SDimitry Andric   Builder = std::make_unique<AppendingTypeTableBuilder>(BuilderAllocator);
46306c3fb27SDimitry Andric 
46406c3fb27SDimitry Andric   // The MSVC precompiled header object file, should contain just a single
46506c3fb27SDimitry Andric   // ".debug$P" section.
46606c3fb27SDimitry Andric   COFFObjectFile &Obj = *cast<COFFObjectFile>(&BinaryObj);
46706c3fb27SDimitry Andric   for (const SectionRef &Section : Obj.sections()) {
46806c3fb27SDimitry Andric     Expected<StringRef> SectionNameOrErr = Section.getName();
46906c3fb27SDimitry Andric     if (!SectionNameOrErr)
47006c3fb27SDimitry Andric       return SectionNameOrErr.takeError();
47106c3fb27SDimitry Andric     if (*SectionNameOrErr == ".debug$P") {
47206c3fb27SDimitry Andric       Expected<StringRef> DataOrErr = Section.getContents();
47306c3fb27SDimitry Andric       if (!DataOrErr)
47406c3fb27SDimitry Andric         return DataOrErr.takeError();
47506c3fb27SDimitry Andric       uint32_t Magic;
47606c3fb27SDimitry Andric       if (Error Err = consume(*DataOrErr, Magic))
47706c3fb27SDimitry Andric         return Err;
47806c3fb27SDimitry Andric       if (Magic != COFF::DEBUG_SECTION_MAGIC)
47906c3fb27SDimitry Andric         return errorCodeToError(object_error::parse_failed);
48006c3fb27SDimitry Andric 
481*5f757f3fSDimitry Andric       ReaderPrecomp = std::make_unique<BinaryStreamReader>(
482*5f757f3fSDimitry Andric           *DataOrErr, llvm::endianness::little);
48306c3fb27SDimitry Andric       cantFail(
48406c3fb27SDimitry Andric           ReaderPrecomp->readArray(CVTypesPrecomp, ReaderPrecomp->getLength()));
48506c3fb27SDimitry Andric 
48606c3fb27SDimitry Andric       // Append all the type records up to the LF_ENDPRECOMP marker and
48706c3fb27SDimitry Andric       // check if the signatures match.
48806c3fb27SDimitry Andric       for (const CVType &Type : CVTypesPrecomp) {
48906c3fb27SDimitry Andric         ArrayRef<uint8_t> TypeData = Type.data();
49006c3fb27SDimitry Andric         if (Type.kind() == LF_ENDPRECOMP) {
49106c3fb27SDimitry Andric           EndPrecompRecord EndPrecomp = cantFail(
49206c3fb27SDimitry Andric               TypeDeserializer::deserializeAs<EndPrecompRecord>(TypeData));
49306c3fb27SDimitry Andric           if (Precomp.getSignature() != EndPrecomp.getSignature())
49406c3fb27SDimitry Andric             return createStringError(errc::invalid_argument, "no matching pch");
49506c3fb27SDimitry Andric           break;
49606c3fb27SDimitry Andric         }
49706c3fb27SDimitry Andric         Builder->insertRecordBytes(TypeData);
49806c3fb27SDimitry Andric       }
49906c3fb27SDimitry Andric       // Done processing .debug$P, break out of section loop.
50006c3fb27SDimitry Andric       break;
50106c3fb27SDimitry Andric     }
50206c3fb27SDimitry Andric   }
50306c3fb27SDimitry Andric 
50406c3fb27SDimitry Andric   // Append all the type records, skipping the first record which is the
50506c3fb27SDimitry Andric   // reference to the precompiled header object information.
50606c3fb27SDimitry Andric   for (const CVType &Type : CVTypesObj) {
50706c3fb27SDimitry Andric     ArrayRef<uint8_t> TypeData = Type.data();
50806c3fb27SDimitry Andric     if (Type.kind() != LF_PRECOMP)
50906c3fb27SDimitry Andric       Builder->insertRecordBytes(TypeData);
51006c3fb27SDimitry Andric   }
51106c3fb27SDimitry Andric 
51206c3fb27SDimitry Andric   // Set up a type stream that refers to the added type records.
51306c3fb27SDimitry Andric   Builder->ForEachRecord(
51406c3fb27SDimitry Andric       [&](TypeIndex TI, const CVType &Type) { TypeArray.push_back(Type); });
51506c3fb27SDimitry Andric 
51606c3fb27SDimitry Andric   ItemStream =
517*5f757f3fSDimitry Andric       std::make_unique<BinaryItemStream<CVType>>(llvm::endianness::little);
51806c3fb27SDimitry Andric   ItemStream->setItems(TypeArray);
51906c3fb27SDimitry Andric   TypeStream.setUnderlyingStream(*ItemStream);
52006c3fb27SDimitry Andric 
52106c3fb27SDimitry Andric   PrecompHeader =
52206c3fb27SDimitry Andric       std::make_shared<LazyRandomTypeCollection>(TypeStream, TypeArray.size());
52306c3fb27SDimitry Andric 
52406c3fb27SDimitry Andric   // Change the original input source to use the collected type records.
52506c3fb27SDimitry Andric   LogicalVisitor.setInput(PrecompHeader);
52606c3fb27SDimitry Andric 
52706c3fb27SDimitry Andric   LazyRandomTypeCollection &Types = types();
52806c3fb27SDimitry Andric   LazyRandomTypeCollection &Ids = ids();
52906c3fb27SDimitry Andric   LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamTPI,
53006c3fb27SDimitry Andric                     LogicalVisitor.getShared());
53106c3fb27SDimitry Andric   return visitTypeStream(Types, TDV);
53206c3fb27SDimitry Andric }
53306c3fb27SDimitry Andric 
53406c3fb27SDimitry Andric Error LVCodeViewReader::traverseTypeSection(StringRef SectionName,
53506c3fb27SDimitry Andric                                             const SectionRef &Section) {
53606c3fb27SDimitry Andric   LLVM_DEBUG({
53706c3fb27SDimitry Andric     ListScope D(W, "CodeViewTypes");
53806c3fb27SDimitry Andric     W.printNumber("Section", SectionName, getObj().getSectionID(Section));
53906c3fb27SDimitry Andric   });
54006c3fb27SDimitry Andric 
54106c3fb27SDimitry Andric   Expected<StringRef> DataOrErr = Section.getContents();
54206c3fb27SDimitry Andric   if (!DataOrErr)
54306c3fb27SDimitry Andric     return DataOrErr.takeError();
54406c3fb27SDimitry Andric   uint32_t Magic;
54506c3fb27SDimitry Andric   if (Error Err = consume(*DataOrErr, Magic))
54606c3fb27SDimitry Andric     return Err;
54706c3fb27SDimitry Andric   if (Magic != COFF::DEBUG_SECTION_MAGIC)
54806c3fb27SDimitry Andric     return errorCodeToError(object_error::parse_failed);
54906c3fb27SDimitry Andric 
55006c3fb27SDimitry Andric   // Get the first type record. It will indicate if this object uses a type
55106c3fb27SDimitry Andric   // server (/Zi) or a PCH file (/Yu).
55206c3fb27SDimitry Andric   CVTypeArray CVTypes;
553*5f757f3fSDimitry Andric   BinaryStreamReader Reader(*DataOrErr, llvm::endianness::little);
55406c3fb27SDimitry Andric   cantFail(Reader.readArray(CVTypes, Reader.getLength()));
55506c3fb27SDimitry Andric   CVTypeArray::Iterator FirstType = CVTypes.begin();
55606c3fb27SDimitry Andric 
55706c3fb27SDimitry Andric   // The object was compiled with /Zi. It uses types from a type server PDB.
55806c3fb27SDimitry Andric   if (FirstType->kind() == LF_TYPESERVER2) {
55906c3fb27SDimitry Andric     TypeServer2Record TS = cantFail(
56006c3fb27SDimitry Andric         TypeDeserializer::deserializeAs<TypeServer2Record>(FirstType->data()));
56106c3fb27SDimitry Andric     return loadTypeServer(TS);
56206c3fb27SDimitry Andric   }
56306c3fb27SDimitry Andric 
56406c3fb27SDimitry Andric   // The object was compiled with /Yc or /Yu. It uses types from another
56506c3fb27SDimitry Andric   // object file with a matching signature.
56606c3fb27SDimitry Andric   if (FirstType->kind() == LF_PRECOMP) {
56706c3fb27SDimitry Andric     PrecompRecord Precomp = cantFail(
56806c3fb27SDimitry Andric         TypeDeserializer::deserializeAs<PrecompRecord>(FirstType->data()));
56906c3fb27SDimitry Andric     return loadPrecompiledObject(Precomp, CVTypes);
57006c3fb27SDimitry Andric   }
57106c3fb27SDimitry Andric 
57206c3fb27SDimitry Andric   LazyRandomTypeCollection &Types = types();
57306c3fb27SDimitry Andric   LazyRandomTypeCollection &Ids = ids();
57406c3fb27SDimitry Andric   Types.reset(*DataOrErr, 100);
57506c3fb27SDimitry Andric   LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamTPI,
57606c3fb27SDimitry Andric                     LogicalVisitor.getShared());
57706c3fb27SDimitry Andric   return visitTypeStream(Types, TDV);
57806c3fb27SDimitry Andric }
57906c3fb27SDimitry Andric 
58006c3fb27SDimitry Andric Error LVCodeViewReader::traverseTypes(PDBFile &Pdb,
58106c3fb27SDimitry Andric                                       LazyRandomTypeCollection &Types,
58206c3fb27SDimitry Andric                                       LazyRandomTypeCollection &Ids) {
58306c3fb27SDimitry Andric   // Traverse types (TPI and IPI).
58406c3fb27SDimitry Andric   auto VisitTypes = [&](LazyRandomTypeCollection &Types,
58506c3fb27SDimitry Andric                         LazyRandomTypeCollection &Ids,
58606c3fb27SDimitry Andric                         SpecialStream StreamIdx) -> Error {
58706c3fb27SDimitry Andric     LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamIdx,
58806c3fb27SDimitry Andric                       LogicalVisitor.getShared());
58906c3fb27SDimitry Andric     return visitTypeStream(Types, TDV);
59006c3fb27SDimitry Andric   };
59106c3fb27SDimitry Andric 
59206c3fb27SDimitry Andric   Expected<TpiStream &> StreamTpiOrErr = Pdb.getPDBTpiStream();
59306c3fb27SDimitry Andric   if (!StreamTpiOrErr)
59406c3fb27SDimitry Andric     return StreamTpiOrErr.takeError();
59506c3fb27SDimitry Andric   TpiStream &StreamTpi = *StreamTpiOrErr;
59606c3fb27SDimitry Andric   StreamTpi.buildHashMap();
59706c3fb27SDimitry Andric   LLVM_DEBUG({
59806c3fb27SDimitry Andric     W.getOStream() << formatv("Showing {0:N} TPI records\n",
59906c3fb27SDimitry Andric                               StreamTpi.getNumTypeRecords());
60006c3fb27SDimitry Andric   });
60106c3fb27SDimitry Andric   if (Error Err = VisitTypes(Types, Ids, StreamTPI))
60206c3fb27SDimitry Andric     return Err;
60306c3fb27SDimitry Andric 
60406c3fb27SDimitry Andric   Expected<TpiStream &> StreamIpiOrErr = Pdb.getPDBIpiStream();
60506c3fb27SDimitry Andric   if (!StreamIpiOrErr)
60606c3fb27SDimitry Andric     return StreamIpiOrErr.takeError();
60706c3fb27SDimitry Andric   TpiStream &StreamIpi = *StreamIpiOrErr;
60806c3fb27SDimitry Andric   StreamIpi.buildHashMap();
60906c3fb27SDimitry Andric   LLVM_DEBUG({
61006c3fb27SDimitry Andric     W.getOStream() << formatv("Showing {0:N} IPI records\n",
61106c3fb27SDimitry Andric                               StreamIpi.getNumTypeRecords());
61206c3fb27SDimitry Andric   });
61306c3fb27SDimitry Andric   return VisitTypes(Ids, Ids, StreamIPI);
61406c3fb27SDimitry Andric }
61506c3fb27SDimitry Andric 
61606c3fb27SDimitry Andric Error LVCodeViewReader::traverseSymbolsSubsection(StringRef Subsection,
61706c3fb27SDimitry Andric                                                   const SectionRef &Section,
61806c3fb27SDimitry Andric                                                   StringRef SectionContents) {
61906c3fb27SDimitry Andric   ArrayRef<uint8_t> BinaryData(Subsection.bytes_begin(),
62006c3fb27SDimitry Andric                                Subsection.bytes_end());
62106c3fb27SDimitry Andric   LVSymbolVisitorDelegate VisitorDelegate(this, Section, &getObj(),
62206c3fb27SDimitry Andric                                           SectionContents);
62306c3fb27SDimitry Andric   CVSymbolArray Symbols;
624*5f757f3fSDimitry Andric   BinaryStreamReader Reader(BinaryData, llvm::endianness::little);
62506c3fb27SDimitry Andric   if (Error E = Reader.readArray(Symbols, Reader.getLength()))
62606c3fb27SDimitry Andric     return createStringError(errorToErrorCode(std::move(E)), getFileName());
62706c3fb27SDimitry Andric 
62806c3fb27SDimitry Andric   LazyRandomTypeCollection &Types = types();
62906c3fb27SDimitry Andric   LazyRandomTypeCollection &Ids = ids();
63006c3fb27SDimitry Andric   SymbolVisitorCallbackPipeline Pipeline;
63106c3fb27SDimitry Andric   SymbolDeserializer Deserializer(&VisitorDelegate,
63206c3fb27SDimitry Andric                                   CodeViewContainer::ObjectFile);
63306c3fb27SDimitry Andric   // As we are processing a COFF format, use TPI as IPI, so the generic code
63406c3fb27SDimitry Andric   // to process the CodeView format does not contain any additional checks.
63506c3fb27SDimitry Andric   LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids,
63606c3fb27SDimitry Andric                             &VisitorDelegate, LogicalVisitor.getShared());
63706c3fb27SDimitry Andric 
63806c3fb27SDimitry Andric   Pipeline.addCallbackToPipeline(Deserializer);
63906c3fb27SDimitry Andric   Pipeline.addCallbackToPipeline(Traverser);
64006c3fb27SDimitry Andric   CVSymbolVisitor Visitor(Pipeline);
64106c3fb27SDimitry Andric   return Visitor.visitSymbolStream(Symbols);
64206c3fb27SDimitry Andric }
64306c3fb27SDimitry Andric 
64406c3fb27SDimitry Andric Error LVCodeViewReader::traverseSymbolSection(StringRef SectionName,
64506c3fb27SDimitry Andric                                               const SectionRef &Section) {
64606c3fb27SDimitry Andric   LLVM_DEBUG({
64706c3fb27SDimitry Andric     ListScope D(W, "CodeViewDebugInfo");
64806c3fb27SDimitry Andric     W.printNumber("Section", SectionName, getObj().getSectionID(Section));
64906c3fb27SDimitry Andric   });
65006c3fb27SDimitry Andric 
65106c3fb27SDimitry Andric   Expected<StringRef> SectionOrErr = Section.getContents();
65206c3fb27SDimitry Andric   if (!SectionOrErr)
65306c3fb27SDimitry Andric     return SectionOrErr.takeError();
65406c3fb27SDimitry Andric   StringRef SectionContents = *SectionOrErr;
65506c3fb27SDimitry Andric   StringRef Data = SectionContents;
65606c3fb27SDimitry Andric 
65706c3fb27SDimitry Andric   SmallVector<StringRef, 10> SymbolNames;
65806c3fb27SDimitry Andric   StringMap<StringRef> FunctionLineTables;
65906c3fb27SDimitry Andric 
66006c3fb27SDimitry Andric   uint32_t Magic;
66106c3fb27SDimitry Andric   if (Error E = consume(Data, Magic))
66206c3fb27SDimitry Andric     return createStringError(errorToErrorCode(std::move(E)), getFileName());
66306c3fb27SDimitry Andric 
66406c3fb27SDimitry Andric   if (Magic != COFF::DEBUG_SECTION_MAGIC)
66506c3fb27SDimitry Andric     return createStringError(object_error::parse_failed, getFileName());
66606c3fb27SDimitry Andric 
667*5f757f3fSDimitry Andric   BinaryStreamReader FSReader(Data, llvm::endianness::little);
66806c3fb27SDimitry Andric   if (Error Err = initializeFileAndStringTables(FSReader))
66906c3fb27SDimitry Andric     return Err;
67006c3fb27SDimitry Andric 
67106c3fb27SDimitry Andric   while (!Data.empty()) {
67206c3fb27SDimitry Andric     // The section consists of a number of subsection in the following format:
67306c3fb27SDimitry Andric     // |SubSectionType|SubSectionSize|Contents...|
67406c3fb27SDimitry Andric     uint32_t SubType, SubSectionSize;
67506c3fb27SDimitry Andric     if (Error E = consume(Data, SubType))
67606c3fb27SDimitry Andric       return createStringError(errorToErrorCode(std::move(E)), getFileName());
67706c3fb27SDimitry Andric     if (Error E = consume(Data, SubSectionSize))
67806c3fb27SDimitry Andric       return createStringError(errorToErrorCode(std::move(E)), getFileName());
67906c3fb27SDimitry Andric 
68006c3fb27SDimitry Andric     // Process the subsection as normal even if the ignore bit is set.
68106c3fb27SDimitry Andric     SubType &= ~SubsectionIgnoreFlag;
68206c3fb27SDimitry Andric 
68306c3fb27SDimitry Andric     // Get the contents of the subsection.
68406c3fb27SDimitry Andric     if (SubSectionSize > Data.size())
68506c3fb27SDimitry Andric       return createStringError(object_error::parse_failed, getFileName());
68606c3fb27SDimitry Andric     StringRef Contents = Data.substr(0, SubSectionSize);
68706c3fb27SDimitry Andric 
68806c3fb27SDimitry Andric     // Add SubSectionSize to the current offset and align that offset
68906c3fb27SDimitry Andric     // to find the next subsection.
69006c3fb27SDimitry Andric     size_t SectionOffset = Data.data() - SectionContents.data();
69106c3fb27SDimitry Andric     size_t NextOffset = SectionOffset + SubSectionSize;
69206c3fb27SDimitry Andric     NextOffset = alignTo(NextOffset, 4);
69306c3fb27SDimitry Andric     if (NextOffset > SectionContents.size())
69406c3fb27SDimitry Andric       return createStringError(object_error::parse_failed, getFileName());
69506c3fb27SDimitry Andric     Data = SectionContents.drop_front(NextOffset);
69606c3fb27SDimitry Andric 
69706c3fb27SDimitry Andric     switch (DebugSubsectionKind(SubType)) {
69806c3fb27SDimitry Andric     case DebugSubsectionKind::Symbols:
69906c3fb27SDimitry Andric       if (Error Err =
70006c3fb27SDimitry Andric               traverseSymbolsSubsection(Contents, Section, SectionContents))
70106c3fb27SDimitry Andric         return Err;
70206c3fb27SDimitry Andric       break;
70306c3fb27SDimitry Andric 
70406c3fb27SDimitry Andric     case DebugSubsectionKind::InlineeLines:
70506c3fb27SDimitry Andric       if (Error Err = traverseInlineeLines(Contents))
70606c3fb27SDimitry Andric         return Err;
70706c3fb27SDimitry Andric       break;
70806c3fb27SDimitry Andric 
70906c3fb27SDimitry Andric     case DebugSubsectionKind::Lines:
71006c3fb27SDimitry Andric       // Holds a PC to file:line table. Some data to parse this subsection
71106c3fb27SDimitry Andric       // is stored in the other subsections, so just check sanity and store
71206c3fb27SDimitry Andric       // the pointers for deferred processing.
71306c3fb27SDimitry Andric 
71406c3fb27SDimitry Andric       // Collect function and ranges only if we need to print logical lines.
71506c3fb27SDimitry Andric       if (options().getGeneralCollectRanges()) {
71606c3fb27SDimitry Andric 
71706c3fb27SDimitry Andric         if (SubSectionSize < 12) {
71806c3fb27SDimitry Andric           // There should be at least three words to store two function
71906c3fb27SDimitry Andric           // relocations and size of the code.
72006c3fb27SDimitry Andric           return createStringError(object_error::parse_failed, getFileName());
72106c3fb27SDimitry Andric         }
72206c3fb27SDimitry Andric 
72306c3fb27SDimitry Andric         StringRef SymbolName;
72406c3fb27SDimitry Andric         if (Error Err = resolveSymbolName(getObj().getCOFFSection(Section),
72506c3fb27SDimitry Andric                                           SectionOffset, SymbolName))
72606c3fb27SDimitry Andric           return createStringError(errorToErrorCode(std::move(Err)),
72706c3fb27SDimitry Andric                                    getFileName());
72806c3fb27SDimitry Andric 
72906c3fb27SDimitry Andric         LLVM_DEBUG({ W.printString("Symbol Name", SymbolName); });
73006c3fb27SDimitry Andric         if (FunctionLineTables.count(SymbolName) != 0) {
73106c3fb27SDimitry Andric           // Saw debug info for this function already?
73206c3fb27SDimitry Andric           return createStringError(object_error::parse_failed, getFileName());
73306c3fb27SDimitry Andric         }
73406c3fb27SDimitry Andric 
73506c3fb27SDimitry Andric         FunctionLineTables[SymbolName] = Contents;
73606c3fb27SDimitry Andric         SymbolNames.push_back(SymbolName);
73706c3fb27SDimitry Andric       }
73806c3fb27SDimitry Andric       break;
73906c3fb27SDimitry Andric 
74006c3fb27SDimitry Andric     // Do nothing for unrecognized subsections.
74106c3fb27SDimitry Andric     default:
74206c3fb27SDimitry Andric       break;
74306c3fb27SDimitry Andric     }
74406c3fb27SDimitry Andric     W.flush();
74506c3fb27SDimitry Andric   }
74606c3fb27SDimitry Andric 
74706c3fb27SDimitry Andric   // Traverse the line tables now that we've read all the subsections and
74806c3fb27SDimitry Andric   // know all the required information.
74906c3fb27SDimitry Andric   for (StringRef SymbolName : SymbolNames) {
75006c3fb27SDimitry Andric     LLVM_DEBUG({
75106c3fb27SDimitry Andric       ListScope S(W, "FunctionLineTable");
75206c3fb27SDimitry Andric       W.printString("Symbol Name", SymbolName);
75306c3fb27SDimitry Andric     });
75406c3fb27SDimitry Andric 
755*5f757f3fSDimitry Andric     BinaryStreamReader Reader(FunctionLineTables[SymbolName],
756*5f757f3fSDimitry Andric                               llvm::endianness::little);
75706c3fb27SDimitry Andric 
75806c3fb27SDimitry Andric     DebugLinesSubsectionRef Lines;
75906c3fb27SDimitry Andric     if (Error E = Lines.initialize(Reader))
76006c3fb27SDimitry Andric       return createStringError(errorToErrorCode(std::move(E)), getFileName());
76106c3fb27SDimitry Andric 
76206c3fb27SDimitry Andric     // Find the associated symbol table information.
76306c3fb27SDimitry Andric     LVSymbolTableEntry SymbolTableEntry = getSymbolTableEntry(SymbolName);
76406c3fb27SDimitry Andric     LVScope *Function = SymbolTableEntry.Scope;
76506c3fb27SDimitry Andric     if (!Function)
76606c3fb27SDimitry Andric       continue;
76706c3fb27SDimitry Andric 
76806c3fb27SDimitry Andric     LVAddress Addendum = SymbolTableEntry.Address;
76906c3fb27SDimitry Andric     LVSectionIndex SectionIndex = SymbolTableEntry.SectionIndex;
77006c3fb27SDimitry Andric 
77106c3fb27SDimitry Andric     // The given scope represents the function that contains the line numbers.
77206c3fb27SDimitry Andric     // Collect all generated debug lines associated with the function.
77306c3fb27SDimitry Andric     CULines.clear();
77406c3fb27SDimitry Andric 
77506c3fb27SDimitry Andric     // For the given scope, collect all scopes ranges.
77606c3fb27SDimitry Andric     LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
77706c3fb27SDimitry Andric     ScopesWithRanges->clear();
77806c3fb27SDimitry Andric     Function->getRanges(*ScopesWithRanges);
77906c3fb27SDimitry Andric     ScopesWithRanges->sort();
78006c3fb27SDimitry Andric 
78106c3fb27SDimitry Andric     uint16_t Segment = Lines.header()->RelocSegment;
78206c3fb27SDimitry Andric     uint32_t Begin = Lines.header()->RelocOffset;
78306c3fb27SDimitry Andric     uint32_t Size = Lines.header()->CodeSize;
78406c3fb27SDimitry Andric     for (const LineColumnEntry &Block : Lines)
78506c3fb27SDimitry Andric       if (Error Err = createLines(Block.LineNumbers, Addendum, Segment, Begin,
78606c3fb27SDimitry Andric                                   Size, Block.NameIndex))
78706c3fb27SDimitry Andric         return Err;
78806c3fb27SDimitry Andric 
78906c3fb27SDimitry Andric     // Include lines from any inlined functions within the current function.
79006c3fb27SDimitry Andric     includeInlineeLines(SectionIndex, Function);
79106c3fb27SDimitry Andric 
79206c3fb27SDimitry Andric     if (Error Err = createInstructions(Function, SectionIndex))
79306c3fb27SDimitry Andric       return Err;
79406c3fb27SDimitry Andric 
79506c3fb27SDimitry Andric     processLines(&CULines, SectionIndex, Function);
79606c3fb27SDimitry Andric   }
79706c3fb27SDimitry Andric 
79806c3fb27SDimitry Andric   return Error::success();
79906c3fb27SDimitry Andric }
80006c3fb27SDimitry Andric 
80106c3fb27SDimitry Andric void LVCodeViewReader::sortScopes() { Root->sort(); }
80206c3fb27SDimitry Andric 
80306c3fb27SDimitry Andric void LVCodeViewReader::print(raw_ostream &OS) const {
80406c3fb27SDimitry Andric   LLVM_DEBUG(dbgs() << "CreateReaders\n");
80506c3fb27SDimitry Andric }
80606c3fb27SDimitry Andric 
80706c3fb27SDimitry Andric void LVCodeViewReader::mapRangeAddress(const ObjectFile &Obj,
80806c3fb27SDimitry Andric                                        const SectionRef &Section,
80906c3fb27SDimitry Andric                                        bool IsComdat) {
81006c3fb27SDimitry Andric   if (!Obj.isCOFF())
81106c3fb27SDimitry Andric     return;
81206c3fb27SDimitry Andric 
81306c3fb27SDimitry Andric   const COFFObjectFile *Object = cast<COFFObjectFile>(&Obj);
81406c3fb27SDimitry Andric 
81506c3fb27SDimitry Andric   for (const SymbolRef &Sym : Object->symbols()) {
81606c3fb27SDimitry Andric     if (!Section.containsSymbol(Sym))
81706c3fb27SDimitry Andric       continue;
81806c3fb27SDimitry Andric 
81906c3fb27SDimitry Andric     COFFSymbolRef Symbol = Object->getCOFFSymbol(Sym);
82006c3fb27SDimitry Andric     if (Symbol.getComplexType() != llvm::COFF::IMAGE_SYM_DTYPE_FUNCTION)
82106c3fb27SDimitry Andric       continue;
82206c3fb27SDimitry Andric 
82306c3fb27SDimitry Andric     StringRef SymbolName;
82406c3fb27SDimitry Andric     Expected<StringRef> SymNameOrErr = Object->getSymbolName(Symbol);
82506c3fb27SDimitry Andric     if (!SymNameOrErr) {
82606c3fb27SDimitry Andric       W.startLine() << "Invalid symbol name: " << Symbol.getSectionNumber()
82706c3fb27SDimitry Andric                     << "\n";
82806c3fb27SDimitry Andric       consumeError(SymNameOrErr.takeError());
82906c3fb27SDimitry Andric       continue;
83006c3fb27SDimitry Andric     }
83106c3fb27SDimitry Andric     SymbolName = *SymNameOrErr;
83206c3fb27SDimitry Andric 
83306c3fb27SDimitry Andric     LLVM_DEBUG({
83406c3fb27SDimitry Andric       Expected<const coff_section *> SectionOrErr =
83506c3fb27SDimitry Andric           Object->getSection(Symbol.getSectionNumber());
83606c3fb27SDimitry Andric       if (!SectionOrErr) {
83706c3fb27SDimitry Andric         W.startLine() << "Invalid section number: " << Symbol.getSectionNumber()
83806c3fb27SDimitry Andric                       << "\n";
83906c3fb27SDimitry Andric         consumeError(SectionOrErr.takeError());
84006c3fb27SDimitry Andric         return;
84106c3fb27SDimitry Andric       }
84206c3fb27SDimitry Andric       W.printNumber("Section #", Symbol.getSectionNumber());
84306c3fb27SDimitry Andric       W.printString("Name", SymbolName);
84406c3fb27SDimitry Andric       W.printHex("Value", Symbol.getValue());
84506c3fb27SDimitry Andric     });
84606c3fb27SDimitry Andric 
84706c3fb27SDimitry Andric     // Record the symbol name (linkage) and its loading address.
84806c3fb27SDimitry Andric     addToSymbolTable(SymbolName, Symbol.getValue(), Symbol.getSectionNumber(),
84906c3fb27SDimitry Andric                      IsComdat);
85006c3fb27SDimitry Andric   }
85106c3fb27SDimitry Andric }
85206c3fb27SDimitry Andric 
85306c3fb27SDimitry Andric Error LVCodeViewReader::createScopes(COFFObjectFile &Obj) {
85406c3fb27SDimitry Andric   if (Error Err = loadTargetInfo(Obj))
85506c3fb27SDimitry Andric     return Err;
85606c3fb27SDimitry Andric 
85706c3fb27SDimitry Andric   // Initialization required when processing a COFF file:
85806c3fb27SDimitry Andric   // Cache the symbols relocations.
85906c3fb27SDimitry Andric   // Create a mapping for virtual addresses.
86006c3fb27SDimitry Andric   // Get the functions entry points.
86106c3fb27SDimitry Andric   cacheRelocations();
86206c3fb27SDimitry Andric   mapVirtualAddress(Obj);
86306c3fb27SDimitry Andric 
86406c3fb27SDimitry Andric   for (const SectionRef &Section : Obj.sections()) {
86506c3fb27SDimitry Andric     Expected<StringRef> SectionNameOrErr = Section.getName();
86606c3fb27SDimitry Andric     if (!SectionNameOrErr)
86706c3fb27SDimitry Andric       return SectionNameOrErr.takeError();
86806c3fb27SDimitry Andric     // .debug$T is a standard CodeView type section, while .debug$P is the
86906c3fb27SDimitry Andric     // same format but used for MSVC precompiled header object files.
87006c3fb27SDimitry Andric     if (*SectionNameOrErr == ".debug$T" || *SectionNameOrErr == ".debug$P")
87106c3fb27SDimitry Andric       if (Error Err = traverseTypeSection(*SectionNameOrErr, Section))
87206c3fb27SDimitry Andric         return Err;
87306c3fb27SDimitry Andric   }
87406c3fb27SDimitry Andric 
87506c3fb27SDimitry Andric   // Process collected namespaces.
87606c3fb27SDimitry Andric   LogicalVisitor.processNamespaces();
87706c3fb27SDimitry Andric 
87806c3fb27SDimitry Andric   for (const SectionRef &Section : Obj.sections()) {
87906c3fb27SDimitry Andric     Expected<StringRef> SectionNameOrErr = Section.getName();
88006c3fb27SDimitry Andric     if (!SectionNameOrErr)
88106c3fb27SDimitry Andric       return SectionNameOrErr.takeError();
88206c3fb27SDimitry Andric     if (*SectionNameOrErr == ".debug$S")
88306c3fb27SDimitry Andric       if (Error Err = traverseSymbolSection(*SectionNameOrErr, Section))
88406c3fb27SDimitry Andric         return Err;
88506c3fb27SDimitry Andric   }
88606c3fb27SDimitry Andric 
88706c3fb27SDimitry Andric   // Check if we have to close the Compile Unit scope.
88806c3fb27SDimitry Andric   LogicalVisitor.closeScope();
88906c3fb27SDimitry Andric 
89006c3fb27SDimitry Andric   // Traverse the strings recorded and transform them into filenames.
89106c3fb27SDimitry Andric   LogicalVisitor.processFiles();
89206c3fb27SDimitry Andric 
89306c3fb27SDimitry Andric   // Process collected element lines.
89406c3fb27SDimitry Andric   LogicalVisitor.processLines();
89506c3fb27SDimitry Andric 
89606c3fb27SDimitry Andric   // Translate composite names into a single component.
89706c3fb27SDimitry Andric   Root->transformScopedName();
89806c3fb27SDimitry Andric   return Error::success();
89906c3fb27SDimitry Andric }
90006c3fb27SDimitry Andric 
90106c3fb27SDimitry Andric Error LVCodeViewReader::createScopes(PDBFile &Pdb) {
90206c3fb27SDimitry Andric   if (Error Err = loadTargetInfo(Pdb))
90306c3fb27SDimitry Andric     return Err;
90406c3fb27SDimitry Andric 
90506c3fb27SDimitry Andric   if (!Pdb.hasPDBTpiStream() || !Pdb.hasPDBDbiStream())
90606c3fb27SDimitry Andric     return Error::success();
90706c3fb27SDimitry Andric 
90806c3fb27SDimitry Andric   // Open the executable associated with the PDB file and get the section
90906c3fb27SDimitry Andric   // addresses used to calculate linear addresses for CodeView Symbols.
91006c3fb27SDimitry Andric   if (!ExePath.empty()) {
91106c3fb27SDimitry Andric     ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
91206c3fb27SDimitry Andric         MemoryBuffer::getFileOrSTDIN(ExePath);
91306c3fb27SDimitry Andric     if (BuffOrErr.getError()) {
91406c3fb27SDimitry Andric       return createStringError(errc::bad_file_descriptor,
91506c3fb27SDimitry Andric                                "File '%s' does not exist.", ExePath.c_str());
91606c3fb27SDimitry Andric     }
91706c3fb27SDimitry Andric     BinaryBuffer = std::move(BuffOrErr.get());
91806c3fb27SDimitry Andric 
91906c3fb27SDimitry Andric     // Check if the buffer corresponds to a PECOFF executable.
92006c3fb27SDimitry Andric     assert(identify_magic(BinaryBuffer->getBuffer()) ==
92106c3fb27SDimitry Andric                file_magic::pecoff_executable &&
92206c3fb27SDimitry Andric            "Invalid PECOFF executable file.");
92306c3fb27SDimitry Andric 
92406c3fb27SDimitry Andric     Expected<std::unique_ptr<Binary>> BinOrErr =
92506c3fb27SDimitry Andric         createBinary(BinaryBuffer->getMemBufferRef());
92606c3fb27SDimitry Andric     if (errorToErrorCode(BinOrErr.takeError())) {
92706c3fb27SDimitry Andric       return createStringError(errc::not_supported,
92806c3fb27SDimitry Andric                                "Binary object format in '%s' is not supported.",
92906c3fb27SDimitry Andric                                ExePath.c_str());
93006c3fb27SDimitry Andric     }
93106c3fb27SDimitry Andric     BinaryExecutable = std::move(*BinOrErr);
93206c3fb27SDimitry Andric     if (COFFObjectFile *COFFObject =
93306c3fb27SDimitry Andric             dyn_cast<COFFObjectFile>(BinaryExecutable.get()))
93406c3fb27SDimitry Andric       mapVirtualAddress(*COFFObject);
93506c3fb27SDimitry Andric   }
93606c3fb27SDimitry Andric 
93706c3fb27SDimitry Andric   // In order to generate a full logical view, we have to traverse both
93806c3fb27SDimitry Andric   // streams TPI and IPI if they are present. The following table gives
93906c3fb27SDimitry Andric   // the stream where a specified type is located. If the IPI stream is
94006c3fb27SDimitry Andric   // not present, all the types are located in the TPI stream.
94106c3fb27SDimitry Andric   //
94206c3fb27SDimitry Andric   // TPI Stream:
94306c3fb27SDimitry Andric   //   LF_POINTER   LF_MODIFIER     LF_PROCEDURE    LF_MFUNCTION
94406c3fb27SDimitry Andric   //   LF_LABEL     LF_ARGLIST      LF_FIELDLIST    LF_ARRAY
94506c3fb27SDimitry Andric   //   LF_CLASS     LF_STRUCTURE    LF_INTERFACE    LF_UNION
94606c3fb27SDimitry Andric   //   LF_ENUM      LF_TYPESERVER2  LF_VFTABLE      LF_VTSHAPE
94706c3fb27SDimitry Andric   //   LF_BITFIELD  LF_METHODLIST   LF_PRECOMP      LF_ENDPRECOMP
94806c3fb27SDimitry Andric   //
94906c3fb27SDimitry Andric   // IPI stream:
95006c3fb27SDimitry Andric   //   LF_FUNC_ID           LF_MFUNC_ID   LF_BUILDINFO
95106c3fb27SDimitry Andric   //   LF_SUBSTR_LIST       LF_STRING_ID  LF_UDT_SRC_LINE
95206c3fb27SDimitry Andric   //   LF_UDT_MOD_SRC_LINE
95306c3fb27SDimitry Andric 
95406c3fb27SDimitry Andric   LazyRandomTypeCollection &Types = types();
95506c3fb27SDimitry Andric   LazyRandomTypeCollection &Ids = ids();
95606c3fb27SDimitry Andric   if (Error Err = traverseTypes(Pdb, Types, Ids))
95706c3fb27SDimitry Andric     return Err;
95806c3fb27SDimitry Andric 
95906c3fb27SDimitry Andric   // Process collected namespaces.
96006c3fb27SDimitry Andric   LogicalVisitor.processNamespaces();
96106c3fb27SDimitry Andric 
96206c3fb27SDimitry Andric   LLVM_DEBUG({ W.getOStream() << "Traversing inlined lines\n"; });
96306c3fb27SDimitry Andric 
96406c3fb27SDimitry Andric   auto VisitInlineeLines = [&](int32_t Modi, const SymbolGroup &SG,
96506c3fb27SDimitry Andric                                DebugInlineeLinesSubsectionRef &Lines) -> Error {
96606c3fb27SDimitry Andric     return collectInlineeInfo(Lines, &SG);
96706c3fb27SDimitry Andric   };
96806c3fb27SDimitry Andric 
96906c3fb27SDimitry Andric   FilterOptions Filters = {};
97006c3fb27SDimitry Andric   LinePrinter Printer(/*Indent=*/2, false, nulls(), Filters);
97106c3fb27SDimitry Andric   const PrintScope HeaderScope(Printer, /*IndentLevel=*/2);
97206c3fb27SDimitry Andric   if (Error Err = iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
97306c3fb27SDimitry Andric           Input, HeaderScope, VisitInlineeLines))
97406c3fb27SDimitry Andric     return Err;
97506c3fb27SDimitry Andric 
97606c3fb27SDimitry Andric   // Traverse global symbols.
97706c3fb27SDimitry Andric   LLVM_DEBUG({ W.getOStream() << "Traversing global symbols\n"; });
97806c3fb27SDimitry Andric   if (Pdb.hasPDBGlobalsStream()) {
97906c3fb27SDimitry Andric     Expected<GlobalsStream &> GlobalsOrErr = Pdb.getPDBGlobalsStream();
98006c3fb27SDimitry Andric     if (!GlobalsOrErr)
98106c3fb27SDimitry Andric       return GlobalsOrErr.takeError();
98206c3fb27SDimitry Andric     GlobalsStream &Globals = *GlobalsOrErr;
98306c3fb27SDimitry Andric     const GSIHashTable &Table = Globals.getGlobalsTable();
98406c3fb27SDimitry Andric     Expected<SymbolStream &> ExpectedSyms = Pdb.getPDBSymbolStream();
98506c3fb27SDimitry Andric     if (ExpectedSyms) {
98606c3fb27SDimitry Andric 
98706c3fb27SDimitry Andric       SymbolVisitorCallbackPipeline Pipeline;
98806c3fb27SDimitry Andric       SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
98906c3fb27SDimitry Andric       LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr,
99006c3fb27SDimitry Andric                                 LogicalVisitor.getShared());
99106c3fb27SDimitry Andric 
99206c3fb27SDimitry Andric       // As the global symbols do not have an associated Compile Unit, create
99306c3fb27SDimitry Andric       // one, as the container for all global symbols.
99406c3fb27SDimitry Andric       RecordPrefix Prefix(SymbolKind::S_COMPILE3);
99506c3fb27SDimitry Andric       CVSymbol Symbol(&Prefix, sizeof(Prefix));
99606c3fb27SDimitry Andric       uint32_t Offset = 0;
99706c3fb27SDimitry Andric       if (Error Err = Traverser.visitSymbolBegin(Symbol, Offset))
99806c3fb27SDimitry Andric         consumeError(std::move(Err));
99906c3fb27SDimitry Andric       else {
100006c3fb27SDimitry Andric         // The CodeView compile unit containing the global symbols does not
100106c3fb27SDimitry Andric         // have a name; generate one using its parent name (object filename)
100206c3fb27SDimitry Andric         // follow by the '_global' string.
100306c3fb27SDimitry Andric         std::string Name(CompileUnit->getParentScope()->getName());
100406c3fb27SDimitry Andric         CompileUnit->setName(Name.append("_global"));
100506c3fb27SDimitry Andric 
100606c3fb27SDimitry Andric         Pipeline.addCallbackToPipeline(Deserializer);
100706c3fb27SDimitry Andric         Pipeline.addCallbackToPipeline(Traverser);
100806c3fb27SDimitry Andric         CVSymbolVisitor Visitor(Pipeline);
100906c3fb27SDimitry Andric 
101006c3fb27SDimitry Andric         BinaryStreamRef SymStream =
101106c3fb27SDimitry Andric             ExpectedSyms->getSymbolArray().getUnderlyingStream();
101206c3fb27SDimitry Andric         for (uint32_t PubSymOff : Table) {
101306c3fb27SDimitry Andric           Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, PubSymOff);
101406c3fb27SDimitry Andric           if (Sym) {
101506c3fb27SDimitry Andric             if (Error Err = Visitor.visitSymbolRecord(*Sym, PubSymOff))
101606c3fb27SDimitry Andric               return createStringError(errorToErrorCode(std::move(Err)),
101706c3fb27SDimitry Andric                                        getFileName());
101806c3fb27SDimitry Andric           } else {
101906c3fb27SDimitry Andric             consumeError(Sym.takeError());
102006c3fb27SDimitry Andric           }
102106c3fb27SDimitry Andric         }
102206c3fb27SDimitry Andric       }
102306c3fb27SDimitry Andric 
102406c3fb27SDimitry Andric       LogicalVisitor.closeScope();
102506c3fb27SDimitry Andric     } else {
102606c3fb27SDimitry Andric       consumeError(ExpectedSyms.takeError());
102706c3fb27SDimitry Andric     }
102806c3fb27SDimitry Andric   }
102906c3fb27SDimitry Andric 
103006c3fb27SDimitry Andric   // Traverse symbols (DBI).
103106c3fb27SDimitry Andric   LLVM_DEBUG({ W.getOStream() << "Traversing symbol groups\n"; });
103206c3fb27SDimitry Andric 
103306c3fb27SDimitry Andric   auto VisitSymbolGroup = [&](uint32_t Modi, const SymbolGroup &SG) -> Error {
103406c3fb27SDimitry Andric     Expected<ModuleDebugStreamRef> ExpectedModS =
103506c3fb27SDimitry Andric         getModuleDebugStream(Pdb, Modi);
103606c3fb27SDimitry Andric     if (ExpectedModS) {
103706c3fb27SDimitry Andric       ModuleDebugStreamRef &ModS = *ExpectedModS;
103806c3fb27SDimitry Andric 
103906c3fb27SDimitry Andric       LLVM_DEBUG({
104006c3fb27SDimitry Andric         W.getOStream() << formatv("Traversing Group: Mod {0:4}\n", Modi);
104106c3fb27SDimitry Andric       });
104206c3fb27SDimitry Andric 
104306c3fb27SDimitry Andric       SymbolVisitorCallbackPipeline Pipeline;
104406c3fb27SDimitry Andric       SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
104506c3fb27SDimitry Andric       LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr,
104606c3fb27SDimitry Andric                                 LogicalVisitor.getShared());
104706c3fb27SDimitry Andric 
104806c3fb27SDimitry Andric       Pipeline.addCallbackToPipeline(Deserializer);
104906c3fb27SDimitry Andric       Pipeline.addCallbackToPipeline(Traverser);
105006c3fb27SDimitry Andric       CVSymbolVisitor Visitor(Pipeline);
105106c3fb27SDimitry Andric       BinarySubstreamRef SS = ModS.getSymbolsSubstream();
105206c3fb27SDimitry Andric       if (Error Err =
105306c3fb27SDimitry Andric               Visitor.visitSymbolStream(ModS.getSymbolArray(), SS.Offset))
105406c3fb27SDimitry Andric         return createStringError(errorToErrorCode(std::move(Err)),
105506c3fb27SDimitry Andric                                  getFileName());
105606c3fb27SDimitry Andric     } else {
105706c3fb27SDimitry Andric       // If the module stream does not exist, it is not an error condition.
105806c3fb27SDimitry Andric       consumeError(ExpectedModS.takeError());
105906c3fb27SDimitry Andric     }
106006c3fb27SDimitry Andric 
106106c3fb27SDimitry Andric     return Error::success();
106206c3fb27SDimitry Andric   };
106306c3fb27SDimitry Andric 
106406c3fb27SDimitry Andric   if (Error Err = iterateSymbolGroups(Input, HeaderScope, VisitSymbolGroup))
106506c3fb27SDimitry Andric     return Err;
106606c3fb27SDimitry Andric 
106706c3fb27SDimitry Andric   // At this stage, the logical view contains all scopes, symbols and types.
106806c3fb27SDimitry Andric   // For PDBs we can use the module id, to access its specific compile unit.
106906c3fb27SDimitry Andric   // The line record addresses has been already resolved, so we can apply the
107006c3fb27SDimitry Andric   // flow as when processing DWARF.
107106c3fb27SDimitry Andric 
107206c3fb27SDimitry Andric   LLVM_DEBUG({ W.getOStream() << "Traversing lines\n"; });
107306c3fb27SDimitry Andric 
107406c3fb27SDimitry Andric   // Record all line records for a Compile Unit.
107506c3fb27SDimitry Andric   CULines.clear();
107606c3fb27SDimitry Andric 
107706c3fb27SDimitry Andric   auto VisitDebugLines = [this](int32_t Modi, const SymbolGroup &SG,
107806c3fb27SDimitry Andric                                 DebugLinesSubsectionRef &Lines) -> Error {
107906c3fb27SDimitry Andric     if (!options().getPrintLines())
108006c3fb27SDimitry Andric       return Error::success();
108106c3fb27SDimitry Andric 
108206c3fb27SDimitry Andric     uint16_t Segment = Lines.header()->RelocSegment;
108306c3fb27SDimitry Andric     uint32_t Begin = Lines.header()->RelocOffset;
108406c3fb27SDimitry Andric     uint32_t Size = Lines.header()->CodeSize;
108506c3fb27SDimitry Andric 
108606c3fb27SDimitry Andric     LLVM_DEBUG({ W.getOStream() << formatv("Modi = {0}\n", Modi); });
108706c3fb27SDimitry Andric 
108806c3fb27SDimitry Andric     // We have line information for a new module; finish processing the
108906c3fb27SDimitry Andric     // collected information for the current module. Once it is done, start
109006c3fb27SDimitry Andric     // recording the line information for the new module.
109106c3fb27SDimitry Andric     if (CurrentModule != Modi) {
109206c3fb27SDimitry Andric       if (Error Err = processModule())
109306c3fb27SDimitry Andric         return Err;
109406c3fb27SDimitry Andric       CULines.clear();
109506c3fb27SDimitry Andric       CurrentModule = Modi;
109606c3fb27SDimitry Andric     }
109706c3fb27SDimitry Andric 
109806c3fb27SDimitry Andric     for (const LineColumnEntry &Block : Lines)
109906c3fb27SDimitry Andric       if (Error Err = createLines(Block.LineNumbers, /*Addendum=*/0, Segment,
110006c3fb27SDimitry Andric                                   Begin, Size, Block.NameIndex, &SG))
110106c3fb27SDimitry Andric         return Err;
110206c3fb27SDimitry Andric 
110306c3fb27SDimitry Andric     return Error::success();
110406c3fb27SDimitry Andric   };
110506c3fb27SDimitry Andric 
110606c3fb27SDimitry Andric   if (Error Err = iterateModuleSubsections<DebugLinesSubsectionRef>(
110706c3fb27SDimitry Andric           Input, HeaderScope, VisitDebugLines))
110806c3fb27SDimitry Andric     return Err;
110906c3fb27SDimitry Andric 
111006c3fb27SDimitry Andric   // Check if we have to close the Compile Unit scope.
111106c3fb27SDimitry Andric   LogicalVisitor.closeScope();
111206c3fb27SDimitry Andric 
111306c3fb27SDimitry Andric   // Process collected element lines.
111406c3fb27SDimitry Andric   LogicalVisitor.processLines();
111506c3fb27SDimitry Andric 
111606c3fb27SDimitry Andric   // Translate composite names into a single component.
111706c3fb27SDimitry Andric   Root->transformScopedName();
111806c3fb27SDimitry Andric   return Error::success();
111906c3fb27SDimitry Andric }
112006c3fb27SDimitry Andric 
112106c3fb27SDimitry Andric Error LVCodeViewReader::processModule() {
112206c3fb27SDimitry Andric   if (LVScope *Scope = getScopeForModule(CurrentModule)) {
112306c3fb27SDimitry Andric     CompileUnit = static_cast<LVScopeCompileUnit *>(Scope);
112406c3fb27SDimitry Andric 
112506c3fb27SDimitry Andric     LLVM_DEBUG({ dbgs() << "Processing Scope: " << Scope->getName() << "\n"; });
112606c3fb27SDimitry Andric 
112706c3fb27SDimitry Andric     // For the given compile unit, collect all scopes ranges.
112806c3fb27SDimitry Andric     // For a complete ranges and lines mapping, the logical view support
112906c3fb27SDimitry Andric     // needs for the compile unit to have a low and high pc values. We
113006c3fb27SDimitry Andric     // can traverse the 'Modules' section and get the information for the
113106c3fb27SDimitry Andric     // specific module. Another option, is from all the ranges collected
113206c3fb27SDimitry Andric     // to take the first and last values.
113306c3fb27SDimitry Andric     LVSectionIndex SectionIndex = DotTextSectionIndex;
113406c3fb27SDimitry Andric     LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
113506c3fb27SDimitry Andric     ScopesWithRanges->clear();
113606c3fb27SDimitry Andric     CompileUnit->getRanges(*ScopesWithRanges);
113706c3fb27SDimitry Andric     if (!ScopesWithRanges->empty())
113806c3fb27SDimitry Andric       CompileUnit->addObject(ScopesWithRanges->getLower(),
113906c3fb27SDimitry Andric                              ScopesWithRanges->getUpper());
114006c3fb27SDimitry Andric     ScopesWithRanges->sort();
114106c3fb27SDimitry Andric 
114206c3fb27SDimitry Andric     if (Error Err = createInstructions())
114306c3fb27SDimitry Andric       return Err;
114406c3fb27SDimitry Andric 
114506c3fb27SDimitry Andric     // Include lines from any inlined functions within the current function.
114606c3fb27SDimitry Andric     includeInlineeLines(SectionIndex, Scope);
114706c3fb27SDimitry Andric 
114806c3fb27SDimitry Andric     processLines(&CULines, SectionIndex, nullptr);
114906c3fb27SDimitry Andric   }
115006c3fb27SDimitry Andric 
115106c3fb27SDimitry Andric   return Error::success();
115206c3fb27SDimitry Andric }
115306c3fb27SDimitry Andric 
115406c3fb27SDimitry Andric // In order to create the scopes, the CodeView Reader will:
115506c3fb27SDimitry Andric // = Traverse the TPI/IPI stream (Type visitor):
115606c3fb27SDimitry Andric // Collect forward references, scoped names, type indexes that will represent
115706c3fb27SDimitry Andric // a logical element, strings, line records, linkage names.
115806c3fb27SDimitry Andric // = Traverse the symbols section (Symbol visitor):
115906c3fb27SDimitry Andric // Create the scopes tree and creates the required logical elements, by
116006c3fb27SDimitry Andric // using the collected indexes from the type visitor.
116106c3fb27SDimitry Andric Error LVCodeViewReader::createScopes() {
116206c3fb27SDimitry Andric   LLVM_DEBUG({
116306c3fb27SDimitry Andric     W.startLine() << "\n";
116406c3fb27SDimitry Andric     W.printString("File", getFileName().str());
116506c3fb27SDimitry Andric     W.printString("Exe", ExePath);
116606c3fb27SDimitry Andric     W.printString("Format", FileFormatName);
116706c3fb27SDimitry Andric   });
116806c3fb27SDimitry Andric 
116906c3fb27SDimitry Andric   if (Error Err = LVReader::createScopes())
117006c3fb27SDimitry Andric     return Err;
117106c3fb27SDimitry Andric 
117206c3fb27SDimitry Andric   LogicalVisitor.setRoot(Root);
117306c3fb27SDimitry Andric 
117406c3fb27SDimitry Andric   if (isObj()) {
117506c3fb27SDimitry Andric     if (Error Err = createScopes(getObj()))
117606c3fb27SDimitry Andric       return Err;
117706c3fb27SDimitry Andric   } else {
117806c3fb27SDimitry Andric     if (Error Err = createScopes(getPdb()))
117906c3fb27SDimitry Andric       return Err;
118006c3fb27SDimitry Andric   }
118106c3fb27SDimitry Andric 
118206c3fb27SDimitry Andric   return Error::success();
118306c3fb27SDimitry Andric }
118406c3fb27SDimitry Andric 
118506c3fb27SDimitry Andric Error LVCodeViewReader::loadTargetInfo(const ObjectFile &Obj) {
118606c3fb27SDimitry Andric   // Detect the architecture from the object file. We usually don't need OS
118706c3fb27SDimitry Andric   // info to lookup a target and create register info.
118806c3fb27SDimitry Andric   Triple TT;
118906c3fb27SDimitry Andric   TT.setArch(Triple::ArchType(Obj.getArch()));
119006c3fb27SDimitry Andric   TT.setVendor(Triple::UnknownVendor);
119106c3fb27SDimitry Andric   TT.setOS(Triple::UnknownOS);
119206c3fb27SDimitry Andric 
119306c3fb27SDimitry Andric   // Features to be passed to target/subtarget
119406c3fb27SDimitry Andric   Expected<SubtargetFeatures> Features = Obj.getFeatures();
119506c3fb27SDimitry Andric   SubtargetFeatures FeaturesValue;
119606c3fb27SDimitry Andric   if (!Features) {
119706c3fb27SDimitry Andric     consumeError(Features.takeError());
119806c3fb27SDimitry Andric     FeaturesValue = SubtargetFeatures();
119906c3fb27SDimitry Andric   }
120006c3fb27SDimitry Andric   FeaturesValue = *Features;
120106c3fb27SDimitry Andric   return loadGenericTargetInfo(TT.str(), FeaturesValue.getString());
120206c3fb27SDimitry Andric }
120306c3fb27SDimitry Andric 
120406c3fb27SDimitry Andric Error LVCodeViewReader::loadTargetInfo(const PDBFile &Pdb) {
120506c3fb27SDimitry Andric   Triple TT;
120606c3fb27SDimitry Andric   TT.setArch(Triple::ArchType::x86_64);
120706c3fb27SDimitry Andric   TT.setVendor(Triple::UnknownVendor);
120806c3fb27SDimitry Andric   TT.setOS(Triple::Win32);
120906c3fb27SDimitry Andric 
121006c3fb27SDimitry Andric   StringRef TheFeature = "";
121106c3fb27SDimitry Andric 
121206c3fb27SDimitry Andric   return loadGenericTargetInfo(TT.str(), TheFeature);
121306c3fb27SDimitry Andric }
121406c3fb27SDimitry Andric 
121506c3fb27SDimitry Andric std::string LVCodeViewReader::getRegisterName(LVSmall Opcode,
121606c3fb27SDimitry Andric                                               ArrayRef<uint64_t> Operands) {
121706c3fb27SDimitry Andric   // Get Compilation Unit CPU Type.
121806c3fb27SDimitry Andric   CPUType CPU = getCompileUnitCPUType();
121906c3fb27SDimitry Andric   // For CodeView the register always is in Operands[0];
122006c3fb27SDimitry Andric   RegisterId Register = (RegisterId(Operands[0]));
122106c3fb27SDimitry Andric   return formatRegisterId(Register, CPU);
122206c3fb27SDimitry Andric }
1223