180814287SRaphael Isemann //===-- ValueObjectMemory.cpp ---------------------------------------------===// 278a685aaSJim Ingham // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 678a685aaSJim Ingham // 778a685aaSJim Ingham //===----------------------------------------------------------------------===// 878a685aaSJim Ingham 978a685aaSJim Ingham #include "lldb/Core/ValueObjectMemory.h" 1078a685aaSJim Ingham #include "lldb/Core/Value.h" 1178a685aaSJim Ingham #include "lldb/Core/ValueObject.h" 1278a685aaSJim Ingham #include "lldb/Symbol/Type.h" 1378a685aaSJim Ingham #include "lldb/Target/ExecutionContext.h" 1478a685aaSJim Ingham #include "lldb/Target/Target.h" 15672d2c12SJonas Devlieghere #include "lldb/Utility/DataExtractor.h" 16672d2c12SJonas Devlieghere #include "lldb/Utility/Scalar.h" 17672d2c12SJonas Devlieghere #include "lldb/Utility/Status.h" 18672d2c12SJonas Devlieghere #include "lldb/lldb-types.h" 19672d2c12SJonas Devlieghere #include "llvm/Support/ErrorHandling.h" 202f3df613SZachary Turner 21*76e47d48SRaphael Isemann #include <cassert> 22672d2c12SJonas Devlieghere #include <memory> 232f3df613SZachary Turner 242f3df613SZachary Turner namespace lldb_private { 252f3df613SZachary Turner class ExecutionContextScope; 262f3df613SZachary Turner } 2778a685aaSJim Ingham 2858b59f95SJim Ingham using namespace lldb; 2978a685aaSJim Ingham using namespace lldb_private; 3078a685aaSJim Ingham 31b9c1b51eSKate Stone ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope, 3222a2628fSZachary Turner llvm::StringRef name, 3358b59f95SJim Ingham const Address &address, 34b9c1b51eSKate Stone lldb::TypeSP &type_sp) { 35363f05b8SPavel Labath auto manager_sp = ValueObjectManager::Create(); 36363f05b8SPavel Labath return (new ValueObjectMemory(exe_scope, *manager_sp, name, address, type_sp)) 37363f05b8SPavel Labath ->GetSP(); 3858b59f95SJim Ingham } 3958b59f95SJim Ingham 40b9c1b51eSKate Stone ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope, 4122a2628fSZachary Turner llvm::StringRef name, 4284c39663SGreg Clayton const Address &address, 43b9c1b51eSKate Stone const CompilerType &ast_type) { 44363f05b8SPavel Labath auto manager_sp = ValueObjectManager::Create(); 45363f05b8SPavel Labath return (new ValueObjectMemory(exe_scope, *manager_sp, name, address, 46363f05b8SPavel Labath ast_type)) 47363f05b8SPavel Labath ->GetSP(); 4884c39663SGreg Clayton } 4984c39663SGreg Clayton 5078a685aaSJim Ingham ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, 51363f05b8SPavel Labath ValueObjectManager &manager, 5222a2628fSZachary Turner llvm::StringRef name, 5322a2628fSZachary Turner const Address &address, 54b9c1b51eSKate Stone lldb::TypeSP &type_sp) 55363f05b8SPavel Labath : ValueObject(exe_scope, manager), m_address(address), m_type_sp(type_sp), 56b9c1b51eSKate Stone m_compiler_type() { 5778a685aaSJim Ingham // Do not attempt to construct one of these objects with no variable! 58248a1305SKonrad Kleine assert(m_type_sp.get() != nullptr); 596f3533fbSEnrico Granata SetName(ConstString(name)); 60057efa99SAdrian Prantl m_value.SetContext(Value::ContextType::LLDBType, m_type_sp.get()); 61cc4d0146SGreg Clayton TargetSP target_sp(GetTargetSP()); 62cc4d0146SGreg Clayton lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 63b9c1b51eSKate Stone if (load_address != LLDB_INVALID_ADDRESS) { 64057efa99SAdrian Prantl m_value.SetValueType(Value::ValueType::LoadAddress); 6578a685aaSJim Ingham m_value.GetScalar() = load_address; 66b9c1b51eSKate Stone } else { 6778a685aaSJim Ingham lldb::addr_t file_address = m_address.GetFileAddress(); 68b9c1b51eSKate Stone if (file_address != LLDB_INVALID_ADDRESS) { 69057efa99SAdrian Prantl m_value.SetValueType(Value::ValueType::FileAddress); 7078a685aaSJim Ingham m_value.GetScalar() = file_address; 71b9c1b51eSKate Stone } else { 7278a685aaSJim Ingham m_value.GetScalar() = m_address.GetOffset(); 73057efa99SAdrian Prantl m_value.SetValueType(Value::ValueType::Scalar); 7478a685aaSJim Ingham } 7578a685aaSJim Ingham } 7678a685aaSJim Ingham } 7778a685aaSJim Ingham 7884c39663SGreg Clayton ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, 79363f05b8SPavel Labath ValueObjectManager &manager, 8022a2628fSZachary Turner llvm::StringRef name, 8122a2628fSZachary Turner const Address &address, 82b9c1b51eSKate Stone const CompilerType &ast_type) 83363f05b8SPavel Labath : ValueObject(exe_scope, manager), m_address(address), m_type_sp(), 84b9c1b51eSKate Stone m_compiler_type(ast_type) { 8584c39663SGreg Clayton // Do not attempt to construct one of these objects with no variable! 863ad353f3SBruce Mitchener assert(m_compiler_type.GetTypeSystem()); 873ad353f3SBruce Mitchener assert(m_compiler_type.GetOpaqueQualType()); 8884c39663SGreg Clayton 89cc4d0146SGreg Clayton TargetSP target_sp(GetTargetSP()); 90cc4d0146SGreg Clayton 916f3533fbSEnrico Granata SetName(ConstString(name)); 923ad353f3SBruce Mitchener m_value.SetCompilerType(m_compiler_type); 93cc4d0146SGreg Clayton lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 94b9c1b51eSKate Stone if (load_address != LLDB_INVALID_ADDRESS) { 95057efa99SAdrian Prantl m_value.SetValueType(Value::ValueType::LoadAddress); 9684c39663SGreg Clayton m_value.GetScalar() = load_address; 97b9c1b51eSKate Stone } else { 9884c39663SGreg Clayton lldb::addr_t file_address = m_address.GetFileAddress(); 99b9c1b51eSKate Stone if (file_address != LLDB_INVALID_ADDRESS) { 100057efa99SAdrian Prantl m_value.SetValueType(Value::ValueType::FileAddress); 10184c39663SGreg Clayton m_value.GetScalar() = file_address; 102b9c1b51eSKate Stone } else { 10384c39663SGreg Clayton m_value.GetScalar() = m_address.GetOffset(); 104057efa99SAdrian Prantl m_value.SetValueType(Value::ValueType::Scalar); 10584c39663SGreg Clayton } 10684c39663SGreg Clayton } 10784c39663SGreg Clayton } 10884c39663SGreg Clayton 109b9c1b51eSKate Stone ValueObjectMemory::~ValueObjectMemory() {} 11078a685aaSJim Ingham 111b9c1b51eSKate Stone CompilerType ValueObjectMemory::GetCompilerTypeImpl() { 11284c39663SGreg Clayton if (m_type_sp) 11399558cc4SGreg Clayton return m_type_sp->GetForwardCompilerType(); 1143ad353f3SBruce Mitchener return m_compiler_type; 11578a685aaSJim Ingham } 11678a685aaSJim Ingham 117b9c1b51eSKate Stone ConstString ValueObjectMemory::GetTypeName() { 11884c39663SGreg Clayton if (m_type_sp) 11978a685aaSJim Ingham return m_type_sp->GetName(); 12030ce956aSRaphael Isemann return m_compiler_type.GetTypeName(); 12178a685aaSJim Ingham } 12278a685aaSJim Ingham 123b9c1b51eSKate Stone ConstString ValueObjectMemory::GetDisplayTypeName() { 124e8daa2f8SEnrico Granata if (m_type_sp) 12599558cc4SGreg Clayton return m_type_sp->GetForwardCompilerType().GetDisplayTypeName(); 1263ad353f3SBruce Mitchener return m_compiler_type.GetDisplayTypeName(); 127e8daa2f8SEnrico Granata } 128e8daa2f8SEnrico Granata 129b9c1b51eSKate Stone size_t ValueObjectMemory::CalculateNumChildren(uint32_t max) { 130b9c1b51eSKate Stone if (m_type_sp) { 1319ac7a6c5SSiva Chandra auto child_count = m_type_sp->GetNumChildren(true); 1329ac7a6c5SSiva Chandra return child_count <= max ? child_count : max; 1339ac7a6c5SSiva Chandra } 1349ac7a6c5SSiva Chandra 135eca07c59SAdrian Prantl ExecutionContext exe_ctx(GetExecutionContextRef()); 13684c39663SGreg Clayton const bool omit_empty_base_classes = true; 137eca07c59SAdrian Prantl auto child_count = 138eca07c59SAdrian Prantl m_compiler_type.GetNumChildren(omit_empty_base_classes, &exe_ctx); 1399ac7a6c5SSiva Chandra return child_count <= max ? child_count : max; 14078a685aaSJim Ingham } 14178a685aaSJim Ingham 142113f56fbSAdrian Prantl llvm::Optional<uint64_t> ValueObjectMemory::GetByteSize() { 14302f58373SAdrian Prantl ExecutionContext exe_ctx(GetExecutionContextRef()); 14484c39663SGreg Clayton if (m_type_sp) 145113f56fbSAdrian Prantl return m_type_sp->GetByteSize(exe_ctx.GetBestExecutionContextScope()); 146113f56fbSAdrian Prantl return m_compiler_type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); 14778a685aaSJim Ingham } 14878a685aaSJim Ingham 149b9c1b51eSKate Stone lldb::ValueType ValueObjectMemory::GetValueType() const { 15078a685aaSJim Ingham // RETHINK: Should this be inherited from somewhere? 15178a685aaSJim Ingham return lldb::eValueTypeVariableGlobal; 15278a685aaSJim Ingham } 15378a685aaSJim Ingham 154b9c1b51eSKate Stone bool ValueObjectMemory::UpdateValue() { 15578a685aaSJim Ingham SetValueIsValid(false); 15678a685aaSJim Ingham m_error.Clear(); 15778a685aaSJim Ingham 158cc4d0146SGreg Clayton ExecutionContext exe_ctx(GetExecutionContextRef()); 15978a685aaSJim Ingham 160c14ee32dSGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 161b9c1b51eSKate Stone if (target) { 162c14ee32dSGreg Clayton m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); 163c14ee32dSGreg Clayton m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); 16478a685aaSJim Ingham } 16578a685aaSJim Ingham 16678a685aaSJim Ingham Value old_value(m_value); 167b9c1b51eSKate Stone if (m_address.IsValid()) { 16878a685aaSJim Ingham Value::ValueType value_type = m_value.GetValueType(); 16978a685aaSJim Ingham 170b9c1b51eSKate Stone switch (value_type) { 171057efa99SAdrian Prantl case Value::ValueType::Invalid: 172057efa99SAdrian Prantl m_error.SetErrorString("Invalid value"); 173057efa99SAdrian Prantl return false; 174057efa99SAdrian Prantl case Value::ValueType::Scalar: 17505097246SAdrian Prantl // The variable value is in the Scalar value inside the m_value. We can 17605097246SAdrian Prantl // point our m_data right to it. 177d9cbd2acSAdrian Prantl m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); 17878a685aaSJim Ingham break; 17978a685aaSJim Ingham 180057efa99SAdrian Prantl case Value::ValueType::FileAddress: 181057efa99SAdrian Prantl case Value::ValueType::LoadAddress: 182057efa99SAdrian Prantl case Value::ValueType::HostAddress: 18305097246SAdrian Prantl // The DWARF expression result was an address in the inferior process. If 18405097246SAdrian Prantl // this variable is an aggregate type, we just need the address as the 18505097246SAdrian Prantl // main value as all child variable objects will rely upon this location 18605097246SAdrian Prantl // and add an offset and then read their own values as needed. If this 18705097246SAdrian Prantl // variable is a simple type, we read all data for it into m_data. Make 18805097246SAdrian Prantl // sure this type has a value before we try and read it 18978a685aaSJim Ingham 19078a685aaSJim Ingham // If we have a file address, convert it to a load address if we can. 191057efa99SAdrian Prantl if (value_type == Value::ValueType::FileAddress && 192b9c1b51eSKate Stone exe_ctx.GetProcessPtr()) { 193c14ee32dSGreg Clayton lldb::addr_t load_addr = m_address.GetLoadAddress(target); 194b9c1b51eSKate Stone if (load_addr != LLDB_INVALID_ADDRESS) { 195057efa99SAdrian Prantl m_value.SetValueType(Value::ValueType::LoadAddress); 19678a685aaSJim Ingham m_value.GetScalar() = load_addr; 19778a685aaSJim Ingham } 19878a685aaSJim Ingham } 19978a685aaSJim Ingham 200b9c1b51eSKate Stone if (!CanProvideValue()) { 20105097246SAdrian Prantl // this value object represents an aggregate type whose children have 20205097246SAdrian Prantl // values, but this object does not. So we say we are changed if our 20305097246SAdrian Prantl // location has changed. 204b9c1b51eSKate Stone SetValueDidChange(value_type != old_value.GetValueType() || 205b9c1b51eSKate Stone m_value.GetScalar() != old_value.GetScalar()); 206b9c1b51eSKate Stone } else { 20705097246SAdrian Prantl // Copy the Value and set the context to use our Variable so it can 20805097246SAdrian Prantl // extract read its value into m_data appropriately 20978a685aaSJim Ingham Value value(m_value); 21084c39663SGreg Clayton if (m_type_sp) 211057efa99SAdrian Prantl value.SetContext(Value::ContextType::LLDBType, m_type_sp.get()); 212b9c1b51eSKate Stone else { 2133ad353f3SBruce Mitchener value.SetCompilerType(m_compiler_type); 21457ee3067SGreg Clayton } 21584c39663SGreg Clayton 216d9cbd2acSAdrian Prantl m_error = value.GetValueAsData(&exe_ctx, m_data, 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