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/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 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), 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(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 children 76 // is always strictly positive, hence we could avoid creating a 77 // ValueObject if that's not the case, but it turns out there 78 // are languages out there which allow zero-size types with 79 // 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 if 89 // the parent is a pointer, the live address is where that pointer 90 // value lives in memory, so the children live addresses aren't 91 // offsets from that value, they are just other load addresses that 92 // 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 103 ValueObject * 104 ValueObjectConstResultImpl::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 children 132 // is always strictly positive, hence we could avoid creating a 133 // ValueObject if that's not the case, but it turns out there 134 // are languages out there which allow zero-size types with 135 // 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 if 147 // the parent is a pointer, the live address is where that pointer 148 // value lives in memory, so the children live addresses aren't 149 // offsets from that value, they are just other load addresses that 150 // 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 160 lldb::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 170 lldb::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 } else 195 return m_impl_backend->ValueObject::AddressOf(error); 196 } 197 198 lldb::ValueObjectSP 199 ValueObjectConstResultImpl::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 209 ValueObject::AddrAndType 210 ValueObjectConstResultImpl::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 221 size_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