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