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