Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/ValueObject/DILEval.cpp
213764 views
1
//===-- DILEval.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/ValueObject/DILEval.h"
10
#include "lldb/Symbol/CompileUnit.h"
11
#include "lldb/Symbol/VariableList.h"
12
#include "lldb/Target/RegisterContext.h"
13
#include "lldb/ValueObject/DILAST.h"
14
#include "lldb/ValueObject/ValueObject.h"
15
#include "lldb/ValueObject/ValueObjectRegister.h"
16
#include "lldb/ValueObject/ValueObjectVariable.h"
17
#include "llvm/Support/FormatAdapters.h"
18
#include <memory>
19
20
namespace lldb_private::dil {
21
22
static lldb::VariableSP DILFindVariable(ConstString name,
23
VariableList &variable_list) {
24
lldb::VariableSP exact_match;
25
std::vector<lldb::VariableSP> possible_matches;
26
27
for (lldb::VariableSP var_sp : variable_list) {
28
llvm::StringRef str_ref_name = var_sp->GetName().GetStringRef();
29
30
str_ref_name.consume_front("::");
31
// Check for the exact same match
32
if (str_ref_name == name.GetStringRef())
33
return var_sp;
34
35
// Check for possible matches by base name
36
if (var_sp->NameMatches(name))
37
possible_matches.push_back(var_sp);
38
}
39
40
// If there's a non-exact match, take it.
41
if (possible_matches.size() > 0)
42
return possible_matches[0];
43
44
return nullptr;
45
}
46
47
lldb::ValueObjectSP LookupGlobalIdentifier(
48
llvm::StringRef name_ref, std::shared_ptr<StackFrame> stack_frame,
49
lldb::TargetSP target_sp, lldb::DynamicValueType use_dynamic) {
50
// Get a global variables list without the locals from the current frame
51
SymbolContext symbol_context =
52
stack_frame->GetSymbolContext(lldb::eSymbolContextCompUnit);
53
lldb::VariableListSP variable_list;
54
if (symbol_context.comp_unit)
55
variable_list = symbol_context.comp_unit->GetVariableList(true);
56
57
name_ref.consume_front("::");
58
lldb::ValueObjectSP value_sp;
59
if (variable_list) {
60
lldb::VariableSP var_sp =
61
DILFindVariable(ConstString(name_ref), *variable_list);
62
if (var_sp)
63
value_sp =
64
stack_frame->GetValueObjectForFrameVariable(var_sp, use_dynamic);
65
}
66
67
if (value_sp)
68
return value_sp;
69
70
// Check for match in modules global variables.
71
VariableList modules_var_list;
72
target_sp->GetImages().FindGlobalVariables(
73
ConstString(name_ref), std::numeric_limits<uint32_t>::max(),
74
modules_var_list);
75
76
if (!modules_var_list.Empty()) {
77
lldb::VariableSP var_sp =
78
DILFindVariable(ConstString(name_ref), modules_var_list);
79
if (var_sp)
80
value_sp = ValueObjectVariable::Create(stack_frame.get(), var_sp);
81
82
if (value_sp)
83
return value_sp;
84
}
85
return nullptr;
86
}
87
88
lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
89
std::shared_ptr<StackFrame> stack_frame,
90
lldb::DynamicValueType use_dynamic) {
91
// Support $rax as a special syntax for accessing registers.
92
// Will return an invalid value in case the requested register doesn't exist.
93
if (name_ref.consume_front("$")) {
94
lldb::RegisterContextSP reg_ctx(stack_frame->GetRegisterContext());
95
if (!reg_ctx)
96
return nullptr;
97
98
if (const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name_ref))
99
return ValueObjectRegister::Create(stack_frame.get(), reg_ctx, reg_info);
100
101
return nullptr;
102
}
103
104
if (!name_ref.contains("::")) {
105
// Lookup in the current frame.
106
// Try looking for a local variable in current scope.
107
lldb::VariableListSP variable_list(
108
stack_frame->GetInScopeVariableList(false));
109
110
lldb::ValueObjectSP value_sp;
111
if (variable_list) {
112
lldb::VariableSP var_sp =
113
variable_list->FindVariable(ConstString(name_ref));
114
if (var_sp)
115
value_sp =
116
stack_frame->GetValueObjectForFrameVariable(var_sp, use_dynamic);
117
}
118
119
if (value_sp)
120
return value_sp;
121
122
// Try looking for an instance variable (class member).
123
SymbolContext sc = stack_frame->GetSymbolContext(
124
lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
125
llvm::StringRef ivar_name = sc.GetInstanceVariableName();
126
value_sp = stack_frame->FindVariable(ConstString(ivar_name));
127
if (value_sp)
128
value_sp = value_sp->GetChildMemberWithName(name_ref);
129
130
if (value_sp)
131
return value_sp;
132
}
133
return nullptr;
134
}
135
136
Interpreter::Interpreter(lldb::TargetSP target, llvm::StringRef expr,
137
std::shared_ptr<StackFrame> frame_sp,
138
lldb::DynamicValueType use_dynamic, bool use_synthetic,
139
bool fragile_ivar, bool check_ptr_vs_member)
140
: m_target(std::move(target)), m_expr(expr), m_exe_ctx_scope(frame_sp),
141
m_use_dynamic(use_dynamic), m_use_synthetic(use_synthetic),
142
m_fragile_ivar(fragile_ivar), m_check_ptr_vs_member(check_ptr_vs_member) {
143
}
144
145
llvm::Expected<lldb::ValueObjectSP> Interpreter::Evaluate(const ASTNode *node) {
146
// Evaluate an AST.
147
auto value_or_error = node->Accept(this);
148
// Return the computed value-or-error. The caller is responsible for
149
// checking if an error occured during the evaluation.
150
return value_or_error;
151
}
152
153
llvm::Expected<lldb::ValueObjectSP>
154
Interpreter::Visit(const IdentifierNode *node) {
155
lldb::DynamicValueType use_dynamic = m_use_dynamic;
156
157
lldb::ValueObjectSP identifier =
158
LookupIdentifier(node->GetName(), m_exe_ctx_scope, use_dynamic);
159
160
if (!identifier)
161
identifier = LookupGlobalIdentifier(node->GetName(), m_exe_ctx_scope,
162
m_target, use_dynamic);
163
if (!identifier) {
164
std::string errMsg =
165
llvm::formatv("use of undeclared identifier '{0}'", node->GetName());
166
return llvm::make_error<DILDiagnosticError>(
167
m_expr, errMsg, node->GetLocation(), node->GetName().size());
168
}
169
170
return identifier;
171
}
172
173
llvm::Expected<lldb::ValueObjectSP>
174
Interpreter::Visit(const UnaryOpNode *node) {
175
Status error;
176
auto rhs_or_err = Evaluate(node->GetOperand());
177
if (!rhs_or_err)
178
return rhs_or_err;
179
180
lldb::ValueObjectSP rhs = *rhs_or_err;
181
182
switch (node->GetKind()) {
183
case UnaryOpKind::Deref: {
184
lldb::ValueObjectSP dynamic_rhs = rhs->GetDynamicValue(m_use_dynamic);
185
if (dynamic_rhs)
186
rhs = dynamic_rhs;
187
188
lldb::ValueObjectSP child_sp = rhs->Dereference(error);
189
if (!child_sp && m_use_synthetic) {
190
if (lldb::ValueObjectSP synth_obj_sp = rhs->GetSyntheticValue()) {
191
error.Clear();
192
child_sp = synth_obj_sp->Dereference(error);
193
}
194
}
195
if (error.Fail())
196
return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
197
node->GetLocation());
198
199
return child_sp;
200
}
201
case UnaryOpKind::AddrOf: {
202
Status error;
203
lldb::ValueObjectSP value = rhs->AddressOf(error);
204
if (error.Fail())
205
return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
206
node->GetLocation());
207
208
return value;
209
}
210
}
211
212
// Unsupported/invalid operation.
213
return llvm::make_error<DILDiagnosticError>(
214
m_expr, "invalid ast: unexpected binary operator", node->GetLocation());
215
}
216
217
llvm::Expected<lldb::ValueObjectSP>
218
Interpreter::Visit(const MemberOfNode *node) {
219
auto base_or_err = Evaluate(node->GetBase());
220
if (!base_or_err)
221
return base_or_err;
222
bool expr_is_ptr = node->GetIsArrow();
223
lldb::ValueObjectSP base = *base_or_err;
224
225
// Perform some basic type & correctness checking.
226
if (node->GetIsArrow()) {
227
if (!m_fragile_ivar) {
228
// Make sure we aren't trying to deref an objective
229
// C ivar if this is not allowed
230
const uint32_t pointer_type_flags =
231
base->GetCompilerType().GetTypeInfo(nullptr);
232
if ((pointer_type_flags & lldb::eTypeIsObjC) &&
233
(pointer_type_flags & lldb::eTypeIsPointer)) {
234
// This was an objective C object pointer and it was requested we
235
// skip any fragile ivars so return nothing here
236
return lldb::ValueObjectSP();
237
}
238
}
239
240
// If we have a non-pointer type with a synthetic value then lets check
241
// if we have a synthetic dereference specified.
242
if (!base->IsPointerType() && base->HasSyntheticValue()) {
243
Status deref_error;
244
if (lldb::ValueObjectSP synth_deref_sp =
245
base->GetSyntheticValue()->Dereference(deref_error);
246
synth_deref_sp && deref_error.Success()) {
247
base = std::move(synth_deref_sp);
248
}
249
if (!base || deref_error.Fail()) {
250
std::string errMsg = llvm::formatv(
251
"Failed to dereference synthetic value: {0}", deref_error);
252
return llvm::make_error<DILDiagnosticError>(
253
m_expr, errMsg, node->GetLocation(), node->GetFieldName().size());
254
}
255
256
// Some synthetic plug-ins fail to set the error in Dereference
257
if (!base) {
258
std::string errMsg = "Failed to dereference synthetic value";
259
return llvm::make_error<DILDiagnosticError>(
260
m_expr, errMsg, node->GetLocation(), node->GetFieldName().size());
261
}
262
expr_is_ptr = false;
263
}
264
}
265
266
if (m_check_ptr_vs_member) {
267
bool base_is_ptr = base->IsPointerType();
268
269
if (expr_is_ptr != base_is_ptr) {
270
if (base_is_ptr) {
271
std::string errMsg =
272
llvm::formatv("member reference type {0} is a pointer; "
273
"did you mean to use '->'?",
274
base->GetCompilerType().TypeDescription());
275
return llvm::make_error<DILDiagnosticError>(
276
m_expr, errMsg, node->GetLocation(), node->GetFieldName().size());
277
} else {
278
std::string errMsg =
279
llvm::formatv("member reference type {0} is not a pointer; "
280
"did you mean to use '.'?",
281
base->GetCompilerType().TypeDescription());
282
return llvm::make_error<DILDiagnosticError>(
283
m_expr, errMsg, node->GetLocation(), node->GetFieldName().size());
284
}
285
}
286
}
287
288
lldb::ValueObjectSP field_obj =
289
base->GetChildMemberWithName(node->GetFieldName());
290
if (!field_obj) {
291
if (m_use_synthetic) {
292
field_obj = base->GetSyntheticValue();
293
if (field_obj)
294
field_obj = field_obj->GetChildMemberWithName(node->GetFieldName());
295
}
296
297
if (!m_use_synthetic || !field_obj) {
298
std::string errMsg = llvm::formatv(
299
"\"{0}\" is not a member of \"({1}) {2}\"", node->GetFieldName(),
300
base->GetTypeName().AsCString("<invalid type>"), base->GetName());
301
return llvm::make_error<DILDiagnosticError>(
302
m_expr, errMsg, node->GetLocation(), node->GetFieldName().size());
303
}
304
}
305
306
if (field_obj) {
307
if (m_use_dynamic != lldb::eNoDynamicValues) {
308
lldb::ValueObjectSP dynamic_val_sp =
309
field_obj->GetDynamicValue(m_use_dynamic);
310
if (dynamic_val_sp)
311
field_obj = dynamic_val_sp;
312
}
313
return field_obj;
314
}
315
316
CompilerType base_type = base->GetCompilerType();
317
if (node->GetIsArrow() && base->IsPointerType())
318
base_type = base_type.GetPointeeType();
319
std::string errMsg = llvm::formatv(
320
"\"{0}\" is not a member of \"({1}) {2}\"", node->GetFieldName(),
321
base->GetTypeName().AsCString("<invalid type>"), base->GetName());
322
return llvm::make_error<DILDiagnosticError>(
323
m_expr, errMsg, node->GetLocation(), node->GetFieldName().size());
324
}
325
326
llvm::Expected<lldb::ValueObjectSP>
327
Interpreter::Visit(const ArraySubscriptNode *node) {
328
auto lhs_or_err = Evaluate(node->GetBase());
329
if (!lhs_or_err)
330
return lhs_or_err;
331
lldb::ValueObjectSP base = *lhs_or_err;
332
333
// Check to see if 'base' has a synthetic value; if so, try using that.
334
uint64_t child_idx = node->GetIndex();
335
if (lldb::ValueObjectSP synthetic = base->GetSyntheticValue()) {
336
llvm::Expected<uint32_t> num_children =
337
synthetic->GetNumChildren(child_idx + 1);
338
if (!num_children)
339
return llvm::make_error<DILDiagnosticError>(
340
m_expr, toString(num_children.takeError()), node->GetLocation());
341
if (child_idx >= *num_children) {
342
std::string message = llvm::formatv(
343
"array index {0} is not valid for \"({1}) {2}\"", child_idx,
344
base->GetTypeName().AsCString("<invalid type>"),
345
base->GetName().AsCString());
346
return llvm::make_error<DILDiagnosticError>(m_expr, message,
347
node->GetLocation());
348
}
349
if (lldb::ValueObjectSP child_valobj_sp =
350
synthetic->GetChildAtIndex(child_idx))
351
return child_valobj_sp;
352
}
353
354
auto base_type = base->GetCompilerType().GetNonReferenceType();
355
if (!base_type.IsPointerType() && !base_type.IsArrayType())
356
return llvm::make_error<DILDiagnosticError>(
357
m_expr, "subscripted value is not an array or pointer",
358
node->GetLocation());
359
if (base_type.IsPointerToVoid())
360
return llvm::make_error<DILDiagnosticError>(
361
m_expr, "subscript of pointer to incomplete type 'void'",
362
node->GetLocation());
363
364
if (base_type.IsArrayType()) {
365
if (lldb::ValueObjectSP child_valobj_sp = base->GetChildAtIndex(child_idx))
366
return child_valobj_sp;
367
}
368
369
int64_t signed_child_idx = node->GetIndex();
370
return base->GetSyntheticArrayMember(signed_child_idx, true);
371
}
372
373
llvm::Expected<lldb::ValueObjectSP>
374
Interpreter::Visit(const BitFieldExtractionNode *node) {
375
auto lhs_or_err = Evaluate(node->GetBase());
376
if (!lhs_or_err)
377
return lhs_or_err;
378
lldb::ValueObjectSP base = *lhs_or_err;
379
int64_t first_index = node->GetFirstIndex();
380
int64_t last_index = node->GetLastIndex();
381
382
// if the format given is [high-low], swap range
383
if (first_index > last_index)
384
std::swap(first_index, last_index);
385
386
Status error;
387
if (base->GetCompilerType().IsReferenceType()) {
388
base = base->Dereference(error);
389
if (error.Fail())
390
return error.ToError();
391
}
392
lldb::ValueObjectSP child_valobj_sp =
393
base->GetSyntheticBitFieldChild(first_index, last_index, true);
394
if (!child_valobj_sp) {
395
std::string message = llvm::formatv(
396
"bitfield range {0}-{1} is not valid for \"({2}) {3}\"", first_index,
397
last_index, base->GetTypeName().AsCString("<invalid type>"),
398
base->GetName().AsCString());
399
return llvm::make_error<DILDiagnosticError>(m_expr, message,
400
node->GetLocation());
401
}
402
return child_valobj_sp;
403
}
404
405
} // namespace lldb_private::dil
406
407