120dbd0d0SZachary Turner //===-- PDBContext.cpp ------------------------------------------*- C++ -*-===//
220dbd0d0SZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
620dbd0d0SZachary Turner //
720dbd0d0SZachary Turner //===----------------------------------------------------------------------===/
820dbd0d0SZachary Turner
920dbd0d0SZachary Turner #include "llvm/DebugInfo/PDB/PDBContext.h"
1020dbd0d0SZachary Turner #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
1120dbd0d0SZachary Turner #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
1220dbd0d0SZachary Turner #include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
1320dbd0d0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbol.h"
1420dbd0d0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
156bda14b3SChandler Carruth #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
16c007aa41SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
17eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
18ed98c1b3Sserge-sans-paille #include "llvm/DebugInfo/PDB/PDBTypes.h"
1920dbd0d0SZachary Turner #include "llvm/Object/COFF.h"
2020dbd0d0SZachary Turner
2120dbd0d0SZachary Turner using namespace llvm;
2220dbd0d0SZachary Turner using namespace llvm::object;
23ec28fc34SZachary Turner using namespace llvm::pdb;
2420dbd0d0SZachary Turner
PDBContext(const COFFObjectFile & Object,std::unique_ptr<IPDBSession> PDBSession)2520dbd0d0SZachary Turner PDBContext::PDBContext(const COFFObjectFile &Object,
26e94fef7bSReid Kleckner std::unique_ptr<IPDBSession> PDBSession)
2720dbd0d0SZachary Turner : DIContext(CK_PDB), Session(std::move(PDBSession)) {
28e94fef7bSReid Kleckner ErrorOr<uint64_t> ImageBase = Object.getImageBase();
29e94fef7bSReid Kleckner if (ImageBase)
30e94fef7bSReid Kleckner Session->setLoadAddress(ImageBase.get());
31c007aa41SZachary Turner }
3220dbd0d0SZachary Turner
dump(raw_ostream & OS,DIDumpOptions DumpOpts)33f4bc1f77SAdrian Prantl void PDBContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){}
3420dbd0d0SZachary Turner
getLineInfoForAddress(object::SectionedAddress Address,DILineInfoSpecifier Specifier)3577fc1f60SAlexey Lapshin DILineInfo PDBContext::getLineInfoForAddress(object::SectionedAddress Address,
3620dbd0d0SZachary Turner DILineInfoSpecifier Specifier) {
37c007aa41SZachary Turner DILineInfo Result;
3877fc1f60SAlexey Lapshin Result.FunctionName = getFunctionName(Address.Address, Specifier.FNKind);
3920dbd0d0SZachary Turner
4020dbd0d0SZachary Turner uint32_t Length = 1;
41c007aa41SZachary Turner std::unique_ptr<PDBSymbol> Symbol =
4277fc1f60SAlexey Lapshin Session->findSymbolByAddress(Address.Address, PDB_SymType::None);
4320dbd0d0SZachary Turner if (auto Func = dyn_cast_or_null<PDBSymbolFunc>(Symbol.get())) {
4420dbd0d0SZachary Turner Length = Func->getLength();
4520dbd0d0SZachary Turner } else if (auto Data = dyn_cast_or_null<PDBSymbolData>(Symbol.get())) {
4620dbd0d0SZachary Turner Length = Data->getLength();
4720dbd0d0SZachary Turner }
4820dbd0d0SZachary Turner
4920dbd0d0SZachary Turner // If we couldn't find a symbol, then just assume 1 byte, so that we get
5020dbd0d0SZachary Turner // only the line number of the first instruction.
5177fc1f60SAlexey Lapshin auto LineNumbers = Session->findLineNumbersByAddress(Address.Address, Length);
5220dbd0d0SZachary Turner if (!LineNumbers || LineNumbers->getChildCount() == 0)
5320dbd0d0SZachary Turner return Result;
5420dbd0d0SZachary Turner
5520dbd0d0SZachary Turner auto LineInfo = LineNumbers->getNext();
5620dbd0d0SZachary Turner assert(LineInfo);
5720dbd0d0SZachary Turner auto SourceFile = Session->getSourceFileById(LineInfo->getSourceFileId());
5820dbd0d0SZachary Turner
5920dbd0d0SZachary Turner if (SourceFile &&
6020dbd0d0SZachary Turner Specifier.FLIKind != DILineInfoSpecifier::FileLineInfoKind::None)
6120dbd0d0SZachary Turner Result.FileName = SourceFile->getFileName();
6220dbd0d0SZachary Turner Result.Column = LineInfo->getColumnNumber();
6320dbd0d0SZachary Turner Result.Line = LineInfo->getLineNumber();
6420dbd0d0SZachary Turner return Result;
6520dbd0d0SZachary Turner }
6620dbd0d0SZachary Turner
67*cead4eceSMitch Phillips DILineInfo
getLineInfoForDataAddress(object::SectionedAddress Address)68*cead4eceSMitch Phillips PDBContext::getLineInfoForDataAddress(object::SectionedAddress Address) {
69*cead4eceSMitch Phillips // Unimplemented. S_GDATA and S_LDATA in CodeView (used to describe global
70*cead4eceSMitch Phillips // variables) aren't capable of carrying line information.
71*cead4eceSMitch Phillips return DILineInfo();
72*cead4eceSMitch Phillips }
73*cead4eceSMitch Phillips
7420dbd0d0SZachary Turner DILineInfoTable
getLineInfoForAddressRange(object::SectionedAddress Address,uint64_t Size,DILineInfoSpecifier Specifier)7577fc1f60SAlexey Lapshin PDBContext::getLineInfoForAddressRange(object::SectionedAddress Address,
7677fc1f60SAlexey Lapshin uint64_t Size,
7720dbd0d0SZachary Turner DILineInfoSpecifier Specifier) {
7820dbd0d0SZachary Turner if (Size == 0)
7920dbd0d0SZachary Turner return DILineInfoTable();
8020dbd0d0SZachary Turner
8120dbd0d0SZachary Turner DILineInfoTable Table;
8277fc1f60SAlexey Lapshin auto LineNumbers = Session->findLineNumbersByAddress(Address.Address, Size);
8320dbd0d0SZachary Turner if (!LineNumbers || LineNumbers->getChildCount() == 0)
8420dbd0d0SZachary Turner return Table;
8520dbd0d0SZachary Turner
8620dbd0d0SZachary Turner while (auto LineInfo = LineNumbers->getNext()) {
8777fc1f60SAlexey Lapshin DILineInfo LineEntry = getLineInfoForAddress(
8877fc1f60SAlexey Lapshin {LineInfo->getVirtualAddress(), Address.SectionIndex}, Specifier);
8920dbd0d0SZachary Turner Table.push_back(std::make_pair(LineInfo->getVirtualAddress(), LineEntry));
9020dbd0d0SZachary Turner }
9120dbd0d0SZachary Turner return Table;
9220dbd0d0SZachary Turner }
9320dbd0d0SZachary Turner
9420dbd0d0SZachary Turner DIInliningInfo
getInliningInfoForAddress(object::SectionedAddress Address,DILineInfoSpecifier Specifier)9577fc1f60SAlexey Lapshin PDBContext::getInliningInfoForAddress(object::SectionedAddress Address,
9620dbd0d0SZachary Turner DILineInfoSpecifier Specifier) {
9720dbd0d0SZachary Turner DIInliningInfo InlineInfo;
98bc980340SAmy Huang DILineInfo CurrentLine = getLineInfoForAddress(Address, Specifier);
99bc980340SAmy Huang
100bc980340SAmy Huang // Find the function at this address.
101bc980340SAmy Huang std::unique_ptr<PDBSymbol> ParentFunc =
102bc980340SAmy Huang Session->findSymbolByAddress(Address.Address, PDB_SymType::Function);
103bc980340SAmy Huang if (!ParentFunc) {
104bc980340SAmy Huang InlineInfo.addFrame(CurrentLine);
105bc980340SAmy Huang return InlineInfo;
106bc980340SAmy Huang }
107bc980340SAmy Huang
108bc980340SAmy Huang auto Frames = ParentFunc->findInlineFramesByVA(Address.Address);
109bc980340SAmy Huang if (!Frames || Frames->getChildCount() == 0) {
110bc980340SAmy Huang InlineInfo.addFrame(CurrentLine);
111bc980340SAmy Huang return InlineInfo;
112bc980340SAmy Huang }
113bc980340SAmy Huang
114bc980340SAmy Huang while (auto Frame = Frames->getNext()) {
115bc980340SAmy Huang uint32_t Length = 1;
116bc980340SAmy Huang auto LineNumbers = Frame->findInlineeLinesByVA(Address.Address, Length);
117bc980340SAmy Huang if (!LineNumbers || LineNumbers->getChildCount() == 0)
118bc980340SAmy Huang break;
119bc980340SAmy Huang
120bc980340SAmy Huang std::unique_ptr<IPDBLineNumber> Line = LineNumbers->getNext();
121bc980340SAmy Huang assert(Line);
122bc980340SAmy Huang
123bc980340SAmy Huang DILineInfo LineInfo;
124bc980340SAmy Huang LineInfo.FunctionName = Frame->getName();
125bc980340SAmy Huang auto SourceFile = Session->getSourceFileById(Line->getSourceFileId());
126bc980340SAmy Huang if (SourceFile &&
127bc980340SAmy Huang Specifier.FLIKind != DILineInfoSpecifier::FileLineInfoKind::None)
128bc980340SAmy Huang LineInfo.FileName = SourceFile->getFileName();
129bc980340SAmy Huang LineInfo.Line = Line->getLineNumber();
130bc980340SAmy Huang LineInfo.Column = Line->getColumnNumber();
131bc980340SAmy Huang InlineInfo.addFrame(LineInfo);
132bc980340SAmy Huang }
133bc980340SAmy Huang
134bc980340SAmy Huang InlineInfo.addFrame(CurrentLine);
13520dbd0d0SZachary Turner return InlineInfo;
13620dbd0d0SZachary Turner }
137c007aa41SZachary Turner
1389c8282a9SPeter Collingbourne std::vector<DILocal>
getLocalsForAddress(object::SectionedAddress Address)1399c8282a9SPeter Collingbourne PDBContext::getLocalsForAddress(object::SectionedAddress Address) {
1409c8282a9SPeter Collingbourne return std::vector<DILocal>();
1419c8282a9SPeter Collingbourne }
1429c8282a9SPeter Collingbourne
getFunctionName(uint64_t Address,DINameKind NameKind) const143c007aa41SZachary Turner std::string PDBContext::getFunctionName(uint64_t Address,
144c007aa41SZachary Turner DINameKind NameKind) const {
145c007aa41SZachary Turner if (NameKind == DINameKind::None)
146c007aa41SZachary Turner return std::string();
147c007aa41SZachary Turner
1480336cc05SReid Kleckner std::unique_ptr<PDBSymbol> FuncSymbol =
1490336cc05SReid Kleckner Session->findSymbolByAddress(Address, PDB_SymType::Function);
1500336cc05SReid Kleckner auto *Func = dyn_cast_or_null<PDBSymbolFunc>(FuncSymbol.get());
1510336cc05SReid Kleckner
152c007aa41SZachary Turner if (NameKind == DINameKind::LinkageName) {
153c007aa41SZachary Turner // It is not possible to get the mangled linkage name through a
154c007aa41SZachary Turner // PDBSymbolFunc. For that we have to specifically request a
155c007aa41SZachary Turner // PDBSymbolPublicSymbol.
156c007aa41SZachary Turner auto PublicSym =
157c007aa41SZachary Turner Session->findSymbolByAddress(Address, PDB_SymType::PublicSymbol);
1580336cc05SReid Kleckner if (auto *PS = dyn_cast_or_null<PDBSymbolPublicSymbol>(PublicSym.get())) {
1590336cc05SReid Kleckner // If we also have a function symbol, prefer the use of public symbol name
1600336cc05SReid Kleckner // only if it refers to the same address. The public symbol uses the
1610336cc05SReid Kleckner // linkage name while the function does not.
1620336cc05SReid Kleckner if (!Func || Func->getVirtualAddress() == PS->getVirtualAddress())
163c007aa41SZachary Turner return PS->getName();
164c007aa41SZachary Turner }
1650336cc05SReid Kleckner }
166c007aa41SZachary Turner
1670336cc05SReid Kleckner return Func ? Func->getName() : std::string();
168c007aa41SZachary Turner }
169