1dda28197Spatrick //===-- ValueObjectDynamicValue.cpp ---------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "lldb/Core/ValueObjectDynamicValue.h"
10061da546Spatrick #include "lldb/Core/Value.h"
11061da546Spatrick #include "lldb/Core/ValueObject.h"
12061da546Spatrick #include "lldb/Symbol/CompilerType.h"
13061da546Spatrick #include "lldb/Symbol/Type.h"
14061da546Spatrick #include "lldb/Target/ExecutionContext.h"
15061da546Spatrick #include "lldb/Target/LanguageRuntime.h"
16061da546Spatrick #include "lldb/Target/Process.h"
17061da546Spatrick #include "lldb/Target/Target.h"
18061da546Spatrick #include "lldb/Utility/DataExtractor.h"
19*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
20061da546Spatrick #include "lldb/Utility/Log.h"
21061da546Spatrick #include "lldb/Utility/Scalar.h"
22061da546Spatrick #include "lldb/Utility/Status.h"
23061da546Spatrick #include "lldb/lldb-types.h"
24061da546Spatrick
25be691f3bSpatrick #include <cstring>
26*f6aab3d8Srobert #include <optional>
27061da546Spatrick namespace lldb_private {
28061da546Spatrick class Declaration;
29061da546Spatrick }
30061da546Spatrick
31061da546Spatrick using namespace lldb_private;
32061da546Spatrick
ValueObjectDynamicValue(ValueObject & parent,lldb::DynamicValueType use_dynamic)33061da546Spatrick ValueObjectDynamicValue::ValueObjectDynamicValue(
34061da546Spatrick ValueObject &parent, lldb::DynamicValueType use_dynamic)
35061da546Spatrick : ValueObject(parent), m_address(), m_dynamic_type_info(),
36061da546Spatrick m_use_dynamic(use_dynamic) {
37061da546Spatrick SetName(parent.GetName());
38061da546Spatrick }
39061da546Spatrick
GetCompilerTypeImpl()40061da546Spatrick CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
41061da546Spatrick const bool success = UpdateValueIfNeeded(false);
42061da546Spatrick if (success) {
43061da546Spatrick if (m_dynamic_type_info.HasType())
44061da546Spatrick return m_value.GetCompilerType();
45061da546Spatrick else
46061da546Spatrick return m_parent->GetCompilerType();
47061da546Spatrick }
48061da546Spatrick return m_parent->GetCompilerType();
49061da546Spatrick }
50061da546Spatrick
GetTypeName()51061da546Spatrick ConstString ValueObjectDynamicValue::GetTypeName() {
52061da546Spatrick const bool success = UpdateValueIfNeeded(false);
53061da546Spatrick if (success) {
54061da546Spatrick if (m_dynamic_type_info.HasName())
55061da546Spatrick return m_dynamic_type_info.GetName();
56061da546Spatrick }
57061da546Spatrick return m_parent->GetTypeName();
58061da546Spatrick }
59061da546Spatrick
GetTypeImpl()60061da546Spatrick TypeImpl ValueObjectDynamicValue::GetTypeImpl() {
61061da546Spatrick const bool success = UpdateValueIfNeeded(false);
62061da546Spatrick if (success && m_type_impl.IsValid()) {
63061da546Spatrick return m_type_impl;
64061da546Spatrick }
65061da546Spatrick return m_parent->GetTypeImpl();
66061da546Spatrick }
67061da546Spatrick
GetQualifiedTypeName()68061da546Spatrick ConstString ValueObjectDynamicValue::GetQualifiedTypeName() {
69061da546Spatrick const bool success = UpdateValueIfNeeded(false);
70061da546Spatrick if (success) {
71061da546Spatrick if (m_dynamic_type_info.HasName())
72061da546Spatrick return m_dynamic_type_info.GetName();
73061da546Spatrick }
74061da546Spatrick return m_parent->GetQualifiedTypeName();
75061da546Spatrick }
76061da546Spatrick
GetDisplayTypeName()77061da546Spatrick ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
78061da546Spatrick const bool success = UpdateValueIfNeeded(false);
79061da546Spatrick if (success) {
80061da546Spatrick if (m_dynamic_type_info.HasType())
81061da546Spatrick return GetCompilerType().GetDisplayTypeName();
82061da546Spatrick if (m_dynamic_type_info.HasName())
83061da546Spatrick return m_dynamic_type_info.GetName();
84061da546Spatrick }
85061da546Spatrick return m_parent->GetDisplayTypeName();
86061da546Spatrick }
87061da546Spatrick
CalculateNumChildren(uint32_t max)88061da546Spatrick size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
89061da546Spatrick const bool success = UpdateValueIfNeeded(false);
90061da546Spatrick if (success && m_dynamic_type_info.HasType()) {
91061da546Spatrick ExecutionContext exe_ctx(GetExecutionContextRef());
92061da546Spatrick auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
93061da546Spatrick return children_count <= max ? children_count : max;
94061da546Spatrick } else
95061da546Spatrick return m_parent->GetNumChildren(max);
96061da546Spatrick }
97061da546Spatrick
GetByteSize()98*f6aab3d8Srobert std::optional<uint64_t> ValueObjectDynamicValue::GetByteSize() {
99061da546Spatrick const bool success = UpdateValueIfNeeded(false);
100061da546Spatrick if (success && m_dynamic_type_info.HasType()) {
101061da546Spatrick ExecutionContext exe_ctx(GetExecutionContextRef());
102061da546Spatrick return m_value.GetValueByteSize(nullptr, &exe_ctx);
103061da546Spatrick } else
104061da546Spatrick return m_parent->GetByteSize();
105061da546Spatrick }
106061da546Spatrick
GetValueType() const107061da546Spatrick lldb::ValueType ValueObjectDynamicValue::GetValueType() const {
108061da546Spatrick return m_parent->GetValueType();
109061da546Spatrick }
110061da546Spatrick
UpdateValue()111061da546Spatrick bool ValueObjectDynamicValue::UpdateValue() {
112061da546Spatrick SetValueIsValid(false);
113061da546Spatrick m_error.Clear();
114061da546Spatrick
115061da546Spatrick if (!m_parent->UpdateValueIfNeeded(false)) {
116061da546Spatrick // The dynamic value failed to get an error, pass the error along
117061da546Spatrick if (m_error.Success() && m_parent->GetError().Fail())
118061da546Spatrick m_error = m_parent->GetError();
119061da546Spatrick return false;
120061da546Spatrick }
121061da546Spatrick
122061da546Spatrick // Setting our type_sp to NULL will route everything back through our parent
123061da546Spatrick // which is equivalent to not using dynamic values.
124061da546Spatrick if (m_use_dynamic == lldb::eNoDynamicValues) {
125061da546Spatrick m_dynamic_type_info.Clear();
126061da546Spatrick return true;
127061da546Spatrick }
128061da546Spatrick
129061da546Spatrick ExecutionContext exe_ctx(GetExecutionContextRef());
130061da546Spatrick Target *target = exe_ctx.GetTargetPtr();
131061da546Spatrick if (target) {
132061da546Spatrick m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
133061da546Spatrick m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
134061da546Spatrick }
135061da546Spatrick
136061da546Spatrick // First make sure our Type and/or Address haven't changed:
137061da546Spatrick Process *process = exe_ctx.GetProcessPtr();
138061da546Spatrick if (!process)
139061da546Spatrick return false;
140061da546Spatrick
141061da546Spatrick TypeAndOrName class_type_or_name;
142061da546Spatrick Address dynamic_address;
143061da546Spatrick bool found_dynamic_type = false;
144061da546Spatrick Value::ValueType value_type;
145061da546Spatrick
146061da546Spatrick LanguageRuntime *runtime = nullptr;
147061da546Spatrick
148061da546Spatrick lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
149061da546Spatrick if (known_type != lldb::eLanguageTypeUnknown &&
150061da546Spatrick known_type != lldb::eLanguageTypeC) {
151061da546Spatrick runtime = process->GetLanguageRuntime(known_type);
152061da546Spatrick if (runtime)
153061da546Spatrick found_dynamic_type = runtime->GetDynamicTypeAndAddress(
154061da546Spatrick *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
155061da546Spatrick value_type);
156061da546Spatrick } else {
157061da546Spatrick runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus);
158061da546Spatrick if (runtime)
159061da546Spatrick found_dynamic_type = runtime->GetDynamicTypeAndAddress(
160061da546Spatrick *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
161061da546Spatrick value_type);
162061da546Spatrick
163061da546Spatrick if (!found_dynamic_type) {
164061da546Spatrick runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC);
165061da546Spatrick if (runtime)
166061da546Spatrick found_dynamic_type = runtime->GetDynamicTypeAndAddress(
167061da546Spatrick *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
168061da546Spatrick value_type);
169061da546Spatrick }
170061da546Spatrick }
171061da546Spatrick
172061da546Spatrick // Getting the dynamic value may have run the program a bit, and so marked us
173061da546Spatrick // as needing updating, but we really don't...
174061da546Spatrick
175061da546Spatrick m_update_point.SetUpdated();
176061da546Spatrick
177061da546Spatrick if (runtime && found_dynamic_type) {
178061da546Spatrick if (class_type_or_name.HasType()) {
179061da546Spatrick m_type_impl =
180061da546Spatrick TypeImpl(m_parent->GetCompilerType(),
181061da546Spatrick runtime->FixUpDynamicType(class_type_or_name, *m_parent)
182061da546Spatrick .GetCompilerType());
183061da546Spatrick } else {
184061da546Spatrick m_type_impl.Clear();
185061da546Spatrick }
186061da546Spatrick } else {
187061da546Spatrick m_type_impl.Clear();
188061da546Spatrick }
189061da546Spatrick
190061da546Spatrick // If we don't have a dynamic type, then make ourselves just a echo of our
191061da546Spatrick // parent. Or we could return false, and make ourselves an echo of our
192061da546Spatrick // parent?
193061da546Spatrick if (!found_dynamic_type) {
194061da546Spatrick if (m_dynamic_type_info)
195061da546Spatrick SetValueDidChange(true);
196061da546Spatrick ClearDynamicTypeInformation();
197061da546Spatrick m_dynamic_type_info.Clear();
198061da546Spatrick m_value = m_parent->GetValue();
199061da546Spatrick m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
200061da546Spatrick return m_error.Success();
201061da546Spatrick }
202061da546Spatrick
203061da546Spatrick Value old_value(m_value);
204061da546Spatrick
205*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Types);
206061da546Spatrick
207061da546Spatrick bool has_changed_type = false;
208061da546Spatrick
209061da546Spatrick if (!m_dynamic_type_info) {
210061da546Spatrick m_dynamic_type_info = class_type_or_name;
211061da546Spatrick has_changed_type = true;
212061da546Spatrick } else if (class_type_or_name != m_dynamic_type_info) {
213061da546Spatrick // We are another type, we need to tear down our children...
214061da546Spatrick m_dynamic_type_info = class_type_or_name;
215061da546Spatrick SetValueDidChange(true);
216061da546Spatrick has_changed_type = true;
217061da546Spatrick }
218061da546Spatrick
219061da546Spatrick if (has_changed_type)
220061da546Spatrick ClearDynamicTypeInformation();
221061da546Spatrick
222061da546Spatrick if (!m_address.IsValid() || m_address != dynamic_address) {
223061da546Spatrick if (m_address.IsValid())
224061da546Spatrick SetValueDidChange(true);
225061da546Spatrick
226061da546Spatrick // We've moved, so we should be fine...
227061da546Spatrick m_address = dynamic_address;
228061da546Spatrick lldb::TargetSP target_sp(GetTargetSP());
229061da546Spatrick lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
230061da546Spatrick m_value.GetScalar() = load_address;
231061da546Spatrick }
232061da546Spatrick
233061da546Spatrick if (runtime)
234061da546Spatrick m_dynamic_type_info =
235061da546Spatrick runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
236061da546Spatrick
237061da546Spatrick m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
238061da546Spatrick
239061da546Spatrick m_value.SetValueType(value_type);
240061da546Spatrick
241061da546Spatrick if (has_changed_type && log)
242061da546Spatrick LLDB_LOGF(log, "[%s %p] has a new dynamic type %s", GetName().GetCString(),
243061da546Spatrick static_cast<void *>(this), GetTypeName().GetCString());
244061da546Spatrick
245061da546Spatrick if (m_address.IsValid() && m_dynamic_type_info) {
246061da546Spatrick // The variable value is in the Scalar value inside the m_value. We can
247061da546Spatrick // point our m_data right to it.
248061da546Spatrick m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
249061da546Spatrick if (m_error.Success()) {
250061da546Spatrick if (!CanProvideValue()) {
251061da546Spatrick // this value object represents an aggregate type whose children have
252061da546Spatrick // values, but this object does not. So we say we are changed if our
253061da546Spatrick // location has changed.
254061da546Spatrick SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
255061da546Spatrick m_value.GetScalar() != old_value.GetScalar());
256061da546Spatrick }
257061da546Spatrick
258061da546Spatrick SetValueIsValid(true);
259061da546Spatrick return true;
260061da546Spatrick }
261061da546Spatrick }
262061da546Spatrick
263061da546Spatrick // We get here if we've failed above...
264061da546Spatrick SetValueIsValid(false);
265061da546Spatrick return false;
266061da546Spatrick }
267061da546Spatrick
IsInScope()268061da546Spatrick bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
269061da546Spatrick
SetValueFromCString(const char * value_str,Status & error)270061da546Spatrick bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
271061da546Spatrick Status &error) {
272061da546Spatrick if (!UpdateValueIfNeeded(false)) {
273061da546Spatrick error.SetErrorString("unable to read value");
274061da546Spatrick return false;
275061da546Spatrick }
276061da546Spatrick
277061da546Spatrick uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
278061da546Spatrick uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
279061da546Spatrick
280061da546Spatrick if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
281061da546Spatrick error.SetErrorString("unable to read value");
282061da546Spatrick return false;
283061da546Spatrick }
284061da546Spatrick
285061da546Spatrick // if we are at an offset from our parent, in order to set ourselves
286061da546Spatrick // correctly we would need to change the new value so that it refers to the
287061da546Spatrick // correct dynamic type. we choose not to deal with that - if anything more
288061da546Spatrick // than a value overwrite is required, you should be using the expression
289061da546Spatrick // parser instead of the value editing facility
290061da546Spatrick if (my_value != parent_value) {
291061da546Spatrick // but NULL'ing out a value should always be allowed
292061da546Spatrick if (strcmp(value_str, "0")) {
293061da546Spatrick error.SetErrorString(
294061da546Spatrick "unable to modify dynamic value, use 'expression' command");
295061da546Spatrick return false;
296061da546Spatrick }
297061da546Spatrick }
298061da546Spatrick
299061da546Spatrick bool ret_val = m_parent->SetValueFromCString(value_str, error);
300061da546Spatrick SetNeedsUpdate();
301061da546Spatrick return ret_val;
302061da546Spatrick }
303061da546Spatrick
SetData(DataExtractor & data,Status & error)304061da546Spatrick bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
305061da546Spatrick if (!UpdateValueIfNeeded(false)) {
306061da546Spatrick error.SetErrorString("unable to read value");
307061da546Spatrick return false;
308061da546Spatrick }
309061da546Spatrick
310061da546Spatrick uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
311061da546Spatrick uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
312061da546Spatrick
313061da546Spatrick if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
314061da546Spatrick error.SetErrorString("unable to read value");
315061da546Spatrick return false;
316061da546Spatrick }
317061da546Spatrick
318061da546Spatrick // if we are at an offset from our parent, in order to set ourselves
319061da546Spatrick // correctly we would need to change the new value so that it refers to the
320061da546Spatrick // correct dynamic type. we choose not to deal with that - if anything more
321061da546Spatrick // than a value overwrite is required, you should be using the expression
322061da546Spatrick // parser instead of the value editing facility
323061da546Spatrick if (my_value != parent_value) {
324061da546Spatrick // but NULL'ing out a value should always be allowed
325061da546Spatrick lldb::offset_t offset = 0;
326061da546Spatrick
327dda28197Spatrick if (data.GetAddress(&offset) != 0) {
328061da546Spatrick error.SetErrorString(
329061da546Spatrick "unable to modify dynamic value, use 'expression' command");
330061da546Spatrick return false;
331061da546Spatrick }
332061da546Spatrick }
333061da546Spatrick
334061da546Spatrick bool ret_val = m_parent->SetData(data, error);
335061da546Spatrick SetNeedsUpdate();
336061da546Spatrick return ret_val;
337061da546Spatrick }
338061da546Spatrick
SetPreferredDisplayLanguage(lldb::LanguageType lang)339061da546Spatrick void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
340061da546Spatrick lldb::LanguageType lang) {
341061da546Spatrick this->ValueObject::SetPreferredDisplayLanguage(lang);
342061da546Spatrick if (m_parent)
343061da546Spatrick m_parent->SetPreferredDisplayLanguage(lang);
344061da546Spatrick }
345061da546Spatrick
GetPreferredDisplayLanguage()346061da546Spatrick lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
347061da546Spatrick if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
348061da546Spatrick if (m_parent)
349061da546Spatrick return m_parent->GetPreferredDisplayLanguage();
350061da546Spatrick return lldb::eLanguageTypeUnknown;
351061da546Spatrick } else
352061da546Spatrick return m_preferred_display_language;
353061da546Spatrick }
354061da546Spatrick
IsSyntheticChildrenGenerated()355061da546Spatrick bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
356061da546Spatrick if (m_parent)
357061da546Spatrick return m_parent->IsSyntheticChildrenGenerated();
358061da546Spatrick return false;
359061da546Spatrick }
360061da546Spatrick
SetSyntheticChildrenGenerated(bool b)361061da546Spatrick void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
362061da546Spatrick if (m_parent)
363061da546Spatrick m_parent->SetSyntheticChildrenGenerated(b);
364061da546Spatrick this->ValueObject::SetSyntheticChildrenGenerated(b);
365061da546Spatrick }
366061da546Spatrick
GetDeclaration(Declaration & decl)367061da546Spatrick bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
368061da546Spatrick if (m_parent)
369061da546Spatrick return m_parent->GetDeclaration(decl);
370061da546Spatrick
371061da546Spatrick return ValueObject::GetDeclaration(decl);
372061da546Spatrick }
373061da546Spatrick
GetLanguageFlags()374061da546Spatrick uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
375061da546Spatrick if (m_parent)
376061da546Spatrick return m_parent->GetLanguageFlags();
377061da546Spatrick return this->ValueObject::GetLanguageFlags();
378061da546Spatrick }
379061da546Spatrick
SetLanguageFlags(uint64_t flags)380061da546Spatrick void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
381061da546Spatrick if (m_parent)
382061da546Spatrick m_parent->SetLanguageFlags(flags);
383061da546Spatrick else
384061da546Spatrick this->ValueObject::SetLanguageFlags(flags);
385061da546Spatrick }
386