1 //===-- ValueObjectDynamicValue.cpp ------------------------------*- C++-*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Core/ValueObjectDynamicValue.h"
10 #include "lldb/Core/Value.h"
11 #include "lldb/Core/ValueObject.h"
12 #include "lldb/Symbol/CompilerType.h"
13 #include "lldb/Symbol/Type.h"
14 #include "lldb/Target/ExecutionContext.h"
15 #include "lldb/Target/LanguageRuntime.h"
16 #include "lldb/Target/Process.h"
17 #include "lldb/Target/Target.h"
18 #include "lldb/Utility/DataExtractor.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"
26 namespace lldb_private {
30 using namespace lldb_private;
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());
39 ValueObjectDynamicValue::~ValueObjectDynamicValue() {
40 m_owning_valobj_sp.reset();
43 CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
44 const bool success = UpdateValueIfNeeded(false);
46 if (m_dynamic_type_info.HasType())
47 return m_value.GetCompilerType();
49 return m_parent->GetCompilerType();
51 return m_parent->GetCompilerType();
54 ConstString ValueObjectDynamicValue::GetTypeName() {
55 const bool success = UpdateValueIfNeeded(false);
57 if (m_dynamic_type_info.HasName())
58 return m_dynamic_type_info.GetName();
60 return m_parent->GetTypeName();
63 TypeImpl ValueObjectDynamicValue::GetTypeImpl() {
64 const bool success = UpdateValueIfNeeded(false);
65 if (success && m_type_impl.IsValid()) {
68 return m_parent->GetTypeImpl();
71 ConstString ValueObjectDynamicValue::GetQualifiedTypeName() {
72 const bool success = UpdateValueIfNeeded(false);
74 if (m_dynamic_type_info.HasName())
75 return m_dynamic_type_info.GetName();
77 return m_parent->GetQualifiedTypeName();
80 ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
81 const bool success = UpdateValueIfNeeded(false);
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();
88 return m_parent->GetDisplayTypeName();
91 size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
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;
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 parent
126 // 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 don't...
178 m_update_point.SetUpdated();
180 if (runtime && found_dynamic_type) {
181 if (class_type_or_name.HasType()) {
183 TypeImpl(m_parent->GetCompilerType(),
184 runtime->FixUpDynamicType(class_type_or_name, *m_parent)
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
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, GetModule().get());
203 return m_error.Success();
206 Value old_value(m_value);
208 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
210 bool has_changed_type = false;
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;
222 if (has_changed_type)
223 ClearDynamicTypeInformation();
225 if (!m_address.IsValid() || m_address != dynamic_address) {
226 if (m_address.IsValid())
227 SetValueDidChange(true);
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;
237 m_dynamic_type_info =
238 runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
240 // m_value.SetContext (Value::eContextTypeClangType, corrected_type);
241 m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
243 m_value.SetValueType(value_type);
245 if (has_changed_type && log)
246 LLDB_LOGF(log, "[%s %p] has a new dynamic type %s", GetName().GetCString(),
247 static_cast<void *>(this), GetTypeName().GetCString());
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, 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());
262 SetValueIsValid(true);
267 // We get here if we've failed above...
268 SetValueIsValid(false);
272 bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
274 bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
276 if (!UpdateValueIfNeeded(false)) {
277 error.SetErrorString("unable to read value");
281 uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
282 uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
284 if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
285 error.SetErrorString("unable to read value");
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");
303 bool ret_val = m_parent->SetValueFromCString(value_str, error);
308 bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
309 if (!UpdateValueIfNeeded(false)) {
310 error.SetErrorString("unable to read value");
314 uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
315 uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
317 if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
318 error.SetErrorString("unable to read value");
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;
331 if (data.GetPointer(&offset) != 0) {
332 error.SetErrorString(
333 "unable to modify dynamic value, use 'expression' command");
338 bool ret_val = m_parent->SetData(data, error);
343 void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
344 lldb::LanguageType lang) {
345 this->ValueObject::SetPreferredDisplayLanguage(lang);
347 m_parent->SetPreferredDisplayLanguage(lang);
350 lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
351 if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
353 return m_parent->GetPreferredDisplayLanguage();
354 return lldb::eLanguageTypeUnknown;
356 return m_preferred_display_language;
359 bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
361 return m_parent->IsSyntheticChildrenGenerated();
365 void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
367 m_parent->SetSyntheticChildrenGenerated(b);
368 this->ValueObject::SetSyntheticChildrenGenerated(b);
371 bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
373 return m_parent->GetDeclaration(decl);
375 return ValueObject::GetDeclaration(decl);
378 uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
380 return m_parent->GetLanguageFlags();
381 return this->ValueObject::GetLanguageFlags();
384 void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
386 m_parent->SetLanguageFlags(flags);
388 this->ValueObject::SetLanguageFlags(flags);