//===- NativeFunctionSymbol.cpp - info about function symbols----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/Native/SymbolCache.h" #include "llvm/DebugInfo/PDB/PDBExtras.h" using namespace llvm; using namespace llvm::codeview; using namespace llvm::pdb; NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session, SymIndexId Id, const codeview::ProcSym &Sym, uint32_t Offset) : NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym), RecordOffset(Offset) {} NativeFunctionSymbol::~NativeFunctionSymbol() = default; void NativeFunctionSymbol::dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, PdbSymbolIdField RecurseIdFields) const { NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); dumpSymbolField(OS, "name", getName(), Indent); dumpSymbolField(OS, "length", getLength(), Indent); dumpSymbolField(OS, "offset", getAddressOffset(), Indent); dumpSymbolField(OS, "section", getAddressSection(), Indent); } uint32_t NativeFunctionSymbol::getAddressOffset() const { return Sym.CodeOffset; } uint32_t NativeFunctionSymbol::getAddressSection() const { return Sym.Segment; } std::string NativeFunctionSymbol::getName() const { return std::string(Sym.Name); } uint64_t NativeFunctionSymbol::getLength() const { return Sym.CodeSize; } uint32_t NativeFunctionSymbol::getRelativeVirtualAddress() const { return Session.getRVAFromSectOffset(Sym.Segment, Sym.CodeOffset); } uint64_t NativeFunctionSymbol::getVirtualAddress() const { return Session.getVAFromSectOffset(Sym.Segment, Sym.CodeOffset); } static bool inlineSiteContainsAddress(InlineSiteSym &IS, uint32_t OffsetInFunc) { // Returns true if inline site contains the offset. bool Found = false; uint32_t CodeOffset = 0; for (auto &Annot : IS.annotations()) { switch (Annot.OpCode) { case BinaryAnnotationsOpCode::CodeOffset: case BinaryAnnotationsOpCode::ChangeCodeOffset: case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: CodeOffset += Annot.U1; if (OffsetInFunc >= CodeOffset) Found = true; break; case BinaryAnnotationsOpCode::ChangeCodeLength: CodeOffset += Annot.U1; if (Found && OffsetInFunc < CodeOffset) return true; Found = false; break; case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: CodeOffset += Annot.U2; if (OffsetInFunc >= CodeOffset && OffsetInFunc < CodeOffset + Annot.U1) return true; Found = false; break; default: break; } } return false; } std::unique_ptr NativeFunctionSymbol::findInlineFramesByVA(uint64_t VA) const { uint16_t Modi; if (!Session.moduleIndexForVA(VA, Modi)) return nullptr; Expected ModS = Session.getModuleDebugStream(Modi); if (!ModS) { consumeError(ModS.takeError()); return nullptr; } CVSymbolArray Syms = ModS->getSymbolArray(); // Search for inline sites. There should be one matching top level inline // site. Then search in its nested inline sites. std::vector Frames; uint32_t CodeOffset = VA - getVirtualAddress(); auto Start = Syms.at(RecordOffset); auto End = Syms.at(Sym.End); while (Start != End) { bool Found = false; // Find matching inline site within Start and End. for (; Start != End; ++Start) { if (Start->kind() != S_INLINESITE) continue; InlineSiteSym IS = cantFail(SymbolDeserializer::deserializeAs(*Start)); if (inlineSiteContainsAddress(IS, CodeOffset)) { // Insert frames in reverse order. SymIndexId Id = Session.getSymbolCache().getOrCreateInlineSymbol( IS, getVirtualAddress(), Modi, Start.offset()); Frames.insert(Frames.begin(), Id); // Update offsets to search within this inline site. ++Start; End = Syms.at(IS.End); Found = true; break; } Start = Syms.at(IS.End); if (Start == End) break; } if (!Found) break; } return std::make_unique(Session, std::move(Frames)); }