1 //===-- PDBContext.cpp ------------------------------------------*- 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/PDBContext.h" 10 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" 11 #include "llvm/DebugInfo/PDB/IPDBLineNumber.h" 12 #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" 13 #include "llvm/DebugInfo/PDB/PDBSymbol.h" 14 #include "llvm/DebugInfo/PDB/PDBSymbolData.h" 15 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" 16 #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h" 17 #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" 18 #include "llvm/DebugInfo/PDB/PDBTypes.h" 19 #include "llvm/Object/COFF.h" 20 21 using namespace llvm; 22 using namespace llvm::object; 23 using namespace llvm::pdb; 24 25 PDBContext::PDBContext(const COFFObjectFile &Object, 26 std::unique_ptr<IPDBSession> PDBSession) 27 : DIContext(CK_PDB), Session(std::move(PDBSession)) { 28 ErrorOr<uint64_t> ImageBase = Object.getImageBase(); 29 if (ImageBase) 30 Session->setLoadAddress(ImageBase.get()); 31 } 32 33 void PDBContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){} 34 35 DILineInfo PDBContext::getLineInfoForAddress(object::SectionedAddress Address, 36 DILineInfoSpecifier Specifier) { 37 DILineInfo Result; 38 Result.FunctionName = getFunctionName(Address.Address, Specifier.FNKind); 39 40 uint32_t Length = 1; 41 std::unique_ptr<PDBSymbol> Symbol = 42 Session->findSymbolByAddress(Address.Address, PDB_SymType::None); 43 if (auto Func = dyn_cast_or_null<PDBSymbolFunc>(Symbol.get())) { 44 Length = Func->getLength(); 45 } else if (auto Data = dyn_cast_or_null<PDBSymbolData>(Symbol.get())) { 46 Length = Data->getLength(); 47 } 48 49 // If we couldn't find a symbol, then just assume 1 byte, so that we get 50 // only the line number of the first instruction. 51 auto LineNumbers = Session->findLineNumbersByAddress(Address.Address, Length); 52 if (!LineNumbers || LineNumbers->getChildCount() == 0) 53 return Result; 54 55 auto LineInfo = LineNumbers->getNext(); 56 assert(LineInfo); 57 auto SourceFile = Session->getSourceFileById(LineInfo->getSourceFileId()); 58 59 if (SourceFile && 60 Specifier.FLIKind != DILineInfoSpecifier::FileLineInfoKind::None) 61 Result.FileName = SourceFile->getFileName(); 62 Result.Column = LineInfo->getColumnNumber(); 63 Result.Line = LineInfo->getLineNumber(); 64 return Result; 65 } 66 67 DILineInfoTable 68 PDBContext::getLineInfoForAddressRange(object::SectionedAddress Address, 69 uint64_t Size, 70 DILineInfoSpecifier Specifier) { 71 if (Size == 0) 72 return DILineInfoTable(); 73 74 DILineInfoTable Table; 75 auto LineNumbers = Session->findLineNumbersByAddress(Address.Address, Size); 76 if (!LineNumbers || LineNumbers->getChildCount() == 0) 77 return Table; 78 79 while (auto LineInfo = LineNumbers->getNext()) { 80 DILineInfo LineEntry = getLineInfoForAddress( 81 {LineInfo->getVirtualAddress(), Address.SectionIndex}, Specifier); 82 Table.push_back(std::make_pair(LineInfo->getVirtualAddress(), LineEntry)); 83 } 84 return Table; 85 } 86 87 DIInliningInfo 88 PDBContext::getInliningInfoForAddress(object::SectionedAddress Address, 89 DILineInfoSpecifier Specifier) { 90 DIInliningInfo InlineInfo; 91 DILineInfo CurrentLine = getLineInfoForAddress(Address, Specifier); 92 93 // Find the function at this address. 94 std::unique_ptr<PDBSymbol> ParentFunc = 95 Session->findSymbolByAddress(Address.Address, PDB_SymType::Function); 96 if (!ParentFunc) { 97 InlineInfo.addFrame(CurrentLine); 98 return InlineInfo; 99 } 100 101 auto Frames = ParentFunc->findInlineFramesByVA(Address.Address); 102 if (!Frames || Frames->getChildCount() == 0) { 103 InlineInfo.addFrame(CurrentLine); 104 return InlineInfo; 105 } 106 107 while (auto Frame = Frames->getNext()) { 108 uint32_t Length = 1; 109 auto LineNumbers = Frame->findInlineeLinesByVA(Address.Address, Length); 110 if (!LineNumbers || LineNumbers->getChildCount() == 0) 111 break; 112 113 std::unique_ptr<IPDBLineNumber> Line = LineNumbers->getNext(); 114 assert(Line); 115 116 DILineInfo LineInfo; 117 LineInfo.FunctionName = Frame->getName(); 118 auto SourceFile = Session->getSourceFileById(Line->getSourceFileId()); 119 if (SourceFile && 120 Specifier.FLIKind != DILineInfoSpecifier::FileLineInfoKind::None) 121 LineInfo.FileName = SourceFile->getFileName(); 122 LineInfo.Line = Line->getLineNumber(); 123 LineInfo.Column = Line->getColumnNumber(); 124 InlineInfo.addFrame(LineInfo); 125 } 126 127 InlineInfo.addFrame(CurrentLine); 128 return InlineInfo; 129 } 130 131 std::vector<DILocal> 132 PDBContext::getLocalsForAddress(object::SectionedAddress Address) { 133 return std::vector<DILocal>(); 134 } 135 136 std::string PDBContext::getFunctionName(uint64_t Address, 137 DINameKind NameKind) const { 138 if (NameKind == DINameKind::None) 139 return std::string(); 140 141 std::unique_ptr<PDBSymbol> FuncSymbol = 142 Session->findSymbolByAddress(Address, PDB_SymType::Function); 143 auto *Func = dyn_cast_or_null<PDBSymbolFunc>(FuncSymbol.get()); 144 145 if (NameKind == DINameKind::LinkageName) { 146 // It is not possible to get the mangled linkage name through a 147 // PDBSymbolFunc. For that we have to specifically request a 148 // PDBSymbolPublicSymbol. 149 auto PublicSym = 150 Session->findSymbolByAddress(Address, PDB_SymType::PublicSymbol); 151 if (auto *PS = dyn_cast_or_null<PDBSymbolPublicSymbol>(PublicSym.get())) { 152 // If we also have a function symbol, prefer the use of public symbol name 153 // only if it refers to the same address. The public symbol uses the 154 // linkage name while the function does not. 155 if (!Func || Func->getVirtualAddress() == PS->getVirtualAddress()) 156 return PS->getName(); 157 } 158 } 159 160 return Func ? Func->getName() : std::string(); 161 } 162