1641ae73fSAmy Huang //===- NativeFunctionSymbol.cpp - info about function symbols----*- C++ -*-===//
2641ae73fSAmy Huang //
3641ae73fSAmy Huang // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4641ae73fSAmy Huang // See https://llvm.org/LICENSE.txt for license information.
5641ae73fSAmy Huang // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6641ae73fSAmy Huang //
7641ae73fSAmy Huang //===----------------------------------------------------------------------===//
8641ae73fSAmy Huang
9641ae73fSAmy Huang #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
10641ae73fSAmy Huang
11*eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/CodeView/CVRecord.h"
12*eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/CodeView/CodeView.h"
13bc980340SAmy Huang #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
14641ae73fSAmy Huang #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
15*eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
16bc980340SAmy Huang #include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h"
17*eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
18*eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
19*eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/PDB/PDBExtras.h"
20641ae73fSAmy Huang
21641ae73fSAmy Huang using namespace llvm;
22641ae73fSAmy Huang using namespace llvm::codeview;
23641ae73fSAmy Huang using namespace llvm::pdb;
24641ae73fSAmy Huang
NativeFunctionSymbol(NativeSession & Session,SymIndexId Id,const codeview::ProcSym & Sym,uint32_t Offset)25641ae73fSAmy Huang NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session,
26641ae73fSAmy Huang SymIndexId Id,
27bc980340SAmy Huang const codeview::ProcSym &Sym,
28bc980340SAmy Huang uint32_t Offset)
29bc980340SAmy Huang : NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym),
30bc980340SAmy Huang RecordOffset(Offset) {}
31641ae73fSAmy Huang
323a3cb929SKazu Hirata NativeFunctionSymbol::~NativeFunctionSymbol() = default;
33641ae73fSAmy Huang
dump(raw_ostream & OS,int Indent,PdbSymbolIdField ShowIdFields,PdbSymbolIdField RecurseIdFields) const34641ae73fSAmy Huang void NativeFunctionSymbol::dump(raw_ostream &OS, int Indent,
35641ae73fSAmy Huang PdbSymbolIdField ShowIdFields,
36641ae73fSAmy Huang PdbSymbolIdField RecurseIdFields) const {
37641ae73fSAmy Huang NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
38641ae73fSAmy Huang dumpSymbolField(OS, "name", getName(), Indent);
39641ae73fSAmy Huang dumpSymbolField(OS, "length", getLength(), Indent);
40641ae73fSAmy Huang dumpSymbolField(OS, "offset", getAddressOffset(), Indent);
41641ae73fSAmy Huang dumpSymbolField(OS, "section", getAddressSection(), Indent);
42641ae73fSAmy Huang }
43641ae73fSAmy Huang
getAddressOffset() const44641ae73fSAmy Huang uint32_t NativeFunctionSymbol::getAddressOffset() const {
45641ae73fSAmy Huang return Sym.CodeOffset;
46641ae73fSAmy Huang }
47641ae73fSAmy Huang
getAddressSection() const48641ae73fSAmy Huang uint32_t NativeFunctionSymbol::getAddressSection() const { return Sym.Segment; }
getName() const49641ae73fSAmy Huang std::string NativeFunctionSymbol::getName() const {
50641ae73fSAmy Huang return std::string(Sym.Name);
51641ae73fSAmy Huang }
52641ae73fSAmy Huang
getLength() const53641ae73fSAmy Huang uint64_t NativeFunctionSymbol::getLength() const { return Sym.CodeSize; }
54641ae73fSAmy Huang
getRelativeVirtualAddress() const55641ae73fSAmy Huang uint32_t NativeFunctionSymbol::getRelativeVirtualAddress() const {
56641ae73fSAmy Huang return Session.getRVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
57641ae73fSAmy Huang }
58641ae73fSAmy Huang
getVirtualAddress() const59641ae73fSAmy Huang uint64_t NativeFunctionSymbol::getVirtualAddress() const {
60641ae73fSAmy Huang return Session.getVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
61641ae73fSAmy Huang }
62bc980340SAmy Huang
inlineSiteContainsAddress(InlineSiteSym & IS,uint32_t OffsetInFunc)63bc980340SAmy Huang static bool inlineSiteContainsAddress(InlineSiteSym &IS,
64bc980340SAmy Huang uint32_t OffsetInFunc) {
65bc980340SAmy Huang // Returns true if inline site contains the offset.
66bc980340SAmy Huang bool Found = false;
67bc980340SAmy Huang uint32_t CodeOffset = 0;
68bc980340SAmy Huang for (auto &Annot : IS.annotations()) {
69bc980340SAmy Huang switch (Annot.OpCode) {
70bc980340SAmy Huang case BinaryAnnotationsOpCode::CodeOffset:
71bc980340SAmy Huang case BinaryAnnotationsOpCode::ChangeCodeOffset:
72bc980340SAmy Huang case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
73bc980340SAmy Huang CodeOffset += Annot.U1;
74bc980340SAmy Huang if (OffsetInFunc >= CodeOffset)
75bc980340SAmy Huang Found = true;
76bc980340SAmy Huang break;
77bc980340SAmy Huang case BinaryAnnotationsOpCode::ChangeCodeLength:
78bc980340SAmy Huang CodeOffset += Annot.U1;
79bc980340SAmy Huang if (Found && OffsetInFunc < CodeOffset)
80bc980340SAmy Huang return true;
81bc980340SAmy Huang Found = false;
82bc980340SAmy Huang break;
83bc980340SAmy Huang case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
84bc980340SAmy Huang CodeOffset += Annot.U2;
8500bbef2bSAmy Huang if (OffsetInFunc >= CodeOffset && OffsetInFunc < CodeOffset + Annot.U1)
86bc980340SAmy Huang return true;
87bc980340SAmy Huang Found = false;
88bc980340SAmy Huang break;
89bc980340SAmy Huang default:
90bc980340SAmy Huang break;
91bc980340SAmy Huang }
92bc980340SAmy Huang }
93bc980340SAmy Huang return false;
94bc980340SAmy Huang }
95bc980340SAmy Huang
96bc980340SAmy Huang std::unique_ptr<IPDBEnumSymbols>
findInlineFramesByVA(uint64_t VA) const97bc980340SAmy Huang NativeFunctionSymbol::findInlineFramesByVA(uint64_t VA) const {
98bc980340SAmy Huang uint16_t Modi;
99bc980340SAmy Huang if (!Session.moduleIndexForVA(VA, Modi))
100bc980340SAmy Huang return nullptr;
101bc980340SAmy Huang
102bc980340SAmy Huang Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi);
103bc980340SAmy Huang if (!ModS) {
104bc980340SAmy Huang consumeError(ModS.takeError());
105bc980340SAmy Huang return nullptr;
106bc980340SAmy Huang }
107bc980340SAmy Huang CVSymbolArray Syms = ModS->getSymbolArray();
108bc980340SAmy Huang
109bc980340SAmy Huang // Search for inline sites. There should be one matching top level inline
110bc980340SAmy Huang // site. Then search in its nested inline sites.
111bc980340SAmy Huang std::vector<SymIndexId> Frames;
112bc980340SAmy Huang uint32_t CodeOffset = VA - getVirtualAddress();
113bc980340SAmy Huang auto Start = Syms.at(RecordOffset);
114bc980340SAmy Huang auto End = Syms.at(Sym.End);
115bc980340SAmy Huang while (Start != End) {
116bc980340SAmy Huang bool Found = false;
117bc980340SAmy Huang // Find matching inline site within Start and End.
118bc980340SAmy Huang for (; Start != End; ++Start) {
119bc980340SAmy Huang if (Start->kind() != S_INLINESITE)
120bc980340SAmy Huang continue;
121bc980340SAmy Huang
122bc980340SAmy Huang InlineSiteSym IS =
123bc980340SAmy Huang cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(*Start));
124bc980340SAmy Huang if (inlineSiteContainsAddress(IS, CodeOffset)) {
125bc980340SAmy Huang // Insert frames in reverse order.
126bc980340SAmy Huang SymIndexId Id = Session.getSymbolCache().getOrCreateInlineSymbol(
127bc980340SAmy Huang IS, getVirtualAddress(), Modi, Start.offset());
128bc980340SAmy Huang Frames.insert(Frames.begin(), Id);
129bc980340SAmy Huang
130bc980340SAmy Huang // Update offsets to search within this inline site.
131bc980340SAmy Huang ++Start;
132bc980340SAmy Huang End = Syms.at(IS.End);
133bc980340SAmy Huang Found = true;
134bc980340SAmy Huang break;
135bc980340SAmy Huang }
136bc980340SAmy Huang
137bc980340SAmy Huang Start = Syms.at(IS.End);
138bc980340SAmy Huang if (Start == End)
139bc980340SAmy Huang break;
140bc980340SAmy Huang }
141bc980340SAmy Huang
142bc980340SAmy Huang if (!Found)
143bc980340SAmy Huang break;
144bc980340SAmy Huang }
145bc980340SAmy Huang
146bc980340SAmy Huang return std::make_unique<NativeEnumSymbols>(Session, std::move(Frames));
147bc980340SAmy Huang }
148