1e7950fceSCarlos Alberto Enciso //===-- LVCodeViewReader.cpp ----------------------------------------------===// 2e7950fceSCarlos Alberto Enciso // 3e7950fceSCarlos Alberto Enciso // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e7950fceSCarlos Alberto Enciso // See https://llvm.org/LICENSE.txt for license information. 5e7950fceSCarlos Alberto Enciso // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e7950fceSCarlos Alberto Enciso // 7e7950fceSCarlos Alberto Enciso //===----------------------------------------------------------------------===// 8e7950fceSCarlos Alberto Enciso // 9e7950fceSCarlos Alberto Enciso // This implements the LVCodeViewReader class. 10e7950fceSCarlos Alberto Enciso // 11e7950fceSCarlos Alberto Enciso //===----------------------------------------------------------------------===// 12e7950fceSCarlos Alberto Enciso 13e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h" 14e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" 15e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" 16e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" 17e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" 18e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h" 19e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVLine.h" 20e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVScope.h" 21e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/DbiStream.h" 22e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" 23e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/InfoStream.h" 24e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/LinePrinter.h" 25e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 26e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/RawConstants.h" 27e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/SymbolStream.h" 28e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 29e7950fceSCarlos Alberto Enciso #include "llvm/Object/COFF.h" 30e7950fceSCarlos Alberto Enciso #include "llvm/Support/Errc.h" 31e7950fceSCarlos Alberto Enciso #include "llvm/Support/Error.h" 32e7950fceSCarlos Alberto Enciso #include "llvm/Support/FormatAdapters.h" 33e7950fceSCarlos Alberto Enciso #include "llvm/Support/FormatVariadic.h" 34e7950fceSCarlos Alberto Enciso #include "llvm/Support/WithColor.h" 35e7950fceSCarlos Alberto Enciso 36e7950fceSCarlos Alberto Enciso using namespace llvm; 37e7950fceSCarlos Alberto Enciso using namespace llvm::codeview; 38e7950fceSCarlos Alberto Enciso using namespace llvm::logicalview; 39e7950fceSCarlos Alberto Enciso using namespace llvm::msf; 40e7950fceSCarlos Alberto Enciso using namespace llvm::object; 41e7950fceSCarlos Alberto Enciso using namespace llvm::pdb; 42e7950fceSCarlos Alberto Enciso 43e7950fceSCarlos Alberto Enciso #define DEBUG_TYPE "CodeViewReader" 44e7950fceSCarlos Alberto Enciso 45e7950fceSCarlos Alberto Enciso StringRef LVCodeViewReader::getSymbolKindName(SymbolKind Kind) { 46e7950fceSCarlos Alberto Enciso switch (Kind) { 47e7950fceSCarlos Alberto Enciso #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ 48e7950fceSCarlos Alberto Enciso case EnumName: \ 49e7950fceSCarlos Alberto Enciso return #EnumName; 50e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" 51e7950fceSCarlos Alberto Enciso default: 52e7950fceSCarlos Alberto Enciso return "UnknownSym"; 53e7950fceSCarlos Alberto Enciso } 54e7950fceSCarlos Alberto Enciso llvm_unreachable("Unknown SymbolKind::Kind"); 55e7950fceSCarlos Alberto Enciso } 56e7950fceSCarlos Alberto Enciso 57e7950fceSCarlos Alberto Enciso std::string LVCodeViewReader::formatRegisterId(RegisterId Register, 58e7950fceSCarlos Alberto Enciso CPUType CPU) { 59e7950fceSCarlos Alberto Enciso #define RETURN_CASE(Enum, X, Ret) \ 60e7950fceSCarlos Alberto Enciso case Enum::X: \ 61e7950fceSCarlos Alberto Enciso return Ret; 62e7950fceSCarlos Alberto Enciso 63e7950fceSCarlos Alberto Enciso if (CPU == CPUType::ARMNT) { 64e7950fceSCarlos Alberto Enciso switch (Register) { 65e7950fceSCarlos Alberto Enciso #define CV_REGISTERS_ARM 66e7950fceSCarlos Alberto Enciso #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name) 67e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def" 68e7950fceSCarlos Alberto Enciso #undef CV_REGISTER 69e7950fceSCarlos Alberto Enciso #undef CV_REGISTERS_ARM 70e7950fceSCarlos Alberto Enciso 71e7950fceSCarlos Alberto Enciso default: 72e7950fceSCarlos Alberto Enciso break; 73e7950fceSCarlos Alberto Enciso } 74e7950fceSCarlos Alberto Enciso } else if (CPU == CPUType::ARM64) { 75e7950fceSCarlos Alberto Enciso switch (Register) { 76e7950fceSCarlos Alberto Enciso #define CV_REGISTERS_ARM64 77e7950fceSCarlos Alberto Enciso #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name) 78e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def" 79e7950fceSCarlos Alberto Enciso #undef CV_REGISTER 80e7950fceSCarlos Alberto Enciso #undef CV_REGISTERS_ARM64 81e7950fceSCarlos Alberto Enciso 82e7950fceSCarlos Alberto Enciso default: 83e7950fceSCarlos Alberto Enciso break; 84e7950fceSCarlos Alberto Enciso } 85e7950fceSCarlos Alberto Enciso } else { 86e7950fceSCarlos Alberto Enciso switch (Register) { 87e7950fceSCarlos Alberto Enciso #define CV_REGISTERS_X86 88e7950fceSCarlos Alberto Enciso #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name) 89e7950fceSCarlos Alberto Enciso #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def" 90e7950fceSCarlos Alberto Enciso #undef CV_REGISTER 91e7950fceSCarlos Alberto Enciso #undef CV_REGISTERS_X86 92e7950fceSCarlos Alberto Enciso 93e7950fceSCarlos Alberto Enciso default: 94e7950fceSCarlos Alberto Enciso break; 95e7950fceSCarlos Alberto Enciso } 96e7950fceSCarlos Alberto Enciso } 97e7950fceSCarlos Alberto Enciso return "formatUnknownEnum(Id)"; 98e7950fceSCarlos Alberto Enciso } 99e7950fceSCarlos Alberto Enciso 100e7950fceSCarlos Alberto Enciso void LVCodeViewReader::printRelocatedField(StringRef Label, 101e7950fceSCarlos Alberto Enciso const coff_section *CoffSection, 102e7950fceSCarlos Alberto Enciso uint32_t RelocOffset, 103e7950fceSCarlos Alberto Enciso uint32_t Offset, 104e7950fceSCarlos Alberto Enciso StringRef *RelocSym) { 105e7950fceSCarlos Alberto Enciso StringRef SymStorage; 106e7950fceSCarlos Alberto Enciso StringRef &Symbol = RelocSym ? *RelocSym : SymStorage; 107e7950fceSCarlos Alberto Enciso if (!resolveSymbolName(CoffSection, RelocOffset, Symbol)) 108e7950fceSCarlos Alberto Enciso W.printSymbolOffset(Label, Symbol, Offset); 109e7950fceSCarlos Alberto Enciso else 110e7950fceSCarlos Alberto Enciso W.printHex(Label, RelocOffset); 111e7950fceSCarlos Alberto Enciso } 112e7950fceSCarlos Alberto Enciso 113e7950fceSCarlos Alberto Enciso void LVCodeViewReader::getLinkageName(const coff_section *CoffSection, 114e7950fceSCarlos Alberto Enciso uint32_t RelocOffset, uint32_t Offset, 115e7950fceSCarlos Alberto Enciso StringRef *RelocSym) { 116e7950fceSCarlos Alberto Enciso StringRef SymStorage; 117e7950fceSCarlos Alberto Enciso StringRef &Symbol = RelocSym ? *RelocSym : SymStorage; 118e7950fceSCarlos Alberto Enciso if (resolveSymbolName(CoffSection, RelocOffset, Symbol)) 119e7950fceSCarlos Alberto Enciso Symbol = ""; 120e7950fceSCarlos Alberto Enciso } 121e7950fceSCarlos Alberto Enciso 122e7950fceSCarlos Alberto Enciso Expected<StringRef> 123e7950fceSCarlos Alberto Enciso LVCodeViewReader::getFileNameForFileOffset(uint32_t FileOffset, 124e7950fceSCarlos Alberto Enciso const SymbolGroup *SG) { 125e7950fceSCarlos Alberto Enciso if (SG) { 126e7950fceSCarlos Alberto Enciso Expected<StringRef> Filename = SG->getNameFromChecksums(FileOffset); 127e7950fceSCarlos Alberto Enciso if (!Filename) { 128e7950fceSCarlos Alberto Enciso consumeError(Filename.takeError()); 129e7950fceSCarlos Alberto Enciso return StringRef(""); 130e7950fceSCarlos Alberto Enciso } 131e7950fceSCarlos Alberto Enciso return *Filename; 132e7950fceSCarlos Alberto Enciso } 133e7950fceSCarlos Alberto Enciso 134e7950fceSCarlos Alberto Enciso // The file checksum subsection should precede all references to it. 135e7950fceSCarlos Alberto Enciso if (!CVFileChecksumTable.valid() || !CVStringTable.valid()) 136e7950fceSCarlos Alberto Enciso return createStringError(object_error::parse_failed, getFileName()); 137e7950fceSCarlos Alberto Enciso 138e7950fceSCarlos Alberto Enciso VarStreamArray<FileChecksumEntry>::Iterator Iter = 139e7950fceSCarlos Alberto Enciso CVFileChecksumTable.getArray().at(FileOffset); 140e7950fceSCarlos Alberto Enciso 141e7950fceSCarlos Alberto Enciso // Check if the file checksum table offset is valid. 142e7950fceSCarlos Alberto Enciso if (Iter == CVFileChecksumTable.end()) 143e7950fceSCarlos Alberto Enciso return createStringError(object_error::parse_failed, getFileName()); 144e7950fceSCarlos Alberto Enciso 145e7950fceSCarlos Alberto Enciso Expected<StringRef> NameOrErr = CVStringTable.getString(Iter->FileNameOffset); 146e7950fceSCarlos Alberto Enciso if (!NameOrErr) 147e7950fceSCarlos Alberto Enciso return createStringError(object_error::parse_failed, getFileName()); 148e7950fceSCarlos Alberto Enciso return *NameOrErr; 149e7950fceSCarlos Alberto Enciso } 150e7950fceSCarlos Alberto Enciso 151e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::printFileNameForOffset(StringRef Label, 152e7950fceSCarlos Alberto Enciso uint32_t FileOffset, 153e7950fceSCarlos Alberto Enciso const SymbolGroup *SG) { 154e7950fceSCarlos Alberto Enciso Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset, SG); 155e7950fceSCarlos Alberto Enciso if (!NameOrErr) 156e7950fceSCarlos Alberto Enciso return NameOrErr.takeError(); 157e7950fceSCarlos Alberto Enciso W.printHex(Label, *NameOrErr, FileOffset); 158e7950fceSCarlos Alberto Enciso return Error::success(); 159e7950fceSCarlos Alberto Enciso } 160e7950fceSCarlos Alberto Enciso 161e7950fceSCarlos Alberto Enciso void LVCodeViewReader::cacheRelocations() { 162e7950fceSCarlos Alberto Enciso for (const SectionRef &Section : getObj().sections()) { 163e7950fceSCarlos Alberto Enciso const coff_section *CoffSection = getObj().getCOFFSection(Section); 164e7950fceSCarlos Alberto Enciso 165e7950fceSCarlos Alberto Enciso for (const RelocationRef &Relocacion : Section.relocations()) 166e7950fceSCarlos Alberto Enciso RelocMap[CoffSection].push_back(Relocacion); 167e7950fceSCarlos Alberto Enciso 168e7950fceSCarlos Alberto Enciso // Sort relocations by address. 169e7950fceSCarlos Alberto Enciso llvm::sort(RelocMap[CoffSection], [](RelocationRef L, RelocationRef R) { 170e7950fceSCarlos Alberto Enciso return L.getOffset() < R.getOffset(); 171e7950fceSCarlos Alberto Enciso }); 172e7950fceSCarlos Alberto Enciso } 173e7950fceSCarlos Alberto Enciso } 174e7950fceSCarlos Alberto Enciso 175e7950fceSCarlos Alberto Enciso // Given a section and an offset into this section the function returns the 176e7950fceSCarlos Alberto Enciso // symbol used for the relocation at the offset. 177e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::resolveSymbol(const coff_section *CoffSection, 178e7950fceSCarlos Alberto Enciso uint64_t Offset, SymbolRef &Sym) { 179e7950fceSCarlos Alberto Enciso const auto &Relocations = RelocMap[CoffSection]; 180e7950fceSCarlos Alberto Enciso basic_symbol_iterator SymI = getObj().symbol_end(); 181e7950fceSCarlos Alberto Enciso for (const RelocationRef &Relocation : Relocations) { 182e7950fceSCarlos Alberto Enciso uint64_t RelocationOffset = Relocation.getOffset(); 183e7950fceSCarlos Alberto Enciso 184e7950fceSCarlos Alberto Enciso if (RelocationOffset == Offset) { 185e7950fceSCarlos Alberto Enciso SymI = Relocation.getSymbol(); 186e7950fceSCarlos Alberto Enciso break; 187e7950fceSCarlos Alberto Enciso } 188e7950fceSCarlos Alberto Enciso } 189e7950fceSCarlos Alberto Enciso if (SymI == getObj().symbol_end()) 190e7950fceSCarlos Alberto Enciso return make_error<StringError>("Unknown Symbol", inconvertibleErrorCode()); 191e7950fceSCarlos Alberto Enciso Sym = *SymI; 192e7950fceSCarlos Alberto Enciso return ErrorSuccess(); 193e7950fceSCarlos Alberto Enciso } 194e7950fceSCarlos Alberto Enciso 195e7950fceSCarlos Alberto Enciso // Given a section and an offset into this section the function returns the 196e7950fceSCarlos Alberto Enciso // name of the symbol used for the relocation at the offset. 197e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::resolveSymbolName(const coff_section *CoffSection, 198e7950fceSCarlos Alberto Enciso uint64_t Offset, StringRef &Name) { 199e7950fceSCarlos Alberto Enciso SymbolRef Symbol; 200e7950fceSCarlos Alberto Enciso if (Error E = resolveSymbol(CoffSection, Offset, Symbol)) 201e7950fceSCarlos Alberto Enciso return E; 202e7950fceSCarlos Alberto Enciso Expected<StringRef> NameOrErr = Symbol.getName(); 203e7950fceSCarlos Alberto Enciso if (!NameOrErr) 204e7950fceSCarlos Alberto Enciso return NameOrErr.takeError(); 205e7950fceSCarlos Alberto Enciso Name = *NameOrErr; 206e7950fceSCarlos Alberto Enciso return ErrorSuccess(); 207e7950fceSCarlos Alberto Enciso } 208e7950fceSCarlos Alberto Enciso 209e7950fceSCarlos Alberto Enciso // CodeView and DWARF can have references to compiler generated elements, 210e7950fceSCarlos Alberto Enciso // used for initialization. The MSVC includes in the PDBs, internal compile 211e7950fceSCarlos Alberto Enciso // units, associated with the MS runtime support. We mark them as 'system' 212e7950fceSCarlos Alberto Enciso // and they are printed only if the command line option 'internal=system'. 213e7950fceSCarlos Alberto Enciso bool LVCodeViewReader::isSystemEntry(LVElement *Element, StringRef Name) const { 214e7950fceSCarlos Alberto Enciso Name = Name.empty() ? Element->getName() : Name; 215*c6cfd535SKazu Hirata auto Find = [=](const char *String) -> bool { return Name.contains(String); }; 216e7950fceSCarlos Alberto Enciso auto Starts = [=](const char *Pattern) -> bool { 2171950190bSSimon Pilgrim return Name.starts_with(Pattern); 218e7950fceSCarlos Alberto Enciso }; 219e7950fceSCarlos Alberto Enciso auto CheckExclude = [&]() -> bool { 220e7950fceSCarlos Alberto Enciso if (Starts("__") || Starts("_PMD") || Starts("_PMFN")) 221e7950fceSCarlos Alberto Enciso return true; 222e7950fceSCarlos Alberto Enciso if (Find("_s__")) 223e7950fceSCarlos Alberto Enciso return true; 224e7950fceSCarlos Alberto Enciso if (Find("_CatchableType") || Find("_TypeDescriptor")) 225e7950fceSCarlos Alberto Enciso return true; 226e7950fceSCarlos Alberto Enciso if (Find("Intermediate\\vctools")) 227e7950fceSCarlos Alberto Enciso return true; 228e7950fceSCarlos Alberto Enciso if (Find("$initializer$") || Find("dynamic initializer")) 229e7950fceSCarlos Alberto Enciso return true; 230e7950fceSCarlos Alberto Enciso if (Find("`vftable'") || Find("_GLOBAL__sub")) 231e7950fceSCarlos Alberto Enciso return true; 232e7950fceSCarlos Alberto Enciso return false; 233e7950fceSCarlos Alberto Enciso }; 234e7950fceSCarlos Alberto Enciso bool Excluded = CheckExclude(); 235e7950fceSCarlos Alberto Enciso if (Excluded) 236e7950fceSCarlos Alberto Enciso Element->setIsSystem(); 237e7950fceSCarlos Alberto Enciso 238e7950fceSCarlos Alberto Enciso return Excluded; 239e7950fceSCarlos Alberto Enciso } 240e7950fceSCarlos Alberto Enciso 241e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::collectInlineeInfo( 242e7950fceSCarlos Alberto Enciso DebugInlineeLinesSubsectionRef &Lines, const llvm::pdb::SymbolGroup *SG) { 243e7950fceSCarlos Alberto Enciso for (const InlineeSourceLine &Line : Lines) { 244e7950fceSCarlos Alberto Enciso TypeIndex TIInlinee = Line.Header->Inlinee; 245e7950fceSCarlos Alberto Enciso uint32_t LineNumber = Line.Header->SourceLineNum; 246e7950fceSCarlos Alberto Enciso uint32_t FileOffset = Line.Header->FileID; 247e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 248e7950fceSCarlos Alberto Enciso DictScope S(W, "InlineeSourceLine"); 249e7950fceSCarlos Alberto Enciso LogicalVisitor.printTypeIndex("Inlinee", TIInlinee, StreamTPI); 250e7950fceSCarlos Alberto Enciso if (Error Err = printFileNameForOffset("FileID", FileOffset, SG)) 251e7950fceSCarlos Alberto Enciso return Err; 252e7950fceSCarlos Alberto Enciso W.printNumber("SourceLineNum", LineNumber); 253e7950fceSCarlos Alberto Enciso 254e7950fceSCarlos Alberto Enciso if (Lines.hasExtraFiles()) { 255e7950fceSCarlos Alberto Enciso W.printNumber("ExtraFileCount", Line.ExtraFiles.size()); 256e7950fceSCarlos Alberto Enciso ListScope ExtraFiles(W, "ExtraFiles"); 257e7950fceSCarlos Alberto Enciso for (const ulittle32_t &FID : Line.ExtraFiles) 258e7950fceSCarlos Alberto Enciso if (Error Err = printFileNameForOffset("FileID", FID, SG)) 259e7950fceSCarlos Alberto Enciso return Err; 260e7950fceSCarlos Alberto Enciso } 261e7950fceSCarlos Alberto Enciso }); 262e7950fceSCarlos Alberto Enciso Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset, SG); 263e7950fceSCarlos Alberto Enciso if (!NameOrErr) 264e7950fceSCarlos Alberto Enciso return NameOrErr.takeError(); 265e7950fceSCarlos Alberto Enciso LogicalVisitor.addInlineeInfo(TIInlinee, LineNumber, *NameOrErr); 266e7950fceSCarlos Alberto Enciso } 267e7950fceSCarlos Alberto Enciso 268e7950fceSCarlos Alberto Enciso return Error::success(); 269e7950fceSCarlos Alberto Enciso } 270e7950fceSCarlos Alberto Enciso 271e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::traverseInlineeLines(StringRef Subsection) { 272b8885926SKazu Hirata BinaryStreamReader SR(Subsection, llvm::endianness::little); 273e7950fceSCarlos Alberto Enciso DebugInlineeLinesSubsectionRef Lines; 274e7950fceSCarlos Alberto Enciso if (Error E = Lines.initialize(SR)) 275e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(E)), getFileName()); 276e7950fceSCarlos Alberto Enciso 277e7950fceSCarlos Alberto Enciso return collectInlineeInfo(Lines); 278e7950fceSCarlos Alberto Enciso } 279e7950fceSCarlos Alberto Enciso 280e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::createLines( 281e7950fceSCarlos Alberto Enciso const FixedStreamArray<LineNumberEntry> &LineNumbers, LVAddress Addendum, 282e7950fceSCarlos Alberto Enciso uint32_t Segment, uint32_t Begin, uint32_t Size, uint32_t NameIndex, 283e7950fceSCarlos Alberto Enciso const SymbolGroup *SG) { 284e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 285e7950fceSCarlos Alberto Enciso uint32_t End = Begin + Size; 286e7950fceSCarlos Alberto Enciso W.getOStream() << formatv("{0:x-4}:{1:x-8}-{2:x-8}\n", Segment, Begin, End); 287e7950fceSCarlos Alberto Enciso }); 288e7950fceSCarlos Alberto Enciso 289e7950fceSCarlos Alberto Enciso for (const LineNumberEntry &Line : LineNumbers) { 290e7950fceSCarlos Alberto Enciso if (Line.Offset >= Size) 291e7950fceSCarlos Alberto Enciso return createStringError(object_error::parse_failed, getFileName()); 292e7950fceSCarlos Alberto Enciso 293e7950fceSCarlos Alberto Enciso LineInfo LI(Line.Flags); 294e7950fceSCarlos Alberto Enciso 295e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 296e7950fceSCarlos Alberto Enciso W.getOStream() << formatv( 297e7950fceSCarlos Alberto Enciso "{0} {1:x-8}\n", utostr(LI.getStartLine()), 298e7950fceSCarlos Alberto Enciso fmt_align(Begin + Line.Offset, AlignStyle::Right, 8, '0')); 299e7950fceSCarlos Alberto Enciso }); 300e7950fceSCarlos Alberto Enciso 301e7950fceSCarlos Alberto Enciso // The 'processLines()' function will move each created logical line 302e7950fceSCarlos Alberto Enciso // to its enclosing logical scope, using the debug ranges information 303e7950fceSCarlos Alberto Enciso // and they will be released when its scope parent is deleted. 304e7950fceSCarlos Alberto Enciso LVLineDebug *LineDebug = createLineDebug(); 305e7950fceSCarlos Alberto Enciso CULines.push_back(LineDebug); 306e7950fceSCarlos Alberto Enciso LVAddress Address = linearAddress(Segment, Begin + Line.Offset); 307e7950fceSCarlos Alberto Enciso LineDebug->setAddress(Address + Addendum); 308e7950fceSCarlos Alberto Enciso 309e7950fceSCarlos Alberto Enciso if (LI.isAlwaysStepInto()) 310e7950fceSCarlos Alberto Enciso LineDebug->setIsAlwaysStepInto(); 311e7950fceSCarlos Alberto Enciso else if (LI.isNeverStepInto()) 312e7950fceSCarlos Alberto Enciso LineDebug->setIsNeverStepInto(); 313e7950fceSCarlos Alberto Enciso else 314e7950fceSCarlos Alberto Enciso LineDebug->setLineNumber(LI.getStartLine()); 315e7950fceSCarlos Alberto Enciso 316e7950fceSCarlos Alberto Enciso if (LI.isStatement()) 317e7950fceSCarlos Alberto Enciso LineDebug->setIsNewStatement(); 318e7950fceSCarlos Alberto Enciso 319e7950fceSCarlos Alberto Enciso Expected<StringRef> NameOrErr = getFileNameForFileOffset(NameIndex, SG); 320e7950fceSCarlos Alberto Enciso if (!NameOrErr) 321e7950fceSCarlos Alberto Enciso return NameOrErr.takeError(); 322e7950fceSCarlos Alberto Enciso LineDebug->setFilename(*NameOrErr); 323e7950fceSCarlos Alberto Enciso } 324e7950fceSCarlos Alberto Enciso 325e7950fceSCarlos Alberto Enciso return Error::success(); 326e7950fceSCarlos Alberto Enciso } 327e7950fceSCarlos Alberto Enciso 328e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::initializeFileAndStringTables( 329e7950fceSCarlos Alberto Enciso BinaryStreamReader &Reader) { 330e7950fceSCarlos Alberto Enciso while (Reader.bytesRemaining() > 0 && 331e7950fceSCarlos Alberto Enciso (!CVFileChecksumTable.valid() || !CVStringTable.valid())) { 332e7950fceSCarlos Alberto Enciso // The section consists of a number of subsection in the following format: 333e7950fceSCarlos Alberto Enciso // |SubSectionType|SubSectionSize|Contents...| 334e7950fceSCarlos Alberto Enciso uint32_t SubType, SubSectionSize; 335e7950fceSCarlos Alberto Enciso 336e7950fceSCarlos Alberto Enciso if (Error E = Reader.readInteger(SubType)) 337e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(E)), getFileName()); 338e7950fceSCarlos Alberto Enciso if (Error E = Reader.readInteger(SubSectionSize)) 339e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(E)), getFileName()); 340e7950fceSCarlos Alberto Enciso 341e7950fceSCarlos Alberto Enciso StringRef Contents; 342e7950fceSCarlos Alberto Enciso if (Error E = Reader.readFixedString(Contents, SubSectionSize)) 343e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(E)), getFileName()); 344e7950fceSCarlos Alberto Enciso 3454a0ccfa8SKazu Hirata BinaryStreamRef ST(Contents, llvm::endianness::little); 346e7950fceSCarlos Alberto Enciso switch (DebugSubsectionKind(SubType)) { 347e7950fceSCarlos Alberto Enciso case DebugSubsectionKind::FileChecksums: 348e7950fceSCarlos Alberto Enciso if (Error E = CVFileChecksumTable.initialize(ST)) 349e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(E)), getFileName()); 350e7950fceSCarlos Alberto Enciso break; 351e7950fceSCarlos Alberto Enciso case DebugSubsectionKind::StringTable: 352e7950fceSCarlos Alberto Enciso if (Error E = CVStringTable.initialize(ST)) 353e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(E)), getFileName()); 354e7950fceSCarlos Alberto Enciso break; 355e7950fceSCarlos Alberto Enciso default: 356e7950fceSCarlos Alberto Enciso break; 357e7950fceSCarlos Alberto Enciso } 358e7950fceSCarlos Alberto Enciso 359e7950fceSCarlos Alberto Enciso uint32_t PaddedSize = alignTo(SubSectionSize, 4); 360e7950fceSCarlos Alberto Enciso if (Error E = Reader.skip(PaddedSize - SubSectionSize)) 361e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(E)), getFileName()); 362e7950fceSCarlos Alberto Enciso } 363e7950fceSCarlos Alberto Enciso 364e7950fceSCarlos Alberto Enciso return Error::success(); 365e7950fceSCarlos Alberto Enciso } 366e7950fceSCarlos Alberto Enciso 367e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::loadTypeServer(TypeServer2Record &TS) { 368e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 369e7950fceSCarlos Alberto Enciso W.printString("Guid", formatv("{0}", TS.getGuid()).str()); 370e7950fceSCarlos Alberto Enciso W.printNumber("Age", TS.getAge()); 371e7950fceSCarlos Alberto Enciso W.printString("Name", TS.getName()); 372e7950fceSCarlos Alberto Enciso }); 373e7950fceSCarlos Alberto Enciso 374e7950fceSCarlos Alberto Enciso SmallString<128> ServerName(TS.getName()); 375e7950fceSCarlos Alberto Enciso BuffOrErr = MemoryBuffer::getFile(ServerName); 376e7950fceSCarlos Alberto Enciso if (BuffOrErr.getError()) { 377e7950fceSCarlos Alberto Enciso // The server name does not exist. Try in the same directory as the 378e7950fceSCarlos Alberto Enciso // input file. 379e7950fceSCarlos Alberto Enciso ServerName = createAlternativePath(ServerName); 380e7950fceSCarlos Alberto Enciso BuffOrErr = MemoryBuffer::getFile(ServerName); 381e7950fceSCarlos Alberto Enciso if (BuffOrErr.getError()) { 382e7950fceSCarlos Alberto Enciso // For the error message, use the original type server name. 383e7950fceSCarlos Alberto Enciso return createStringError(errc::bad_file_descriptor, 384e7950fceSCarlos Alberto Enciso "File '%s' does not exist.", 385e7950fceSCarlos Alberto Enciso TS.getName().str().c_str()); 386e7950fceSCarlos Alberto Enciso } 387e7950fceSCarlos Alberto Enciso } 388e7950fceSCarlos Alberto Enciso MemBuffer = std::move(BuffOrErr.get()); 389e7950fceSCarlos Alberto Enciso 390e7950fceSCarlos Alberto Enciso // Check if the buffer corresponds to a PDB file. 391e7950fceSCarlos Alberto Enciso assert(identify_magic((*MemBuffer).getBuffer()) == file_magic::pdb && 392e7950fceSCarlos Alberto Enciso "Invalid PDB file."); 393e7950fceSCarlos Alberto Enciso 394e7950fceSCarlos Alberto Enciso if (Error Err = loadDataForPDB(PDB_ReaderType::Native, ServerName, Session)) 395e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(Err)), "%s", 396e7950fceSCarlos Alberto Enciso ServerName.c_str()); 397e7950fceSCarlos Alberto Enciso 398e7950fceSCarlos Alberto Enciso PdbSession.reset(static_cast<NativeSession *>(Session.release())); 399e7950fceSCarlos Alberto Enciso PDBFile &Pdb = PdbSession->getPDBFile(); 400e7950fceSCarlos Alberto Enciso 401e7950fceSCarlos Alberto Enciso // Just because a file with a matching name was found and it was an actual 402e7950fceSCarlos Alberto Enciso // PDB file doesn't mean it matches. For it to match the InfoStream's GUID 403e7950fceSCarlos Alberto Enciso // must match the GUID specified in the TypeServer2 record. 404e7950fceSCarlos Alberto Enciso Expected<InfoStream &> expectedInfo = Pdb.getPDBInfoStream(); 405e7950fceSCarlos Alberto Enciso if (!expectedInfo || expectedInfo->getGuid() != TS.getGuid()) 406e7950fceSCarlos Alberto Enciso return createStringError(errc::invalid_argument, "signature_out_of_date"); 407e7950fceSCarlos Alberto Enciso 408e7950fceSCarlos Alberto Enciso // The reader needs to switch to a type server, to process the types from 409e7950fceSCarlos Alberto Enciso // the server. We need to keep the original input source, as reading other 410e7950fceSCarlos Alberto Enciso // sections will require the input associated with the loaded object file. 411e7950fceSCarlos Alberto Enciso TypeServer = std::make_shared<InputFile>(&Pdb); 412e7950fceSCarlos Alberto Enciso LogicalVisitor.setInput(TypeServer); 413e7950fceSCarlos Alberto Enciso 414e7950fceSCarlos Alberto Enciso LazyRandomTypeCollection &Types = types(); 415e7950fceSCarlos Alberto Enciso LazyRandomTypeCollection &Ids = ids(); 416e7950fceSCarlos Alberto Enciso if (Error Err = traverseTypes(Pdb, Types, Ids)) 417e7950fceSCarlos Alberto Enciso return Err; 418e7950fceSCarlos Alberto Enciso 419e7950fceSCarlos Alberto Enciso return Error::success(); 420e7950fceSCarlos Alberto Enciso } 421e7950fceSCarlos Alberto Enciso 422e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::loadPrecompiledObject(PrecompRecord &Precomp, 423e7950fceSCarlos Alberto Enciso CVTypeArray &CVTypesObj) { 424e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 425e7950fceSCarlos Alberto Enciso W.printHex("Count", Precomp.getTypesCount()); 426e7950fceSCarlos Alberto Enciso W.printHex("Signature", Precomp.getSignature()); 427e7950fceSCarlos Alberto Enciso W.printString("PrecompFile", Precomp.getPrecompFilePath()); 428e7950fceSCarlos Alberto Enciso }); 429e7950fceSCarlos Alberto Enciso 430e7950fceSCarlos Alberto Enciso SmallString<128> ServerName(Precomp.getPrecompFilePath()); 431e7950fceSCarlos Alberto Enciso BuffOrErr = MemoryBuffer::getFile(ServerName); 432e7950fceSCarlos Alberto Enciso if (BuffOrErr.getError()) { 433e7950fceSCarlos Alberto Enciso // The server name does not exist. Try in the directory as the input file. 434e7950fceSCarlos Alberto Enciso ServerName = createAlternativePath(ServerName); 435e7950fceSCarlos Alberto Enciso if (BuffOrErr.getError()) { 436e7950fceSCarlos Alberto Enciso // For the error message, use the original type server name. 437e7950fceSCarlos Alberto Enciso return createStringError(errc::bad_file_descriptor, 438e7950fceSCarlos Alberto Enciso "File '%s' does not exist.", 439e7950fceSCarlos Alberto Enciso Precomp.getPrecompFilePath().str().c_str()); 440e7950fceSCarlos Alberto Enciso } 441e7950fceSCarlos Alberto Enciso } 442e7950fceSCarlos Alberto Enciso MemBuffer = std::move(BuffOrErr.get()); 443e7950fceSCarlos Alberto Enciso 444e7950fceSCarlos Alberto Enciso Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(*MemBuffer); 445e7950fceSCarlos Alberto Enciso if (errorToErrorCode(BinOrErr.takeError())) 446e7950fceSCarlos Alberto Enciso return createStringError(errc::not_supported, 447e7950fceSCarlos Alberto Enciso "Binary object format in '%s' is not supported.", 448e7950fceSCarlos Alberto Enciso ServerName.c_str()); 449e7950fceSCarlos Alberto Enciso 450e7950fceSCarlos Alberto Enciso Binary &BinaryObj = *BinOrErr.get(); 451e7950fceSCarlos Alberto Enciso if (!BinaryObj.isCOFF()) 452e7950fceSCarlos Alberto Enciso return createStringError(errc::not_supported, "'%s' is not a COFF object.", 453e7950fceSCarlos Alberto Enciso ServerName.c_str()); 454e7950fceSCarlos Alberto Enciso 455e7950fceSCarlos Alberto Enciso Builder = std::make_unique<AppendingTypeTableBuilder>(BuilderAllocator); 456e7950fceSCarlos Alberto Enciso 457e7950fceSCarlos Alberto Enciso // The MSVC precompiled header object file, should contain just a single 458e7950fceSCarlos Alberto Enciso // ".debug$P" section. 459e7950fceSCarlos Alberto Enciso COFFObjectFile &Obj = *cast<COFFObjectFile>(&BinaryObj); 460e7950fceSCarlos Alberto Enciso for (const SectionRef &Section : Obj.sections()) { 461e7950fceSCarlos Alberto Enciso Expected<StringRef> SectionNameOrErr = Section.getName(); 462e7950fceSCarlos Alberto Enciso if (!SectionNameOrErr) 463e7950fceSCarlos Alberto Enciso return SectionNameOrErr.takeError(); 464e7950fceSCarlos Alberto Enciso if (*SectionNameOrErr == ".debug$P") { 465e7950fceSCarlos Alberto Enciso Expected<StringRef> DataOrErr = Section.getContents(); 466e7950fceSCarlos Alberto Enciso if (!DataOrErr) 467e7950fceSCarlos Alberto Enciso return DataOrErr.takeError(); 468e7950fceSCarlos Alberto Enciso uint32_t Magic; 469e7950fceSCarlos Alberto Enciso if (Error Err = consume(*DataOrErr, Magic)) 470e7950fceSCarlos Alberto Enciso return Err; 471e7950fceSCarlos Alberto Enciso if (Magic != COFF::DEBUG_SECTION_MAGIC) 472e7950fceSCarlos Alberto Enciso return errorCodeToError(object_error::parse_failed); 473e7950fceSCarlos Alberto Enciso 4744a0ccfa8SKazu Hirata ReaderPrecomp = std::make_unique<BinaryStreamReader>( 4754a0ccfa8SKazu Hirata *DataOrErr, llvm::endianness::little); 476e7950fceSCarlos Alberto Enciso cantFail( 477e7950fceSCarlos Alberto Enciso ReaderPrecomp->readArray(CVTypesPrecomp, ReaderPrecomp->getLength())); 478e7950fceSCarlos Alberto Enciso 479e7950fceSCarlos Alberto Enciso // Append all the type records up to the LF_ENDPRECOMP marker and 480e7950fceSCarlos Alberto Enciso // check if the signatures match. 481e7950fceSCarlos Alberto Enciso for (const CVType &Type : CVTypesPrecomp) { 482e7950fceSCarlos Alberto Enciso ArrayRef<uint8_t> TypeData = Type.data(); 483e7950fceSCarlos Alberto Enciso if (Type.kind() == LF_ENDPRECOMP) { 484e7950fceSCarlos Alberto Enciso EndPrecompRecord EndPrecomp = cantFail( 485e7950fceSCarlos Alberto Enciso TypeDeserializer::deserializeAs<EndPrecompRecord>(TypeData)); 486e7950fceSCarlos Alberto Enciso if (Precomp.getSignature() != EndPrecomp.getSignature()) 487e7950fceSCarlos Alberto Enciso return createStringError(errc::invalid_argument, "no matching pch"); 488e7950fceSCarlos Alberto Enciso break; 489e7950fceSCarlos Alberto Enciso } 490e7950fceSCarlos Alberto Enciso Builder->insertRecordBytes(TypeData); 491e7950fceSCarlos Alberto Enciso } 492e7950fceSCarlos Alberto Enciso // Done processing .debug$P, break out of section loop. 493e7950fceSCarlos Alberto Enciso break; 494e7950fceSCarlos Alberto Enciso } 495e7950fceSCarlos Alberto Enciso } 496e7950fceSCarlos Alberto Enciso 497e7950fceSCarlos Alberto Enciso // Append all the type records, skipping the first record which is the 498e7950fceSCarlos Alberto Enciso // reference to the precompiled header object information. 499e7950fceSCarlos Alberto Enciso for (const CVType &Type : CVTypesObj) { 500e7950fceSCarlos Alberto Enciso ArrayRef<uint8_t> TypeData = Type.data(); 501e7950fceSCarlos Alberto Enciso if (Type.kind() != LF_PRECOMP) 502e7950fceSCarlos Alberto Enciso Builder->insertRecordBytes(TypeData); 503e7950fceSCarlos Alberto Enciso } 504e7950fceSCarlos Alberto Enciso 505e7950fceSCarlos Alberto Enciso // Set up a type stream that refers to the added type records. 506e7950fceSCarlos Alberto Enciso Builder->ForEachRecord( 507e7950fceSCarlos Alberto Enciso [&](TypeIndex TI, const CVType &Type) { TypeArray.push_back(Type); }); 508e7950fceSCarlos Alberto Enciso 509e7950fceSCarlos Alberto Enciso ItemStream = 510b8885926SKazu Hirata std::make_unique<BinaryItemStream<CVType>>(llvm::endianness::little); 511e7950fceSCarlos Alberto Enciso ItemStream->setItems(TypeArray); 512e7950fceSCarlos Alberto Enciso TypeStream.setUnderlyingStream(*ItemStream); 513e7950fceSCarlos Alberto Enciso 514e7950fceSCarlos Alberto Enciso PrecompHeader = 515e7950fceSCarlos Alberto Enciso std::make_shared<LazyRandomTypeCollection>(TypeStream, TypeArray.size()); 516e7950fceSCarlos Alberto Enciso 517e7950fceSCarlos Alberto Enciso // Change the original input source to use the collected type records. 518e7950fceSCarlos Alberto Enciso LogicalVisitor.setInput(PrecompHeader); 519e7950fceSCarlos Alberto Enciso 520e7950fceSCarlos Alberto Enciso LazyRandomTypeCollection &Types = types(); 521e7950fceSCarlos Alberto Enciso LazyRandomTypeCollection &Ids = ids(); 522e7950fceSCarlos Alberto Enciso LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamTPI, 523e7950fceSCarlos Alberto Enciso LogicalVisitor.getShared()); 524e7950fceSCarlos Alberto Enciso return visitTypeStream(Types, TDV); 525e7950fceSCarlos Alberto Enciso } 526e7950fceSCarlos Alberto Enciso 527e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::traverseTypeSection(StringRef SectionName, 528e7950fceSCarlos Alberto Enciso const SectionRef &Section) { 529e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 530e7950fceSCarlos Alberto Enciso ListScope D(W, "CodeViewTypes"); 531e7950fceSCarlos Alberto Enciso W.printNumber("Section", SectionName, getObj().getSectionID(Section)); 532e7950fceSCarlos Alberto Enciso }); 533e7950fceSCarlos Alberto Enciso 534e7950fceSCarlos Alberto Enciso Expected<StringRef> DataOrErr = Section.getContents(); 535e7950fceSCarlos Alberto Enciso if (!DataOrErr) 536e7950fceSCarlos Alberto Enciso return DataOrErr.takeError(); 537e7950fceSCarlos Alberto Enciso uint32_t Magic; 538e7950fceSCarlos Alberto Enciso if (Error Err = consume(*DataOrErr, Magic)) 539e7950fceSCarlos Alberto Enciso return Err; 540e7950fceSCarlos Alberto Enciso if (Magic != COFF::DEBUG_SECTION_MAGIC) 541e7950fceSCarlos Alberto Enciso return errorCodeToError(object_error::parse_failed); 542e7950fceSCarlos Alberto Enciso 543e7950fceSCarlos Alberto Enciso // Get the first type record. It will indicate if this object uses a type 544e7950fceSCarlos Alberto Enciso // server (/Zi) or a PCH file (/Yu). 545e7950fceSCarlos Alberto Enciso CVTypeArray CVTypes; 5464a0ccfa8SKazu Hirata BinaryStreamReader Reader(*DataOrErr, llvm::endianness::little); 547e7950fceSCarlos Alberto Enciso cantFail(Reader.readArray(CVTypes, Reader.getLength())); 548e7950fceSCarlos Alberto Enciso CVTypeArray::Iterator FirstType = CVTypes.begin(); 549e7950fceSCarlos Alberto Enciso 550e7950fceSCarlos Alberto Enciso // The object was compiled with /Zi. It uses types from a type server PDB. 551e7950fceSCarlos Alberto Enciso if (FirstType->kind() == LF_TYPESERVER2) { 552e7950fceSCarlos Alberto Enciso TypeServer2Record TS = cantFail( 553e7950fceSCarlos Alberto Enciso TypeDeserializer::deserializeAs<TypeServer2Record>(FirstType->data())); 554e7950fceSCarlos Alberto Enciso return loadTypeServer(TS); 555e7950fceSCarlos Alberto Enciso } 556e7950fceSCarlos Alberto Enciso 557e7950fceSCarlos Alberto Enciso // The object was compiled with /Yc or /Yu. It uses types from another 558e7950fceSCarlos Alberto Enciso // object file with a matching signature. 559e7950fceSCarlos Alberto Enciso if (FirstType->kind() == LF_PRECOMP) { 560e7950fceSCarlos Alberto Enciso PrecompRecord Precomp = cantFail( 561e7950fceSCarlos Alberto Enciso TypeDeserializer::deserializeAs<PrecompRecord>(FirstType->data())); 562e7950fceSCarlos Alberto Enciso return loadPrecompiledObject(Precomp, CVTypes); 563e7950fceSCarlos Alberto Enciso } 564e7950fceSCarlos Alberto Enciso 565e7950fceSCarlos Alberto Enciso LazyRandomTypeCollection &Types = types(); 566e7950fceSCarlos Alberto Enciso LazyRandomTypeCollection &Ids = ids(); 567e7950fceSCarlos Alberto Enciso Types.reset(*DataOrErr, 100); 568e7950fceSCarlos Alberto Enciso LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamTPI, 569e7950fceSCarlos Alberto Enciso LogicalVisitor.getShared()); 570e7950fceSCarlos Alberto Enciso return visitTypeStream(Types, TDV); 571e7950fceSCarlos Alberto Enciso } 572e7950fceSCarlos Alberto Enciso 573e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::traverseTypes(PDBFile &Pdb, 574e7950fceSCarlos Alberto Enciso LazyRandomTypeCollection &Types, 575e7950fceSCarlos Alberto Enciso LazyRandomTypeCollection &Ids) { 576e7950fceSCarlos Alberto Enciso // Traverse types (TPI and IPI). 577e7950fceSCarlos Alberto Enciso auto VisitTypes = [&](LazyRandomTypeCollection &Types, 578e7950fceSCarlos Alberto Enciso LazyRandomTypeCollection &Ids, 579e7950fceSCarlos Alberto Enciso SpecialStream StreamIdx) -> Error { 580e7950fceSCarlos Alberto Enciso LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamIdx, 581e7950fceSCarlos Alberto Enciso LogicalVisitor.getShared()); 582e7950fceSCarlos Alberto Enciso return visitTypeStream(Types, TDV); 583e7950fceSCarlos Alberto Enciso }; 584e7950fceSCarlos Alberto Enciso 585e7950fceSCarlos Alberto Enciso Expected<TpiStream &> StreamTpiOrErr = Pdb.getPDBTpiStream(); 586e7950fceSCarlos Alberto Enciso if (!StreamTpiOrErr) 587e7950fceSCarlos Alberto Enciso return StreamTpiOrErr.takeError(); 588e7950fceSCarlos Alberto Enciso TpiStream &StreamTpi = *StreamTpiOrErr; 589e7950fceSCarlos Alberto Enciso StreamTpi.buildHashMap(); 590e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 591e7950fceSCarlos Alberto Enciso W.getOStream() << formatv("Showing {0:N} TPI records\n", 592e7950fceSCarlos Alberto Enciso StreamTpi.getNumTypeRecords()); 593e7950fceSCarlos Alberto Enciso }); 594e7950fceSCarlos Alberto Enciso if (Error Err = VisitTypes(Types, Ids, StreamTPI)) 595e7950fceSCarlos Alberto Enciso return Err; 596e7950fceSCarlos Alberto Enciso 597e7950fceSCarlos Alberto Enciso Expected<TpiStream &> StreamIpiOrErr = Pdb.getPDBIpiStream(); 598e7950fceSCarlos Alberto Enciso if (!StreamIpiOrErr) 599e7950fceSCarlos Alberto Enciso return StreamIpiOrErr.takeError(); 600e7950fceSCarlos Alberto Enciso TpiStream &StreamIpi = *StreamIpiOrErr; 601e7950fceSCarlos Alberto Enciso StreamIpi.buildHashMap(); 602e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 603e7950fceSCarlos Alberto Enciso W.getOStream() << formatv("Showing {0:N} IPI records\n", 604e7950fceSCarlos Alberto Enciso StreamIpi.getNumTypeRecords()); 605e7950fceSCarlos Alberto Enciso }); 606e7950fceSCarlos Alberto Enciso return VisitTypes(Ids, Ids, StreamIPI); 607e7950fceSCarlos Alberto Enciso } 608e7950fceSCarlos Alberto Enciso 609e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::traverseSymbolsSubsection(StringRef Subsection, 610e7950fceSCarlos Alberto Enciso const SectionRef &Section, 611e7950fceSCarlos Alberto Enciso StringRef SectionContents) { 612e7950fceSCarlos Alberto Enciso ArrayRef<uint8_t> BinaryData(Subsection.bytes_begin(), 613e7950fceSCarlos Alberto Enciso Subsection.bytes_end()); 614e7950fceSCarlos Alberto Enciso LVSymbolVisitorDelegate VisitorDelegate(this, Section, &getObj(), 615e7950fceSCarlos Alberto Enciso SectionContents); 616e7950fceSCarlos Alberto Enciso CVSymbolArray Symbols; 617b8885926SKazu Hirata BinaryStreamReader Reader(BinaryData, llvm::endianness::little); 618e7950fceSCarlos Alberto Enciso if (Error E = Reader.readArray(Symbols, Reader.getLength())) 619e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(E)), getFileName()); 620e7950fceSCarlos Alberto Enciso 621e7950fceSCarlos Alberto Enciso LazyRandomTypeCollection &Types = types(); 622e7950fceSCarlos Alberto Enciso LazyRandomTypeCollection &Ids = ids(); 623e7950fceSCarlos Alberto Enciso SymbolVisitorCallbackPipeline Pipeline; 624e7950fceSCarlos Alberto Enciso SymbolDeserializer Deserializer(&VisitorDelegate, 625e7950fceSCarlos Alberto Enciso CodeViewContainer::ObjectFile); 626e7950fceSCarlos Alberto Enciso // As we are processing a COFF format, use TPI as IPI, so the generic code 627e7950fceSCarlos Alberto Enciso // to process the CodeView format does not contain any additional checks. 628e7950fceSCarlos Alberto Enciso LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, 629e7950fceSCarlos Alberto Enciso &VisitorDelegate, LogicalVisitor.getShared()); 630e7950fceSCarlos Alberto Enciso 631e7950fceSCarlos Alberto Enciso Pipeline.addCallbackToPipeline(Deserializer); 632e7950fceSCarlos Alberto Enciso Pipeline.addCallbackToPipeline(Traverser); 633e7950fceSCarlos Alberto Enciso CVSymbolVisitor Visitor(Pipeline); 634e7950fceSCarlos Alberto Enciso return Visitor.visitSymbolStream(Symbols); 635e7950fceSCarlos Alberto Enciso } 636e7950fceSCarlos Alberto Enciso 637e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::traverseSymbolSection(StringRef SectionName, 638e7950fceSCarlos Alberto Enciso const SectionRef &Section) { 639e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 640e7950fceSCarlos Alberto Enciso ListScope D(W, "CodeViewDebugInfo"); 641e7950fceSCarlos Alberto Enciso W.printNumber("Section", SectionName, getObj().getSectionID(Section)); 642e7950fceSCarlos Alberto Enciso }); 643e7950fceSCarlos Alberto Enciso 644e7950fceSCarlos Alberto Enciso Expected<StringRef> SectionOrErr = Section.getContents(); 645e7950fceSCarlos Alberto Enciso if (!SectionOrErr) 646e7950fceSCarlos Alberto Enciso return SectionOrErr.takeError(); 647e7950fceSCarlos Alberto Enciso StringRef SectionContents = *SectionOrErr; 648e7950fceSCarlos Alberto Enciso StringRef Data = SectionContents; 649e7950fceSCarlos Alberto Enciso 650e7950fceSCarlos Alberto Enciso SmallVector<StringRef, 10> SymbolNames; 651e7950fceSCarlos Alberto Enciso StringMap<StringRef> FunctionLineTables; 652e7950fceSCarlos Alberto Enciso 653e7950fceSCarlos Alberto Enciso uint32_t Magic; 654e7950fceSCarlos Alberto Enciso if (Error E = consume(Data, Magic)) 655e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(E)), getFileName()); 656e7950fceSCarlos Alberto Enciso 657e7950fceSCarlos Alberto Enciso if (Magic != COFF::DEBUG_SECTION_MAGIC) 658e7950fceSCarlos Alberto Enciso return createStringError(object_error::parse_failed, getFileName()); 659e7950fceSCarlos Alberto Enciso 6604a0ccfa8SKazu Hirata BinaryStreamReader FSReader(Data, llvm::endianness::little); 661e7950fceSCarlos Alberto Enciso if (Error Err = initializeFileAndStringTables(FSReader)) 662e7950fceSCarlos Alberto Enciso return Err; 663e7950fceSCarlos Alberto Enciso 664e7950fceSCarlos Alberto Enciso while (!Data.empty()) { 665e7950fceSCarlos Alberto Enciso // The section consists of a number of subsection in the following format: 666e7950fceSCarlos Alberto Enciso // |SubSectionType|SubSectionSize|Contents...| 667e7950fceSCarlos Alberto Enciso uint32_t SubType, SubSectionSize; 668e7950fceSCarlos Alberto Enciso if (Error E = consume(Data, SubType)) 669e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(E)), getFileName()); 670e7950fceSCarlos Alberto Enciso if (Error E = consume(Data, SubSectionSize)) 671e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(E)), getFileName()); 672e7950fceSCarlos Alberto Enciso 673e7950fceSCarlos Alberto Enciso // Process the subsection as normal even if the ignore bit is set. 674e7950fceSCarlos Alberto Enciso SubType &= ~SubsectionIgnoreFlag; 675e7950fceSCarlos Alberto Enciso 676e7950fceSCarlos Alberto Enciso // Get the contents of the subsection. 677e7950fceSCarlos Alberto Enciso if (SubSectionSize > Data.size()) 678e7950fceSCarlos Alberto Enciso return createStringError(object_error::parse_failed, getFileName()); 679e7950fceSCarlos Alberto Enciso StringRef Contents = Data.substr(0, SubSectionSize); 680e7950fceSCarlos Alberto Enciso 681e7950fceSCarlos Alberto Enciso // Add SubSectionSize to the current offset and align that offset 682e7950fceSCarlos Alberto Enciso // to find the next subsection. 683e7950fceSCarlos Alberto Enciso size_t SectionOffset = Data.data() - SectionContents.data(); 684e7950fceSCarlos Alberto Enciso size_t NextOffset = SectionOffset + SubSectionSize; 685e7950fceSCarlos Alberto Enciso NextOffset = alignTo(NextOffset, 4); 686e7950fceSCarlos Alberto Enciso if (NextOffset > SectionContents.size()) 687e7950fceSCarlos Alberto Enciso return createStringError(object_error::parse_failed, getFileName()); 688e7950fceSCarlos Alberto Enciso Data = SectionContents.drop_front(NextOffset); 689e7950fceSCarlos Alberto Enciso 690e7950fceSCarlos Alberto Enciso switch (DebugSubsectionKind(SubType)) { 691e7950fceSCarlos Alberto Enciso case DebugSubsectionKind::Symbols: 692e7950fceSCarlos Alberto Enciso if (Error Err = 693e7950fceSCarlos Alberto Enciso traverseSymbolsSubsection(Contents, Section, SectionContents)) 694e7950fceSCarlos Alberto Enciso return Err; 695e7950fceSCarlos Alberto Enciso break; 696e7950fceSCarlos Alberto Enciso 697e7950fceSCarlos Alberto Enciso case DebugSubsectionKind::InlineeLines: 698e7950fceSCarlos Alberto Enciso if (Error Err = traverseInlineeLines(Contents)) 699e7950fceSCarlos Alberto Enciso return Err; 700e7950fceSCarlos Alberto Enciso break; 701e7950fceSCarlos Alberto Enciso 702e7950fceSCarlos Alberto Enciso case DebugSubsectionKind::Lines: 703e7950fceSCarlos Alberto Enciso // Holds a PC to file:line table. Some data to parse this subsection 704e7950fceSCarlos Alberto Enciso // is stored in the other subsections, so just check sanity and store 705e7950fceSCarlos Alberto Enciso // the pointers for deferred processing. 706e7950fceSCarlos Alberto Enciso 707e7950fceSCarlos Alberto Enciso // Collect function and ranges only if we need to print logical lines. 708e7950fceSCarlos Alberto Enciso if (options().getGeneralCollectRanges()) { 709e7950fceSCarlos Alberto Enciso 710e7950fceSCarlos Alberto Enciso if (SubSectionSize < 12) { 711e7950fceSCarlos Alberto Enciso // There should be at least three words to store two function 712e7950fceSCarlos Alberto Enciso // relocations and size of the code. 713e7950fceSCarlos Alberto Enciso return createStringError(object_error::parse_failed, getFileName()); 714e7950fceSCarlos Alberto Enciso } 715e7950fceSCarlos Alberto Enciso 716e7950fceSCarlos Alberto Enciso StringRef SymbolName; 717e7950fceSCarlos Alberto Enciso if (Error Err = resolveSymbolName(getObj().getCOFFSection(Section), 718e7950fceSCarlos Alberto Enciso SectionOffset, SymbolName)) 719e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(Err)), 720e7950fceSCarlos Alberto Enciso getFileName()); 721e7950fceSCarlos Alberto Enciso 722e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ W.printString("Symbol Name", SymbolName); }); 723e7950fceSCarlos Alberto Enciso if (FunctionLineTables.count(SymbolName) != 0) { 724e7950fceSCarlos Alberto Enciso // Saw debug info for this function already? 725e7950fceSCarlos Alberto Enciso return createStringError(object_error::parse_failed, getFileName()); 726e7950fceSCarlos Alberto Enciso } 727e7950fceSCarlos Alberto Enciso 728e7950fceSCarlos Alberto Enciso FunctionLineTables[SymbolName] = Contents; 729e7950fceSCarlos Alberto Enciso SymbolNames.push_back(SymbolName); 730e7950fceSCarlos Alberto Enciso } 731e7950fceSCarlos Alberto Enciso break; 732e7950fceSCarlos Alberto Enciso 733e7950fceSCarlos Alberto Enciso // Do nothing for unrecognized subsections. 734e7950fceSCarlos Alberto Enciso default: 735e7950fceSCarlos Alberto Enciso break; 736e7950fceSCarlos Alberto Enciso } 737e7950fceSCarlos Alberto Enciso W.flush(); 738e7950fceSCarlos Alberto Enciso } 739e7950fceSCarlos Alberto Enciso 740e7950fceSCarlos Alberto Enciso // Traverse the line tables now that we've read all the subsections and 741e7950fceSCarlos Alberto Enciso // know all the required information. 742e7950fceSCarlos Alberto Enciso for (StringRef SymbolName : SymbolNames) { 743e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 744e7950fceSCarlos Alberto Enciso ListScope S(W, "FunctionLineTable"); 745e7950fceSCarlos Alberto Enciso W.printString("Symbol Name", SymbolName); 746e7950fceSCarlos Alberto Enciso }); 747e7950fceSCarlos Alberto Enciso 7484a0ccfa8SKazu Hirata BinaryStreamReader Reader(FunctionLineTables[SymbolName], 7494a0ccfa8SKazu Hirata llvm::endianness::little); 750e7950fceSCarlos Alberto Enciso 751e7950fceSCarlos Alberto Enciso DebugLinesSubsectionRef Lines; 752e7950fceSCarlos Alberto Enciso if (Error E = Lines.initialize(Reader)) 753e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(E)), getFileName()); 754e7950fceSCarlos Alberto Enciso 755e7950fceSCarlos Alberto Enciso // Find the associated symbol table information. 756e7950fceSCarlos Alberto Enciso LVSymbolTableEntry SymbolTableEntry = getSymbolTableEntry(SymbolName); 757e7950fceSCarlos Alberto Enciso LVScope *Function = SymbolTableEntry.Scope; 758e7950fceSCarlos Alberto Enciso if (!Function) 759e7950fceSCarlos Alberto Enciso continue; 760e7950fceSCarlos Alberto Enciso 761e7950fceSCarlos Alberto Enciso LVAddress Addendum = SymbolTableEntry.Address; 762e7950fceSCarlos Alberto Enciso LVSectionIndex SectionIndex = SymbolTableEntry.SectionIndex; 763e7950fceSCarlos Alberto Enciso 764e7950fceSCarlos Alberto Enciso // The given scope represents the function that contains the line numbers. 765e7950fceSCarlos Alberto Enciso // Collect all generated debug lines associated with the function. 766e7950fceSCarlos Alberto Enciso CULines.clear(); 767e7950fceSCarlos Alberto Enciso 768e7950fceSCarlos Alberto Enciso // For the given scope, collect all scopes ranges. 769e7950fceSCarlos Alberto Enciso LVRange *ScopesWithRanges = getSectionRanges(SectionIndex); 770e7950fceSCarlos Alberto Enciso ScopesWithRanges->clear(); 771e7950fceSCarlos Alberto Enciso Function->getRanges(*ScopesWithRanges); 772e7950fceSCarlos Alberto Enciso ScopesWithRanges->sort(); 773e7950fceSCarlos Alberto Enciso 774e7950fceSCarlos Alberto Enciso uint16_t Segment = Lines.header()->RelocSegment; 775e7950fceSCarlos Alberto Enciso uint32_t Begin = Lines.header()->RelocOffset; 776e7950fceSCarlos Alberto Enciso uint32_t Size = Lines.header()->CodeSize; 777e7950fceSCarlos Alberto Enciso for (const LineColumnEntry &Block : Lines) 778e7950fceSCarlos Alberto Enciso if (Error Err = createLines(Block.LineNumbers, Addendum, Segment, Begin, 779e7950fceSCarlos Alberto Enciso Size, Block.NameIndex)) 780e7950fceSCarlos Alberto Enciso return Err; 781e7950fceSCarlos Alberto Enciso 782e7950fceSCarlos Alberto Enciso // Include lines from any inlined functions within the current function. 783e7950fceSCarlos Alberto Enciso includeInlineeLines(SectionIndex, Function); 784e7950fceSCarlos Alberto Enciso 785e7950fceSCarlos Alberto Enciso if (Error Err = createInstructions(Function, SectionIndex)) 786e7950fceSCarlos Alberto Enciso return Err; 787e7950fceSCarlos Alberto Enciso 788e7950fceSCarlos Alberto Enciso processLines(&CULines, SectionIndex, Function); 789e7950fceSCarlos Alberto Enciso } 790e7950fceSCarlos Alberto Enciso 791e7950fceSCarlos Alberto Enciso return Error::success(); 792e7950fceSCarlos Alberto Enciso } 793e7950fceSCarlos Alberto Enciso 794e7950fceSCarlos Alberto Enciso void LVCodeViewReader::sortScopes() { Root->sort(); } 795e7950fceSCarlos Alberto Enciso 796e7950fceSCarlos Alberto Enciso void LVCodeViewReader::print(raw_ostream &OS) const { 797e7950fceSCarlos Alberto Enciso LLVM_DEBUG(dbgs() << "CreateReaders\n"); 798e7950fceSCarlos Alberto Enciso } 799e7950fceSCarlos Alberto Enciso 800e7950fceSCarlos Alberto Enciso void LVCodeViewReader::mapRangeAddress(const ObjectFile &Obj, 801e7950fceSCarlos Alberto Enciso const SectionRef &Section, 802e7950fceSCarlos Alberto Enciso bool IsComdat) { 803e7950fceSCarlos Alberto Enciso if (!Obj.isCOFF()) 804e7950fceSCarlos Alberto Enciso return; 805e7950fceSCarlos Alberto Enciso 806e7950fceSCarlos Alberto Enciso const COFFObjectFile *Object = cast<COFFObjectFile>(&Obj); 807e7950fceSCarlos Alberto Enciso 808e7950fceSCarlos Alberto Enciso for (const SymbolRef &Sym : Object->symbols()) { 809e7950fceSCarlos Alberto Enciso if (!Section.containsSymbol(Sym)) 810e7950fceSCarlos Alberto Enciso continue; 811e7950fceSCarlos Alberto Enciso 812e7950fceSCarlos Alberto Enciso COFFSymbolRef Symbol = Object->getCOFFSymbol(Sym); 813e7950fceSCarlos Alberto Enciso if (Symbol.getComplexType() != llvm::COFF::IMAGE_SYM_DTYPE_FUNCTION) 814e7950fceSCarlos Alberto Enciso continue; 815e7950fceSCarlos Alberto Enciso 816e7950fceSCarlos Alberto Enciso StringRef SymbolName; 817e7950fceSCarlos Alberto Enciso Expected<StringRef> SymNameOrErr = Object->getSymbolName(Symbol); 818e7950fceSCarlos Alberto Enciso if (!SymNameOrErr) { 819e7950fceSCarlos Alberto Enciso W.startLine() << "Invalid symbol name: " << Symbol.getSectionNumber() 820e7950fceSCarlos Alberto Enciso << "\n"; 821e7950fceSCarlos Alberto Enciso consumeError(SymNameOrErr.takeError()); 822e7950fceSCarlos Alberto Enciso continue; 823e7950fceSCarlos Alberto Enciso } 824e7950fceSCarlos Alberto Enciso SymbolName = *SymNameOrErr; 825e7950fceSCarlos Alberto Enciso 826e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 827e7950fceSCarlos Alberto Enciso Expected<const coff_section *> SectionOrErr = 828e7950fceSCarlos Alberto Enciso Object->getSection(Symbol.getSectionNumber()); 829e7950fceSCarlos Alberto Enciso if (!SectionOrErr) { 830e7950fceSCarlos Alberto Enciso W.startLine() << "Invalid section number: " << Symbol.getSectionNumber() 831e7950fceSCarlos Alberto Enciso << "\n"; 832e7950fceSCarlos Alberto Enciso consumeError(SectionOrErr.takeError()); 833e7950fceSCarlos Alberto Enciso return; 834e7950fceSCarlos Alberto Enciso } 835e7950fceSCarlos Alberto Enciso W.printNumber("Section #", Symbol.getSectionNumber()); 836e7950fceSCarlos Alberto Enciso W.printString("Name", SymbolName); 837e7950fceSCarlos Alberto Enciso W.printHex("Value", Symbol.getValue()); 838e7950fceSCarlos Alberto Enciso }); 839e7950fceSCarlos Alberto Enciso 840e7950fceSCarlos Alberto Enciso // Record the symbol name (linkage) and its loading address. 841e7950fceSCarlos Alberto Enciso addToSymbolTable(SymbolName, Symbol.getValue(), Symbol.getSectionNumber(), 842e7950fceSCarlos Alberto Enciso IsComdat); 843e7950fceSCarlos Alberto Enciso } 844e7950fceSCarlos Alberto Enciso } 845e7950fceSCarlos Alberto Enciso 846e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::createScopes(COFFObjectFile &Obj) { 847e7950fceSCarlos Alberto Enciso if (Error Err = loadTargetInfo(Obj)) 848e7950fceSCarlos Alberto Enciso return Err; 849e7950fceSCarlos Alberto Enciso 850e7950fceSCarlos Alberto Enciso // Initialization required when processing a COFF file: 851e7950fceSCarlos Alberto Enciso // Cache the symbols relocations. 852e7950fceSCarlos Alberto Enciso // Create a mapping for virtual addresses. 853e7950fceSCarlos Alberto Enciso // Get the functions entry points. 854e7950fceSCarlos Alberto Enciso cacheRelocations(); 855e7950fceSCarlos Alberto Enciso mapVirtualAddress(Obj); 856e7950fceSCarlos Alberto Enciso 857e7950fceSCarlos Alberto Enciso for (const SectionRef &Section : Obj.sections()) { 858e7950fceSCarlos Alberto Enciso Expected<StringRef> SectionNameOrErr = Section.getName(); 859e7950fceSCarlos Alberto Enciso if (!SectionNameOrErr) 860e7950fceSCarlos Alberto Enciso return SectionNameOrErr.takeError(); 861e7950fceSCarlos Alberto Enciso // .debug$T is a standard CodeView type section, while .debug$P is the 862e7950fceSCarlos Alberto Enciso // same format but used for MSVC precompiled header object files. 863e7950fceSCarlos Alberto Enciso if (*SectionNameOrErr == ".debug$T" || *SectionNameOrErr == ".debug$P") 864e7950fceSCarlos Alberto Enciso if (Error Err = traverseTypeSection(*SectionNameOrErr, Section)) 865e7950fceSCarlos Alberto Enciso return Err; 866e7950fceSCarlos Alberto Enciso } 867e7950fceSCarlos Alberto Enciso 868e7950fceSCarlos Alberto Enciso // Process collected namespaces. 869e7950fceSCarlos Alberto Enciso LogicalVisitor.processNamespaces(); 870e7950fceSCarlos Alberto Enciso 871e7950fceSCarlos Alberto Enciso for (const SectionRef &Section : Obj.sections()) { 872e7950fceSCarlos Alberto Enciso Expected<StringRef> SectionNameOrErr = Section.getName(); 873e7950fceSCarlos Alberto Enciso if (!SectionNameOrErr) 874e7950fceSCarlos Alberto Enciso return SectionNameOrErr.takeError(); 875e7950fceSCarlos Alberto Enciso if (*SectionNameOrErr == ".debug$S") 876e7950fceSCarlos Alberto Enciso if (Error Err = traverseSymbolSection(*SectionNameOrErr, Section)) 877e7950fceSCarlos Alberto Enciso return Err; 878e7950fceSCarlos Alberto Enciso } 879e7950fceSCarlos Alberto Enciso 880e7950fceSCarlos Alberto Enciso // Check if we have to close the Compile Unit scope. 881e7950fceSCarlos Alberto Enciso LogicalVisitor.closeScope(); 882e7950fceSCarlos Alberto Enciso 883e7950fceSCarlos Alberto Enciso // Traverse the strings recorded and transform them into filenames. 884e7950fceSCarlos Alberto Enciso LogicalVisitor.processFiles(); 885e7950fceSCarlos Alberto Enciso 886e7950fceSCarlos Alberto Enciso // Process collected element lines. 887e7950fceSCarlos Alberto Enciso LogicalVisitor.processLines(); 888e7950fceSCarlos Alberto Enciso 889e7950fceSCarlos Alberto Enciso // Translate composite names into a single component. 890e7950fceSCarlos Alberto Enciso Root->transformScopedName(); 891e7950fceSCarlos Alberto Enciso return Error::success(); 892e7950fceSCarlos Alberto Enciso } 893e7950fceSCarlos Alberto Enciso 894e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::createScopes(PDBFile &Pdb) { 895e7950fceSCarlos Alberto Enciso if (Error Err = loadTargetInfo(Pdb)) 896e7950fceSCarlos Alberto Enciso return Err; 897e7950fceSCarlos Alberto Enciso 898e7950fceSCarlos Alberto Enciso if (!Pdb.hasPDBTpiStream() || !Pdb.hasPDBDbiStream()) 899e7950fceSCarlos Alberto Enciso return Error::success(); 900e7950fceSCarlos Alberto Enciso 901e7950fceSCarlos Alberto Enciso // Open the executable associated with the PDB file and get the section 902e7950fceSCarlos Alberto Enciso // addresses used to calculate linear addresses for CodeView Symbols. 903e7950fceSCarlos Alberto Enciso if (!ExePath.empty()) { 904e7950fceSCarlos Alberto Enciso ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr = 905e7950fceSCarlos Alberto Enciso MemoryBuffer::getFileOrSTDIN(ExePath); 906e7950fceSCarlos Alberto Enciso if (BuffOrErr.getError()) { 907e7950fceSCarlos Alberto Enciso return createStringError(errc::bad_file_descriptor, 908e7950fceSCarlos Alberto Enciso "File '%s' does not exist.", ExePath.c_str()); 909e7950fceSCarlos Alberto Enciso } 910e7950fceSCarlos Alberto Enciso BinaryBuffer = std::move(BuffOrErr.get()); 911e7950fceSCarlos Alberto Enciso 912e7950fceSCarlos Alberto Enciso // Check if the buffer corresponds to a PECOFF executable. 913e7950fceSCarlos Alberto Enciso assert(identify_magic(BinaryBuffer->getBuffer()) == 914e7950fceSCarlos Alberto Enciso file_magic::pecoff_executable && 915e7950fceSCarlos Alberto Enciso "Invalid PECOFF executable file."); 916e7950fceSCarlos Alberto Enciso 917e7950fceSCarlos Alberto Enciso Expected<std::unique_ptr<Binary>> BinOrErr = 918e7950fceSCarlos Alberto Enciso createBinary(BinaryBuffer->getMemBufferRef()); 919e7950fceSCarlos Alberto Enciso if (errorToErrorCode(BinOrErr.takeError())) { 920e7950fceSCarlos Alberto Enciso return createStringError(errc::not_supported, 921e7950fceSCarlos Alberto Enciso "Binary object format in '%s' is not supported.", 922e7950fceSCarlos Alberto Enciso ExePath.c_str()); 923e7950fceSCarlos Alberto Enciso } 924e7950fceSCarlos Alberto Enciso BinaryExecutable = std::move(*BinOrErr); 925e7950fceSCarlos Alberto Enciso if (COFFObjectFile *COFFObject = 926e7950fceSCarlos Alberto Enciso dyn_cast<COFFObjectFile>(BinaryExecutable.get())) 927e7950fceSCarlos Alberto Enciso mapVirtualAddress(*COFFObject); 928e7950fceSCarlos Alberto Enciso } 929e7950fceSCarlos Alberto Enciso 930e7950fceSCarlos Alberto Enciso // In order to generate a full logical view, we have to traverse both 931e7950fceSCarlos Alberto Enciso // streams TPI and IPI if they are present. The following table gives 932e7950fceSCarlos Alberto Enciso // the stream where a specified type is located. If the IPI stream is 933e7950fceSCarlos Alberto Enciso // not present, all the types are located in the TPI stream. 934e7950fceSCarlos Alberto Enciso // 935e7950fceSCarlos Alberto Enciso // TPI Stream: 936e7950fceSCarlos Alberto Enciso // LF_POINTER LF_MODIFIER LF_PROCEDURE LF_MFUNCTION 937e7950fceSCarlos Alberto Enciso // LF_LABEL LF_ARGLIST LF_FIELDLIST LF_ARRAY 938e7950fceSCarlos Alberto Enciso // LF_CLASS LF_STRUCTURE LF_INTERFACE LF_UNION 939e7950fceSCarlos Alberto Enciso // LF_ENUM LF_TYPESERVER2 LF_VFTABLE LF_VTSHAPE 940e7950fceSCarlos Alberto Enciso // LF_BITFIELD LF_METHODLIST LF_PRECOMP LF_ENDPRECOMP 941e7950fceSCarlos Alberto Enciso // 942e7950fceSCarlos Alberto Enciso // IPI stream: 943e7950fceSCarlos Alberto Enciso // LF_FUNC_ID LF_MFUNC_ID LF_BUILDINFO 944e7950fceSCarlos Alberto Enciso // LF_SUBSTR_LIST LF_STRING_ID LF_UDT_SRC_LINE 945e7950fceSCarlos Alberto Enciso // LF_UDT_MOD_SRC_LINE 946e7950fceSCarlos Alberto Enciso 947e7950fceSCarlos Alberto Enciso LazyRandomTypeCollection &Types = types(); 948e7950fceSCarlos Alberto Enciso LazyRandomTypeCollection &Ids = ids(); 949e7950fceSCarlos Alberto Enciso if (Error Err = traverseTypes(Pdb, Types, Ids)) 950e7950fceSCarlos Alberto Enciso return Err; 951e7950fceSCarlos Alberto Enciso 952e7950fceSCarlos Alberto Enciso // Process collected namespaces. 953e7950fceSCarlos Alberto Enciso LogicalVisitor.processNamespaces(); 954e7950fceSCarlos Alberto Enciso 955e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ W.getOStream() << "Traversing inlined lines\n"; }); 956e7950fceSCarlos Alberto Enciso 957e7950fceSCarlos Alberto Enciso auto VisitInlineeLines = [&](int32_t Modi, const SymbolGroup &SG, 958e7950fceSCarlos Alberto Enciso DebugInlineeLinesSubsectionRef &Lines) -> Error { 959e7950fceSCarlos Alberto Enciso return collectInlineeInfo(Lines, &SG); 960e7950fceSCarlos Alberto Enciso }; 961e7950fceSCarlos Alberto Enciso 962e7950fceSCarlos Alberto Enciso FilterOptions Filters = {}; 963e7950fceSCarlos Alberto Enciso LinePrinter Printer(/*Indent=*/2, false, nulls(), Filters); 964e7950fceSCarlos Alberto Enciso const PrintScope HeaderScope(Printer, /*IndentLevel=*/2); 965e7950fceSCarlos Alberto Enciso if (Error Err = iterateModuleSubsections<DebugInlineeLinesSubsectionRef>( 966e7950fceSCarlos Alberto Enciso Input, HeaderScope, VisitInlineeLines)) 967e7950fceSCarlos Alberto Enciso return Err; 968e7950fceSCarlos Alberto Enciso 969e7950fceSCarlos Alberto Enciso // Traverse global symbols. 970e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ W.getOStream() << "Traversing global symbols\n"; }); 971e7950fceSCarlos Alberto Enciso if (Pdb.hasPDBGlobalsStream()) { 972e7950fceSCarlos Alberto Enciso Expected<GlobalsStream &> GlobalsOrErr = Pdb.getPDBGlobalsStream(); 973e7950fceSCarlos Alberto Enciso if (!GlobalsOrErr) 974e7950fceSCarlos Alberto Enciso return GlobalsOrErr.takeError(); 975e7950fceSCarlos Alberto Enciso GlobalsStream &Globals = *GlobalsOrErr; 976e7950fceSCarlos Alberto Enciso const GSIHashTable &Table = Globals.getGlobalsTable(); 977e7950fceSCarlos Alberto Enciso Expected<SymbolStream &> ExpectedSyms = Pdb.getPDBSymbolStream(); 978e7950fceSCarlos Alberto Enciso if (ExpectedSyms) { 979e7950fceSCarlos Alberto Enciso 980e7950fceSCarlos Alberto Enciso SymbolVisitorCallbackPipeline Pipeline; 981e7950fceSCarlos Alberto Enciso SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb); 982e7950fceSCarlos Alberto Enciso LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr, 983e7950fceSCarlos Alberto Enciso LogicalVisitor.getShared()); 984e7950fceSCarlos Alberto Enciso 985e7950fceSCarlos Alberto Enciso // As the global symbols do not have an associated Compile Unit, create 986e7950fceSCarlos Alberto Enciso // one, as the container for all global symbols. 987e7950fceSCarlos Alberto Enciso RecordPrefix Prefix(SymbolKind::S_COMPILE3); 988e7950fceSCarlos Alberto Enciso CVSymbol Symbol(&Prefix, sizeof(Prefix)); 989e7950fceSCarlos Alberto Enciso uint32_t Offset = 0; 990e7950fceSCarlos Alberto Enciso if (Error Err = Traverser.visitSymbolBegin(Symbol, Offset)) 991e7950fceSCarlos Alberto Enciso consumeError(std::move(Err)); 992e7950fceSCarlos Alberto Enciso else { 993e7950fceSCarlos Alberto Enciso // The CodeView compile unit containing the global symbols does not 994e7950fceSCarlos Alberto Enciso // have a name; generate one using its parent name (object filename) 995e7950fceSCarlos Alberto Enciso // follow by the '_global' string. 996e7950fceSCarlos Alberto Enciso std::string Name(CompileUnit->getParentScope()->getName()); 997e7950fceSCarlos Alberto Enciso CompileUnit->setName(Name.append("_global")); 998e7950fceSCarlos Alberto Enciso 999e7950fceSCarlos Alberto Enciso Pipeline.addCallbackToPipeline(Deserializer); 1000e7950fceSCarlos Alberto Enciso Pipeline.addCallbackToPipeline(Traverser); 1001e7950fceSCarlos Alberto Enciso CVSymbolVisitor Visitor(Pipeline); 1002e7950fceSCarlos Alberto Enciso 1003e7950fceSCarlos Alberto Enciso BinaryStreamRef SymStream = 1004e7950fceSCarlos Alberto Enciso ExpectedSyms->getSymbolArray().getUnderlyingStream(); 1005e7950fceSCarlos Alberto Enciso for (uint32_t PubSymOff : Table) { 1006e7950fceSCarlos Alberto Enciso Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, PubSymOff); 1007e7950fceSCarlos Alberto Enciso if (Sym) { 1008e7950fceSCarlos Alberto Enciso if (Error Err = Visitor.visitSymbolRecord(*Sym, PubSymOff)) 1009e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(Err)), 1010e7950fceSCarlos Alberto Enciso getFileName()); 1011e7950fceSCarlos Alberto Enciso } else { 1012e7950fceSCarlos Alberto Enciso consumeError(Sym.takeError()); 1013e7950fceSCarlos Alberto Enciso } 1014e7950fceSCarlos Alberto Enciso } 1015e7950fceSCarlos Alberto Enciso } 1016e7950fceSCarlos Alberto Enciso 1017e7950fceSCarlos Alberto Enciso LogicalVisitor.closeScope(); 1018e7950fceSCarlos Alberto Enciso } else { 1019e7950fceSCarlos Alberto Enciso consumeError(ExpectedSyms.takeError()); 1020e7950fceSCarlos Alberto Enciso } 1021e7950fceSCarlos Alberto Enciso } 1022e7950fceSCarlos Alberto Enciso 1023e7950fceSCarlos Alberto Enciso // Traverse symbols (DBI). 1024e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ W.getOStream() << "Traversing symbol groups\n"; }); 1025e7950fceSCarlos Alberto Enciso 1026e7950fceSCarlos Alberto Enciso auto VisitSymbolGroup = [&](uint32_t Modi, const SymbolGroup &SG) -> Error { 1027e7950fceSCarlos Alberto Enciso Expected<ModuleDebugStreamRef> ExpectedModS = 1028e7950fceSCarlos Alberto Enciso getModuleDebugStream(Pdb, Modi); 1029e7950fceSCarlos Alberto Enciso if (ExpectedModS) { 1030e7950fceSCarlos Alberto Enciso ModuleDebugStreamRef &ModS = *ExpectedModS; 1031e7950fceSCarlos Alberto Enciso 1032e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 1033e7950fceSCarlos Alberto Enciso W.getOStream() << formatv("Traversing Group: Mod {0:4}\n", Modi); 1034e7950fceSCarlos Alberto Enciso }); 1035e7950fceSCarlos Alberto Enciso 1036e7950fceSCarlos Alberto Enciso SymbolVisitorCallbackPipeline Pipeline; 1037e7950fceSCarlos Alberto Enciso SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb); 1038e7950fceSCarlos Alberto Enciso LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr, 1039e7950fceSCarlos Alberto Enciso LogicalVisitor.getShared()); 1040e7950fceSCarlos Alberto Enciso 1041e7950fceSCarlos Alberto Enciso Pipeline.addCallbackToPipeline(Deserializer); 1042e7950fceSCarlos Alberto Enciso Pipeline.addCallbackToPipeline(Traverser); 1043e7950fceSCarlos Alberto Enciso CVSymbolVisitor Visitor(Pipeline); 1044e7950fceSCarlos Alberto Enciso BinarySubstreamRef SS = ModS.getSymbolsSubstream(); 1045e7950fceSCarlos Alberto Enciso if (Error Err = 1046e7950fceSCarlos Alberto Enciso Visitor.visitSymbolStream(ModS.getSymbolArray(), SS.Offset)) 1047e7950fceSCarlos Alberto Enciso return createStringError(errorToErrorCode(std::move(Err)), 1048e7950fceSCarlos Alberto Enciso getFileName()); 1049e7950fceSCarlos Alberto Enciso } else { 1050e7950fceSCarlos Alberto Enciso // If the module stream does not exist, it is not an error condition. 1051e7950fceSCarlos Alberto Enciso consumeError(ExpectedModS.takeError()); 1052e7950fceSCarlos Alberto Enciso } 1053e7950fceSCarlos Alberto Enciso 1054e7950fceSCarlos Alberto Enciso return Error::success(); 1055e7950fceSCarlos Alberto Enciso }; 1056e7950fceSCarlos Alberto Enciso 1057e7950fceSCarlos Alberto Enciso if (Error Err = iterateSymbolGroups(Input, HeaderScope, VisitSymbolGroup)) 1058e7950fceSCarlos Alberto Enciso return Err; 1059e7950fceSCarlos Alberto Enciso 1060e7950fceSCarlos Alberto Enciso // At this stage, the logical view contains all scopes, symbols and types. 1061e7950fceSCarlos Alberto Enciso // For PDBs we can use the module id, to access its specific compile unit. 1062e7950fceSCarlos Alberto Enciso // The line record addresses has been already resolved, so we can apply the 1063e7950fceSCarlos Alberto Enciso // flow as when processing DWARF. 1064e7950fceSCarlos Alberto Enciso 1065e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ W.getOStream() << "Traversing lines\n"; }); 1066e7950fceSCarlos Alberto Enciso 1067e7950fceSCarlos Alberto Enciso // Record all line records for a Compile Unit. 1068e7950fceSCarlos Alberto Enciso CULines.clear(); 1069e7950fceSCarlos Alberto Enciso 1070e7950fceSCarlos Alberto Enciso auto VisitDebugLines = [this](int32_t Modi, const SymbolGroup &SG, 1071e7950fceSCarlos Alberto Enciso DebugLinesSubsectionRef &Lines) -> Error { 1072e7950fceSCarlos Alberto Enciso if (!options().getPrintLines()) 1073e7950fceSCarlos Alberto Enciso return Error::success(); 1074e7950fceSCarlos Alberto Enciso 1075e7950fceSCarlos Alberto Enciso uint16_t Segment = Lines.header()->RelocSegment; 1076e7950fceSCarlos Alberto Enciso uint32_t Begin = Lines.header()->RelocOffset; 1077e7950fceSCarlos Alberto Enciso uint32_t Size = Lines.header()->CodeSize; 1078e7950fceSCarlos Alberto Enciso 1079e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ W.getOStream() << formatv("Modi = {0}\n", Modi); }); 1080e7950fceSCarlos Alberto Enciso 1081e7950fceSCarlos Alberto Enciso // We have line information for a new module; finish processing the 1082e7950fceSCarlos Alberto Enciso // collected information for the current module. Once it is done, start 1083e7950fceSCarlos Alberto Enciso // recording the line information for the new module. 1084e7950fceSCarlos Alberto Enciso if (CurrentModule != Modi) { 1085e7950fceSCarlos Alberto Enciso if (Error Err = processModule()) 1086e7950fceSCarlos Alberto Enciso return Err; 1087e7950fceSCarlos Alberto Enciso CULines.clear(); 1088e7950fceSCarlos Alberto Enciso CurrentModule = Modi; 1089e7950fceSCarlos Alberto Enciso } 1090e7950fceSCarlos Alberto Enciso 1091e7950fceSCarlos Alberto Enciso for (const LineColumnEntry &Block : Lines) 1092e7950fceSCarlos Alberto Enciso if (Error Err = createLines(Block.LineNumbers, /*Addendum=*/0, Segment, 1093e7950fceSCarlos Alberto Enciso Begin, Size, Block.NameIndex, &SG)) 1094e7950fceSCarlos Alberto Enciso return Err; 1095e7950fceSCarlos Alberto Enciso 1096e7950fceSCarlos Alberto Enciso return Error::success(); 1097e7950fceSCarlos Alberto Enciso }; 1098e7950fceSCarlos Alberto Enciso 1099e7950fceSCarlos Alberto Enciso if (Error Err = iterateModuleSubsections<DebugLinesSubsectionRef>( 1100e7950fceSCarlos Alberto Enciso Input, HeaderScope, VisitDebugLines)) 1101e7950fceSCarlos Alberto Enciso return Err; 1102e7950fceSCarlos Alberto Enciso 1103e7950fceSCarlos Alberto Enciso // Check if we have to close the Compile Unit scope. 1104e7950fceSCarlos Alberto Enciso LogicalVisitor.closeScope(); 1105e7950fceSCarlos Alberto Enciso 1106e7950fceSCarlos Alberto Enciso // Process collected element lines. 1107e7950fceSCarlos Alberto Enciso LogicalVisitor.processLines(); 1108e7950fceSCarlos Alberto Enciso 1109e7950fceSCarlos Alberto Enciso // Translate composite names into a single component. 1110e7950fceSCarlos Alberto Enciso Root->transformScopedName(); 1111e7950fceSCarlos Alberto Enciso return Error::success(); 1112e7950fceSCarlos Alberto Enciso } 1113e7950fceSCarlos Alberto Enciso 1114e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::processModule() { 1115e7950fceSCarlos Alberto Enciso if (LVScope *Scope = getScopeForModule(CurrentModule)) { 1116e7950fceSCarlos Alberto Enciso CompileUnit = static_cast<LVScopeCompileUnit *>(Scope); 1117e7950fceSCarlos Alberto Enciso 1118e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ dbgs() << "Processing Scope: " << Scope->getName() << "\n"; }); 1119e7950fceSCarlos Alberto Enciso 1120e7950fceSCarlos Alberto Enciso // For the given compile unit, collect all scopes ranges. 1121e7950fceSCarlos Alberto Enciso // For a complete ranges and lines mapping, the logical view support 1122e7950fceSCarlos Alberto Enciso // needs for the compile unit to have a low and high pc values. We 1123e7950fceSCarlos Alberto Enciso // can traverse the 'Modules' section and get the information for the 1124e7950fceSCarlos Alberto Enciso // specific module. Another option, is from all the ranges collected 1125e7950fceSCarlos Alberto Enciso // to take the first and last values. 1126e7950fceSCarlos Alberto Enciso LVSectionIndex SectionIndex = DotTextSectionIndex; 1127e7950fceSCarlos Alberto Enciso LVRange *ScopesWithRanges = getSectionRanges(SectionIndex); 1128e7950fceSCarlos Alberto Enciso ScopesWithRanges->clear(); 1129e7950fceSCarlos Alberto Enciso CompileUnit->getRanges(*ScopesWithRanges); 1130e7950fceSCarlos Alberto Enciso if (!ScopesWithRanges->empty()) 1131e7950fceSCarlos Alberto Enciso CompileUnit->addObject(ScopesWithRanges->getLower(), 1132e7950fceSCarlos Alberto Enciso ScopesWithRanges->getUpper()); 1133e7950fceSCarlos Alberto Enciso ScopesWithRanges->sort(); 1134e7950fceSCarlos Alberto Enciso 1135e7950fceSCarlos Alberto Enciso if (Error Err = createInstructions()) 1136e7950fceSCarlos Alberto Enciso return Err; 1137e7950fceSCarlos Alberto Enciso 1138e7950fceSCarlos Alberto Enciso // Include lines from any inlined functions within the current function. 1139e7950fceSCarlos Alberto Enciso includeInlineeLines(SectionIndex, Scope); 1140e7950fceSCarlos Alberto Enciso 1141e7950fceSCarlos Alberto Enciso processLines(&CULines, SectionIndex, nullptr); 1142e7950fceSCarlos Alberto Enciso } 1143e7950fceSCarlos Alberto Enciso 1144e7950fceSCarlos Alberto Enciso return Error::success(); 1145e7950fceSCarlos Alberto Enciso } 1146e7950fceSCarlos Alberto Enciso 1147e7950fceSCarlos Alberto Enciso // In order to create the scopes, the CodeView Reader will: 1148e7950fceSCarlos Alberto Enciso // = Traverse the TPI/IPI stream (Type visitor): 1149e7950fceSCarlos Alberto Enciso // Collect forward references, scoped names, type indexes that will represent 1150e7950fceSCarlos Alberto Enciso // a logical element, strings, line records, linkage names. 1151e7950fceSCarlos Alberto Enciso // = Traverse the symbols section (Symbol visitor): 1152e7950fceSCarlos Alberto Enciso // Create the scopes tree and creates the required logical elements, by 1153e7950fceSCarlos Alberto Enciso // using the collected indexes from the type visitor. 1154e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::createScopes() { 1155e7950fceSCarlos Alberto Enciso LLVM_DEBUG({ 1156e7950fceSCarlos Alberto Enciso W.startLine() << "\n"; 1157e7950fceSCarlos Alberto Enciso W.printString("File", getFileName().str()); 1158e7950fceSCarlos Alberto Enciso W.printString("Exe", ExePath); 1159e7950fceSCarlos Alberto Enciso W.printString("Format", FileFormatName); 1160e7950fceSCarlos Alberto Enciso }); 1161e7950fceSCarlos Alberto Enciso 1162e7950fceSCarlos Alberto Enciso if (Error Err = LVReader::createScopes()) 1163e7950fceSCarlos Alberto Enciso return Err; 1164e7950fceSCarlos Alberto Enciso 1165e7950fceSCarlos Alberto Enciso LogicalVisitor.setRoot(Root); 1166e7950fceSCarlos Alberto Enciso 1167e7950fceSCarlos Alberto Enciso if (isObj()) { 1168e7950fceSCarlos Alberto Enciso if (Error Err = createScopes(getObj())) 1169e7950fceSCarlos Alberto Enciso return Err; 1170e7950fceSCarlos Alberto Enciso } else { 1171e7950fceSCarlos Alberto Enciso if (Error Err = createScopes(getPdb())) 1172e7950fceSCarlos Alberto Enciso return Err; 1173e7950fceSCarlos Alberto Enciso } 1174e7950fceSCarlos Alberto Enciso 1175e7950fceSCarlos Alberto Enciso return Error::success(); 1176e7950fceSCarlos Alberto Enciso } 1177e7950fceSCarlos Alberto Enciso 1178e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::loadTargetInfo(const ObjectFile &Obj) { 1179e7950fceSCarlos Alberto Enciso // Detect the architecture from the object file. We usually don't need OS 1180e7950fceSCarlos Alberto Enciso // info to lookup a target and create register info. 1181e7950fceSCarlos Alberto Enciso Triple TT; 1182e7950fceSCarlos Alberto Enciso TT.setArch(Triple::ArchType(Obj.getArch())); 1183e7950fceSCarlos Alberto Enciso TT.setVendor(Triple::UnknownVendor); 1184e7950fceSCarlos Alberto Enciso TT.setOS(Triple::UnknownOS); 1185e7950fceSCarlos Alberto Enciso 1186e7950fceSCarlos Alberto Enciso // Features to be passed to target/subtarget 1187e7950fceSCarlos Alberto Enciso Expected<SubtargetFeatures> Features = Obj.getFeatures(); 1188e7950fceSCarlos Alberto Enciso SubtargetFeatures FeaturesValue; 1189e7950fceSCarlos Alberto Enciso if (!Features) { 1190e7950fceSCarlos Alberto Enciso consumeError(Features.takeError()); 1191e7950fceSCarlos Alberto Enciso FeaturesValue = SubtargetFeatures(); 1192e7950fceSCarlos Alberto Enciso } 1193e7950fceSCarlos Alberto Enciso FeaturesValue = *Features; 1194e7950fceSCarlos Alberto Enciso return loadGenericTargetInfo(TT.str(), FeaturesValue.getString()); 1195e7950fceSCarlos Alberto Enciso } 1196e7950fceSCarlos Alberto Enciso 1197e7950fceSCarlos Alberto Enciso Error LVCodeViewReader::loadTargetInfo(const PDBFile &Pdb) { 1198e7950fceSCarlos Alberto Enciso Triple TT; 1199e7950fceSCarlos Alberto Enciso TT.setArch(Triple::ArchType::x86_64); 1200e7950fceSCarlos Alberto Enciso TT.setVendor(Triple::UnknownVendor); 1201e7950fceSCarlos Alberto Enciso TT.setOS(Triple::Win32); 1202e7950fceSCarlos Alberto Enciso 1203e7950fceSCarlos Alberto Enciso StringRef TheFeature = ""; 1204e7950fceSCarlos Alberto Enciso 1205e7950fceSCarlos Alberto Enciso return loadGenericTargetInfo(TT.str(), TheFeature); 1206e7950fceSCarlos Alberto Enciso } 1207e7950fceSCarlos Alberto Enciso 1208e7950fceSCarlos Alberto Enciso std::string LVCodeViewReader::getRegisterName(LVSmall Opcode, 12092e6bb8c9SScott Linder ArrayRef<uint64_t> Operands) { 1210e7950fceSCarlos Alberto Enciso // Get Compilation Unit CPU Type. 1211e7950fceSCarlos Alberto Enciso CPUType CPU = getCompileUnitCPUType(); 1212e7950fceSCarlos Alberto Enciso // For CodeView the register always is in Operands[0]; 1213e7950fceSCarlos Alberto Enciso RegisterId Register = (RegisterId(Operands[0])); 1214e7950fceSCarlos Alberto Enciso return formatRegisterId(Register, CPU); 1215e7950fceSCarlos Alberto Enciso } 1216