229 lines · cpp
1//===-- ValueObjectConstResultImpl.cpp ------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/ValueObject/ValueObjectConstResultImpl.h"10 11#include "lldb/Core/Value.h"12#include "lldb/Symbol/CompilerType.h"13#include "lldb/Target/ExecutionContext.h"14#include "lldb/Utility/DataBufferHeap.h"15#include "lldb/Utility/Endian.h"16#include "lldb/Utility/LLDBLog.h"17#include "lldb/Utility/Log.h"18#include "lldb/Utility/Scalar.h"19#include "lldb/ValueObject/ValueObject.h"20#include "lldb/ValueObject/ValueObjectConstResult.h"21#include "lldb/ValueObject/ValueObjectConstResultCast.h"22#include "lldb/ValueObject/ValueObjectConstResultChild.h"23 24#include <string>25 26namespace lldb_private {27class DataExtractor;28}29namespace lldb_private {30class Status;31}32 33using namespace lldb;34using namespace lldb_private;35 36ValueObjectConstResultImpl::ValueObjectConstResultImpl(37 ValueObject *valobj, lldb::addr_t live_address)38 : m_impl_backend(valobj), m_live_address(live_address),39 m_live_address_type(eAddressTypeLoad), m_address_of_backend() {}40 41lldb::ValueObjectSP ValueObjectConstResultImpl::Dereference(Status &error) {42 if (m_impl_backend == nullptr)43 return lldb::ValueObjectSP();44 45 return m_impl_backend->ValueObject::Dereference(error);46}47 48ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex(size_t idx) {49 if (m_impl_backend == nullptr)50 return nullptr;51 52 m_impl_backend->UpdateValueIfNeeded(false);53 54 bool omit_empty_base_classes = true;55 bool ignore_array_bounds = false;56 std::string child_name;57 uint32_t child_byte_size = 0;58 int32_t child_byte_offset = 0;59 uint32_t child_bitfield_bit_size = 0;60 uint32_t child_bitfield_bit_offset = 0;61 bool child_is_base_class = false;62 bool child_is_deref_of_parent = false;63 uint64_t language_flags;64 const bool transparent_pointers = true;65 CompilerType compiler_type = m_impl_backend->GetCompilerType();66 67 ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef());68 69 auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex(70 &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,71 ignore_array_bounds, child_name, child_byte_size, child_byte_offset,72 child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,73 child_is_deref_of_parent, m_impl_backend, language_flags);74 75 // One might think we should check that the size of the children76 // is always strictly positive, hence we could avoid creating a77 // ValueObject if that's not the case, but it turns out there78 // are languages out there which allow zero-size types with79 // children (e.g. Swift).80 if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) {81 LLDB_LOG_ERROR(GetLog(LLDBLog::Types),82 child_compiler_type_or_err.takeError(),83 "could not find child: {0}");84 return nullptr;85 }86 87 lldb::addr_t child_live_addr = LLDB_INVALID_ADDRESS;88 // Transfer the live address (with offset) to the child. But if89 // the parent is a pointer, the live address is where that pointer90 // value lives in memory, so the children live addresses aren't91 // offsets from that value, they are just other load addresses that92 // are recorded in the Value of the child ValueObjects.93 if (m_live_address != LLDB_INVALID_ADDRESS && !compiler_type.IsPointerType())94 child_live_addr = m_live_address + child_byte_offset;95 96 return new ValueObjectConstResultChild(97 *m_impl_backend, *child_compiler_type_or_err, ConstString(child_name),98 child_byte_size, child_byte_offset, child_bitfield_bit_size,99 child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent,100 child_live_addr, language_flags);101}102 103ValueObject *104ValueObjectConstResultImpl::CreateSyntheticArrayMember(size_t idx) {105 if (m_impl_backend == nullptr)106 return nullptr;107 108 m_impl_backend->UpdateValueIfNeeded(false);109 110 bool omit_empty_base_classes = true;111 bool ignore_array_bounds = true;112 std::string child_name;113 uint32_t child_byte_size = 0;114 int32_t child_byte_offset = 0;115 uint32_t child_bitfield_bit_size = 0;116 uint32_t child_bitfield_bit_offset = 0;117 bool child_is_base_class = false;118 bool child_is_deref_of_parent = false;119 uint64_t language_flags;120 121 const bool transparent_pointers = false;122 CompilerType compiler_type = m_impl_backend->GetCompilerType();123 124 ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef());125 126 auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex(127 &exe_ctx, 0, transparent_pointers, omit_empty_base_classes,128 ignore_array_bounds, child_name, child_byte_size, child_byte_offset,129 child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,130 child_is_deref_of_parent, m_impl_backend, language_flags);131 // One might think we should check that the size of the children132 // is always strictly positive, hence we could avoid creating a133 // ValueObject if that's not the case, but it turns out there134 // are languages out there which allow zero-size types with135 // children (e.g. Swift).136 if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) {137 LLDB_LOG_ERROR(GetLog(LLDBLog::Types),138 child_compiler_type_or_err.takeError(),139 "could not find child: {0}");140 return nullptr;141 }142 143 child_byte_offset += child_byte_size * idx;144 145 lldb::addr_t child_live_addr = LLDB_INVALID_ADDRESS;146 // Transfer the live address (with offset) to the child. But if147 // the parent is a pointer, the live address is where that pointer148 // value lives in memory, so the children live addresses aren't149 // offsets from that value, they are just other load addresses that150 // are recorded in the Value of the child ValueObjects.151 if (m_live_address != LLDB_INVALID_ADDRESS && !compiler_type.IsPointerType())152 child_live_addr = m_live_address + child_byte_offset;153 return new ValueObjectConstResultChild(154 *m_impl_backend, *child_compiler_type_or_err, ConstString(child_name),155 child_byte_size, child_byte_offset, child_bitfield_bit_size,156 child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent,157 child_live_addr, language_flags);158}159 160lldb::ValueObjectSP ValueObjectConstResultImpl::GetSyntheticChildAtOffset(161 uint32_t offset, const CompilerType &type, bool can_create,162 ConstString name_const_str) {163 if (m_impl_backend == nullptr)164 return lldb::ValueObjectSP();165 166 return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(167 offset, type, can_create, name_const_str);168}169 170lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf(Status &error) {171 if (m_address_of_backend.get() != nullptr)172 return m_address_of_backend;173 174 if (m_impl_backend == nullptr)175 return lldb::ValueObjectSP();176 if (m_live_address != LLDB_INVALID_ADDRESS) {177 CompilerType compiler_type(m_impl_backend->GetCompilerType());178 179 lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(180 &m_live_address, sizeof(lldb::addr_t)));181 182 std::string new_name("&");183 new_name.append(m_impl_backend->GetName().AsCString(""));184 ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef());185 m_address_of_backend = ValueObjectConstResult::Create(186 exe_ctx.GetBestExecutionContextScope(), compiler_type.GetPointerType(),187 ConstString(new_name.c_str()), buffer, endian::InlHostByteOrder(),188 exe_ctx.GetAddressByteSize());189 190 m_address_of_backend->GetValue().SetValueType(Value::ValueType::Scalar);191 m_address_of_backend->GetValue().GetScalar() = m_live_address;192 193 return m_address_of_backend;194 } else195 return m_impl_backend->ValueObject::AddressOf(error);196}197 198lldb::ValueObjectSP199ValueObjectConstResultImpl::Cast(const CompilerType &compiler_type) {200 if (m_impl_backend == nullptr)201 return lldb::ValueObjectSP();202 203 ValueObjectConstResultCast *result_cast =204 new ValueObjectConstResultCast(*m_impl_backend, m_impl_backend->GetName(),205 compiler_type, m_live_address);206 return result_cast->GetSP();207}208 209ValueObject::AddrAndType210ValueObjectConstResultImpl::GetAddressOf(bool scalar_is_load_address) {211 212 if (m_impl_backend == nullptr)213 return {0, eAddressTypeInvalid};214 215 if (m_live_address == LLDB_INVALID_ADDRESS)216 return m_impl_backend->ValueObject::GetAddressOf(scalar_is_load_address);217 218 return {m_live_address, m_live_address_type};219}220 221size_t ValueObjectConstResultImpl::GetPointeeData(DataExtractor &data,222 uint32_t item_idx,223 uint32_t item_count) {224 if (m_impl_backend == nullptr)225 return 0;226 return m_impl_backend->ValueObject::GetPointeeData(data, item_idx,227 item_count);228}229