Make llvm-symbolizer work on Windows.
[oota-llvm.git] / lib / DebugInfo / PDB / PDBContext.cpp
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);
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 }