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
NativeInlineSiteSymbol(NativeSession & Session,SymIndexId Id,const codeview::InlineSiteSym & Sym,uint64_t ParentAddr)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
~NativeInlineSiteSymbol()28 NativeInlineSiteSymbol::~NativeInlineSiteSymbol() {}
29
dump(raw_ostream & OS,int Indent,PdbSymbolIdField ShowIdFields,PdbSymbolIdField RecurseIdFields) const30 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>
findInlineeByTypeIndex(TypeIndex Id,ModuleDebugStreamRef & ModS)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
getName() const57 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
getLineOffset(uint32_t OffsetInFunc,uint32_t & LineOffset,uint32_t & FileOffset) const95 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>
findInlineeLinesByVA(uint64_t VA,uint32_t Length) const129 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