Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Expression/DWARFExpressionList.cpp
39587 views
1
//===-- DWARFExpressionList.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 "lldb/Expression/DWARFExpressionList.h"
10
#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
11
#include "lldb/Symbol/Function.h"
12
#include "lldb/Target/RegisterContext.h"
13
#include "lldb/Target/StackFrame.h"
14
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
15
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
16
17
using namespace lldb;
18
using namespace lldb_private;
19
20
bool DWARFExpressionList::IsAlwaysValidSingleExpr() const {
21
return GetAlwaysValidExpr() != nullptr;
22
}
23
24
const DWARFExpression * DWARFExpressionList::GetAlwaysValidExpr() const {
25
if (m_exprs.GetSize() != 1)
26
return nullptr;
27
const auto *expr = m_exprs.GetEntryAtIndex(0);
28
if (expr->base == 0 && expr->size == LLDB_INVALID_ADDRESS)
29
return &expr->data;
30
return nullptr;
31
}
32
33
bool DWARFExpressionList::AddExpression(addr_t base, addr_t end,
34
DWARFExpression expr) {
35
if (IsAlwaysValidSingleExpr() || base >= end)
36
return false;
37
m_exprs.Append({base, end - base, expr});
38
return true;
39
}
40
41
bool DWARFExpressionList::GetExpressionData(DataExtractor &data,
42
lldb::addr_t func_load_addr,
43
lldb::addr_t file_addr) const {
44
if (const DWARFExpression *expr =
45
GetExpressionAtAddress(func_load_addr, file_addr))
46
return expr->GetExpressionData(data);
47
return false;
48
}
49
50
bool DWARFExpressionList::ContainsAddress(lldb::addr_t func_load_addr,
51
lldb::addr_t addr) const {
52
if (IsAlwaysValidSingleExpr())
53
return true;
54
return GetExpressionAtAddress(func_load_addr, addr) != nullptr;
55
}
56
57
const DWARFExpression *
58
DWARFExpressionList::GetExpressionAtAddress(lldb::addr_t func_load_addr,
59
lldb::addr_t load_addr) const {
60
if (const DWARFExpression *expr = GetAlwaysValidExpr())
61
return expr;
62
if (func_load_addr == LLDB_INVALID_ADDRESS)
63
func_load_addr = m_func_file_addr;
64
addr_t addr = load_addr - func_load_addr + m_func_file_addr;
65
uint32_t index = m_exprs.FindEntryIndexThatContains(addr);
66
if (index == UINT32_MAX)
67
return nullptr;
68
return &m_exprs.GetEntryAtIndex(index)->data;
69
}
70
71
DWARFExpression *
72
DWARFExpressionList::GetMutableExpressionAtAddress(lldb::addr_t func_load_addr,
73
lldb::addr_t load_addr) {
74
if (IsAlwaysValidSingleExpr())
75
return &m_exprs.GetMutableEntryAtIndex(0)->data;
76
if (func_load_addr == LLDB_INVALID_ADDRESS)
77
func_load_addr = m_func_file_addr;
78
addr_t addr = load_addr - func_load_addr + m_func_file_addr;
79
uint32_t index = m_exprs.FindEntryIndexThatContains(addr);
80
if (index == UINT32_MAX)
81
return nullptr;
82
return &m_exprs.GetMutableEntryAtIndex(index)->data;
83
}
84
85
bool DWARFExpressionList::ContainsThreadLocalStorage() const {
86
// We are assuming for now that any thread local variable will not have a
87
// location list. This has been true for all thread local variables we have
88
// seen so far produced by any compiler.
89
if (!IsAlwaysValidSingleExpr())
90
return false;
91
92
const DWARFExpression &expr = m_exprs.GetEntryRef(0).data;
93
return expr.ContainsThreadLocalStorage(m_dwarf_cu);
94
}
95
96
bool DWARFExpressionList::LinkThreadLocalStorage(
97
lldb::ModuleSP new_module_sp,
98
std::function<lldb::addr_t(lldb::addr_t file_addr)> const
99
&link_address_callback) {
100
// We are assuming for now that any thread local variable will not have a
101
// location list. This has been true for all thread local variables we have
102
// seen so far produced by any compiler.
103
if (!IsAlwaysValidSingleExpr())
104
return false;
105
106
DWARFExpression &expr = m_exprs.GetEntryRef(0).data;
107
// If we linked the TLS address correctly, update the module so that when the
108
// expression is evaluated it can resolve the file address to a load address
109
// and read the TLS data
110
if (expr.LinkThreadLocalStorage(m_dwarf_cu, link_address_callback))
111
m_module_wp = new_module_sp;
112
return true;
113
}
114
115
bool DWARFExpressionList::MatchesOperand(
116
StackFrame &frame, const Instruction::Operand &operand) const {
117
RegisterContextSP reg_ctx_sp = frame.GetRegisterContext();
118
if (!reg_ctx_sp) {
119
return false;
120
}
121
const DWARFExpression *expr = nullptr;
122
if (IsAlwaysValidSingleExpr())
123
expr = &m_exprs.GetEntryAtIndex(0)->data;
124
else {
125
SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction);
126
if (!sc.function)
127
return false;
128
129
addr_t load_function_start =
130
sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
131
if (load_function_start == LLDB_INVALID_ADDRESS)
132
return false;
133
134
addr_t pc = frame.GetFrameCodeAddressForSymbolication().GetFileAddress();
135
expr = GetExpressionAtAddress(LLDB_INVALID_ADDRESS, pc);
136
}
137
if (!expr)
138
return false;
139
return expr->MatchesOperand(frame, operand);
140
}
141
142
bool DWARFExpressionList::DumpLocations(Stream *s, lldb::DescriptionLevel level,
143
lldb::addr_t func_load_addr,
144
lldb::addr_t file_addr,
145
ABI *abi) const {
146
llvm::raw_ostream &os = s->AsRawOstream();
147
llvm::ListSeparator separator;
148
if (const DWARFExpression *expr = GetAlwaysValidExpr()) {
149
expr->DumpLocation(s, level, abi);
150
return true;
151
}
152
for (const Entry &entry : *this) {
153
addr_t load_base = entry.GetRangeBase() + func_load_addr - m_func_file_addr;
154
addr_t load_end = entry.GetRangeEnd() + func_load_addr - m_func_file_addr;
155
if (file_addr != LLDB_INVALID_ADDRESS &&
156
(file_addr < load_base || file_addr >= load_end))
157
continue;
158
const auto &expr = entry.data;
159
DataExtractor data;
160
expr.GetExpressionData(data);
161
uint32_t addr_size = data.GetAddressByteSize();
162
163
os << separator;
164
os << "[";
165
os << llvm::format_hex(load_base, 2 + 2 * addr_size);
166
os << ", ";
167
os << llvm::format_hex(load_end, 2 + 2 * addr_size);
168
os << ") -> ";
169
expr.DumpLocation(s, level, abi);
170
if (file_addr != LLDB_INVALID_ADDRESS)
171
break;
172
}
173
return true;
174
}
175
176
void DWARFExpressionList::GetDescription(Stream *s,
177
lldb::DescriptionLevel level,
178
ABI *abi) const {
179
llvm::raw_ostream &os = s->AsRawOstream();
180
if (IsAlwaysValidSingleExpr()) {
181
m_exprs.Back()->data.DumpLocation(s, level, abi);
182
return;
183
}
184
os << llvm::format("0x%8.8" PRIx64 ": ", 0);
185
for (const Entry &entry : *this) {
186
const auto &expr = entry.data;
187
DataExtractor data;
188
expr.GetExpressionData(data);
189
uint32_t addr_size = data.GetAddressByteSize();
190
os << "\n";
191
os.indent(s->GetIndentLevel() + 2);
192
os << "[";
193
llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeBase());
194
os << ", ";
195
llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeEnd());
196
os << "): ";
197
expr.DumpLocation(s, level, abi);
198
}
199
}
200
201
llvm::Expected<Value> DWARFExpressionList::Evaluate(
202
ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
203
lldb::addr_t func_load_addr, const Value *initial_value_ptr,
204
const Value *object_address_ptr) const {
205
ModuleSP module_sp = m_module_wp.lock();
206
DataExtractor data;
207
RegisterKind reg_kind;
208
DWARFExpression expr;
209
if (IsAlwaysValidSingleExpr()) {
210
expr = m_exprs.Back()->data;
211
} else {
212
Address pc;
213
StackFrame *frame = nullptr;
214
if (!reg_ctx || !reg_ctx->GetPCForSymbolication(pc)) {
215
if (exe_ctx)
216
frame = exe_ctx->GetFramePtr();
217
if (!frame)
218
return llvm::createStringError("no frame");
219
RegisterContextSP reg_ctx_sp = frame->GetRegisterContext();
220
if (!reg_ctx_sp)
221
return llvm::createStringError("no register context");
222
reg_ctx_sp->GetPCForSymbolication(pc);
223
}
224
225
if (!pc.IsValid()) {
226
return llvm::createStringError("Invalid PC in frame.");
227
}
228
addr_t pc_load_addr = pc.GetLoadAddress(exe_ctx->GetTargetPtr());
229
const DWARFExpression *entry =
230
GetExpressionAtAddress(func_load_addr, pc_load_addr);
231
if (!entry)
232
return llvm::createStringError("variable not available");
233
expr = *entry;
234
}
235
expr.GetExpressionData(data);
236
reg_kind = expr.GetRegisterKind();
237
return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, data,
238
m_dwarf_cu, reg_kind, initial_value_ptr,
239
object_address_ptr);
240
}
241
242