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