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 std::optional<DILineInfo> 36 PDBContext::getLineInfoForAddress(object::SectionedAddress Address, 37 DILineInfoSpecifier Specifier) { 38 DILineInfo Result; 39 Result.FunctionName = getFunctionName(Address.Address, Specifier.FNKind); 40 41 uint32_t Length = 1; 42 std::unique_ptr<PDBSymbol> Symbol = 43 Session->findSymbolByAddress(Address.Address, PDB_SymType::None); 44 if (auto Func = dyn_cast_or_null<PDBSymbolFunc>(Symbol.get())) { 45 Length = Func->getLength(); 46 } else if (auto Data = dyn_cast_or_null<PDBSymbolData>(Symbol.get())) { 47 Length = Data->getLength(); 48 } 49 50 // If we couldn't find a symbol, then just assume 1 byte, so that we get 51 // only the line number of the first instruction. 52 auto LineNumbers = Session->findLineNumbersByAddress(Address.Address, Length); 53 if (!LineNumbers || LineNumbers->getChildCount() == 0) 54 return Result; 55 56 auto LineInfo = LineNumbers->getNext(); 57 assert(LineInfo); 58 auto SourceFile = Session->getSourceFileById(LineInfo->getSourceFileId()); 59 60 if (SourceFile && 61 Specifier.FLIKind != DILineInfoSpecifier::FileLineInfoKind::None) 62 Result.FileName = SourceFile->getFileName(); 63 Result.Column = LineInfo->getColumnNumber(); 64 Result.Line = LineInfo->getLineNumber(); 65 return Result; 66 } 67 68 std::optional<DILineInfo> 69 PDBContext::getLineInfoForDataAddress(object::SectionedAddress Address) { 70 // Unimplemented. S_GDATA and S_LDATA in CodeView (used to describe global 71 // variables) aren't capable of carrying line information. 72 return DILineInfo(); 73 } 74 75 DILineInfoTable 76 PDBContext::getLineInfoForAddressRange(object::SectionedAddress Address, 77 uint64_t Size, 78 DILineInfoSpecifier Specifier) { 79 if (Size == 0) 80 return DILineInfoTable(); 81 82 DILineInfoTable Table; 83 auto LineNumbers = Session->findLineNumbersByAddress(Address.Address, Size); 84 if (!LineNumbers || LineNumbers->getChildCount() == 0) 85 return Table; 86 87 while (auto LineInfo = LineNumbers->getNext()) { 88 if (std::optional<DILineInfo> LineEntry = getLineInfoForAddress( 89 {LineInfo->getVirtualAddress(), Address.SectionIndex}, Specifier)) 90 Table.push_back( 91 std::make_pair(LineInfo->getVirtualAddress(), *LineEntry)); 92 } 93 return Table; 94 } 95 96 DIInliningInfo 97 PDBContext::getInliningInfoForAddress(object::SectionedAddress Address, 98 DILineInfoSpecifier Specifier) { 99 DIInliningInfo InlineInfo; 100 DILineInfo CurrentLine = 101 getLineInfoForAddress(Address, Specifier).value_or(DILineInfo()); 102 103 // Find the function at this address. 104 std::unique_ptr<PDBSymbol> ParentFunc = 105 Session->findSymbolByAddress(Address.Address, PDB_SymType::Function); 106 if (!ParentFunc) { 107 InlineInfo.addFrame(CurrentLine); 108 return InlineInfo; 109 } 110 111 auto Frames = ParentFunc->findInlineFramesByVA(Address.Address); 112 if (!Frames || Frames->getChildCount() == 0) { 113 InlineInfo.addFrame(CurrentLine); 114 return InlineInfo; 115 } 116 117 while (auto Frame = Frames->getNext()) { 118 uint32_t Length = 1; 119 auto LineNumbers = Frame->findInlineeLinesByVA(Address.Address, Length); 120 if (!LineNumbers || LineNumbers->getChildCount() == 0) 121 break; 122 123 std::unique_ptr<IPDBLineNumber> Line = LineNumbers->getNext(); 124 assert(Line); 125 126 DILineInfo LineInfo; 127 LineInfo.FunctionName = Frame->getName(); 128 auto SourceFile = Session->getSourceFileById(Line->getSourceFileId()); 129 if (SourceFile && 130 Specifier.FLIKind != DILineInfoSpecifier::FileLineInfoKind::None) 131 LineInfo.FileName = SourceFile->getFileName(); 132 LineInfo.Line = Line->getLineNumber(); 133 LineInfo.Column = Line->getColumnNumber(); 134 InlineInfo.addFrame(LineInfo); 135 } 136 137 InlineInfo.addFrame(CurrentLine); 138 return InlineInfo; 139 } 140 141 std::vector<DILocal> 142 PDBContext::getLocalsForAddress(object::SectionedAddress Address) { 143 return std::vector<DILocal>(); 144 } 145 146 std::string PDBContext::getFunctionName(uint64_t Address, 147 DINameKind NameKind) const { 148 if (NameKind == DINameKind::None) 149 return std::string(); 150 151 std::unique_ptr<PDBSymbol> FuncSymbol = 152 Session->findSymbolByAddress(Address, PDB_SymType::Function); 153 auto *Func = dyn_cast_or_null<PDBSymbolFunc>(FuncSymbol.get()); 154 155 if (NameKind == DINameKind::LinkageName) { 156 // It is not possible to get the mangled linkage name through a 157 // PDBSymbolFunc. For that we have to specifically request a 158 // PDBSymbolPublicSymbol. 159 auto PublicSym = 160 Session->findSymbolByAddress(Address, PDB_SymType::PublicSymbol); 161 if (auto *PS = dyn_cast_or_null<PDBSymbolPublicSymbol>(PublicSym.get())) { 162 // If we also have a function symbol, prefer the use of public symbol name 163 // only if it refers to the same address. The public symbol uses the 164 // linkage name while the function does not. 165 if (!Func || Func->getVirtualAddress() == PS->getVirtualAddress()) 166 return PS->getName(); 167 } 168 } 169 170 return Func ? Func->getName() : std::string(); 171 } 172