178a685aaSJim Ingham //===-- ValueObjectMemory.cpp ---------------------------------*- C++ -*-===// 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 21672d2c12SJonas Devlieghere #include <assert.h> 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) { 3558b59f95SJim Ingham return (new ValueObjectMemory(exe_scope, name, address, type_sp))->GetSP(); 3658b59f95SJim Ingham } 3758b59f95SJim Ingham 38b9c1b51eSKate Stone ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope, 3922a2628fSZachary Turner llvm::StringRef name, 4084c39663SGreg Clayton const Address &address, 41b9c1b51eSKate Stone const CompilerType &ast_type) { 4284c39663SGreg Clayton return (new ValueObjectMemory(exe_scope, name, address, ast_type))->GetSP(); 4384c39663SGreg Clayton } 4484c39663SGreg Clayton 4578a685aaSJim Ingham ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, 4622a2628fSZachary Turner llvm::StringRef name, 4722a2628fSZachary Turner const Address &address, 48b9c1b51eSKate Stone lldb::TypeSP &type_sp) 49b9c1b51eSKate Stone : ValueObject(exe_scope), m_address(address), m_type_sp(type_sp), 50b9c1b51eSKate Stone m_compiler_type() { 5178a685aaSJim Ingham // Do not attempt to construct one of these objects with no variable! 52248a1305SKonrad Kleine assert(m_type_sp.get() != nullptr); 536f3533fbSEnrico Granata SetName(ConstString(name)); 5478a685aaSJim Ingham m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); 55cc4d0146SGreg Clayton TargetSP target_sp(GetTargetSP()); 56cc4d0146SGreg Clayton lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 57b9c1b51eSKate Stone if (load_address != LLDB_INVALID_ADDRESS) { 5878a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeLoadAddress); 5978a685aaSJim Ingham m_value.GetScalar() = load_address; 60b9c1b51eSKate Stone } else { 6178a685aaSJim Ingham lldb::addr_t file_address = m_address.GetFileAddress(); 62b9c1b51eSKate Stone if (file_address != LLDB_INVALID_ADDRESS) { 6378a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeFileAddress); 6478a685aaSJim Ingham m_value.GetScalar() = file_address; 65b9c1b51eSKate Stone } else { 6678a685aaSJim Ingham m_value.GetScalar() = m_address.GetOffset(); 6778a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeScalar); 6878a685aaSJim Ingham } 6978a685aaSJim Ingham } 7078a685aaSJim Ingham } 7178a685aaSJim Ingham 7284c39663SGreg Clayton ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, 7322a2628fSZachary Turner llvm::StringRef name, 7422a2628fSZachary Turner const Address &address, 75b9c1b51eSKate Stone const CompilerType &ast_type) 76b9c1b51eSKate Stone : ValueObject(exe_scope), m_address(address), m_type_sp(), 77b9c1b51eSKate Stone m_compiler_type(ast_type) { 7884c39663SGreg Clayton // Do not attempt to construct one of these objects with no variable! 793ad353f3SBruce Mitchener assert(m_compiler_type.GetTypeSystem()); 803ad353f3SBruce Mitchener assert(m_compiler_type.GetOpaqueQualType()); 8184c39663SGreg Clayton 82cc4d0146SGreg Clayton TargetSP target_sp(GetTargetSP()); 83cc4d0146SGreg Clayton 846f3533fbSEnrico Granata SetName(ConstString(name)); 85b9c1b51eSKate Stone // m_value.SetContext(Value::eContextTypeClangType, 86b9c1b51eSKate Stone // m_compiler_type.GetOpaqueQualType()); 873ad353f3SBruce Mitchener m_value.SetCompilerType(m_compiler_type); 88cc4d0146SGreg Clayton lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 89b9c1b51eSKate Stone if (load_address != LLDB_INVALID_ADDRESS) { 9084c39663SGreg Clayton m_value.SetValueType(Value::eValueTypeLoadAddress); 9184c39663SGreg Clayton m_value.GetScalar() = load_address; 92b9c1b51eSKate Stone } else { 9384c39663SGreg Clayton lldb::addr_t file_address = m_address.GetFileAddress(); 94b9c1b51eSKate Stone if (file_address != LLDB_INVALID_ADDRESS) { 9584c39663SGreg Clayton m_value.SetValueType(Value::eValueTypeFileAddress); 9684c39663SGreg Clayton m_value.GetScalar() = file_address; 97b9c1b51eSKate Stone } else { 9884c39663SGreg Clayton m_value.GetScalar() = m_address.GetOffset(); 9984c39663SGreg Clayton m_value.SetValueType(Value::eValueTypeScalar); 10084c39663SGreg Clayton } 10184c39663SGreg Clayton } 10284c39663SGreg Clayton } 10384c39663SGreg Clayton 104b9c1b51eSKate Stone ValueObjectMemory::~ValueObjectMemory() {} 10578a685aaSJim Ingham 106b9c1b51eSKate Stone CompilerType ValueObjectMemory::GetCompilerTypeImpl() { 10784c39663SGreg Clayton if (m_type_sp) 10899558cc4SGreg Clayton return m_type_sp->GetForwardCompilerType(); 1093ad353f3SBruce Mitchener return m_compiler_type; 11078a685aaSJim Ingham } 11178a685aaSJim Ingham 112b9c1b51eSKate Stone ConstString ValueObjectMemory::GetTypeName() { 11384c39663SGreg Clayton if (m_type_sp) 11478a685aaSJim Ingham return m_type_sp->GetName(); 1153ad353f3SBruce Mitchener return m_compiler_type.GetConstTypeName(); 11678a685aaSJim Ingham } 11778a685aaSJim Ingham 118b9c1b51eSKate Stone ConstString ValueObjectMemory::GetDisplayTypeName() { 119e8daa2f8SEnrico Granata if (m_type_sp) 12099558cc4SGreg Clayton return m_type_sp->GetForwardCompilerType().GetDisplayTypeName(); 1213ad353f3SBruce Mitchener return m_compiler_type.GetDisplayTypeName(); 122e8daa2f8SEnrico Granata } 123e8daa2f8SEnrico Granata 124b9c1b51eSKate Stone size_t ValueObjectMemory::CalculateNumChildren(uint32_t max) { 125b9c1b51eSKate Stone if (m_type_sp) { 1269ac7a6c5SSiva Chandra auto child_count = m_type_sp->GetNumChildren(true); 1279ac7a6c5SSiva Chandra return child_count <= max ? child_count : max; 1289ac7a6c5SSiva Chandra } 1299ac7a6c5SSiva Chandra 130eca07c59SAdrian Prantl ExecutionContext exe_ctx(GetExecutionContextRef()); 13184c39663SGreg Clayton const bool omit_empty_base_classes = true; 132eca07c59SAdrian Prantl auto child_count = 133eca07c59SAdrian Prantl m_compiler_type.GetNumChildren(omit_empty_base_classes, &exe_ctx); 1349ac7a6c5SSiva Chandra return child_count <= max ? child_count : max; 13578a685aaSJim Ingham } 13678a685aaSJim Ingham 137b9c1b51eSKate Stone uint64_t ValueObjectMemory::GetByteSize() { 13884c39663SGreg Clayton if (m_type_sp) 139d13777aaSAdrian Prantl return m_type_sp->GetByteSize().getValueOr(0); 140d13777aaSAdrian Prantl return m_compiler_type.GetByteSize(nullptr).getValueOr(0); 14178a685aaSJim Ingham } 14278a685aaSJim Ingham 143b9c1b51eSKate Stone lldb::ValueType ValueObjectMemory::GetValueType() const { 14478a685aaSJim Ingham // RETHINK: Should this be inherited from somewhere? 14578a685aaSJim Ingham return lldb::eValueTypeVariableGlobal; 14678a685aaSJim Ingham } 14778a685aaSJim Ingham 148b9c1b51eSKate Stone bool ValueObjectMemory::UpdateValue() { 14978a685aaSJim Ingham SetValueIsValid(false); 15078a685aaSJim Ingham m_error.Clear(); 15178a685aaSJim Ingham 152cc4d0146SGreg Clayton ExecutionContext exe_ctx(GetExecutionContextRef()); 15378a685aaSJim Ingham 154c14ee32dSGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 155b9c1b51eSKate Stone if (target) { 156c14ee32dSGreg Clayton m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); 157c14ee32dSGreg Clayton m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); 15878a685aaSJim Ingham } 15978a685aaSJim Ingham 16078a685aaSJim Ingham Value old_value(m_value); 161b9c1b51eSKate Stone if (m_address.IsValid()) { 16278a685aaSJim Ingham Value::ValueType value_type = m_value.GetValueType(); 16378a685aaSJim Ingham 164b9c1b51eSKate Stone switch (value_type) { 16578a685aaSJim Ingham default: 166a322f36cSDavid Blaikie llvm_unreachable("Unhandled expression result value kind..."); 16778a685aaSJim Ingham 16878a685aaSJim Ingham case Value::eValueTypeScalar: 16905097246SAdrian Prantl // The variable value is in the Scalar value inside the m_value. We can 17005097246SAdrian Prantl // point our m_data right to it. 171*d9cbd2acSAdrian Prantl m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); 17278a685aaSJim Ingham break; 17378a685aaSJim Ingham 17478a685aaSJim Ingham case Value::eValueTypeFileAddress: 17578a685aaSJim Ingham case Value::eValueTypeLoadAddress: 17678a685aaSJim Ingham case Value::eValueTypeHostAddress: 17705097246SAdrian Prantl // The DWARF expression result was an address in the inferior process. If 17805097246SAdrian Prantl // this variable is an aggregate type, we just need the address as the 17905097246SAdrian Prantl // main value as all child variable objects will rely upon this location 18005097246SAdrian Prantl // and add an offset and then read their own values as needed. If this 18105097246SAdrian Prantl // variable is a simple type, we read all data for it into m_data. Make 18205097246SAdrian Prantl // sure this type has a value before we try and read it 18378a685aaSJim Ingham 18478a685aaSJim Ingham // If we have a file address, convert it to a load address if we can. 185b9c1b51eSKate Stone if (value_type == Value::eValueTypeFileAddress && 186b9c1b51eSKate Stone exe_ctx.GetProcessPtr()) { 187c14ee32dSGreg Clayton lldb::addr_t load_addr = m_address.GetLoadAddress(target); 188b9c1b51eSKate Stone if (load_addr != LLDB_INVALID_ADDRESS) { 18978a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeLoadAddress); 19078a685aaSJim Ingham m_value.GetScalar() = load_addr; 19178a685aaSJim Ingham } 19278a685aaSJim Ingham } 19378a685aaSJim Ingham 194b9c1b51eSKate Stone if (!CanProvideValue()) { 19505097246SAdrian Prantl // this value object represents an aggregate type whose children have 19605097246SAdrian Prantl // values, but this object does not. So we say we are changed if our 19705097246SAdrian Prantl // location has changed. 198b9c1b51eSKate Stone SetValueDidChange(value_type != old_value.GetValueType() || 199b9c1b51eSKate Stone m_value.GetScalar() != old_value.GetScalar()); 200b9c1b51eSKate Stone } else { 20105097246SAdrian Prantl // Copy the Value and set the context to use our Variable so it can 20205097246SAdrian Prantl // extract read its value into m_data appropriately 20378a685aaSJim Ingham Value value(m_value); 20484c39663SGreg Clayton if (m_type_sp) 20578a685aaSJim Ingham value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); 206b9c1b51eSKate Stone else { 207b9c1b51eSKate Stone // value.SetContext(Value::eContextTypeClangType, 208b9c1b51eSKate Stone // m_compiler_type.GetOpaqueQualType()); 2093ad353f3SBruce Mitchener value.SetCompilerType(m_compiler_type); 21057ee3067SGreg Clayton } 21184c39663SGreg Clayton 212*d9cbd2acSAdrian Prantl m_error = value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); 21378a685aaSJim Ingham } 21478a685aaSJim Ingham break; 21578a685aaSJim Ingham } 21678a685aaSJim Ingham 21778a685aaSJim Ingham SetValueIsValid(m_error.Success()); 21878a685aaSJim Ingham } 21978a685aaSJim Ingham return m_error.Success(); 22078a685aaSJim Ingham } 22178a685aaSJim Ingham 222b9c1b51eSKate Stone bool ValueObjectMemory::IsInScope() { 22378a685aaSJim Ingham // FIXME: Maybe try to read the memory address, and if that works, then 22478a685aaSJim Ingham // we are in scope? 22578a685aaSJim Ingham return true; 22678a685aaSJim Ingham } 22778a685aaSJim Ingham 228b9c1b51eSKate Stone lldb::ModuleSP ValueObjectMemory::GetModule() { return m_address.GetModule(); } 229