xref: /src/contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewReader.cpp (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
17fa27ce4SDimitry Andric //===-- LVCodeViewReader.cpp ----------------------------------------------===//
27fa27ce4SDimitry Andric //
37fa27ce4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47fa27ce4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
57fa27ce4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67fa27ce4SDimitry Andric //
77fa27ce4SDimitry Andric //===----------------------------------------------------------------------===//
87fa27ce4SDimitry Andric //
97fa27ce4SDimitry Andric // This implements the LVCodeViewReader class.
107fa27ce4SDimitry Andric //
117fa27ce4SDimitry Andric //===----------------------------------------------------------------------===//
127fa27ce4SDimitry Andric 
137fa27ce4SDimitry Andric #include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h"
147fa27ce4SDimitry Andric #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
157fa27ce4SDimitry Andric #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
167fa27ce4SDimitry Andric #include "llvm/DebugInfo/CodeView/EnumTables.h"
177fa27ce4SDimitry Andric #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
187fa27ce4SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
197fa27ce4SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
207fa27ce4SDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
217fa27ce4SDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
227fa27ce4SDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
237fa27ce4SDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVType.h"
247fa27ce4SDimitry Andric #include "llvm/DebugInfo/PDB/GenericError.h"
257fa27ce4SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
267fa27ce4SDimitry Andric #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
277fa27ce4SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
287fa27ce4SDimitry Andric #include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
297fa27ce4SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
307fa27ce4SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
317fa27ce4SDimitry Andric #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
327fa27ce4SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
337fa27ce4SDimitry Andric #include "llvm/Demangle/Demangle.h"
347fa27ce4SDimitry Andric #include "llvm/Object/COFF.h"
357fa27ce4SDimitry Andric #include "llvm/Support/Errc.h"
367fa27ce4SDimitry Andric #include "llvm/Support/Error.h"
377fa27ce4SDimitry Andric #include "llvm/Support/FormatAdapters.h"
387fa27ce4SDimitry Andric #include "llvm/Support/FormatVariadic.h"
397fa27ce4SDimitry Andric #include "llvm/Support/WithColor.h"
407fa27ce4SDimitry Andric 
417fa27ce4SDimitry Andric using namespace llvm;
427fa27ce4SDimitry Andric using namespace llvm::codeview;
437fa27ce4SDimitry Andric using namespace llvm::logicalview;
447fa27ce4SDimitry Andric using namespace llvm::msf;
457fa27ce4SDimitry Andric using namespace llvm::object;
467fa27ce4SDimitry Andric using namespace llvm::pdb;
477fa27ce4SDimitry Andric 
487fa27ce4SDimitry Andric #define DEBUG_TYPE "CodeViewReader"
497fa27ce4SDimitry Andric 
getSymbolKindName(SymbolKind Kind)507fa27ce4SDimitry Andric StringRef LVCodeViewReader::getSymbolKindName(SymbolKind Kind) {
517fa27ce4SDimitry Andric   switch (Kind) {
527fa27ce4SDimitry Andric #define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
537fa27ce4SDimitry Andric   case EnumName:                                                               \
547fa27ce4SDimitry Andric     return #EnumName;
557fa27ce4SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
567fa27ce4SDimitry Andric   default:
577fa27ce4SDimitry Andric     return "UnknownSym";
587fa27ce4SDimitry Andric   }
597fa27ce4SDimitry Andric   llvm_unreachable("Unknown SymbolKind::Kind");
607fa27ce4SDimitry Andric }
617fa27ce4SDimitry Andric 
formatRegisterId(RegisterId Register,CPUType CPU)627fa27ce4SDimitry Andric std::string LVCodeViewReader::formatRegisterId(RegisterId Register,
637fa27ce4SDimitry Andric                                                CPUType CPU) {
647fa27ce4SDimitry Andric #define RETURN_CASE(Enum, X, Ret)                                              \
657fa27ce4SDimitry Andric   case Enum::X:                                                                \
667fa27ce4SDimitry Andric     return Ret;
677fa27ce4SDimitry Andric 
687fa27ce4SDimitry Andric   if (CPU == CPUType::ARMNT) {
697fa27ce4SDimitry Andric     switch (Register) {
707fa27ce4SDimitry Andric #define CV_REGISTERS_ARM
717fa27ce4SDimitry Andric #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
727fa27ce4SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
737fa27ce4SDimitry Andric #undef CV_REGISTER
747fa27ce4SDimitry Andric #undef CV_REGISTERS_ARM
757fa27ce4SDimitry Andric 
767fa27ce4SDimitry Andric     default:
777fa27ce4SDimitry Andric       break;
787fa27ce4SDimitry Andric     }
797fa27ce4SDimitry Andric   } else if (CPU == CPUType::ARM64) {
807fa27ce4SDimitry Andric     switch (Register) {
817fa27ce4SDimitry Andric #define CV_REGISTERS_ARM64
827fa27ce4SDimitry Andric #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
837fa27ce4SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
847fa27ce4SDimitry Andric #undef CV_REGISTER
857fa27ce4SDimitry Andric #undef CV_REGISTERS_ARM64
867fa27ce4SDimitry Andric 
877fa27ce4SDimitry Andric     default:
887fa27ce4SDimitry Andric       break;
897fa27ce4SDimitry Andric     }
907fa27ce4SDimitry Andric   } else {
917fa27ce4SDimitry Andric     switch (Register) {
927fa27ce4SDimitry Andric #define CV_REGISTERS_X86
937fa27ce4SDimitry Andric #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
947fa27ce4SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
957fa27ce4SDimitry Andric #undef CV_REGISTER
967fa27ce4SDimitry Andric #undef CV_REGISTERS_X86
977fa27ce4SDimitry Andric 
987fa27ce4SDimitry Andric     default:
997fa27ce4SDimitry Andric       break;
1007fa27ce4SDimitry Andric     }
1017fa27ce4SDimitry Andric   }
1027fa27ce4SDimitry Andric   return "formatUnknownEnum(Id)";
1037fa27ce4SDimitry Andric }
1047fa27ce4SDimitry Andric 
printRelocatedField(StringRef Label,const coff_section * CoffSection,uint32_t RelocOffset,uint32_t Offset,StringRef * RelocSym)1057fa27ce4SDimitry Andric void LVCodeViewReader::printRelocatedField(StringRef Label,
1067fa27ce4SDimitry Andric                                            const coff_section *CoffSection,
1077fa27ce4SDimitry Andric                                            uint32_t RelocOffset,
1087fa27ce4SDimitry Andric                                            uint32_t Offset,
1097fa27ce4SDimitry Andric                                            StringRef *RelocSym) {
1107fa27ce4SDimitry Andric   StringRef SymStorage;
1117fa27ce4SDimitry Andric   StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
1127fa27ce4SDimitry Andric   if (!resolveSymbolName(CoffSection, RelocOffset, Symbol))
1137fa27ce4SDimitry Andric     W.printSymbolOffset(Label, Symbol, Offset);
1147fa27ce4SDimitry Andric   else
1157fa27ce4SDimitry Andric     W.printHex(Label, RelocOffset);
1167fa27ce4SDimitry Andric }
1177fa27ce4SDimitry Andric 
getLinkageName(const coff_section * CoffSection,uint32_t RelocOffset,uint32_t Offset,StringRef * RelocSym)1187fa27ce4SDimitry Andric void LVCodeViewReader::getLinkageName(const coff_section *CoffSection,
1197fa27ce4SDimitry Andric                                       uint32_t RelocOffset, uint32_t Offset,
1207fa27ce4SDimitry Andric                                       StringRef *RelocSym) {
1217fa27ce4SDimitry Andric   StringRef SymStorage;
1227fa27ce4SDimitry Andric   StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
1237fa27ce4SDimitry Andric   if (resolveSymbolName(CoffSection, RelocOffset, Symbol))
1247fa27ce4SDimitry Andric     Symbol = "";
1257fa27ce4SDimitry Andric }
1267fa27ce4SDimitry Andric 
1277fa27ce4SDimitry Andric Expected<StringRef>
getFileNameForFileOffset(uint32_t FileOffset,const SymbolGroup * SG)1287fa27ce4SDimitry Andric LVCodeViewReader::getFileNameForFileOffset(uint32_t FileOffset,
1297fa27ce4SDimitry Andric                                            const SymbolGroup *SG) {
1307fa27ce4SDimitry Andric   if (SG) {
1317fa27ce4SDimitry Andric     Expected<StringRef> Filename = SG->getNameFromChecksums(FileOffset);
1327fa27ce4SDimitry Andric     if (!Filename) {
1337fa27ce4SDimitry Andric       consumeError(Filename.takeError());
1347fa27ce4SDimitry Andric       return StringRef("");
1357fa27ce4SDimitry Andric     }
1367fa27ce4SDimitry Andric     return *Filename;
1377fa27ce4SDimitry Andric   }
1387fa27ce4SDimitry Andric 
1397fa27ce4SDimitry Andric   // The file checksum subsection should precede all references to it.
1407fa27ce4SDimitry Andric   if (!CVFileChecksumTable.valid() || !CVStringTable.valid())
1417fa27ce4SDimitry Andric     return createStringError(object_error::parse_failed, getFileName());
1427fa27ce4SDimitry Andric 
1437fa27ce4SDimitry Andric   VarStreamArray<FileChecksumEntry>::Iterator Iter =
1447fa27ce4SDimitry Andric       CVFileChecksumTable.getArray().at(FileOffset);
1457fa27ce4SDimitry Andric 
1467fa27ce4SDimitry Andric   // Check if the file checksum table offset is valid.
1477fa27ce4SDimitry Andric   if (Iter == CVFileChecksumTable.end())
1487fa27ce4SDimitry Andric     return createStringError(object_error::parse_failed, getFileName());
1497fa27ce4SDimitry Andric 
1507fa27ce4SDimitry Andric   Expected<StringRef> NameOrErr = CVStringTable.getString(Iter->FileNameOffset);
1517fa27ce4SDimitry Andric   if (!NameOrErr)
1527fa27ce4SDimitry Andric     return createStringError(object_error::parse_failed, getFileName());
1537fa27ce4SDimitry Andric   return *NameOrErr;
1547fa27ce4SDimitry Andric }
1557fa27ce4SDimitry Andric 
printFileNameForOffset(StringRef Label,uint32_t FileOffset,const SymbolGroup * SG)1567fa27ce4SDimitry Andric Error LVCodeViewReader::printFileNameForOffset(StringRef Label,
1577fa27ce4SDimitry Andric                                                uint32_t FileOffset,
1587fa27ce4SDimitry Andric                                                const SymbolGroup *SG) {
1597fa27ce4SDimitry Andric   Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset, SG);
1607fa27ce4SDimitry Andric   if (!NameOrErr)
1617fa27ce4SDimitry Andric     return NameOrErr.takeError();
1627fa27ce4SDimitry Andric   W.printHex(Label, *NameOrErr, FileOffset);
1637fa27ce4SDimitry Andric   return Error::success();
1647fa27ce4SDimitry Andric }
1657fa27ce4SDimitry Andric 
cacheRelocations()1667fa27ce4SDimitry Andric void LVCodeViewReader::cacheRelocations() {
1677fa27ce4SDimitry Andric   for (const SectionRef &Section : getObj().sections()) {
1687fa27ce4SDimitry Andric     const coff_section *CoffSection = getObj().getCOFFSection(Section);
1697fa27ce4SDimitry Andric 
1707fa27ce4SDimitry Andric     for (const RelocationRef &Relocacion : Section.relocations())
1717fa27ce4SDimitry Andric       RelocMap[CoffSection].push_back(Relocacion);
1727fa27ce4SDimitry Andric 
1737fa27ce4SDimitry Andric     // Sort relocations by address.
1747fa27ce4SDimitry Andric     llvm::sort(RelocMap[CoffSection], [](RelocationRef L, RelocationRef R) {
1757fa27ce4SDimitry Andric       return L.getOffset() < R.getOffset();
1767fa27ce4SDimitry Andric     });
1777fa27ce4SDimitry Andric   }
1787fa27ce4SDimitry Andric }
1797fa27ce4SDimitry Andric 
1807fa27ce4SDimitry Andric // Given a section and an offset into this section the function returns the
1817fa27ce4SDimitry Andric // symbol used for the relocation at the offset.
resolveSymbol(const coff_section * CoffSection,uint64_t Offset,SymbolRef & Sym)1827fa27ce4SDimitry Andric Error LVCodeViewReader::resolveSymbol(const coff_section *CoffSection,
1837fa27ce4SDimitry Andric                                       uint64_t Offset, SymbolRef &Sym) {
1847fa27ce4SDimitry Andric   const auto &Relocations = RelocMap[CoffSection];
1857fa27ce4SDimitry Andric   basic_symbol_iterator SymI = getObj().symbol_end();
1867fa27ce4SDimitry Andric   for (const RelocationRef &Relocation : Relocations) {
1877fa27ce4SDimitry Andric     uint64_t RelocationOffset = Relocation.getOffset();
1887fa27ce4SDimitry Andric 
1897fa27ce4SDimitry Andric     if (RelocationOffset == Offset) {
1907fa27ce4SDimitry Andric       SymI = Relocation.getSymbol();
1917fa27ce4SDimitry Andric       break;
1927fa27ce4SDimitry Andric     }
1937fa27ce4SDimitry Andric   }
1947fa27ce4SDimitry Andric   if (SymI == getObj().symbol_end())
1957fa27ce4SDimitry Andric     return make_error<StringError>("Unknown Symbol", inconvertibleErrorCode());
1967fa27ce4SDimitry Andric   Sym = *SymI;
1977fa27ce4SDimitry Andric   return ErrorSuccess();
1987fa27ce4SDimitry Andric }
1997fa27ce4SDimitry Andric 
2007fa27ce4SDimitry Andric // Given a section and an offset into this section the function returns the
2017fa27ce4SDimitry Andric // name of the symbol used for the relocation at the offset.
resolveSymbolName(const coff_section * CoffSection,uint64_t Offset,StringRef & Name)2027fa27ce4SDimitry Andric Error LVCodeViewReader::resolveSymbolName(const coff_section *CoffSection,
2037fa27ce4SDimitry Andric                                           uint64_t Offset, StringRef &Name) {
2047fa27ce4SDimitry Andric   SymbolRef Symbol;
2057fa27ce4SDimitry Andric   if (Error E = resolveSymbol(CoffSection, Offset, Symbol))
2067fa27ce4SDimitry Andric     return E;
2077fa27ce4SDimitry Andric   Expected<StringRef> NameOrErr = Symbol.getName();
2087fa27ce4SDimitry Andric   if (!NameOrErr)
2097fa27ce4SDimitry Andric     return NameOrErr.takeError();
2107fa27ce4SDimitry Andric   Name = *NameOrErr;
2117fa27ce4SDimitry Andric   return ErrorSuccess();
2127fa27ce4SDimitry Andric }
2137fa27ce4SDimitry Andric 
2147fa27ce4SDimitry Andric // CodeView and DWARF can have references to compiler generated elements,
2157fa27ce4SDimitry Andric // used for initialization. The MSVC includes in the PDBs, internal compile
2167fa27ce4SDimitry Andric // units, associated with the MS runtime support. We mark them as 'system'
2177fa27ce4SDimitry Andric // and they are printed only if the command line option 'internal=system'.
isSystemEntry(LVElement * Element,StringRef Name) const2187fa27ce4SDimitry Andric bool LVCodeViewReader::isSystemEntry(LVElement *Element, StringRef Name) const {
2197fa27ce4SDimitry Andric   Name = Name.empty() ? Element->getName() : Name;
2204df029ccSDimitry Andric   auto Find = [=](const char *String) -> bool { return Name.contains(String); };
2217fa27ce4SDimitry Andric   auto Starts = [=](const char *Pattern) -> bool {
222b1c73532SDimitry Andric     return Name.starts_with(Pattern);
2237fa27ce4SDimitry Andric   };
2247fa27ce4SDimitry Andric   auto CheckExclude = [&]() -> bool {
2257fa27ce4SDimitry Andric     if (Starts("__") || Starts("_PMD") || Starts("_PMFN"))
2267fa27ce4SDimitry Andric       return true;
2277fa27ce4SDimitry Andric     if (Find("_s__"))
2287fa27ce4SDimitry Andric       return true;
2297fa27ce4SDimitry Andric     if (Find("_CatchableType") || Find("_TypeDescriptor"))
2307fa27ce4SDimitry Andric       return true;
2317fa27ce4SDimitry Andric     if (Find("Intermediate\\vctools"))
2327fa27ce4SDimitry Andric       return true;
2337fa27ce4SDimitry Andric     if (Find("$initializer$") || Find("dynamic initializer"))
2347fa27ce4SDimitry Andric       return true;
2357fa27ce4SDimitry Andric     if (Find("`vftable'") || Find("_GLOBAL__sub"))
2367fa27ce4SDimitry Andric       return true;
2377fa27ce4SDimitry Andric     return false;
2387fa27ce4SDimitry Andric   };
2397fa27ce4SDimitry Andric   bool Excluded = CheckExclude();
2407fa27ce4SDimitry Andric   if (Excluded)
2417fa27ce4SDimitry Andric     Element->setIsSystem();
2427fa27ce4SDimitry Andric 
2437fa27ce4SDimitry Andric   return Excluded;
2447fa27ce4SDimitry Andric }
2457fa27ce4SDimitry Andric 
collectInlineeInfo(DebugInlineeLinesSubsectionRef & Lines,const llvm::pdb::SymbolGroup * SG)2467fa27ce4SDimitry Andric Error LVCodeViewReader::collectInlineeInfo(
2477fa27ce4SDimitry Andric     DebugInlineeLinesSubsectionRef &Lines, const llvm::pdb::SymbolGroup *SG) {
2487fa27ce4SDimitry Andric   for (const InlineeSourceLine &Line : Lines) {
2497fa27ce4SDimitry Andric     TypeIndex TIInlinee = Line.Header->Inlinee;
2507fa27ce4SDimitry Andric     uint32_t LineNumber = Line.Header->SourceLineNum;
2517fa27ce4SDimitry Andric     uint32_t FileOffset = Line.Header->FileID;
2527fa27ce4SDimitry Andric     LLVM_DEBUG({
2537fa27ce4SDimitry Andric       DictScope S(W, "InlineeSourceLine");
2547fa27ce4SDimitry Andric       LogicalVisitor.printTypeIndex("Inlinee", TIInlinee, StreamTPI);
2557fa27ce4SDimitry Andric       if (Error Err = printFileNameForOffset("FileID", FileOffset, SG))
2567fa27ce4SDimitry Andric         return Err;
2577fa27ce4SDimitry Andric       W.printNumber("SourceLineNum", LineNumber);
2587fa27ce4SDimitry Andric 
2597fa27ce4SDimitry Andric       if (Lines.hasExtraFiles()) {
2607fa27ce4SDimitry Andric         W.printNumber("ExtraFileCount", Line.ExtraFiles.size());
2617fa27ce4SDimitry Andric         ListScope ExtraFiles(W, "ExtraFiles");
2627fa27ce4SDimitry Andric         for (const ulittle32_t &FID : Line.ExtraFiles)
2637fa27ce4SDimitry Andric           if (Error Err = printFileNameForOffset("FileID", FID, SG))
2647fa27ce4SDimitry Andric             return Err;
2657fa27ce4SDimitry Andric       }
2667fa27ce4SDimitry Andric     });
2677fa27ce4SDimitry Andric     Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset, SG);
2687fa27ce4SDimitry Andric     if (!NameOrErr)
2697fa27ce4SDimitry Andric       return NameOrErr.takeError();
2707fa27ce4SDimitry Andric     LogicalVisitor.addInlineeInfo(TIInlinee, LineNumber, *NameOrErr);
2717fa27ce4SDimitry Andric   }
2727fa27ce4SDimitry Andric 
2737fa27ce4SDimitry Andric   return Error::success();
2747fa27ce4SDimitry Andric }
2757fa27ce4SDimitry Andric 
traverseInlineeLines(StringRef Subsection)2767fa27ce4SDimitry Andric Error LVCodeViewReader::traverseInlineeLines(StringRef Subsection) {
277b1c73532SDimitry Andric   BinaryStreamReader SR(Subsection, llvm::endianness::little);
2787fa27ce4SDimitry Andric   DebugInlineeLinesSubsectionRef Lines;
2797fa27ce4SDimitry Andric   if (Error E = Lines.initialize(SR))
2807fa27ce4SDimitry Andric     return createStringError(errorToErrorCode(std::move(E)), getFileName());
2817fa27ce4SDimitry Andric 
2827fa27ce4SDimitry Andric   return collectInlineeInfo(Lines);
2837fa27ce4SDimitry Andric }
2847fa27ce4SDimitry Andric 
createLines(const FixedStreamArray<LineNumberEntry> & LineNumbers,LVAddress Addendum,uint32_t Segment,uint32_t Begin,uint32_t Size,uint32_t NameIndex,const SymbolGroup * SG)2857fa27ce4SDimitry Andric Error LVCodeViewReader::createLines(
2867fa27ce4SDimitry Andric     const FixedStreamArray<LineNumberEntry> &LineNumbers, LVAddress Addendum,
2877fa27ce4SDimitry Andric     uint32_t Segment, uint32_t Begin, uint32_t Size, uint32_t NameIndex,
2887fa27ce4SDimitry Andric     const SymbolGroup *SG) {
2897fa27ce4SDimitry Andric   LLVM_DEBUG({
2907fa27ce4SDimitry Andric     uint32_t End = Begin + Size;
2917fa27ce4SDimitry Andric     W.getOStream() << formatv("{0:x-4}:{1:x-8}-{2:x-8}\n", Segment, Begin, End);
2927fa27ce4SDimitry Andric   });
2937fa27ce4SDimitry Andric 
2947fa27ce4SDimitry Andric   for (const LineNumberEntry &Line : LineNumbers) {
2957fa27ce4SDimitry Andric     if (Line.Offset >= Size)
2967fa27ce4SDimitry Andric       return createStringError(object_error::parse_failed, getFileName());
2977fa27ce4SDimitry Andric 
2987fa27ce4SDimitry Andric     LineInfo LI(Line.Flags);
2997fa27ce4SDimitry Andric 
3007fa27ce4SDimitry Andric     LLVM_DEBUG({
3017fa27ce4SDimitry Andric       W.getOStream() << formatv(
3027fa27ce4SDimitry Andric           "{0} {1:x-8}\n", utostr(LI.getStartLine()),
3037fa27ce4SDimitry Andric           fmt_align(Begin + Line.Offset, AlignStyle::Right, 8, '0'));
3047fa27ce4SDimitry Andric     });
3057fa27ce4SDimitry Andric 
3067fa27ce4SDimitry Andric     // The 'processLines()' function will move each created logical line
3077fa27ce4SDimitry Andric     // to its enclosing logical scope, using the debug ranges information
3087fa27ce4SDimitry Andric     // and they will be released when its scope parent is deleted.
3097fa27ce4SDimitry Andric     LVLineDebug *LineDebug = createLineDebug();
3107fa27ce4SDimitry Andric     CULines.push_back(LineDebug);
3117fa27ce4SDimitry Andric     LVAddress Address = linearAddress(Segment, Begin + Line.Offset);
3127fa27ce4SDimitry Andric     LineDebug->setAddress(Address + Addendum);
3137fa27ce4SDimitry Andric 
3147fa27ce4SDimitry Andric     if (LI.isAlwaysStepInto())
3157fa27ce4SDimitry Andric       LineDebug->setIsAlwaysStepInto();
3167fa27ce4SDimitry Andric     else if (LI.isNeverStepInto())
3177fa27ce4SDimitry Andric       LineDebug->setIsNeverStepInto();
3187fa27ce4SDimitry Andric     else
3197fa27ce4SDimitry Andric       LineDebug->setLineNumber(LI.getStartLine());
3207fa27ce4SDimitry Andric 
3217fa27ce4SDimitry Andric     if (LI.isStatement())
3227fa27ce4SDimitry Andric       LineDebug->setIsNewStatement();
3237fa27ce4SDimitry Andric 
3247fa27ce4SDimitry Andric     Expected<StringRef> NameOrErr = getFileNameForFileOffset(NameIndex, SG);
3257fa27ce4SDimitry Andric     if (!NameOrErr)
3267fa27ce4SDimitry Andric       return NameOrErr.takeError();
3277fa27ce4SDimitry Andric     LineDebug->setFilename(*NameOrErr);
3287fa27ce4SDimitry Andric   }
3297fa27ce4SDimitry Andric 
3307fa27ce4SDimitry Andric   return Error::success();
3317fa27ce4SDimitry Andric }
3327fa27ce4SDimitry Andric 
initializeFileAndStringTables(BinaryStreamReader & Reader)3337fa27ce4SDimitry Andric Error LVCodeViewReader::initializeFileAndStringTables(
3347fa27ce4SDimitry Andric     BinaryStreamReader &Reader) {
3357fa27ce4SDimitry Andric   while (Reader.bytesRemaining() > 0 &&
3367fa27ce4SDimitry Andric          (!CVFileChecksumTable.valid() || !CVStringTable.valid())) {
3377fa27ce4SDimitry Andric     // The section consists of a number of subsection in the following format:
3387fa27ce4SDimitry Andric     // |SubSectionType|SubSectionSize|Contents...|
3397fa27ce4SDimitry Andric     uint32_t SubType, SubSectionSize;
3407fa27ce4SDimitry Andric 
3417fa27ce4SDimitry Andric     if (Error E = Reader.readInteger(SubType))
3427fa27ce4SDimitry Andric       return createStringError(errorToErrorCode(std::move(E)), getFileName());
3437fa27ce4SDimitry Andric     if (Error E = Reader.readInteger(SubSectionSize))
3447fa27ce4SDimitry Andric       return createStringError(errorToErrorCode(std::move(E)), getFileName());
3457fa27ce4SDimitry Andric 
3467fa27ce4SDimitry Andric     StringRef Contents;
3477fa27ce4SDimitry Andric     if (Error E = Reader.readFixedString(Contents, SubSectionSize))
3487fa27ce4SDimitry Andric       return createStringError(errorToErrorCode(std::move(E)), getFileName());
3497fa27ce4SDimitry Andric 
350b1c73532SDimitry Andric     BinaryStreamRef ST(Contents, llvm::endianness::little);
3517fa27ce4SDimitry Andric     switch (DebugSubsectionKind(SubType)) {
3527fa27ce4SDimitry Andric     case DebugSubsectionKind::FileChecksums:
3537fa27ce4SDimitry Andric       if (Error E = CVFileChecksumTable.initialize(ST))
3547fa27ce4SDimitry Andric         return createStringError(errorToErrorCode(std::move(E)), getFileName());
3557fa27ce4SDimitry Andric       break;
3567fa27ce4SDimitry Andric     case DebugSubsectionKind::StringTable:
3577fa27ce4SDimitry Andric       if (Error E = CVStringTable.initialize(ST))
3587fa27ce4SDimitry Andric         return createStringError(errorToErrorCode(std::move(E)), getFileName());
3597fa27ce4SDimitry Andric       break;
3607fa27ce4SDimitry Andric     default:
3617fa27ce4SDimitry Andric       break;
3627fa27ce4SDimitry Andric     }
3637fa27ce4SDimitry Andric 
3647fa27ce4SDimitry Andric     uint32_t PaddedSize = alignTo(SubSectionSize, 4);
3657fa27ce4SDimitry Andric     if (Error E = Reader.skip(PaddedSize - SubSectionSize))
3667fa27ce4SDimitry Andric       return createStringError(errorToErrorCode(std::move(E)), getFileName());
3677fa27ce4SDimitry Andric   }
3687fa27ce4SDimitry Andric 
3697fa27ce4SDimitry Andric   return Error::success();
3707fa27ce4SDimitry Andric }
3717fa27ce4SDimitry Andric 
loadTypeServer(TypeServer2Record & TS)3727fa27ce4SDimitry Andric Error LVCodeViewReader::loadTypeServer(TypeServer2Record &TS) {
3737fa27ce4SDimitry Andric   LLVM_DEBUG({
3747fa27ce4SDimitry Andric     W.printString("Guid", formatv("{0}", TS.getGuid()).str());
3757fa27ce4SDimitry Andric     W.printNumber("Age", TS.getAge());
3767fa27ce4SDimitry Andric     W.printString("Name", TS.getName());
3777fa27ce4SDimitry Andric   });
3787fa27ce4SDimitry Andric 
3797fa27ce4SDimitry Andric   SmallString<128> ServerName(TS.getName());
3807fa27ce4SDimitry Andric   BuffOrErr = MemoryBuffer::getFile(ServerName);
3817fa27ce4SDimitry Andric   if (BuffOrErr.getError()) {
3827fa27ce4SDimitry Andric     // The server name does not exist. Try in the same directory as the
3837fa27ce4SDimitry Andric     // input file.
3847fa27ce4SDimitry Andric     ServerName = createAlternativePath(ServerName);
3857fa27ce4SDimitry Andric     BuffOrErr = MemoryBuffer::getFile(ServerName);
3867fa27ce4SDimitry Andric     if (BuffOrErr.getError()) {
3877fa27ce4SDimitry Andric       // For the error message, use the original type server name.
3887fa27ce4SDimitry Andric       return createStringError(errc::bad_file_descriptor,
3897fa27ce4SDimitry Andric                                "File '%s' does not exist.",
3907fa27ce4SDimitry Andric                                TS.getName().str().c_str());
3917fa27ce4SDimitry Andric     }
3927fa27ce4SDimitry Andric   }
3937fa27ce4SDimitry Andric   MemBuffer = std::move(BuffOrErr.get());
3947fa27ce4SDimitry Andric 
3957fa27ce4SDimitry Andric   // Check if the buffer corresponds to a PDB file.
3967fa27ce4SDimitry Andric   assert(identify_magic((*MemBuffer).getBuffer()) == file_magic::pdb &&
3977fa27ce4SDimitry Andric          "Invalid PDB file.");
3987fa27ce4SDimitry Andric 
3997fa27ce4SDimitry Andric   if (Error Err = loadDataForPDB(PDB_ReaderType::Native, ServerName, Session))
4007fa27ce4SDimitry Andric     return createStringError(errorToErrorCode(std::move(Err)), "%s",
4017fa27ce4SDimitry Andric                              ServerName.c_str());
4027fa27ce4SDimitry Andric 
4037fa27ce4SDimitry Andric   PdbSession.reset(static_cast<NativeSession *>(Session.release()));
4047fa27ce4SDimitry Andric   PDBFile &Pdb = PdbSession->getPDBFile();
4057fa27ce4SDimitry Andric 
4067fa27ce4SDimitry Andric   // Just because a file with a matching name was found and it was an actual
4077fa27ce4SDimitry Andric   // PDB file doesn't mean it matches. For it to match the InfoStream's GUID
4087fa27ce4SDimitry Andric   // must match the GUID specified in the TypeServer2 record.
4097fa27ce4SDimitry Andric   Expected<InfoStream &> expectedInfo = Pdb.getPDBInfoStream();
4107fa27ce4SDimitry Andric   if (!expectedInfo || expectedInfo->getGuid() != TS.getGuid())
4117fa27ce4SDimitry Andric     return createStringError(errc::invalid_argument, "signature_out_of_date");
4127fa27ce4SDimitry Andric 
4137fa27ce4SDimitry Andric   // The reader needs to switch to a type server, to process the types from
4147fa27ce4SDimitry Andric   // the server. We need to keep the original input source, as reading other
4157fa27ce4SDimitry Andric   // sections will require the input associated with the loaded object file.
4167fa27ce4SDimitry Andric   TypeServer = std::make_shared<InputFile>(&Pdb);
4177fa27ce4SDimitry Andric   LogicalVisitor.setInput(TypeServer);
4187fa27ce4SDimitry Andric 
4197fa27ce4SDimitry Andric   LazyRandomTypeCollection &Types = types();
4207fa27ce4SDimitry Andric   LazyRandomTypeCollection &Ids = ids();
4217fa27ce4SDimitry Andric   if (Error Err = traverseTypes(Pdb, Types, Ids))
4227fa27ce4SDimitry Andric     return Err;
4237fa27ce4SDimitry Andric 
4247fa27ce4SDimitry Andric   return Error::success();
4257fa27ce4SDimitry Andric }
4267fa27ce4SDimitry Andric 
loadPrecompiledObject(PrecompRecord & Precomp,CVTypeArray & CVTypesObj)4277fa27ce4SDimitry Andric Error LVCodeViewReader::loadPrecompiledObject(PrecompRecord &Precomp,
4287fa27ce4SDimitry Andric                                               CVTypeArray &CVTypesObj) {
4297fa27ce4SDimitry Andric   LLVM_DEBUG({
4307fa27ce4SDimitry Andric     W.printHex("Count", Precomp.getTypesCount());
4317fa27ce4SDimitry Andric     W.printHex("Signature", Precomp.getSignature());
4327fa27ce4SDimitry Andric     W.printString("PrecompFile", Precomp.getPrecompFilePath());
4337fa27ce4SDimitry Andric   });
4347fa27ce4SDimitry Andric 
4357fa27ce4SDimitry Andric   SmallString<128> ServerName(Precomp.getPrecompFilePath());
4367fa27ce4SDimitry Andric   BuffOrErr = MemoryBuffer::getFile(ServerName);
4377fa27ce4SDimitry Andric   if (BuffOrErr.getError()) {
4387fa27ce4SDimitry Andric     // The server name does not exist. Try in the directory as the input file.
4397fa27ce4SDimitry Andric     ServerName = createAlternativePath(ServerName);
4407fa27ce4SDimitry Andric     if (BuffOrErr.getError()) {
4417fa27ce4SDimitry Andric       // For the error message, use the original type server name.
4427fa27ce4SDimitry Andric       return createStringError(errc::bad_file_descriptor,
4437fa27ce4SDimitry Andric                                "File '%s' does not exist.",
4447fa27ce4SDimitry Andric                                Precomp.getPrecompFilePath().str().c_str());
4457fa27ce4SDimitry Andric     }
4467fa27ce4SDimitry Andric   }
4477fa27ce4SDimitry Andric   MemBuffer = std::move(BuffOrErr.get());
4487fa27ce4SDimitry Andric 
4497fa27ce4SDimitry Andric   Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(*MemBuffer);
4507fa27ce4SDimitry Andric   if (errorToErrorCode(BinOrErr.takeError()))
4517fa27ce4SDimitry Andric     return createStringError(errc::not_supported,
4527fa27ce4SDimitry Andric                              "Binary object format in '%s' is not supported.",
4537fa27ce4SDimitry Andric                              ServerName.c_str());
4547fa27ce4SDimitry Andric 
4557fa27ce4SDimitry Andric   Binary &BinaryObj = *BinOrErr.get();
4567fa27ce4SDimitry Andric   if (!BinaryObj.isCOFF())
4577fa27ce4SDimitry Andric     return createStringError(errc::not_supported, "'%s' is not a COFF object.",
4587fa27ce4SDimitry Andric                              ServerName.c_str());
4597fa27ce4SDimitry Andric 
4607fa27ce4SDimitry Andric   Builder = std::make_unique<AppendingTypeTableBuilder>(BuilderAllocator);
4617fa27ce4SDimitry Andric 
4627fa27ce4SDimitry Andric   // The MSVC precompiled header object file, should contain just a single
4637fa27ce4SDimitry Andric   // ".debug$P" section.
4647fa27ce4SDimitry Andric   COFFObjectFile &Obj = *cast<COFFObjectFile>(&BinaryObj);
4657fa27ce4SDimitry Andric   for (const SectionRef &Section : Obj.sections()) {
4667fa27ce4SDimitry Andric     Expected<StringRef> SectionNameOrErr = Section.getName();
4677fa27ce4SDimitry Andric     if (!SectionNameOrErr)
4687fa27ce4SDimitry Andric       return SectionNameOrErr.takeError();
4697fa27ce4SDimitry Andric     if (*SectionNameOrErr == ".debug$P") {
4707fa27ce4SDimitry Andric       Expected<StringRef> DataOrErr = Section.getContents();
4717fa27ce4SDimitry Andric       if (!DataOrErr)
4727fa27ce4SDimitry Andric         return DataOrErr.takeError();
4737fa27ce4SDimitry Andric       uint32_t Magic;
4747fa27ce4SDimitry Andric       if (Error Err = consume(*DataOrErr, Magic))
4757fa27ce4SDimitry Andric         return Err;
4767fa27ce4SDimitry Andric       if (Magic != COFF::DEBUG_SECTION_MAGIC)
4777fa27ce4SDimitry Andric         return errorCodeToError(object_error::parse_failed);
4787fa27ce4SDimitry Andric 
479b1c73532SDimitry Andric       ReaderPrecomp = std::make_unique<BinaryStreamReader>(
480b1c73532SDimitry Andric           *DataOrErr, llvm::endianness::little);
4817fa27ce4SDimitry Andric       cantFail(
4827fa27ce4SDimitry Andric           ReaderPrecomp->readArray(CVTypesPrecomp, ReaderPrecomp->getLength()));
4837fa27ce4SDimitry Andric 
4847fa27ce4SDimitry Andric       // Append all the type records up to the LF_ENDPRECOMP marker and
4857fa27ce4SDimitry Andric       // check if the signatures match.
4867fa27ce4SDimitry Andric       for (const CVType &Type : CVTypesPrecomp) {
4877fa27ce4SDimitry Andric         ArrayRef<uint8_t> TypeData = Type.data();
4887fa27ce4SDimitry Andric         if (Type.kind() == LF_ENDPRECOMP) {
4897fa27ce4SDimitry Andric           EndPrecompRecord EndPrecomp = cantFail(
4907fa27ce4SDimitry Andric               TypeDeserializer::deserializeAs<EndPrecompRecord>(TypeData));
4917fa27ce4SDimitry Andric           if (Precomp.getSignature() != EndPrecomp.getSignature())
4927fa27ce4SDimitry Andric             return createStringError(errc::invalid_argument, "no matching pch");
4937fa27ce4SDimitry Andric           break;
4947fa27ce4SDimitry Andric         }
4957fa27ce4SDimitry Andric         Builder->insertRecordBytes(TypeData);
4967fa27ce4SDimitry Andric       }
4977fa27ce4SDimitry Andric       // Done processing .debug$P, break out of section loop.
4987fa27ce4SDimitry Andric       break;
4997fa27ce4SDimitry Andric     }
5007fa27ce4SDimitry Andric   }
5017fa27ce4SDimitry Andric 
5027fa27ce4SDimitry Andric   // Append all the type records, skipping the first record which is the
5037fa27ce4SDimitry Andric   // reference to the precompiled header object information.
5047fa27ce4SDimitry Andric   for (const CVType &Type : CVTypesObj) {
5057fa27ce4SDimitry Andric     ArrayRef<uint8_t> TypeData = Type.data();
5067fa27ce4SDimitry Andric     if (Type.kind() != LF_PRECOMP)
5077fa27ce4SDimitry Andric       Builder->insertRecordBytes(TypeData);
5087fa27ce4SDimitry Andric   }
5097fa27ce4SDimitry Andric 
5107fa27ce4SDimitry Andric   // Set up a type stream that refers to the added type records.
5117fa27ce4SDimitry Andric   Builder->ForEachRecord(
5127fa27ce4SDimitry Andric       [&](TypeIndex TI, const CVType &Type) { TypeArray.push_back(Type); });
5137fa27ce4SDimitry Andric 
5147fa27ce4SDimitry Andric   ItemStream =
515b1c73532SDimitry Andric       std::make_unique<BinaryItemStream<CVType>>(llvm::endianness::little);
5167fa27ce4SDimitry Andric   ItemStream->setItems(TypeArray);
5177fa27ce4SDimitry Andric   TypeStream.setUnderlyingStream(*ItemStream);
5187fa27ce4SDimitry Andric 
5197fa27ce4SDimitry Andric   PrecompHeader =
5207fa27ce4SDimitry Andric       std::make_shared<LazyRandomTypeCollection>(TypeStream, TypeArray.size());
5217fa27ce4SDimitry Andric 
5227fa27ce4SDimitry Andric   // Change the original input source to use the collected type records.
5237fa27ce4SDimitry Andric   LogicalVisitor.setInput(PrecompHeader);
5247fa27ce4SDimitry Andric 
5257fa27ce4SDimitry Andric   LazyRandomTypeCollection &Types = types();
5267fa27ce4SDimitry Andric   LazyRandomTypeCollection &Ids = ids();
5277fa27ce4SDimitry Andric   LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamTPI,
5287fa27ce4SDimitry Andric                     LogicalVisitor.getShared());
5297fa27ce4SDimitry Andric   return visitTypeStream(Types, TDV);
5307fa27ce4SDimitry Andric }
5317fa27ce4SDimitry Andric 
traverseTypeSection(StringRef SectionName,const SectionRef & Section)5327fa27ce4SDimitry Andric Error LVCodeViewReader::traverseTypeSection(StringRef SectionName,
5337fa27ce4SDimitry Andric                                             const SectionRef &Section) {
5347fa27ce4SDimitry Andric   LLVM_DEBUG({
5357fa27ce4SDimitry Andric     ListScope D(W, "CodeViewTypes");
5367fa27ce4SDimitry Andric     W.printNumber("Section", SectionName, getObj().getSectionID(Section));
5377fa27ce4SDimitry Andric   });
5387fa27ce4SDimitry Andric 
5397fa27ce4SDimitry Andric   Expected<StringRef> DataOrErr = Section.getContents();
5407fa27ce4SDimitry Andric   if (!DataOrErr)
5417fa27ce4SDimitry Andric     return DataOrErr.takeError();
5427fa27ce4SDimitry Andric   uint32_t Magic;
5437fa27ce4SDimitry Andric   if (Error Err = consume(*DataOrErr, Magic))
5447fa27ce4SDimitry Andric     return Err;
5457fa27ce4SDimitry Andric   if (Magic != COFF::DEBUG_SECTION_MAGIC)
5467fa27ce4SDimitry Andric     return errorCodeToError(object_error::parse_failed);
5477fa27ce4SDimitry Andric 
5487fa27ce4SDimitry Andric   // Get the first type record. It will indicate if this object uses a type
5497fa27ce4SDimitry Andric   // server (/Zi) or a PCH file (/Yu).
5507fa27ce4SDimitry Andric   CVTypeArray CVTypes;
551b1c73532SDimitry Andric   BinaryStreamReader Reader(*DataOrErr, llvm::endianness::little);
5527fa27ce4SDimitry Andric   cantFail(Reader.readArray(CVTypes, Reader.getLength()));
5537fa27ce4SDimitry Andric   CVTypeArray::Iterator FirstType = CVTypes.begin();
5547fa27ce4SDimitry Andric 
5557fa27ce4SDimitry Andric   // The object was compiled with /Zi. It uses types from a type server PDB.
5567fa27ce4SDimitry Andric   if (FirstType->kind() == LF_TYPESERVER2) {
5577fa27ce4SDimitry Andric     TypeServer2Record TS = cantFail(
5587fa27ce4SDimitry Andric         TypeDeserializer::deserializeAs<TypeServer2Record>(FirstType->data()));
5597fa27ce4SDimitry Andric     return loadTypeServer(TS);
5607fa27ce4SDimitry Andric   }
5617fa27ce4SDimitry Andric 
5627fa27ce4SDimitry Andric   // The object was compiled with /Yc or /Yu. It uses types from another
5637fa27ce4SDimitry Andric   // object file with a matching signature.
5647fa27ce4SDimitry Andric   if (FirstType->kind() == LF_PRECOMP) {
5657fa27ce4SDimitry Andric     PrecompRecord Precomp = cantFail(
5667fa27ce4SDimitry Andric         TypeDeserializer::deserializeAs<PrecompRecord>(FirstType->data()));
5677fa27ce4SDimitry Andric     return loadPrecompiledObject(Precomp, CVTypes);
5687fa27ce4SDimitry Andric   }
5697fa27ce4SDimitry Andric 
5707fa27ce4SDimitry Andric   LazyRandomTypeCollection &Types = types();
5717fa27ce4SDimitry Andric   LazyRandomTypeCollection &Ids = ids();
5727fa27ce4SDimitry Andric   Types.reset(*DataOrErr, 100);
5737fa27ce4SDimitry Andric   LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamTPI,
5747fa27ce4SDimitry Andric                     LogicalVisitor.getShared());
5757fa27ce4SDimitry Andric   return visitTypeStream(Types, TDV);
5767fa27ce4SDimitry Andric }
5777fa27ce4SDimitry Andric 
traverseTypes(PDBFile & Pdb,LazyRandomTypeCollection & Types,LazyRandomTypeCollection & Ids)5787fa27ce4SDimitry Andric Error LVCodeViewReader::traverseTypes(PDBFile &Pdb,
5797fa27ce4SDimitry Andric                                       LazyRandomTypeCollection &Types,
5807fa27ce4SDimitry Andric                                       LazyRandomTypeCollection &Ids) {
5817fa27ce4SDimitry Andric   // Traverse types (TPI and IPI).
5827fa27ce4SDimitry Andric   auto VisitTypes = [&](LazyRandomTypeCollection &Types,
5837fa27ce4SDimitry Andric                         LazyRandomTypeCollection &Ids,
5847fa27ce4SDimitry Andric                         SpecialStream StreamIdx) -> Error {
5857fa27ce4SDimitry Andric     LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamIdx,
5867fa27ce4SDimitry Andric                       LogicalVisitor.getShared());
5877fa27ce4SDimitry Andric     return visitTypeStream(Types, TDV);
5887fa27ce4SDimitry Andric   };
5897fa27ce4SDimitry Andric 
5907fa27ce4SDimitry Andric   Expected<TpiStream &> StreamTpiOrErr = Pdb.getPDBTpiStream();
5917fa27ce4SDimitry Andric   if (!StreamTpiOrErr)
5927fa27ce4SDimitry Andric     return StreamTpiOrErr.takeError();
5937fa27ce4SDimitry Andric   TpiStream &StreamTpi = *StreamTpiOrErr;
5947fa27ce4SDimitry Andric   StreamTpi.buildHashMap();
5957fa27ce4SDimitry Andric   LLVM_DEBUG({
5967fa27ce4SDimitry Andric     W.getOStream() << formatv("Showing {0:N} TPI records\n",
5977fa27ce4SDimitry Andric                               StreamTpi.getNumTypeRecords());
5987fa27ce4SDimitry Andric   });
5997fa27ce4SDimitry Andric   if (Error Err = VisitTypes(Types, Ids, StreamTPI))
6007fa27ce4SDimitry Andric     return Err;
6017fa27ce4SDimitry Andric 
6027fa27ce4SDimitry Andric   Expected<TpiStream &> StreamIpiOrErr = Pdb.getPDBIpiStream();
6037fa27ce4SDimitry Andric   if (!StreamIpiOrErr)
6047fa27ce4SDimitry Andric     return StreamIpiOrErr.takeError();
6057fa27ce4SDimitry Andric   TpiStream &StreamIpi = *StreamIpiOrErr;
6067fa27ce4SDimitry Andric   StreamIpi.buildHashMap();
6077fa27ce4SDimitry Andric   LLVM_DEBUG({
6087fa27ce4SDimitry Andric     W.getOStream() << formatv("Showing {0:N} IPI records\n",
6097fa27ce4SDimitry Andric                               StreamIpi.getNumTypeRecords());
6107fa27ce4SDimitry Andric   });
6117fa27ce4SDimitry Andric   return VisitTypes(Ids, Ids, StreamIPI);
6127fa27ce4SDimitry Andric }
6137fa27ce4SDimitry Andric 
traverseSymbolsSubsection(StringRef Subsection,const SectionRef & Section,StringRef SectionContents)6147fa27ce4SDimitry Andric Error LVCodeViewReader::traverseSymbolsSubsection(StringRef Subsection,
6157fa27ce4SDimitry Andric                                                   const SectionRef &Section,
6167fa27ce4SDimitry Andric                                                   StringRef SectionContents) {
6177fa27ce4SDimitry Andric   ArrayRef<uint8_t> BinaryData(Subsection.bytes_begin(),
6187fa27ce4SDimitry Andric                                Subsection.bytes_end());
6197fa27ce4SDimitry Andric   LVSymbolVisitorDelegate VisitorDelegate(this, Section, &getObj(),
6207fa27ce4SDimitry Andric                                           SectionContents);
6217fa27ce4SDimitry Andric   CVSymbolArray Symbols;
622b1c73532SDimitry Andric   BinaryStreamReader Reader(BinaryData, llvm::endianness::little);
6237fa27ce4SDimitry Andric   if (Error E = Reader.readArray(Symbols, Reader.getLength()))
6247fa27ce4SDimitry Andric     return createStringError(errorToErrorCode(std::move(E)), getFileName());
6257fa27ce4SDimitry Andric 
6267fa27ce4SDimitry Andric   LazyRandomTypeCollection &Types = types();
6277fa27ce4SDimitry Andric   LazyRandomTypeCollection &Ids = ids();
6287fa27ce4SDimitry Andric   SymbolVisitorCallbackPipeline Pipeline;
6297fa27ce4SDimitry Andric   SymbolDeserializer Deserializer(&VisitorDelegate,
6307fa27ce4SDimitry Andric                                   CodeViewContainer::ObjectFile);
6317fa27ce4SDimitry Andric   // As we are processing a COFF format, use TPI as IPI, so the generic code
6327fa27ce4SDimitry Andric   // to process the CodeView format does not contain any additional checks.
6337fa27ce4SDimitry Andric   LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids,
6347fa27ce4SDimitry Andric                             &VisitorDelegate, LogicalVisitor.getShared());
6357fa27ce4SDimitry Andric 
6367fa27ce4SDimitry Andric   Pipeline.addCallbackToPipeline(Deserializer);
6377fa27ce4SDimitry Andric   Pipeline.addCallbackToPipeline(Traverser);
6387fa27ce4SDimitry Andric   CVSymbolVisitor Visitor(Pipeline);
6397fa27ce4SDimitry Andric   return Visitor.visitSymbolStream(Symbols);
6407fa27ce4SDimitry Andric }
6417fa27ce4SDimitry Andric 
traverseSymbolSection(StringRef SectionName,const SectionRef & Section)6427fa27ce4SDimitry Andric Error LVCodeViewReader::traverseSymbolSection(StringRef SectionName,
6437fa27ce4SDimitry Andric                                               const SectionRef &Section) {
6447fa27ce4SDimitry Andric   LLVM_DEBUG({
6457fa27ce4SDimitry Andric     ListScope D(W, "CodeViewDebugInfo");
6467fa27ce4SDimitry Andric     W.printNumber("Section", SectionName, getObj().getSectionID(Section));
6477fa27ce4SDimitry Andric   });
6487fa27ce4SDimitry Andric 
6497fa27ce4SDimitry Andric   Expected<StringRef> SectionOrErr = Section.getContents();
6507fa27ce4SDimitry Andric   if (!SectionOrErr)
6517fa27ce4SDimitry Andric     return SectionOrErr.takeError();
6527fa27ce4SDimitry Andric   StringRef SectionContents = *SectionOrErr;
6537fa27ce4SDimitry Andric   StringRef Data = SectionContents;
6547fa27ce4SDimitry Andric 
6557fa27ce4SDimitry Andric   SmallVector<StringRef, 10> SymbolNames;
6567fa27ce4SDimitry Andric   StringMap<StringRef> FunctionLineTables;
6577fa27ce4SDimitry Andric 
6587fa27ce4SDimitry Andric   uint32_t Magic;
6597fa27ce4SDimitry Andric   if (Error E = consume(Data, Magic))
6607fa27ce4SDimitry Andric     return createStringError(errorToErrorCode(std::move(E)), getFileName());
6617fa27ce4SDimitry Andric 
6627fa27ce4SDimitry Andric   if (Magic != COFF::DEBUG_SECTION_MAGIC)
6637fa27ce4SDimitry Andric     return createStringError(object_error::parse_failed, getFileName());
6647fa27ce4SDimitry Andric 
665b1c73532SDimitry Andric   BinaryStreamReader FSReader(Data, llvm::endianness::little);
6667fa27ce4SDimitry Andric   if (Error Err = initializeFileAndStringTables(FSReader))
6677fa27ce4SDimitry Andric     return Err;
6687fa27ce4SDimitry Andric 
6697fa27ce4SDimitry Andric   while (!Data.empty()) {
6707fa27ce4SDimitry Andric     // The section consists of a number of subsection in the following format:
6717fa27ce4SDimitry Andric     // |SubSectionType|SubSectionSize|Contents...|
6727fa27ce4SDimitry Andric     uint32_t SubType, SubSectionSize;
6737fa27ce4SDimitry Andric     if (Error E = consume(Data, SubType))
6747fa27ce4SDimitry Andric       return createStringError(errorToErrorCode(std::move(E)), getFileName());
6757fa27ce4SDimitry Andric     if (Error E = consume(Data, SubSectionSize))
6767fa27ce4SDimitry Andric       return createStringError(errorToErrorCode(std::move(E)), getFileName());
6777fa27ce4SDimitry Andric 
6787fa27ce4SDimitry Andric     // Process the subsection as normal even if the ignore bit is set.
6797fa27ce4SDimitry Andric     SubType &= ~SubsectionIgnoreFlag;
6807fa27ce4SDimitry Andric 
6817fa27ce4SDimitry Andric     // Get the contents of the subsection.
6827fa27ce4SDimitry Andric     if (SubSectionSize > Data.size())
6837fa27ce4SDimitry Andric       return createStringError(object_error::parse_failed, getFileName());
6847fa27ce4SDimitry Andric     StringRef Contents = Data.substr(0, SubSectionSize);
6857fa27ce4SDimitry Andric 
6867fa27ce4SDimitry Andric     // Add SubSectionSize to the current offset and align that offset
6877fa27ce4SDimitry Andric     // to find the next subsection.
6887fa27ce4SDimitry Andric     size_t SectionOffset = Data.data() - SectionContents.data();
6897fa27ce4SDimitry Andric     size_t NextOffset = SectionOffset + SubSectionSize;
6907fa27ce4SDimitry Andric     NextOffset = alignTo(NextOffset, 4);
6917fa27ce4SDimitry Andric     if (NextOffset > SectionContents.size())
6927fa27ce4SDimitry Andric       return createStringError(object_error::parse_failed, getFileName());
6937fa27ce4SDimitry Andric     Data = SectionContents.drop_front(NextOffset);
6947fa27ce4SDimitry Andric 
6957fa27ce4SDimitry Andric     switch (DebugSubsectionKind(SubType)) {
6967fa27ce4SDimitry Andric     case DebugSubsectionKind::Symbols:
6977fa27ce4SDimitry Andric       if (Error Err =
6987fa27ce4SDimitry Andric               traverseSymbolsSubsection(Contents, Section, SectionContents))
6997fa27ce4SDimitry Andric         return Err;
7007fa27ce4SDimitry Andric       break;
7017fa27ce4SDimitry Andric 
7027fa27ce4SDimitry Andric     case DebugSubsectionKind::InlineeLines:
7037fa27ce4SDimitry Andric       if (Error Err = traverseInlineeLines(Contents))
7047fa27ce4SDimitry Andric         return Err;
7057fa27ce4SDimitry Andric       break;
7067fa27ce4SDimitry Andric 
7077fa27ce4SDimitry Andric     case DebugSubsectionKind::Lines:
7087fa27ce4SDimitry Andric       // Holds a PC to file:line table. Some data to parse this subsection
7097fa27ce4SDimitry Andric       // is stored in the other subsections, so just check sanity and store
7107fa27ce4SDimitry Andric       // the pointers for deferred processing.
7117fa27ce4SDimitry Andric 
7127fa27ce4SDimitry Andric       // Collect function and ranges only if we need to print logical lines.
7137fa27ce4SDimitry Andric       if (options().getGeneralCollectRanges()) {
7147fa27ce4SDimitry Andric 
7157fa27ce4SDimitry Andric         if (SubSectionSize < 12) {
7167fa27ce4SDimitry Andric           // There should be at least three words to store two function
7177fa27ce4SDimitry Andric           // relocations and size of the code.
7187fa27ce4SDimitry Andric           return createStringError(object_error::parse_failed, getFileName());
7197fa27ce4SDimitry Andric         }
7207fa27ce4SDimitry Andric 
7217fa27ce4SDimitry Andric         StringRef SymbolName;
7227fa27ce4SDimitry Andric         if (Error Err = resolveSymbolName(getObj().getCOFFSection(Section),
7237fa27ce4SDimitry Andric                                           SectionOffset, SymbolName))
7247fa27ce4SDimitry Andric           return createStringError(errorToErrorCode(std::move(Err)),
7257fa27ce4SDimitry Andric                                    getFileName());
7267fa27ce4SDimitry Andric 
7277fa27ce4SDimitry Andric         LLVM_DEBUG({ W.printString("Symbol Name", SymbolName); });
7287fa27ce4SDimitry Andric         if (FunctionLineTables.count(SymbolName) != 0) {
7297fa27ce4SDimitry Andric           // Saw debug info for this function already?
7307fa27ce4SDimitry Andric           return createStringError(object_error::parse_failed, getFileName());
7317fa27ce4SDimitry Andric         }
7327fa27ce4SDimitry Andric 
7337fa27ce4SDimitry Andric         FunctionLineTables[SymbolName] = Contents;
7347fa27ce4SDimitry Andric         SymbolNames.push_back(SymbolName);
7357fa27ce4SDimitry Andric       }
7367fa27ce4SDimitry Andric       break;
7377fa27ce4SDimitry Andric 
7387fa27ce4SDimitry Andric     // Do nothing for unrecognized subsections.
7397fa27ce4SDimitry Andric     default:
7407fa27ce4SDimitry Andric       break;
7417fa27ce4SDimitry Andric     }
7427fa27ce4SDimitry Andric     W.flush();
7437fa27ce4SDimitry Andric   }
7447fa27ce4SDimitry Andric 
7457fa27ce4SDimitry Andric   // Traverse the line tables now that we've read all the subsections and
7467fa27ce4SDimitry Andric   // know all the required information.
7477fa27ce4SDimitry Andric   for (StringRef SymbolName : SymbolNames) {
7487fa27ce4SDimitry Andric     LLVM_DEBUG({
7497fa27ce4SDimitry Andric       ListScope S(W, "FunctionLineTable");
7507fa27ce4SDimitry Andric       W.printString("Symbol Name", SymbolName);
7517fa27ce4SDimitry Andric     });
7527fa27ce4SDimitry Andric 
753b1c73532SDimitry Andric     BinaryStreamReader Reader(FunctionLineTables[SymbolName],
754b1c73532SDimitry Andric                               llvm::endianness::little);
7557fa27ce4SDimitry Andric 
7567fa27ce4SDimitry Andric     DebugLinesSubsectionRef Lines;
7577fa27ce4SDimitry Andric     if (Error E = Lines.initialize(Reader))
7587fa27ce4SDimitry Andric       return createStringError(errorToErrorCode(std::move(E)), getFileName());
7597fa27ce4SDimitry Andric 
7607fa27ce4SDimitry Andric     // Find the associated symbol table information.
7617fa27ce4SDimitry Andric     LVSymbolTableEntry SymbolTableEntry = getSymbolTableEntry(SymbolName);
7627fa27ce4SDimitry Andric     LVScope *Function = SymbolTableEntry.Scope;
7637fa27ce4SDimitry Andric     if (!Function)
7647fa27ce4SDimitry Andric       continue;
7657fa27ce4SDimitry Andric 
7667fa27ce4SDimitry Andric     LVAddress Addendum = SymbolTableEntry.Address;
7677fa27ce4SDimitry Andric     LVSectionIndex SectionIndex = SymbolTableEntry.SectionIndex;
7687fa27ce4SDimitry Andric 
7697fa27ce4SDimitry Andric     // The given scope represents the function that contains the line numbers.
7707fa27ce4SDimitry Andric     // Collect all generated debug lines associated with the function.
7717fa27ce4SDimitry Andric     CULines.clear();
7727fa27ce4SDimitry Andric 
7737fa27ce4SDimitry Andric     // For the given scope, collect all scopes ranges.
7747fa27ce4SDimitry Andric     LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
7757fa27ce4SDimitry Andric     ScopesWithRanges->clear();
7767fa27ce4SDimitry Andric     Function->getRanges(*ScopesWithRanges);
7777fa27ce4SDimitry Andric     ScopesWithRanges->sort();
7787fa27ce4SDimitry Andric 
7797fa27ce4SDimitry Andric     uint16_t Segment = Lines.header()->RelocSegment;
7807fa27ce4SDimitry Andric     uint32_t Begin = Lines.header()->RelocOffset;
7817fa27ce4SDimitry Andric     uint32_t Size = Lines.header()->CodeSize;
7827fa27ce4SDimitry Andric     for (const LineColumnEntry &Block : Lines)
7837fa27ce4SDimitry Andric       if (Error Err = createLines(Block.LineNumbers, Addendum, Segment, Begin,
7847fa27ce4SDimitry Andric                                   Size, Block.NameIndex))
7857fa27ce4SDimitry Andric         return Err;
7867fa27ce4SDimitry Andric 
7877fa27ce4SDimitry Andric     // Include lines from any inlined functions within the current function.
7887fa27ce4SDimitry Andric     includeInlineeLines(SectionIndex, Function);
7897fa27ce4SDimitry Andric 
7907fa27ce4SDimitry Andric     if (Error Err = createInstructions(Function, SectionIndex))
7917fa27ce4SDimitry Andric       return Err;
7927fa27ce4SDimitry Andric 
7937fa27ce4SDimitry Andric     processLines(&CULines, SectionIndex, Function);
7947fa27ce4SDimitry Andric   }
7957fa27ce4SDimitry Andric 
7967fa27ce4SDimitry Andric   return Error::success();
7977fa27ce4SDimitry Andric }
7987fa27ce4SDimitry Andric 
sortScopes()7997fa27ce4SDimitry Andric void LVCodeViewReader::sortScopes() { Root->sort(); }
8007fa27ce4SDimitry Andric 
print(raw_ostream & OS) const8017fa27ce4SDimitry Andric void LVCodeViewReader::print(raw_ostream &OS) const {
8027fa27ce4SDimitry Andric   LLVM_DEBUG(dbgs() << "CreateReaders\n");
8037fa27ce4SDimitry Andric }
8047fa27ce4SDimitry Andric 
mapRangeAddress(const ObjectFile & Obj,const SectionRef & Section,bool IsComdat)8057fa27ce4SDimitry Andric void LVCodeViewReader::mapRangeAddress(const ObjectFile &Obj,
8067fa27ce4SDimitry Andric                                        const SectionRef &Section,
8077fa27ce4SDimitry Andric                                        bool IsComdat) {
8087fa27ce4SDimitry Andric   if (!Obj.isCOFF())
8097fa27ce4SDimitry Andric     return;
8107fa27ce4SDimitry Andric 
8117fa27ce4SDimitry Andric   const COFFObjectFile *Object = cast<COFFObjectFile>(&Obj);
8127fa27ce4SDimitry Andric 
8137fa27ce4SDimitry Andric   for (const SymbolRef &Sym : Object->symbols()) {
8147fa27ce4SDimitry Andric     if (!Section.containsSymbol(Sym))
8157fa27ce4SDimitry Andric       continue;
8167fa27ce4SDimitry Andric 
8177fa27ce4SDimitry Andric     COFFSymbolRef Symbol = Object->getCOFFSymbol(Sym);
8187fa27ce4SDimitry Andric     if (Symbol.getComplexType() != llvm::COFF::IMAGE_SYM_DTYPE_FUNCTION)
8197fa27ce4SDimitry Andric       continue;
8207fa27ce4SDimitry Andric 
8217fa27ce4SDimitry Andric     StringRef SymbolName;
8227fa27ce4SDimitry Andric     Expected<StringRef> SymNameOrErr = Object->getSymbolName(Symbol);
8237fa27ce4SDimitry Andric     if (!SymNameOrErr) {
8247fa27ce4SDimitry Andric       W.startLine() << "Invalid symbol name: " << Symbol.getSectionNumber()
8257fa27ce4SDimitry Andric                     << "\n";
8267fa27ce4SDimitry Andric       consumeError(SymNameOrErr.takeError());
8277fa27ce4SDimitry Andric       continue;
8287fa27ce4SDimitry Andric     }
8297fa27ce4SDimitry Andric     SymbolName = *SymNameOrErr;
8307fa27ce4SDimitry Andric 
8317fa27ce4SDimitry Andric     LLVM_DEBUG({
8327fa27ce4SDimitry Andric       Expected<const coff_section *> SectionOrErr =
8337fa27ce4SDimitry Andric           Object->getSection(Symbol.getSectionNumber());
8347fa27ce4SDimitry Andric       if (!SectionOrErr) {
8357fa27ce4SDimitry Andric         W.startLine() << "Invalid section number: " << Symbol.getSectionNumber()
8367fa27ce4SDimitry Andric                       << "\n";
8377fa27ce4SDimitry Andric         consumeError(SectionOrErr.takeError());
8387fa27ce4SDimitry Andric         return;
8397fa27ce4SDimitry Andric       }
8407fa27ce4SDimitry Andric       W.printNumber("Section #", Symbol.getSectionNumber());
8417fa27ce4SDimitry Andric       W.printString("Name", SymbolName);
8427fa27ce4SDimitry Andric       W.printHex("Value", Symbol.getValue());
8437fa27ce4SDimitry Andric     });
8447fa27ce4SDimitry Andric 
8457fa27ce4SDimitry Andric     // Record the symbol name (linkage) and its loading address.
8467fa27ce4SDimitry Andric     addToSymbolTable(SymbolName, Symbol.getValue(), Symbol.getSectionNumber(),
8477fa27ce4SDimitry Andric                      IsComdat);
8487fa27ce4SDimitry Andric   }
8497fa27ce4SDimitry Andric }
8507fa27ce4SDimitry Andric 
createScopes(COFFObjectFile & Obj)8517fa27ce4SDimitry Andric Error LVCodeViewReader::createScopes(COFFObjectFile &Obj) {
8527fa27ce4SDimitry Andric   if (Error Err = loadTargetInfo(Obj))
8537fa27ce4SDimitry Andric     return Err;
8547fa27ce4SDimitry Andric 
8557fa27ce4SDimitry Andric   // Initialization required when processing a COFF file:
8567fa27ce4SDimitry Andric   // Cache the symbols relocations.
8577fa27ce4SDimitry Andric   // Create a mapping for virtual addresses.
8587fa27ce4SDimitry Andric   // Get the functions entry points.
8597fa27ce4SDimitry Andric   cacheRelocations();
8607fa27ce4SDimitry Andric   mapVirtualAddress(Obj);
8617fa27ce4SDimitry Andric 
8627fa27ce4SDimitry Andric   for (const SectionRef &Section : Obj.sections()) {
8637fa27ce4SDimitry Andric     Expected<StringRef> SectionNameOrErr = Section.getName();
8647fa27ce4SDimitry Andric     if (!SectionNameOrErr)
8657fa27ce4SDimitry Andric       return SectionNameOrErr.takeError();
8667fa27ce4SDimitry Andric     // .debug$T is a standard CodeView type section, while .debug$P is the
8677fa27ce4SDimitry Andric     // same format but used for MSVC precompiled header object files.
8687fa27ce4SDimitry Andric     if (*SectionNameOrErr == ".debug$T" || *SectionNameOrErr == ".debug$P")
8697fa27ce4SDimitry Andric       if (Error Err = traverseTypeSection(*SectionNameOrErr, Section))
8707fa27ce4SDimitry Andric         return Err;
8717fa27ce4SDimitry Andric   }
8727fa27ce4SDimitry Andric 
8737fa27ce4SDimitry Andric   // Process collected namespaces.
8747fa27ce4SDimitry Andric   LogicalVisitor.processNamespaces();
8757fa27ce4SDimitry Andric 
8767fa27ce4SDimitry Andric   for (const SectionRef &Section : Obj.sections()) {
8777fa27ce4SDimitry Andric     Expected<StringRef> SectionNameOrErr = Section.getName();
8787fa27ce4SDimitry Andric     if (!SectionNameOrErr)
8797fa27ce4SDimitry Andric       return SectionNameOrErr.takeError();
8807fa27ce4SDimitry Andric     if (*SectionNameOrErr == ".debug$S")
8817fa27ce4SDimitry Andric       if (Error Err = traverseSymbolSection(*SectionNameOrErr, Section))
8827fa27ce4SDimitry Andric         return Err;
8837fa27ce4SDimitry Andric   }
8847fa27ce4SDimitry Andric 
8857fa27ce4SDimitry Andric   // Check if we have to close the Compile Unit scope.
8867fa27ce4SDimitry Andric   LogicalVisitor.closeScope();
8877fa27ce4SDimitry Andric 
8887fa27ce4SDimitry Andric   // Traverse the strings recorded and transform them into filenames.
8897fa27ce4SDimitry Andric   LogicalVisitor.processFiles();
8907fa27ce4SDimitry Andric 
8917fa27ce4SDimitry Andric   // Process collected element lines.
8927fa27ce4SDimitry Andric   LogicalVisitor.processLines();
8937fa27ce4SDimitry Andric 
8947fa27ce4SDimitry Andric   // Translate composite names into a single component.
8957fa27ce4SDimitry Andric   Root->transformScopedName();
8967fa27ce4SDimitry Andric   return Error::success();
8977fa27ce4SDimitry Andric }
8987fa27ce4SDimitry Andric 
createScopes(PDBFile & Pdb)8997fa27ce4SDimitry Andric Error LVCodeViewReader::createScopes(PDBFile &Pdb) {
9007fa27ce4SDimitry Andric   if (Error Err = loadTargetInfo(Pdb))
9017fa27ce4SDimitry Andric     return Err;
9027fa27ce4SDimitry Andric 
9037fa27ce4SDimitry Andric   if (!Pdb.hasPDBTpiStream() || !Pdb.hasPDBDbiStream())
9047fa27ce4SDimitry Andric     return Error::success();
9057fa27ce4SDimitry Andric 
9067fa27ce4SDimitry Andric   // Open the executable associated with the PDB file and get the section
9077fa27ce4SDimitry Andric   // addresses used to calculate linear addresses for CodeView Symbols.
9087fa27ce4SDimitry Andric   if (!ExePath.empty()) {
9097fa27ce4SDimitry Andric     ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
9107fa27ce4SDimitry Andric         MemoryBuffer::getFileOrSTDIN(ExePath);
9117fa27ce4SDimitry Andric     if (BuffOrErr.getError()) {
9127fa27ce4SDimitry Andric       return createStringError(errc::bad_file_descriptor,
9137fa27ce4SDimitry Andric                                "File '%s' does not exist.", ExePath.c_str());
9147fa27ce4SDimitry Andric     }
9157fa27ce4SDimitry Andric     BinaryBuffer = std::move(BuffOrErr.get());
9167fa27ce4SDimitry Andric 
9177fa27ce4SDimitry Andric     // Check if the buffer corresponds to a PECOFF executable.
9187fa27ce4SDimitry Andric     assert(identify_magic(BinaryBuffer->getBuffer()) ==
9197fa27ce4SDimitry Andric                file_magic::pecoff_executable &&
9207fa27ce4SDimitry Andric            "Invalid PECOFF executable file.");
9217fa27ce4SDimitry Andric 
9227fa27ce4SDimitry Andric     Expected<std::unique_ptr<Binary>> BinOrErr =
9237fa27ce4SDimitry Andric         createBinary(BinaryBuffer->getMemBufferRef());
9247fa27ce4SDimitry Andric     if (errorToErrorCode(BinOrErr.takeError())) {
9257fa27ce4SDimitry Andric       return createStringError(errc::not_supported,
9267fa27ce4SDimitry Andric                                "Binary object format in '%s' is not supported.",
9277fa27ce4SDimitry Andric                                ExePath.c_str());
9287fa27ce4SDimitry Andric     }
9297fa27ce4SDimitry Andric     BinaryExecutable = std::move(*BinOrErr);
9307fa27ce4SDimitry Andric     if (COFFObjectFile *COFFObject =
9317fa27ce4SDimitry Andric             dyn_cast<COFFObjectFile>(BinaryExecutable.get()))
9327fa27ce4SDimitry Andric       mapVirtualAddress(*COFFObject);
9337fa27ce4SDimitry Andric   }
9347fa27ce4SDimitry Andric 
9357fa27ce4SDimitry Andric   // In order to generate a full logical view, we have to traverse both
9367fa27ce4SDimitry Andric   // streams TPI and IPI if they are present. The following table gives
9377fa27ce4SDimitry Andric   // the stream where a specified type is located. If the IPI stream is
9387fa27ce4SDimitry Andric   // not present, all the types are located in the TPI stream.
9397fa27ce4SDimitry Andric   //
9407fa27ce4SDimitry Andric   // TPI Stream:
9417fa27ce4SDimitry Andric   //   LF_POINTER   LF_MODIFIER     LF_PROCEDURE    LF_MFUNCTION
9427fa27ce4SDimitry Andric   //   LF_LABEL     LF_ARGLIST      LF_FIELDLIST    LF_ARRAY
9437fa27ce4SDimitry Andric   //   LF_CLASS     LF_STRUCTURE    LF_INTERFACE    LF_UNION
9447fa27ce4SDimitry Andric   //   LF_ENUM      LF_TYPESERVER2  LF_VFTABLE      LF_VTSHAPE
9457fa27ce4SDimitry Andric   //   LF_BITFIELD  LF_METHODLIST   LF_PRECOMP      LF_ENDPRECOMP
9467fa27ce4SDimitry Andric   //
9477fa27ce4SDimitry Andric   // IPI stream:
9487fa27ce4SDimitry Andric   //   LF_FUNC_ID           LF_MFUNC_ID   LF_BUILDINFO
9497fa27ce4SDimitry Andric   //   LF_SUBSTR_LIST       LF_STRING_ID  LF_UDT_SRC_LINE
9507fa27ce4SDimitry Andric   //   LF_UDT_MOD_SRC_LINE
9517fa27ce4SDimitry Andric 
9527fa27ce4SDimitry Andric   LazyRandomTypeCollection &Types = types();
9537fa27ce4SDimitry Andric   LazyRandomTypeCollection &Ids = ids();
9547fa27ce4SDimitry Andric   if (Error Err = traverseTypes(Pdb, Types, Ids))
9557fa27ce4SDimitry Andric     return Err;
9567fa27ce4SDimitry Andric 
9577fa27ce4SDimitry Andric   // Process collected namespaces.
9587fa27ce4SDimitry Andric   LogicalVisitor.processNamespaces();
9597fa27ce4SDimitry Andric 
9607fa27ce4SDimitry Andric   LLVM_DEBUG({ W.getOStream() << "Traversing inlined lines\n"; });
9617fa27ce4SDimitry Andric 
9627fa27ce4SDimitry Andric   auto VisitInlineeLines = [&](int32_t Modi, const SymbolGroup &SG,
9637fa27ce4SDimitry Andric                                DebugInlineeLinesSubsectionRef &Lines) -> Error {
9647fa27ce4SDimitry Andric     return collectInlineeInfo(Lines, &SG);
9657fa27ce4SDimitry Andric   };
9667fa27ce4SDimitry Andric 
9677fa27ce4SDimitry Andric   FilterOptions Filters = {};
9687fa27ce4SDimitry Andric   LinePrinter Printer(/*Indent=*/2, false, nulls(), Filters);
9697fa27ce4SDimitry Andric   const PrintScope HeaderScope(Printer, /*IndentLevel=*/2);
9707fa27ce4SDimitry Andric   if (Error Err = iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
9717fa27ce4SDimitry Andric           Input, HeaderScope, VisitInlineeLines))
9727fa27ce4SDimitry Andric     return Err;
9737fa27ce4SDimitry Andric 
9747fa27ce4SDimitry Andric   // Traverse global symbols.
9757fa27ce4SDimitry Andric   LLVM_DEBUG({ W.getOStream() << "Traversing global symbols\n"; });
9767fa27ce4SDimitry Andric   if (Pdb.hasPDBGlobalsStream()) {
9777fa27ce4SDimitry Andric     Expected<GlobalsStream &> GlobalsOrErr = Pdb.getPDBGlobalsStream();
9787fa27ce4SDimitry Andric     if (!GlobalsOrErr)
9797fa27ce4SDimitry Andric       return GlobalsOrErr.takeError();
9807fa27ce4SDimitry Andric     GlobalsStream &Globals = *GlobalsOrErr;
9817fa27ce4SDimitry Andric     const GSIHashTable &Table = Globals.getGlobalsTable();
9827fa27ce4SDimitry Andric     Expected<SymbolStream &> ExpectedSyms = Pdb.getPDBSymbolStream();
9837fa27ce4SDimitry Andric     if (ExpectedSyms) {
9847fa27ce4SDimitry Andric 
9857fa27ce4SDimitry Andric       SymbolVisitorCallbackPipeline Pipeline;
9867fa27ce4SDimitry Andric       SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
9877fa27ce4SDimitry Andric       LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr,
9887fa27ce4SDimitry Andric                                 LogicalVisitor.getShared());
9897fa27ce4SDimitry Andric 
9907fa27ce4SDimitry Andric       // As the global symbols do not have an associated Compile Unit, create
9917fa27ce4SDimitry Andric       // one, as the container for all global symbols.
9927fa27ce4SDimitry Andric       RecordPrefix Prefix(SymbolKind::S_COMPILE3);
9937fa27ce4SDimitry Andric       CVSymbol Symbol(&Prefix, sizeof(Prefix));
9947fa27ce4SDimitry Andric       uint32_t Offset = 0;
9957fa27ce4SDimitry Andric       if (Error Err = Traverser.visitSymbolBegin(Symbol, Offset))
9967fa27ce4SDimitry Andric         consumeError(std::move(Err));
9977fa27ce4SDimitry Andric       else {
9987fa27ce4SDimitry Andric         // The CodeView compile unit containing the global symbols does not
9997fa27ce4SDimitry Andric         // have a name; generate one using its parent name (object filename)
10007fa27ce4SDimitry Andric         // follow by the '_global' string.
10017fa27ce4SDimitry Andric         std::string Name(CompileUnit->getParentScope()->getName());
10027fa27ce4SDimitry Andric         CompileUnit->setName(Name.append("_global"));
10037fa27ce4SDimitry Andric 
10047fa27ce4SDimitry Andric         Pipeline.addCallbackToPipeline(Deserializer);
10057fa27ce4SDimitry Andric         Pipeline.addCallbackToPipeline(Traverser);
10067fa27ce4SDimitry Andric         CVSymbolVisitor Visitor(Pipeline);
10077fa27ce4SDimitry Andric 
10087fa27ce4SDimitry Andric         BinaryStreamRef SymStream =
10097fa27ce4SDimitry Andric             ExpectedSyms->getSymbolArray().getUnderlyingStream();
10107fa27ce4SDimitry Andric         for (uint32_t PubSymOff : Table) {
10117fa27ce4SDimitry Andric           Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, PubSymOff);
10127fa27ce4SDimitry Andric           if (Sym) {
10137fa27ce4SDimitry Andric             if (Error Err = Visitor.visitSymbolRecord(*Sym, PubSymOff))
10147fa27ce4SDimitry Andric               return createStringError(errorToErrorCode(std::move(Err)),
10157fa27ce4SDimitry Andric                                        getFileName());
10167fa27ce4SDimitry Andric           } else {
10177fa27ce4SDimitry Andric             consumeError(Sym.takeError());
10187fa27ce4SDimitry Andric           }
10197fa27ce4SDimitry Andric         }
10207fa27ce4SDimitry Andric       }
10217fa27ce4SDimitry Andric 
10227fa27ce4SDimitry Andric       LogicalVisitor.closeScope();
10237fa27ce4SDimitry Andric     } else {
10247fa27ce4SDimitry Andric       consumeError(ExpectedSyms.takeError());
10257fa27ce4SDimitry Andric     }
10267fa27ce4SDimitry Andric   }
10277fa27ce4SDimitry Andric 
10287fa27ce4SDimitry Andric   // Traverse symbols (DBI).
10297fa27ce4SDimitry Andric   LLVM_DEBUG({ W.getOStream() << "Traversing symbol groups\n"; });
10307fa27ce4SDimitry Andric 
10317fa27ce4SDimitry Andric   auto VisitSymbolGroup = [&](uint32_t Modi, const SymbolGroup &SG) -> Error {
10327fa27ce4SDimitry Andric     Expected<ModuleDebugStreamRef> ExpectedModS =
10337fa27ce4SDimitry Andric         getModuleDebugStream(Pdb, Modi);
10347fa27ce4SDimitry Andric     if (ExpectedModS) {
10357fa27ce4SDimitry Andric       ModuleDebugStreamRef &ModS = *ExpectedModS;
10367fa27ce4SDimitry Andric 
10377fa27ce4SDimitry Andric       LLVM_DEBUG({
10387fa27ce4SDimitry Andric         W.getOStream() << formatv("Traversing Group: Mod {0:4}\n", Modi);
10397fa27ce4SDimitry Andric       });
10407fa27ce4SDimitry Andric 
10417fa27ce4SDimitry Andric       SymbolVisitorCallbackPipeline Pipeline;
10427fa27ce4SDimitry Andric       SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
10437fa27ce4SDimitry Andric       LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr,
10447fa27ce4SDimitry Andric                                 LogicalVisitor.getShared());
10457fa27ce4SDimitry Andric 
10467fa27ce4SDimitry Andric       Pipeline.addCallbackToPipeline(Deserializer);
10477fa27ce4SDimitry Andric       Pipeline.addCallbackToPipeline(Traverser);
10487fa27ce4SDimitry Andric       CVSymbolVisitor Visitor(Pipeline);
10497fa27ce4SDimitry Andric       BinarySubstreamRef SS = ModS.getSymbolsSubstream();
10507fa27ce4SDimitry Andric       if (Error Err =
10517fa27ce4SDimitry Andric               Visitor.visitSymbolStream(ModS.getSymbolArray(), SS.Offset))
10527fa27ce4SDimitry Andric         return createStringError(errorToErrorCode(std::move(Err)),
10537fa27ce4SDimitry Andric                                  getFileName());
10547fa27ce4SDimitry Andric     } else {
10557fa27ce4SDimitry Andric       // If the module stream does not exist, it is not an error condition.
10567fa27ce4SDimitry Andric       consumeError(ExpectedModS.takeError());
10577fa27ce4SDimitry Andric     }
10587fa27ce4SDimitry Andric 
10597fa27ce4SDimitry Andric     return Error::success();
10607fa27ce4SDimitry Andric   };
10617fa27ce4SDimitry Andric 
10627fa27ce4SDimitry Andric   if (Error Err = iterateSymbolGroups(Input, HeaderScope, VisitSymbolGroup))
10637fa27ce4SDimitry Andric     return Err;
10647fa27ce4SDimitry Andric 
10657fa27ce4SDimitry Andric   // At this stage, the logical view contains all scopes, symbols and types.
10667fa27ce4SDimitry Andric   // For PDBs we can use the module id, to access its specific compile unit.
10677fa27ce4SDimitry Andric   // The line record addresses has been already resolved, so we can apply the
10687fa27ce4SDimitry Andric   // flow as when processing DWARF.
10697fa27ce4SDimitry Andric 
10707fa27ce4SDimitry Andric   LLVM_DEBUG({ W.getOStream() << "Traversing lines\n"; });
10717fa27ce4SDimitry Andric 
10727fa27ce4SDimitry Andric   // Record all line records for a Compile Unit.
10737fa27ce4SDimitry Andric   CULines.clear();
10747fa27ce4SDimitry Andric 
10757fa27ce4SDimitry Andric   auto VisitDebugLines = [this](int32_t Modi, const SymbolGroup &SG,
10767fa27ce4SDimitry Andric                                 DebugLinesSubsectionRef &Lines) -> Error {
10777fa27ce4SDimitry Andric     if (!options().getPrintLines())
10787fa27ce4SDimitry Andric       return Error::success();
10797fa27ce4SDimitry Andric 
10807fa27ce4SDimitry Andric     uint16_t Segment = Lines.header()->RelocSegment;
10817fa27ce4SDimitry Andric     uint32_t Begin = Lines.header()->RelocOffset;
10827fa27ce4SDimitry Andric     uint32_t Size = Lines.header()->CodeSize;
10837fa27ce4SDimitry Andric 
10847fa27ce4SDimitry Andric     LLVM_DEBUG({ W.getOStream() << formatv("Modi = {0}\n", Modi); });
10857fa27ce4SDimitry Andric 
10867fa27ce4SDimitry Andric     // We have line information for a new module; finish processing the
10877fa27ce4SDimitry Andric     // collected information for the current module. Once it is done, start
10887fa27ce4SDimitry Andric     // recording the line information for the new module.
10897fa27ce4SDimitry Andric     if (CurrentModule != Modi) {
10907fa27ce4SDimitry Andric       if (Error Err = processModule())
10917fa27ce4SDimitry Andric         return Err;
10927fa27ce4SDimitry Andric       CULines.clear();
10937fa27ce4SDimitry Andric       CurrentModule = Modi;
10947fa27ce4SDimitry Andric     }
10957fa27ce4SDimitry Andric 
10967fa27ce4SDimitry Andric     for (const LineColumnEntry &Block : Lines)
10977fa27ce4SDimitry Andric       if (Error Err = createLines(Block.LineNumbers, /*Addendum=*/0, Segment,
10987fa27ce4SDimitry Andric                                   Begin, Size, Block.NameIndex, &SG))
10997fa27ce4SDimitry Andric         return Err;
11007fa27ce4SDimitry Andric 
11017fa27ce4SDimitry Andric     return Error::success();
11027fa27ce4SDimitry Andric   };
11037fa27ce4SDimitry Andric 
11047fa27ce4SDimitry Andric   if (Error Err = iterateModuleSubsections<DebugLinesSubsectionRef>(
11057fa27ce4SDimitry Andric           Input, HeaderScope, VisitDebugLines))
11067fa27ce4SDimitry Andric     return Err;
11077fa27ce4SDimitry Andric 
11087fa27ce4SDimitry Andric   // Check if we have to close the Compile Unit scope.
11097fa27ce4SDimitry Andric   LogicalVisitor.closeScope();
11107fa27ce4SDimitry Andric 
11117fa27ce4SDimitry Andric   // Process collected element lines.
11127fa27ce4SDimitry Andric   LogicalVisitor.processLines();
11137fa27ce4SDimitry Andric 
11147fa27ce4SDimitry Andric   // Translate composite names into a single component.
11157fa27ce4SDimitry Andric   Root->transformScopedName();
11167fa27ce4SDimitry Andric   return Error::success();
11177fa27ce4SDimitry Andric }
11187fa27ce4SDimitry Andric 
processModule()11197fa27ce4SDimitry Andric Error LVCodeViewReader::processModule() {
11207fa27ce4SDimitry Andric   if (LVScope *Scope = getScopeForModule(CurrentModule)) {
11217fa27ce4SDimitry Andric     CompileUnit = static_cast<LVScopeCompileUnit *>(Scope);
11227fa27ce4SDimitry Andric 
11237fa27ce4SDimitry Andric     LLVM_DEBUG({ dbgs() << "Processing Scope: " << Scope->getName() << "\n"; });
11247fa27ce4SDimitry Andric 
11257fa27ce4SDimitry Andric     // For the given compile unit, collect all scopes ranges.
11267fa27ce4SDimitry Andric     // For a complete ranges and lines mapping, the logical view support
11277fa27ce4SDimitry Andric     // needs for the compile unit to have a low and high pc values. We
11287fa27ce4SDimitry Andric     // can traverse the 'Modules' section and get the information for the
11297fa27ce4SDimitry Andric     // specific module. Another option, is from all the ranges collected
11307fa27ce4SDimitry Andric     // to take the first and last values.
11317fa27ce4SDimitry Andric     LVSectionIndex SectionIndex = DotTextSectionIndex;
11327fa27ce4SDimitry Andric     LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
11337fa27ce4SDimitry Andric     ScopesWithRanges->clear();
11347fa27ce4SDimitry Andric     CompileUnit->getRanges(*ScopesWithRanges);
11357fa27ce4SDimitry Andric     if (!ScopesWithRanges->empty())
11367fa27ce4SDimitry Andric       CompileUnit->addObject(ScopesWithRanges->getLower(),
11377fa27ce4SDimitry Andric                              ScopesWithRanges->getUpper());
11387fa27ce4SDimitry Andric     ScopesWithRanges->sort();
11397fa27ce4SDimitry Andric 
11407fa27ce4SDimitry Andric     if (Error Err = createInstructions())
11417fa27ce4SDimitry Andric       return Err;
11427fa27ce4SDimitry Andric 
11437fa27ce4SDimitry Andric     // Include lines from any inlined functions within the current function.
11447fa27ce4SDimitry Andric     includeInlineeLines(SectionIndex, Scope);
11457fa27ce4SDimitry Andric 
11467fa27ce4SDimitry Andric     processLines(&CULines, SectionIndex, nullptr);
11477fa27ce4SDimitry Andric   }
11487fa27ce4SDimitry Andric 
11497fa27ce4SDimitry Andric   return Error::success();
11507fa27ce4SDimitry Andric }
11517fa27ce4SDimitry Andric 
11527fa27ce4SDimitry Andric // In order to create the scopes, the CodeView Reader will:
11537fa27ce4SDimitry Andric // = Traverse the TPI/IPI stream (Type visitor):
11547fa27ce4SDimitry Andric // Collect forward references, scoped names, type indexes that will represent
11557fa27ce4SDimitry Andric // a logical element, strings, line records, linkage names.
11567fa27ce4SDimitry Andric // = Traverse the symbols section (Symbol visitor):
11577fa27ce4SDimitry Andric // Create the scopes tree and creates the required logical elements, by
11587fa27ce4SDimitry Andric // using the collected indexes from the type visitor.
createScopes()11597fa27ce4SDimitry Andric Error LVCodeViewReader::createScopes() {
11607fa27ce4SDimitry Andric   LLVM_DEBUG({
11617fa27ce4SDimitry Andric     W.startLine() << "\n";
11627fa27ce4SDimitry Andric     W.printString("File", getFileName().str());
11637fa27ce4SDimitry Andric     W.printString("Exe", ExePath);
11647fa27ce4SDimitry Andric     W.printString("Format", FileFormatName);
11657fa27ce4SDimitry Andric   });
11667fa27ce4SDimitry Andric 
11677fa27ce4SDimitry Andric   if (Error Err = LVReader::createScopes())
11687fa27ce4SDimitry Andric     return Err;
11697fa27ce4SDimitry Andric 
11707fa27ce4SDimitry Andric   LogicalVisitor.setRoot(Root);
11717fa27ce4SDimitry Andric 
11727fa27ce4SDimitry Andric   if (isObj()) {
11737fa27ce4SDimitry Andric     if (Error Err = createScopes(getObj()))
11747fa27ce4SDimitry Andric       return Err;
11757fa27ce4SDimitry Andric   } else {
11767fa27ce4SDimitry Andric     if (Error Err = createScopes(getPdb()))
11777fa27ce4SDimitry Andric       return Err;
11787fa27ce4SDimitry Andric   }
11797fa27ce4SDimitry Andric 
11807fa27ce4SDimitry Andric   return Error::success();
11817fa27ce4SDimitry Andric }
11827fa27ce4SDimitry Andric 
loadTargetInfo(const ObjectFile & Obj)11837fa27ce4SDimitry Andric Error LVCodeViewReader::loadTargetInfo(const ObjectFile &Obj) {
11847fa27ce4SDimitry Andric   // Detect the architecture from the object file. We usually don't need OS
11857fa27ce4SDimitry Andric   // info to lookup a target and create register info.
11867fa27ce4SDimitry Andric   Triple TT;
11877fa27ce4SDimitry Andric   TT.setArch(Triple::ArchType(Obj.getArch()));
11887fa27ce4SDimitry Andric   TT.setVendor(Triple::UnknownVendor);
11897fa27ce4SDimitry Andric   TT.setOS(Triple::UnknownOS);
11907fa27ce4SDimitry Andric 
11917fa27ce4SDimitry Andric   // Features to be passed to target/subtarget
11927fa27ce4SDimitry Andric   Expected<SubtargetFeatures> Features = Obj.getFeatures();
11937fa27ce4SDimitry Andric   SubtargetFeatures FeaturesValue;
11947fa27ce4SDimitry Andric   if (!Features) {
11957fa27ce4SDimitry Andric     consumeError(Features.takeError());
11967fa27ce4SDimitry Andric     FeaturesValue = SubtargetFeatures();
11977fa27ce4SDimitry Andric   }
11987fa27ce4SDimitry Andric   FeaturesValue = *Features;
11997fa27ce4SDimitry Andric   return loadGenericTargetInfo(TT.str(), FeaturesValue.getString());
12007fa27ce4SDimitry Andric }
12017fa27ce4SDimitry Andric 
loadTargetInfo(const PDBFile & Pdb)12027fa27ce4SDimitry Andric Error LVCodeViewReader::loadTargetInfo(const PDBFile &Pdb) {
12037fa27ce4SDimitry Andric   Triple TT;
12047fa27ce4SDimitry Andric   TT.setArch(Triple::ArchType::x86_64);
12057fa27ce4SDimitry Andric   TT.setVendor(Triple::UnknownVendor);
12067fa27ce4SDimitry Andric   TT.setOS(Triple::Win32);
12077fa27ce4SDimitry Andric 
12087fa27ce4SDimitry Andric   StringRef TheFeature = "";
12097fa27ce4SDimitry Andric 
12107fa27ce4SDimitry Andric   return loadGenericTargetInfo(TT.str(), TheFeature);
12117fa27ce4SDimitry Andric }
12127fa27ce4SDimitry Andric 
getRegisterName(LVSmall Opcode,ArrayRef<uint64_t> Operands)12137fa27ce4SDimitry Andric std::string LVCodeViewReader::getRegisterName(LVSmall Opcode,
12147fa27ce4SDimitry Andric                                               ArrayRef<uint64_t> Operands) {
12157fa27ce4SDimitry Andric   // Get Compilation Unit CPU Type.
12167fa27ce4SDimitry Andric   CPUType CPU = getCompileUnitCPUType();
12177fa27ce4SDimitry Andric   // For CodeView the register always is in Operands[0];
12187fa27ce4SDimitry Andric   RegisterId Register = (RegisterId(Operands[0]));
12197fa27ce4SDimitry Andric   return formatRegisterId(Register, CPU);
12207fa27ce4SDimitry Andric }
1221