178a685aaSJim Ingham //===-- ValueObjectMemory.cpp ---------------------------------*- C++ -*-===// 278a685aaSJim Ingham // 378a685aaSJim Ingham // The LLVM Compiler Infrastructure 478a685aaSJim Ingham // 578a685aaSJim Ingham // This file is distributed under the University of Illinois Open Source 678a685aaSJim Ingham // License. See LICENSE.TXT for details. 778a685aaSJim Ingham // 878a685aaSJim Ingham //===----------------------------------------------------------------------===// 978a685aaSJim Ingham 1078a685aaSJim Ingham 1178a685aaSJim Ingham #include "lldb/Core/ValueObjectMemory.h" 1278a685aaSJim Ingham 1378a685aaSJim Ingham // C Includes 1478a685aaSJim Ingham // C++ Includes 1578a685aaSJim Ingham // Other libraries and framework includes 1678a685aaSJim Ingham // Project includes 1778a685aaSJim Ingham #include "lldb/Core/Module.h" 1878a685aaSJim Ingham #include "lldb/Core/ValueObjectList.h" 1978a685aaSJim Ingham #include "lldb/Core/Value.h" 2078a685aaSJim Ingham #include "lldb/Core/ValueObject.h" 2178a685aaSJim Ingham 2278a685aaSJim Ingham #include "lldb/Symbol/ObjectFile.h" 2378a685aaSJim Ingham #include "lldb/Symbol/SymbolContext.h" 2478a685aaSJim Ingham #include "lldb/Symbol/Type.h" 2578a685aaSJim Ingham #include "lldb/Symbol/Variable.h" 2678a685aaSJim Ingham 2778a685aaSJim Ingham #include "lldb/Target/ExecutionContext.h" 2878a685aaSJim Ingham #include "lldb/Target/Process.h" 2978a685aaSJim Ingham #include "lldb/Target/RegisterContext.h" 3078a685aaSJim Ingham #include "lldb/Target/Target.h" 3178a685aaSJim Ingham #include "lldb/Target/Thread.h" 3278a685aaSJim Ingham 33*58b59f95SJim Ingham using namespace lldb; 3478a685aaSJim Ingham using namespace lldb_private; 3578a685aaSJim Ingham 36*58b59f95SJim Ingham ValueObjectSP 37*58b59f95SJim Ingham ValueObjectMemory::Create (ExecutionContextScope *exe_scope, 38*58b59f95SJim Ingham const char *name, 39*58b59f95SJim Ingham const Address &address, 40*58b59f95SJim Ingham lldb::TypeSP &type_sp) 41*58b59f95SJim Ingham { 42*58b59f95SJim Ingham return (new ValueObjectMemory (exe_scope, name, address, type_sp))->GetSP(); 43*58b59f95SJim Ingham } 44*58b59f95SJim Ingham 4578a685aaSJim Ingham ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope, 4678a685aaSJim Ingham const char *name, 4778a685aaSJim Ingham const Address &address, 4878a685aaSJim Ingham lldb::TypeSP &type_sp) : 4978a685aaSJim Ingham ValueObject(exe_scope), 5078a685aaSJim Ingham m_address (address), 5178a685aaSJim Ingham m_type_sp(type_sp) 5278a685aaSJim Ingham { 5378a685aaSJim Ingham // Do not attempt to construct one of these objects with no variable! 5478a685aaSJim Ingham assert (m_type_sp.get() != NULL); 5578a685aaSJim Ingham SetName (name); 5678a685aaSJim Ingham m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); 5778a685aaSJim Ingham lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTarget()); 5878a685aaSJim Ingham if (load_address != LLDB_INVALID_ADDRESS) 5978a685aaSJim Ingham { 6078a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeLoadAddress); 6178a685aaSJim Ingham m_value.GetScalar() = load_address; 6278a685aaSJim Ingham } 6378a685aaSJim Ingham else 6478a685aaSJim Ingham { 6578a685aaSJim Ingham lldb::addr_t file_address = m_address.GetFileAddress(); 6678a685aaSJim Ingham if (file_address != LLDB_INVALID_ADDRESS) 6778a685aaSJim Ingham { 6878a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeFileAddress); 6978a685aaSJim Ingham m_value.GetScalar() = file_address; 7078a685aaSJim Ingham } 7178a685aaSJim Ingham else 7278a685aaSJim Ingham { 7378a685aaSJim Ingham m_value.GetScalar() = m_address.GetOffset(); 7478a685aaSJim Ingham m_value.SetValueType (Value::eValueTypeScalar); 7578a685aaSJim Ingham } 7678a685aaSJim Ingham } 7778a685aaSJim Ingham } 7878a685aaSJim Ingham 7978a685aaSJim Ingham ValueObjectMemory::~ValueObjectMemory() 8078a685aaSJim Ingham { 8178a685aaSJim Ingham } 8278a685aaSJim Ingham 8378a685aaSJim Ingham lldb::clang_type_t 8478a685aaSJim Ingham ValueObjectMemory::GetClangType () 8578a685aaSJim Ingham { 8678a685aaSJim Ingham return m_type_sp->GetClangForwardType(); 8778a685aaSJim Ingham } 8878a685aaSJim Ingham 8978a685aaSJim Ingham ConstString 9078a685aaSJim Ingham ValueObjectMemory::GetTypeName() 9178a685aaSJim Ingham { 9278a685aaSJim Ingham return m_type_sp->GetName(); 9378a685aaSJim Ingham } 9478a685aaSJim Ingham 9578a685aaSJim Ingham uint32_t 9678a685aaSJim Ingham ValueObjectMemory::CalculateNumChildren() 9778a685aaSJim Ingham { 9878a685aaSJim Ingham return m_type_sp->GetNumChildren(true); 9978a685aaSJim Ingham } 10078a685aaSJim Ingham 10178a685aaSJim Ingham clang::ASTContext * 10278a685aaSJim Ingham ValueObjectMemory::GetClangAST () 10378a685aaSJim Ingham { 10478a685aaSJim Ingham return m_type_sp->GetClangAST(); 10578a685aaSJim Ingham } 10678a685aaSJim Ingham 10778a685aaSJim Ingham size_t 10878a685aaSJim Ingham ValueObjectMemory::GetByteSize() 10978a685aaSJim Ingham { 11078a685aaSJim Ingham return m_type_sp->GetByteSize(); 11178a685aaSJim Ingham } 11278a685aaSJim Ingham 11378a685aaSJim Ingham lldb::ValueType 11478a685aaSJim Ingham ValueObjectMemory::GetValueType() const 11578a685aaSJim Ingham { 11678a685aaSJim Ingham // RETHINK: Should this be inherited from somewhere? 11778a685aaSJim Ingham return lldb::eValueTypeVariableGlobal; 11878a685aaSJim Ingham } 11978a685aaSJim Ingham 12078a685aaSJim Ingham bool 12178a685aaSJim Ingham ValueObjectMemory::UpdateValue () 12278a685aaSJim Ingham { 12378a685aaSJim Ingham SetValueIsValid (false); 12478a685aaSJim Ingham m_error.Clear(); 12578a685aaSJim Ingham 12678a685aaSJim Ingham ExecutionContext exe_ctx (GetExecutionContextScope()); 12778a685aaSJim Ingham 12878a685aaSJim Ingham if (exe_ctx.target) 12978a685aaSJim Ingham { 13078a685aaSJim Ingham m_data.SetByteOrder(exe_ctx.target->GetArchitecture().GetByteOrder()); 13178a685aaSJim Ingham m_data.SetAddressByteSize(exe_ctx.target->GetArchitecture().GetAddressByteSize()); 13278a685aaSJim Ingham } 13378a685aaSJim Ingham 13478a685aaSJim Ingham Value old_value(m_value); 13578a685aaSJim Ingham if (m_address.IsValid()) 13678a685aaSJim Ingham { 13778a685aaSJim Ingham Value::ValueType value_type = m_value.GetValueType(); 13878a685aaSJim Ingham 13978a685aaSJim Ingham switch (value_type) 14078a685aaSJim Ingham { 14178a685aaSJim Ingham default: 14278a685aaSJim Ingham assert(!"Unhandled expression result value kind..."); 14378a685aaSJim Ingham break; 14478a685aaSJim Ingham 14578a685aaSJim Ingham case Value::eValueTypeScalar: 14678a685aaSJim Ingham // The variable value is in the Scalar value inside the m_value. 14778a685aaSJim Ingham // We can point our m_data right to it. 14878a685aaSJim Ingham m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0); 14978a685aaSJim Ingham break; 15078a685aaSJim Ingham 15178a685aaSJim Ingham case Value::eValueTypeFileAddress: 15278a685aaSJim Ingham case Value::eValueTypeLoadAddress: 15378a685aaSJim Ingham case Value::eValueTypeHostAddress: 15478a685aaSJim Ingham // The DWARF expression result was an address in the inferior 15578a685aaSJim Ingham // process. If this variable is an aggregate type, we just need 15678a685aaSJim Ingham // the address as the main value as all child variable objects 15778a685aaSJim Ingham // will rely upon this location and add an offset and then read 15878a685aaSJim Ingham // their own values as needed. If this variable is a simple 15978a685aaSJim Ingham // type, we read all data for it into m_data. 16078a685aaSJim Ingham // Make sure this type has a value before we try and read it 16178a685aaSJim Ingham 16278a685aaSJim Ingham // If we have a file address, convert it to a load address if we can. 16378a685aaSJim Ingham if (value_type == Value::eValueTypeFileAddress && exe_ctx.process) 16478a685aaSJim Ingham { 16578a685aaSJim Ingham lldb::addr_t load_addr = m_address.GetLoadAddress(exe_ctx.target); 16678a685aaSJim Ingham if (load_addr != LLDB_INVALID_ADDRESS) 16778a685aaSJim Ingham { 16878a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeLoadAddress); 16978a685aaSJim Ingham m_value.GetScalar() = load_addr; 17078a685aaSJim Ingham } 17178a685aaSJim Ingham } 17278a685aaSJim Ingham 17378a685aaSJim Ingham if (ClangASTContext::IsAggregateType (GetClangType())) 17478a685aaSJim Ingham { 17578a685aaSJim Ingham // this value object represents an aggregate type whose 17678a685aaSJim Ingham // children have values, but this object does not. So we 17778a685aaSJim Ingham // say we are changed if our location has changed. 17878a685aaSJim Ingham SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); 17978a685aaSJim Ingham } 18078a685aaSJim Ingham else 18178a685aaSJim Ingham { 18278a685aaSJim Ingham // Copy the Value and set the context to use our Variable 18378a685aaSJim Ingham // so it can extract read its value into m_data appropriately 18478a685aaSJim Ingham Value value(m_value); 18578a685aaSJim Ingham value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); 18678a685aaSJim Ingham m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0); 18778a685aaSJim Ingham } 18878a685aaSJim Ingham break; 18978a685aaSJim Ingham } 19078a685aaSJim Ingham 19178a685aaSJim Ingham SetValueIsValid (m_error.Success()); 19278a685aaSJim Ingham } 19378a685aaSJim Ingham return m_error.Success(); 19478a685aaSJim Ingham } 19578a685aaSJim Ingham 19678a685aaSJim Ingham 19778a685aaSJim Ingham 19878a685aaSJim Ingham bool 19978a685aaSJim Ingham ValueObjectMemory::IsInScope () 20078a685aaSJim Ingham { 20178a685aaSJim Ingham // FIXME: Maybe try to read the memory address, and if that works, then 20278a685aaSJim Ingham // we are in scope? 20378a685aaSJim Ingham return true; 20478a685aaSJim Ingham } 20578a685aaSJim Ingham 206