1 //===-- PDBContext.cpp ------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===/
9 
10 #include "llvm/DebugInfo/PDB/PDBContext.h"
11 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
12 #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
13 #include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
14 #include "llvm/DebugInfo/PDB/PDBSymbol.h"
15 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
16 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
17 #include "llvm/Object/COFF.h"
18 
19 using namespace llvm;
20 using namespace llvm::object;
21 
22 PDBContext::PDBContext(const COFFObjectFile &Object,
23                        std::unique_ptr<IPDBSession> PDBSession)
24     : DIContext(CK_PDB), Session(std::move(PDBSession)) {
25   uint64_t ImageBase = 0;
26   if (Object.is64()) {
27     const pe32plus_header *Header = nullptr;
28     Object.getPE32PlusHeader(Header);
29     if (Header)
30       ImageBase = Header->ImageBase;
31   } else {
32     const pe32_header *Header = nullptr;
33     Object.getPE32Header(Header);
34     if (Header)
35       ImageBase = static_cast<uint64_t>(Header->ImageBase);
36   }
37   Session->setLoadAddress(ImageBase);
38 }
39 
40 void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType) {}
41 
42 DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address,
43                                              DILineInfoSpecifier Specifier) {
44   auto Symbol = Session->findSymbolByAddress(Address, PDB_SymType::None);
45 
46   uint32_t Length = 1;
47   DILineInfo Result;
48   if (auto Func = dyn_cast_or_null<PDBSymbolFunc>(Symbol.get())) {
49     if (Specifier.FNKind == DINameKind::LinkageName)
50       Result.FunctionName = Func->getUndecoratedName();
51     else if (Specifier.FNKind == DINameKind::ShortName)
52       Result.FunctionName = Func->getName();
53 
54     Length = Func->getLength();
55   } else if (auto Data = dyn_cast_or_null<PDBSymbolData>(Symbol.get())) {
56     Length = Data->getLength();
57   }
58 
59   // If we couldn't find a symbol, then just assume 1 byte, so that we get
60   // only the line number of the first instruction.
61   auto LineNumbers = Session->findLineNumbersByAddress(Address, Length);
62   if (!LineNumbers || LineNumbers->getChildCount() == 0)
63     return Result;
64 
65   auto LineInfo = LineNumbers->getNext();
66   assert(LineInfo);
67   auto SourceFile = Session->getSourceFileById(LineInfo->getSourceFileId());
68 
69   if (SourceFile &&
70       Specifier.FLIKind != DILineInfoSpecifier::FileLineInfoKind::None)
71     Result.FileName = SourceFile->getFileName();
72   Result.Column = LineInfo->getColumnNumber();
73   Result.Line = LineInfo->getLineNumber();
74   return Result;
75 }
76 
77 DILineInfoTable
78 PDBContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
79                                        DILineInfoSpecifier Specifier) {
80   if (Size == 0)
81     return DILineInfoTable();
82 
83   DILineInfoTable Table;
84   auto LineNumbers = Session->findLineNumbersByAddress(Address, Size);
85   if (!LineNumbers || LineNumbers->getChildCount() == 0)
86     return Table;
87 
88   while (auto LineInfo = LineNumbers->getNext()) {
89     DILineInfo LineEntry =
90         getLineInfoForAddress(LineInfo->getVirtualAddress(), Specifier);
91     Table.push_back(std::make_pair(LineInfo->getVirtualAddress(), LineEntry));
92   }
93   return Table;
94 }
95 
96 DIInliningInfo
97 PDBContext::getInliningInfoForAddress(uint64_t Address,
98                                       DILineInfoSpecifier Specifier) {
99   DIInliningInfo InlineInfo;
100   DILineInfo Frame = getLineInfoForAddress(Address, Specifier);
101   InlineInfo.addFrame(Frame);
102   return InlineInfo;
103 }
104