15ffd83dbSDimitry Andric //===-- ValueObjectConstResultImpl.cpp ------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResultImpl.h" 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "lldb/Core/Value.h" 120b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h" 130b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResult.h" 140b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResultCast.h" 150b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResultChild.h" 160b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h" 170b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h" 180b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h" 190b57cec5SDimitry Andric #include "lldb/Utility/Endian.h" 20*0fca6ea1SDimitry Andric #include "lldb/Utility/LLDBLog.h" 21*0fca6ea1SDimitry Andric #include "lldb/Utility/Log.h" 220b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #include <string> 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric namespace lldb_private { 270b57cec5SDimitry Andric class DataExtractor; 280b57cec5SDimitry Andric } 290b57cec5SDimitry Andric namespace lldb_private { 300b57cec5SDimitry Andric class Status; 310b57cec5SDimitry Andric } 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric using namespace lldb; 340b57cec5SDimitry Andric using namespace lldb_private; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric ValueObjectConstResultImpl::ValueObjectConstResultImpl( 370b57cec5SDimitry Andric ValueObject *valobj, lldb::addr_t live_address) 380b57cec5SDimitry Andric : m_impl_backend(valobj), m_live_address(live_address), 39349cc55cSDimitry Andric m_live_address_type(eAddressTypeLoad), 400b57cec5SDimitry Andric m_address_of_backend() {} 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric lldb::ValueObjectSP ValueObjectConstResultImpl::Dereference(Status &error) { 430b57cec5SDimitry Andric if (m_impl_backend == nullptr) 440b57cec5SDimitry Andric return lldb::ValueObjectSP(); 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric return m_impl_backend->ValueObject::Dereference(error); 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric 49*0fca6ea1SDimitry Andric ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex(size_t idx) { 500b57cec5SDimitry Andric if (m_impl_backend == nullptr) 510b57cec5SDimitry Andric return nullptr; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric m_impl_backend->UpdateValueIfNeeded(false); 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric bool omit_empty_base_classes = true; 56*0fca6ea1SDimitry Andric bool ignore_array_bounds = false; 57*0fca6ea1SDimitry Andric std::string child_name; 580b57cec5SDimitry Andric uint32_t child_byte_size = 0; 590b57cec5SDimitry Andric int32_t child_byte_offset = 0; 600b57cec5SDimitry Andric uint32_t child_bitfield_bit_size = 0; 610b57cec5SDimitry Andric uint32_t child_bitfield_bit_offset = 0; 620b57cec5SDimitry Andric bool child_is_base_class = false; 630b57cec5SDimitry Andric bool child_is_deref_of_parent = false; 640b57cec5SDimitry Andric uint64_t language_flags; 65*0fca6ea1SDimitry Andric const bool transparent_pointers = true; 660b57cec5SDimitry Andric CompilerType compiler_type = m_impl_backend->GetCompilerType(); 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef()); 690b57cec5SDimitry Andric 70*0fca6ea1SDimitry Andric auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex( 710b57cec5SDimitry Andric &exe_ctx, idx, transparent_pointers, omit_empty_base_classes, 72*0fca6ea1SDimitry Andric ignore_array_bounds, child_name, child_byte_size, child_byte_offset, 730b57cec5SDimitry Andric child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, 740b57cec5SDimitry Andric child_is_deref_of_parent, m_impl_backend, language_flags); 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric // One might think we should check that the size of the children 770b57cec5SDimitry Andric // is always strictly positive, hence we could avoid creating a 780b57cec5SDimitry Andric // ValueObject if that's not the case, but it turns out there 790b57cec5SDimitry Andric // are languages out there which allow zero-size types with 800b57cec5SDimitry Andric // children (e.g. Swift). 81*0fca6ea1SDimitry Andric if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) { 82*0fca6ea1SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Types), 83*0fca6ea1SDimitry Andric child_compiler_type_or_err.takeError(), 84*0fca6ea1SDimitry Andric "could not find child: {0}"); 85*0fca6ea1SDimitry Andric return nullptr; 86*0fca6ea1SDimitry Andric } 870b57cec5SDimitry Andric 88bdd1243dSDimitry Andric lldb::addr_t child_live_addr = LLDB_INVALID_ADDRESS; 89bdd1243dSDimitry Andric // Transfer the live address (with offset) to the child. But if 90bdd1243dSDimitry Andric // the parent is a pointer, the live address is where that pointer 91bdd1243dSDimitry Andric // value lives in memory, so the children live addresses aren't 92bdd1243dSDimitry Andric // offsets from that value, they are just other load addresses that 93bdd1243dSDimitry Andric // are recorded in the Value of the child ValueObjects. 94*0fca6ea1SDimitry Andric if (m_live_address != LLDB_INVALID_ADDRESS && !compiler_type.IsPointerType()) 95bdd1243dSDimitry Andric child_live_addr = m_live_address + child_byte_offset; 96*0fca6ea1SDimitry Andric 97*0fca6ea1SDimitry Andric return new ValueObjectConstResultChild( 98*0fca6ea1SDimitry Andric *m_impl_backend, *child_compiler_type_or_err, ConstString(child_name), 99*0fca6ea1SDimitry Andric child_byte_size, child_byte_offset, child_bitfield_bit_size, 100*0fca6ea1SDimitry Andric child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent, 101*0fca6ea1SDimitry Andric child_live_addr, language_flags); 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 104*0fca6ea1SDimitry Andric ValueObject * 105*0fca6ea1SDimitry Andric ValueObjectConstResultImpl::CreateSyntheticArrayMember(size_t idx) { 106*0fca6ea1SDimitry Andric if (m_impl_backend == nullptr) 107*0fca6ea1SDimitry Andric return nullptr; 108*0fca6ea1SDimitry Andric 109*0fca6ea1SDimitry Andric m_impl_backend->UpdateValueIfNeeded(false); 110*0fca6ea1SDimitry Andric 111*0fca6ea1SDimitry Andric bool omit_empty_base_classes = true; 112*0fca6ea1SDimitry Andric bool ignore_array_bounds = true; 113*0fca6ea1SDimitry Andric std::string child_name; 114*0fca6ea1SDimitry Andric uint32_t child_byte_size = 0; 115*0fca6ea1SDimitry Andric int32_t child_byte_offset = 0; 116*0fca6ea1SDimitry Andric uint32_t child_bitfield_bit_size = 0; 117*0fca6ea1SDimitry Andric uint32_t child_bitfield_bit_offset = 0; 118*0fca6ea1SDimitry Andric bool child_is_base_class = false; 119*0fca6ea1SDimitry Andric bool child_is_deref_of_parent = false; 120*0fca6ea1SDimitry Andric uint64_t language_flags; 121*0fca6ea1SDimitry Andric 122*0fca6ea1SDimitry Andric const bool transparent_pointers = false; 123*0fca6ea1SDimitry Andric CompilerType compiler_type = m_impl_backend->GetCompilerType(); 124*0fca6ea1SDimitry Andric 125*0fca6ea1SDimitry Andric ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef()); 126*0fca6ea1SDimitry Andric 127*0fca6ea1SDimitry Andric auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex( 128*0fca6ea1SDimitry Andric &exe_ctx, 0, transparent_pointers, omit_empty_base_classes, 129*0fca6ea1SDimitry Andric ignore_array_bounds, child_name, child_byte_size, child_byte_offset, 130*0fca6ea1SDimitry Andric child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, 131*0fca6ea1SDimitry Andric child_is_deref_of_parent, m_impl_backend, language_flags); 132*0fca6ea1SDimitry Andric // One might think we should check that the size of the children 133*0fca6ea1SDimitry Andric // is always strictly positive, hence we could avoid creating a 134*0fca6ea1SDimitry Andric // ValueObject if that's not the case, but it turns out there 135*0fca6ea1SDimitry Andric // are languages out there which allow zero-size types with 136*0fca6ea1SDimitry Andric // children (e.g. Swift). 137*0fca6ea1SDimitry Andric if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) { 138*0fca6ea1SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Types), 139*0fca6ea1SDimitry Andric child_compiler_type_or_err.takeError(), 140*0fca6ea1SDimitry Andric "could not find child: {0}"); 141*0fca6ea1SDimitry Andric return nullptr; 142*0fca6ea1SDimitry Andric } 143*0fca6ea1SDimitry Andric 144*0fca6ea1SDimitry Andric child_byte_offset += child_byte_size * idx; 145*0fca6ea1SDimitry Andric 146*0fca6ea1SDimitry Andric lldb::addr_t child_live_addr = LLDB_INVALID_ADDRESS; 147*0fca6ea1SDimitry Andric // Transfer the live address (with offset) to the child. But if 148*0fca6ea1SDimitry Andric // the parent is a pointer, the live address is where that pointer 149*0fca6ea1SDimitry Andric // value lives in memory, so the children live addresses aren't 150*0fca6ea1SDimitry Andric // offsets from that value, they are just other load addresses that 151*0fca6ea1SDimitry Andric // are recorded in the Value of the child ValueObjects. 152*0fca6ea1SDimitry Andric if (m_live_address != LLDB_INVALID_ADDRESS && !compiler_type.IsPointerType()) 153*0fca6ea1SDimitry Andric child_live_addr = m_live_address + child_byte_offset; 154*0fca6ea1SDimitry Andric return new ValueObjectConstResultChild( 155*0fca6ea1SDimitry Andric *m_impl_backend, *child_compiler_type_or_err, ConstString(child_name), 156*0fca6ea1SDimitry Andric child_byte_size, child_byte_offset, child_bitfield_bit_size, 157*0fca6ea1SDimitry Andric child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent, 158*0fca6ea1SDimitry Andric child_live_addr, language_flags); 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric lldb::ValueObjectSP ValueObjectConstResultImpl::GetSyntheticChildAtOffset( 1620b57cec5SDimitry Andric uint32_t offset, const CompilerType &type, bool can_create, 1630b57cec5SDimitry Andric ConstString name_const_str) { 1640b57cec5SDimitry Andric if (m_impl_backend == nullptr) 1650b57cec5SDimitry Andric return lldb::ValueObjectSP(); 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric return m_impl_backend->ValueObject::GetSyntheticChildAtOffset( 1680b57cec5SDimitry Andric offset, type, can_create, name_const_str); 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf(Status &error) { 1720b57cec5SDimitry Andric if (m_address_of_backend.get() != nullptr) 1730b57cec5SDimitry Andric return m_address_of_backend; 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric if (m_impl_backend == nullptr) 1760b57cec5SDimitry Andric return lldb::ValueObjectSP(); 1770b57cec5SDimitry Andric if (m_live_address != LLDB_INVALID_ADDRESS) { 1780b57cec5SDimitry Andric CompilerType compiler_type(m_impl_backend->GetCompilerType()); 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap( 1810b57cec5SDimitry Andric &m_live_address, sizeof(lldb::addr_t))); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric std::string new_name("&"); 1840b57cec5SDimitry Andric new_name.append(m_impl_backend->GetName().AsCString("")); 1850b57cec5SDimitry Andric ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef()); 1860b57cec5SDimitry Andric m_address_of_backend = ValueObjectConstResult::Create( 1870b57cec5SDimitry Andric exe_ctx.GetBestExecutionContextScope(), compiler_type.GetPointerType(), 1880b57cec5SDimitry Andric ConstString(new_name.c_str()), buffer, endian::InlHostByteOrder(), 1890b57cec5SDimitry Andric exe_ctx.GetAddressByteSize()); 1900b57cec5SDimitry Andric 191fe6060f1SDimitry Andric m_address_of_backend->GetValue().SetValueType(Value::ValueType::Scalar); 1920b57cec5SDimitry Andric m_address_of_backend->GetValue().GetScalar() = m_live_address; 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric return m_address_of_backend; 1950b57cec5SDimitry Andric } else 1960b57cec5SDimitry Andric return m_impl_backend->ValueObject::AddressOf(error); 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric lldb::ValueObjectSP 2000b57cec5SDimitry Andric ValueObjectConstResultImpl::Cast(const CompilerType &compiler_type) { 2010b57cec5SDimitry Andric if (m_impl_backend == nullptr) 2020b57cec5SDimitry Andric return lldb::ValueObjectSP(); 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric ValueObjectConstResultCast *result_cast = 2050b57cec5SDimitry Andric new ValueObjectConstResultCast(*m_impl_backend, m_impl_backend->GetName(), 2060b57cec5SDimitry Andric compiler_type, m_live_address); 2070b57cec5SDimitry Andric return result_cast->GetSP(); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric lldb::addr_t 2110b57cec5SDimitry Andric ValueObjectConstResultImpl::GetAddressOf(bool scalar_is_load_address, 2120b57cec5SDimitry Andric AddressType *address_type) { 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric if (m_impl_backend == nullptr) 2150b57cec5SDimitry Andric return 0; 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric if (m_live_address == LLDB_INVALID_ADDRESS) { 2180b57cec5SDimitry Andric return m_impl_backend->ValueObject::GetAddressOf(scalar_is_load_address, 2190b57cec5SDimitry Andric address_type); 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric if (address_type) 2230b57cec5SDimitry Andric *address_type = m_live_address_type; 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric return m_live_address; 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric size_t ValueObjectConstResultImpl::GetPointeeData(DataExtractor &data, 2290b57cec5SDimitry Andric uint32_t item_idx, 2300b57cec5SDimitry Andric uint32_t item_count) { 2310b57cec5SDimitry Andric if (m_impl_backend == nullptr) 2320b57cec5SDimitry Andric return 0; 2330b57cec5SDimitry Andric return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, 2340b57cec5SDimitry Andric item_count); 2350b57cec5SDimitry Andric } 236