1 //===- NativeFunctionSymbol.cpp - info about function symbols----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h" 10 11 #include "llvm/DebugInfo/CodeView/CVRecord.h" 12 #include "llvm/DebugInfo/CodeView/CodeView.h" 13 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" 14 #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 15 #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" 16 #include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h" 17 #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 18 #include "llvm/DebugInfo/PDB/Native/SymbolCache.h" 19 #include "llvm/DebugInfo/PDB/PDBExtras.h" 20 21 using namespace llvm; 22 using namespace llvm::codeview; 23 using namespace llvm::pdb; 24 25 NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session, 26 SymIndexId Id, 27 const codeview::ProcSym &Sym, 28 uint32_t Offset) 29 : NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym), 30 RecordOffset(Offset) {} 31 32 NativeFunctionSymbol::~NativeFunctionSymbol() = default; 33 34 void NativeFunctionSymbol::dump(raw_ostream &OS, int Indent, 35 PdbSymbolIdField ShowIdFields, 36 PdbSymbolIdField RecurseIdFields) const { 37 NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); 38 dumpSymbolField(OS, "name", getName(), Indent); 39 dumpSymbolField(OS, "length", getLength(), Indent); 40 dumpSymbolField(OS, "offset", getAddressOffset(), Indent); 41 dumpSymbolField(OS, "section", getAddressSection(), Indent); 42 } 43 44 uint32_t NativeFunctionSymbol::getAddressOffset() const { 45 return Sym.CodeOffset; 46 } 47 48 uint32_t NativeFunctionSymbol::getAddressSection() const { return Sym.Segment; } 49 std::string NativeFunctionSymbol::getName() const { 50 return std::string(Sym.Name); 51 } 52 53 uint64_t NativeFunctionSymbol::getLength() const { return Sym.CodeSize; } 54 55 uint32_t NativeFunctionSymbol::getRelativeVirtualAddress() const { 56 return Session.getRVAFromSectOffset(Sym.Segment, Sym.CodeOffset); 57 } 58 59 uint64_t NativeFunctionSymbol::getVirtualAddress() const { 60 return Session.getVAFromSectOffset(Sym.Segment, Sym.CodeOffset); 61 } 62 63 static bool inlineSiteContainsAddress(InlineSiteSym &IS, 64 uint32_t OffsetInFunc) { 65 // Returns true if inline site contains the offset. 66 bool Found = false; 67 uint32_t CodeOffset = 0; 68 for (auto &Annot : IS.annotations()) { 69 switch (Annot.OpCode) { 70 case BinaryAnnotationsOpCode::CodeOffset: 71 case BinaryAnnotationsOpCode::ChangeCodeOffset: 72 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: 73 CodeOffset += Annot.U1; 74 if (OffsetInFunc >= CodeOffset) 75 Found = true; 76 break; 77 case BinaryAnnotationsOpCode::ChangeCodeLength: 78 CodeOffset += Annot.U1; 79 if (Found && OffsetInFunc < CodeOffset) 80 return true; 81 Found = false; 82 break; 83 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: 84 CodeOffset += Annot.U2; 85 if (OffsetInFunc >= CodeOffset && OffsetInFunc < CodeOffset + Annot.U1) 86 return true; 87 Found = false; 88 break; 89 default: 90 break; 91 } 92 } 93 return false; 94 } 95 96 std::unique_ptr<IPDBEnumSymbols> 97 NativeFunctionSymbol::findInlineFramesByVA(uint64_t VA) const { 98 uint16_t Modi; 99 if (!Session.moduleIndexForVA(VA, Modi)) 100 return nullptr; 101 102 Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi); 103 if (!ModS) { 104 consumeError(ModS.takeError()); 105 return nullptr; 106 } 107 CVSymbolArray Syms = ModS->getSymbolArray(); 108 109 // Search for inline sites. There should be one matching top level inline 110 // site. Then search in its nested inline sites. 111 std::vector<SymIndexId> Frames; 112 uint32_t CodeOffset = VA - getVirtualAddress(); 113 auto Start = Syms.at(RecordOffset); 114 auto End = Syms.at(Sym.End); 115 while (Start != End) { 116 bool Found = false; 117 // Find matching inline site within Start and End. 118 for (; Start != End; ++Start) { 119 if (Start->kind() != S_INLINESITE) 120 continue; 121 122 InlineSiteSym IS = 123 cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(*Start)); 124 if (inlineSiteContainsAddress(IS, CodeOffset)) { 125 // Insert frames in reverse order. 126 SymIndexId Id = Session.getSymbolCache().getOrCreateInlineSymbol( 127 IS, getVirtualAddress(), Modi, Start.offset()); 128 Frames.insert(Frames.begin(), Id); 129 130 // Update offsets to search within this inline site. 131 ++Start; 132 End = Syms.at(IS.End); 133 Found = true; 134 break; 135 } 136 137 Start = Syms.at(IS.End); 138 if (Start == End) 139 break; 140 } 141 142 if (!Found) 143 break; 144 } 145 146 return std::make_unique<NativeEnumSymbols>(Session, std::move(Frames)); 147 } 148