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" 16672d2c12SJonas Devlieghere #include "lldb/Utility/DataExtractor.h" 17672d2c12SJonas Devlieghere #include "lldb/Utility/Scalar.h" 18672d2c12SJonas Devlieghere #include "lldb/Utility/Status.h" 19672d2c12SJonas Devlieghere #include "lldb/lldb-types.h" 20672d2c12SJonas Devlieghere #include "llvm/Support/ErrorHandling.h" 212f3df613SZachary Turner 22672d2c12SJonas Devlieghere #include <assert.h> 23672d2c12SJonas Devlieghere #include <memory> 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 131eca07c59SAdrian Prantl ExecutionContext exe_ctx(GetExecutionContextRef()); 13284c39663SGreg Clayton const bool omit_empty_base_classes = true; 133eca07c59SAdrian Prantl auto child_count = 134eca07c59SAdrian 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(); 141*d6a9bbf6SAdrian Prantl if (llvm::Optional<uint64_t> size = m_compiler_type.GetByteSize(nullptr)) 142d963a7c3SAdrian Prantl return *size; 143d963a7c3SAdrian Prantl return 0; 14478a685aaSJim Ingham } 14578a685aaSJim Ingham 146b9c1b51eSKate Stone lldb::ValueType ValueObjectMemory::GetValueType() const { 14778a685aaSJim Ingham // RETHINK: Should this be inherited from somewhere? 14878a685aaSJim Ingham return lldb::eValueTypeVariableGlobal; 14978a685aaSJim Ingham } 15078a685aaSJim Ingham 151b9c1b51eSKate Stone bool ValueObjectMemory::UpdateValue() { 15278a685aaSJim Ingham SetValueIsValid(false); 15378a685aaSJim Ingham m_error.Clear(); 15478a685aaSJim Ingham 155cc4d0146SGreg Clayton ExecutionContext exe_ctx(GetExecutionContextRef()); 15678a685aaSJim Ingham 157c14ee32dSGreg Clayton Target *target = exe_ctx.GetTargetPtr(); 158b9c1b51eSKate Stone if (target) { 159c14ee32dSGreg Clayton m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); 160c14ee32dSGreg Clayton m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); 16178a685aaSJim Ingham } 16278a685aaSJim Ingham 16378a685aaSJim Ingham Value old_value(m_value); 164b9c1b51eSKate Stone if (m_address.IsValid()) { 16578a685aaSJim Ingham Value::ValueType value_type = m_value.GetValueType(); 16678a685aaSJim Ingham 167b9c1b51eSKate Stone switch (value_type) { 16878a685aaSJim Ingham default: 169a322f36cSDavid Blaikie llvm_unreachable("Unhandled expression result value kind..."); 17078a685aaSJim Ingham 17178a685aaSJim Ingham case Value::eValueTypeScalar: 17205097246SAdrian Prantl // The variable value is in the Scalar value inside the m_value. We can 17305097246SAdrian Prantl // 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: 18005097246SAdrian Prantl // The DWARF expression result was an address in the inferior process. If 18105097246SAdrian Prantl // this variable is an aggregate type, we just need the address as the 18205097246SAdrian Prantl // main value as all child variable objects will rely upon this location 18305097246SAdrian Prantl // and add an offset and then read their own values as needed. If this 18405097246SAdrian Prantl // variable is a simple type, we read all data for it into m_data. Make 18505097246SAdrian Prantl // sure this type has a value before we try and read it 18678a685aaSJim Ingham 18778a685aaSJim Ingham // If we have a file address, convert it to a load address if we can. 188b9c1b51eSKate Stone if (value_type == Value::eValueTypeFileAddress && 189b9c1b51eSKate Stone exe_ctx.GetProcessPtr()) { 190c14ee32dSGreg Clayton lldb::addr_t load_addr = m_address.GetLoadAddress(target); 191b9c1b51eSKate Stone if (load_addr != LLDB_INVALID_ADDRESS) { 19278a685aaSJim Ingham m_value.SetValueType(Value::eValueTypeLoadAddress); 19378a685aaSJim Ingham m_value.GetScalar() = load_addr; 19478a685aaSJim Ingham } 19578a685aaSJim Ingham } 19678a685aaSJim Ingham 197b9c1b51eSKate Stone if (!CanProvideValue()) { 19805097246SAdrian Prantl // this value object represents an aggregate type whose children have 19905097246SAdrian Prantl // values, but this object does not. So we say we are changed if our 20005097246SAdrian Prantl // location has changed. 201b9c1b51eSKate Stone SetValueDidChange(value_type != old_value.GetValueType() || 202b9c1b51eSKate Stone m_value.GetScalar() != old_value.GetScalar()); 203b9c1b51eSKate Stone } else { 20405097246SAdrian Prantl // Copy the Value and set the context to use our Variable so it can 20505097246SAdrian Prantl // extract read its value into m_data appropriately 20678a685aaSJim Ingham Value value(m_value); 20784c39663SGreg Clayton if (m_type_sp) 20878a685aaSJim Ingham value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); 209b9c1b51eSKate Stone else { 210b9c1b51eSKate Stone // value.SetContext(Value::eContextTypeClangType, 211b9c1b51eSKate Stone // m_compiler_type.GetOpaqueQualType()); 2123ad353f3SBruce Mitchener value.SetCompilerType(m_compiler_type); 21357ee3067SGreg Clayton } 21484c39663SGreg Clayton 21557ee3067SGreg Clayton m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); 21678a685aaSJim Ingham } 21778a685aaSJim Ingham break; 21878a685aaSJim Ingham } 21978a685aaSJim Ingham 22078a685aaSJim Ingham SetValueIsValid(m_error.Success()); 22178a685aaSJim Ingham } 22278a685aaSJim Ingham return m_error.Success(); 22378a685aaSJim Ingham } 22478a685aaSJim Ingham 225b9c1b51eSKate Stone bool ValueObjectMemory::IsInScope() { 22678a685aaSJim Ingham // FIXME: Maybe try to read the memory address, and if that works, then 22778a685aaSJim Ingham // we are in scope? 22878a685aaSJim Ingham return true; 22978a685aaSJim Ingham } 23078a685aaSJim Ingham 231b9c1b51eSKate Stone lldb::ModuleSP ValueObjectMemory::GetModule() { return m_address.GetModule(); } 232