1 //===- NativeInlineSiteSymbol.cpp - info about inline sites -----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h" 10 11 #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" 12 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" 13 #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 14 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" 15 #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" 16 #include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h" 17 #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 18 #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 19 #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 20 #include "llvm/DebugInfo/PDB/PDBExtras.h" 21 22 using namespace llvm; 23 using namespace llvm::codeview; 24 using namespace llvm::pdb; 25 26 NativeInlineSiteSymbol::NativeInlineSiteSymbol( 27 NativeSession &Session, SymIndexId Id, const codeview::InlineSiteSym &Sym, 28 uint64_t ParentAddr) 29 : NativeRawSymbol(Session, PDB_SymType::InlineSite, Id), Sym(Sym), 30 ParentAddr(ParentAddr) {} 31 32 NativeInlineSiteSymbol::~NativeInlineSiteSymbol() = default; 33 34 void NativeInlineSiteSymbol::dump(raw_ostream &OS, int Indent, 35 PdbSymbolIdField ShowIdFields, 36 PdbSymbolIdField RecurseIdFields) const { 37 NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); 38 dumpSymbolField(OS, "name", getName(), Indent); 39 } 40 41 static Optional<InlineeSourceLine> 42 findInlineeByTypeIndex(TypeIndex Id, ModuleDebugStreamRef &ModS) { 43 for (const auto &SS : ModS.getSubsectionsArray()) { 44 if (SS.kind() != DebugSubsectionKind::InlineeLines) 45 continue; 46 47 DebugInlineeLinesSubsectionRef InlineeLines; 48 BinaryStreamReader Reader(SS.getRecordData()); 49 if (auto EC = InlineeLines.initialize(Reader)) { 50 consumeError(std::move(EC)); 51 continue; 52 } 53 54 for (const InlineeSourceLine &Line : InlineeLines) 55 if (Line.Header->Inlinee == Id) 56 return Line; 57 } 58 return None; 59 } 60 61 std::string NativeInlineSiteSymbol::getName() const { 62 auto Tpi = Session.getPDBFile().getPDBTpiStream(); 63 if (!Tpi) { 64 consumeError(Tpi.takeError()); 65 return ""; 66 } 67 auto Ipi = Session.getPDBFile().getPDBIpiStream(); 68 if (!Ipi) { 69 consumeError(Ipi.takeError()); 70 return ""; 71 } 72 73 LazyRandomTypeCollection &Types = Tpi->typeCollection(); 74 LazyRandomTypeCollection &Ids = Ipi->typeCollection(); 75 CVType InlineeType = Ids.getType(Sym.Inlinee); 76 std::string QualifiedName; 77 if (InlineeType.kind() == LF_MFUNC_ID) { 78 MemberFuncIdRecord MFRecord; 79 cantFail(TypeDeserializer::deserializeAs<MemberFuncIdRecord>(InlineeType, 80 MFRecord)); 81 TypeIndex ClassTy = MFRecord.getClassType(); 82 QualifiedName.append(std::string(Types.getTypeName(ClassTy))); 83 QualifiedName.append("::"); 84 } else if (InlineeType.kind() == LF_FUNC_ID) { 85 FuncIdRecord FRecord; 86 cantFail( 87 TypeDeserializer::deserializeAs<FuncIdRecord>(InlineeType, FRecord)); 88 TypeIndex ParentScope = FRecord.getParentScope(); 89 if (!ParentScope.isNoneType()) { 90 QualifiedName.append(std::string(Ids.getTypeName(ParentScope))); 91 QualifiedName.append("::"); 92 } 93 } 94 95 QualifiedName.append(std::string(Ids.getTypeName(Sym.Inlinee))); 96 return QualifiedName; 97 } 98 99 void NativeInlineSiteSymbol::getLineOffset(uint32_t OffsetInFunc, 100 uint32_t &LineOffset, 101 uint32_t &FileOffset) const { 102 LineOffset = 0; 103 FileOffset = 0; 104 uint32_t CodeOffset = 0; 105 for (const auto &Annot : Sym.annotations()) { 106 switch (Annot.OpCode) { 107 case BinaryAnnotationsOpCode::CodeOffset: 108 case BinaryAnnotationsOpCode::ChangeCodeOffset: 109 case BinaryAnnotationsOpCode::ChangeCodeLength: 110 CodeOffset += Annot.U1; 111 break; 112 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: 113 CodeOffset += Annot.U2; 114 break; 115 case BinaryAnnotationsOpCode::ChangeLineOffset: 116 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: 117 CodeOffset += Annot.U1; 118 LineOffset += Annot.S1; 119 break; 120 case BinaryAnnotationsOpCode::ChangeFile: 121 FileOffset = Annot.U1; 122 break; 123 default: 124 break; 125 } 126 127 if (CodeOffset >= OffsetInFunc) 128 return; 129 } 130 } 131 132 std::unique_ptr<IPDBEnumLineNumbers> 133 NativeInlineSiteSymbol::findInlineeLinesByVA(uint64_t VA, 134 uint32_t Length) const { 135 uint16_t Modi; 136 if (!Session.moduleIndexForVA(VA, Modi)) 137 return nullptr; 138 139 Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi); 140 if (!ModS) { 141 consumeError(ModS.takeError()); 142 return nullptr; 143 } 144 145 Expected<DebugChecksumsSubsectionRef> Checksums = 146 ModS->findChecksumsSubsection(); 147 if (!Checksums) { 148 consumeError(Checksums.takeError()); 149 return nullptr; 150 } 151 152 // Get the line number offset and source file offset. 153 uint32_t SrcLineOffset; 154 uint32_t SrcFileOffset; 155 getLineOffset(VA - ParentAddr, SrcLineOffset, SrcFileOffset); 156 157 // Get line info from inlinee line table. 158 Optional<InlineeSourceLine> Inlinee = 159 findInlineeByTypeIndex(Sym.Inlinee, ModS.get()); 160 161 if (!Inlinee) 162 return nullptr; 163 164 uint32_t SrcLine = Inlinee->Header->SourceLineNum + SrcLineOffset; 165 uint32_t SrcCol = 0; // Inline sites don't seem to have column info. 166 uint32_t FileChecksumOffset = 167 (SrcFileOffset == 0) ? Inlinee->Header->FileID : SrcFileOffset; 168 169 auto ChecksumIter = Checksums->getArray().at(FileChecksumOffset); 170 uint32_t SrcFileId = 171 Session.getSymbolCache().getOrCreateSourceFile(*ChecksumIter); 172 173 uint32_t LineSect, LineOff; 174 Session.addressForVA(VA, LineSect, LineOff); 175 NativeLineNumber LineNum(Session, SrcLine, SrcCol, LineSect, LineOff, Length, 176 SrcFileId, Modi); 177 auto SrcFile = Session.getSymbolCache().getSourceFileById(SrcFileId); 178 std::vector<NativeLineNumber> Lines{LineNum}; 179 180 return std::make_unique<NativeEnumLineNumbers>(std::move(Lines)); 181 } 182