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 #include "lldb/Core/ValueObjectMemory.h" 1178a685aaSJim Ingham 1278a685aaSJim Ingham // C Includes 1378a685aaSJim Ingham // C++ Includes 1478a685aaSJim Ingham // Other libraries and framework includes 1578a685aaSJim Ingham // Project includes 1678a685aaSJim Ingham #include "lldb/Core/Module.h" 1778a685aaSJim Ingham #include "lldb/Core/Value.h" 1878a685aaSJim Ingham #include "lldb/Core/ValueObject.h" 19b9c1b51eSKate Stone #include "lldb/Core/ValueObjectList.h" 2078a685aaSJim Ingham 2178a685aaSJim Ingham #include "lldb/Symbol/ObjectFile.h" 2278a685aaSJim Ingham #include "lldb/Symbol/SymbolContext.h" 2378a685aaSJim Ingham #include "lldb/Symbol/Type.h" 2478a685aaSJim Ingham #include "lldb/Symbol/Variable.h" 2578a685aaSJim Ingham 2678a685aaSJim Ingham #include "lldb/Target/ExecutionContext.h" 2778a685aaSJim Ingham #include "lldb/Target/Process.h" 2878a685aaSJim Ingham #include "lldb/Target/RegisterContext.h" 2978a685aaSJim Ingham #include "lldb/Target/Target.h" 3078a685aaSJim Ingham #include "lldb/Target/Thread.h" 3178a685aaSJim Ingham 3258b59f95SJim Ingham using namespace lldb; 3378a685aaSJim Ingham using namespace lldb_private; 3478a685aaSJim Ingham 35b9c1b51eSKate Stone ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope, 36*22a2628fSZachary Turner llvm::StringRef name, 3758b59f95SJim Ingham const Address &address, 38b9c1b51eSKate Stone lldb::TypeSP &type_sp) { 3958b59f95SJim Ingham return (new ValueObjectMemory(exe_scope, name, address, type_sp))->GetSP(); 4058b59f95SJim Ingham } 4158b59f95SJim Ingham 42b9c1b51eSKate Stone ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope, 43*22a2628fSZachary Turner llvm::StringRef name, 4484c39663SGreg Clayton const Address &address, 45b9c1b51eSKate Stone const CompilerType &ast_type) { 4684c39663SGreg Clayton return (new ValueObjectMemory(exe_scope, name, address, ast_type))->GetSP(); 4784c39663SGreg Clayton } 4884c39663SGreg Clayton 4978a685aaSJim Ingham ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, 50*22a2628fSZachary Turner llvm::StringRef name, 51*22a2628fSZachary Turner const Address &address, 52b9c1b51eSKate Stone lldb::TypeSP &type_sp) 53b9c1b51eSKate Stone : ValueObject(exe_scope), m_address(address), m_type_sp(type_sp), 54b9c1b51eSKate Stone m_compiler_type() { 5578a685aaSJim Ingham // Do not attempt to construct one of these objects with no variable! 5678a685aaSJim Ingham assert(m_type_sp.get() != NULL); 576f3533fbSEnrico Granata SetName(ConstString(name)); 5878a685aaSJim Ingham m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); 59cc4d0146SGreg Clayton TargetSP target_sp(GetTargetSP()); 60cc4d0146SGreg Clayton lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 61b9c1b51eSKate Stone if (load_address != LLDB_INVALID_ADDRESS) { 6278a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeLoadAddress); 6378a685aaSJim Ingham m_value.GetScalar() = load_address; 64b9c1b51eSKate Stone } else { 6578a685aaSJim Ingham lldb::addr_t file_address = m_address.GetFileAddress(); 66b9c1b51eSKate Stone if (file_address != LLDB_INVALID_ADDRESS) { 6778a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeFileAddress); 6878a685aaSJim Ingham m_value.GetScalar() = file_address; 69b9c1b51eSKate Stone } else { 7078a685aaSJim Ingham m_value.GetScalar() = m_address.GetOffset(); 7178a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeScalar); 7278a685aaSJim Ingham } 7378a685aaSJim Ingham } 7478a685aaSJim Ingham } 7578a685aaSJim Ingham 7684c39663SGreg Clayton ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, 77*22a2628fSZachary Turner llvm::StringRef name, 78*22a2628fSZachary Turner const Address &address, 79b9c1b51eSKate Stone const CompilerType &ast_type) 80b9c1b51eSKate Stone : ValueObject(exe_scope), m_address(address), m_type_sp(), 81b9c1b51eSKate Stone m_compiler_type(ast_type) { 8284c39663SGreg Clayton // Do not attempt to construct one of these objects with no variable! 833ad353f3SBruce Mitchener assert(m_compiler_type.GetTypeSystem()); 843ad353f3SBruce Mitchener assert(m_compiler_type.GetOpaqueQualType()); 8584c39663SGreg Clayton 86cc4d0146SGreg Clayton TargetSP target_sp(GetTargetSP()); 87cc4d0146SGreg Clayton 886f3533fbSEnrico Granata SetName(ConstString(name)); 89b9c1b51eSKate Stone // m_value.SetContext(Value::eContextTypeClangType, 90b9c1b51eSKate Stone // m_compiler_type.GetOpaqueQualType()); 913ad353f3SBruce Mitchener m_value.SetCompilerType(m_compiler_type); 92cc4d0146SGreg Clayton lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 93b9c1b51eSKate Stone if (load_address != LLDB_INVALID_ADDRESS) { 9484c39663SGreg Clayton m_value.SetValueType(Value::eValueTypeLoadAddress); 9584c39663SGreg Clayton m_value.GetScalar() = load_address; 96b9c1b51eSKate Stone } else { 9784c39663SGreg Clayton lldb::addr_t file_address = m_address.GetFileAddress(); 98b9c1b51eSKate Stone if (file_address != LLDB_INVALID_ADDRESS) { 9984c39663SGreg Clayton m_value.SetValueType(Value::eValueTypeFileAddress); 10084c39663SGreg Clayton m_value.GetScalar() = file_address; 101b9c1b51eSKate Stone } else { 10284c39663SGreg Clayton m_value.GetScalar() = m_address.GetOffset(); 10384c39663SGreg Clayton m_value.SetValueType(Value::eValueTypeScalar); 10484c39663SGreg Clayton } 10584c39663SGreg Clayton } 10684c39663SGreg Clayton } 10784c39663SGreg Clayton 108b9c1b51eSKate Stone ValueObjectMemory::~ValueObjectMemory() {} 10978a685aaSJim Ingham 110b9c1b51eSKate Stone CompilerType ValueObjectMemory::GetCompilerTypeImpl() { 11184c39663SGreg Clayton if (m_type_sp) 11299558cc4SGreg Clayton return m_type_sp->GetForwardCompilerType(); 1133ad353f3SBruce Mitchener return m_compiler_type; 11478a685aaSJim Ingham } 11578a685aaSJim Ingham 116b9c1b51eSKate Stone ConstString ValueObjectMemory::GetTypeName() { 11784c39663SGreg Clayton if (m_type_sp) 11878a685aaSJim Ingham return m_type_sp->GetName(); 1193ad353f3SBruce Mitchener return m_compiler_type.GetConstTypeName(); 12078a685aaSJim Ingham } 12178a685aaSJim Ingham 122b9c1b51eSKate Stone ConstString ValueObjectMemory::GetDisplayTypeName() { 123e8daa2f8SEnrico Granata if (m_type_sp) 12499558cc4SGreg Clayton return m_type_sp->GetForwardCompilerType().GetDisplayTypeName(); 1253ad353f3SBruce Mitchener return m_compiler_type.GetDisplayTypeName(); 126e8daa2f8SEnrico Granata } 127e8daa2f8SEnrico Granata 128b9c1b51eSKate Stone size_t ValueObjectMemory::CalculateNumChildren(uint32_t max) { 129b9c1b51eSKate Stone if (m_type_sp) { 1309ac7a6c5SSiva Chandra auto child_count = m_type_sp->GetNumChildren(true); 1319ac7a6c5SSiva Chandra return child_count <= max ? child_count : max; 1329ac7a6c5SSiva Chandra } 1339ac7a6c5SSiva Chandra 13484c39663SGreg Clayton const bool omit_empty_base_classes = true; 1359ac7a6c5SSiva Chandra auto child_count = m_compiler_type.GetNumChildren(omit_empty_base_classes); 1369ac7a6c5SSiva Chandra return child_count <= max ? child_count : max; 13778a685aaSJim Ingham } 13878a685aaSJim Ingham 139b9c1b51eSKate Stone uint64_t ValueObjectMemory::GetByteSize() { 14084c39663SGreg Clayton if (m_type_sp) 14178a685aaSJim Ingham return m_type_sp->GetByteSize(); 1423ad353f3SBruce Mitchener return m_compiler_type.GetByteSize(nullptr); 14378a685aaSJim Ingham } 14478a685aaSJim Ingham 145b9c1b51eSKate Stone lldb::ValueType ValueObjectMemory::GetValueType() const { 14678a685aaSJim Ingham // RETHINK: Should this be inherited from somewhere? 14778a685aaSJim Ingham return lldb::eValueTypeVariableGlobal; 14878a685aaSJim Ingham } 14978a685aaSJim Ingham 150b9c1b51eSKate Stone bool ValueObjectMemory::UpdateValue() { 15178a685aaSJim Ingham SetValueIsValid(false); 15278a685aaSJim Ingham m_error.Clear(); 15378a685aaSJim Ingham 154cc4d0146SGreg Clayton ExecutionContext exe_ctx(GetExecutionContextRef()); 15578a685aaSJim Ingham 156c14ee32dSGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 157b9c1b51eSKate Stone if (target) { 158c14ee32dSGreg Clayton m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); 159c14ee32dSGreg Clayton m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); 16078a685aaSJim Ingham } 16178a685aaSJim Ingham 16278a685aaSJim Ingham Value old_value(m_value); 163b9c1b51eSKate Stone if (m_address.IsValid()) { 16478a685aaSJim Ingham Value::ValueType value_type = m_value.GetValueType(); 16578a685aaSJim Ingham 166b9c1b51eSKate Stone switch (value_type) { 16778a685aaSJim Ingham default: 16878a685aaSJim Ingham assert(!"Unhandled expression result value kind..."); 16978a685aaSJim Ingham break; 17078a685aaSJim Ingham 17178a685aaSJim Ingham case Value::eValueTypeScalar: 17278a685aaSJim Ingham // The variable value is in the Scalar value inside the m_value. 17378a685aaSJim Ingham // We can point our m_data right to it. 17457ee3067SGreg Clayton m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); 17578a685aaSJim Ingham break; 17678a685aaSJim Ingham 17778a685aaSJim Ingham case Value::eValueTypeFileAddress: 17878a685aaSJim Ingham case Value::eValueTypeLoadAddress: 17978a685aaSJim Ingham case Value::eValueTypeHostAddress: 18078a685aaSJim Ingham // The DWARF expression result was an address in the inferior 18178a685aaSJim Ingham // process. If this variable is an aggregate type, we just need 18278a685aaSJim Ingham // the address as the main value as all child variable objects 18378a685aaSJim Ingham // will rely upon this location and add an offset and then read 18478a685aaSJim Ingham // their own values as needed. If this variable is a simple 18578a685aaSJim Ingham // type, we read all data for it into m_data. 18678a685aaSJim Ingham // Make sure this type has a value before we try and read it 18778a685aaSJim Ingham 18878a685aaSJim Ingham // If we have a file address, convert it to a load address if we can. 189b9c1b51eSKate Stone if (value_type == Value::eValueTypeFileAddress && 190b9c1b51eSKate Stone exe_ctx.GetProcessPtr()) { 191c14ee32dSGreg Clayton lldb::addr_t load_addr = m_address.GetLoadAddress(target); 192b9c1b51eSKate Stone if (load_addr != LLDB_INVALID_ADDRESS) { 19378a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeLoadAddress); 19478a685aaSJim Ingham m_value.GetScalar() = load_addr; 19578a685aaSJim Ingham } 19678a685aaSJim Ingham } 19778a685aaSJim Ingham 198b9c1b51eSKate Stone if (!CanProvideValue()) { 19978a685aaSJim Ingham // this value object represents an aggregate type whose 20078a685aaSJim Ingham // children have values, but this object does not. So we 20178a685aaSJim Ingham // say we are changed if our location has changed. 202b9c1b51eSKate Stone SetValueDidChange(value_type != old_value.GetValueType() || 203b9c1b51eSKate Stone m_value.GetScalar() != old_value.GetScalar()); 204b9c1b51eSKate Stone } else { 20578a685aaSJim Ingham // Copy the Value and set the context to use our Variable 20678a685aaSJim Ingham // so it can extract read its value into m_data appropriately 20778a685aaSJim Ingham Value value(m_value); 20884c39663SGreg Clayton if (m_type_sp) 20978a685aaSJim Ingham value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); 210b9c1b51eSKate Stone else { 211b9c1b51eSKate Stone // value.SetContext(Value::eContextTypeClangType, 212b9c1b51eSKate Stone // m_compiler_type.GetOpaqueQualType()); 2133ad353f3SBruce Mitchener value.SetCompilerType(m_compiler_type); 21457ee3067SGreg Clayton } 21584c39663SGreg Clayton 21657ee3067SGreg Clayton m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); 21778a685aaSJim Ingham } 21878a685aaSJim Ingham break; 21978a685aaSJim Ingham } 22078a685aaSJim Ingham 22178a685aaSJim Ingham SetValueIsValid(m_error.Success()); 22278a685aaSJim Ingham } 22378a685aaSJim Ingham return m_error.Success(); 22478a685aaSJim Ingham } 22578a685aaSJim Ingham 226b9c1b51eSKate Stone bool ValueObjectMemory::IsInScope() { 22778a685aaSJim Ingham // FIXME: Maybe try to read the memory address, and if that works, then 22878a685aaSJim Ingham // we are in scope? 22978a685aaSJim Ingham return true; 23078a685aaSJim Ingham } 23178a685aaSJim Ingham 232b9c1b51eSKate Stone lldb::ModuleSP ValueObjectMemory::GetModule() { return m_address.GetModule(); } 233