• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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"
24 
25 #include <string.h>
26 namespace lldb_private {
27 class Declaration;
28 }
29 
30 using namespace lldb_private;
31 
ValueObjectDynamicValue(ValueObject & parent,lldb::DynamicValueType use_dynamic)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 
~ValueObjectDynamicValue()39 ValueObjectDynamicValue::~ValueObjectDynamicValue() {
40   m_owning_valobj_sp.reset();
41 }
42 
GetCompilerTypeImpl()43 CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
44   const bool success = UpdateValueIfNeeded(false);
45   if (success) {
46     if (m_dynamic_type_info.HasType())
47       return m_value.GetCompilerType();
48     else
49       return m_parent->GetCompilerType();
50   }
51   return m_parent->GetCompilerType();
52 }
53 
GetTypeName()54 ConstString ValueObjectDynamicValue::GetTypeName() {
55   const bool success = UpdateValueIfNeeded(false);
56   if (success) {
57     if (m_dynamic_type_info.HasName())
58       return m_dynamic_type_info.GetName();
59   }
60   return m_parent->GetTypeName();
61 }
62 
GetTypeImpl()63 TypeImpl ValueObjectDynamicValue::GetTypeImpl() {
64   const bool success = UpdateValueIfNeeded(false);
65   if (success && m_type_impl.IsValid()) {
66     return m_type_impl;
67   }
68   return m_parent->GetTypeImpl();
69 }
70 
GetQualifiedTypeName()71 ConstString ValueObjectDynamicValue::GetQualifiedTypeName() {
72   const bool success = UpdateValueIfNeeded(false);
73   if (success) {
74     if (m_dynamic_type_info.HasName())
75       return m_dynamic_type_info.GetName();
76   }
77   return m_parent->GetQualifiedTypeName();
78 }
79 
GetDisplayTypeName()80 ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
81   const bool success = UpdateValueIfNeeded(false);
82   if (success) {
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();
87   }
88   return m_parent->GetDisplayTypeName();
89 }
90 
CalculateNumChildren(uint32_t max)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;
97   } else
98     return m_parent->GetNumChildren(max);
99 }
100 
GetByteSize()101 llvm::Optional<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();
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 
149   LanguageRuntime *runtime = nullptr;
150 
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);
155     if (runtime)
156       found_dynamic_type = runtime->GetDynamicTypeAndAddress(
157           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
158           value_type);
159   } else {
160     runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus);
161     if (runtime)
162       found_dynamic_type = runtime->GetDynamicTypeAndAddress(
163           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
164           value_type);
165 
166     if (!found_dynamic_type) {
167       runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC);
168       if (runtime)
169         found_dynamic_type = runtime->GetDynamicTypeAndAddress(
170             *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
171             value_type);
172     }
173   }
174 
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...
177 
178   m_update_point.SetUpdated();
179 
180   if (runtime && found_dynamic_type) {
181     if (class_type_or_name.HasType()) {
182       m_type_impl =
183           TypeImpl(m_parent->GetCompilerType(),
184                    runtime->FixUpDynamicType(class_type_or_name, *m_parent)
185                        .GetCompilerType());
186     } else {
187       m_type_impl.Clear();
188     }
189   } else {
190     m_type_impl.Clear();
191   }
192 
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
195   // parent?
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();
204   }
205 
206   Value old_value(m_value);
207 
208   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
209 
210   bool has_changed_type = false;
211 
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;
220   }
221 
222   if (has_changed_type)
223     ClearDynamicTypeInformation();
224 
225   if (!m_address.IsValid() || m_address != dynamic_address) {
226     if (m_address.IsValid())
227       SetValueDidChange(true);
228 
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;
234   }
235 
236   if (runtime)
237     m_dynamic_type_info =
238         runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
239 
240   m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
241 
242   m_value.SetValueType(value_type);
243 
244   if (has_changed_type && log)
245     LLDB_LOGF(log, "[%s %p] has a new dynamic type %s", GetName().GetCString(),
246               static_cast<void *>(this), GetTypeName().GetCString());
247 
248   if (m_address.IsValid() && m_dynamic_type_info) {
249     // The variable value is in the Scalar value inside the m_value. We can
250     // point our m_data right to it.
251     m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
252     if (m_error.Success()) {
253       if (!CanProvideValue()) {
254         // this value object represents an aggregate type whose children have
255         // values, but this object does not. So we say we are changed if our
256         // location has changed.
257         SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
258                           m_value.GetScalar() != old_value.GetScalar());
259       }
260 
261       SetValueIsValid(true);
262       return true;
263     }
264   }
265 
266   // We get here if we've failed above...
267   SetValueIsValid(false);
268   return false;
269 }
270 
IsInScope()271 bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
272 
SetValueFromCString(const char * value_str,Status & error)273 bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
274                                                   Status &error) {
275   if (!UpdateValueIfNeeded(false)) {
276     error.SetErrorString("unable to read value");
277     return false;
278   }
279 
280   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
281   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
282 
283   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
284     error.SetErrorString("unable to read value");
285     return false;
286   }
287 
288   // if we are at an offset from our parent, in order to set ourselves
289   // correctly we would need to change the new value so that it refers to the
290   // correct dynamic type. we choose not to deal with that - if anything more
291   // than a value overwrite is required, you should be using the expression
292   // parser instead of the value editing facility
293   if (my_value != parent_value) {
294     // but NULL'ing out a value should always be allowed
295     if (strcmp(value_str, "0")) {
296       error.SetErrorString(
297           "unable to modify dynamic value, use 'expression' command");
298       return false;
299     }
300   }
301 
302   bool ret_val = m_parent->SetValueFromCString(value_str, error);
303   SetNeedsUpdate();
304   return ret_val;
305 }
306 
SetData(DataExtractor & data,Status & error)307 bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
308   if (!UpdateValueIfNeeded(false)) {
309     error.SetErrorString("unable to read value");
310     return false;
311   }
312 
313   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
314   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
315 
316   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
317     error.SetErrorString("unable to read value");
318     return false;
319   }
320 
321   // if we are at an offset from our parent, in order to set ourselves
322   // correctly we would need to change the new value so that it refers to the
323   // correct dynamic type. we choose not to deal with that - if anything more
324   // than a value overwrite is required, you should be using the expression
325   // parser instead of the value editing facility
326   if (my_value != parent_value) {
327     // but NULL'ing out a value should always be allowed
328     lldb::offset_t offset = 0;
329 
330     if (data.GetAddress(&offset) != 0) {
331       error.SetErrorString(
332           "unable to modify dynamic value, use 'expression' command");
333       return false;
334     }
335   }
336 
337   bool ret_val = m_parent->SetData(data, error);
338   SetNeedsUpdate();
339   return ret_val;
340 }
341 
SetPreferredDisplayLanguage(lldb::LanguageType lang)342 void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
343     lldb::LanguageType lang) {
344   this->ValueObject::SetPreferredDisplayLanguage(lang);
345   if (m_parent)
346     m_parent->SetPreferredDisplayLanguage(lang);
347 }
348 
GetPreferredDisplayLanguage()349 lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
350   if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
351     if (m_parent)
352       return m_parent->GetPreferredDisplayLanguage();
353     return lldb::eLanguageTypeUnknown;
354   } else
355     return m_preferred_display_language;
356 }
357 
IsSyntheticChildrenGenerated()358 bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
359   if (m_parent)
360     return m_parent->IsSyntheticChildrenGenerated();
361   return false;
362 }
363 
SetSyntheticChildrenGenerated(bool b)364 void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
365   if (m_parent)
366     m_parent->SetSyntheticChildrenGenerated(b);
367   this->ValueObject::SetSyntheticChildrenGenerated(b);
368 }
369 
GetDeclaration(Declaration & decl)370 bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
371   if (m_parent)
372     return m_parent->GetDeclaration(decl);
373 
374   return ValueObject::GetDeclaration(decl);
375 }
376 
GetLanguageFlags()377 uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
378   if (m_parent)
379     return m_parent->GetLanguageFlags();
380   return this->ValueObject::GetLanguageFlags();
381 }
382 
SetLanguageFlags(uint64_t flags)383 void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
384   if (m_parent)
385     m_parent->SetLanguageFlags(flags);
386   else
387     this->ValueObject::SetLanguageFlags(flags);
388 }
389