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