1 //===-- ValueObjectDynamicValue.cpp ---------------------------------*- C++
4 // The LLVM Compiler Infrastructure
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
9 //===----------------------------------------------------------------------===//
11 #include "lldb/Core/ValueObjectDynamicValue.h"
15 // Other libraries and framework includes
17 #include "lldb/Core/Log.h"
18 #include "lldb/Core/Module.h"
19 #include "lldb/Core/Value.h"
20 #include "lldb/Core/ValueObject.h"
21 #include "lldb/Core/ValueObjectList.h"
23 #include "lldb/Symbol/CompilerType.h"
24 #include "lldb/Symbol/ObjectFile.h"
25 #include "lldb/Symbol/SymbolContext.h"
26 #include "lldb/Symbol/Type.h"
27 #include "lldb/Symbol/Variable.h"
29 #include "lldb/Target/ExecutionContext.h"
30 #include "lldb/Target/LanguageRuntime.h"
31 #include "lldb/Target/Process.h"
32 #include "lldb/Target/RegisterContext.h"
33 #include "lldb/Target/Target.h"
34 #include "lldb/Target/Thread.h"
36 using namespace lldb_private;
38 ValueObjectDynamicValue::ValueObjectDynamicValue(
39 ValueObject &parent, lldb::DynamicValueType use_dynamic)
40 : ValueObject(parent), m_address(), m_dynamic_type_info(),
41 m_use_dynamic(use_dynamic) {
42 SetName(parent.GetName());
45 ValueObjectDynamicValue::~ValueObjectDynamicValue() {
46 m_owning_valobj_sp.reset();
49 CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
50 const bool success = UpdateValueIfNeeded(false);
52 if (m_dynamic_type_info.HasType())
53 return m_value.GetCompilerType();
55 return m_parent->GetCompilerType();
57 return m_parent->GetCompilerType();
60 ConstString ValueObjectDynamicValue::GetTypeName() {
61 const bool success = UpdateValueIfNeeded(false);
63 if (m_dynamic_type_info.HasName())
64 return m_dynamic_type_info.GetName();
66 return m_parent->GetTypeName();
69 TypeImpl ValueObjectDynamicValue::GetTypeImpl() {
70 const bool success = UpdateValueIfNeeded(false);
71 if (success && m_type_impl.IsValid()) {
74 return m_parent->GetTypeImpl();
77 ConstString ValueObjectDynamicValue::GetQualifiedTypeName() {
78 const bool success = UpdateValueIfNeeded(false);
80 if (m_dynamic_type_info.HasName())
81 return m_dynamic_type_info.GetName();
83 return m_parent->GetQualifiedTypeName();
86 ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
87 const bool success = UpdateValueIfNeeded(false);
89 if (m_dynamic_type_info.HasType())
90 return GetCompilerType().GetDisplayTypeName();
91 if (m_dynamic_type_info.HasName())
92 return m_dynamic_type_info.GetName();
94 return m_parent->GetDisplayTypeName();
97 size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
98 const bool success = UpdateValueIfNeeded(false);
99 if (success && m_dynamic_type_info.HasType()) {
100 auto children_count = GetCompilerType().GetNumChildren(true);
101 return children_count <= max ? children_count : max;
103 return m_parent->GetNumChildren(max);
106 uint64_t ValueObjectDynamicValue::GetByteSize() {
107 const bool success = UpdateValueIfNeeded(false);
108 if (success && m_dynamic_type_info.HasType()) {
109 ExecutionContext exe_ctx(GetExecutionContextRef());
110 return m_value.GetValueByteSize(nullptr, &exe_ctx);
112 return m_parent->GetByteSize();
115 lldb::ValueType ValueObjectDynamicValue::GetValueType() const {
116 return m_parent->GetValueType();
119 bool ValueObjectDynamicValue::UpdateValue() {
120 SetValueIsValid(false);
123 if (!m_parent->UpdateValueIfNeeded(false)) {
124 // The dynamic value failed to get an error, pass the error along
125 if (m_error.Success() && m_parent->GetError().Fail())
126 m_error = m_parent->GetError();
130 // Setting our type_sp to NULL will route everything back through our
131 // parent which is equivalent to not using dynamic values.
132 if (m_use_dynamic == lldb::eNoDynamicValues) {
133 m_dynamic_type_info.Clear();
137 ExecutionContext exe_ctx(GetExecutionContextRef());
138 Target *target = exe_ctx.GetTargetPtr();
140 m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
141 m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
144 // First make sure our Type and/or Address haven't changed:
145 Process *process = exe_ctx.GetProcessPtr();
149 TypeAndOrName class_type_or_name;
150 Address dynamic_address;
151 bool found_dynamic_type = false;
152 Value::ValueType value_type;
154 LanguageRuntime *runtime = nullptr;
156 lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
157 if (known_type != lldb::eLanguageTypeUnknown &&
158 known_type != lldb::eLanguageTypeC) {
159 runtime = process->GetLanguageRuntime(known_type);
161 found_dynamic_type = runtime->GetDynamicTypeAndAddress(
162 *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
165 runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus);
167 found_dynamic_type = runtime->GetDynamicTypeAndAddress(
168 *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
171 if (!found_dynamic_type) {
172 runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC);
174 found_dynamic_type = runtime->GetDynamicTypeAndAddress(
175 *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
180 // Getting the dynamic value may have run the program a bit, and so marked us
181 // as needing updating, but we really
184 m_update_point.SetUpdated();
186 if (runtime && found_dynamic_type) {
187 if (class_type_or_name.HasType()) {
189 TypeImpl(m_parent->GetCompilerType(),
190 runtime->FixUpDynamicType(class_type_or_name, *m_parent)
199 // If we don't have a dynamic type, then make ourselves just a echo of our
201 // Or we could return false, and make ourselves an echo of our parent?
202 if (!found_dynamic_type) {
203 if (m_dynamic_type_info)
204 SetValueDidChange(true);
205 ClearDynamicTypeInformation();
206 m_dynamic_type_info.Clear();
207 m_value = m_parent->GetValue();
208 m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
209 return m_error.Success();
212 Value old_value(m_value);
214 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
216 bool has_changed_type = false;
218 if (!m_dynamic_type_info) {
219 m_dynamic_type_info = class_type_or_name;
220 has_changed_type = true;
221 } else if (class_type_or_name != m_dynamic_type_info) {
222 // We are another type, we need to tear down our children...
223 m_dynamic_type_info = class_type_or_name;
224 SetValueDidChange(true);
225 has_changed_type = true;
228 if (has_changed_type)
229 ClearDynamicTypeInformation();
231 if (!m_address.IsValid() || m_address != dynamic_address) {
232 if (m_address.IsValid())
233 SetValueDidChange(true);
235 // We've moved, so we should be fine...
236 m_address = dynamic_address;
237 lldb::TargetSP target_sp(GetTargetSP());
238 lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
239 m_value.GetScalar() = load_address;
243 m_dynamic_type_info =
244 runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
246 // m_value.SetContext (Value::eContextTypeClangType, corrected_type);
247 m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
249 m_value.SetValueType(value_type);
251 if (has_changed_type && log)
252 log->Printf("[%s %p] has a new dynamic type %s", GetName().GetCString(),
253 static_cast<void *>(this), GetTypeName().GetCString());
255 if (m_address.IsValid() && m_dynamic_type_info) {
256 // The variable value is in the Scalar value inside the m_value.
257 // We can point our m_data right to it.
258 m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
259 if (m_error.Success()) {
260 if (!CanProvideValue()) {
261 // this value object represents an aggregate type whose
262 // children have values, but this object does not. So we
263 // say we are changed if our location has changed.
264 SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
265 m_value.GetScalar() != old_value.GetScalar());
268 SetValueIsValid(true);
273 // We get here if we've failed above...
274 SetValueIsValid(false);
278 bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
280 bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
282 if (!UpdateValueIfNeeded(false)) {
283 error.SetErrorString("unable to read value");
287 uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
288 uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
290 if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
291 error.SetErrorString("unable to read value");
295 // if we are at an offset from our parent, in order to set ourselves correctly
297 // to change the new value so that it refers to the correct dynamic type. we
298 // choose not to deal
299 // with that - if anything more than a value overwrite is required, you should
301 // expression parser instead of the value editing facility
302 if (my_value != parent_value) {
303 // but NULL'ing out a value should always be allowed
304 if (strcmp(value_str, "0")) {
305 error.SetErrorString(
306 "unable to modify dynamic value, use 'expression' command");
311 bool ret_val = m_parent->SetValueFromCString(value_str, error);
316 bool ValueObjectDynamicValue::SetData(DataExtractor &data, Error &error) {
317 if (!UpdateValueIfNeeded(false)) {
318 error.SetErrorString("unable to read value");
322 uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
323 uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
325 if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
326 error.SetErrorString("unable to read value");
330 // if we are at an offset from our parent, in order to set ourselves correctly
332 // to change the new value so that it refers to the correct dynamic type. we
333 // choose not to deal
334 // with that - if anything more than a value overwrite is required, you should
336 // expression parser instead of the value editing facility
337 if (my_value != parent_value) {
338 // but NULL'ing out a value should always be allowed
339 lldb::offset_t offset = 0;
341 if (data.GetPointer(&offset) != 0) {
342 error.SetErrorString(
343 "unable to modify dynamic value, use 'expression' command");
348 bool ret_val = m_parent->SetData(data, error);
353 void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
354 lldb::LanguageType lang) {
355 this->ValueObject::SetPreferredDisplayLanguage(lang);
357 m_parent->SetPreferredDisplayLanguage(lang);
360 lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
361 if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
363 return m_parent->GetPreferredDisplayLanguage();
364 return lldb::eLanguageTypeUnknown;
366 return m_preferred_display_language;
369 bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
371 return m_parent->IsSyntheticChildrenGenerated();
375 void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
377 m_parent->SetSyntheticChildrenGenerated(b);
378 this->ValueObject::SetSyntheticChildrenGenerated(b);
381 bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
383 return m_parent->GetDeclaration(decl);
385 return ValueObject::GetDeclaration(decl);
388 uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
390 return m_parent->GetLanguageFlags();
391 return this->ValueObject::GetLanguageFlags();
394 void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
396 m_parent->SetLanguageFlags(flags);
398 this->ValueObject::SetLanguageFlags(flags);