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*bc980340SAmy Huang #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
12641ae73fSAmy Huang #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
13*bc980340SAmy Huang #include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h"
14641ae73fSAmy Huang #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
15641ae73fSAmy Huang #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
16641ae73fSAmy Huang 
17641ae73fSAmy Huang using namespace llvm;
18641ae73fSAmy Huang using namespace llvm::codeview;
19641ae73fSAmy Huang using namespace llvm::pdb;
20641ae73fSAmy Huang 
21641ae73fSAmy Huang NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session,
22641ae73fSAmy Huang                                            SymIndexId Id,
23*bc980340SAmy Huang                                            const codeview::ProcSym &Sym,
24*bc980340SAmy Huang                                            uint32_t Offset)
25*bc980340SAmy Huang     : NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym),
26*bc980340SAmy Huang       RecordOffset(Offset) {}
27641ae73fSAmy Huang 
28641ae73fSAmy Huang NativeFunctionSymbol::~NativeFunctionSymbol() {}
29641ae73fSAmy Huang 
30641ae73fSAmy Huang void NativeFunctionSymbol::dump(raw_ostream &OS, int Indent,
31641ae73fSAmy Huang                                 PdbSymbolIdField ShowIdFields,
32641ae73fSAmy Huang                                 PdbSymbolIdField RecurseIdFields) const {
33641ae73fSAmy Huang   NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
34641ae73fSAmy Huang   dumpSymbolField(OS, "name", getName(), Indent);
35641ae73fSAmy Huang   dumpSymbolField(OS, "length", getLength(), Indent);
36641ae73fSAmy Huang   dumpSymbolField(OS, "offset", getAddressOffset(), Indent);
37641ae73fSAmy Huang   dumpSymbolField(OS, "section", getAddressSection(), Indent);
38641ae73fSAmy Huang }
39641ae73fSAmy Huang 
40641ae73fSAmy Huang uint32_t NativeFunctionSymbol::getAddressOffset() const {
41641ae73fSAmy Huang   return Sym.CodeOffset;
42641ae73fSAmy Huang }
43641ae73fSAmy Huang 
44641ae73fSAmy Huang uint32_t NativeFunctionSymbol::getAddressSection() const { return Sym.Segment; }
45641ae73fSAmy Huang std::string NativeFunctionSymbol::getName() const {
46641ae73fSAmy Huang   return std::string(Sym.Name);
47641ae73fSAmy Huang }
48641ae73fSAmy Huang 
49641ae73fSAmy Huang uint64_t NativeFunctionSymbol::getLength() const { return Sym.CodeSize; }
50641ae73fSAmy Huang 
51641ae73fSAmy Huang uint32_t NativeFunctionSymbol::getRelativeVirtualAddress() const {
52641ae73fSAmy Huang   return Session.getRVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
53641ae73fSAmy Huang }
54641ae73fSAmy Huang 
55641ae73fSAmy Huang uint64_t NativeFunctionSymbol::getVirtualAddress() const {
56641ae73fSAmy Huang   return Session.getVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
57641ae73fSAmy Huang }
58*bc980340SAmy Huang 
59*bc980340SAmy Huang static bool inlineSiteContainsAddress(InlineSiteSym &IS,
60*bc980340SAmy Huang                                       uint32_t OffsetInFunc) {
61*bc980340SAmy Huang   // Returns true if inline site contains the offset.
62*bc980340SAmy Huang   bool Found = false;
63*bc980340SAmy Huang   uint32_t CodeOffset = 0;
64*bc980340SAmy Huang   for (auto &Annot : IS.annotations()) {
65*bc980340SAmy Huang     switch (Annot.OpCode) {
66*bc980340SAmy Huang     case BinaryAnnotationsOpCode::CodeOffset:
67*bc980340SAmy Huang     case BinaryAnnotationsOpCode::ChangeCodeOffset:
68*bc980340SAmy Huang     case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
69*bc980340SAmy Huang       CodeOffset += Annot.U1;
70*bc980340SAmy Huang       if (OffsetInFunc >= CodeOffset)
71*bc980340SAmy Huang         Found = true;
72*bc980340SAmy Huang       break;
73*bc980340SAmy Huang     case BinaryAnnotationsOpCode::ChangeCodeLength:
74*bc980340SAmy Huang       CodeOffset += Annot.U1;
75*bc980340SAmy Huang       if (Found && OffsetInFunc < CodeOffset)
76*bc980340SAmy Huang         return true;
77*bc980340SAmy Huang       Found = false;
78*bc980340SAmy Huang       break;
79*bc980340SAmy Huang     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
80*bc980340SAmy Huang       CodeOffset += Annot.U2;
81*bc980340SAmy Huang       if (OffsetInFunc >= CodeOffset)
82*bc980340SAmy Huang         Found = true;
83*bc980340SAmy Huang       CodeOffset += Annot.U1;
84*bc980340SAmy Huang       if (Found && OffsetInFunc < CodeOffset)
85*bc980340SAmy Huang         return true;
86*bc980340SAmy Huang       Found = false;
87*bc980340SAmy Huang       break;
88*bc980340SAmy Huang     default:
89*bc980340SAmy Huang       break;
90*bc980340SAmy Huang     }
91*bc980340SAmy Huang   }
92*bc980340SAmy Huang   return false;
93*bc980340SAmy Huang }
94*bc980340SAmy Huang 
95*bc980340SAmy Huang std::unique_ptr<IPDBEnumSymbols>
96*bc980340SAmy Huang NativeFunctionSymbol::findInlineFramesByVA(uint64_t VA) const {
97*bc980340SAmy Huang   uint16_t Modi;
98*bc980340SAmy Huang   if (!Session.moduleIndexForVA(VA, Modi))
99*bc980340SAmy Huang     return nullptr;
100*bc980340SAmy Huang 
101*bc980340SAmy Huang   Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi);
102*bc980340SAmy Huang   if (!ModS) {
103*bc980340SAmy Huang     consumeError(ModS.takeError());
104*bc980340SAmy Huang     return nullptr;
105*bc980340SAmy Huang   }
106*bc980340SAmy Huang   CVSymbolArray Syms = ModS->getSymbolArray();
107*bc980340SAmy Huang 
108*bc980340SAmy Huang   // Search for inline sites. There should be one matching top level inline
109*bc980340SAmy Huang   // site. Then search in its nested inline sites.
110*bc980340SAmy Huang   std::vector<SymIndexId> Frames;
111*bc980340SAmy Huang   uint32_t CodeOffset = VA - getVirtualAddress();
112*bc980340SAmy Huang   auto Start = Syms.at(RecordOffset);
113*bc980340SAmy Huang   auto End = Syms.at(Sym.End);
114*bc980340SAmy Huang   while (Start != End) {
115*bc980340SAmy Huang     bool Found = false;
116*bc980340SAmy Huang     // Find matching inline site within Start and End.
117*bc980340SAmy Huang     for (; Start != End; ++Start) {
118*bc980340SAmy Huang       if (Start->kind() != S_INLINESITE)
119*bc980340SAmy Huang         continue;
120*bc980340SAmy Huang 
121*bc980340SAmy Huang       InlineSiteSym IS =
122*bc980340SAmy Huang           cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(*Start));
123*bc980340SAmy Huang       if (inlineSiteContainsAddress(IS, CodeOffset)) {
124*bc980340SAmy Huang         fprintf(stderr, "inline: %d\n", Start.offset());
125*bc980340SAmy Huang         // Insert frames in reverse order.
126*bc980340SAmy Huang         SymIndexId Id = Session.getSymbolCache().getOrCreateInlineSymbol(
127*bc980340SAmy Huang             IS, getVirtualAddress(), Modi, Start.offset());
128*bc980340SAmy Huang         Frames.insert(Frames.begin(), Id);
129*bc980340SAmy Huang 
130*bc980340SAmy Huang         // Update offsets to search within this inline site.
131*bc980340SAmy Huang         ++Start;
132*bc980340SAmy Huang         End = Syms.at(IS.End);
133*bc980340SAmy Huang         Found = true;
134*bc980340SAmy Huang         break;
135*bc980340SAmy Huang       }
136*bc980340SAmy Huang 
137*bc980340SAmy Huang       Start = Syms.at(IS.End);
138*bc980340SAmy Huang       if (Start == End)
139*bc980340SAmy Huang         break;
140*bc980340SAmy Huang     }
141*bc980340SAmy Huang 
142*bc980340SAmy Huang     if (!Found)
143*bc980340SAmy Huang       break;
144*bc980340SAmy Huang   }
145*bc980340SAmy Huang 
146*bc980340SAmy Huang   return std::make_unique<NativeEnumSymbols>(Session, std::move(Frames));
147*bc980340SAmy Huang }
148