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