xref: /freebsd-src/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
15ffd83dbSDimitry Andric //===- NativeFunctionSymbol.cpp - info about function symbols----*- C++ -*-===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric 
95ffd83dbSDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
105ffd83dbSDimitry Andric 
11*e8d8bef9SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
125ffd83dbSDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
13*e8d8bef9SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h"
145ffd83dbSDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
155ffd83dbSDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
165ffd83dbSDimitry Andric 
175ffd83dbSDimitry Andric using namespace llvm;
185ffd83dbSDimitry Andric using namespace llvm::codeview;
195ffd83dbSDimitry Andric using namespace llvm::pdb;
205ffd83dbSDimitry Andric 
215ffd83dbSDimitry Andric NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session,
225ffd83dbSDimitry Andric                                            SymIndexId Id,
23*e8d8bef9SDimitry Andric                                            const codeview::ProcSym &Sym,
24*e8d8bef9SDimitry Andric                                            uint32_t Offset)
25*e8d8bef9SDimitry Andric     : NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym),
26*e8d8bef9SDimitry Andric       RecordOffset(Offset) {}
275ffd83dbSDimitry Andric 
285ffd83dbSDimitry Andric NativeFunctionSymbol::~NativeFunctionSymbol() {}
295ffd83dbSDimitry Andric 
305ffd83dbSDimitry Andric void NativeFunctionSymbol::dump(raw_ostream &OS, int Indent,
315ffd83dbSDimitry Andric                                 PdbSymbolIdField ShowIdFields,
325ffd83dbSDimitry Andric                                 PdbSymbolIdField RecurseIdFields) const {
335ffd83dbSDimitry Andric   NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
345ffd83dbSDimitry Andric   dumpSymbolField(OS, "name", getName(), Indent);
355ffd83dbSDimitry Andric   dumpSymbolField(OS, "length", getLength(), Indent);
365ffd83dbSDimitry Andric   dumpSymbolField(OS, "offset", getAddressOffset(), Indent);
375ffd83dbSDimitry Andric   dumpSymbolField(OS, "section", getAddressSection(), Indent);
385ffd83dbSDimitry Andric }
395ffd83dbSDimitry Andric 
405ffd83dbSDimitry Andric uint32_t NativeFunctionSymbol::getAddressOffset() const {
415ffd83dbSDimitry Andric   return Sym.CodeOffset;
425ffd83dbSDimitry Andric }
435ffd83dbSDimitry Andric 
445ffd83dbSDimitry Andric uint32_t NativeFunctionSymbol::getAddressSection() const { return Sym.Segment; }
455ffd83dbSDimitry Andric std::string NativeFunctionSymbol::getName() const {
465ffd83dbSDimitry Andric   return std::string(Sym.Name);
475ffd83dbSDimitry Andric }
485ffd83dbSDimitry Andric 
495ffd83dbSDimitry Andric uint64_t NativeFunctionSymbol::getLength() const { return Sym.CodeSize; }
505ffd83dbSDimitry Andric 
515ffd83dbSDimitry Andric uint32_t NativeFunctionSymbol::getRelativeVirtualAddress() const {
525ffd83dbSDimitry Andric   return Session.getRVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
535ffd83dbSDimitry Andric }
545ffd83dbSDimitry Andric 
555ffd83dbSDimitry Andric uint64_t NativeFunctionSymbol::getVirtualAddress() const {
565ffd83dbSDimitry Andric   return Session.getVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
575ffd83dbSDimitry Andric }
58*e8d8bef9SDimitry Andric 
59*e8d8bef9SDimitry Andric static bool inlineSiteContainsAddress(InlineSiteSym &IS,
60*e8d8bef9SDimitry Andric                                       uint32_t OffsetInFunc) {
61*e8d8bef9SDimitry Andric   // Returns true if inline site contains the offset.
62*e8d8bef9SDimitry Andric   bool Found = false;
63*e8d8bef9SDimitry Andric   uint32_t CodeOffset = 0;
64*e8d8bef9SDimitry Andric   for (auto &Annot : IS.annotations()) {
65*e8d8bef9SDimitry Andric     switch (Annot.OpCode) {
66*e8d8bef9SDimitry Andric     case BinaryAnnotationsOpCode::CodeOffset:
67*e8d8bef9SDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeOffset:
68*e8d8bef9SDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
69*e8d8bef9SDimitry Andric       CodeOffset += Annot.U1;
70*e8d8bef9SDimitry Andric       if (OffsetInFunc >= CodeOffset)
71*e8d8bef9SDimitry Andric         Found = true;
72*e8d8bef9SDimitry Andric       break;
73*e8d8bef9SDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeLength:
74*e8d8bef9SDimitry Andric       CodeOffset += Annot.U1;
75*e8d8bef9SDimitry Andric       if (Found && OffsetInFunc < CodeOffset)
76*e8d8bef9SDimitry Andric         return true;
77*e8d8bef9SDimitry Andric       Found = false;
78*e8d8bef9SDimitry Andric       break;
79*e8d8bef9SDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
80*e8d8bef9SDimitry Andric       CodeOffset += Annot.U2;
81*e8d8bef9SDimitry Andric       if (OffsetInFunc >= CodeOffset && OffsetInFunc < CodeOffset + Annot.U1)
82*e8d8bef9SDimitry Andric         return true;
83*e8d8bef9SDimitry Andric       Found = false;
84*e8d8bef9SDimitry Andric       break;
85*e8d8bef9SDimitry Andric     default:
86*e8d8bef9SDimitry Andric       break;
87*e8d8bef9SDimitry Andric     }
88*e8d8bef9SDimitry Andric   }
89*e8d8bef9SDimitry Andric   return false;
90*e8d8bef9SDimitry Andric }
91*e8d8bef9SDimitry Andric 
92*e8d8bef9SDimitry Andric std::unique_ptr<IPDBEnumSymbols>
93*e8d8bef9SDimitry Andric NativeFunctionSymbol::findInlineFramesByVA(uint64_t VA) const {
94*e8d8bef9SDimitry Andric   uint16_t Modi;
95*e8d8bef9SDimitry Andric   if (!Session.moduleIndexForVA(VA, Modi))
96*e8d8bef9SDimitry Andric     return nullptr;
97*e8d8bef9SDimitry Andric 
98*e8d8bef9SDimitry Andric   Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi);
99*e8d8bef9SDimitry Andric   if (!ModS) {
100*e8d8bef9SDimitry Andric     consumeError(ModS.takeError());
101*e8d8bef9SDimitry Andric     return nullptr;
102*e8d8bef9SDimitry Andric   }
103*e8d8bef9SDimitry Andric   CVSymbolArray Syms = ModS->getSymbolArray();
104*e8d8bef9SDimitry Andric 
105*e8d8bef9SDimitry Andric   // Search for inline sites. There should be one matching top level inline
106*e8d8bef9SDimitry Andric   // site. Then search in its nested inline sites.
107*e8d8bef9SDimitry Andric   std::vector<SymIndexId> Frames;
108*e8d8bef9SDimitry Andric   uint32_t CodeOffset = VA - getVirtualAddress();
109*e8d8bef9SDimitry Andric   auto Start = Syms.at(RecordOffset);
110*e8d8bef9SDimitry Andric   auto End = Syms.at(Sym.End);
111*e8d8bef9SDimitry Andric   while (Start != End) {
112*e8d8bef9SDimitry Andric     bool Found = false;
113*e8d8bef9SDimitry Andric     // Find matching inline site within Start and End.
114*e8d8bef9SDimitry Andric     for (; Start != End; ++Start) {
115*e8d8bef9SDimitry Andric       if (Start->kind() != S_INLINESITE)
116*e8d8bef9SDimitry Andric         continue;
117*e8d8bef9SDimitry Andric 
118*e8d8bef9SDimitry Andric       InlineSiteSym IS =
119*e8d8bef9SDimitry Andric           cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(*Start));
120*e8d8bef9SDimitry Andric       if (inlineSiteContainsAddress(IS, CodeOffset)) {
121*e8d8bef9SDimitry Andric         // Insert frames in reverse order.
122*e8d8bef9SDimitry Andric         SymIndexId Id = Session.getSymbolCache().getOrCreateInlineSymbol(
123*e8d8bef9SDimitry Andric             IS, getVirtualAddress(), Modi, Start.offset());
124*e8d8bef9SDimitry Andric         Frames.insert(Frames.begin(), Id);
125*e8d8bef9SDimitry Andric 
126*e8d8bef9SDimitry Andric         // Update offsets to search within this inline site.
127*e8d8bef9SDimitry Andric         ++Start;
128*e8d8bef9SDimitry Andric         End = Syms.at(IS.End);
129*e8d8bef9SDimitry Andric         Found = true;
130*e8d8bef9SDimitry Andric         break;
131*e8d8bef9SDimitry Andric       }
132*e8d8bef9SDimitry Andric 
133*e8d8bef9SDimitry Andric       Start = Syms.at(IS.End);
134*e8d8bef9SDimitry Andric       if (Start == End)
135*e8d8bef9SDimitry Andric         break;
136*e8d8bef9SDimitry Andric     }
137*e8d8bef9SDimitry Andric 
138*e8d8bef9SDimitry Andric     if (!Found)
139*e8d8bef9SDimitry Andric       break;
140*e8d8bef9SDimitry Andric   }
141*e8d8bef9SDimitry Andric 
142*e8d8bef9SDimitry Andric   return std::make_unique<NativeEnumSymbols>(Session, std::move(Frames));
143*e8d8bef9SDimitry Andric }
144