ValueObjectDynamicValue.cpp revision 263363
11539Srgrimes//===-- ValueObjectDynamicValue.cpp ---------------------------------*- C++ -*-===//
21539Srgrimes//
31539Srgrimes//                     The LLVM Compiler Infrastructure
41539Srgrimes//
51539Srgrimes// This file is distributed under the University of Illinois Open Source
61539Srgrimes// License. See LICENSE.TXT for details.
71539Srgrimes//
81539Srgrimes//===----------------------------------------------------------------------===//
91539Srgrimes
101539Srgrimes
111539Srgrimes#include "lldb/Core/ValueObjectDynamicValue.h"
121539Srgrimes
131539Srgrimes// C Includes
141539Srgrimes// C++ Includes
151539Srgrimes// Other libraries and framework includes
161539Srgrimes// Project includes
171539Srgrimes#include "lldb/Core/Log.h"
181539Srgrimes#include "lldb/Core/Module.h"
191539Srgrimes#include "lldb/Core/ValueObjectList.h"
201539Srgrimes#include "lldb/Core/Value.h"
211539Srgrimes#include "lldb/Core/ValueObject.h"
221539Srgrimes
231539Srgrimes#include "lldb/Symbol/ClangASTType.h"
241539Srgrimes#include "lldb/Symbol/ObjectFile.h"
251539Srgrimes#include "lldb/Symbol/SymbolContext.h"
261539Srgrimes#include "lldb/Symbol/Type.h"
271539Srgrimes#include "lldb/Symbol/Variable.h"
281539Srgrimes
291539Srgrimes#include "lldb/Target/ExecutionContext.h"
301539Srgrimes#include "lldb/Target/LanguageRuntime.h"
311539Srgrimes#include "lldb/Target/Process.h"
321539Srgrimes#include "lldb/Target/RegisterContext.h"
331539Srgrimes#include "lldb/Target/Target.h"
3451794Smarcel#include "lldb/Target/Thread.h"
3551794Smarcel
361539Srgrimesusing namespace lldb_private;
371539Srgrimes
389343SbdeValueObjectDynamicValue::ValueObjectDynamicValue (ValueObject &parent, lldb::DynamicValueType use_dynamic) :
399343Sbde    ValueObject(parent),
401539Srgrimes    m_address (),
411539Srgrimes    m_dynamic_type_info(),
4234925Sdufault    m_use_dynamic (use_dynamic)
43102227Smike{
441539Srgrimes    SetName (parent.GetName());
4551794Smarcel}
461539Srgrimes
471539SrgrimesValueObjectDynamicValue::~ValueObjectDynamicValue()
481539Srgrimes{
491539Srgrimes    m_owning_valobj_sp.reset();
5047289Speter}
511539Srgrimes
521539SrgrimesClangASTType
531539SrgrimesValueObjectDynamicValue::GetClangTypeImpl ()
5493032Simp{
551539Srgrimes    const bool success = UpdateValueIfNeeded(false);
56102227Smike    if (success)
5793032Simp    {
5893032Simp        if (m_dynamic_type_info.HasType())
5993032Simp            return m_value.GetClangType();
6093032Simp        else
6193032Simp            return m_parent->GetClangType();
6293032Simp    }
6393032Simp    return m_parent->GetClangType();
6493032Simp}
6593032Simp
6693032SimpConstString
6734319SdufaultValueObjectDynamicValue::GetTypeName()
6834319Sdufault{
6934925Sdufault    const bool success = UpdateValueIfNeeded(false);
7034319Sdufault    if (success)
7134319Sdufault    {
72102227Smike        if (m_dynamic_type_info.HasName())
7393032Simp            return m_dynamic_type_info.GetName();
7493032Simp        if (m_dynamic_type_info.HasType())
7534319Sdufault            return GetClangType().GetConstTypeName();
7634319Sdufault    }
7734030Sdufault    return m_parent->GetTypeName();
781539Srgrimes}
79102227Smike
8093032SimpTypeImpl
8193032SimpValueObjectDynamicValue::GetTypeImpl ()
8293032Simp{
8393032Simp    const bool success = UpdateValueIfNeeded(false);
8493032Simp    if (success && m_type_impl.IsValid())
8593032Simp    {
8693032Simp        return m_type_impl;
8793032Simp    }
8893032Simp    return m_parent->GetTypeImpl();
899343Sbde}
909343Sbde
911539SrgrimesConstString
921539SrgrimesValueObjectDynamicValue::GetQualifiedTypeName()
939343Sbde{
94    const bool success = UpdateValueIfNeeded(false);
95    if (success)
96    {
97        if (m_dynamic_type_info.HasName())
98            return m_dynamic_type_info.GetName();
99        if (m_dynamic_type_info.HasType())
100            return GetClangType().GetConstQualifiedTypeName ();
101    }
102    return m_parent->GetTypeName();
103}
104
105size_t
106ValueObjectDynamicValue::CalculateNumChildren()
107{
108    const bool success = UpdateValueIfNeeded(false);
109    if (success && m_dynamic_type_info.HasType())
110        return GetClangType().GetNumChildren (true);
111    else
112        return m_parent->GetNumChildren();
113}
114
115uint64_t
116ValueObjectDynamicValue::GetByteSize()
117{
118    const bool success = UpdateValueIfNeeded(false);
119    if (success && m_dynamic_type_info.HasType())
120        return m_value.GetValueByteSize(NULL);
121    else
122        return m_parent->GetByteSize();
123}
124
125lldb::ValueType
126ValueObjectDynamicValue::GetValueType() const
127{
128    return m_parent->GetValueType();
129}
130
131
132static TypeAndOrName
133FixupTypeAndOrName (const TypeAndOrName& type_andor_name,
134                    ValueObject& parent)
135{
136    TypeAndOrName ret(type_andor_name);
137    if (type_andor_name.HasType())
138    {
139        // The type will always be the type of the dynamic object.  If our parent's type was a pointer,
140        // then our type should be a pointer to the type of the dynamic object.  If a reference, then the original type
141        // should be okay...
142        ClangASTType orig_type = type_andor_name.GetClangASTType();
143        ClangASTType corrected_type = orig_type;
144        if (parent.IsPointerType())
145            corrected_type = orig_type.GetPointerType ();
146        else if (parent.IsPointerOrReferenceType())
147            corrected_type = orig_type.GetLValueReferenceType ();
148        ret.SetClangASTType(corrected_type);
149    }
150    else /*if (m_dynamic_type_info.HasName())*/
151    {
152        // If we are here we need to adjust our dynamic type name to include the correct & or * symbol
153        std::string corrected_name (type_andor_name.GetName().GetCString());
154        if (parent.IsPointerType())
155            corrected_name.append(" *");
156        else if (parent.IsPointerOrReferenceType())
157            corrected_name.append(" &");
158        // the parent type should be a correctly pointer'ed or referenc'ed type
159        ret.SetClangASTType(parent.GetClangType());
160        ret.SetName(corrected_name.c_str());
161    }
162    return ret;
163}
164
165bool
166ValueObjectDynamicValue::UpdateValue ()
167{
168    SetValueIsValid (false);
169    m_error.Clear();
170
171    if (!m_parent->UpdateValueIfNeeded(false))
172    {
173        // The dynamic value failed to get an error, pass the error along
174        if (m_error.Success() && m_parent->GetError().Fail())
175            m_error = m_parent->GetError();
176        return false;
177    }
178
179    // Setting our type_sp to NULL will route everything back through our
180    // parent which is equivalent to not using dynamic values.
181    if (m_use_dynamic == lldb::eNoDynamicValues)
182    {
183        m_dynamic_type_info.Clear();
184        return true;
185    }
186
187    ExecutionContext exe_ctx (GetExecutionContextRef());
188    Target *target = exe_ctx.GetTargetPtr();
189    if (target)
190    {
191        m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
192        m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
193    }
194
195    // First make sure our Type and/or Address haven't changed:
196    Process *process = exe_ctx.GetProcessPtr();
197    if (!process)
198        return false;
199
200    TypeAndOrName class_type_or_name;
201    Address dynamic_address;
202    bool found_dynamic_type = false;
203
204    lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
205    if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC)
206    {
207        LanguageRuntime *runtime = process->GetLanguageRuntime (known_type);
208        if (runtime)
209            found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
210    }
211    else
212    {
213        LanguageRuntime *cpp_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus);
214        if (cpp_runtime)
215            found_dynamic_type = cpp_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
216
217        if (!found_dynamic_type)
218        {
219            LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC);
220            if (objc_runtime)
221                found_dynamic_type = objc_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
222        }
223    }
224
225    // Getting the dynamic value may have run the program a bit, and so marked us as needing updating, but we really
226    // don't...
227
228    m_update_point.SetUpdated();
229
230    if (found_dynamic_type)
231    {
232        if (class_type_or_name.HasType())
233        {
234            // TypeSP are always generated from debug info
235            if (!class_type_or_name.HasTypeSP() && class_type_or_name.GetClangASTType().IsRuntimeGeneratedType())
236            {
237                m_type_impl = TypeImpl(m_parent->GetClangType(),FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType());
238                class_type_or_name.SetClangASTType(ClangASTType());
239            }
240            else
241            {
242                m_type_impl = TypeImpl(FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType());
243            }
244        }
245        else
246        {
247            m_type_impl.Clear();
248        }
249    }
250    else
251    {
252        m_type_impl.Clear();
253    }
254
255    // If we don't have a dynamic type, then make ourselves just a echo of our parent.
256    // Or we could return false, and make ourselves an echo of our parent?
257    if (!found_dynamic_type)
258    {
259        if (m_dynamic_type_info)
260            SetValueDidChange(true);
261        ClearDynamicTypeInformation();
262        m_dynamic_type_info.Clear();
263        m_value = m_parent->GetValue();
264        m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
265        return m_error.Success();
266    }
267
268    Value old_value(m_value);
269
270    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
271
272    bool has_changed_type = false;
273
274    if (!m_dynamic_type_info)
275    {
276        m_dynamic_type_info = class_type_or_name;
277        has_changed_type = true;
278    }
279    else if (class_type_or_name != m_dynamic_type_info)
280    {
281        // We are another type, we need to tear down our children...
282        m_dynamic_type_info = class_type_or_name;
283        SetValueDidChange (true);
284        has_changed_type = true;
285    }
286
287    if (has_changed_type)
288        ClearDynamicTypeInformation ();
289
290    if (!m_address.IsValid() || m_address != dynamic_address)
291    {
292        if (m_address.IsValid())
293            SetValueDidChange (true);
294
295        // We've moved, so we should be fine...
296        m_address = dynamic_address;
297        lldb::TargetSP target_sp (GetTargetSP());
298        lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
299        m_value.GetScalar() = load_address;
300    }
301
302    m_dynamic_type_info = FixupTypeAndOrName(m_dynamic_type_info, *m_parent);
303
304    //m_value.SetContext (Value::eContextTypeClangType, corrected_type);
305    m_value.SetClangType (m_dynamic_type_info.GetClangASTType());
306
307    // Our address is the location of the dynamic type stored in memory.  It isn't a load address,
308    // because we aren't pointing to the LOCATION that stores the pointer to us, we're pointing to us...
309    m_value.SetValueType(Value::eValueTypeScalar);
310
311    if (has_changed_type && log)
312        log->Printf("[%s %p] has a new dynamic type %s",
313                    GetName().GetCString(),
314                    this,
315                    GetTypeName().GetCString());
316
317    if (m_address.IsValid() && m_dynamic_type_info)
318    {
319        // The variable value is in the Scalar value inside the m_value.
320        // We can point our m_data right to it.
321        m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
322        if (m_error.Success())
323        {
324            if (GetClangType().IsAggregateType ())
325            {
326                // this value object represents an aggregate type whose
327                // children have values, but this object does not. So we
328                // say we are changed if our location has changed.
329                SetValueDidChange (m_value.GetValueType() != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
330            }
331
332            SetValueIsValid (true);
333            return true;
334        }
335    }
336
337    // We get here if we've failed above...
338    SetValueIsValid (false);
339    return false;
340}
341
342
343
344bool
345ValueObjectDynamicValue::IsInScope ()
346{
347    return m_parent->IsInScope();
348}
349
350bool
351ValueObjectDynamicValue::SetValueFromCString (const char *value_str, Error& error)
352{
353    if (!UpdateValueIfNeeded(false))
354    {
355        error.SetErrorString("unable to read value");
356        return false;
357    }
358
359    uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
360    uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
361
362    if (my_value == UINT64_MAX || parent_value == UINT64_MAX)
363    {
364        error.SetErrorString("unable to read value");
365        return false;
366    }
367
368    // if we are at an offset from our parent, in order to set ourselves correctly we would need
369    // to change the new value so that it refers to the correct dynamic type. we choose not to deal
370    // with that - if anything more than a value overwrite is required, you should be using the
371    // expression parser instead of the value editing facility
372    if (my_value != parent_value)
373    {
374        // but NULL'ing out a value should always be allowed
375        if (strcmp(value_str,"0"))
376        {
377            error.SetErrorString("unable to modify dynamic value, use 'expression' command");
378            return false;
379        }
380    }
381
382    bool ret_val = m_parent->SetValueFromCString(value_str,error);
383    SetNeedsUpdate();
384    return ret_val;
385}
386
387bool
388ValueObjectDynamicValue::SetData (DataExtractor &data, Error &error)
389{
390    if (!UpdateValueIfNeeded(false))
391    {
392        error.SetErrorString("unable to read value");
393        return false;
394    }
395
396    uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
397    uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
398
399    if (my_value == UINT64_MAX || parent_value == UINT64_MAX)
400    {
401        error.SetErrorString("unable to read value");
402        return false;
403    }
404
405    // if we are at an offset from our parent, in order to set ourselves correctly we would need
406    // to change the new value so that it refers to the correct dynamic type. we choose not to deal
407    // with that - if anything more than a value overwrite is required, you should be using the
408    // expression parser instead of the value editing facility
409    if (my_value != parent_value)
410    {
411        // but NULL'ing out a value should always be allowed
412        lldb::offset_t offset = 0;
413
414        if (data.GetPointer(&offset) != 0)
415        {
416            error.SetErrorString("unable to modify dynamic value, use 'expression' command");
417            return false;
418        }
419    }
420
421    bool ret_val = m_parent->SetData(data, error);
422    SetNeedsUpdate();
423    return ret_val;
424}
425