| //===-- ValueObjectConstResult.cpp ----------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "lldb/ValueObject/ValueObjectConstResult.h" | |
| #include "lldb/Symbol/CompilerType.h" | |
| #include "lldb/Target/ExecutionContext.h" | |
| #include "lldb/Target/ExecutionContextScope.h" | |
| #include "lldb/Target/Process.h" | |
| #include "lldb/Utility/DataBuffer.h" | |
| #include "lldb/Utility/DataBufferHeap.h" | |
| #include "lldb/Utility/DataExtractor.h" | |
| #include "lldb/Utility/Scalar.h" | |
| #include "lldb/ValueObject/ValueObjectDynamicValue.h" | |
| #include <optional> | |
| namespace lldb_private { | |
| class Module; | |
| } | |
| using namespace lldb; | |
| using namespace lldb_private; | |
| ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope, | |
| ByteOrder byte_order, | |
| uint32_t addr_byte_size, | |
| lldb::addr_t address, | |
| ValueObjectManager *manager) { | |
| ValueObjectManagerSP manager_sp = CreateManagerIfEmpty(manager); | |
| return (new ValueObjectConstResult(exe_scope, *manager, byte_order, | |
| addr_byte_size, address)) | |
| ->GetSP(); | |
| } | |
| ValueObjectConstResult::ValueObjectConstResult(ExecutionContextScope *exe_scope, | |
| ValueObjectManager &manager, | |
| ByteOrder byte_order, | |
| uint32_t addr_byte_size, | |
| lldb::addr_t address) | |
| : ValueObject(exe_scope, manager), m_impl(this, address) { | |
| SetIsConstant(); | |
| SetValueIsValid(true); | |
| m_data.SetByteOrder(byte_order); | |
| m_data.SetAddressByteSize(addr_byte_size); | |
| SetAddressTypeOfChildren(eAddressTypeLoad); | |
| } | |
| ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope, | |
| const CompilerType &compiler_type, | |
| ConstString name, | |
| const DataExtractor &data, | |
| lldb::addr_t address, | |
| ValueObjectManager *manager) { | |
| std::shared_ptr<ValueObjectManager> manager_sp = | |
| CreateManagerIfEmpty(manager); | |
| return (new ValueObjectConstResult(exe_scope, *manager, compiler_type, name, | |
| data, address)) | |
| ->GetSP(); | |
| } | |
| ValueObjectConstResult::ValueObjectConstResult( | |
| ExecutionContextScope *exe_scope, ValueObjectManager &manager, | |
| const CompilerType &compiler_type, ConstString name, | |
| const DataExtractor &data, lldb::addr_t address) | |
| : ValueObject(exe_scope, manager), m_impl(this, address) { | |
| m_data = data; | |
| if (!m_data.GetSharedDataBuffer()) { | |
| DataBufferSP shared_data_buffer( | |
| new DataBufferHeap(data.GetDataStart(), data.GetByteSize())); | |
| m_data.SetData(shared_data_buffer); | |
| } | |
| m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); | |
| m_value.SetValueType(Value::ValueType::HostAddress); | |
| m_value.SetCompilerType(compiler_type); | |
| m_name = name; | |
| SetIsConstant(); | |
| SetValueIsValid(true); | |
| SetAddressTypeOfChildren(eAddressTypeLoad); | |
| } | |
| ValueObjectSP ValueObjectConstResult::Create( | |
| ExecutionContextScope *exe_scope, const CompilerType &compiler_type, | |
| ConstString name, const lldb::DataBufferSP &data_sp, | |
| lldb::ByteOrder data_byte_order, uint32_t data_addr_size, | |
| lldb::addr_t address, ValueObjectManager *manager) { | |
| std::shared_ptr<ValueObjectManager> manager_sp = | |
| CreateManagerIfEmpty(manager); | |
| return (new ValueObjectConstResult(exe_scope, *manager, compiler_type, name, | |
| data_sp, data_byte_order, data_addr_size, | |
| address)) | |
| ->GetSP(); | |
| } | |
| ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope, | |
| Value &value, ConstString name, | |
| Module *module, | |
| ValueObjectManager *manager) { | |
| std::shared_ptr<ValueObjectManager> manager_sp = | |
| CreateManagerIfEmpty(manager); | |
| return (new ValueObjectConstResult(exe_scope, *manager, value, name, module)) | |
| ->GetSP(); | |
| } | |
| ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope, | |
| const CompilerType &compiler_type, | |
| Scalar &scalar, ConstString name, | |
| Module *module, | |
| ValueObjectManager *manager) { | |
| std::shared_ptr<ValueObjectManager> manager_sp = | |
| CreateManagerIfEmpty(manager); | |
| return (new ValueObjectConstResult(exe_scope, *manager, compiler_type, scalar, | |
| name, module)) | |
| ->GetSP(); | |
| } | |
| ValueObjectConstResult::ValueObjectConstResult( | |
| ExecutionContextScope *exe_scope, ValueObjectManager &manager, | |
| const CompilerType &compiler_type, ConstString name, | |
| const lldb::DataBufferSP &data_sp, lldb::ByteOrder data_byte_order, | |
| uint32_t data_addr_size, lldb::addr_t address) | |
| : ValueObject(exe_scope, manager), m_impl(this, address) { | |
| m_data.SetByteOrder(data_byte_order); | |
| m_data.SetAddressByteSize(data_addr_size); | |
| m_data.SetData(data_sp); | |
| m_value.GetScalar() = (uintptr_t)data_sp->GetBytes(); | |
| m_value.SetValueType(Value::ValueType::HostAddress); | |
| m_value.SetCompilerType(compiler_type); | |
| m_name = name; | |
| SetIsConstant(); | |
| SetValueIsValid(true); | |
| SetAddressTypeOfChildren(eAddressTypeLoad); | |
| } | |
| ValueObjectSP ValueObjectConstResult::Create( | |
| ExecutionContextScope *exe_scope, const CompilerType &compiler_type, | |
| ConstString name, lldb::addr_t address, AddressType address_type, | |
| uint32_t addr_byte_size, ValueObjectManager *manager) { | |
| std::shared_ptr<ValueObjectManager> manager_sp = | |
| CreateManagerIfEmpty(manager); | |
| return (new ValueObjectConstResult(exe_scope, *manager, compiler_type, name, | |
| address, address_type, addr_byte_size)) | |
| ->GetSP(); | |
| } | |
| ValueObjectConstResult::ValueObjectConstResult( | |
| ExecutionContextScope *exe_scope, ValueObjectManager &manager, | |
| const CompilerType &compiler_type, ConstString name, lldb::addr_t address, | |
| AddressType address_type, uint32_t addr_byte_size) | |
| : ValueObject(exe_scope, manager), m_type_name(), m_impl(this, address) { | |
| m_value.GetScalar() = address; | |
| m_data.SetAddressByteSize(addr_byte_size); | |
| m_value.GetScalar().GetData(m_data, addr_byte_size); | |
| // m_value.SetValueType(Value::ValueType::HostAddress); | |
| switch (address_type) { | |
| case eAddressTypeInvalid: | |
| m_value.SetValueType(Value::ValueType::Scalar); | |
| break; | |
| case eAddressTypeFile: | |
| m_value.SetValueType(Value::ValueType::FileAddress); | |
| break; | |
| case eAddressTypeLoad: | |
| m_value.SetValueType(Value::ValueType::LoadAddress); | |
| break; | |
| case eAddressTypeHost: | |
| m_value.SetValueType(Value::ValueType::HostAddress); | |
| break; | |
| } | |
| m_value.SetCompilerType(compiler_type); | |
| m_name = name; | |
| SetIsConstant(); | |
| SetValueIsValid(true); | |
| SetAddressTypeOfChildren(eAddressTypeLoad); | |
| } | |
| ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope, | |
| Status &&error, | |
| ValueObjectManager *manager) { | |
| std::shared_ptr<ValueObjectManager> manager_sp = | |
| CreateManagerIfEmpty(manager); | |
| return (new ValueObjectConstResult(exe_scope, *manager, std::move(error))) | |
| ->GetSP(); | |
| } | |
| ValueObjectConstResult::ValueObjectConstResult(ExecutionContextScope *exe_scope, | |
| ValueObjectManager &manager, | |
| Status &&error) | |
| : ValueObject(exe_scope, manager), m_impl(this) { | |
| m_error = std::move(error); | |
| SetIsConstant(); | |
| } | |
| ValueObjectConstResult::ValueObjectConstResult(ExecutionContextScope *exe_scope, | |
| ValueObjectManager &manager, | |
| const Value &value, | |
| ConstString name, Module *module) | |
| : ValueObject(exe_scope, manager), m_impl(this) { | |
| m_value = value; | |
| m_name = name; | |
| ExecutionContext exe_ctx; | |
| exe_scope->CalculateExecutionContext(exe_ctx); | |
| m_error = m_value.GetValueAsData(&exe_ctx, m_data, module); | |
| } | |
| ValueObjectConstResult::ValueObjectConstResult( | |
| ExecutionContextScope *exe_scope, ValueObjectManager &manager, | |
| const CompilerType &compiler_type, const Scalar &scalar, ConstString name, | |
| Module *module) | |
| : ValueObject(exe_scope, manager), m_impl(this) { | |
| m_value = Value(scalar); | |
| m_value.SetCompilerType(compiler_type); | |
| m_value.SetValueType(Value::ValueType::Scalar); | |
| m_name = name; | |
| ExecutionContext exe_ctx; | |
| exe_scope->CalculateExecutionContext(exe_ctx); | |
| m_error = m_value.GetValueAsData(&exe_ctx, m_data, module); | |
| SetIsConstant(); | |
| SetValueIsValid(true); | |
| SetAddressTypeOfChildren(eAddressTypeLoad); | |
| } | |
| ValueObjectConstResult::~ValueObjectConstResult() = default; | |
| CompilerType ValueObjectConstResult::GetCompilerTypeImpl() { | |
| return m_value.GetCompilerType(); | |
| } | |
| lldb::ValueType ValueObjectConstResult::GetValueType() const { | |
| return eValueTypeConstResult; | |
| } | |
| llvm::Expected<uint64_t> ValueObjectConstResult::GetByteSize() { | |
| ExecutionContext exe_ctx(GetExecutionContextRef()); | |
| if (!m_byte_size) { | |
| auto size_or_err = | |
| GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope()); | |
| if (!size_or_err) | |
| return size_or_err; | |
| SetByteSize(*size_or_err); | |
| } | |
| if (m_byte_size) | |
| return *m_byte_size; | |
| return llvm::createStringError("unknown size of const result"); | |
| } | |
| void ValueObjectConstResult::SetByteSize(size_t size) { m_byte_size = size; } | |
| llvm::Expected<uint32_t> | |
| ValueObjectConstResult::CalculateNumChildren(uint32_t max) { | |
| ExecutionContext exe_ctx(GetExecutionContextRef()); | |
| auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx); | |
| if (!children_count) | |
| return children_count; | |
| return *children_count <= max ? *children_count : max; | |
| } | |
| ConstString ValueObjectConstResult::GetTypeName() { | |
| if (m_type_name.IsEmpty()) | |
| m_type_name = GetCompilerType().GetTypeName(); | |
| return m_type_name; | |
| } | |
| ConstString ValueObjectConstResult::GetDisplayTypeName() { | |
| return GetCompilerType().GetDisplayTypeName(); | |
| } | |
| bool ValueObjectConstResult::UpdateValue() { | |
| // Const value is always valid | |
| SetValueIsValid(true); | |
| return true; | |
| } | |
| bool ValueObjectConstResult::IsInScope() { | |
| // A const result value is always in scope since it serializes all | |
| // information needed to contain the constant value. | |
| return true; | |
| } | |
| lldb::ValueObjectSP ValueObjectConstResult::Dereference(Status &error) { | |
| return m_impl.Dereference(error); | |
| } | |
| lldb::ValueObjectSP ValueObjectConstResult::GetSyntheticChildAtOffset( | |
| uint32_t offset, const CompilerType &type, bool can_create, | |
| ConstString name_const_str) { | |
| return m_impl.GetSyntheticChildAtOffset(offset, type, can_create, | |
| name_const_str); | |
| } | |
| lldb::ValueObjectSP ValueObjectConstResult::AddressOf(Status &error) { | |
| return m_impl.AddressOf(error); | |
| } | |
| ValueObject::AddrAndType | |
| ValueObjectConstResult::GetAddressOf(bool scalar_is_load_address) { | |
| return m_impl.GetAddressOf(scalar_is_load_address); | |
| } | |
| size_t ValueObjectConstResult::GetPointeeData(DataExtractor &data, | |
| uint32_t item_idx, | |
| uint32_t item_count) { | |
| return m_impl.GetPointeeData(data, item_idx, item_count); | |
| } | |
| lldb::ValueObjectSP | |
| ValueObjectConstResult::GetDynamicValue(lldb::DynamicValueType use_dynamic) { | |
| // Always recalculate dynamic values for const results as the memory that | |
| // they might point to might have changed at any time. | |
| if (use_dynamic != eNoDynamicValues) { | |
| if (!IsDynamic()) { | |
| ExecutionContext exe_ctx(GetExecutionContextRef()); | |
| Process *process = exe_ctx.GetProcessPtr(); | |
| if (process && process->IsPossibleDynamicValue(*this)) | |
| m_dynamic_value = new ValueObjectDynamicValue(*this, use_dynamic); | |
| } | |
| if (m_dynamic_value && m_dynamic_value->GetError().Success()) | |
| return m_dynamic_value->GetSP(); | |
| } | |
| return ValueObjectSP(); | |
| } | |
| lldb::ValueObjectSP | |
| ValueObjectConstResult::DoCast(const CompilerType &compiler_type) { | |
| return m_impl.Cast(compiler_type); | |
| } | |
| lldb::LanguageType ValueObjectConstResult::GetPreferredDisplayLanguage() { | |
| if (m_preferred_display_language != lldb::eLanguageTypeUnknown) | |
| return m_preferred_display_language; | |
| return GetCompilerTypeImpl().GetMinimumLanguage(); | |
| } |