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 ; |
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(update_format: 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: &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, valobj: 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(update_format: 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: &exe_ctx, idx: 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, valobj: 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(s: m_impl_backend->GetName().AsCString(value_if_empty: "" )); |
184 | ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef()); |
185 | m_address_of_backend = ValueObjectConstResult::Create( |
186 | exe_scope: exe_ctx.GetBestExecutionContextScope(), compiler_type: compiler_type.GetPointerType(), |
187 | name: ConstString(new_name.c_str()), result_data_sp: buffer, byte_order: endian::InlHostByteOrder(), |
188 | addr_size: 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 {.address: 0, .type: eAddressTypeInvalid}; |
214 | |
215 | if (m_live_address == LLDB_INVALID_ADDRESS) |
216 | return m_impl_backend->ValueObject::GetAddressOf(scalar_is_load_address); |
217 | |
218 | return {.address: m_live_address, .type: m_live_address_type}; |
219 | } |
220 | |
221 | size_t ValueObjectConstResultImpl::(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 | |