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