xref: /src/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1cfca06d7SDimitry Andric //===- NativeFunctionSymbol.cpp - info about function symbols----*- C++ -*-===//
2cfca06d7SDimitry Andric //
3cfca06d7SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4cfca06d7SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5cfca06d7SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cfca06d7SDimitry Andric //
7cfca06d7SDimitry Andric //===----------------------------------------------------------------------===//
8cfca06d7SDimitry Andric 
9cfca06d7SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
10cfca06d7SDimitry Andric 
11145449b1SDimitry Andric #include "llvm/DebugInfo/CodeView/CVRecord.h"
12145449b1SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h"
13b60736ecSDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
14cfca06d7SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
15145449b1SDimitry Andric #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
16b60736ecSDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h"
17145449b1SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
18145449b1SDimitry Andric #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
19145449b1SDimitry Andric #include "llvm/DebugInfo/PDB/PDBExtras.h"
20cfca06d7SDimitry Andric 
21cfca06d7SDimitry Andric using namespace llvm;
22cfca06d7SDimitry Andric using namespace llvm::codeview;
23cfca06d7SDimitry Andric using namespace llvm::pdb;
24cfca06d7SDimitry Andric 
NativeFunctionSymbol(NativeSession & Session,SymIndexId Id,const codeview::ProcSym & Sym,uint32_t Offset)25cfca06d7SDimitry Andric NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session,
26cfca06d7SDimitry Andric                                            SymIndexId Id,
27b60736ecSDimitry Andric                                            const codeview::ProcSym &Sym,
28b60736ecSDimitry Andric                                            uint32_t Offset)
29b60736ecSDimitry Andric     : NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym),
30b60736ecSDimitry Andric       RecordOffset(Offset) {}
31cfca06d7SDimitry Andric 
32145449b1SDimitry Andric NativeFunctionSymbol::~NativeFunctionSymbol() = default;
33cfca06d7SDimitry Andric 
dump(raw_ostream & OS,int Indent,PdbSymbolIdField ShowIdFields,PdbSymbolIdField RecurseIdFields) const34cfca06d7SDimitry Andric void NativeFunctionSymbol::dump(raw_ostream &OS, int Indent,
35cfca06d7SDimitry Andric                                 PdbSymbolIdField ShowIdFields,
36cfca06d7SDimitry Andric                                 PdbSymbolIdField RecurseIdFields) const {
37cfca06d7SDimitry Andric   NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
38cfca06d7SDimitry Andric   dumpSymbolField(OS, "name", getName(), Indent);
39cfca06d7SDimitry Andric   dumpSymbolField(OS, "length", getLength(), Indent);
40cfca06d7SDimitry Andric   dumpSymbolField(OS, "offset", getAddressOffset(), Indent);
41cfca06d7SDimitry Andric   dumpSymbolField(OS, "section", getAddressSection(), Indent);
42cfca06d7SDimitry Andric }
43cfca06d7SDimitry Andric 
getAddressOffset() const44cfca06d7SDimitry Andric uint32_t NativeFunctionSymbol::getAddressOffset() const {
45cfca06d7SDimitry Andric   return Sym.CodeOffset;
46cfca06d7SDimitry Andric }
47cfca06d7SDimitry Andric 
getAddressSection() const48cfca06d7SDimitry Andric uint32_t NativeFunctionSymbol::getAddressSection() const { return Sym.Segment; }
getName() const49cfca06d7SDimitry Andric std::string NativeFunctionSymbol::getName() const {
50cfca06d7SDimitry Andric   return std::string(Sym.Name);
51cfca06d7SDimitry Andric }
52cfca06d7SDimitry Andric 
getLength() const53cfca06d7SDimitry Andric uint64_t NativeFunctionSymbol::getLength() const { return Sym.CodeSize; }
54cfca06d7SDimitry Andric 
getRelativeVirtualAddress() const55cfca06d7SDimitry Andric uint32_t NativeFunctionSymbol::getRelativeVirtualAddress() const {
56cfca06d7SDimitry Andric   return Session.getRVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
57cfca06d7SDimitry Andric }
58cfca06d7SDimitry Andric 
getVirtualAddress() const59cfca06d7SDimitry Andric uint64_t NativeFunctionSymbol::getVirtualAddress() const {
60cfca06d7SDimitry Andric   return Session.getVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
61cfca06d7SDimitry Andric }
62b60736ecSDimitry Andric 
inlineSiteContainsAddress(InlineSiteSym & IS,uint32_t OffsetInFunc)63b60736ecSDimitry Andric static bool inlineSiteContainsAddress(InlineSiteSym &IS,
64b60736ecSDimitry Andric                                       uint32_t OffsetInFunc) {
65b60736ecSDimitry Andric   // Returns true if inline site contains the offset.
66b60736ecSDimitry Andric   bool Found = false;
67b60736ecSDimitry Andric   uint32_t CodeOffset = 0;
68b60736ecSDimitry Andric   for (auto &Annot : IS.annotations()) {
69b60736ecSDimitry Andric     switch (Annot.OpCode) {
70b60736ecSDimitry Andric     case BinaryAnnotationsOpCode::CodeOffset:
71b60736ecSDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeOffset:
72b60736ecSDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
73b60736ecSDimitry Andric       CodeOffset += Annot.U1;
74b60736ecSDimitry Andric       if (OffsetInFunc >= CodeOffset)
75b60736ecSDimitry Andric         Found = true;
76b60736ecSDimitry Andric       break;
77b60736ecSDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeLength:
78b60736ecSDimitry Andric       CodeOffset += Annot.U1;
79b60736ecSDimitry Andric       if (Found && OffsetInFunc < CodeOffset)
80b60736ecSDimitry Andric         return true;
81b60736ecSDimitry Andric       Found = false;
82b60736ecSDimitry Andric       break;
83b60736ecSDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
84b60736ecSDimitry Andric       CodeOffset += Annot.U2;
85b60736ecSDimitry Andric       if (OffsetInFunc >= CodeOffset && OffsetInFunc < CodeOffset + Annot.U1)
86b60736ecSDimitry Andric         return true;
87b60736ecSDimitry Andric       Found = false;
88b60736ecSDimitry Andric       break;
89b60736ecSDimitry Andric     default:
90b60736ecSDimitry Andric       break;
91b60736ecSDimitry Andric     }
92b60736ecSDimitry Andric   }
93b60736ecSDimitry Andric   return false;
94b60736ecSDimitry Andric }
95b60736ecSDimitry Andric 
96b60736ecSDimitry Andric std::unique_ptr<IPDBEnumSymbols>
findInlineFramesByVA(uint64_t VA) const97b60736ecSDimitry Andric NativeFunctionSymbol::findInlineFramesByVA(uint64_t VA) const {
98b60736ecSDimitry Andric   uint16_t Modi;
99b60736ecSDimitry Andric   if (!Session.moduleIndexForVA(VA, Modi))
100b60736ecSDimitry Andric     return nullptr;
101b60736ecSDimitry Andric 
102b60736ecSDimitry Andric   Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi);
103b60736ecSDimitry Andric   if (!ModS) {
104b60736ecSDimitry Andric     consumeError(ModS.takeError());
105b60736ecSDimitry Andric     return nullptr;
106b60736ecSDimitry Andric   }
107b60736ecSDimitry Andric   CVSymbolArray Syms = ModS->getSymbolArray();
108b60736ecSDimitry Andric 
109b60736ecSDimitry Andric   // Search for inline sites. There should be one matching top level inline
110b60736ecSDimitry Andric   // site. Then search in its nested inline sites.
111b60736ecSDimitry Andric   std::vector<SymIndexId> Frames;
112b60736ecSDimitry Andric   uint32_t CodeOffset = VA - getVirtualAddress();
113b60736ecSDimitry Andric   auto Start = Syms.at(RecordOffset);
114b60736ecSDimitry Andric   auto End = Syms.at(Sym.End);
115b60736ecSDimitry Andric   while (Start != End) {
116b60736ecSDimitry Andric     bool Found = false;
117b60736ecSDimitry Andric     // Find matching inline site within Start and End.
118b60736ecSDimitry Andric     for (; Start != End; ++Start) {
119b60736ecSDimitry Andric       if (Start->kind() != S_INLINESITE)
120b60736ecSDimitry Andric         continue;
121b60736ecSDimitry Andric 
122b60736ecSDimitry Andric       InlineSiteSym IS =
123b60736ecSDimitry Andric           cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(*Start));
124b60736ecSDimitry Andric       if (inlineSiteContainsAddress(IS, CodeOffset)) {
125b60736ecSDimitry Andric         // Insert frames in reverse order.
126b60736ecSDimitry Andric         SymIndexId Id = Session.getSymbolCache().getOrCreateInlineSymbol(
127b60736ecSDimitry Andric             IS, getVirtualAddress(), Modi, Start.offset());
128b60736ecSDimitry Andric         Frames.insert(Frames.begin(), Id);
129b60736ecSDimitry Andric 
130b60736ecSDimitry Andric         // Update offsets to search within this inline site.
131b60736ecSDimitry Andric         ++Start;
132b60736ecSDimitry Andric         End = Syms.at(IS.End);
133b60736ecSDimitry Andric         Found = true;
134b60736ecSDimitry Andric         break;
135b60736ecSDimitry Andric       }
136b60736ecSDimitry Andric 
137b60736ecSDimitry Andric       Start = Syms.at(IS.End);
138b60736ecSDimitry Andric       if (Start == End)
139b60736ecSDimitry Andric         break;
140b60736ecSDimitry Andric     }
141b60736ecSDimitry Andric 
142b60736ecSDimitry Andric     if (!Found)
143b60736ecSDimitry Andric       break;
144b60736ecSDimitry Andric   }
145b60736ecSDimitry Andric 
146b60736ecSDimitry Andric   return std::make_unique<NativeEnumSymbols>(Session, std::move(Frames));
147b60736ecSDimitry Andric }
148