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         return m_value.GetValueByteSize(nullptr);
131     else
132         return m_parent->GetByteSize();
133 }
134 
135 lldb::ValueType
136 ValueObjectDynamicValue::GetValueType() const
137 {
138     return m_parent->GetValueType();
139 }
140 
141 bool
142 ValueObjectDynamicValue::UpdateValue ()
143 {
144     SetValueIsValid (false);
145     m_error.Clear();
146 
147     if (!m_parent->UpdateValueIfNeeded(false))
148     {
149         // The dynamic value failed to get an error, pass the error along
150         if (m_error.Success() && m_parent->GetError().Fail())
151             m_error = m_parent->GetError();
152         return false;
153     }
154 
155     // Setting our type_sp to NULL will route everything back through our
156     // parent which is equivalent to not using dynamic values.
157     if (m_use_dynamic == lldb::eNoDynamicValues)
158     {
159         m_dynamic_type_info.Clear();
160         return true;
161     }
162 
163     ExecutionContext exe_ctx (GetExecutionContextRef());
164     Target *target = exe_ctx.GetTargetPtr();
165     if (target)
166     {
167         m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
168         m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
169     }
170 
171     // First make sure our Type and/or Address haven't changed:
172     Process *process = exe_ctx.GetProcessPtr();
173     if (!process)
174         return false;
175 
176     TypeAndOrName class_type_or_name;
177     Address dynamic_address;
178     bool found_dynamic_type = false;
179     Value::ValueType value_type;
180 
181     LanguageRuntime *runtime = nullptr;
182 
183     lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
184     if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC)
185     {
186         runtime = process->GetLanguageRuntime (known_type);
187         if (runtime)
188             found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address, value_type);
189     }
190     else
191     {
192         runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus);
193         if (runtime)
194             found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address, value_type);
195 
196         if (!found_dynamic_type)
197         {
198             runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC);
199             if (runtime)
200                 found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address, value_type);
201         }
202     }
203 
204     // Getting the dynamic value may have run the program a bit, and so marked us as needing updating, but we really
205     // don't...
206 
207     m_update_point.SetUpdated();
208 
209     if (runtime && found_dynamic_type)
210     {
211         if (class_type_or_name.HasType())
212         {
213             m_type_impl = TypeImpl(m_parent->GetCompilerType(),
214                                    runtime->FixUpDynamicType(class_type_or_name, *m_parent).GetCompilerType());
215         }
216         else
217         {
218             m_type_impl.Clear();
219         }
220     }
221     else
222     {
223         m_type_impl.Clear();
224     }
225 
226     // If we don't have a dynamic type, then make ourselves just a echo of our parent.
227     // Or we could return false, and make ourselves an echo of our parent?
228     if (!found_dynamic_type)
229     {
230         if (m_dynamic_type_info)
231             SetValueDidChange(true);
232         ClearDynamicTypeInformation();
233         m_dynamic_type_info.Clear();
234         m_value = m_parent->GetValue();
235         m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
236         return m_error.Success();
237     }
238 
239     Value old_value(m_value);
240 
241     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
242 
243     bool has_changed_type = false;
244 
245     if (!m_dynamic_type_info)
246     {
247         m_dynamic_type_info = class_type_or_name;
248         has_changed_type = true;
249     }
250     else if (class_type_or_name != m_dynamic_type_info)
251     {
252         // We are another type, we need to tear down our children...
253         m_dynamic_type_info = class_type_or_name;
254         SetValueDidChange (true);
255         has_changed_type = true;
256     }
257 
258     if (has_changed_type)
259         ClearDynamicTypeInformation ();
260 
261     if (!m_address.IsValid() || m_address != dynamic_address)
262     {
263         if (m_address.IsValid())
264             SetValueDidChange (true);
265 
266         // We've moved, so we should be fine...
267         m_address = dynamic_address;
268         lldb::TargetSP target_sp (GetTargetSP());
269         lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
270         m_value.GetScalar() = load_address;
271     }
272 
273     if (runtime)
274         m_dynamic_type_info = runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
275 
276     //m_value.SetContext (Value::eContextTypeClangType, corrected_type);
277     m_value.SetCompilerType (m_dynamic_type_info.GetCompilerType());
278 
279     m_value.SetValueType(value_type);
280 
281     if (has_changed_type && log)
282         log->Printf("[%s %p] has a new dynamic type %s", GetName().GetCString(),
283                     static_cast<void*>(this), GetTypeName().GetCString());
284 
285     if (m_address.IsValid() && m_dynamic_type_info)
286     {
287         // The variable value is in the Scalar value inside the m_value.
288         // We can point our m_data right to it.
289         m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
290         if (m_error.Success())
291         {
292             if (!CanProvideValue())
293             {
294                 // this value object represents an aggregate type whose
295                 // children have values, but this object does not. So we
296                 // say we are changed if our location has changed.
297                 SetValueDidChange (m_value.GetValueType() != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
298             }
299 
300             SetValueIsValid (true);
301             return true;
302         }
303     }
304 
305     // We get here if we've failed above...
306     SetValueIsValid (false);
307     return false;
308 }
309 
310 
311 
312 bool
313 ValueObjectDynamicValue::IsInScope ()
314 {
315     return m_parent->IsInScope();
316 }
317 
318 bool
319 ValueObjectDynamicValue::SetValueFromCString (const char *value_str, Error& error)
320 {
321     if (!UpdateValueIfNeeded(false))
322     {
323         error.SetErrorString("unable to read value");
324         return false;
325     }
326 
327     uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
328     uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
329 
330     if (my_value == UINT64_MAX || parent_value == UINT64_MAX)
331     {
332         error.SetErrorString("unable to read value");
333         return false;
334     }
335 
336     // if we are at an offset from our parent, in order to set ourselves correctly we would need
337     // to change the new value so that it refers to the correct dynamic type. we choose not to deal
338     // with that - if anything more than a value overwrite is required, you should be using the
339     // expression parser instead of the value editing facility
340     if (my_value != parent_value)
341     {
342         // but NULL'ing out a value should always be allowed
343         if (strcmp(value_str,"0"))
344         {
345             error.SetErrorString("unable to modify dynamic value, use 'expression' command");
346             return false;
347         }
348     }
349 
350     bool ret_val = m_parent->SetValueFromCString(value_str,error);
351     SetNeedsUpdate();
352     return ret_val;
353 }
354 
355 bool
356 ValueObjectDynamicValue::SetData (DataExtractor &data, Error &error)
357 {
358     if (!UpdateValueIfNeeded(false))
359     {
360         error.SetErrorString("unable to read value");
361         return false;
362     }
363 
364     uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
365     uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
366 
367     if (my_value == UINT64_MAX || parent_value == UINT64_MAX)
368     {
369         error.SetErrorString("unable to read value");
370         return false;
371     }
372 
373     // if we are at an offset from our parent, in order to set ourselves correctly we would need
374     // to change the new value so that it refers to the correct dynamic type. we choose not to deal
375     // with that - if anything more than a value overwrite is required, you should be using the
376     // expression parser instead of the value editing facility
377     if (my_value != parent_value)
378     {
379         // but NULL'ing out a value should always be allowed
380         lldb::offset_t offset = 0;
381 
382         if (data.GetPointer(&offset) != 0)
383         {
384             error.SetErrorString("unable to modify dynamic value, use 'expression' command");
385             return false;
386         }
387     }
388 
389     bool ret_val = m_parent->SetData(data, error);
390     SetNeedsUpdate();
391     return ret_val;
392 }
393 
394 bool
395 ValueObjectDynamicValue::GetDeclaration (Declaration &decl)
396 {
397     if (m_parent)
398         return m_parent->GetDeclaration(decl);
399 
400     return ValueObject::GetDeclaration(decl);
401 }
402