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) 82 Found = true; 83 CodeOffset += Annot.U1; 84 if (Found && OffsetInFunc < CodeOffset) 85 return true; 86 Found = false; 87 break; 88 default: 89 break; 90 } 91 } 92 return false; 93 } 94 95 std::unique_ptr<IPDBEnumSymbols> 96 NativeFunctionSymbol::findInlineFramesByVA(uint64_t VA) const { 97 uint16_t Modi; 98 if (!Session.moduleIndexForVA(VA, Modi)) 99 return nullptr; 100 101 Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi); 102 if (!ModS) { 103 consumeError(ModS.takeError()); 104 return nullptr; 105 } 106 CVSymbolArray Syms = ModS->getSymbolArray(); 107 108 // Search for inline sites. There should be one matching top level inline 109 // site. Then search in its nested inline sites. 110 std::vector<SymIndexId> Frames; 111 uint32_t CodeOffset = VA - getVirtualAddress(); 112 auto Start = Syms.at(RecordOffset); 113 auto End = Syms.at(Sym.End); 114 while (Start != End) { 115 bool Found = false; 116 // Find matching inline site within Start and End. 117 for (; Start != End; ++Start) { 118 if (Start->kind() != S_INLINESITE) 119 continue; 120 121 InlineSiteSym IS = 122 cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(*Start)); 123 if (inlineSiteContainsAddress(IS, CodeOffset)) { 124 // Insert frames in reverse order. 125 SymIndexId Id = Session.getSymbolCache().getOrCreateInlineSymbol( 126 IS, getVirtualAddress(), Modi, Start.offset()); 127 Frames.insert(Frames.begin(), Id); 128 129 // Update offsets to search within this inline site. 130 ++Start; 131 End = Syms.at(IS.End); 132 Found = true; 133 break; 134 } 135 136 Start = Syms.at(IS.End); 137 if (Start == End) 138 break; 139 } 140 141 if (!Found) 142 break; 143 } 144 145 return std::make_unique<NativeEnumSymbols>(Session, std::move(Frames)); 146 } 147