xref: /freebsd/contrib/llvm-project/lldb/source/ValueObject/ValueObjectDynamicValue.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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/ValueObject/ValueObjectDynamicValue.h"
10 #include "lldb/Core/Value.h"
11 #include "lldb/Symbol/CompilerType.h"
12 #include "lldb/Symbol/Type.h"
13 #include "lldb/Target/ExecutionContext.h"
14 #include "lldb/Target/LanguageRuntime.h"
15 #include "lldb/Target/Process.h"
16 #include "lldb/Target/Target.h"
17 #include "lldb/Utility/DataExtractor.h"
18 #include "lldb/Utility/LLDBLog.h"
19 #include "lldb/Utility/Log.h"
20 #include "lldb/Utility/Scalar.h"
21 #include "lldb/Utility/Status.h"
22 #include "lldb/ValueObject/ValueObject.h"
23 #include "lldb/lldb-types.h"
24 
25 #include <cstring>
26 #include <optional>
27 namespace lldb_private {
28 class Declaration;
29 }
30 
31 using namespace lldb_private;
32 
ValueObjectDynamicValue(ValueObject & parent,lldb::DynamicValueType use_dynamic)33 ValueObjectDynamicValue::ValueObjectDynamicValue(
34     ValueObject &parent, lldb::DynamicValueType use_dynamic)
35     : ValueObject(parent), m_address(), m_dynamic_type_info(),
36       m_use_dynamic(use_dynamic) {
37   SetName(parent.GetName());
38 }
39 
GetCompilerTypeImpl()40 CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
41   const bool success = UpdateValueIfNeeded(false);
42   if (success) {
43     if (m_dynamic_type_info.HasType())
44       return m_value.GetCompilerType();
45     else
46       return m_parent->GetCompilerType();
47   }
48   return m_parent->GetCompilerType();
49 }
50 
GetTypeName()51 ConstString ValueObjectDynamicValue::GetTypeName() {
52   const bool success = UpdateValueIfNeeded(false);
53   if (success) {
54     if (m_dynamic_type_info.HasName())
55       return m_dynamic_type_info.GetName();
56   }
57   return m_parent->GetTypeName();
58 }
59 
GetTypeImpl()60 TypeImpl ValueObjectDynamicValue::GetTypeImpl() {
61   const bool success = UpdateValueIfNeeded(false);
62   if (success && m_type_impl.IsValid()) {
63     return m_type_impl;
64   }
65   return m_parent->GetTypeImpl();
66 }
67 
GetQualifiedTypeName()68 ConstString ValueObjectDynamicValue::GetQualifiedTypeName() {
69   const bool success = UpdateValueIfNeeded(false);
70   if (success) {
71     if (m_dynamic_type_info.HasName())
72       return m_dynamic_type_info.GetName();
73   }
74   return m_parent->GetQualifiedTypeName();
75 }
76 
GetDisplayTypeName()77 ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
78   const bool success = UpdateValueIfNeeded(false);
79   if (success) {
80     if (m_dynamic_type_info.HasType())
81       return GetCompilerType().GetDisplayTypeName();
82     if (m_dynamic_type_info.HasName())
83       return m_dynamic_type_info.GetName();
84   }
85   return m_parent->GetDisplayTypeName();
86 }
87 
88 llvm::Expected<uint32_t>
CalculateNumChildren(uint32_t max)89 ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
90   const bool success = UpdateValueIfNeeded(false);
91   if (success && m_dynamic_type_info.HasType()) {
92     ExecutionContext exe_ctx(GetExecutionContextRef());
93     auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
94     if (!children_count)
95       return children_count;
96     return *children_count <= max ? *children_count : max;
97   } else
98     return m_parent->GetNumChildren(max);
99 }
100 
GetByteSize()101 llvm::Expected<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);
106   } else
107     return m_parent->GetByteSize();
108 }
109 
GetValueType() const110 lldb::ValueType ValueObjectDynamicValue::GetValueType() const {
111   return m_parent->GetValueType();
112 }
113 
UpdateValue()114 bool ValueObjectDynamicValue::UpdateValue() {
115   SetValueIsValid(false);
116   m_error.Clear();
117 
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().Clone();
122     return false;
123   }
124 
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();
129     return true;
130   }
131 
132   ExecutionContext exe_ctx(GetExecutionContextRef());
133   Target *target = exe_ctx.GetTargetPtr();
134   if (target) {
135     m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
136     m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
137   }
138 
139   // First make sure our Type and/or Address haven't changed:
140   Process *process = exe_ctx.GetProcessPtr();
141   if (!process)
142     return false;
143 
144   TypeAndOrName class_type_or_name;
145   Address dynamic_address;
146   bool found_dynamic_type = false;
147   Value::ValueType value_type;
148   llvm::ArrayRef<uint8_t> local_buffer;
149 
150   LanguageRuntime *runtime = nullptr;
151 
152   lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
153   if (known_type != lldb::eLanguageTypeUnknown &&
154       known_type != lldb::eLanguageTypeC) {
155     runtime = process->GetLanguageRuntime(known_type);
156     if (auto *preferred_runtime =
157             runtime->GetPreferredLanguageRuntime(*m_parent)) {
158       // Try the preferred runtime first.
159       found_dynamic_type = preferred_runtime->GetDynamicTypeAndAddress(
160           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
161           value_type, local_buffer);
162       if (found_dynamic_type)
163         // Set the operative `runtime` for later use in this function.
164         runtime = preferred_runtime;
165     }
166     if (!found_dynamic_type)
167       // Fallback to the runtime for `known_type`.
168       found_dynamic_type = runtime->GetDynamicTypeAndAddress(
169           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
170           value_type, local_buffer);
171   } else {
172     runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus);
173     if (runtime)
174       found_dynamic_type = runtime->GetDynamicTypeAndAddress(
175           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
176           value_type, local_buffer);
177 
178     if (!found_dynamic_type) {
179       runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC);
180       if (runtime)
181         found_dynamic_type = runtime->GetDynamicTypeAndAddress(
182             *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
183             value_type, local_buffer);
184     }
185   }
186 
187   // Getting the dynamic value may have run the program a bit, and so marked us
188   // as needing updating, but we really don't...
189 
190   m_update_point.SetUpdated();
191 
192   if (runtime && found_dynamic_type) {
193     if (class_type_or_name.HasType()) {
194       m_type_impl =
195           TypeImpl(m_parent->GetCompilerType(),
196                    runtime->FixUpDynamicType(class_type_or_name, *m_parent)
197                        .GetCompilerType());
198     } else {
199       m_type_impl.Clear();
200     }
201   } else {
202     m_type_impl.Clear();
203   }
204 
205   // If we don't have a dynamic type, set ourselves to be invalid and return
206   // false.  We used to try to produce a dynamic ValueObject that behaved "like"
207   // its parent, but that failed for ValueObjectConstResult, which is too
208   // complex a beast to try to emulate.  If we return an invalid ValueObject,
209   // clients will end up getting the static value instead, which behaves
210   // correctly.
211   if (!found_dynamic_type) {
212     if (m_dynamic_type_info)
213       SetValueDidChange(true);
214     ClearDynamicTypeInformation();
215     m_dynamic_type_info.Clear();
216     m_error = Status::FromErrorString("no dynamic type found");
217     return false;
218   }
219 
220   Value old_value(m_value);
221 
222   Log *log = GetLog(LLDBLog::Types);
223 
224   bool has_changed_type = false;
225 
226   if (!m_dynamic_type_info) {
227     m_dynamic_type_info = class_type_or_name;
228     has_changed_type = true;
229   } else if (class_type_or_name != m_dynamic_type_info) {
230     // We are another type, we need to tear down our children...
231     m_dynamic_type_info = class_type_or_name;
232     SetValueDidChange(true);
233     has_changed_type = true;
234   }
235 
236   if (has_changed_type)
237     ClearDynamicTypeInformation();
238 
239   if (!m_address.IsValid() || m_address != dynamic_address) {
240     if (m_address.IsValid())
241       SetValueDidChange(true);
242 
243     // If we found a host address, and the dynamic type fits in the local buffer
244     // that was found, point to that buffer. Later on this function will copy
245     // the buffer over.
246     if (value_type == Value::ValueType::HostAddress && !local_buffer.empty()) {
247       auto *exe_scope = exe_ctx.GetBestExecutionContextScope();
248       // If we found a host address but it doesn't fit in the buffer, there's
249       // nothing we can do.
250       if (local_buffer.size() <
251           llvm::expectedToOptional(
252               m_dynamic_type_info.GetCompilerType().GetByteSize(exe_scope))) {
253         SetValueIsValid(false);
254         return false;
255       }
256 
257       m_value.GetScalar() = (uint64_t)local_buffer.data();
258       m_address = LLDB_INVALID_ADDRESS;
259     } else {
260       // Otherwise we have a legitimate address on the target. Point to the load
261       // address.
262       m_address = dynamic_address;
263       lldb::TargetSP target_sp(GetTargetSP());
264       lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
265       m_value.GetScalar() = load_address;
266     }
267   }
268 
269   if (runtime)
270     m_dynamic_type_info =
271         runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
272 
273   m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
274 
275   m_value.SetValueType(value_type);
276 
277   if (has_changed_type && log)
278     LLDB_LOGF(log, "[%s %p] has a new dynamic type %s", GetName().GetCString(),
279               static_cast<void *>(this), GetTypeName().GetCString());
280 
281   // m_address could be invalid but we could still have a local buffer
282   // containing the dynamic value.
283   if ((m_address.IsValid() ||
284        m_value.GetValueType() == Value::ValueType::HostAddress) &&
285       m_dynamic_type_info) {
286     // The variable value is in the Scalar value inside the m_value. We can
287     // point our m_data right to it.
288     m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
289     if (m_error.Success()) {
290       if (!CanProvideValue()) {
291         // this value object represents an aggregate type whose children have
292         // values, but this object does not. So we say we are changed if our
293         // location has changed.
294         SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
295                           m_value.GetScalar() != old_value.GetScalar());
296       }
297 
298       SetValueIsValid(true);
299       return true;
300     }
301   }
302 
303   // We get here if we've failed above...
304   SetValueIsValid(false);
305   return false;
306 }
307 
IsInScope()308 bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
309 
SetValueFromCString(const char * value_str,Status & error)310 bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
311                                                   Status &error) {
312   if (!UpdateValueIfNeeded(false)) {
313     error = Status::FromErrorString("unable to read value");
314     return false;
315   }
316 
317   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
318   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
319 
320   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
321     error = Status::FromErrorString("unable to read value");
322     return false;
323   }
324 
325   // if we are at an offset from our parent, in order to set ourselves
326   // correctly we would need to change the new value so that it refers to the
327   // correct dynamic type. we choose not to deal with that - if anything more
328   // than a value overwrite is required, you should be using the expression
329   // parser instead of the value editing facility
330   if (my_value != parent_value) {
331     // but NULL'ing out a value should always be allowed
332     if (strcmp(value_str, "0")) {
333       error = Status::FromErrorString(
334           "unable to modify dynamic value, use 'expression' command");
335       return false;
336     }
337   }
338 
339   bool ret_val = m_parent->SetValueFromCString(value_str, error);
340   SetNeedsUpdate();
341   return ret_val;
342 }
343 
SetData(DataExtractor & data,Status & error)344 bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
345   if (!UpdateValueIfNeeded(false)) {
346     error = Status::FromErrorString("unable to read value");
347     return false;
348   }
349 
350   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
351   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
352 
353   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
354     error = Status::FromErrorString("unable to read value");
355     return false;
356   }
357 
358   // if we are at an offset from our parent, in order to set ourselves
359   // correctly we would need to change the new value so that it refers to the
360   // correct dynamic type. we choose not to deal with that - if anything more
361   // than a value overwrite is required, you should be using the expression
362   // parser instead of the value editing facility
363   if (my_value != parent_value) {
364     // but NULL'ing out a value should always be allowed
365     lldb::offset_t offset = 0;
366 
367     if (data.GetAddress(&offset) != 0) {
368       error = Status::FromErrorString(
369           "unable to modify dynamic value, use 'expression' command");
370       return false;
371     }
372   }
373 
374   bool ret_val = m_parent->SetData(data, error);
375   SetNeedsUpdate();
376   return ret_val;
377 }
378 
SetPreferredDisplayLanguage(lldb::LanguageType lang)379 void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
380     lldb::LanguageType lang) {
381   this->ValueObject::SetPreferredDisplayLanguage(lang);
382   if (m_parent)
383     m_parent->SetPreferredDisplayLanguage(lang);
384 }
385 
GetPreferredDisplayLanguage()386 lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
387   if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
388     if (m_parent)
389       return m_parent->GetPreferredDisplayLanguage();
390     return lldb::eLanguageTypeUnknown;
391   } else
392     return m_preferred_display_language;
393 }
394 
IsSyntheticChildrenGenerated()395 bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
396   if (m_parent)
397     return m_parent->IsSyntheticChildrenGenerated();
398   return false;
399 }
400 
SetSyntheticChildrenGenerated(bool b)401 void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
402   if (m_parent)
403     m_parent->SetSyntheticChildrenGenerated(b);
404   this->ValueObject::SetSyntheticChildrenGenerated(b);
405 }
406 
GetDeclaration(Declaration & decl)407 bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
408   if (m_parent)
409     return m_parent->GetDeclaration(decl);
410 
411   return ValueObject::GetDeclaration(decl);
412 }
413 
GetLanguageFlags()414 uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
415   if (m_parent)
416     return m_parent->GetLanguageFlags();
417   return this->ValueObject::GetLanguageFlags();
418 }
419 
SetLanguageFlags(uint64_t flags)420 void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
421   if (m_parent)
422     m_parent->SetLanguageFlags(flags);
423   else
424     this->ValueObject::SetLanguageFlags(flags);
425 }
426