Home | History | Annotate | Download | only in Core
      1 //===-- ValueObjectVariable.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/ValueObjectVariable.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/RegisterValue.h"
     19 #include "lldb/Core/ValueObjectList.h"
     20 #include "lldb/Core/Value.h"
     21 
     22 #include "lldb/Symbol/Function.h"
     23 #include "lldb/Symbol/ObjectFile.h"
     24 #include "lldb/Symbol/SymbolContext.h"
     25 #include "lldb/Symbol/SymbolContextScope.h"
     26 #include "lldb/Symbol/Type.h"
     27 #include "lldb/Symbol/Variable.h"
     28 
     29 #include "lldb/Target/ExecutionContext.h"
     30 #include "lldb/Target/Process.h"
     31 #include "lldb/Target/RegisterContext.h"
     32 #include "lldb/Target/Target.h"
     33 #include "lldb/Target/Thread.h"
     34 
     35 
     36 using namespace lldb_private;
     37 
     38 lldb::ValueObjectSP
     39 ValueObjectVariable::Create (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp)
     40 {
     41     return (new ValueObjectVariable (exe_scope, var_sp))->GetSP();
     42 }
     43 
     44 ValueObjectVariable::ValueObjectVariable (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp) :
     45     ValueObject(exe_scope),
     46     m_variable_sp(var_sp)
     47 {
     48     // Do not attempt to construct one of these objects with no variable!
     49     assert (m_variable_sp.get() != NULL);
     50     m_name = var_sp->GetName();
     51 }
     52 
     53 ValueObjectVariable::~ValueObjectVariable()
     54 {
     55 }
     56 
     57 ClangASTType
     58 ValueObjectVariable::GetClangTypeImpl ()
     59 {
     60     Type *var_type = m_variable_sp->GetType();
     61     if (var_type)
     62         return var_type->GetClangForwardType();
     63     return ClangASTType();
     64 }
     65 
     66 ConstString
     67 ValueObjectVariable::GetTypeName()
     68 {
     69     Type * var_type = m_variable_sp->GetType();
     70     if (var_type)
     71         return var_type->GetName();
     72     return ConstString();
     73 }
     74 
     75 ConstString
     76 ValueObjectVariable::GetQualifiedTypeName()
     77 {
     78     Type * var_type = m_variable_sp->GetType();
     79     if (var_type)
     80         return var_type->GetQualifiedName();
     81     return ConstString();
     82 }
     83 
     84 size_t
     85 ValueObjectVariable::CalculateNumChildren()
     86 {
     87     ClangASTType type(GetClangType());
     88 
     89     if (!type.IsValid())
     90         return 0;
     91 
     92     const bool omit_empty_base_classes = true;
     93     return type.GetNumChildren(omit_empty_base_classes);
     94 }
     95 
     96 uint64_t
     97 ValueObjectVariable::GetByteSize()
     98 {
     99     ClangASTType type(GetClangType());
    100 
    101     if (!type.IsValid())
    102         return 0;
    103 
    104     return type.GetByteSize();
    105 }
    106 
    107 lldb::ValueType
    108 ValueObjectVariable::GetValueType() const
    109 {
    110     if (m_variable_sp)
    111         return m_variable_sp->GetScope();
    112     return lldb::eValueTypeInvalid;
    113 }
    114 
    115 bool
    116 ValueObjectVariable::UpdateValue ()
    117 {
    118     SetValueIsValid (false);
    119     m_error.Clear();
    120 
    121     Variable *variable = m_variable_sp.get();
    122     DWARFExpression &expr = variable->LocationExpression();
    123 
    124     if (variable->GetLocationIsConstantValueData())
    125     {
    126         // expr doesn't contain DWARF bytes, it contains the constant variable
    127         // value bytes themselves...
    128         if (expr.GetExpressionData(m_data))
    129             m_value.SetContext(Value::eContextTypeVariable, variable);
    130         else
    131             m_error.SetErrorString ("empty constant data");
    132         // constant bytes can't be edited - sorry
    133         m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL);
    134     }
    135     else
    136     {
    137         lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS;
    138         ExecutionContext exe_ctx (GetExecutionContextRef());
    139 
    140         Target *target = exe_ctx.GetTargetPtr();
    141         if (target)
    142         {
    143             m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
    144             m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
    145         }
    146 
    147         if (expr.IsLocationList())
    148         {
    149             SymbolContext sc;
    150             variable->CalculateSymbolContext (&sc);
    151             if (sc.function)
    152                 loclist_base_load_addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (target);
    153         }
    154         Value old_value(m_value);
    155         if (expr.Evaluate (&exe_ctx, NULL, NULL, NULL, loclist_base_load_addr, NULL, m_value, &m_error))
    156         {
    157             m_resolved_value = m_value;
    158             m_value.SetContext(Value::eContextTypeVariable, variable);
    159 
    160             Value::ValueType value_type = m_value.GetValueType();
    161 
    162             switch (value_type)
    163             {
    164                 case Value::eValueTypeFileAddress:
    165                     SetAddressTypeOfChildren(eAddressTypeFile);
    166                     break;
    167                 case Value::eValueTypeHostAddress:
    168                     SetAddressTypeOfChildren(eAddressTypeHost);
    169                     break;
    170                 case Value::eValueTypeLoadAddress:
    171                 case Value::eValueTypeScalar:
    172                 case Value::eValueTypeVector:
    173                     SetAddressTypeOfChildren(eAddressTypeLoad);
    174                     break;
    175             }
    176 
    177             switch (value_type)
    178             {
    179             case Value::eValueTypeVector:
    180                     // fall through
    181             case Value::eValueTypeScalar:
    182                 // The variable value is in the Scalar value inside the m_value.
    183                 // We can point our m_data right to it.
    184                 m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
    185                 break;
    186 
    187             case Value::eValueTypeFileAddress:
    188             case Value::eValueTypeLoadAddress:
    189             case Value::eValueTypeHostAddress:
    190                 // The DWARF expression result was an address in the inferior
    191                 // process. If this variable is an aggregate type, we just need
    192                 // the address as the main value as all child variable objects
    193                 // will rely upon this location and add an offset and then read
    194                 // their own values as needed. If this variable is a simple
    195                 // type, we read all data for it into m_data.
    196                 // Make sure this type has a value before we try and read it
    197 
    198                 // If we have a file address, convert it to a load address if we can.
    199                 Process *process = exe_ctx.GetProcessPtr();
    200                 if (value_type == Value::eValueTypeFileAddress && process && process->IsAlive())
    201                 {
    202                     lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
    203                     if (file_addr != LLDB_INVALID_ADDRESS)
    204                     {
    205                         SymbolContext var_sc;
    206                         variable->CalculateSymbolContext(&var_sc);
    207                         if (var_sc.module_sp)
    208                         {
    209                             ObjectFile *objfile = var_sc.module_sp->GetObjectFile();
    210                             if (objfile)
    211                             {
    212                                 Address so_addr(file_addr, objfile->GetSectionList());
    213                                 lldb::addr_t load_addr = so_addr.GetLoadAddress (target);
    214                                 if (load_addr != LLDB_INVALID_ADDRESS)
    215                                 {
    216                                     m_value.SetValueType(Value::eValueTypeLoadAddress);
    217                                     m_value.GetScalar() = load_addr;
    218                                 }
    219                             }
    220                         }
    221                     }
    222                 }
    223 
    224                 if (GetClangType().IsAggregateType())
    225                 {
    226                     // this value object represents an aggregate type whose
    227                     // children have values, but this object does not. So we
    228                     // say we are changed if our location has changed.
    229                     SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
    230                 }
    231                 else
    232                 {
    233                     // Copy the Value and set the context to use our Variable
    234                     // so it can extract read its value into m_data appropriately
    235                     Value value(m_value);
    236                     value.SetContext(Value::eContextTypeVariable, variable);
    237                     m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
    238                 }
    239                 break;
    240             }
    241 
    242             SetValueIsValid (m_error.Success());
    243         }
    244         else
    245         {
    246             // could not find location, won't allow editing
    247             m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL);
    248         }
    249     }
    250     return m_error.Success();
    251 }
    252 
    253 
    254 
    255 bool
    256 ValueObjectVariable::IsInScope ()
    257 {
    258     const ExecutionContextRef &exe_ctx_ref = GetExecutionContextRef();
    259     if (exe_ctx_ref.HasFrameRef())
    260     {
    261         ExecutionContext exe_ctx (exe_ctx_ref);
    262         StackFrame *frame = exe_ctx.GetFramePtr();
    263         if (frame)
    264         {
    265             return m_variable_sp->IsInScope (frame);
    266         }
    267         else
    268         {
    269             // This ValueObject had a frame at one time, but now we
    270             // can't locate it, so return false since we probably aren't
    271             // in scope.
    272             return false;
    273         }
    274     }
    275     // We have a variable that wasn't tied to a frame, which
    276     // means it is a global and is always in scope.
    277     return true;
    278 
    279 }
    280 
    281 lldb::ModuleSP
    282 ValueObjectVariable::GetModule()
    283 {
    284     if (m_variable_sp)
    285     {
    286         SymbolContextScope *sc_scope = m_variable_sp->GetSymbolContextScope();
    287         if (sc_scope)
    288         {
    289             return sc_scope->CalculateSymbolContextModule();
    290         }
    291     }
    292     return lldb::ModuleSP();
    293 }
    294 
    295 SymbolContextScope *
    296 ValueObjectVariable::GetSymbolContextScope()
    297 {
    298     if (m_variable_sp)
    299         return m_variable_sp->GetSymbolContextScope();
    300     return NULL;
    301 }
    302 
    303 bool
    304 ValueObjectVariable::GetDeclaration (Declaration &decl)
    305 {
    306     if (m_variable_sp)
    307     {
    308         decl = m_variable_sp->GetDeclaration();
    309         return true;
    310     }
    311     return false;
    312 }
    313 
    314 const char *
    315 ValueObjectVariable::GetLocationAsCString ()
    316 {
    317     if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo)
    318         return GetLocationAsCStringImpl(m_resolved_value,
    319                                         m_data);
    320     else
    321         return ValueObject::GetLocationAsCString();
    322 }
    323 
    324 bool
    325 ValueObjectVariable::SetValueFromCString (const char *value_str, Error& error)
    326 {
    327     if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo)
    328     {
    329         RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo();
    330         ExecutionContext exe_ctx(GetExecutionContextRef());
    331         RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
    332         RegisterValue reg_value;
    333         if (!reg_info || !reg_ctx)
    334         {
    335             error.SetErrorString("unable to retrieve register info");
    336             return false;
    337         }
    338         error = reg_value.SetValueFromCString(reg_info, value_str);
    339         if (error.Fail())
    340             return false;
    341         if (reg_ctx->WriteRegister (reg_info, reg_value))
    342         {
    343             SetNeedsUpdate();
    344             return true;
    345         }
    346         else
    347         {
    348             error.SetErrorString("unable to write back to register");
    349             return false;
    350         }
    351     }
    352     else
    353         return ValueObject::SetValueFromCString(value_str, error);
    354 }
    355 
    356 bool
    357 ValueObjectVariable::SetData (DataExtractor &data, Error &error)
    358 {
    359     if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo)
    360     {
    361         RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo();
    362         ExecutionContext exe_ctx(GetExecutionContextRef());
    363         RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
    364         RegisterValue reg_value;
    365         if (!reg_info || !reg_ctx)
    366         {
    367             error.SetErrorString("unable to retrieve register info");
    368             return false;
    369         }
    370         error = reg_value.SetValueFromData(reg_info, data, 0, false);
    371         if (error.Fail())
    372             return false;
    373         if (reg_ctx->WriteRegister (reg_info, reg_value))
    374         {
    375             SetNeedsUpdate();
    376             return true;
    377         }
    378         else
    379         {
    380             error.SetErrorString("unable to write back to register");
    381             return false;
    382         }
    383     }
    384     else
    385         return ValueObject::SetData(data, error);
    386 }
    387