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 11bc980340SAmy Huang #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" 12641ae73fSAmy Huang #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 13bc980340SAmy 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, 23bc980340SAmy Huang const codeview::ProcSym &Sym, 24bc980340SAmy Huang uint32_t Offset) 25bc980340SAmy Huang : NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym), 26bc980340SAmy 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 } 58bc980340SAmy Huang 59bc980340SAmy Huang static bool inlineSiteContainsAddress(InlineSiteSym &IS, 60bc980340SAmy Huang uint32_t OffsetInFunc) { 61bc980340SAmy Huang // Returns true if inline site contains the offset. 62bc980340SAmy Huang bool Found = false; 63bc980340SAmy Huang uint32_t CodeOffset = 0; 64bc980340SAmy Huang for (auto &Annot : IS.annotations()) { 65bc980340SAmy Huang switch (Annot.OpCode) { 66bc980340SAmy Huang case BinaryAnnotationsOpCode::CodeOffset: 67bc980340SAmy Huang case BinaryAnnotationsOpCode::ChangeCodeOffset: 68bc980340SAmy Huang case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: 69bc980340SAmy Huang CodeOffset += Annot.U1; 70bc980340SAmy Huang if (OffsetInFunc >= CodeOffset) 71bc980340SAmy Huang Found = true; 72bc980340SAmy Huang break; 73bc980340SAmy Huang case BinaryAnnotationsOpCode::ChangeCodeLength: 74bc980340SAmy Huang CodeOffset += Annot.U1; 75bc980340SAmy Huang if (Found && OffsetInFunc < CodeOffset) 76bc980340SAmy Huang return true; 77bc980340SAmy Huang Found = false; 78bc980340SAmy Huang break; 79bc980340SAmy Huang case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: 80bc980340SAmy Huang CodeOffset += Annot.U2; 81*00bbef2bSAmy Huang if (OffsetInFunc >= CodeOffset && OffsetInFunc < CodeOffset + Annot.U1) 82bc980340SAmy Huang return true; 83bc980340SAmy Huang Found = false; 84bc980340SAmy Huang break; 85bc980340SAmy Huang default: 86bc980340SAmy Huang break; 87bc980340SAmy Huang } 88bc980340SAmy Huang } 89bc980340SAmy Huang return false; 90bc980340SAmy Huang } 91bc980340SAmy Huang 92bc980340SAmy Huang std::unique_ptr<IPDBEnumSymbols> 93bc980340SAmy Huang NativeFunctionSymbol::findInlineFramesByVA(uint64_t VA) const { 94bc980340SAmy Huang uint16_t Modi; 95bc980340SAmy Huang if (!Session.moduleIndexForVA(VA, Modi)) 96bc980340SAmy Huang return nullptr; 97bc980340SAmy Huang 98bc980340SAmy Huang Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi); 99bc980340SAmy Huang if (!ModS) { 100bc980340SAmy Huang consumeError(ModS.takeError()); 101bc980340SAmy Huang return nullptr; 102bc980340SAmy Huang } 103bc980340SAmy Huang CVSymbolArray Syms = ModS->getSymbolArray(); 104bc980340SAmy Huang 105bc980340SAmy Huang // Search for inline sites. There should be one matching top level inline 106bc980340SAmy Huang // site. Then search in its nested inline sites. 107bc980340SAmy Huang std::vector<SymIndexId> Frames; 108bc980340SAmy Huang uint32_t CodeOffset = VA - getVirtualAddress(); 109bc980340SAmy Huang auto Start = Syms.at(RecordOffset); 110bc980340SAmy Huang auto End = Syms.at(Sym.End); 111bc980340SAmy Huang while (Start != End) { 112bc980340SAmy Huang bool Found = false; 113bc980340SAmy Huang // Find matching inline site within Start and End. 114bc980340SAmy Huang for (; Start != End; ++Start) { 115bc980340SAmy Huang if (Start->kind() != S_INLINESITE) 116bc980340SAmy Huang continue; 117bc980340SAmy Huang 118bc980340SAmy Huang InlineSiteSym IS = 119bc980340SAmy Huang cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(*Start)); 120bc980340SAmy Huang if (inlineSiteContainsAddress(IS, CodeOffset)) { 121bc980340SAmy Huang // Insert frames in reverse order. 122bc980340SAmy Huang SymIndexId Id = Session.getSymbolCache().getOrCreateInlineSymbol( 123bc980340SAmy Huang IS, getVirtualAddress(), Modi, Start.offset()); 124bc980340SAmy Huang Frames.insert(Frames.begin(), Id); 125bc980340SAmy Huang 126bc980340SAmy Huang // Update offsets to search within this inline site. 127bc980340SAmy Huang ++Start; 128bc980340SAmy Huang End = Syms.at(IS.End); 129bc980340SAmy Huang Found = true; 130bc980340SAmy Huang break; 131bc980340SAmy Huang } 132bc980340SAmy Huang 133bc980340SAmy Huang Start = Syms.at(IS.End); 134bc980340SAmy Huang if (Start == End) 135bc980340SAmy Huang break; 136bc980340SAmy Huang } 137bc980340SAmy Huang 138bc980340SAmy Huang if (!Found) 139bc980340SAmy Huang break; 140bc980340SAmy Huang } 141bc980340SAmy Huang 142bc980340SAmy Huang return std::make_unique<NativeEnumSymbols>(Session, std::move(Frames)); 143bc980340SAmy Huang } 144