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