1 //===-- PDBContext.cpp ------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===/
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/Object/COFF.h"
20 using namespace llvm::object
;
21 using namespace llvm::pdb
;
23 PDBContext::PDBContext(const COFFObjectFile
&Object
,
24 std::unique_ptr
<IPDBSession
> PDBSession
)
25 : DIContext(CK_PDB
), Session(std::move(PDBSession
)) {
26 ErrorOr
<uint64_t> ImageBase
= Object
.getImageBase();
28 Session
->setLoadAddress(ImageBase
.get());
31 void PDBContext::dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
){}
33 DILineInfo
PDBContext::getLineInfoForAddress(uint64_t Address
,
34 DILineInfoSpecifier Specifier
) {
36 Result
.FunctionName
= getFunctionName(Address
, Specifier
.FNKind
);
39 std::unique_ptr
<PDBSymbol
> Symbol
=
40 Session
->findSymbolByAddress(Address
, PDB_SymType::None
);
41 if (auto Func
= dyn_cast_or_null
<PDBSymbolFunc
>(Symbol
.get())) {
42 Length
= Func
->getLength();
43 } else if (auto Data
= dyn_cast_or_null
<PDBSymbolData
>(Symbol
.get())) {
44 Length
= Data
->getLength();
47 // If we couldn't find a symbol, then just assume 1 byte, so that we get
48 // only the line number of the first instruction.
49 auto LineNumbers
= Session
->findLineNumbersByAddress(Address
, Length
);
50 if (!LineNumbers
|| LineNumbers
->getChildCount() == 0)
53 auto LineInfo
= LineNumbers
->getNext();
55 auto SourceFile
= Session
->getSourceFileById(LineInfo
->getSourceFileId());
58 Specifier
.FLIKind
!= DILineInfoSpecifier::FileLineInfoKind::None
)
59 Result
.FileName
= SourceFile
->getFileName();
60 Result
.Column
= LineInfo
->getColumnNumber();
61 Result
.Line
= LineInfo
->getLineNumber();
66 PDBContext::getLineInfoForAddressRange(uint64_t Address
, uint64_t Size
,
67 DILineInfoSpecifier Specifier
) {
69 return DILineInfoTable();
71 DILineInfoTable Table
;
72 auto LineNumbers
= Session
->findLineNumbersByAddress(Address
, Size
);
73 if (!LineNumbers
|| LineNumbers
->getChildCount() == 0)
76 while (auto LineInfo
= LineNumbers
->getNext()) {
77 DILineInfo LineEntry
=
78 getLineInfoForAddress(LineInfo
->getVirtualAddress(), Specifier
);
79 Table
.push_back(std::make_pair(LineInfo
->getVirtualAddress(), LineEntry
));
85 PDBContext::getInliningInfoForAddress(uint64_t Address
,
86 DILineInfoSpecifier Specifier
) {
87 DIInliningInfo InlineInfo
;
88 DILineInfo Frame
= getLineInfoForAddress(Address
, Specifier
);
89 InlineInfo
.addFrame(Frame
);
93 std::string
PDBContext::getFunctionName(uint64_t Address
,
94 DINameKind NameKind
) const {
95 if (NameKind
== DINameKind::None
)
98 std::unique_ptr
<PDBSymbol
> FuncSymbol
=
99 Session
->findSymbolByAddress(Address
, PDB_SymType::Function
);
100 auto *Func
= dyn_cast_or_null
<PDBSymbolFunc
>(FuncSymbol
.get());
102 if (NameKind
== DINameKind::LinkageName
) {
103 // It is not possible to get the mangled linkage name through a
104 // PDBSymbolFunc. For that we have to specifically request a
105 // PDBSymbolPublicSymbol.
107 Session
->findSymbolByAddress(Address
, PDB_SymType::PublicSymbol
);
108 if (auto *PS
= dyn_cast_or_null
<PDBSymbolPublicSymbol
>(PublicSym
.get())) {
109 // If we also have a function symbol, prefer the use of public symbol name
110 // only if it refers to the same address. The public symbol uses the
111 // linkage name while the function does not.
112 if (!Func
|| Func
->getVirtualAddress() == PS
->getVirtualAddress())
113 return PS
->getName();
117 return Func
? Func
->getName() : std::string();