LLDB  mainline
ValueObjectSyntheticFilter.cpp
Go to the documentation of this file.
1 //===-- ValueObjectSyntheticFilter.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"
12 #include "lldb/Core/ValueObject.h"
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/Logging.h"
17 #include "lldb/Utility/Status.h"
18 
19 #include "llvm/ADT/STLExtras.h"
20 
21 namespace lldb_private {
22 class Declaration;
23 }
24 
25 using namespace lldb_private;
26 
28 public:
30  : SyntheticChildrenFrontEnd(backend) {}
31 
32  size_t CalculateNumChildren() override { return m_backend.GetNumChildren(); }
33 
34  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
35  return m_backend.GetChildAtIndex(idx, true);
36  }
37 
38  size_t GetIndexOfChildWithName(ConstString name) override {
39  return m_backend.GetIndexOfChildWithName(name);
40  }
41 
42  bool MightHaveChildren() override { return true; }
43 
44  bool Update() override { return false; }
45 };
46 
48  lldb::SyntheticChildrenSP filter)
49  : ValueObject(parent), m_synth_sp(filter), m_children_byindex(),
50  m_name_toindex(), m_synthetic_children_cache(),
51  m_synthetic_children_count(UINT32_MAX),
52  m_parent_type_name(parent.GetTypeName()),
53  m_might_have_children(eLazyBoolCalculate),
54  m_provides_value(eLazyBoolCalculate) {
55  SetName(parent.GetName());
56  // Copying the data of an incomplete type won't work as it has no byte size.
60 }
61 
63 
65  return m_parent->GetCompilerType();
66 }
67 
69  return m_parent->GetTypeName();
70 }
71 
74 }
75 
77  if (ConstString synth_name = m_synth_filter_up->GetSyntheticTypeName())
78  return synth_name;
79 
80  return m_parent->GetDisplayTypeName();
81 }
82 
85 
89 
90  if (max < UINT32_MAX) {
91  size_t num_children = m_synth_filter_up->CalculateNumChildren(max);
92  LLDB_LOGF(log,
93  "[ValueObjectSynthetic::CalculateNumChildren] for VO of name "
94  "%s and type %s, the filter returned %zu child values",
95  GetName().AsCString(), GetTypeName().AsCString(), num_children);
96  return num_children;
97  } else {
98  size_t num_children = (m_synthetic_children_count =
99  m_synth_filter_up->CalculateNumChildren(max));
100  LLDB_LOGF(log,
101  "[ValueObjectSynthetic::CalculateNumChildren] for VO of name "
102  "%s and type %s, the filter returned %zu child values",
103  GetName().AsCString(), GetTypeName().AsCString(), num_children);
104  return num_children;
105  }
106 }
107 
108 lldb::ValueObjectSP
110  if (!m_parent)
111  return lldb::ValueObjectSP();
112  if (IsDynamic() && GetDynamicValueType() == valueType)
113  return GetSP();
114  return m_parent->GetDynamicValue(valueType);
115 }
116 
120  (m_synth_filter_up->MightHaveChildren() ? eLazyBoolYes : eLazyBoolNo);
122 }
123 
125 
127  return m_parent->GetValueType();
128 }
129 
131  ValueObject *valobj_for_frontend = m_parent;
132  if (m_synth_sp->WantsDereference())
133  {
135  if (type.IsValid() && type.IsPointerOrReferenceType())
136  {
137  Status error;
138  lldb::ValueObjectSP deref_sp = m_parent->Dereference(error);
139  if (error.Success())
140  valobj_for_frontend = deref_sp.get();
141  }
142  }
143  m_synth_filter_up = (m_synth_sp->GetFrontEnd(*valobj_for_frontend));
144  if (!m_synth_filter_up)
145  m_synth_filter_up = std::make_unique<DummySyntheticFrontEnd>(*m_parent);
146 }
147 
150 
151  SetValueIsValid(false);
152  m_error.Clear();
153 
154  if (!m_parent->UpdateValueIfNeeded(false)) {
155  // our parent could not update.. as we are meaningless without a parent,
156  // just stop
157  if (m_parent->GetError().Fail())
159  return false;
160  }
161 
162  // regenerate the synthetic filter if our typename changes
163  // <rdar://problem/12424824>
164  ConstString new_parent_type_name = m_parent->GetTypeName();
165  if (new_parent_type_name != m_parent_type_name) {
166  LLDB_LOGF(log,
167  "[ValueObjectSynthetic::UpdateValue] name=%s, type changed "
168  "from %s to %s, recomputing synthetic filter",
169  GetName().AsCString(), m_parent_type_name.AsCString(),
170  new_parent_type_name.AsCString());
171  m_parent_type_name = new_parent_type_name;
173  }
174 
175  // let our backend do its update
176  if (!m_synth_filter_up->Update()) {
177  LLDB_LOGF(log,
178  "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
179  "filter said caches are stale - clearing",
180  GetName().AsCString());
181  // filter said that cached values are stale
182  {
183  std::lock_guard<std::mutex> guard(m_child_mutex);
184  m_children_byindex.clear();
185  m_name_toindex.clear();
186  }
187  // usually, an object's value can change but this does not alter its
188  // children count for a synthetic VO that might indeed happen, so we need
189  // to tell the upper echelons that they need to come back to us asking for
190  // children
191  m_children_count_valid = false;
192  {
193  std::lock_guard<std::mutex> guard(m_child_mutex);
195  }
198  } else {
199  LLDB_LOGF(log,
200  "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
201  "filter said caches are still valid",
202  GetName().AsCString());
203  }
204 
206 
207  lldb::ValueObjectSP synth_val(m_synth_filter_up->GetSyntheticValue());
208 
209  if (synth_val && synth_val->CanProvideValue()) {
210  LLDB_LOGF(log,
211  "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
212  "filter said it can provide a value",
213  GetName().AsCString());
214 
216  CopyValueData(synth_val.get());
217  } else {
218  LLDB_LOGF(log,
219  "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
220  "filter said it will not provide a value",
221  GetName().AsCString());
222 
224  // Copying the data of an incomplete type won't work as it has no byte size.
227  }
228 
229  SetValueIsValid(true);
230  return true;
231 }
232 
233 lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(size_t idx,
234  bool can_create) {
236 
237  LLDB_LOGF(log,
238  "[ValueObjectSynthetic::GetChildAtIndex] name=%s, retrieving "
239  "child at index %zu",
240  GetName().AsCString(), idx);
241 
243 
244  ValueObject *valobj;
245  bool child_is_cached;
246  {
247  std::lock_guard<std::mutex> guard(m_child_mutex);
248  auto cached_child_it = m_children_byindex.find(idx);
249  child_is_cached = cached_child_it != m_children_byindex.end();
250  if (child_is_cached)
251  valobj = cached_child_it->second;
252  }
253 
254  if (!child_is_cached) {
255  if (can_create && m_synth_filter_up != nullptr) {
256  LLDB_LOGF(log,
257  "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
258  "index %zu not cached and will be created",
259  GetName().AsCString(), idx);
260 
261  lldb::ValueObjectSP synth_guy = m_synth_filter_up->GetChildAtIndex(idx);
262 
263  LLDB_LOGF(
264  log,
265  "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index "
266  "%zu created as %p (is "
267  "synthetic: %s)",
268  GetName().AsCString(), idx, static_cast<void *>(synth_guy.get()),
269  synth_guy.get()
270  ? (synth_guy->IsSyntheticChildrenGenerated() ? "yes" : "no")
271  : "no");
272 
273  if (!synth_guy)
274  return synth_guy;
275 
276  {
277  std::lock_guard<std::mutex> guard(m_child_mutex);
278  if (synth_guy->IsSyntheticChildrenGenerated())
279  m_synthetic_children_cache.push_back(synth_guy);
280  m_children_byindex[idx] = synth_guy.get();
281  }
282  synth_guy->SetPreferredDisplayLanguageIfNeeded(
284  return synth_guy;
285  } else {
286  LLDB_LOGF(log,
287  "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
288  "index %zu not cached and cannot "
289  "be created (can_create = %s, synth_filter = %p)",
290  GetName().AsCString(), idx, can_create ? "yes" : "no",
291  static_cast<void *>(m_synth_filter_up.get()));
292 
293  return lldb::ValueObjectSP();
294  }
295  } else {
296  LLDB_LOGF(log,
297  "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
298  "index %zu cached as %p",
299  GetName().AsCString(), idx, static_cast<void *>(valobj));
300 
301  return valobj->GetSP();
302  }
303 }
304 
305 lldb::ValueObjectSP
307  bool can_create) {
309 
310  uint32_t index = GetIndexOfChildWithName(name);
311 
312  if (index == UINT32_MAX)
313  return lldb::ValueObjectSP();
314 
315  return GetChildAtIndex(index, can_create);
316 }
317 
320 
321  uint32_t found_index = UINT32_MAX;
322  bool did_find;
323  {
324  std::lock_guard<std::mutex> guard(m_child_mutex);
325  auto name_to_index = m_name_toindex.find(name.GetCString());
326  did_find = name_to_index != m_name_toindex.end();
327  if (did_find)
328  found_index = name_to_index->second;
329  }
330 
331  if (!did_find && m_synth_filter_up != nullptr) {
332  uint32_t index = m_synth_filter_up->GetIndexOfChildWithName(name);
333  if (index == UINT32_MAX)
334  return index;
335  std::lock_guard<std::mutex> guard(m_child_mutex);
336  m_name_toindex[name.GetCString()] = index;
337  return index;
338  } else if (!did_find && m_synth_filter_up == nullptr)
339  return UINT32_MAX;
340  else /*if (iter != m_name_toindex.end())*/
341  return found_index;
342 }
343 
345 
347  return m_parent->GetSP();
348 }
349 
351  m_value = (source->UpdateValueIfNeeded(), source->GetValue());
353  m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
354 }
355 
357  if (!UpdateValueIfNeeded())
358  return false;
360  return true;
361  return m_parent->CanProvideValue();
362 }
363 
364 bool ValueObjectSynthetic::SetValueFromCString(const char *value_str,
365  Status &error) {
366  return m_parent->SetValueFromCString(value_str, error);
367 }
368 
370  if (m_parent) {
372  m_parent->SetFormat(format);
373  }
374  this->ValueObject::SetFormat(format);
376 }
377 
379  lldb::LanguageType lang) {
381  if (m_parent)
383 }
384 
387  if (m_parent)
390  } else
392 }
393 
395  if (m_parent)
397  return false;
398 }
399 
401  if (m_parent)
404 }
405 
407  if (m_parent)
408  return m_parent->GetDeclaration(decl);
409 
410  return ValueObject::GetDeclaration(decl);
411 }
412 
414  if (m_parent)
415  return m_parent->GetLanguageFlags();
416  return this->ValueObject::GetLanguageFlags();
417 }
418 
420  if (m_parent)
421  m_parent->SetLanguageFlags(flags);
422  else
423  this->ValueObject::SetLanguageFlags(flags);
424 }
NameToIndexMap m_name_toindex
Guarded by m_child_mutex;.
#define LIBLLDB_LOG_DATAFORMATTERS
Definition: Logging.h:43
CompilerType GetCompilerType()
A class that represents a running process on the host machine.
bool IsPointerOrReferenceType(CompilerType *pointee_type=nullptr) const
virtual lldb::LanguageType GetPreferredDisplayLanguage()
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:223
bool SetValueFromCString(const char *value_str, Status &error) override
virtual lldb::ValueObjectSP Dereference(Status &error)
virtual ConstString GetTypeName()
void SetFormat(lldb::Format format) override
ConstString GetName() const
virtual bool SetValueFromCString(const char *value_str, Status &error)
void SetPreferredDisplayLanguage(lldb::LanguageType)
virtual uint64_t GetLanguageFlags()
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
const Status & GetError()
lldb::ValueObjectSP GetChildMemberWithName(ConstString name, bool can_create) override
Format
Display format definitions.
Status GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, Module *module)
Definition: Value.cpp:316
virtual lldb::ModuleSP GetModule()
lldb::LanguageType GetPreferredDisplayLanguage() override
virtual lldb::DynamicValueType GetDynamicValueType()
lldb::LanguageType m_preferred_display_language
Definition: ValueObject.h:878
virtual ConstString GetQualifiedTypeName()
#define UINT32_MAX
Definition: lldb-defines.h:31
LanguageType
Programming language type.
virtual bool CanProvideValue()
ByIndexMap m_children_byindex
Guarded by m_child_mutex;.
virtual void SetFormat(lldb::Format format)
Definition: ValueObject.h:689
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:58
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
size_t GetIndexOfChildWithName(ConstString name) override
void Clear()
Clear the object state.
Definition: Status.cpp:168
std::unique_ptr< SyntheticChildrenFrontEnd > m_synth_filter_up
void ClearUserVisibleData(uint32_t items=ValueObject::eClearUserVisibleDataItemsAllStrings)
const ExecutionContextRef & GetExecutionContextRef() const
Definition: ValueObject.h:331
virtual bool IsInScope()
Definition: ValueObject.h:411
bool Success() const
Test for success condition.
Definition: Status.cpp:288
virtual lldb::ValueObjectSP GetDynamicValue(lldb::DynamicValueType valueType)
virtual uint64_t GetByteSize()=0
SyntheticChildrenCache m_synthetic_children_cache
Guarded by m_child_mutex;.
virtual bool IsSyntheticChildrenGenerated()
void SetValueIsValid(bool valid)
#define LLDB_LOGF(log,...)
Definition: Log.h:249
bool GetDeclaration(Declaration &decl) override
bool UpdateValueIfNeeded(bool update_format=true)
lldb::ValueObjectSP GetChildAtIndex(size_t idx, bool can_create) override
A uniqued constant string class.
Definition: ConstString.h:40
Unknown or invalid language value.
virtual bool GetDeclaration(Declaration &decl)
bool Fail() const
Test for error condition.
Definition: Status.cpp:182
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:246
lldb::ValueObjectSP GetNonSyntheticValue() override
ValueObjectSynthetic(ValueObject &parent, lldb::SyntheticChildrenSP filter)
Represents a generic type in a programming language.
Definition: CompilerType.h:33
lldb::ValueObjectSP GetSP()
Definition: ValueObject.h:539
lldb::ValueObjectSP GetDynamicValue(lldb::DynamicValueType valueType) override
virtual lldb::ValueType GetValueType() const =0
size_t CalculateNumChildren(uint32_t max) override
const Value & GetValue() const
virtual void SetLanguageFlags(uint64_t flags)
DummySyntheticFrontEnd(ValueObject &backend)
void SetName(ConstString name)
virtual void SetSyntheticChildrenGenerated(bool b)
virtual ConstString GetDisplayTypeName()
A class that describes the declaration location of a lldb object.
Definition: Declaration.h:24
bool MightHaveChildren() override
Find out if a ValueObject might have children.
size_t GetIndexOfChildWithName(ConstString name) override
void SetLanguageFlags(uint64_t flags) override
lldb::ValueType GetValueType() const override
An error handling class.
Definition: Status.h:44