LLDB mainline
ValueObjectSynthetic.cpp
Go to the documentation of this file.
1//===-- ValueObjectSynthetic.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
10
11#include "lldb/Core/Value.h"
17#include "lldb/Utility/Log.h"
18#include "lldb/Utility/Status.h"
20
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/Support/Error.h"
23#include "llvm/Support/ErrorExtras.h"
24#include <optional>
25
26namespace lldb_private {
27class Declaration;
28}
29
30using namespace lldb_private;
31
33public:
36
37 llvm::Expected<uint32_t> CalculateNumChildren() override {
38 return m_backend.GetNumChildren();
39 }
40
41 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {
42 return m_backend.GetChildAtIndex(idx);
43 }
44
45 llvm::Expected<size_t>
46 GetIndexOfChildWithName(llvm::StringRef name) override {
47 return m_backend.GetIndexOfChildWithName(name);
48 }
49
50 bool MightHaveChildren() override { return m_backend.MightHaveChildren(); }
51
55};
56
59 : ValueObject(parent), m_synth_sp(std::move(filter)), m_children_byindex(),
65 SetName(parent.GetName());
66 // Copying the data of an incomplete type won't work as it has no byte size.
67 if (m_parent->GetCompilerType().IsCompleteType())
70}
71
73
77
79 return m_parent->GetTypeName();
80}
81
83 return m_parent->GetQualifiedTypeName();
84}
85
87 const std::string synth_name = m_synth_filter_up->GetSyntheticTypeName();
88 if (!synth_name.empty())
89 return ConstString(synth_name);
90
91 return m_parent->GetDisplayTypeName();
92}
93
94llvm::Expected<uint32_t>
97
101
102 if (max < UINT32_MAX) {
103 auto num_children = m_synth_filter_up->CalculateNumChildren(max);
104 LLDB_LOG(log,
105 "[ValueObjectSynthetic::CalculateNumChildren] for VO of name "
106 "{0} and type {1}, the filter returned {2} child values",
107 GetName(), GetTypeName(), num_children ? *num_children : 0);
108 return num_children;
109 } else {
110 auto num_children_or_err = m_synth_filter_up->CalculateNumChildren(max);
111 if (!num_children_or_err) {
113 return num_children_or_err;
114 }
115 auto num_children = (m_synthetic_children_count = *num_children_or_err);
116 LLDB_LOG(log,
117 "[ValueObjectSynthetic::CalculateNumChildren] for VO of name "
118 "{0} and type {1}, the filter returned {2} child values",
119 GetName(), GetTypeName(), num_children);
120 return num_children;
121 }
122}
123
126 if (!m_parent)
127 return lldb::ValueObjectSP();
128 if (IsDynamic() && GetDynamicValueType() == valueType)
129 return GetSP();
130 return m_parent->GetDynamicValue(valueType);
131}
132
139
140llvm::Expected<uint64_t> ValueObjectSynthetic::GetByteSize() {
141 return m_parent->GetByteSize();
142}
143
145 return m_parent->GetValueType();
146}
147
149 ValueObject *valobj_for_frontend = m_parent;
150 if (m_synth_sp->WantsDereference()) {
151 CompilerType type = m_parent->GetCompilerType();
152 if (type.IsValid() && type.IsPointerOrReferenceType()) {
154 lldb::ValueObjectSP deref_sp = m_parent->Dereference(error);
155 if (error.Success())
156 valobj_for_frontend = deref_sp.get();
157 }
158 }
159 m_synth_filter_up = (m_synth_sp->GetFrontEnd(*valobj_for_frontend));
161 m_synth_filter_up = std::make_unique<DummySyntheticFrontEnd>(*m_parent);
162}
163
166
167 SetValueIsValid(false);
168 m_error.Clear();
169
170 if (!m_parent->UpdateValueIfNeeded(false)) {
171 // our parent could not update.. as we are meaningless without a parent,
172 // just stop
173 if (m_parent->GetError().Fail())
174 m_error = m_parent->GetError().Clone();
175 return false;
176 }
177
178 // Regenerate the synthetic filter if our typename changes. When the (dynamic)
179 // type of an object changes, so does their synthetic filter of choice.
180 ConstString new_parent_type_name = m_parent->GetTypeName();
181 if (new_parent_type_name != m_parent_type_name) {
182 LLDB_LOG(log,
183 "[ValueObjectSynthetic::UpdateValue] name={0}, type changed "
184 "from {1} to {2}, recomputing synthetic filter",
185 GetName(), m_parent_type_name, new_parent_type_name);
186 m_parent_type_name = new_parent_type_name;
188 }
189
190 // let our backend do its update
192 LLDB_LOG(log,
193 "[ValueObjectSynthetic::UpdateValue] name={0}, synthetic "
194 "filter said caches are stale - clearing",
195 GetName());
196 // filter said that cached values are stale
197 {
198 std::lock_guard<std::mutex> guard(m_child_mutex);
199 m_children_byindex.clear();
200 m_name_toindex.clear();
201 }
202 // usually, an object's value can change but this does not alter its
203 // children count for a synthetic VO that might indeed happen, so we need
204 // to tell the upper echelons that they need to come back to us asking for
205 // children
206 m_flags.m_children_count_valid = false;
207 {
208 std::lock_guard<std::mutex> guard(m_child_mutex);
210 }
213 } else {
214 LLDB_LOG(log,
215 "[ValueObjectSynthetic::UpdateValue] name={0}, synthetic "
216 "filter said caches are still valid",
217 GetName());
218 }
219
221
222 lldb::ValueObjectSP synth_val(m_synth_filter_up->GetSyntheticValue());
223
224 if (synth_val && synth_val->CanProvideValue()) {
225 LLDB_LOG(log,
226 "[ValueObjectSynthetic::UpdateValue] name={0}, synthetic "
227 "filter said it can provide a value",
228 GetName());
229
231 CopyValueData(synth_val.get());
232 } else {
233 LLDB_LOG(log,
234 "[ValueObjectSynthetic::UpdateValue] name={0}, synthetic "
235 "filter said it will not provide a value",
236 GetName());
237
239 // Copying the data of an incomplete type won't work as it has no byte size.
240 if (m_parent->GetCompilerType().IsCompleteType())
242 }
243
244 SetValueIsValid(true);
245 return true;
246}
247
249 bool can_create) {
251
252 LLDB_LOG(log,
253 "[ValueObjectSynthetic::GetChildAtIndex] name={0}, retrieving "
254 "child at index {1}",
255 GetName(), idx);
256
258
259 ValueObject *valobj;
260 bool child_is_cached;
261 {
262 std::lock_guard<std::mutex> guard(m_child_mutex);
263 auto cached_child_it = m_children_byindex.find(idx);
264 child_is_cached = cached_child_it != m_children_byindex.end();
265 if (child_is_cached)
266 valobj = cached_child_it->second;
267 }
268
269 if (!child_is_cached) {
270 if (can_create && m_synth_filter_up != nullptr) {
271 LLDB_LOG(log,
272 "[ValueObjectSynthetic::GetChildAtIndex] name={0}, child at "
273 "index {1} not cached and will be created",
274 GetName(), idx);
275
276 lldb::ValueObjectSP synth_guy = m_synth_filter_up->GetChildAtIndex(idx);
277
278 LLDB_LOG(
279 log,
280 "[ValueObjectSynthetic::GetChildAtIndex] name={0}, child at index "
281 "{1} created as {2} (is "
282 "synthetic: {3})",
283 GetName(), idx, static_cast<void *>(synth_guy.get()),
284 synth_guy.get()
285 ? (synth_guy->IsSyntheticChildrenGenerated() ? "yes" : "no")
286 : "no");
287
288 if (!synth_guy)
289 return synth_guy;
290
291 if (synth_guy->IsSyntheticChildrenGenerated())
292 synth_guy->SetLogicalParent(this);
293
294 {
295 std::lock_guard<std::mutex> guard(m_child_mutex);
296 if (synth_guy->IsSyntheticChildrenGenerated())
297 m_synthetic_children_cache.push_back(synth_guy);
298 m_children_byindex[idx] = synth_guy.get();
299 }
300 synth_guy->SetPreferredDisplayLanguageIfNeeded(
302
303 if (lldb::ValueObjectSP check_sp =
304 CheckValueObjectOwnership(synth_guy.get()))
305 return check_sp;
306 return synth_guy;
307 } else {
308 LLDB_LOG(log,
309 "[ValueObjectSynthetic::GetChildAtIndex] name={0}, child at "
310 "index {1} not cached and cannot "
311 "be created (can_create = {2}, synth_filter = {3})",
312 GetName(), idx, can_create ? "yes" : "no",
313 static_cast<void *>(m_synth_filter_up.get()));
314
315 return lldb::ValueObjectSP();
316 }
317 } else {
318 LLDB_LOG(log,
319 "[ValueObjectSynthetic::GetChildAtIndex] name={0}, child at "
320 "index {1} cached as {2}",
321 GetName(), idx, static_cast<void *>(valobj));
323 if (check_sp)
324 return check_sp;
325 return valobj->GetSP();
326 }
327}
328
331 bool can_create) {
333
334 auto index_or_err = GetIndexOfChildWithName(name);
335
336 if (!index_or_err) {
337 LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), index_or_err.takeError(),
338 "{0}");
339 return lldb::ValueObjectSP();
340 }
341
342 return GetChildAtIndex(*index_or_err, can_create);
343}
344
345llvm::Expected<size_t>
348
349 ConstString name(name_ref);
350
351 {
352 std::lock_guard<std::mutex> guard(m_child_mutex);
353 auto name_to_index = m_name_toindex.find(name.GetCString());
354 if (name_to_index != m_name_toindex.end())
355 return name_to_index->second;
356 }
357
359 return llvm::createStringErrorV("type has no child named '{0}'", name);
360
361 size_t index;
362 auto index_or_err = m_synth_filter_up->GetIndexOfChildWithName(name);
363 if (index_or_err) {
364 index = *index_or_err;
365 } else {
366 // The front-end does its own subscripting, so its answer is final.
367 if (m_synth_sp->CustomSubscripting())
368 return index_or_err.takeError();
369
370 // Provide automatic support for subscript child names ("[N]").
371 auto maybe_index = formatters::ExtractIndexFromString(name.GetCString());
372 if (!maybe_index)
373 // The child name was not of the form "[N]", return the original error.
374 return index_or_err.takeError();
375
376 // Subscripting succeeded, ignore the original error.
377 llvm::consumeError(index_or_err.takeError());
378 index = *maybe_index;
379
380 // Prevent unnecessary work by limiting max to one past the index.
381 uint32_t max = index + 1;
382 auto num_children = GetNumChildren(max);
383 if (!num_children)
384 return num_children.takeError();
385 if (index >= *num_children)
386 return llvm::createStringErrorV("subscript index out of range: {0}",
387 index);
388 }
389
390 std::lock_guard<std::mutex> guard(m_child_mutex);
391 m_name_toindex[name.GetCString()] = index;
392 return index;
393}
394
395bool ValueObjectSynthetic::IsInScope() { return m_parent->IsInScope(); }
396
400
402 if (!source->UpdateValueIfNeeded())
403 return;
404 m_value = source->GetValue();
406 m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
407}
408
410 if (!UpdateValueIfNeeded())
411 return false;
413 return true;
414 return m_parent->CanProvideValue();
415}
416
418 Status &error) {
419 return m_parent->SetValueFromCString(value_str, error);
420}
421
423 if (m_parent) {
424 m_parent->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
425 m_parent->SetFormat(format);
426 }
427 this->ValueObject::SetFormat(format);
429}
430
432 lldb::LanguageType lang) {
434 if (m_parent)
435 m_parent->SetPreferredDisplayLanguage(lang);
436}
437
446
448 if (m_parent)
449 return m_parent->IsSyntheticChildrenGenerated();
450 return false;
451}
452
454 if (m_parent)
455 m_parent->SetSyntheticChildrenGenerated(b);
457}
458
460 if (m_parent)
461 return m_parent->GetDeclaration(decl);
462
463 return ValueObject::GetDeclaration(decl);
464}
465
467 if (m_parent)
468 return m_parent->GetLanguageFlags();
469 return this->ValueObject::GetLanguageFlags();
470}
471
473 if (m_parent)
474 m_parent->SetLanguageFlags(flags);
475 else
477}
478
480 GetExpressionPathFormat epformat) {
481 // A synthetic ValueObject may wrap an underlying Register or RegisterSet
482 // ValueObject, which requires a different approach to generating the
483 // expression path. In such cases, delegate to the non-synthetic value object.
484 if (const lldb::ValueType obj_value_type = GetValueType();
485 IsSynthetic() && (obj_value_type == lldb::eValueTypeRegister ||
486 obj_value_type == lldb::eValueTypeRegisterSet)) {
487
488 if (const lldb::ValueObjectSP raw_value = GetNonSyntheticValue())
489 return raw_value->GetExpressionPath(stream, epformat);
490 }
491 return ValueObject::GetExpressionPath(stream, epformat);
492}
493
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:405
llvm::Expected< uint32_t > CalculateNumChildren() override
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
llvm::Expected< size_t > GetIndexOfChildWithName(llvm::StringRef name) override
Determine the index of a named child.
DummySyntheticFrontEnd(ValueObject &backend)
Generic representation of a type in a programming language.
bool IsPointerOrReferenceType(CompilerType *pointee_type=nullptr) const
A uniqued constant string class.
Definition ConstString.h:40
const char * GetCString() const
Get the string value as a C string.
A class that describes the declaration location of a lldb object.
Definition Declaration.h:24
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
An error handling class.
Definition Status.h:118
A stream class that can stream formatted output to a file.
Definition Stream.h:28
SyntheticChildrenFrontEnd(ValueObject &backend)
virtual lldb::DynamicValueType GetDynamicValueType()
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx, bool can_create=true) override
bool SetValueFromCString(const char *value_str, Status &error) override
lldb::ValueType GetValueType() const override
lldb::LanguageType GetPreferredDisplayLanguage() override
void GetExpressionPath(Stream &stream, GetExpressionPathFormat epformat=eGetExpressionPathFormatDereferencePointers) override
void SetFormat(lldb::Format format) override
NameToIndexMap m_name_toindex
Guarded by m_child_mutex;.
ByIndexMap m_children_byindex
Guarded by m_child_mutex;.
std::unique_ptr< SyntheticChildrenFrontEnd > m_synth_filter_up
lldb::ValueObjectSP GetDynamicValue(lldb::DynamicValueType valueType) override
void SetSyntheticChildrenGenerated(bool b) override
void SetPreferredDisplayLanguage(lldb::LanguageType)
lldb::ValueObjectSP GetNonSyntheticValue() override
SyntheticChildrenCache m_synthetic_children_cache
Guarded by m_child_mutex;.
llvm::Expected< size_t > GetIndexOfChildWithName(llvm::StringRef name) override
Return the index of the child named name.
bool GetDeclaration(Declaration &decl) override
bool MightHaveChildren() override
Find out if a ValueObject might have children.
lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name, bool can_create=true) override
llvm::Expected< uint64_t > GetByteSize() override
ValueObjectSynthetic(ValueObject &parent, lldb::SyntheticChildrenSP filter)
void SetLanguageFlags(uint64_t flags) override
SyntheticChildrenFrontEnd * GetSyntheticChildrenFrontEnd() override
llvm::Expected< uint32_t > CalculateNumChildren(uint32_t max) override
Should only be called by ValueObject::GetNumChildren().
void SetValueIsValid(bool valid)
lldb::ValueObjectSP CheckValueObjectOwnership(ValueObject *child)
void ClearUserVisibleData(uint32_t items=ValueObject::eClearUserVisibleDataItemsAllStrings)
void SetPreferredDisplayLanguage(lldb::LanguageType lt)
struct lldb_private::ValueObject::Bitflags m_flags
lldb::ValueObjectSP GetSP()
virtual void SetLanguageFlags(uint64_t flags)
Status m_error
An error object that can describe any errors that occur when updating values.
virtual uint64_t GetLanguageFlags()
virtual void SetSyntheticChildrenGenerated(bool b)
DataExtractor m_data
A data extractor that can be used to extract the value.
llvm::Expected< uint32_t > GetNumChildren(uint32_t max=UINT32_MAX)
virtual void GetExpressionPath(Stream &s, GetExpressionPathFormat=eGetExpressionPathFormatDereferencePointers)
virtual lldb::ModuleSP GetModule()
Return the module associated with this value object in case the value is from an executable file and ...
lldb::LanguageType m_preferred_display_language
ValueObject * m_parent
The parent value object, or nullptr if this has no parent.
virtual bool GetDeclaration(Declaration &decl)
void SetName(llvm::StringRef name)
Change the name of the current ValueObject.
bool UpdateValueIfNeeded(bool update_format=true)
ConstString GetName() const
virtual void SetFormat(lldb::Format format)
const ExecutionContextRef & GetExecutionContextRef() const
const Value & GetValue() const
#define UINT32_MAX
std::optional< size_t > ExtractIndexFromString(llvm::StringRef item_name)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
ChildCacheState
Specifies if children need to be re-computed after a call to SyntheticChildrenFrontEnd::Update.
@ eRefetch
Children need to be recomputed dynamically.
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Format
Display format definitions.
LanguageType
Programming language type.
@ eLanguageTypeUnknown
Unknown or invalid language value.
@ eValueTypeRegister
stack frame register value
@ eValueTypeRegisterSet
A collection of stack frame register values.
std::shared_ptr< lldb_private::SyntheticChildren > SyntheticChildrenSP