LLDB  mainline
ValueObjectDynamicValue.cpp
Go to the documentation of this file.
1 //===-- ValueObjectDynamicValue.cpp ------------------------------*- C++-*-===//
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 #include "lldb/Core/Value.h"
11 #include "lldb/Core/ValueObject.h"
13 #include "lldb/Symbol/Type.h"
16 #include "lldb/Target/Process.h"
17 #include "lldb/Target/Target.h"
19 #include "lldb/Utility/Log.h"
20 #include "lldb/Utility/Logging.h"
21 #include "lldb/Utility/Scalar.h"
22 #include "lldb/Utility/Status.h"
23 #include "lldb/lldb-types.h"
24 
25 #include <string.h>
26 namespace lldb_private {
27 class Declaration;
28 }
29 
30 using namespace lldb_private;
31 
32 ValueObjectDynamicValue::ValueObjectDynamicValue(
33  ValueObject &parent, lldb::DynamicValueType use_dynamic)
34  : ValueObject(parent), m_address(), m_dynamic_type_info(),
35  m_use_dynamic(use_dynamic) {
36  SetName(parent.GetName());
37 }
38 
40  m_owning_valobj_sp.reset();
41 }
42 
44  const bool success = UpdateValueIfNeeded(false);
45  if (success) {
46  if (m_dynamic_type_info.HasType())
47  return m_value.GetCompilerType();
48  else
49  return m_parent->GetCompilerType();
50  }
51  return m_parent->GetCompilerType();
52 }
53 
55  const bool success = UpdateValueIfNeeded(false);
56  if (success) {
57  if (m_dynamic_type_info.HasName())
58  return m_dynamic_type_info.GetName();
59  }
60  return m_parent->GetTypeName();
61 }
62 
64  const bool success = UpdateValueIfNeeded(false);
65  if (success && m_type_impl.IsValid()) {
66  return m_type_impl;
67  }
68  return m_parent->GetTypeImpl();
69 }
70 
72  const bool success = UpdateValueIfNeeded(false);
73  if (success) {
74  if (m_dynamic_type_info.HasName())
75  return m_dynamic_type_info.GetName();
76  }
77  return m_parent->GetQualifiedTypeName();
78 }
79 
81  const bool success = UpdateValueIfNeeded(false);
82  if (success) {
83  if (m_dynamic_type_info.HasType())
84  return GetCompilerType().GetDisplayTypeName();
85  if (m_dynamic_type_info.HasName())
86  return m_dynamic_type_info.GetName();
87  }
88  return m_parent->GetDisplayTypeName();
89 }
90 
92  const bool success = UpdateValueIfNeeded(false);
93  if (success && m_dynamic_type_info.HasType()) {
94  ExecutionContext exe_ctx(GetExecutionContextRef());
95  auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
96  return children_count <= max ? children_count : max;
97  } else
98  return m_parent->GetNumChildren(max);
99 }
100 
102  const bool success = UpdateValueIfNeeded(false);
103  if (success && m_dynamic_type_info.HasType()) {
104  ExecutionContext exe_ctx(GetExecutionContextRef());
105  return m_value.GetValueByteSize(nullptr, &exe_ctx);
106  } else
107  return m_parent->GetByteSize();
108 }
109 
111  return m_parent->GetValueType();
112 }
113 
115  SetValueIsValid(false);
116  m_error.Clear();
117 
118  if (!m_parent->UpdateValueIfNeeded(false)) {
119  // The dynamic value failed to get an error, pass the error along
120  if (m_error.Success() && m_parent->GetError().Fail())
121  m_error = m_parent->GetError();
122  return false;
123  }
124 
125  // Setting our type_sp to NULL will route everything back through our parent
126  // which is equivalent to not using dynamic values.
127  if (m_use_dynamic == lldb::eNoDynamicValues) {
128  m_dynamic_type_info.Clear();
129  return true;
130  }
131 
132  ExecutionContext exe_ctx(GetExecutionContextRef());
133  Target *target = exe_ctx.GetTargetPtr();
134  if (target) {
135  m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
136  m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
137  }
138 
139  // First make sure our Type and/or Address haven't changed:
140  Process *process = exe_ctx.GetProcessPtr();
141  if (!process)
142  return false;
143 
144  TypeAndOrName class_type_or_name;
145  Address dynamic_address;
146  bool found_dynamic_type = false;
147  Value::ValueType value_type;
148 
149  LanguageRuntime *runtime = nullptr;
150 
151  lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
152  if (known_type != lldb::eLanguageTypeUnknown &&
153  known_type != lldb::eLanguageTypeC) {
154  runtime = process->GetLanguageRuntime(known_type);
155  if (runtime)
156  found_dynamic_type = runtime->GetDynamicTypeAndAddress(
157  *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
158  value_type);
159  } else {
161  if (runtime)
162  found_dynamic_type = runtime->GetDynamicTypeAndAddress(
163  *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
164  value_type);
165 
166  if (!found_dynamic_type) {
167  runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC);
168  if (runtime)
169  found_dynamic_type = runtime->GetDynamicTypeAndAddress(
170  *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
171  value_type);
172  }
173  }
174 
175  // Getting the dynamic value may have run the program a bit, and so marked us
176  // as needing updating, but we really don't...
177 
178  m_update_point.SetUpdated();
179 
180  if (runtime && found_dynamic_type) {
181  if (class_type_or_name.HasType()) {
182  m_type_impl =
183  TypeImpl(m_parent->GetCompilerType(),
184  runtime->FixUpDynamicType(class_type_or_name, *m_parent)
185  .GetCompilerType());
186  } else {
187  m_type_impl.Clear();
188  }
189  } else {
190  m_type_impl.Clear();
191  }
192 
193  // If we don't have a dynamic type, then make ourselves just a echo of our
194  // parent. Or we could return false, and make ourselves an echo of our
195  // parent?
196  if (!found_dynamic_type) {
197  if (m_dynamic_type_info)
198  SetValueDidChange(true);
199  ClearDynamicTypeInformation();
200  m_dynamic_type_info.Clear();
201  m_value = m_parent->GetValue();
202  m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
203  return m_error.Success();
204  }
205 
206  Value old_value(m_value);
207 
209 
210  bool has_changed_type = false;
211 
212  if (!m_dynamic_type_info) {
213  m_dynamic_type_info = class_type_or_name;
214  has_changed_type = true;
215  } else if (class_type_or_name != m_dynamic_type_info) {
216  // We are another type, we need to tear down our children...
217  m_dynamic_type_info = class_type_or_name;
218  SetValueDidChange(true);
219  has_changed_type = true;
220  }
221 
222  if (has_changed_type)
223  ClearDynamicTypeInformation();
224 
225  if (!m_address.IsValid() || m_address != dynamic_address) {
226  if (m_address.IsValid())
227  SetValueDidChange(true);
228 
229  // We've moved, so we should be fine...
230  m_address = dynamic_address;
231  lldb::TargetSP target_sp(GetTargetSP());
232  lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
233  m_value.GetScalar() = load_address;
234  }
235 
236  if (runtime)
237  m_dynamic_type_info =
238  runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
239 
240  // m_value.SetContext (Value::eContextTypeClangType, corrected_type);
241  m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
242 
243  m_value.SetValueType(value_type);
244 
245  if (has_changed_type && log)
246  log->Printf("[%s %p] has a new dynamic type %s", GetName().GetCString(),
247  static_cast<void *>(this), GetTypeName().GetCString());
248 
249  if (m_address.IsValid() && m_dynamic_type_info) {
250  // The variable value is in the Scalar value inside the m_value. We can
251  // point our m_data right to it.
252  m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
253  if (m_error.Success()) {
254  if (!CanProvideValue()) {
255  // this value object represents an aggregate type whose children have
256  // values, but this object does not. So we say we are changed if our
257  // location has changed.
258  SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
259  m_value.GetScalar() != old_value.GetScalar());
260  }
261 
262  SetValueIsValid(true);
263  return true;
264  }
265  }
266 
267  // We get here if we've failed above...
268  SetValueIsValid(false);
269  return false;
270 }
271 
272 bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
273 
275  Status &error) {
276  if (!UpdateValueIfNeeded(false)) {
277  error.SetErrorString("unable to read value");
278  return false;
279  }
280 
281  uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
282  uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
283 
284  if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
285  error.SetErrorString("unable to read value");
286  return false;
287  }
288 
289  // if we are at an offset from our parent, in order to set ourselves
290  // correctly we would need to change the new value so that it refers to the
291  // correct dynamic type. we choose not to deal with that - if anything more
292  // than a value overwrite is required, you should be using the expression
293  // parser instead of the value editing facility
294  if (my_value != parent_value) {
295  // but NULL'ing out a value should always be allowed
296  if (strcmp(value_str, "0")) {
297  error.SetErrorString(
298  "unable to modify dynamic value, use 'expression' command");
299  return false;
300  }
301  }
302 
303  bool ret_val = m_parent->SetValueFromCString(value_str, error);
304  SetNeedsUpdate();
305  return ret_val;
306 }
307 
309  if (!UpdateValueIfNeeded(false)) {
310  error.SetErrorString("unable to read value");
311  return false;
312  }
313 
314  uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
315  uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
316 
317  if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
318  error.SetErrorString("unable to read value");
319  return false;
320  }
321 
322  // if we are at an offset from our parent, in order to set ourselves
323  // correctly we would need to change the new value so that it refers to the
324  // correct dynamic type. we choose not to deal with that - if anything more
325  // than a value overwrite is required, you should be using the expression
326  // parser instead of the value editing facility
327  if (my_value != parent_value) {
328  // but NULL'ing out a value should always be allowed
329  lldb::offset_t offset = 0;
330 
331  if (data.GetPointer(&offset) != 0) {
332  error.SetErrorString(
333  "unable to modify dynamic value, use 'expression' command");
334  return false;
335  }
336  }
337 
338  bool ret_val = m_parent->SetData(data, error);
339  SetNeedsUpdate();
340  return ret_val;
341 }
342 
344  lldb::LanguageType lang) {
346  if (m_parent)
347  m_parent->SetPreferredDisplayLanguage(lang);
348 }
349 
351  if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
352  if (m_parent)
353  return m_parent->GetPreferredDisplayLanguage();
355  } else
356  return m_preferred_display_language;
357 }
358 
360  if (m_parent)
361  return m_parent->IsSyntheticChildrenGenerated();
362  return false;
363 }
364 
366  if (m_parent)
367  m_parent->SetSyntheticChildrenGenerated(b);
369 }
370 
372  if (m_parent)
373  return m_parent->GetDeclaration(decl);
374 
375  return ValueObject::GetDeclaration(decl);
376 }
377 
379  if (m_parent)
380  return m_parent->GetLanguageFlags();
381  return this->ValueObject::GetLanguageFlags();
382 }
383 
385  if (m_parent)
386  m_parent->SetLanguageFlags(flags);
387  else
388  this->ValueObject::SetLanguageFlags(flags);
389 }
An data extractor class.
Definition: DataExtractor.h:47
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
const ArchSpec & GetArchitecture() const
Definition: Target.h:941
Sometimes you can find the name of the type corresponding to an object, but we don&#39;t have debug infor...
Definition: Type.h:396
CompilerType GetCompilerType() const
Definition: Type.h:410
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
Definition: ArchSpec.cpp:742
ConstString GetName() const
void SetPreferredDisplayLanguage(lldb::LanguageType)
size_t CalculateNumChildren(uint32_t max) override
bool SetData(DataExtractor &data, Status &error) override
virtual uint64_t GetLanguageFlags()
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
bool GetDeclaration(Declaration &decl) override
void SetCompilerType(CompilerType compiler_type)
Definition: Type.cpp:742
lldb::LanguageType GetPreferredDisplayLanguage() override
ValueType GetValueType() const
Definition: Value.cpp:114
Target * GetTargetPtr() const
Returns a pointer to the target object.
LanguageType
Programming language type.
uint64_t offset_t
Definition: lldb-types.h:87
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:57
void SetLanguageFlags(uint64_t flags) override
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
A plug-in interface definition class for debugging a process.
Definition: Process.h:353
Process * GetProcessPtr() const
Returns a pointer to the process object.
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
Definition: ArchSpec.cpp:788
A section + offset based address class.
Definition: Address.h:80
uint64_t addr_t
Definition: lldb-types.h:83
A uniqued constant string class.
Definition: ConstString.h:38
Unknown or invalid language value.
virtual bool GetDeclaration(Declaration &decl)
lldb::ValueType GetValueType() const override
Non-standardized C, such as K&R.
virtual bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &address, Value::ValueType &value_type)=0
virtual LanguageRuntime * GetLanguageRuntime(lldb::LanguageType language, bool retry_if_null=true)
Definition: Process.cpp:1547
virtual TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value)=0
virtual void SetLanguageFlags(uint64_t flags)
bool SetValueFromCString(const char *value_str, Status &error) override
#define LIBLLDB_LOG_TYPES
Definition: Logging.h:33
const Scalar & GetScalar() const
Definition: Value.h:178
virtual void SetSyntheticChildrenGenerated(bool b)
bool HasType() const
Definition: Type.h:426
A class that describes the declaration location of a lldb object.
Definition: Declaration.h:24
#define UINT64_MAX
Definition: lldb-defines.h:35
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
uint64_t GetPointer(lldb::offset_t *offset_ptr) const
Extract an pointer from *offset_ptr.
An error handling class.
Definition: Status.h:44