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