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"
12 #include "lldb/Core/ArchSpec.h" // for ArchSpec
13 #include "lldb/Core/Scalar.h" // for Scalar, operator!=
14 #include "lldb/Core/Value.h"
15 #include "lldb/Core/ValueObject.h"
16 #include "lldb/Symbol/CompilerType.h"
17 #include "lldb/Symbol/Type.h"
18 #include "lldb/Target/ExecutionContext.h"
19 #include "lldb/Target/LanguageRuntime.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Utility/DataExtractor.h" // for DataExtractor
23 #include "lldb/Utility/Log.h"
24 #include "lldb/Utility/Logging.h" // for GetLogIfAllCategoriesSet
25 #include "lldb/Utility/Status.h" // for Status
26 #include "lldb/lldb-types.h" // for addr_t, offset_t
28 #include <string.h> // for strcmp, size_t
29 namespace lldb_private {
33 using namespace lldb_private;
35 ValueObjectDynamicValue::ValueObjectDynamicValue(
36 ValueObject &parent, lldb::DynamicValueType use_dynamic)
37 : ValueObject(parent), m_address(), m_dynamic_type_info(),
38 m_use_dynamic(use_dynamic) {
39 SetName(parent.GetName());
42 ValueObjectDynamicValue::~ValueObjectDynamicValue() {
43 m_owning_valobj_sp.reset();
46 CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
47 const bool success = UpdateValueIfNeeded(false);
49 if (m_dynamic_type_info.HasType())
50 return m_value.GetCompilerType();
52 return m_parent->GetCompilerType();
54 return m_parent->GetCompilerType();
57 ConstString ValueObjectDynamicValue::GetTypeName() {
58 const bool success = UpdateValueIfNeeded(false);
60 if (m_dynamic_type_info.HasName())
61 return m_dynamic_type_info.GetName();
63 return m_parent->GetTypeName();
66 TypeImpl ValueObjectDynamicValue::GetTypeImpl() {
67 const bool success = UpdateValueIfNeeded(false);
68 if (success && m_type_impl.IsValid()) {
71 return m_parent->GetTypeImpl();
74 ConstString ValueObjectDynamicValue::GetQualifiedTypeName() {
75 const bool success = UpdateValueIfNeeded(false);
77 if (m_dynamic_type_info.HasName())
78 return m_dynamic_type_info.GetName();
80 return m_parent->GetQualifiedTypeName();
83 ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
84 const bool success = UpdateValueIfNeeded(false);
86 if (m_dynamic_type_info.HasType())
87 return GetCompilerType().GetDisplayTypeName();
88 if (m_dynamic_type_info.HasName())
89 return m_dynamic_type_info.GetName();
91 return m_parent->GetDisplayTypeName();
94 size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
95 const bool success = UpdateValueIfNeeded(false);
96 if (success && m_dynamic_type_info.HasType()) {
97 auto children_count = GetCompilerType().GetNumChildren(true);
98 return children_count <= max ? children_count : max;
100 return m_parent->GetNumChildren(max);
103 uint64_t ValueObjectDynamicValue::GetByteSize() {
104 const bool success = UpdateValueIfNeeded(false);
105 if (success && m_dynamic_type_info.HasType()) {
106 ExecutionContext exe_ctx(GetExecutionContextRef());
107 return m_value.GetValueByteSize(nullptr, &exe_ctx);
109 return m_parent->GetByteSize();
112 lldb::ValueType ValueObjectDynamicValue::GetValueType() const {
113 return m_parent->GetValueType();
116 bool ValueObjectDynamicValue::UpdateValue() {
117 SetValueIsValid(false);
120 if (!m_parent->UpdateValueIfNeeded(false)) {
121 // The dynamic value failed to get an error, pass the error along
122 if (m_error.Success() && m_parent->GetError().Fail())
123 m_error = m_parent->GetError();
127 // Setting our type_sp to NULL will route everything back through our
128 // parent which is equivalent to not using dynamic values.
129 if (m_use_dynamic == lldb::eNoDynamicValues) {
130 m_dynamic_type_info.Clear();
134 ExecutionContext exe_ctx(GetExecutionContextRef());
135 Target *target = exe_ctx.GetTargetPtr();
137 m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
138 m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
141 // First make sure our Type and/or Address haven't changed:
142 Process *process = exe_ctx.GetProcessPtr();
146 TypeAndOrName class_type_or_name;
147 Address dynamic_address;
148 bool found_dynamic_type = false;
149 Value::ValueType value_type;
151 LanguageRuntime *runtime = nullptr;
153 lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
154 if (known_type != lldb::eLanguageTypeUnknown &&
155 known_type != lldb::eLanguageTypeC) {
156 runtime = process->GetLanguageRuntime(known_type);
158 found_dynamic_type = runtime->GetDynamicTypeAndAddress(
159 *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
162 runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus);
164 found_dynamic_type = runtime->GetDynamicTypeAndAddress(
165 *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
168 if (!found_dynamic_type) {
169 runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC);
171 found_dynamic_type = runtime->GetDynamicTypeAndAddress(
172 *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
177 // Getting the dynamic value may have run the program a bit, and so marked us
178 // as needing updating, but we really
181 m_update_point.SetUpdated();
183 if (runtime && found_dynamic_type) {
184 if (class_type_or_name.HasType()) {
186 TypeImpl(m_parent->GetCompilerType(),
187 runtime->FixUpDynamicType(class_type_or_name, *m_parent)
196 // If we don't have a dynamic type, then make ourselves just a echo of our
198 // Or we could return false, and make ourselves an echo of our parent?
199 if (!found_dynamic_type) {
200 if (m_dynamic_type_info)
201 SetValueDidChange(true);
202 ClearDynamicTypeInformation();
203 m_dynamic_type_info.Clear();
204 m_value = m_parent->GetValue();
205 m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
206 return m_error.Success();
209 Value old_value(m_value);
211 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
213 bool has_changed_type = false;
215 if (!m_dynamic_type_info) {
216 m_dynamic_type_info = class_type_or_name;
217 has_changed_type = true;
218 } else if (class_type_or_name != m_dynamic_type_info) {
219 // We are another type, we need to tear down our children...
220 m_dynamic_type_info = class_type_or_name;
221 SetValueDidChange(true);
222 has_changed_type = true;
225 if (has_changed_type)
226 ClearDynamicTypeInformation();
228 if (!m_address.IsValid() || m_address != dynamic_address) {
229 if (m_address.IsValid())
230 SetValueDidChange(true);
232 // We've moved, so we should be fine...
233 m_address = dynamic_address;
234 lldb::TargetSP target_sp(GetTargetSP());
235 lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
236 m_value.GetScalar() = load_address;
240 m_dynamic_type_info =
241 runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
243 // m_value.SetContext (Value::eContextTypeClangType, corrected_type);
244 m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
246 m_value.SetValueType(value_type);
248 if (has_changed_type && log)
249 log->Printf("[%s %p] has a new dynamic type %s", GetName().GetCString(),
250 static_cast<void *>(this), GetTypeName().GetCString());
252 if (m_address.IsValid() && m_dynamic_type_info) {
253 // The variable value is in the Scalar value inside the m_value.
254 // We can point our m_data right to it.
255 m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
256 if (m_error.Success()) {
257 if (!CanProvideValue()) {
258 // this value object represents an aggregate type whose
259 // children have values, but this object does not. So we
260 // say we are changed if our location has changed.
261 SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
262 m_value.GetScalar() != old_value.GetScalar());
265 SetValueIsValid(true);
270 // We get here if we've failed above...
271 SetValueIsValid(false);
275 bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
277 bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
279 if (!UpdateValueIfNeeded(false)) {
280 error.SetErrorString("unable to read value");
284 uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
285 uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
287 if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
288 error.SetErrorString("unable to read value");
292 // if we are at an offset from our parent, in order to set ourselves correctly
294 // to change the new value so that it refers to the correct dynamic type. we
295 // choose not to deal
296 // with that - if anything more than a value overwrite is required, you should
298 // expression parser instead of the value editing facility
299 if (my_value != parent_value) {
300 // but NULL'ing out a value should always be allowed
301 if (strcmp(value_str, "0")) {
302 error.SetErrorString(
303 "unable to modify dynamic value, use 'expression' command");
308 bool ret_val = m_parent->SetValueFromCString(value_str, error);
313 bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
314 if (!UpdateValueIfNeeded(false)) {
315 error.SetErrorString("unable to read value");
319 uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
320 uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
322 if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
323 error.SetErrorString("unable to read value");
327 // if we are at an offset from our parent, in order to set ourselves correctly
329 // to change the new value so that it refers to the correct dynamic type. we
330 // choose not to deal
331 // with that - if anything more than a value overwrite is required, you should
333 // expression parser instead of the value editing facility
334 if (my_value != parent_value) {
335 // but NULL'ing out a value should always be allowed
336 lldb::offset_t offset = 0;
338 if (data.GetPointer(&offset) != 0) {
339 error.SetErrorString(
340 "unable to modify dynamic value, use 'expression' command");
345 bool ret_val = m_parent->SetData(data, error);
350 void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
351 lldb::LanguageType lang) {
352 this->ValueObject::SetPreferredDisplayLanguage(lang);
354 m_parent->SetPreferredDisplayLanguage(lang);
357 lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
358 if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
360 return m_parent->GetPreferredDisplayLanguage();
361 return lldb::eLanguageTypeUnknown;
363 return m_preferred_display_language;
366 bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
368 return m_parent->IsSyntheticChildrenGenerated();
372 void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
374 m_parent->SetSyntheticChildrenGenerated(b);
375 this->ValueObject::SetSyntheticChildrenGenerated(b);
378 bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
380 return m_parent->GetDeclaration(decl);
382 return ValueObject::GetDeclaration(decl);
385 uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
387 return m_parent->GetLanguageFlags();
388 return this->ValueObject::GetLanguageFlags();
391 void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
393 m_parent->SetLanguageFlags(flags);
395 this->ValueObject::SetLanguageFlags(flags);