ValueObjectDynamicValue.cpp revision 276479
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/ClangASTType.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
36using namespace lldb_private;
37
38ValueObjectDynamicValue::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
47ValueObjectDynamicValue::~ValueObjectDynamicValue()
48{
49    m_owning_valobj_sp.reset();
50}
51
52ClangASTType
53ValueObjectDynamicValue::GetClangTypeImpl ()
54{
55    const bool success = UpdateValueIfNeeded(false);
56    if (success)
57    {
58        if (m_dynamic_type_info.HasType())
59            return m_value.GetClangType();
60        else
61            return m_parent->GetClangType();
62    }
63    return m_parent->GetClangType();
64}
65
66ConstString
67ValueObjectDynamicValue::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
78TypeImpl
79ValueObjectDynamicValue::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
89ConstString
90ValueObjectDynamicValue::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
101ConstString
102ValueObjectDynamicValue::GetDisplayTypeName()
103{
104    const bool success = UpdateValueIfNeeded(false);
105    if (success)
106    {
107        if (m_dynamic_type_info.HasType())
108            return GetClangType().GetDisplayTypeName();
109        if (m_dynamic_type_info.HasName())
110            return m_dynamic_type_info.GetName();
111    }
112    return m_parent->GetDisplayTypeName();
113}
114
115size_t
116ValueObjectDynamicValue::CalculateNumChildren()
117{
118    const bool success = UpdateValueIfNeeded(false);
119    if (success && m_dynamic_type_info.HasType())
120        return GetClangType().GetNumChildren (true);
121    else
122        return m_parent->GetNumChildren();
123}
124
125uint64_t
126ValueObjectDynamicValue::GetByteSize()
127{
128    const bool success = UpdateValueIfNeeded(false);
129    if (success && m_dynamic_type_info.HasType())
130        return m_value.GetValueByteSize(NULL);
131    else
132        return m_parent->GetByteSize();
133}
134
135lldb::ValueType
136ValueObjectDynamicValue::GetValueType() const
137{
138    return m_parent->GetValueType();
139}
140
141
142static TypeAndOrName
143FixupTypeAndOrName (const TypeAndOrName& type_andor_name,
144                    ValueObject& parent)
145{
146    TypeAndOrName ret(type_andor_name);
147    if (type_andor_name.HasType())
148    {
149        // The type will always be the type of the dynamic object.  If our parent's type was a pointer,
150        // then our type should be a pointer to the type of the dynamic object.  If a reference, then the original type
151        // should be okay...
152        ClangASTType orig_type = type_andor_name.GetClangASTType();
153        ClangASTType corrected_type = orig_type;
154        if (parent.IsPointerType())
155            corrected_type = orig_type.GetPointerType ();
156        else if (parent.IsPointerOrReferenceType())
157            corrected_type = orig_type.GetLValueReferenceType ();
158        ret.SetClangASTType(corrected_type);
159    }
160    else /*if (m_dynamic_type_info.HasName())*/
161    {
162        // If we are here we need to adjust our dynamic type name to include the correct & or * symbol
163        std::string corrected_name (type_andor_name.GetName().GetCString());
164        if (parent.IsPointerType())
165            corrected_name.append(" *");
166        else if (parent.IsPointerOrReferenceType())
167            corrected_name.append(" &");
168        // the parent type should be a correctly pointer'ed or referenc'ed type
169        ret.SetClangASTType(parent.GetClangType());
170        ret.SetName(corrected_name.c_str());
171    }
172    return ret;
173}
174
175bool
176ValueObjectDynamicValue::UpdateValue ()
177{
178    SetValueIsValid (false);
179    m_error.Clear();
180
181    if (!m_parent->UpdateValueIfNeeded(false))
182    {
183        // The dynamic value failed to get an error, pass the error along
184        if (m_error.Success() && m_parent->GetError().Fail())
185            m_error = m_parent->GetError();
186        return false;
187    }
188
189    // Setting our type_sp to NULL will route everything back through our
190    // parent which is equivalent to not using dynamic values.
191    if (m_use_dynamic == lldb::eNoDynamicValues)
192    {
193        m_dynamic_type_info.Clear();
194        return true;
195    }
196
197    ExecutionContext exe_ctx (GetExecutionContextRef());
198    Target *target = exe_ctx.GetTargetPtr();
199    if (target)
200    {
201        m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
202        m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
203    }
204
205    // First make sure our Type and/or Address haven't changed:
206    Process *process = exe_ctx.GetProcessPtr();
207    if (!process)
208        return false;
209
210    TypeAndOrName class_type_or_name;
211    Address dynamic_address;
212    bool found_dynamic_type = false;
213
214    lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
215    if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC)
216    {
217        LanguageRuntime *runtime = process->GetLanguageRuntime (known_type);
218        if (runtime)
219            found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
220    }
221    else
222    {
223        LanguageRuntime *cpp_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus);
224        if (cpp_runtime)
225            found_dynamic_type = cpp_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
226
227        if (!found_dynamic_type)
228        {
229            LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC);
230            if (objc_runtime)
231                found_dynamic_type = objc_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
232        }
233    }
234
235    // Getting the dynamic value may have run the program a bit, and so marked us as needing updating, but we really
236    // don't...
237
238    m_update_point.SetUpdated();
239
240    if (found_dynamic_type)
241    {
242        if (class_type_or_name.HasType())
243        {
244            // TypeSP are always generated from debug info
245            if (!class_type_or_name.HasTypeSP() && class_type_or_name.GetClangASTType().IsRuntimeGeneratedType())
246            {
247                m_type_impl = TypeImpl(m_parent->GetClangType(),FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType());
248                class_type_or_name.SetClangASTType(ClangASTType());
249            }
250            else
251            {
252                m_type_impl = TypeImpl(FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType());
253            }
254        }
255        else
256        {
257            m_type_impl.Clear();
258        }
259    }
260    else
261    {
262        m_type_impl.Clear();
263    }
264
265    // If we don't have a dynamic type, then make ourselves just a echo of our parent.
266    // Or we could return false, and make ourselves an echo of our parent?
267    if (!found_dynamic_type)
268    {
269        if (m_dynamic_type_info)
270            SetValueDidChange(true);
271        ClearDynamicTypeInformation();
272        m_dynamic_type_info.Clear();
273        m_value = m_parent->GetValue();
274        m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
275        return m_error.Success();
276    }
277
278    Value old_value(m_value);
279
280    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
281
282    bool has_changed_type = false;
283
284    if (!m_dynamic_type_info)
285    {
286        m_dynamic_type_info = class_type_or_name;
287        has_changed_type = true;
288    }
289    else if (class_type_or_name != m_dynamic_type_info)
290    {
291        // We are another type, we need to tear down our children...
292        m_dynamic_type_info = class_type_or_name;
293        SetValueDidChange (true);
294        has_changed_type = true;
295    }
296
297    if (has_changed_type)
298        ClearDynamicTypeInformation ();
299
300    if (!m_address.IsValid() || m_address != dynamic_address)
301    {
302        if (m_address.IsValid())
303            SetValueDidChange (true);
304
305        // We've moved, so we should be fine...
306        m_address = dynamic_address;
307        lldb::TargetSP target_sp (GetTargetSP());
308        lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
309        m_value.GetScalar() = load_address;
310    }
311
312    m_dynamic_type_info = FixupTypeAndOrName(m_dynamic_type_info, *m_parent);
313
314    //m_value.SetContext (Value::eContextTypeClangType, corrected_type);
315    m_value.SetClangType (m_dynamic_type_info.GetClangASTType());
316
317    // Our address is the location of the dynamic type stored in memory.  It isn't a load address,
318    // because we aren't pointing to the LOCATION that stores the pointer to us, we're pointing to us...
319    m_value.SetValueType(Value::eValueTypeScalar);
320
321    if (has_changed_type && log)
322        log->Printf("[%s %p] has a new dynamic type %s", GetName().GetCString(),
323                    static_cast<void*>(this), GetTypeName().GetCString());
324
325    if (m_address.IsValid() && m_dynamic_type_info)
326    {
327        // The variable value is in the Scalar value inside the m_value.
328        // We can point our m_data right to it.
329        m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
330        if (m_error.Success())
331        {
332            if (GetClangType().IsAggregateType ())
333            {
334                // this value object represents an aggregate type whose
335                // children have values, but this object does not. So we
336                // say we are changed if our location has changed.
337                SetValueDidChange (m_value.GetValueType() != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
338            }
339
340            SetValueIsValid (true);
341            return true;
342        }
343    }
344
345    // We get here if we've failed above...
346    SetValueIsValid (false);
347    return false;
348}
349
350
351
352bool
353ValueObjectDynamicValue::IsInScope ()
354{
355    return m_parent->IsInScope();
356}
357
358bool
359ValueObjectDynamicValue::SetValueFromCString (const char *value_str, 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        if (strcmp(value_str,"0"))
384        {
385            error.SetErrorString("unable to modify dynamic value, use 'expression' command");
386            return false;
387        }
388    }
389
390    bool ret_val = m_parent->SetValueFromCString(value_str,error);
391    SetNeedsUpdate();
392    return ret_val;
393}
394
395bool
396ValueObjectDynamicValue::SetData (DataExtractor &data, Error &error)
397{
398    if (!UpdateValueIfNeeded(false))
399    {
400        error.SetErrorString("unable to read value");
401        return false;
402    }
403
404    uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
405    uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
406
407    if (my_value == UINT64_MAX || parent_value == UINT64_MAX)
408    {
409        error.SetErrorString("unable to read value");
410        return false;
411    }
412
413    // if we are at an offset from our parent, in order to set ourselves correctly we would need
414    // to change the new value so that it refers to the correct dynamic type. we choose not to deal
415    // with that - if anything more than a value overwrite is required, you should be using the
416    // expression parser instead of the value editing facility
417    if (my_value != parent_value)
418    {
419        // but NULL'ing out a value should always be allowed
420        lldb::offset_t offset = 0;
421
422        if (data.GetPointer(&offset) != 0)
423        {
424            error.SetErrorString("unable to modify dynamic value, use 'expression' command");
425            return false;
426        }
427    }
428
429    bool ret_val = m_parent->SetData(data, error);
430    SetNeedsUpdate();
431    return ret_val;
432}
433