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 12*2f3df613SZachary Turner #include "lldb/Core/ArchSpec.h" // for ArchSpec 13*2f3df613SZachary Turner #include "lldb/Core/Scalar.h" // for Scalar, operator!= 1478a685aaSJim Ingham #include "lldb/Core/Value.h" 1578a685aaSJim Ingham #include "lldb/Core/ValueObject.h" 1678a685aaSJim Ingham #include "lldb/Symbol/Type.h" 1778a685aaSJim Ingham #include "lldb/Target/ExecutionContext.h" 1878a685aaSJim Ingham #include "lldb/Target/Target.h" 19*2f3df613SZachary Turner #include "lldb/Utility/DataExtractor.h" // for DataExtractor 20*2f3df613SZachary Turner #include "lldb/Utility/Error.h" // for Error 21*2f3df613SZachary Turner #include "lldb/lldb-types.h" // for addr_t 22*2f3df613SZachary Turner #include "llvm/Support/ErrorHandling.h" // for llvm_unreachable 23*2f3df613SZachary Turner 24*2f3df613SZachary Turner #include <assert.h> // for assert 25*2f3df613SZachary Turner #include <memory> // for shared_ptr 26*2f3df613SZachary Turner 27*2f3df613SZachary Turner namespace lldb_private { 28*2f3df613SZachary Turner class ExecutionContextScope; 29*2f3df613SZachary Turner } 3078a685aaSJim Ingham 3158b59f95SJim Ingham using namespace lldb; 3278a685aaSJim Ingham using namespace lldb_private; 3378a685aaSJim Ingham 34b9c1b51eSKate Stone ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope, 3522a2628fSZachary Turner llvm::StringRef name, 3658b59f95SJim Ingham const Address &address, 37b9c1b51eSKate Stone lldb::TypeSP &type_sp) { 3858b59f95SJim Ingham return (new ValueObjectMemory(exe_scope, name, address, type_sp))->GetSP(); 3958b59f95SJim Ingham } 4058b59f95SJim Ingham 41b9c1b51eSKate Stone ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope, 4222a2628fSZachary Turner llvm::StringRef name, 4384c39663SGreg Clayton const Address &address, 44b9c1b51eSKate Stone const CompilerType &ast_type) { 4584c39663SGreg Clayton return (new ValueObjectMemory(exe_scope, name, address, ast_type))->GetSP(); 4684c39663SGreg Clayton } 4784c39663SGreg Clayton 4878a685aaSJim Ingham ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, 4922a2628fSZachary Turner llvm::StringRef name, 5022a2628fSZachary Turner const Address &address, 51b9c1b51eSKate Stone lldb::TypeSP &type_sp) 52b9c1b51eSKate Stone : ValueObject(exe_scope), m_address(address), m_type_sp(type_sp), 53b9c1b51eSKate Stone m_compiler_type() { 5478a685aaSJim Ingham // Do not attempt to construct one of these objects with no variable! 5578a685aaSJim Ingham assert(m_type_sp.get() != NULL); 566f3533fbSEnrico Granata SetName(ConstString(name)); 5778a685aaSJim Ingham m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); 58cc4d0146SGreg Clayton TargetSP target_sp(GetTargetSP()); 59cc4d0146SGreg Clayton lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 60b9c1b51eSKate Stone if (load_address != LLDB_INVALID_ADDRESS) { 6178a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeLoadAddress); 6278a685aaSJim Ingham m_value.GetScalar() = load_address; 63b9c1b51eSKate Stone } else { 6478a685aaSJim Ingham lldb::addr_t file_address = m_address.GetFileAddress(); 65b9c1b51eSKate Stone if (file_address != LLDB_INVALID_ADDRESS) { 6678a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeFileAddress); 6778a685aaSJim Ingham m_value.GetScalar() = file_address; 68b9c1b51eSKate Stone } else { 6978a685aaSJim Ingham m_value.GetScalar() = m_address.GetOffset(); 7078a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeScalar); 7178a685aaSJim Ingham } 7278a685aaSJim Ingham } 7378a685aaSJim Ingham } 7478a685aaSJim Ingham 7584c39663SGreg Clayton ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, 7622a2628fSZachary Turner llvm::StringRef name, 7722a2628fSZachary Turner const Address &address, 78b9c1b51eSKate Stone const CompilerType &ast_type) 79b9c1b51eSKate Stone : ValueObject(exe_scope), m_address(address), m_type_sp(), 80b9c1b51eSKate Stone m_compiler_type(ast_type) { 8184c39663SGreg Clayton // Do not attempt to construct one of these objects with no variable! 823ad353f3SBruce Mitchener assert(m_compiler_type.GetTypeSystem()); 833ad353f3SBruce Mitchener assert(m_compiler_type.GetOpaqueQualType()); 8484c39663SGreg Clayton 85cc4d0146SGreg Clayton TargetSP target_sp(GetTargetSP()); 86cc4d0146SGreg Clayton 876f3533fbSEnrico Granata SetName(ConstString(name)); 88b9c1b51eSKate Stone // m_value.SetContext(Value::eContextTypeClangType, 89b9c1b51eSKate Stone // m_compiler_type.GetOpaqueQualType()); 903ad353f3SBruce Mitchener m_value.SetCompilerType(m_compiler_type); 91cc4d0146SGreg Clayton lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 92b9c1b51eSKate Stone if (load_address != LLDB_INVALID_ADDRESS) { 9384c39663SGreg Clayton m_value.SetValueType(Value::eValueTypeLoadAddress); 9484c39663SGreg Clayton m_value.GetScalar() = load_address; 95b9c1b51eSKate Stone } else { 9684c39663SGreg Clayton lldb::addr_t file_address = m_address.GetFileAddress(); 97b9c1b51eSKate Stone if (file_address != LLDB_INVALID_ADDRESS) { 9884c39663SGreg Clayton m_value.SetValueType(Value::eValueTypeFileAddress); 9984c39663SGreg Clayton m_value.GetScalar() = file_address; 100b9c1b51eSKate Stone } else { 10184c39663SGreg Clayton m_value.GetScalar() = m_address.GetOffset(); 10284c39663SGreg Clayton m_value.SetValueType(Value::eValueTypeScalar); 10384c39663SGreg Clayton } 10484c39663SGreg Clayton } 10584c39663SGreg Clayton } 10684c39663SGreg Clayton 107b9c1b51eSKate Stone ValueObjectMemory::~ValueObjectMemory() {} 10878a685aaSJim Ingham 109b9c1b51eSKate Stone CompilerType ValueObjectMemory::GetCompilerTypeImpl() { 11084c39663SGreg Clayton if (m_type_sp) 11199558cc4SGreg Clayton return m_type_sp->GetForwardCompilerType(); 1123ad353f3SBruce Mitchener return m_compiler_type; 11378a685aaSJim Ingham } 11478a685aaSJim Ingham 115b9c1b51eSKate Stone ConstString ValueObjectMemory::GetTypeName() { 11684c39663SGreg Clayton if (m_type_sp) 11778a685aaSJim Ingham return m_type_sp->GetName(); 1183ad353f3SBruce Mitchener return m_compiler_type.GetConstTypeName(); 11978a685aaSJim Ingham } 12078a685aaSJim Ingham 121b9c1b51eSKate Stone ConstString ValueObjectMemory::GetDisplayTypeName() { 122e8daa2f8SEnrico Granata if (m_type_sp) 12399558cc4SGreg Clayton return m_type_sp->GetForwardCompilerType().GetDisplayTypeName(); 1243ad353f3SBruce Mitchener return m_compiler_type.GetDisplayTypeName(); 125e8daa2f8SEnrico Granata } 126e8daa2f8SEnrico Granata 127b9c1b51eSKate Stone size_t ValueObjectMemory::CalculateNumChildren(uint32_t max) { 128b9c1b51eSKate Stone if (m_type_sp) { 1299ac7a6c5SSiva Chandra auto child_count = m_type_sp->GetNumChildren(true); 1309ac7a6c5SSiva Chandra return child_count <= max ? child_count : max; 1319ac7a6c5SSiva Chandra } 1329ac7a6c5SSiva Chandra 13384c39663SGreg Clayton const bool omit_empty_base_classes = true; 1349ac7a6c5SSiva Chandra auto child_count = m_compiler_type.GetNumChildren(omit_empty_base_classes); 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: 17078a685aaSJim Ingham // The variable value is in the Scalar value inside the m_value. 17178a685aaSJim Ingham // We can 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: 17878a685aaSJim Ingham // The DWARF expression result was an address in the inferior 17978a685aaSJim Ingham // process. If this variable is an aggregate type, we just need 18078a685aaSJim Ingham // the address as the main value as all child variable objects 18178a685aaSJim Ingham // will rely upon this location and add an offset and then read 18278a685aaSJim Ingham // their own values as needed. If this variable is a simple 18378a685aaSJim Ingham // type, we read all data for it into m_data. 18478a685aaSJim Ingham // Make sure this type has a value before we try and read it 18578a685aaSJim Ingham 18678a685aaSJim Ingham // If we have a file address, convert it to a load address if we can. 187b9c1b51eSKate Stone if (value_type == Value::eValueTypeFileAddress && 188b9c1b51eSKate Stone exe_ctx.GetProcessPtr()) { 189c14ee32dSGreg Clayton lldb::addr_t load_addr = m_address.GetLoadAddress(target); 190b9c1b51eSKate Stone if (load_addr != LLDB_INVALID_ADDRESS) { 19178a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeLoadAddress); 19278a685aaSJim Ingham m_value.GetScalar() = load_addr; 19378a685aaSJim Ingham } 19478a685aaSJim Ingham } 19578a685aaSJim Ingham 196b9c1b51eSKate Stone if (!CanProvideValue()) { 19778a685aaSJim Ingham // this value object represents an aggregate type whose 19878a685aaSJim Ingham // children have values, but this object does not. So we 19978a685aaSJim Ingham // say we are changed if our location has changed. 200b9c1b51eSKate Stone SetValueDidChange(value_type != old_value.GetValueType() || 201b9c1b51eSKate Stone m_value.GetScalar() != old_value.GetScalar()); 202b9c1b51eSKate Stone } else { 20378a685aaSJim Ingham // Copy the Value and set the context to use our Variable 20478a685aaSJim Ingham // so it can extract read its value into m_data appropriately 20578a685aaSJim Ingham Value value(m_value); 20684c39663SGreg Clayton if (m_type_sp) 20778a685aaSJim Ingham value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); 208b9c1b51eSKate Stone else { 209b9c1b51eSKate Stone // value.SetContext(Value::eContextTypeClangType, 210b9c1b51eSKate Stone // m_compiler_type.GetOpaqueQualType()); 2113ad353f3SBruce Mitchener value.SetCompilerType(m_compiler_type); 21257ee3067SGreg Clayton } 21384c39663SGreg Clayton 21457ee3067SGreg Clayton m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); 21578a685aaSJim Ingham } 21678a685aaSJim Ingham break; 21778a685aaSJim Ingham } 21878a685aaSJim Ingham 21978a685aaSJim Ingham SetValueIsValid(m_error.Success()); 22078a685aaSJim Ingham } 22178a685aaSJim Ingham return m_error.Success(); 22278a685aaSJim Ingham } 22378a685aaSJim Ingham 224b9c1b51eSKate Stone bool ValueObjectMemory::IsInScope() { 22578a685aaSJim Ingham // FIXME: Maybe try to read the memory address, and if that works, then 22678a685aaSJim Ingham // we are in scope? 22778a685aaSJim Ingham return true; 22878a685aaSJim Ingham } 22978a685aaSJim Ingham 230b9c1b51eSKate Stone lldb::ModuleSP ValueObjectMemory::GetModule() { return m_address.GetModule(); } 231