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