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