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
14using namespace llvm;
15using namespace llvm::gsym;
16
17GsymContext::GsymContext(std::unique_ptr<GsymReader> Reader)
18 : DIContext(CK_GSYM), Reader(std::move(Reader)) {}
19
20void GsymContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {}
21
22static 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
63std::optional<DILineInfo>
64GsymContext::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
95std::optional<DILineInfo>
96GsymContext::getLineInfoForDataAddress(object::SectionedAddress Address) {
97 // We can't implement this, there's no such information in the GSYM file.
98
99 return {};
100}
101
102DILineInfoTable
103GsymContext::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 &LT = *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
133DIInliningInfo
134GsymContext::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
161std::vector<DILocal>
162GsymContext::getLocalsForAddress(object::SectionedAddress Address) {
163 // We can't implement this, there's no such information in the GSYM file.
164
165 return {};
166}
167