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