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