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