1 //===-- ValueObjectConstResultImpl.cpp ---------------------------*- C++-*-===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Core/ValueObjectConstResultImpl.h" 10 11 #include "lldb/Core/Value.h" 12 #include "lldb/Core/ValueObject.h" 13 #include "lldb/Core/ValueObjectConstResult.h" 14 #include "lldb/Core/ValueObjectConstResultCast.h" 15 #include "lldb/Core/ValueObjectConstResultChild.h" 16 #include "lldb/Symbol/CompilerType.h" 17 #include "lldb/Target/ExecutionContext.h" 18 #include "lldb/Utility/DataBufferHeap.h" 19 #include "lldb/Utility/Endian.h" 20 #include "lldb/Utility/Scalar.h" 21 #include "lldb/Utility/SharingPtr.h" 22 23 #include <string> 24 25 namespace lldb_private { 26 class DataExtractor; 27 } 28 namespace lldb_private { 29 class Status; 30 } 31 32 using namespace lldb; 33 using namespace lldb_private; 34 35 ValueObjectConstResultImpl::ValueObjectConstResultImpl( 36 ValueObject *valobj, lldb::addr_t live_address) 37 : m_impl_backend(valobj), m_live_address(live_address), 38 m_live_address_type(eAddressTypeLoad), m_load_addr_backend(), 39 m_address_of_backend() {} 40 41 lldb::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 48 ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex( 49 size_t idx, bool synthetic_array_member, int32_t synthetic_index) { 50 if (m_impl_backend == nullptr) 51 return nullptr; 52 53 m_impl_backend->UpdateValueIfNeeded(false); 54 55 ValueObjectConstResultChild *valobj = nullptr; 56 57 bool omit_empty_base_classes = true; 58 bool ignore_array_bounds = synthetic_array_member; 59 std::string child_name_str; 60 uint32_t child_byte_size = 0; 61 int32_t child_byte_offset = 0; 62 uint32_t child_bitfield_bit_size = 0; 63 uint32_t child_bitfield_bit_offset = 0; 64 bool child_is_base_class = false; 65 bool child_is_deref_of_parent = false; 66 uint64_t language_flags; 67 68 const bool transparent_pointers = !synthetic_array_member; 69 CompilerType compiler_type = m_impl_backend->GetCompilerType(); 70 CompilerType child_compiler_type; 71 72 ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef()); 73 74 child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex( 75 &exe_ctx, idx, transparent_pointers, omit_empty_base_classes, 76 ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset, 77 child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, 78 child_is_deref_of_parent, m_impl_backend, language_flags); 79 80 // One might think we should check that the size of the children 81 // is always strictly positive, hence we could avoid creating a 82 // ValueObject if that's not the case, but it turns out there 83 // are languages out there which allow zero-size types with 84 // children (e.g. Swift). 85 if (child_compiler_type) { 86 if (synthetic_index) 87 child_byte_offset += child_byte_size * synthetic_index; 88 89 ConstString child_name; 90 if (!child_name_str.empty()) 91 child_name.SetCString(child_name_str.c_str()); 92 93 valobj = new ValueObjectConstResultChild( 94 *m_impl_backend, child_compiler_type, child_name, child_byte_size, 95 child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, 96 child_is_base_class, child_is_deref_of_parent, 97 m_live_address == LLDB_INVALID_ADDRESS 98 ? m_live_address 99 : m_live_address + child_byte_offset, 100 language_flags); 101 } 102 103 return valobj; 104 } 105 106 lldb::ValueObjectSP ValueObjectConstResultImpl::GetSyntheticChildAtOffset( 107 uint32_t offset, const CompilerType &type, bool can_create, 108 ConstString name_const_str) { 109 if (m_impl_backend == nullptr) 110 return lldb::ValueObjectSP(); 111 112 return m_impl_backend->ValueObject::GetSyntheticChildAtOffset( 113 offset, type, can_create, name_const_str); 114 } 115 116 lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf(Status &error) { 117 if (m_address_of_backend.get() != nullptr) 118 return m_address_of_backend; 119 120 if (m_impl_backend == nullptr) 121 return lldb::ValueObjectSP(); 122 if (m_live_address != LLDB_INVALID_ADDRESS) { 123 CompilerType compiler_type(m_impl_backend->GetCompilerType()); 124 125 lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap( 126 &m_live_address, sizeof(lldb::addr_t))); 127 128 std::string new_name("&"); 129 new_name.append(m_impl_backend->GetName().AsCString("")); 130 ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef()); 131 m_address_of_backend = ValueObjectConstResult::Create( 132 exe_ctx.GetBestExecutionContextScope(), compiler_type.GetPointerType(), 133 ConstString(new_name.c_str()), buffer, endian::InlHostByteOrder(), 134 exe_ctx.GetAddressByteSize()); 135 136 m_address_of_backend->GetValue().SetValueType(Value::eValueTypeScalar); 137 m_address_of_backend->GetValue().GetScalar() = m_live_address; 138 139 return m_address_of_backend; 140 } else 141 return m_impl_backend->ValueObject::AddressOf(error); 142 } 143 144 lldb::ValueObjectSP 145 ValueObjectConstResultImpl::Cast(const CompilerType &compiler_type) { 146 if (m_impl_backend == nullptr) 147 return lldb::ValueObjectSP(); 148 149 ValueObjectConstResultCast *result_cast = 150 new ValueObjectConstResultCast(*m_impl_backend, m_impl_backend->GetName(), 151 compiler_type, m_live_address); 152 return result_cast->GetSP(); 153 } 154 155 lldb::addr_t 156 ValueObjectConstResultImpl::GetAddressOf(bool scalar_is_load_address, 157 AddressType *address_type) { 158 159 if (m_impl_backend == nullptr) 160 return 0; 161 162 if (m_live_address == LLDB_INVALID_ADDRESS) { 163 return m_impl_backend->ValueObject::GetAddressOf(scalar_is_load_address, 164 address_type); 165 } 166 167 if (address_type) 168 *address_type = m_live_address_type; 169 170 return m_live_address; 171 } 172 173 size_t ValueObjectConstResultImpl::GetPointeeData(DataExtractor &data, 174 uint32_t item_idx, 175 uint32_t item_count) { 176 if (m_impl_backend == nullptr) 177 return 0; 178 return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, 179 item_count); 180 } 181