xref: /freebsd-src/contrib/llvm-project/lldb/source/Core/ValueObjectDynamicValue.cpp (revision ab80f0b21fbb9c44d40e6f7a99090188f4ed2f71)
1 //===-- ValueObjectDynamicValue.cpp ---------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
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/LLDBLog.h"
20 #include "lldb/Utility/Log.h"
21 #include "lldb/Utility/Scalar.h"
22 #include "lldb/Utility/Status.h"
23 #include "lldb/lldb-types.h"
24 
25 #include <cstring>
26 namespace lldb_private {
27 class Declaration;
28 }
29 
30 using namespace lldb_private;
31 
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());
37 }
38 
39 CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
40   const bool success = UpdateValueIfNeeded(false);
41   if (success) {
42     if (m_dynamic_type_info.HasType())
43       return m_value.GetCompilerType();
44     else
45       return m_parent->GetCompilerType();
46   }
47   return m_parent->GetCompilerType();
48 }
49 
50 ConstString ValueObjectDynamicValue::GetTypeName() {
51   const bool success = UpdateValueIfNeeded(false);
52   if (success) {
53     if (m_dynamic_type_info.HasName())
54       return m_dynamic_type_info.GetName();
55   }
56   return m_parent->GetTypeName();
57 }
58 
59 TypeImpl ValueObjectDynamicValue::GetTypeImpl() {
60   const bool success = UpdateValueIfNeeded(false);
61   if (success && m_type_impl.IsValid()) {
62     return m_type_impl;
63   }
64   return m_parent->GetTypeImpl();
65 }
66 
67 ConstString ValueObjectDynamicValue::GetQualifiedTypeName() {
68   const bool success = UpdateValueIfNeeded(false);
69   if (success) {
70     if (m_dynamic_type_info.HasName())
71       return m_dynamic_type_info.GetName();
72   }
73   return m_parent->GetQualifiedTypeName();
74 }
75 
76 ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
77   const bool success = UpdateValueIfNeeded(false);
78   if (success) {
79     if (m_dynamic_type_info.HasType())
80       return GetCompilerType().GetDisplayTypeName();
81     if (m_dynamic_type_info.HasName())
82       return m_dynamic_type_info.GetName();
83   }
84   return m_parent->GetDisplayTypeName();
85 }
86 
87 size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
88   const bool success = UpdateValueIfNeeded(false);
89   if (success && m_dynamic_type_info.HasType()) {
90     ExecutionContext exe_ctx(GetExecutionContextRef());
91     auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
92     return children_count <= max ? children_count : max;
93   } else
94     return m_parent->GetNumChildren(max);
95 }
96 
97 llvm::Optional<uint64_t> ValueObjectDynamicValue::GetByteSize() {
98   const bool success = UpdateValueIfNeeded(false);
99   if (success && m_dynamic_type_info.HasType()) {
100     ExecutionContext exe_ctx(GetExecutionContextRef());
101     return m_value.GetValueByteSize(nullptr, &exe_ctx);
102   } else
103     return m_parent->GetByteSize();
104 }
105 
106 lldb::ValueType ValueObjectDynamicValue::GetValueType() const {
107   return m_parent->GetValueType();
108 }
109 
110 bool ValueObjectDynamicValue::UpdateValue() {
111   SetValueIsValid(false);
112   m_error.Clear();
113 
114   if (!m_parent->UpdateValueIfNeeded(false)) {
115     // The dynamic value failed to get an error, pass the error along
116     if (m_error.Success() && m_parent->GetError().Fail())
117       m_error = m_parent->GetError();
118     return false;
119   }
120 
121   // Setting our type_sp to NULL will route everything back through our parent
122   // which is equivalent to not using dynamic values.
123   if (m_use_dynamic == lldb::eNoDynamicValues) {
124     m_dynamic_type_info.Clear();
125     return true;
126   }
127 
128   ExecutionContext exe_ctx(GetExecutionContextRef());
129   Target *target = exe_ctx.GetTargetPtr();
130   if (target) {
131     m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
132     m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
133   }
134 
135   // First make sure our Type and/or Address haven't changed:
136   Process *process = exe_ctx.GetProcessPtr();
137   if (!process)
138     return false;
139 
140   TypeAndOrName class_type_or_name;
141   Address dynamic_address;
142   bool found_dynamic_type = false;
143   Value::ValueType value_type;
144 
145   LanguageRuntime *runtime = nullptr;
146 
147   lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
148   if (known_type != lldb::eLanguageTypeUnknown &&
149       known_type != lldb::eLanguageTypeC) {
150     runtime = process->GetLanguageRuntime(known_type);
151     if (runtime)
152       found_dynamic_type = runtime->GetDynamicTypeAndAddress(
153           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
154           value_type);
155   } else {
156     runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus);
157     if (runtime)
158       found_dynamic_type = runtime->GetDynamicTypeAndAddress(
159           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
160           value_type);
161 
162     if (!found_dynamic_type) {
163       runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC);
164       if (runtime)
165         found_dynamic_type = runtime->GetDynamicTypeAndAddress(
166             *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
167             value_type);
168     }
169   }
170 
171   // Getting the dynamic value may have run the program a bit, and so marked us
172   // as needing updating, but we really don't...
173 
174   m_update_point.SetUpdated();
175 
176   if (runtime && found_dynamic_type) {
177     if (class_type_or_name.HasType()) {
178       m_type_impl =
179           TypeImpl(m_parent->GetCompilerType(),
180                    runtime->FixUpDynamicType(class_type_or_name, *m_parent)
181                        .GetCompilerType());
182     } else {
183       m_type_impl.Clear();
184     }
185   } else {
186     m_type_impl.Clear();
187   }
188 
189   // If we don't have a dynamic type, then make ourselves just a echo of our
190   // parent. Or we could return false, and make ourselves an echo of our
191   // parent?
192   if (!found_dynamic_type) {
193     if (m_dynamic_type_info)
194       SetValueDidChange(true);
195     ClearDynamicTypeInformation();
196     m_dynamic_type_info.Clear();
197     m_value = m_parent->GetValue();
198     m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
199     return m_error.Success();
200   }
201 
202   Value old_value(m_value);
203 
204   Log *log = GetLog(LLDBLog::Types);
205 
206   bool has_changed_type = false;
207 
208   if (!m_dynamic_type_info) {
209     m_dynamic_type_info = class_type_or_name;
210     has_changed_type = true;
211   } else if (class_type_or_name != m_dynamic_type_info) {
212     // We are another type, we need to tear down our children...
213     m_dynamic_type_info = class_type_or_name;
214     SetValueDidChange(true);
215     has_changed_type = true;
216   }
217 
218   if (has_changed_type)
219     ClearDynamicTypeInformation();
220 
221   if (!m_address.IsValid() || m_address != dynamic_address) {
222     if (m_address.IsValid())
223       SetValueDidChange(true);
224 
225     // We've moved, so we should be fine...
226     m_address = dynamic_address;
227     lldb::TargetSP target_sp(GetTargetSP());
228     lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
229     m_value.GetScalar() = load_address;
230   }
231 
232   if (runtime)
233     m_dynamic_type_info =
234         runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
235 
236   m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
237 
238   m_value.SetValueType(value_type);
239 
240   if (has_changed_type && log)
241     LLDB_LOGF(log, "[%s %p] has a new dynamic type %s", GetName().GetCString(),
242               static_cast<void *>(this), GetTypeName().GetCString());
243 
244   if (m_address.IsValid() && m_dynamic_type_info) {
245     // The variable value is in the Scalar value inside the m_value. We can
246     // point our m_data right to it.
247     m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
248     if (m_error.Success()) {
249       if (!CanProvideValue()) {
250         // this value object represents an aggregate type whose children have
251         // values, but this object does not. So we say we are changed if our
252         // location has changed.
253         SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
254                           m_value.GetScalar() != old_value.GetScalar());
255       }
256 
257       SetValueIsValid(true);
258       return true;
259     }
260   }
261 
262   // We get here if we've failed above...
263   SetValueIsValid(false);
264   return false;
265 }
266 
267 bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
268 
269 bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
270                                                   Status &error) {
271   if (!UpdateValueIfNeeded(false)) {
272     error.SetErrorString("unable to read value");
273     return false;
274   }
275 
276   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
277   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
278 
279   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
280     error.SetErrorString("unable to read value");
281     return false;
282   }
283 
284   // if we are at an offset from our parent, in order to set ourselves
285   // correctly we would need to change the new value so that it refers to the
286   // correct dynamic type. we choose not to deal with that - if anything more
287   // than a value overwrite is required, you should be using the expression
288   // parser instead of the value editing facility
289   if (my_value != parent_value) {
290     // but NULL'ing out a value should always be allowed
291     if (strcmp(value_str, "0")) {
292       error.SetErrorString(
293           "unable to modify dynamic value, use 'expression' command");
294       return false;
295     }
296   }
297 
298   bool ret_val = m_parent->SetValueFromCString(value_str, error);
299   SetNeedsUpdate();
300   return ret_val;
301 }
302 
303 bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
304   if (!UpdateValueIfNeeded(false)) {
305     error.SetErrorString("unable to read value");
306     return false;
307   }
308 
309   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
310   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
311 
312   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
313     error.SetErrorString("unable to read value");
314     return false;
315   }
316 
317   // if we are at an offset from our parent, in order to set ourselves
318   // correctly we would need to change the new value so that it refers to the
319   // correct dynamic type. we choose not to deal with that - if anything more
320   // than a value overwrite is required, you should be using the expression
321   // parser instead of the value editing facility
322   if (my_value != parent_value) {
323     // but NULL'ing out a value should always be allowed
324     lldb::offset_t offset = 0;
325 
326     if (data.GetAddress(&offset) != 0) {
327       error.SetErrorString(
328           "unable to modify dynamic value, use 'expression' command");
329       return false;
330     }
331   }
332 
333   bool ret_val = m_parent->SetData(data, error);
334   SetNeedsUpdate();
335   return ret_val;
336 }
337 
338 void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
339     lldb::LanguageType lang) {
340   this->ValueObject::SetPreferredDisplayLanguage(lang);
341   if (m_parent)
342     m_parent->SetPreferredDisplayLanguage(lang);
343 }
344 
345 lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
346   if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
347     if (m_parent)
348       return m_parent->GetPreferredDisplayLanguage();
349     return lldb::eLanguageTypeUnknown;
350   } else
351     return m_preferred_display_language;
352 }
353 
354 bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
355   if (m_parent)
356     return m_parent->IsSyntheticChildrenGenerated();
357   return false;
358 }
359 
360 void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
361   if (m_parent)
362     m_parent->SetSyntheticChildrenGenerated(b);
363   this->ValueObject::SetSyntheticChildrenGenerated(b);
364 }
365 
366 bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
367   if (m_parent)
368     return m_parent->GetDeclaration(decl);
369 
370   return ValueObject::GetDeclaration(decl);
371 }
372 
373 uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
374   if (m_parent)
375     return m_parent->GetLanguageFlags();
376   return this->ValueObject::GetLanguageFlags();
377 }
378 
379 void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
380   if (m_parent)
381     m_parent->SetLanguageFlags(flags);
382   else
383     this->ValueObject::SetLanguageFlags(flags);
384 }
385