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