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 #include "lldb/Core/Value.h" 1278a685aaSJim Ingham #include "lldb/Core/ValueObject.h" 1378a685aaSJim Ingham #include "lldb/Symbol/Type.h" 1478a685aaSJim Ingham #include "lldb/Target/ExecutionContext.h" 1578a685aaSJim Ingham #include "lldb/Target/Target.h" 162f3df613SZachary Turner #include "lldb/Utility/DataExtractor.h" // for DataExtractor 17d821c997SPavel Labath #include "lldb/Utility/Scalar.h" // for Scalar, operator!= 1897206d57SZachary Turner #include "lldb/Utility/Status.h" // for Status 192f3df613SZachary Turner #include "lldb/lldb-types.h" // for addr_t 202f3df613SZachary Turner #include "llvm/Support/ErrorHandling.h" // for llvm_unreachable 212f3df613SZachary Turner 222f3df613SZachary Turner #include <assert.h> // for assert 232f3df613SZachary Turner #include <memory> // for shared_ptr 242f3df613SZachary Turner 252f3df613SZachary Turner namespace lldb_private { 262f3df613SZachary Turner class ExecutionContextScope; 272f3df613SZachary Turner } 2878a685aaSJim Ingham 2958b59f95SJim Ingham using namespace lldb; 3078a685aaSJim Ingham using namespace lldb_private; 3178a685aaSJim Ingham 32b9c1b51eSKate Stone ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope, 3322a2628fSZachary Turner llvm::StringRef name, 3458b59f95SJim Ingham const Address &address, 35b9c1b51eSKate Stone lldb::TypeSP &type_sp) { 3658b59f95SJim Ingham return (new ValueObjectMemory(exe_scope, name, address, type_sp))->GetSP(); 3758b59f95SJim Ingham } 3858b59f95SJim Ingham 39b9c1b51eSKate Stone ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope, 4022a2628fSZachary Turner llvm::StringRef name, 4184c39663SGreg Clayton const Address &address, 42b9c1b51eSKate Stone const CompilerType &ast_type) { 4384c39663SGreg Clayton return (new ValueObjectMemory(exe_scope, name, address, ast_type))->GetSP(); 4484c39663SGreg Clayton } 4584c39663SGreg Clayton 4678a685aaSJim Ingham ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, 4722a2628fSZachary Turner llvm::StringRef name, 4822a2628fSZachary Turner const Address &address, 49b9c1b51eSKate Stone lldb::TypeSP &type_sp) 50b9c1b51eSKate Stone : ValueObject(exe_scope), m_address(address), m_type_sp(type_sp), 51b9c1b51eSKate Stone m_compiler_type() { 5278a685aaSJim Ingham // Do not attempt to construct one of these objects with no variable! 5378a685aaSJim Ingham assert(m_type_sp.get() != NULL); 546f3533fbSEnrico Granata SetName(ConstString(name)); 5578a685aaSJim Ingham m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); 56cc4d0146SGreg Clayton TargetSP target_sp(GetTargetSP()); 57cc4d0146SGreg Clayton lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 58b9c1b51eSKate Stone if (load_address != LLDB_INVALID_ADDRESS) { 5978a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeLoadAddress); 6078a685aaSJim Ingham m_value.GetScalar() = load_address; 61b9c1b51eSKate Stone } else { 6278a685aaSJim Ingham lldb::addr_t file_address = m_address.GetFileAddress(); 63b9c1b51eSKate Stone if (file_address != LLDB_INVALID_ADDRESS) { 6478a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeFileAddress); 6578a685aaSJim Ingham m_value.GetScalar() = file_address; 66b9c1b51eSKate Stone } else { 6778a685aaSJim Ingham m_value.GetScalar() = m_address.GetOffset(); 6878a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeScalar); 6978a685aaSJim Ingham } 7078a685aaSJim Ingham } 7178a685aaSJim Ingham } 7278a685aaSJim Ingham 7384c39663SGreg Clayton ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, 7422a2628fSZachary Turner llvm::StringRef name, 7522a2628fSZachary Turner const Address &address, 76b9c1b51eSKate Stone const CompilerType &ast_type) 77b9c1b51eSKate Stone : ValueObject(exe_scope), m_address(address), m_type_sp(), 78b9c1b51eSKate Stone m_compiler_type(ast_type) { 7984c39663SGreg Clayton // Do not attempt to construct one of these objects with no variable! 803ad353f3SBruce Mitchener assert(m_compiler_type.GetTypeSystem()); 813ad353f3SBruce Mitchener assert(m_compiler_type.GetOpaqueQualType()); 8284c39663SGreg Clayton 83cc4d0146SGreg Clayton TargetSP target_sp(GetTargetSP()); 84cc4d0146SGreg Clayton 856f3533fbSEnrico Granata SetName(ConstString(name)); 86b9c1b51eSKate Stone // m_value.SetContext(Value::eContextTypeClangType, 87b9c1b51eSKate Stone // m_compiler_type.GetOpaqueQualType()); 883ad353f3SBruce Mitchener m_value.SetCompilerType(m_compiler_type); 89cc4d0146SGreg Clayton lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 90b9c1b51eSKate Stone if (load_address != LLDB_INVALID_ADDRESS) { 9184c39663SGreg Clayton m_value.SetValueType(Value::eValueTypeLoadAddress); 9284c39663SGreg Clayton m_value.GetScalar() = load_address; 93b9c1b51eSKate Stone } else { 9484c39663SGreg Clayton lldb::addr_t file_address = m_address.GetFileAddress(); 95b9c1b51eSKate Stone if (file_address != LLDB_INVALID_ADDRESS) { 9684c39663SGreg Clayton m_value.SetValueType(Value::eValueTypeFileAddress); 9784c39663SGreg Clayton m_value.GetScalar() = file_address; 98b9c1b51eSKate Stone } else { 9984c39663SGreg Clayton m_value.GetScalar() = m_address.GetOffset(); 10084c39663SGreg Clayton m_value.SetValueType(Value::eValueTypeScalar); 10184c39663SGreg Clayton } 10284c39663SGreg Clayton } 10384c39663SGreg Clayton } 10484c39663SGreg Clayton 105b9c1b51eSKate Stone ValueObjectMemory::~ValueObjectMemory() {} 10678a685aaSJim Ingham 107b9c1b51eSKate Stone CompilerType ValueObjectMemory::GetCompilerTypeImpl() { 10884c39663SGreg Clayton if (m_type_sp) 10999558cc4SGreg Clayton return m_type_sp->GetForwardCompilerType(); 1103ad353f3SBruce Mitchener return m_compiler_type; 11178a685aaSJim Ingham } 11278a685aaSJim Ingham 113b9c1b51eSKate Stone ConstString ValueObjectMemory::GetTypeName() { 11484c39663SGreg Clayton if (m_type_sp) 11578a685aaSJim Ingham return m_type_sp->GetName(); 1163ad353f3SBruce Mitchener return m_compiler_type.GetConstTypeName(); 11778a685aaSJim Ingham } 11878a685aaSJim Ingham 119b9c1b51eSKate Stone ConstString ValueObjectMemory::GetDisplayTypeName() { 120e8daa2f8SEnrico Granata if (m_type_sp) 12199558cc4SGreg Clayton return m_type_sp->GetForwardCompilerType().GetDisplayTypeName(); 1223ad353f3SBruce Mitchener return m_compiler_type.GetDisplayTypeName(); 123e8daa2f8SEnrico Granata } 124e8daa2f8SEnrico Granata 125b9c1b51eSKate Stone size_t ValueObjectMemory::CalculateNumChildren(uint32_t max) { 126b9c1b51eSKate Stone if (m_type_sp) { 1279ac7a6c5SSiva Chandra auto child_count = m_type_sp->GetNumChildren(true); 1289ac7a6c5SSiva Chandra return child_count <= max ? child_count : max; 1299ac7a6c5SSiva Chandra } 1309ac7a6c5SSiva Chandra 131*eca07c59SAdrian Prantl ExecutionContext exe_ctx(GetExecutionContextRef()); 13284c39663SGreg Clayton const bool omit_empty_base_classes = true; 133*eca07c59SAdrian Prantl auto child_count = 134*eca07c59SAdrian Prantl m_compiler_type.GetNumChildren(omit_empty_base_classes, &exe_ctx); 1359ac7a6c5SSiva Chandra return child_count <= max ? child_count : max; 13678a685aaSJim Ingham } 13778a685aaSJim Ingham 138b9c1b51eSKate Stone uint64_t ValueObjectMemory::GetByteSize() { 13984c39663SGreg Clayton if (m_type_sp) 14078a685aaSJim Ingham return m_type_sp->GetByteSize(); 1413ad353f3SBruce Mitchener return m_compiler_type.GetByteSize(nullptr); 14278a685aaSJim Ingham } 14378a685aaSJim Ingham 144b9c1b51eSKate Stone lldb::ValueType ValueObjectMemory::GetValueType() const { 14578a685aaSJim Ingham // RETHINK: Should this be inherited from somewhere? 14678a685aaSJim Ingham return lldb::eValueTypeVariableGlobal; 14778a685aaSJim Ingham } 14878a685aaSJim Ingham 149b9c1b51eSKate Stone bool ValueObjectMemory::UpdateValue() { 15078a685aaSJim Ingham SetValueIsValid(false); 15178a685aaSJim Ingham m_error.Clear(); 15278a685aaSJim Ingham 153cc4d0146SGreg Clayton ExecutionContext exe_ctx(GetExecutionContextRef()); 15478a685aaSJim Ingham 155c14ee32dSGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 156b9c1b51eSKate Stone if (target) { 157c14ee32dSGreg Clayton m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); 158c14ee32dSGreg Clayton m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); 15978a685aaSJim Ingham } 16078a685aaSJim Ingham 16178a685aaSJim Ingham Value old_value(m_value); 162b9c1b51eSKate Stone if (m_address.IsValid()) { 16378a685aaSJim Ingham Value::ValueType value_type = m_value.GetValueType(); 16478a685aaSJim Ingham 165b9c1b51eSKate Stone switch (value_type) { 16678a685aaSJim Ingham default: 167a322f36cSDavid Blaikie llvm_unreachable("Unhandled expression result value kind..."); 16878a685aaSJim Ingham 16978a685aaSJim Ingham case Value::eValueTypeScalar: 17005097246SAdrian Prantl // The variable value is in the Scalar value inside the m_value. We can 17105097246SAdrian Prantl // point our m_data right to it. 17257ee3067SGreg Clayton m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); 17378a685aaSJim Ingham break; 17478a685aaSJim Ingham 17578a685aaSJim Ingham case Value::eValueTypeFileAddress: 17678a685aaSJim Ingham case Value::eValueTypeLoadAddress: 17778a685aaSJim Ingham case Value::eValueTypeHostAddress: 17805097246SAdrian Prantl // The DWARF expression result was an address in the inferior process. If 17905097246SAdrian Prantl // this variable is an aggregate type, we just need the address as the 18005097246SAdrian Prantl // main value as all child variable objects will rely upon this location 18105097246SAdrian Prantl // and add an offset and then read their own values as needed. If this 18205097246SAdrian Prantl // variable is a simple type, we read all data for it into m_data. Make 18305097246SAdrian Prantl // sure this type has a value before we try and read it 18478a685aaSJim Ingham 18578a685aaSJim Ingham // If we have a file address, convert it to a load address if we can. 186b9c1b51eSKate Stone if (value_type == Value::eValueTypeFileAddress && 187b9c1b51eSKate Stone exe_ctx.GetProcessPtr()) { 188c14ee32dSGreg Clayton lldb::addr_t load_addr = m_address.GetLoadAddress(target); 189b9c1b51eSKate Stone if (load_addr != LLDB_INVALID_ADDRESS) { 19078a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeLoadAddress); 19178a685aaSJim Ingham m_value.GetScalar() = load_addr; 19278a685aaSJim Ingham } 19378a685aaSJim Ingham } 19478a685aaSJim Ingham 195b9c1b51eSKate Stone if (!CanProvideValue()) { 19605097246SAdrian Prantl // this value object represents an aggregate type whose children have 19705097246SAdrian Prantl // values, but this object does not. So we say we are changed if our 19805097246SAdrian Prantl // location has changed. 199b9c1b51eSKate Stone SetValueDidChange(value_type != old_value.GetValueType() || 200b9c1b51eSKate Stone m_value.GetScalar() != old_value.GetScalar()); 201b9c1b51eSKate Stone } else { 20205097246SAdrian Prantl // Copy the Value and set the context to use our Variable so it can 20305097246SAdrian Prantl // extract read its value into m_data appropriately 20478a685aaSJim Ingham Value value(m_value); 20584c39663SGreg Clayton if (m_type_sp) 20678a685aaSJim Ingham value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); 207b9c1b51eSKate Stone else { 208b9c1b51eSKate Stone // value.SetContext(Value::eContextTypeClangType, 209b9c1b51eSKate Stone // m_compiler_type.GetOpaqueQualType()); 2103ad353f3SBruce Mitchener value.SetCompilerType(m_compiler_type); 21157ee3067SGreg Clayton } 21284c39663SGreg Clayton 21357ee3067SGreg Clayton m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); 21478a685aaSJim Ingham } 21578a685aaSJim Ingham break; 21678a685aaSJim Ingham } 21778a685aaSJim Ingham 21878a685aaSJim Ingham SetValueIsValid(m_error.Success()); 21978a685aaSJim Ingham } 22078a685aaSJim Ingham return m_error.Success(); 22178a685aaSJim Ingham } 22278a685aaSJim Ingham 223b9c1b51eSKate Stone bool ValueObjectMemory::IsInScope() { 22478a685aaSJim Ingham // FIXME: Maybe try to read the memory address, and if that works, then 22578a685aaSJim Ingham // we are in scope? 22678a685aaSJim Ingham return true; 22778a685aaSJim Ingham } 22878a685aaSJim Ingham 229b9c1b51eSKate Stone lldb::ModuleSP ValueObjectMemory::GetModule() { return m_address.GetModule(); } 230