1 //===-- ValueObjectDynamicValue.cpp ------------------------------*- C++-*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Core/ValueObjectDynamicValue.h"
11 #include "lldb/Core/Scalar.h" // for Scalar, operator!=
12 #include "lldb/Core/Value.h"
13 #include "lldb/Core/ValueObject.h"
14 #include "lldb/Symbol/CompilerType.h"
15 #include "lldb/Symbol/Type.h"
16 #include "lldb/Target/ExecutionContext.h"
17 #include "lldb/Target/LanguageRuntime.h"
18 #include "lldb/Target/Process.h"
19 #include "lldb/Target/Target.h"
20 #include "lldb/Utility/DataExtractor.h" // for DataExtractor
21 #include "lldb/Utility/Log.h"
22 #include "lldb/Utility/Logging.h" // for GetLogIfAllCategoriesSet
23 #include "lldb/Utility/Status.h" // for Status
24 #include "lldb/lldb-types.h" // for addr_t, offset_t
26 #include <string.h> // for strcmp, size_t
27 namespace lldb_private {
31 using namespace lldb_private;
33 ValueObjectDynamicValue::ValueObjectDynamicValue(
34 ValueObject &parent, lldb::DynamicValueType use_dynamic)
35 : ValueObject(parent), m_address(), m_dynamic_type_info(),
36 m_use_dynamic(use_dynamic) {
37 SetName(parent.GetName());
40 ValueObjectDynamicValue::~ValueObjectDynamicValue() {
41 m_owning_valobj_sp.reset();
44 CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
45 const bool success = UpdateValueIfNeeded(false);
47 if (m_dynamic_type_info.HasType())
48 return m_value.GetCompilerType();
50 return m_parent->GetCompilerType();
52 return m_parent->GetCompilerType();
55 ConstString ValueObjectDynamicValue::GetTypeName() {
56 const bool success = UpdateValueIfNeeded(false);
58 if (m_dynamic_type_info.HasName())
59 return m_dynamic_type_info.GetName();
61 return m_parent->GetTypeName();
64 TypeImpl ValueObjectDynamicValue::GetTypeImpl() {
65 const bool success = UpdateValueIfNeeded(false);
66 if (success && m_type_impl.IsValid()) {
69 return m_parent->GetTypeImpl();
72 ConstString ValueObjectDynamicValue::GetQualifiedTypeName() {
73 const bool success = UpdateValueIfNeeded(false);
75 if (m_dynamic_type_info.HasName())
76 return m_dynamic_type_info.GetName();
78 return m_parent->GetQualifiedTypeName();
81 ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
82 const bool success = UpdateValueIfNeeded(false);
84 if (m_dynamic_type_info.HasType())
85 return GetCompilerType().GetDisplayTypeName();
86 if (m_dynamic_type_info.HasName())
87 return m_dynamic_type_info.GetName();
89 return m_parent->GetDisplayTypeName();
92 size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
93 const bool success = UpdateValueIfNeeded(false);
94 if (success && m_dynamic_type_info.HasType()) {
95 auto children_count = GetCompilerType().GetNumChildren(true);
96 return children_count <= max ? children_count : max;
98 return m_parent->GetNumChildren(max);
101 uint64_t ValueObjectDynamicValue::GetByteSize() {
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);
107 return m_parent->GetByteSize();
110 lldb::ValueType ValueObjectDynamicValue::GetValueType() const {
111 return m_parent->GetValueType();
114 bool ValueObjectDynamicValue::UpdateValue() {
115 SetValueIsValid(false);
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();
125 // Setting our type_sp to NULL will route everything back through our
126 // parent which is equivalent to not using dynamic values.
127 if (m_use_dynamic == lldb::eNoDynamicValues) {
128 m_dynamic_type_info.Clear();
132 ExecutionContext exe_ctx(GetExecutionContextRef());
133 Target *target = exe_ctx.GetTargetPtr();
135 m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
136 m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
139 // First make sure our Type and/or Address haven't changed:
140 Process *process = exe_ctx.GetProcessPtr();
144 TypeAndOrName class_type_or_name;
145 Address dynamic_address;
146 bool found_dynamic_type = false;
147 Value::ValueType value_type;
149 LanguageRuntime *runtime = nullptr;
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);
156 found_dynamic_type = runtime->GetDynamicTypeAndAddress(
157 *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
160 runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus);
162 found_dynamic_type = runtime->GetDynamicTypeAndAddress(
163 *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
166 if (!found_dynamic_type) {
167 runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC);
169 found_dynamic_type = runtime->GetDynamicTypeAndAddress(
170 *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
175 // Getting the dynamic value may have run the program a bit, and so marked us
176 // as needing updating, but we really
179 m_update_point.SetUpdated();
181 if (runtime && found_dynamic_type) {
182 if (class_type_or_name.HasType()) {
184 TypeImpl(m_parent->GetCompilerType(),
185 runtime->FixUpDynamicType(class_type_or_name, *m_parent)
194 // If we don't have a dynamic type, then make ourselves just a echo of our
196 // Or we could return false, and make ourselves an echo of our parent?
197 if (!found_dynamic_type) {
198 if (m_dynamic_type_info)
199 SetValueDidChange(true);
200 ClearDynamicTypeInformation();
201 m_dynamic_type_info.Clear();
202 m_value = m_parent->GetValue();
203 m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
204 return m_error.Success();
207 Value old_value(m_value);
209 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
211 bool has_changed_type = false;
213 if (!m_dynamic_type_info) {
214 m_dynamic_type_info = class_type_or_name;
215 has_changed_type = true;
216 } else if (class_type_or_name != m_dynamic_type_info) {
217 // We are another type, we need to tear down our children...
218 m_dynamic_type_info = class_type_or_name;
219 SetValueDidChange(true);
220 has_changed_type = true;
223 if (has_changed_type)
224 ClearDynamicTypeInformation();
226 if (!m_address.IsValid() || m_address != dynamic_address) {
227 if (m_address.IsValid())
228 SetValueDidChange(true);
230 // We've moved, so we should be fine...
231 m_address = dynamic_address;
232 lldb::TargetSP target_sp(GetTargetSP());
233 lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
234 m_value.GetScalar() = load_address;
238 m_dynamic_type_info =
239 runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
241 // m_value.SetContext (Value::eContextTypeClangType, corrected_type);
242 m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
244 m_value.SetValueType(value_type);
246 if (has_changed_type && log)
247 log->Printf("[%s %p] has a new dynamic type %s", GetName().GetCString(),
248 static_cast<void *>(this), GetTypeName().GetCString());
250 if (m_address.IsValid() && m_dynamic_type_info) {
251 // The variable value is in the Scalar value inside the m_value.
252 // We can point our m_data right to it.
253 m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
254 if (m_error.Success()) {
255 if (!CanProvideValue()) {
256 // this value object represents an aggregate type whose
257 // children have values, but this object does not. So we
258 // say we are changed if our location has changed.
259 SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
260 m_value.GetScalar() != old_value.GetScalar());
263 SetValueIsValid(true);
268 // We get here if we've failed above...
269 SetValueIsValid(false);
273 bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
275 bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
277 if (!UpdateValueIfNeeded(false)) {
278 error.SetErrorString("unable to read value");
282 uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
283 uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
285 if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
286 error.SetErrorString("unable to read value");
290 // if we are at an offset from our parent, in order to set ourselves correctly
292 // to change the new value so that it refers to the correct dynamic type. we
293 // choose not to deal
294 // with that - if anything more than a value overwrite is required, you should
296 // expression parser instead of the value editing facility
297 if (my_value != parent_value) {
298 // but NULL'ing out a value should always be allowed
299 if (strcmp(value_str, "0")) {
300 error.SetErrorString(
301 "unable to modify dynamic value, use 'expression' command");
306 bool ret_val = m_parent->SetValueFromCString(value_str, error);
311 bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
312 if (!UpdateValueIfNeeded(false)) {
313 error.SetErrorString("unable to read value");
317 uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
318 uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
320 if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
321 error.SetErrorString("unable to read value");
325 // if we are at an offset from our parent, in order to set ourselves correctly
327 // to change the new value so that it refers to the correct dynamic type. we
328 // choose not to deal
329 // with that - if anything more than a value overwrite is required, you should
331 // expression parser instead of the value editing facility
332 if (my_value != parent_value) {
333 // but NULL'ing out a value should always be allowed
334 lldb::offset_t offset = 0;
336 if (data.GetPointer(&offset) != 0) {
337 error.SetErrorString(
338 "unable to modify dynamic value, use 'expression' command");
343 bool ret_val = m_parent->SetData(data, error);
348 void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
349 lldb::LanguageType lang) {
350 this->ValueObject::SetPreferredDisplayLanguage(lang);
352 m_parent->SetPreferredDisplayLanguage(lang);
355 lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
356 if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
358 return m_parent->GetPreferredDisplayLanguage();
359 return lldb::eLanguageTypeUnknown;
361 return m_preferred_display_language;
364 bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
366 return m_parent->IsSyntheticChildrenGenerated();
370 void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
372 m_parent->SetSyntheticChildrenGenerated(b);
373 this->ValueObject::SetSyntheticChildrenGenerated(b);
376 bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
378 return m_parent->GetDeclaration(decl);
380 return ValueObject::GetDeclaration(decl);
383 uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
385 return m_parent->GetLanguageFlags();
386 return this->ValueObject::GetLanguageFlags();
389 void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
391 m_parent->SetLanguageFlags(flags);
393 this->ValueObject::SetLanguageFlags(flags);