1dda28197Spatrick //===-- ValueObjectVariable.cpp -------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "lldb/Core/ValueObjectVariable.h"
10061da546Spatrick
11061da546Spatrick #include "lldb/Core/Address.h"
12061da546Spatrick #include "lldb/Core/AddressRange.h"
13be691f3bSpatrick #include "lldb/Core/Declaration.h"
14061da546Spatrick #include "lldb/Core/Module.h"
15061da546Spatrick #include "lldb/Core/Value.h"
16*f6aab3d8Srobert #include "lldb/Expression/DWARFExpressionList.h"
17061da546Spatrick #include "lldb/Symbol/Function.h"
18061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
19061da546Spatrick #include "lldb/Symbol/SymbolContext.h"
20061da546Spatrick #include "lldb/Symbol/SymbolContextScope.h"
21061da546Spatrick #include "lldb/Symbol/Type.h"
22061da546Spatrick #include "lldb/Symbol/Variable.h"
23061da546Spatrick #include "lldb/Target/ExecutionContext.h"
24061da546Spatrick #include "lldb/Target/Process.h"
25061da546Spatrick #include "lldb/Target/RegisterContext.h"
26061da546Spatrick #include "lldb/Target/Target.h"
27061da546Spatrick #include "lldb/Utility/DataExtractor.h"
28061da546Spatrick #include "lldb/Utility/RegisterValue.h"
29061da546Spatrick #include "lldb/Utility/Scalar.h"
30061da546Spatrick #include "lldb/Utility/Status.h"
31061da546Spatrick #include "lldb/lldb-private-enumerations.h"
32061da546Spatrick #include "lldb/lldb-types.h"
33061da546Spatrick
34061da546Spatrick #include "llvm/ADT/StringRef.h"
35061da546Spatrick
36be691f3bSpatrick #include <cassert>
37061da546Spatrick #include <memory>
38*f6aab3d8Srobert #include <optional>
39061da546Spatrick
40061da546Spatrick namespace lldb_private {
41061da546Spatrick class ExecutionContextScope;
42061da546Spatrick }
43061da546Spatrick namespace lldb_private {
44061da546Spatrick class StackFrame;
45061da546Spatrick }
46061da546Spatrick namespace lldb_private {
47061da546Spatrick struct RegisterInfo;
48061da546Spatrick }
49061da546Spatrick using namespace lldb_private;
50061da546Spatrick
51061da546Spatrick lldb::ValueObjectSP
Create(ExecutionContextScope * exe_scope,const lldb::VariableSP & var_sp)52061da546Spatrick ValueObjectVariable::Create(ExecutionContextScope *exe_scope,
53061da546Spatrick const lldb::VariableSP &var_sp) {
54dda28197Spatrick auto manager_sp = ValueObjectManager::Create();
55dda28197Spatrick return (new ValueObjectVariable(exe_scope, *manager_sp, var_sp))->GetSP();
56061da546Spatrick }
57061da546Spatrick
ValueObjectVariable(ExecutionContextScope * exe_scope,ValueObjectManager & manager,const lldb::VariableSP & var_sp)58061da546Spatrick ValueObjectVariable::ValueObjectVariable(ExecutionContextScope *exe_scope,
59dda28197Spatrick ValueObjectManager &manager,
60061da546Spatrick const lldb::VariableSP &var_sp)
61dda28197Spatrick : ValueObject(exe_scope, manager), m_variable_sp(var_sp) {
62061da546Spatrick // Do not attempt to construct one of these objects with no variable!
63061da546Spatrick assert(m_variable_sp.get() != nullptr);
64061da546Spatrick m_name = var_sp->GetName();
65061da546Spatrick }
66061da546Spatrick
67be691f3bSpatrick ValueObjectVariable::~ValueObjectVariable() = default;
68061da546Spatrick
GetCompilerTypeImpl()69061da546Spatrick CompilerType ValueObjectVariable::GetCompilerTypeImpl() {
70061da546Spatrick Type *var_type = m_variable_sp->GetType();
71061da546Spatrick if (var_type)
72061da546Spatrick return var_type->GetForwardCompilerType();
73061da546Spatrick return CompilerType();
74061da546Spatrick }
75061da546Spatrick
GetTypeName()76061da546Spatrick ConstString ValueObjectVariable::GetTypeName() {
77061da546Spatrick Type *var_type = m_variable_sp->GetType();
78061da546Spatrick if (var_type)
79061da546Spatrick return var_type->GetName();
80061da546Spatrick return ConstString();
81061da546Spatrick }
82061da546Spatrick
GetDisplayTypeName()83061da546Spatrick ConstString ValueObjectVariable::GetDisplayTypeName() {
84061da546Spatrick Type *var_type = m_variable_sp->GetType();
85061da546Spatrick if (var_type)
86061da546Spatrick return var_type->GetForwardCompilerType().GetDisplayTypeName();
87061da546Spatrick return ConstString();
88061da546Spatrick }
89061da546Spatrick
GetQualifiedTypeName()90061da546Spatrick ConstString ValueObjectVariable::GetQualifiedTypeName() {
91061da546Spatrick Type *var_type = m_variable_sp->GetType();
92061da546Spatrick if (var_type)
93061da546Spatrick return var_type->GetQualifiedName();
94061da546Spatrick return ConstString();
95061da546Spatrick }
96061da546Spatrick
CalculateNumChildren(uint32_t max)97061da546Spatrick size_t ValueObjectVariable::CalculateNumChildren(uint32_t max) {
98061da546Spatrick CompilerType type(GetCompilerType());
99061da546Spatrick
100061da546Spatrick if (!type.IsValid())
101061da546Spatrick return 0;
102061da546Spatrick
103061da546Spatrick ExecutionContext exe_ctx(GetExecutionContextRef());
104061da546Spatrick const bool omit_empty_base_classes = true;
105061da546Spatrick auto child_count = type.GetNumChildren(omit_empty_base_classes, &exe_ctx);
106061da546Spatrick return child_count <= max ? child_count : max;
107061da546Spatrick }
108061da546Spatrick
GetByteSize()109*f6aab3d8Srobert std::optional<uint64_t> ValueObjectVariable::GetByteSize() {
110061da546Spatrick ExecutionContext exe_ctx(GetExecutionContextRef());
111061da546Spatrick
112061da546Spatrick CompilerType type(GetCompilerType());
113061da546Spatrick
114061da546Spatrick if (!type.IsValid())
115be691f3bSpatrick return {};
116061da546Spatrick
117be691f3bSpatrick return type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
118061da546Spatrick }
119061da546Spatrick
GetValueType() const120061da546Spatrick lldb::ValueType ValueObjectVariable::GetValueType() const {
121061da546Spatrick if (m_variable_sp)
122061da546Spatrick return m_variable_sp->GetScope();
123061da546Spatrick return lldb::eValueTypeInvalid;
124061da546Spatrick }
125061da546Spatrick
UpdateValue()126061da546Spatrick bool ValueObjectVariable::UpdateValue() {
127061da546Spatrick SetValueIsValid(false);
128061da546Spatrick m_error.Clear();
129061da546Spatrick
130061da546Spatrick Variable *variable = m_variable_sp.get();
131*f6aab3d8Srobert DWARFExpressionList &expr_list = variable->LocationExpressionList();
132061da546Spatrick
133061da546Spatrick if (variable->GetLocationIsConstantValueData()) {
134061da546Spatrick // expr doesn't contain DWARF bytes, it contains the constant variable
135061da546Spatrick // value bytes themselves...
136*f6aab3d8Srobert if (expr_list.GetExpressionData(m_data)) {
137be691f3bSpatrick if (m_data.GetDataStart() && m_data.GetByteSize())
138be691f3bSpatrick m_value.SetBytes(m_data.GetDataStart(), m_data.GetByteSize());
139be691f3bSpatrick m_value.SetContext(Value::ContextType::Variable, variable);
140*f6aab3d8Srobert } else
141061da546Spatrick m_error.SetErrorString("empty constant data");
142061da546Spatrick // constant bytes can't be edited - sorry
143be691f3bSpatrick m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr);
144061da546Spatrick } else {
145061da546Spatrick lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS;
146061da546Spatrick ExecutionContext exe_ctx(GetExecutionContextRef());
147061da546Spatrick
148061da546Spatrick Target *target = exe_ctx.GetTargetPtr();
149061da546Spatrick if (target) {
150061da546Spatrick m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
151061da546Spatrick m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
152061da546Spatrick }
153061da546Spatrick
154*f6aab3d8Srobert if (!expr_list.IsAlwaysValidSingleExpr()) {
155061da546Spatrick SymbolContext sc;
156061da546Spatrick variable->CalculateSymbolContext(&sc);
157061da546Spatrick if (sc.function)
158061da546Spatrick loclist_base_load_addr =
159061da546Spatrick sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(
160061da546Spatrick target);
161061da546Spatrick }
162061da546Spatrick Value old_value(m_value);
163*f6aab3d8Srobert if (expr_list.Evaluate(&exe_ctx, nullptr, loclist_base_load_addr, nullptr,
164061da546Spatrick nullptr, m_value, &m_error)) {
165061da546Spatrick m_resolved_value = m_value;
166be691f3bSpatrick m_value.SetContext(Value::ContextType::Variable, variable);
167061da546Spatrick
168061da546Spatrick CompilerType compiler_type = GetCompilerType();
169061da546Spatrick if (compiler_type.IsValid())
170061da546Spatrick m_value.SetCompilerType(compiler_type);
171061da546Spatrick
172061da546Spatrick Value::ValueType value_type = m_value.GetValueType();
173061da546Spatrick
174dda28197Spatrick // The size of the buffer within m_value can be less than the size
175dda28197Spatrick // prescribed by its type. E.g. this can happen when an expression only
176dda28197Spatrick // partially describes an object (say, because it contains DW_OP_piece).
177dda28197Spatrick //
178dda28197Spatrick // In this case, grow m_value to the expected size. An alternative way to
179dda28197Spatrick // handle this is to teach Value::GetValueAsData() and ValueObjectChild
180dda28197Spatrick // not to read past the end of a host buffer, but this gets impractically
181dda28197Spatrick // complicated as a Value's host buffer may be shared with a distant
182dda28197Spatrick // ancestor or sibling in the ValueObject hierarchy.
183dda28197Spatrick //
184dda28197Spatrick // FIXME: When we grow m_value, we should represent the added bits as
185dda28197Spatrick // undefined somehow instead of as 0's.
186be691f3bSpatrick if (value_type == Value::ValueType::HostAddress &&
187dda28197Spatrick compiler_type.IsValid()) {
188dda28197Spatrick if (size_t value_buf_size = m_value.GetBuffer().GetByteSize()) {
189dda28197Spatrick size_t value_size = m_value.GetValueByteSize(&m_error, &exe_ctx);
190dda28197Spatrick if (m_error.Success() && value_buf_size < value_size)
191dda28197Spatrick m_value.ResizeData(value_size);
192dda28197Spatrick }
193dda28197Spatrick }
194dda28197Spatrick
195061da546Spatrick Process *process = exe_ctx.GetProcessPtr();
196061da546Spatrick const bool process_is_alive = process && process->IsAlive();
197061da546Spatrick
198061da546Spatrick switch (value_type) {
199be691f3bSpatrick case Value::ValueType::Invalid:
200be691f3bSpatrick m_error.SetErrorString("invalid value");
201be691f3bSpatrick break;
202be691f3bSpatrick case Value::ValueType::Scalar:
203061da546Spatrick // The variable value is in the Scalar value inside the m_value. We can
204061da546Spatrick // point our m_data right to it.
205061da546Spatrick m_error =
206061da546Spatrick m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
207061da546Spatrick break;
208061da546Spatrick
209be691f3bSpatrick case Value::ValueType::FileAddress:
210be691f3bSpatrick case Value::ValueType::LoadAddress:
211be691f3bSpatrick case Value::ValueType::HostAddress:
212061da546Spatrick // The DWARF expression result was an address in the inferior process.
213061da546Spatrick // If this variable is an aggregate type, we just need the address as
214061da546Spatrick // the main value as all child variable objects will rely upon this
215061da546Spatrick // location and add an offset and then read their own values as needed.
216061da546Spatrick // If this variable is a simple type, we read all data for it into
217061da546Spatrick // m_data. Make sure this type has a value before we try and read it
218061da546Spatrick
219061da546Spatrick // If we have a file address, convert it to a load address if we can.
220be691f3bSpatrick if (value_type == Value::ValueType::FileAddress && process_is_alive)
221061da546Spatrick m_value.ConvertToLoadAddress(GetModule().get(), target);
222061da546Spatrick
223061da546Spatrick if (!CanProvideValue()) {
224061da546Spatrick // this value object represents an aggregate type whose children have
225061da546Spatrick // values, but this object does not. So we say we are changed if our
226061da546Spatrick // location has changed.
227061da546Spatrick SetValueDidChange(value_type != old_value.GetValueType() ||
228061da546Spatrick m_value.GetScalar() != old_value.GetScalar());
229061da546Spatrick } else {
230061da546Spatrick // Copy the Value and set the context to use our Variable so it can
231061da546Spatrick // extract read its value into m_data appropriately
232061da546Spatrick Value value(m_value);
233be691f3bSpatrick value.SetContext(Value::ContextType::Variable, variable);
234061da546Spatrick m_error =
235061da546Spatrick value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
236061da546Spatrick
237061da546Spatrick SetValueDidChange(value_type != old_value.GetValueType() ||
238061da546Spatrick m_value.GetScalar() != old_value.GetScalar());
239061da546Spatrick }
240061da546Spatrick break;
241061da546Spatrick }
242061da546Spatrick
243061da546Spatrick SetValueIsValid(m_error.Success());
244061da546Spatrick } else {
245061da546Spatrick // could not find location, won't allow editing
246be691f3bSpatrick m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr);
247061da546Spatrick }
248061da546Spatrick }
249dda28197Spatrick
250061da546Spatrick return m_error.Success();
251061da546Spatrick }
252061da546Spatrick
DoUpdateChildrenAddressType(ValueObject & valobj)253dda28197Spatrick void ValueObjectVariable::DoUpdateChildrenAddressType(ValueObject &valobj) {
254dda28197Spatrick Value::ValueType value_type = valobj.GetValue().GetValueType();
255dda28197Spatrick ExecutionContext exe_ctx(GetExecutionContextRef());
256dda28197Spatrick Process *process = exe_ctx.GetProcessPtr();
257dda28197Spatrick const bool process_is_alive = process && process->IsAlive();
258dda28197Spatrick const uint32_t type_info = valobj.GetCompilerType().GetTypeInfo();
259dda28197Spatrick const bool is_pointer_or_ref =
260dda28197Spatrick (type_info & (lldb::eTypeIsPointer | lldb::eTypeIsReference)) != 0;
261dda28197Spatrick
262dda28197Spatrick switch (value_type) {
263be691f3bSpatrick case Value::ValueType::Invalid:
264be691f3bSpatrick break;
265be691f3bSpatrick case Value::ValueType::FileAddress:
266dda28197Spatrick // If this type is a pointer, then its children will be considered load
267dda28197Spatrick // addresses if the pointer or reference is dereferenced, but only if
268dda28197Spatrick // the process is alive.
269dda28197Spatrick //
270dda28197Spatrick // There could be global variables like in the following code:
271dda28197Spatrick // struct LinkedListNode { Foo* foo; LinkedListNode* next; };
272dda28197Spatrick // Foo g_foo1;
273dda28197Spatrick // Foo g_foo2;
274dda28197Spatrick // LinkedListNode g_second_node = { &g_foo2, NULL };
275dda28197Spatrick // LinkedListNode g_first_node = { &g_foo1, &g_second_node };
276dda28197Spatrick //
277dda28197Spatrick // When we aren't running, we should be able to look at these variables
278dda28197Spatrick // using the "target variable" command. Children of the "g_first_node"
279dda28197Spatrick // always will be of the same address type as the parent. But children
280dda28197Spatrick // of the "next" member of LinkedListNode will become load addresses if
281dda28197Spatrick // we have a live process, or remain a file address if it was a file
282dda28197Spatrick // address.
283dda28197Spatrick if (process_is_alive && is_pointer_or_ref)
284dda28197Spatrick valobj.SetAddressTypeOfChildren(eAddressTypeLoad);
285dda28197Spatrick else
286dda28197Spatrick valobj.SetAddressTypeOfChildren(eAddressTypeFile);
287dda28197Spatrick break;
288be691f3bSpatrick case Value::ValueType::HostAddress:
289dda28197Spatrick // Same as above for load addresses, except children of pointer or refs
290dda28197Spatrick // are always load addresses. Host addresses are used to store freeze
291dda28197Spatrick // dried variables. If this type is a struct, the entire struct
292dda28197Spatrick // contents will be copied into the heap of the
293dda28197Spatrick // LLDB process, but we do not currently follow any pointers.
294dda28197Spatrick if (is_pointer_or_ref)
295dda28197Spatrick valobj.SetAddressTypeOfChildren(eAddressTypeLoad);
296dda28197Spatrick else
297dda28197Spatrick valobj.SetAddressTypeOfChildren(eAddressTypeHost);
298dda28197Spatrick break;
299be691f3bSpatrick case Value::ValueType::LoadAddress:
300be691f3bSpatrick case Value::ValueType::Scalar:
301dda28197Spatrick valobj.SetAddressTypeOfChildren(eAddressTypeLoad);
302dda28197Spatrick break;
303dda28197Spatrick }
304dda28197Spatrick }
305dda28197Spatrick
306dda28197Spatrick
307dda28197Spatrick
IsInScope()308061da546Spatrick bool ValueObjectVariable::IsInScope() {
309061da546Spatrick const ExecutionContextRef &exe_ctx_ref = GetExecutionContextRef();
310061da546Spatrick if (exe_ctx_ref.HasFrameRef()) {
311061da546Spatrick ExecutionContext exe_ctx(exe_ctx_ref);
312061da546Spatrick StackFrame *frame = exe_ctx.GetFramePtr();
313061da546Spatrick if (frame) {
314061da546Spatrick return m_variable_sp->IsInScope(frame);
315061da546Spatrick } else {
316061da546Spatrick // This ValueObject had a frame at one time, but now we can't locate it,
317061da546Spatrick // so return false since we probably aren't in scope.
318061da546Spatrick return false;
319061da546Spatrick }
320061da546Spatrick }
321061da546Spatrick // We have a variable that wasn't tied to a frame, which means it is a global
322061da546Spatrick // and is always in scope.
323061da546Spatrick return true;
324061da546Spatrick }
325061da546Spatrick
GetModule()326061da546Spatrick lldb::ModuleSP ValueObjectVariable::GetModule() {
327061da546Spatrick if (m_variable_sp) {
328061da546Spatrick SymbolContextScope *sc_scope = m_variable_sp->GetSymbolContextScope();
329061da546Spatrick if (sc_scope) {
330061da546Spatrick return sc_scope->CalculateSymbolContextModule();
331061da546Spatrick }
332061da546Spatrick }
333061da546Spatrick return lldb::ModuleSP();
334061da546Spatrick }
335061da546Spatrick
GetSymbolContextScope()336061da546Spatrick SymbolContextScope *ValueObjectVariable::GetSymbolContextScope() {
337061da546Spatrick if (m_variable_sp)
338061da546Spatrick return m_variable_sp->GetSymbolContextScope();
339061da546Spatrick return nullptr;
340061da546Spatrick }
341061da546Spatrick
GetDeclaration(Declaration & decl)342061da546Spatrick bool ValueObjectVariable::GetDeclaration(Declaration &decl) {
343061da546Spatrick if (m_variable_sp) {
344061da546Spatrick decl = m_variable_sp->GetDeclaration();
345061da546Spatrick return true;
346061da546Spatrick }
347061da546Spatrick return false;
348061da546Spatrick }
349061da546Spatrick
GetLocationAsCString()350061da546Spatrick const char *ValueObjectVariable::GetLocationAsCString() {
351be691f3bSpatrick if (m_resolved_value.GetContextType() == Value::ContextType::RegisterInfo)
352061da546Spatrick return GetLocationAsCStringImpl(m_resolved_value, m_data);
353061da546Spatrick else
354061da546Spatrick return ValueObject::GetLocationAsCString();
355061da546Spatrick }
356061da546Spatrick
SetValueFromCString(const char * value_str,Status & error)357061da546Spatrick bool ValueObjectVariable::SetValueFromCString(const char *value_str,
358061da546Spatrick Status &error) {
359061da546Spatrick if (!UpdateValueIfNeeded()) {
360061da546Spatrick error.SetErrorString("unable to update value before writing");
361061da546Spatrick return false;
362061da546Spatrick }
363061da546Spatrick
364be691f3bSpatrick if (m_resolved_value.GetContextType() == Value::ContextType::RegisterInfo) {
365061da546Spatrick RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo();
366061da546Spatrick ExecutionContext exe_ctx(GetExecutionContextRef());
367061da546Spatrick RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
368061da546Spatrick RegisterValue reg_value;
369061da546Spatrick if (!reg_info || !reg_ctx) {
370061da546Spatrick error.SetErrorString("unable to retrieve register info");
371061da546Spatrick return false;
372061da546Spatrick }
373061da546Spatrick error = reg_value.SetValueFromString(reg_info, llvm::StringRef(value_str));
374061da546Spatrick if (error.Fail())
375061da546Spatrick return false;
376061da546Spatrick if (reg_ctx->WriteRegister(reg_info, reg_value)) {
377061da546Spatrick SetNeedsUpdate();
378061da546Spatrick return true;
379061da546Spatrick } else {
380061da546Spatrick error.SetErrorString("unable to write back to register");
381061da546Spatrick return false;
382061da546Spatrick }
383061da546Spatrick } else
384061da546Spatrick return ValueObject::SetValueFromCString(value_str, error);
385061da546Spatrick }
386061da546Spatrick
SetData(DataExtractor & data,Status & error)387061da546Spatrick bool ValueObjectVariable::SetData(DataExtractor &data, Status &error) {
388061da546Spatrick if (!UpdateValueIfNeeded()) {
389061da546Spatrick error.SetErrorString("unable to update value before writing");
390061da546Spatrick return false;
391061da546Spatrick }
392061da546Spatrick
393be691f3bSpatrick if (m_resolved_value.GetContextType() == Value::ContextType::RegisterInfo) {
394061da546Spatrick RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo();
395061da546Spatrick ExecutionContext exe_ctx(GetExecutionContextRef());
396061da546Spatrick RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
397061da546Spatrick RegisterValue reg_value;
398061da546Spatrick if (!reg_info || !reg_ctx) {
399061da546Spatrick error.SetErrorString("unable to retrieve register info");
400061da546Spatrick return false;
401061da546Spatrick }
402*f6aab3d8Srobert error = reg_value.SetValueFromData(*reg_info, data, 0, true);
403061da546Spatrick if (error.Fail())
404061da546Spatrick return false;
405061da546Spatrick if (reg_ctx->WriteRegister(reg_info, reg_value)) {
406061da546Spatrick SetNeedsUpdate();
407061da546Spatrick return true;
408061da546Spatrick } else {
409061da546Spatrick error.SetErrorString("unable to write back to register");
410061da546Spatrick return false;
411061da546Spatrick }
412061da546Spatrick } else
413061da546Spatrick return ValueObject::SetData(data, error);
414061da546Spatrick }
415