File: | build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/lldb/source/Core/ValueObjectVariable.cpp |
Warning: | line 54, column 10 Potential memory leak |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- ValueObjectVariable.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/ValueObjectVariable.h" | |||
10 | ||||
11 | #include "lldb/Core/Address.h" | |||
12 | #include "lldb/Core/AddressRange.h" | |||
13 | #include "lldb/Core/Declaration.h" | |||
14 | #include "lldb/Core/Module.h" | |||
15 | #include "lldb/Core/Value.h" | |||
16 | #include "lldb/Expression/DWARFExpression.h" | |||
17 | #include "lldb/Symbol/Function.h" | |||
18 | #include "lldb/Symbol/ObjectFile.h" | |||
19 | #include "lldb/Symbol/SymbolContext.h" | |||
20 | #include "lldb/Symbol/SymbolContextScope.h" | |||
21 | #include "lldb/Symbol/Type.h" | |||
22 | #include "lldb/Symbol/Variable.h" | |||
23 | #include "lldb/Target/ExecutionContext.h" | |||
24 | #include "lldb/Target/Process.h" | |||
25 | #include "lldb/Target/RegisterContext.h" | |||
26 | #include "lldb/Target/Target.h" | |||
27 | #include "lldb/Utility/DataExtractor.h" | |||
28 | #include "lldb/Utility/RegisterValue.h" | |||
29 | #include "lldb/Utility/Scalar.h" | |||
30 | #include "lldb/Utility/Status.h" | |||
31 | #include "lldb/lldb-private-enumerations.h" | |||
32 | #include "lldb/lldb-types.h" | |||
33 | ||||
34 | #include "llvm/ADT/StringRef.h" | |||
35 | ||||
36 | #include <cassert> | |||
37 | #include <memory> | |||
38 | ||||
39 | namespace lldb_private { | |||
40 | class ExecutionContextScope; | |||
41 | } | |||
42 | namespace lldb_private { | |||
43 | class StackFrame; | |||
44 | } | |||
45 | namespace lldb_private { | |||
46 | struct RegisterInfo; | |||
47 | } | |||
48 | using namespace lldb_private; | |||
49 | ||||
50 | lldb::ValueObjectSP | |||
51 | ValueObjectVariable::Create(ExecutionContextScope *exe_scope, | |||
52 | const lldb::VariableSP &var_sp) { | |||
53 | auto manager_sp = ValueObjectManager::Create(); | |||
54 | return (new ValueObjectVariable(exe_scope, *manager_sp, var_sp))->GetSP(); | |||
| ||||
| ||||
55 | } | |||
56 | ||||
57 | ValueObjectVariable::ValueObjectVariable(ExecutionContextScope *exe_scope, | |||
58 | ValueObjectManager &manager, | |||
59 | const lldb::VariableSP &var_sp) | |||
60 | : ValueObject(exe_scope, manager), m_variable_sp(var_sp) { | |||
61 | // Do not attempt to construct one of these objects with no variable! | |||
62 | assert(m_variable_sp.get() != nullptr)(static_cast <bool> (m_variable_sp.get() != nullptr) ? void (0) : __assert_fail ("m_variable_sp.get() != nullptr", "lldb/source/Core/ValueObjectVariable.cpp" , 62, __extension__ __PRETTY_FUNCTION__)); | |||
63 | m_name = var_sp->GetName(); | |||
64 | } | |||
65 | ||||
66 | ValueObjectVariable::~ValueObjectVariable() = default; | |||
67 | ||||
68 | CompilerType ValueObjectVariable::GetCompilerTypeImpl() { | |||
69 | Type *var_type = m_variable_sp->GetType(); | |||
70 | if (var_type) | |||
71 | return var_type->GetForwardCompilerType(); | |||
72 | return CompilerType(); | |||
73 | } | |||
74 | ||||
75 | ConstString ValueObjectVariable::GetTypeName() { | |||
76 | Type *var_type = m_variable_sp->GetType(); | |||
77 | if (var_type) | |||
78 | return var_type->GetName(); | |||
79 | return ConstString(); | |||
80 | } | |||
81 | ||||
82 | ConstString ValueObjectVariable::GetDisplayTypeName() { | |||
83 | Type *var_type = m_variable_sp->GetType(); | |||
84 | if (var_type) | |||
85 | return var_type->GetForwardCompilerType().GetDisplayTypeName(); | |||
86 | return ConstString(); | |||
87 | } | |||
88 | ||||
89 | ConstString ValueObjectVariable::GetQualifiedTypeName() { | |||
90 | Type *var_type = m_variable_sp->GetType(); | |||
91 | if (var_type) | |||
92 | return var_type->GetQualifiedName(); | |||
93 | return ConstString(); | |||
94 | } | |||
95 | ||||
96 | size_t ValueObjectVariable::CalculateNumChildren(uint32_t max) { | |||
97 | CompilerType type(GetCompilerType()); | |||
98 | ||||
99 | if (!type.IsValid()) | |||
100 | return 0; | |||
101 | ||||
102 | ExecutionContext exe_ctx(GetExecutionContextRef()); | |||
103 | const bool omit_empty_base_classes = true; | |||
104 | auto child_count = type.GetNumChildren(omit_empty_base_classes, &exe_ctx); | |||
105 | return child_count <= max ? child_count : max; | |||
106 | } | |||
107 | ||||
108 | llvm::Optional<uint64_t> ValueObjectVariable::GetByteSize() { | |||
109 | ExecutionContext exe_ctx(GetExecutionContextRef()); | |||
110 | ||||
111 | CompilerType type(GetCompilerType()); | |||
112 | ||||
113 | if (!type.IsValid()) | |||
114 | return {}; | |||
115 | ||||
116 | return type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); | |||
117 | } | |||
118 | ||||
119 | lldb::ValueType ValueObjectVariable::GetValueType() const { | |||
120 | if (m_variable_sp) | |||
121 | return m_variable_sp->GetScope(); | |||
122 | return lldb::eValueTypeInvalid; | |||
123 | } | |||
124 | ||||
125 | bool ValueObjectVariable::UpdateValue() { | |||
126 | SetValueIsValid(false); | |||
127 | m_error.Clear(); | |||
128 | ||||
129 | Variable *variable = m_variable_sp.get(); | |||
130 | DWARFExpression &expr = variable->LocationExpression(); | |||
131 | ||||
132 | if (variable->GetLocationIsConstantValueData()) { | |||
133 | // expr doesn't contain DWARF bytes, it contains the constant variable | |||
134 | // value bytes themselves... | |||
135 | if (expr.GetExpressionData(m_data)) { | |||
136 | if (m_data.GetDataStart() && m_data.GetByteSize()) | |||
137 | m_value.SetBytes(m_data.GetDataStart(), m_data.GetByteSize()); | |||
138 | m_value.SetContext(Value::ContextType::Variable, variable); | |||
139 | } | |||
140 | else | |||
141 | m_error.SetErrorString("empty constant data"); | |||
142 | // constant bytes can't be edited - sorry | |||
143 | m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr); | |||
144 | } else { | |||
145 | lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
146 | ExecutionContext exe_ctx(GetExecutionContextRef()); | |||
147 | ||||
148 | Target *target = exe_ctx.GetTargetPtr(); | |||
149 | if (target) { | |||
150 | m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); | |||
151 | m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); | |||
152 | } | |||
153 | ||||
154 | if (expr.IsLocationList()) { | |||
155 | SymbolContext sc; | |||
156 | variable->CalculateSymbolContext(&sc); | |||
157 | if (sc.function) | |||
158 | loclist_base_load_addr = | |||
159 | sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress( | |||
160 | target); | |||
161 | } | |||
162 | Value old_value(m_value); | |||
163 | if (expr.Evaluate(&exe_ctx, nullptr, loclist_base_load_addr, nullptr, | |||
164 | nullptr, m_value, &m_error)) { | |||
165 | m_resolved_value = m_value; | |||
166 | m_value.SetContext(Value::ContextType::Variable, variable); | |||
167 | ||||
168 | CompilerType compiler_type = GetCompilerType(); | |||
169 | if (compiler_type.IsValid()) | |||
170 | m_value.SetCompilerType(compiler_type); | |||
171 | ||||
172 | Value::ValueType value_type = m_value.GetValueType(); | |||
173 | ||||
174 | // The size of the buffer within m_value can be less than the size | |||
175 | // prescribed by its type. E.g. this can happen when an expression only | |||
176 | // partially describes an object (say, because it contains DW_OP_piece). | |||
177 | // | |||
178 | // In this case, grow m_value to the expected size. An alternative way to | |||
179 | // handle this is to teach Value::GetValueAsData() and ValueObjectChild | |||
180 | // not to read past the end of a host buffer, but this gets impractically | |||
181 | // complicated as a Value's host buffer may be shared with a distant | |||
182 | // ancestor or sibling in the ValueObject hierarchy. | |||
183 | // | |||
184 | // FIXME: When we grow m_value, we should represent the added bits as | |||
185 | // undefined somehow instead of as 0's. | |||
186 | if (value_type == Value::ValueType::HostAddress && | |||
187 | compiler_type.IsValid()) { | |||
188 | if (size_t value_buf_size = m_value.GetBuffer().GetByteSize()) { | |||
189 | size_t value_size = m_value.GetValueByteSize(&m_error, &exe_ctx); | |||
190 | if (m_error.Success() && value_buf_size < value_size) | |||
191 | m_value.ResizeData(value_size); | |||
192 | } | |||
193 | } | |||
194 | ||||
195 | Process *process = exe_ctx.GetProcessPtr(); | |||
196 | const bool process_is_alive = process && process->IsAlive(); | |||
197 | ||||
198 | switch (value_type) { | |||
199 | case Value::ValueType::Invalid: | |||
200 | m_error.SetErrorString("invalid value"); | |||
201 | break; | |||
202 | case Value::ValueType::Scalar: | |||
203 | // The variable value is in the Scalar value inside the m_value. We can | |||
204 | // point our m_data right to it. | |||
205 | m_error = | |||
206 | m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); | |||
207 | break; | |||
208 | ||||
209 | case Value::ValueType::FileAddress: | |||
210 | case Value::ValueType::LoadAddress: | |||
211 | case Value::ValueType::HostAddress: | |||
212 | // The DWARF expression result was an address in the inferior process. | |||
213 | // If this variable is an aggregate type, we just need the address as | |||
214 | // the main value as all child variable objects will rely upon this | |||
215 | // location and add an offset and then read their own values as needed. | |||
216 | // If this variable is a simple type, we read all data for it into | |||
217 | // m_data. Make sure this type has a value before we try and read it | |||
218 | ||||
219 | // If we have a file address, convert it to a load address if we can. | |||
220 | if (value_type == Value::ValueType::FileAddress && process_is_alive) | |||
221 | m_value.ConvertToLoadAddress(GetModule().get(), target); | |||
222 | ||||
223 | if (!CanProvideValue()) { | |||
224 | // this value object represents an aggregate type whose children have | |||
225 | // values, but this object does not. So we say we are changed if our | |||
226 | // location has changed. | |||
227 | SetValueDidChange(value_type != old_value.GetValueType() || | |||
228 | m_value.GetScalar() != old_value.GetScalar()); | |||
229 | } else { | |||
230 | // Copy the Value and set the context to use our Variable so it can | |||
231 | // extract read its value into m_data appropriately | |||
232 | Value value(m_value); | |||
233 | value.SetContext(Value::ContextType::Variable, variable); | |||
234 | m_error = | |||
235 | value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); | |||
236 | ||||
237 | SetValueDidChange(value_type != old_value.GetValueType() || | |||
238 | m_value.GetScalar() != old_value.GetScalar()); | |||
239 | } | |||
240 | break; | |||
241 | } | |||
242 | ||||
243 | SetValueIsValid(m_error.Success()); | |||
244 | } else { | |||
245 | // could not find location, won't allow editing | |||
246 | m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr); | |||
247 | } | |||
248 | } | |||
249 | ||||
250 | return m_error.Success(); | |||
251 | } | |||
252 | ||||
253 | void ValueObjectVariable::DoUpdateChildrenAddressType(ValueObject &valobj) { | |||
254 | Value::ValueType value_type = valobj.GetValue().GetValueType(); | |||
255 | ExecutionContext exe_ctx(GetExecutionContextRef()); | |||
256 | Process *process = exe_ctx.GetProcessPtr(); | |||
257 | const bool process_is_alive = process && process->IsAlive(); | |||
258 | const uint32_t type_info = valobj.GetCompilerType().GetTypeInfo(); | |||
259 | const bool is_pointer_or_ref = | |||
260 | (type_info & (lldb::eTypeIsPointer | lldb::eTypeIsReference)) != 0; | |||
261 | ||||
262 | switch (value_type) { | |||
263 | case Value::ValueType::Invalid: | |||
264 | break; | |||
265 | case Value::ValueType::FileAddress: | |||
266 | // If this type is a pointer, then its children will be considered load | |||
267 | // addresses if the pointer or reference is dereferenced, but only if | |||
268 | // the process is alive. | |||
269 | // | |||
270 | // There could be global variables like in the following code: | |||
271 | // struct LinkedListNode { Foo* foo; LinkedListNode* next; }; | |||
272 | // Foo g_foo1; | |||
273 | // Foo g_foo2; | |||
274 | // LinkedListNode g_second_node = { &g_foo2, NULL }; | |||
275 | // LinkedListNode g_first_node = { &g_foo1, &g_second_node }; | |||
276 | // | |||
277 | // When we aren't running, we should be able to look at these variables | |||
278 | // using the "target variable" command. Children of the "g_first_node" | |||
279 | // always will be of the same address type as the parent. But children | |||
280 | // of the "next" member of LinkedListNode will become load addresses if | |||
281 | // we have a live process, or remain a file address if it was a file | |||
282 | // address. | |||
283 | if (process_is_alive && is_pointer_or_ref) | |||
284 | valobj.SetAddressTypeOfChildren(eAddressTypeLoad); | |||
285 | else | |||
286 | valobj.SetAddressTypeOfChildren(eAddressTypeFile); | |||
287 | break; | |||
288 | case Value::ValueType::HostAddress: | |||
289 | // Same as above for load addresses, except children of pointer or refs | |||
290 | // are always load addresses. Host addresses are used to store freeze | |||
291 | // dried variables. If this type is a struct, the entire struct | |||
292 | // contents will be copied into the heap of the | |||
293 | // LLDB process, but we do not currently follow any pointers. | |||
294 | if (is_pointer_or_ref) | |||
295 | valobj.SetAddressTypeOfChildren(eAddressTypeLoad); | |||
296 | else | |||
297 | valobj.SetAddressTypeOfChildren(eAddressTypeHost); | |||
298 | break; | |||
299 | case Value::ValueType::LoadAddress: | |||
300 | case Value::ValueType::Scalar: | |||
301 | valobj.SetAddressTypeOfChildren(eAddressTypeLoad); | |||
302 | break; | |||
303 | } | |||
304 | } | |||
305 | ||||
306 | ||||
307 | ||||
308 | bool ValueObjectVariable::IsInScope() { | |||
309 | const ExecutionContextRef &exe_ctx_ref = GetExecutionContextRef(); | |||
310 | if (exe_ctx_ref.HasFrameRef()) { | |||
311 | ExecutionContext exe_ctx(exe_ctx_ref); | |||
312 | StackFrame *frame = exe_ctx.GetFramePtr(); | |||
313 | if (frame) { | |||
314 | return m_variable_sp->IsInScope(frame); | |||
315 | } else { | |||
316 | // This ValueObject had a frame at one time, but now we can't locate it, | |||
317 | // so return false since we probably aren't in scope. | |||
318 | return false; | |||
319 | } | |||
320 | } | |||
321 | // We have a variable that wasn't tied to a frame, which means it is a global | |||
322 | // and is always in scope. | |||
323 | return true; | |||
324 | } | |||
325 | ||||
326 | lldb::ModuleSP ValueObjectVariable::GetModule() { | |||
327 | if (m_variable_sp) { | |||
328 | SymbolContextScope *sc_scope = m_variable_sp->GetSymbolContextScope(); | |||
329 | if (sc_scope) { | |||
330 | return sc_scope->CalculateSymbolContextModule(); | |||
331 | } | |||
332 | } | |||
333 | return lldb::ModuleSP(); | |||
334 | } | |||
335 | ||||
336 | SymbolContextScope *ValueObjectVariable::GetSymbolContextScope() { | |||
337 | if (m_variable_sp) | |||
338 | return m_variable_sp->GetSymbolContextScope(); | |||
339 | return nullptr; | |||
340 | } | |||
341 | ||||
342 | bool ValueObjectVariable::GetDeclaration(Declaration &decl) { | |||
343 | if (m_variable_sp) { | |||
344 | decl = m_variable_sp->GetDeclaration(); | |||
345 | return true; | |||
346 | } | |||
347 | return false; | |||
348 | } | |||
349 | ||||
350 | const char *ValueObjectVariable::GetLocationAsCString() { | |||
351 | if (m_resolved_value.GetContextType() == Value::ContextType::RegisterInfo) | |||
352 | return GetLocationAsCStringImpl(m_resolved_value, m_data); | |||
353 | else | |||
354 | return ValueObject::GetLocationAsCString(); | |||
355 | } | |||
356 | ||||
357 | bool ValueObjectVariable::SetValueFromCString(const char *value_str, | |||
358 | Status &error) { | |||
359 | if (!UpdateValueIfNeeded()) { | |||
360 | error.SetErrorString("unable to update value before writing"); | |||
361 | return false; | |||
362 | } | |||
363 | ||||
364 | if (m_resolved_value.GetContextType() == Value::ContextType::RegisterInfo) { | |||
365 | RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo(); | |||
366 | ExecutionContext exe_ctx(GetExecutionContextRef()); | |||
367 | RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); | |||
368 | RegisterValue reg_value; | |||
369 | if (!reg_info || !reg_ctx) { | |||
370 | error.SetErrorString("unable to retrieve register info"); | |||
371 | return false; | |||
372 | } | |||
373 | error = reg_value.SetValueFromString(reg_info, llvm::StringRef(value_str)); | |||
374 | if (error.Fail()) | |||
375 | return false; | |||
376 | if (reg_ctx->WriteRegister(reg_info, reg_value)) { | |||
377 | SetNeedsUpdate(); | |||
378 | return true; | |||
379 | } else { | |||
380 | error.SetErrorString("unable to write back to register"); | |||
381 | return false; | |||
382 | } | |||
383 | } else | |||
384 | return ValueObject::SetValueFromCString(value_str, error); | |||
385 | } | |||
386 | ||||
387 | bool ValueObjectVariable::SetData(DataExtractor &data, Status &error) { | |||
388 | if (!UpdateValueIfNeeded()) { | |||
389 | error.SetErrorString("unable to update value before writing"); | |||
390 | return false; | |||
391 | } | |||
392 | ||||
393 | if (m_resolved_value.GetContextType() == Value::ContextType::RegisterInfo) { | |||
394 | RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo(); | |||
395 | ExecutionContext exe_ctx(GetExecutionContextRef()); | |||
396 | RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); | |||
397 | RegisterValue reg_value; | |||
398 | if (!reg_info || !reg_ctx) { | |||
399 | error.SetErrorString("unable to retrieve register info"); | |||
400 | return false; | |||
401 | } | |||
402 | error = reg_value.SetValueFromData(reg_info, data, 0, true); | |||
403 | if (error.Fail()) | |||
404 | return false; | |||
405 | if (reg_ctx->WriteRegister(reg_info, reg_value)) { | |||
406 | SetNeedsUpdate(); | |||
407 | return true; | |||
408 | } else { | |||
409 | error.SetErrorString("unable to write back to register"); | |||
410 | return false; | |||
411 | } | |||
412 | } else | |||
413 | return ValueObject::SetData(data, error); | |||
414 | } |