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