Path: blob/main/contrib/llvm-project/lldb/source/ValueObject/ValueObjectConstResultImpl.cpp
213764 views
//===-- ValueObjectConstResultImpl.cpp ------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/ValueObject/ValueObjectConstResultImpl.h"910#include "lldb/Core/Value.h"11#include "lldb/Symbol/CompilerType.h"12#include "lldb/Target/ExecutionContext.h"13#include "lldb/Utility/DataBufferHeap.h"14#include "lldb/Utility/Endian.h"15#include "lldb/Utility/LLDBLog.h"16#include "lldb/Utility/Log.h"17#include "lldb/Utility/Scalar.h"18#include "lldb/ValueObject/ValueObject.h"19#include "lldb/ValueObject/ValueObjectConstResult.h"20#include "lldb/ValueObject/ValueObjectConstResultCast.h"21#include "lldb/ValueObject/ValueObjectConstResultChild.h"2223#include <string>2425namespace lldb_private {26class DataExtractor;27}28namespace lldb_private {29class Status;30}3132using namespace lldb;33using namespace lldb_private;3435ValueObjectConstResultImpl::ValueObjectConstResultImpl(36ValueObject *valobj, lldb::addr_t live_address)37: m_impl_backend(valobj), m_live_address(live_address),38m_live_address_type(eAddressTypeLoad), m_address_of_backend() {}3940lldb::ValueObjectSP ValueObjectConstResultImpl::Dereference(Status &error) {41if (m_impl_backend == nullptr)42return lldb::ValueObjectSP();4344return m_impl_backend->ValueObject::Dereference(error);45}4647ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex(size_t idx) {48if (m_impl_backend == nullptr)49return nullptr;5051m_impl_backend->UpdateValueIfNeeded(false);5253bool omit_empty_base_classes = true;54bool ignore_array_bounds = false;55std::string child_name;56uint32_t child_byte_size = 0;57int32_t child_byte_offset = 0;58uint32_t child_bitfield_bit_size = 0;59uint32_t child_bitfield_bit_offset = 0;60bool child_is_base_class = false;61bool child_is_deref_of_parent = false;62uint64_t language_flags;63const bool transparent_pointers = true;64CompilerType compiler_type = m_impl_backend->GetCompilerType();6566ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef());6768auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex(69&exe_ctx, idx, transparent_pointers, omit_empty_base_classes,70ignore_array_bounds, child_name, child_byte_size, child_byte_offset,71child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,72child_is_deref_of_parent, m_impl_backend, language_flags);7374// One might think we should check that the size of the children75// is always strictly positive, hence we could avoid creating a76// ValueObject if that's not the case, but it turns out there77// are languages out there which allow zero-size types with78// children (e.g. Swift).79if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) {80LLDB_LOG_ERROR(GetLog(LLDBLog::Types),81child_compiler_type_or_err.takeError(),82"could not find child: {0}");83return nullptr;84}8586lldb::addr_t child_live_addr = LLDB_INVALID_ADDRESS;87// Transfer the live address (with offset) to the child. But if88// the parent is a pointer, the live address is where that pointer89// value lives in memory, so the children live addresses aren't90// offsets from that value, they are just other load addresses that91// are recorded in the Value of the child ValueObjects.92if (m_live_address != LLDB_INVALID_ADDRESS && !compiler_type.IsPointerType())93child_live_addr = m_live_address + child_byte_offset;9495return new ValueObjectConstResultChild(96*m_impl_backend, *child_compiler_type_or_err, ConstString(child_name),97child_byte_size, child_byte_offset, child_bitfield_bit_size,98child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent,99child_live_addr, language_flags);100}101102ValueObject *103ValueObjectConstResultImpl::CreateSyntheticArrayMember(size_t idx) {104if (m_impl_backend == nullptr)105return nullptr;106107m_impl_backend->UpdateValueIfNeeded(false);108109bool omit_empty_base_classes = true;110bool ignore_array_bounds = true;111std::string child_name;112uint32_t child_byte_size = 0;113int32_t child_byte_offset = 0;114uint32_t child_bitfield_bit_size = 0;115uint32_t child_bitfield_bit_offset = 0;116bool child_is_base_class = false;117bool child_is_deref_of_parent = false;118uint64_t language_flags;119120const bool transparent_pointers = false;121CompilerType compiler_type = m_impl_backend->GetCompilerType();122123ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef());124125auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex(126&exe_ctx, 0, transparent_pointers, omit_empty_base_classes,127ignore_array_bounds, child_name, child_byte_size, child_byte_offset,128child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,129child_is_deref_of_parent, m_impl_backend, language_flags);130// One might think we should check that the size of the children131// is always strictly positive, hence we could avoid creating a132// ValueObject if that's not the case, but it turns out there133// are languages out there which allow zero-size types with134// children (e.g. Swift).135if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) {136LLDB_LOG_ERROR(GetLog(LLDBLog::Types),137child_compiler_type_or_err.takeError(),138"could not find child: {0}");139return nullptr;140}141142child_byte_offset += child_byte_size * idx;143144lldb::addr_t child_live_addr = LLDB_INVALID_ADDRESS;145// Transfer the live address (with offset) to the child. But if146// the parent is a pointer, the live address is where that pointer147// value lives in memory, so the children live addresses aren't148// offsets from that value, they are just other load addresses that149// are recorded in the Value of the child ValueObjects.150if (m_live_address != LLDB_INVALID_ADDRESS && !compiler_type.IsPointerType())151child_live_addr = m_live_address + child_byte_offset;152return new ValueObjectConstResultChild(153*m_impl_backend, *child_compiler_type_or_err, ConstString(child_name),154child_byte_size, child_byte_offset, child_bitfield_bit_size,155child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent,156child_live_addr, language_flags);157}158159lldb::ValueObjectSP ValueObjectConstResultImpl::GetSyntheticChildAtOffset(160uint32_t offset, const CompilerType &type, bool can_create,161ConstString name_const_str) {162if (m_impl_backend == nullptr)163return lldb::ValueObjectSP();164165return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(166offset, type, can_create, name_const_str);167}168169lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf(Status &error) {170if (m_address_of_backend.get() != nullptr)171return m_address_of_backend;172173if (m_impl_backend == nullptr)174return lldb::ValueObjectSP();175if (m_live_address != LLDB_INVALID_ADDRESS) {176CompilerType compiler_type(m_impl_backend->GetCompilerType());177178lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(179&m_live_address, sizeof(lldb::addr_t)));180181std::string new_name("&");182new_name.append(m_impl_backend->GetName().AsCString(""));183ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef());184m_address_of_backend = ValueObjectConstResult::Create(185exe_ctx.GetBestExecutionContextScope(), compiler_type.GetPointerType(),186ConstString(new_name.c_str()), buffer, endian::InlHostByteOrder(),187exe_ctx.GetAddressByteSize());188189m_address_of_backend->GetValue().SetValueType(Value::ValueType::Scalar);190m_address_of_backend->GetValue().GetScalar() = m_live_address;191192return m_address_of_backend;193} else194return m_impl_backend->ValueObject::AddressOf(error);195}196197lldb::ValueObjectSP198ValueObjectConstResultImpl::Cast(const CompilerType &compiler_type) {199if (m_impl_backend == nullptr)200return lldb::ValueObjectSP();201202ValueObjectConstResultCast *result_cast =203new ValueObjectConstResultCast(*m_impl_backend, m_impl_backend->GetName(),204compiler_type, m_live_address);205return result_cast->GetSP();206}207208ValueObject::AddrAndType209ValueObjectConstResultImpl::GetAddressOf(bool scalar_is_load_address) {210211if (m_impl_backend == nullptr)212return {0, eAddressTypeInvalid};213214if (m_live_address == LLDB_INVALID_ADDRESS)215return m_impl_backend->ValueObject::GetAddressOf(scalar_is_load_address);216217return {m_live_address, m_live_address_type};218}219220size_t ValueObjectConstResultImpl::GetPointeeData(DataExtractor &data,221uint32_t item_idx,222uint32_t item_count) {223if (m_impl_backend == nullptr)224return 0;225return m_impl_backend->ValueObject::GetPointeeData(data, item_idx,226item_count);227}228229230