Home | History | Annotate | Download | only in Core
      1 //===-- ValueObjectMemory.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/ValueObjectMemory.h"
     12 
     13 // C Includes
     14 // C++ Includes
     15 // Other libraries and framework includes
     16 // Project includes
     17 #include "lldb/Core/Module.h"
     18 #include "lldb/Core/ValueObjectList.h"
     19 #include "lldb/Core/Value.h"
     20 #include "lldb/Core/ValueObject.h"
     21 
     22 #include "lldb/Symbol/ObjectFile.h"
     23 #include "lldb/Symbol/SymbolContext.h"
     24 #include "lldb/Symbol/Type.h"
     25 #include "lldb/Symbol/Variable.h"
     26 
     27 #include "lldb/Target/ExecutionContext.h"
     28 #include "lldb/Target/Process.h"
     29 #include "lldb/Target/RegisterContext.h"
     30 #include "lldb/Target/Target.h"
     31 #include "lldb/Target/Thread.h"
     32 
     33 using namespace lldb;
     34 using namespace lldb_private;
     35 
     36 ValueObjectSP
     37 ValueObjectMemory::Create (ExecutionContextScope *exe_scope,
     38                            const char *name,
     39                            const Address &address,
     40                            lldb::TypeSP &type_sp)
     41 {
     42     return (new ValueObjectMemory (exe_scope, name, address, type_sp))->GetSP();
     43 }
     44 
     45 ValueObjectSP
     46 ValueObjectMemory::Create (ExecutionContextScope *exe_scope,
     47                            const char *name,
     48                            const Address &address,
     49                            const ClangASTType &ast_type)
     50 {
     51     return (new ValueObjectMemory (exe_scope, name, address, ast_type))->GetSP();
     52 }
     53 
     54 ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope,
     55                                       const char *name,
     56                                       const Address &address,
     57                                       lldb::TypeSP &type_sp) :
     58     ValueObject(exe_scope),
     59     m_address (address),
     60     m_type_sp(type_sp),
     61     m_clang_type()
     62 {
     63     // Do not attempt to construct one of these objects with no variable!
     64     assert (m_type_sp.get() != NULL);
     65     SetName (ConstString(name));
     66     m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
     67     TargetSP target_sp (GetTargetSP());
     68     lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
     69     if (load_address != LLDB_INVALID_ADDRESS)
     70     {
     71         m_value.SetValueType(Value::eValueTypeLoadAddress);
     72         m_value.GetScalar() = load_address;
     73     }
     74     else
     75     {
     76         lldb::addr_t file_address = m_address.GetFileAddress();
     77         if (file_address != LLDB_INVALID_ADDRESS)
     78         {
     79             m_value.SetValueType(Value::eValueTypeFileAddress);
     80             m_value.GetScalar() = file_address;
     81         }
     82         else
     83         {
     84             m_value.GetScalar() = m_address.GetOffset();
     85             m_value.SetValueType (Value::eValueTypeScalar);
     86         }
     87     }
     88 }
     89 
     90 ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope,
     91                                       const char *name,
     92                                       const Address &address,
     93                                       const ClangASTType &ast_type) :
     94     ValueObject(exe_scope),
     95     m_address (address),
     96     m_type_sp(),
     97     m_clang_type(ast_type)
     98 {
     99     // Do not attempt to construct one of these objects with no variable!
    100     assert (m_clang_type.GetASTContext());
    101     assert (m_clang_type.GetOpaqueQualType());
    102 
    103     TargetSP target_sp (GetTargetSP());
    104 
    105     SetName (ConstString(name));
    106 //    m_value.SetContext(Value::eContextTypeClangType, m_clang_type.GetOpaqueQualType());
    107     m_value.SetClangType(m_clang_type);
    108     lldb::addr_t load_address = m_address.GetLoadAddress (target_sp.get());
    109     if (load_address != LLDB_INVALID_ADDRESS)
    110     {
    111         m_value.SetValueType(Value::eValueTypeLoadAddress);
    112         m_value.GetScalar() = load_address;
    113     }
    114     else
    115     {
    116         lldb::addr_t file_address = m_address.GetFileAddress();
    117         if (file_address != LLDB_INVALID_ADDRESS)
    118         {
    119             m_value.SetValueType(Value::eValueTypeFileAddress);
    120             m_value.GetScalar() = file_address;
    121         }
    122         else
    123         {
    124             m_value.GetScalar() = m_address.GetOffset();
    125             m_value.SetValueType (Value::eValueTypeScalar);
    126         }
    127     }
    128 }
    129 
    130 ValueObjectMemory::~ValueObjectMemory()
    131 {
    132 }
    133 
    134 ClangASTType
    135 ValueObjectMemory::GetClangTypeImpl ()
    136 {
    137     if (m_type_sp)
    138         return m_type_sp->GetClangForwardType();
    139     return m_clang_type;
    140 }
    141 
    142 ConstString
    143 ValueObjectMemory::GetTypeName()
    144 {
    145     if (m_type_sp)
    146         return m_type_sp->GetName();
    147     return m_clang_type.GetConstTypeName();
    148 }
    149 
    150 size_t
    151 ValueObjectMemory::CalculateNumChildren()
    152 {
    153     if (m_type_sp)
    154         return m_type_sp->GetNumChildren(true);
    155     const bool omit_empty_base_classes = true;
    156     return m_clang_type.GetNumChildren (omit_empty_base_classes);
    157 }
    158 
    159 uint64_t
    160 ValueObjectMemory::GetByteSize()
    161 {
    162     if (m_type_sp)
    163         return m_type_sp->GetByteSize();
    164     return m_clang_type.GetByteSize ();
    165 }
    166 
    167 lldb::ValueType
    168 ValueObjectMemory::GetValueType() const
    169 {
    170     // RETHINK: Should this be inherited from somewhere?
    171     return lldb::eValueTypeVariableGlobal;
    172 }
    173 
    174 bool
    175 ValueObjectMemory::UpdateValue ()
    176 {
    177     SetValueIsValid (false);
    178     m_error.Clear();
    179 
    180     ExecutionContext exe_ctx (GetExecutionContextRef());
    181 
    182     Target *target = exe_ctx.GetTargetPtr();
    183     if (target)
    184     {
    185         m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
    186         m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
    187     }
    188 
    189     Value old_value(m_value);
    190     if (m_address.IsValid())
    191     {
    192         Value::ValueType value_type = m_value.GetValueType();
    193 
    194         switch (value_type)
    195         {
    196         default:
    197             assert(!"Unhandled expression result value kind...");
    198             break;
    199 
    200         case Value::eValueTypeScalar:
    201             // The variable value is in the Scalar value inside the m_value.
    202             // We can point our m_data right to it.
    203             m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
    204             break;
    205 
    206         case Value::eValueTypeFileAddress:
    207         case Value::eValueTypeLoadAddress:
    208         case Value::eValueTypeHostAddress:
    209             // The DWARF expression result was an address in the inferior
    210             // process. If this variable is an aggregate type, we just need
    211             // the address as the main value as all child variable objects
    212             // will rely upon this location and add an offset and then read
    213             // their own values as needed. If this variable is a simple
    214             // type, we read all data for it into m_data.
    215             // Make sure this type has a value before we try and read it
    216 
    217             // If we have a file address, convert it to a load address if we can.
    218             if (value_type == Value::eValueTypeFileAddress && exe_ctx.GetProcessPtr())
    219             {
    220                 lldb::addr_t load_addr = m_address.GetLoadAddress(target);
    221                 if (load_addr != LLDB_INVALID_ADDRESS)
    222                 {
    223                     m_value.SetValueType(Value::eValueTypeLoadAddress);
    224                     m_value.GetScalar() = load_addr;
    225                 }
    226             }
    227 
    228             if (GetClangType().IsAggregateType())
    229             {
    230                 // this value object represents an aggregate type whose
    231                 // children have values, but this object does not. So we
    232                 // say we are changed if our location has changed.
    233                 SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
    234             }
    235             else
    236             {
    237                 // Copy the Value and set the context to use our Variable
    238                 // so it can extract read its value into m_data appropriately
    239                 Value value(m_value);
    240                 if (m_type_sp)
    241                     value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
    242                 else
    243                 {
    244                     //value.SetContext(Value::eContextTypeClangType, m_clang_type.GetOpaqueQualType());
    245                     value.SetClangType(m_clang_type);
    246                 }
    247 
    248                 m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
    249             }
    250             break;
    251         }
    252 
    253         SetValueIsValid (m_error.Success());
    254     }
    255     return m_error.Success();
    256 }
    257 
    258 
    259 
    260 bool
    261 ValueObjectMemory::IsInScope ()
    262 {
    263     // FIXME: Maybe try to read the memory address, and if that works, then
    264     // we are in scope?
    265     return true;
    266 }
    267 
    268 
    269 lldb::ModuleSP
    270 ValueObjectMemory::GetModule()
    271 {
    272     return m_address.GetModule();
    273 }
    274 
    275 
    276