1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
//===-- GsymContext.cpp ------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===/
#include "llvm/DebugInfo/GSYM/GsymContext.h"
#include "llvm/DebugInfo/GSYM/GsymReader.h"
#include "llvm/Support/Path.h"
using namespace llvm;
using namespace llvm::gsym;
GsymContext::GsymContext(std::unique_ptr<GsymReader> Reader)
: DIContext(CK_GSYM), Reader(std::move(Reader)) {}
void GsymContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {}
static bool fillLineInfoFromLocation(const SourceLocation &Location,
DILineInfoSpecifier Specifier,
DILineInfo &LineInfo) {
// FIXME Demangle in case of DINameKind::ShortName
if (Specifier.FNKind != DINameKind::None) {
LineInfo.FunctionName = Location.Name.str();
}
switch (Specifier.FLIKind) {
case DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath:
// We have no information to determine the relative path, so we fall back to
// returning the absolute path.
case DILineInfoSpecifier::FileLineInfoKind::RawValue:
case DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath:
if (Location.Dir.empty()) {
if (Location.Base.empty())
LineInfo.FileName = DILineInfo::BadString;
else
LineInfo.FileName = Location.Base.str();
} else {
SmallString<128> Path(Location.Dir);
sys::path::append(Path, Location.Base);
LineInfo.FileName = static_cast<std::string>(Path);
}
break;
case DILineInfoSpecifier::FileLineInfoKind::BaseNameOnly:
LineInfo.FileName = Location.Base.str();
break;
default:
return false;
}
LineInfo.Line = Location.Line;
// We don't have information in GSYM to fill any of the Source, Column,
// StartFileName or StartLine attributes.
return true;
}
std::optional<DILineInfo>
GsymContext::getLineInfoForAddress(object::SectionedAddress Address,
DILineInfoSpecifier Specifier) {
if (Address.SectionIndex != object::SectionedAddress::UndefSection)
return {};
auto ResultOrErr = Reader->lookup(Address.Address);
if (!ResultOrErr) {
consumeError(ResultOrErr.takeError());
return {};
}
const auto &Result = *ResultOrErr;
DILineInfo LineInfo;
if (Result.Locations.empty()) {
// No debug info for this, we just had a symbol from the symbol table.
// FIXME Demangle in case of DINameKind::ShortName
if (Specifier.FNKind != DINameKind::None)
LineInfo.FunctionName = Result.FuncName.str();
} else if (!fillLineInfoFromLocation(Result.Locations.front(), Specifier,
LineInfo))
return {};
LineInfo.StartAddress = Result.FuncRange.start();
return LineInfo;
}
std::optional<DILineInfo>
GsymContext::getLineInfoForDataAddress(object::SectionedAddress Address) {
// We can't implement this, there's no such information in the GSYM file.
return {};
}
DILineInfoTable
GsymContext::getLineInfoForAddressRange(object::SectionedAddress Address,
uint64_t Size,
DILineInfoSpecifier Specifier) {
if (Size == 0)
return DILineInfoTable();
if (Address.SectionIndex != llvm::object::SectionedAddress::UndefSection)
return DILineInfoTable();
if (auto FuncInfoOrErr = Reader->getFunctionInfo(Address.Address)) {
DILineInfoTable Table;
if (FuncInfoOrErr->OptLineTable) {
const gsym::LineTable < = *FuncInfoOrErr->OptLineTable;
const uint64_t StartAddr = Address.Address;
const uint64_t EndAddr = Address.Address + Size;
for (const auto &LineEntry : LT) {
if (StartAddr <= LineEntry.Addr && LineEntry.Addr < EndAddr) {
// Use LineEntry.Addr, LineEntry.File (which is a file index into the
// files tables from the GsymReader), and LineEntry.Line (source line
// number) to add stuff to the DILineInfoTable
}
}
}
return Table;
} else {
consumeError(FuncInfoOrErr.takeError());
return DILineInfoTable();
}
}
DIInliningInfo
GsymContext::getInliningInfoForAddress(object::SectionedAddress Address,
DILineInfoSpecifier Specifier) {
auto ResultOrErr = Reader->lookup(Address.Address);
if (!ResultOrErr)
return {};
const auto &Result = *ResultOrErr;
DIInliningInfo InlineInfo;
for (const auto &Location : Result.Locations) {
DILineInfo LineInfo;
if (!fillLineInfoFromLocation(Location, Specifier, LineInfo))
return {};
// Hm, that's probably something that should only be filled in the first or
// last frame?
LineInfo.StartAddress = Result.FuncRange.start();
InlineInfo.addFrame(LineInfo);
}
return InlineInfo;
}
std::vector<DILocal>
GsymContext::getLocalsForAddress(object::SectionedAddress Address) {
// We can't implement this, there's no such information in the GSYM file.
return {};
}
|