15ffd83dbSDimitry Andric //===-- ValueObjectVariable.cpp -------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "lldb/Core/ValueObjectVariable.h" 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "lldb/Core/Address.h" 120b57cec5SDimitry Andric #include "lldb/Core/AddressRange.h" 13fe6060f1SDimitry Andric #include "lldb/Core/Declaration.h" 140b57cec5SDimitry Andric #include "lldb/Core/Module.h" 150b57cec5SDimitry Andric #include "lldb/Core/Value.h" 16753f127fSDimitry Andric #include "lldb/Expression/DWARFExpressionList.h" 170b57cec5SDimitry Andric #include "lldb/Symbol/Function.h" 180b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 190b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h" 200b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContextScope.h" 210b57cec5SDimitry Andric #include "lldb/Symbol/Type.h" 220b57cec5SDimitry Andric #include "lldb/Symbol/Variable.h" 230b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h" 240b57cec5SDimitry Andric #include "lldb/Target/Process.h" 250b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h" 260b57cec5SDimitry Andric #include "lldb/Target/Target.h" 270b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h" 280b57cec5SDimitry Andric #include "lldb/Utility/RegisterValue.h" 290b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h" 300b57cec5SDimitry Andric #include "lldb/Utility/Status.h" 310b57cec5SDimitry Andric #include "lldb/lldb-private-enumerations.h" 320b57cec5SDimitry Andric #include "lldb/lldb-types.h" 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 350b57cec5SDimitry Andric 36fe6060f1SDimitry Andric #include <cassert> 370b57cec5SDimitry Andric #include <memory> 38bdd1243dSDimitry Andric #include <optional> 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric namespace lldb_private { 410b57cec5SDimitry Andric class ExecutionContextScope; 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric namespace lldb_private { 440b57cec5SDimitry Andric class StackFrame; 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric namespace lldb_private { 470b57cec5SDimitry Andric struct RegisterInfo; 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric using namespace lldb_private; 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric lldb::ValueObjectSP 520b57cec5SDimitry Andric ValueObjectVariable::Create(ExecutionContextScope *exe_scope, 530b57cec5SDimitry Andric const lldb::VariableSP &var_sp) { 545ffd83dbSDimitry Andric auto manager_sp = ValueObjectManager::Create(); 555ffd83dbSDimitry Andric return (new ValueObjectVariable(exe_scope, *manager_sp, var_sp))->GetSP(); 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric ValueObjectVariable::ValueObjectVariable(ExecutionContextScope *exe_scope, 595ffd83dbSDimitry Andric ValueObjectManager &manager, 600b57cec5SDimitry Andric const lldb::VariableSP &var_sp) 615ffd83dbSDimitry Andric : ValueObject(exe_scope, manager), m_variable_sp(var_sp) { 620b57cec5SDimitry Andric // Do not attempt to construct one of these objects with no variable! 630b57cec5SDimitry Andric assert(m_variable_sp.get() != nullptr); 640b57cec5SDimitry Andric m_name = var_sp->GetName(); 650b57cec5SDimitry Andric } 660b57cec5SDimitry Andric 67fe6060f1SDimitry Andric ValueObjectVariable::~ValueObjectVariable() = default; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric CompilerType ValueObjectVariable::GetCompilerTypeImpl() { 700b57cec5SDimitry Andric Type *var_type = m_variable_sp->GetType(); 710b57cec5SDimitry Andric if (var_type) 720b57cec5SDimitry Andric return var_type->GetForwardCompilerType(); 730b57cec5SDimitry Andric return CompilerType(); 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric ConstString ValueObjectVariable::GetTypeName() { 770b57cec5SDimitry Andric Type *var_type = m_variable_sp->GetType(); 780b57cec5SDimitry Andric if (var_type) 790b57cec5SDimitry Andric return var_type->GetName(); 800b57cec5SDimitry Andric return ConstString(); 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric ConstString ValueObjectVariable::GetDisplayTypeName() { 840b57cec5SDimitry Andric Type *var_type = m_variable_sp->GetType(); 850b57cec5SDimitry Andric if (var_type) 860b57cec5SDimitry Andric return var_type->GetForwardCompilerType().GetDisplayTypeName(); 870b57cec5SDimitry Andric return ConstString(); 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric ConstString ValueObjectVariable::GetQualifiedTypeName() { 910b57cec5SDimitry Andric Type *var_type = m_variable_sp->GetType(); 920b57cec5SDimitry Andric if (var_type) 930b57cec5SDimitry Andric return var_type->GetQualifiedName(); 940b57cec5SDimitry Andric return ConstString(); 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 97*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> 98*0fca6ea1SDimitry Andric ValueObjectVariable::CalculateNumChildren(uint32_t max) { 990b57cec5SDimitry Andric CompilerType type(GetCompilerType()); 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric if (!type.IsValid()) 102*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>("invalid type", 103*0fca6ea1SDimitry Andric llvm::inconvertibleErrorCode()); 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 1060b57cec5SDimitry Andric const bool omit_empty_base_classes = true; 1070b57cec5SDimitry Andric auto child_count = type.GetNumChildren(omit_empty_base_classes, &exe_ctx); 108*0fca6ea1SDimitry Andric if (!child_count) 109*0fca6ea1SDimitry Andric return child_count; 110*0fca6ea1SDimitry Andric return *child_count <= max ? *child_count : max; 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 113bdd1243dSDimitry Andric std::optional<uint64_t> ValueObjectVariable::GetByteSize() { 1140b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric CompilerType type(GetCompilerType()); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric if (!type.IsValid()) 119e8d8bef9SDimitry Andric return {}; 1200b57cec5SDimitry Andric 121e8d8bef9SDimitry Andric return type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric lldb::ValueType ValueObjectVariable::GetValueType() const { 1250b57cec5SDimitry Andric if (m_variable_sp) 1260b57cec5SDimitry Andric return m_variable_sp->GetScope(); 1270b57cec5SDimitry Andric return lldb::eValueTypeInvalid; 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric bool ValueObjectVariable::UpdateValue() { 1310b57cec5SDimitry Andric SetValueIsValid(false); 1320b57cec5SDimitry Andric m_error.Clear(); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric Variable *variable = m_variable_sp.get(); 135753f127fSDimitry Andric DWARFExpressionList &expr_list = variable->LocationExpressionList(); 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric if (variable->GetLocationIsConstantValueData()) { 1380b57cec5SDimitry Andric // expr doesn't contain DWARF bytes, it contains the constant variable 1390b57cec5SDimitry Andric // value bytes themselves... 140753f127fSDimitry Andric if (expr_list.GetExpressionData(m_data)) { 141e8d8bef9SDimitry Andric if (m_data.GetDataStart() && m_data.GetByteSize()) 142e8d8bef9SDimitry Andric m_value.SetBytes(m_data.GetDataStart(), m_data.GetByteSize()); 143fe6060f1SDimitry Andric m_value.SetContext(Value::ContextType::Variable, variable); 144753f127fSDimitry Andric } else 1450b57cec5SDimitry Andric m_error.SetErrorString("empty constant data"); 1460b57cec5SDimitry Andric // constant bytes can't be edited - sorry 147fe6060f1SDimitry Andric m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr); 1480b57cec5SDimitry Andric } else { 1490b57cec5SDimitry Andric lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS; 1500b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric Target *target = exe_ctx.GetTargetPtr(); 1530b57cec5SDimitry Andric if (target) { 1540b57cec5SDimitry Andric m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); 1550b57cec5SDimitry Andric m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 158753f127fSDimitry Andric if (!expr_list.IsAlwaysValidSingleExpr()) { 1590b57cec5SDimitry Andric SymbolContext sc; 1600b57cec5SDimitry Andric variable->CalculateSymbolContext(&sc); 1610b57cec5SDimitry Andric if (sc.function) 1620b57cec5SDimitry Andric loclist_base_load_addr = 1630b57cec5SDimitry Andric sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress( 1640b57cec5SDimitry Andric target); 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric Value old_value(m_value); 167*0fca6ea1SDimitry Andric llvm::Expected<Value> maybe_value = expr_list.Evaluate( 168*0fca6ea1SDimitry Andric &exe_ctx, nullptr, loclist_base_load_addr, nullptr, nullptr); 169*0fca6ea1SDimitry Andric 170*0fca6ea1SDimitry Andric if (maybe_value) { 171*0fca6ea1SDimitry Andric m_value = *maybe_value; 1720b57cec5SDimitry Andric m_resolved_value = m_value; 173fe6060f1SDimitry Andric m_value.SetContext(Value::ContextType::Variable, variable); 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric CompilerType compiler_type = GetCompilerType(); 1760b57cec5SDimitry Andric if (compiler_type.IsValid()) 1770b57cec5SDimitry Andric m_value.SetCompilerType(compiler_type); 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric Value::ValueType value_type = m_value.GetValueType(); 1800b57cec5SDimitry Andric 1815ffd83dbSDimitry Andric // The size of the buffer within m_value can be less than the size 1825ffd83dbSDimitry Andric // prescribed by its type. E.g. this can happen when an expression only 1835ffd83dbSDimitry Andric // partially describes an object (say, because it contains DW_OP_piece). 1845ffd83dbSDimitry Andric // 1855ffd83dbSDimitry Andric // In this case, grow m_value to the expected size. An alternative way to 1865ffd83dbSDimitry Andric // handle this is to teach Value::GetValueAsData() and ValueObjectChild 1875ffd83dbSDimitry Andric // not to read past the end of a host buffer, but this gets impractically 1885ffd83dbSDimitry Andric // complicated as a Value's host buffer may be shared with a distant 1895ffd83dbSDimitry Andric // ancestor or sibling in the ValueObject hierarchy. 1905ffd83dbSDimitry Andric // 1915ffd83dbSDimitry Andric // FIXME: When we grow m_value, we should represent the added bits as 1925ffd83dbSDimitry Andric // undefined somehow instead of as 0's. 193fe6060f1SDimitry Andric if (value_type == Value::ValueType::HostAddress && 1945ffd83dbSDimitry Andric compiler_type.IsValid()) { 1955ffd83dbSDimitry Andric if (size_t value_buf_size = m_value.GetBuffer().GetByteSize()) { 1965ffd83dbSDimitry Andric size_t value_size = m_value.GetValueByteSize(&m_error, &exe_ctx); 1975ffd83dbSDimitry Andric if (m_error.Success() && value_buf_size < value_size) 1985ffd83dbSDimitry Andric m_value.ResizeData(value_size); 1995ffd83dbSDimitry Andric } 2005ffd83dbSDimitry Andric } 2015ffd83dbSDimitry Andric 2020b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 2030b57cec5SDimitry Andric const bool process_is_alive = process && process->IsAlive(); 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric switch (value_type) { 206fe6060f1SDimitry Andric case Value::ValueType::Invalid: 207fe6060f1SDimitry Andric m_error.SetErrorString("invalid value"); 208fe6060f1SDimitry Andric break; 209fe6060f1SDimitry Andric case Value::ValueType::Scalar: 2100b57cec5SDimitry Andric // The variable value is in the Scalar value inside the m_value. We can 2110b57cec5SDimitry Andric // point our m_data right to it. 2120b57cec5SDimitry Andric m_error = 2139dba64beSDimitry Andric m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); 2140b57cec5SDimitry Andric break; 2150b57cec5SDimitry Andric 216fe6060f1SDimitry Andric case Value::ValueType::FileAddress: 217fe6060f1SDimitry Andric case Value::ValueType::LoadAddress: 218fe6060f1SDimitry Andric case Value::ValueType::HostAddress: 2190b57cec5SDimitry Andric // The DWARF expression result was an address in the inferior process. 2200b57cec5SDimitry Andric // If this variable is an aggregate type, we just need the address as 2210b57cec5SDimitry Andric // the main value as all child variable objects will rely upon this 2220b57cec5SDimitry Andric // location and add an offset and then read their own values as needed. 2230b57cec5SDimitry Andric // If this variable is a simple type, we read all data for it into 2240b57cec5SDimitry Andric // m_data. Make sure this type has a value before we try and read it 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric // If we have a file address, convert it to a load address if we can. 227fe6060f1SDimitry Andric if (value_type == Value::ValueType::FileAddress && process_is_alive) 2280b57cec5SDimitry Andric m_value.ConvertToLoadAddress(GetModule().get(), target); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric if (!CanProvideValue()) { 2310b57cec5SDimitry Andric // this value object represents an aggregate type whose children have 2320b57cec5SDimitry Andric // values, but this object does not. So we say we are changed if our 2330b57cec5SDimitry Andric // location has changed. 2340b57cec5SDimitry Andric SetValueDidChange(value_type != old_value.GetValueType() || 2350b57cec5SDimitry Andric m_value.GetScalar() != old_value.GetScalar()); 2360b57cec5SDimitry Andric } else { 2370b57cec5SDimitry Andric // Copy the Value and set the context to use our Variable so it can 2380b57cec5SDimitry Andric // extract read its value into m_data appropriately 2390b57cec5SDimitry Andric Value value(m_value); 240fe6060f1SDimitry Andric value.SetContext(Value::ContextType::Variable, variable); 2410b57cec5SDimitry Andric m_error = 2429dba64beSDimitry Andric value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric SetValueDidChange(value_type != old_value.GetValueType() || 2450b57cec5SDimitry Andric m_value.GetScalar() != old_value.GetScalar()); 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric break; 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric SetValueIsValid(m_error.Success()); 2510b57cec5SDimitry Andric } else { 252*0fca6ea1SDimitry Andric m_error = maybe_value.takeError(); 2530b57cec5SDimitry Andric // could not find location, won't allow editing 254fe6060f1SDimitry Andric m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr); 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric } 2575ffd83dbSDimitry Andric 2580b57cec5SDimitry Andric return m_error.Success(); 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric 2615ffd83dbSDimitry Andric void ValueObjectVariable::DoUpdateChildrenAddressType(ValueObject &valobj) { 2625ffd83dbSDimitry Andric Value::ValueType value_type = valobj.GetValue().GetValueType(); 2635ffd83dbSDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 2645ffd83dbSDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 2655ffd83dbSDimitry Andric const bool process_is_alive = process && process->IsAlive(); 2665ffd83dbSDimitry Andric const uint32_t type_info = valobj.GetCompilerType().GetTypeInfo(); 2675ffd83dbSDimitry Andric const bool is_pointer_or_ref = 2685ffd83dbSDimitry Andric (type_info & (lldb::eTypeIsPointer | lldb::eTypeIsReference)) != 0; 2695ffd83dbSDimitry Andric 2705ffd83dbSDimitry Andric switch (value_type) { 271fe6060f1SDimitry Andric case Value::ValueType::Invalid: 272fe6060f1SDimitry Andric break; 273fe6060f1SDimitry Andric case Value::ValueType::FileAddress: 2745ffd83dbSDimitry Andric // If this type is a pointer, then its children will be considered load 2755ffd83dbSDimitry Andric // addresses if the pointer or reference is dereferenced, but only if 2765ffd83dbSDimitry Andric // the process is alive. 2775ffd83dbSDimitry Andric // 2785ffd83dbSDimitry Andric // There could be global variables like in the following code: 2795ffd83dbSDimitry Andric // struct LinkedListNode { Foo* foo; LinkedListNode* next; }; 2805ffd83dbSDimitry Andric // Foo g_foo1; 2815ffd83dbSDimitry Andric // Foo g_foo2; 2825ffd83dbSDimitry Andric // LinkedListNode g_second_node = { &g_foo2, NULL }; 2835ffd83dbSDimitry Andric // LinkedListNode g_first_node = { &g_foo1, &g_second_node }; 2845ffd83dbSDimitry Andric // 2855ffd83dbSDimitry Andric // When we aren't running, we should be able to look at these variables 2865ffd83dbSDimitry Andric // using the "target variable" command. Children of the "g_first_node" 2875ffd83dbSDimitry Andric // always will be of the same address type as the parent. But children 2885ffd83dbSDimitry Andric // of the "next" member of LinkedListNode will become load addresses if 2895ffd83dbSDimitry Andric // we have a live process, or remain a file address if it was a file 2905ffd83dbSDimitry Andric // address. 2915ffd83dbSDimitry Andric if (process_is_alive && is_pointer_or_ref) 2925ffd83dbSDimitry Andric valobj.SetAddressTypeOfChildren(eAddressTypeLoad); 2935ffd83dbSDimitry Andric else 2945ffd83dbSDimitry Andric valobj.SetAddressTypeOfChildren(eAddressTypeFile); 2955ffd83dbSDimitry Andric break; 296fe6060f1SDimitry Andric case Value::ValueType::HostAddress: 2975ffd83dbSDimitry Andric // Same as above for load addresses, except children of pointer or refs 2985ffd83dbSDimitry Andric // are always load addresses. Host addresses are used to store freeze 2995ffd83dbSDimitry Andric // dried variables. If this type is a struct, the entire struct 3005ffd83dbSDimitry Andric // contents will be copied into the heap of the 3015ffd83dbSDimitry Andric // LLDB process, but we do not currently follow any pointers. 3025ffd83dbSDimitry Andric if (is_pointer_or_ref) 3035ffd83dbSDimitry Andric valobj.SetAddressTypeOfChildren(eAddressTypeLoad); 3045ffd83dbSDimitry Andric else 3055ffd83dbSDimitry Andric valobj.SetAddressTypeOfChildren(eAddressTypeHost); 3065ffd83dbSDimitry Andric break; 307fe6060f1SDimitry Andric case Value::ValueType::LoadAddress: 308fe6060f1SDimitry Andric case Value::ValueType::Scalar: 3095ffd83dbSDimitry Andric valobj.SetAddressTypeOfChildren(eAddressTypeLoad); 3105ffd83dbSDimitry Andric break; 3115ffd83dbSDimitry Andric } 3125ffd83dbSDimitry Andric } 3135ffd83dbSDimitry Andric 3145ffd83dbSDimitry Andric 3155ffd83dbSDimitry Andric 3160b57cec5SDimitry Andric bool ValueObjectVariable::IsInScope() { 3170b57cec5SDimitry Andric const ExecutionContextRef &exe_ctx_ref = GetExecutionContextRef(); 3180b57cec5SDimitry Andric if (exe_ctx_ref.HasFrameRef()) { 3190b57cec5SDimitry Andric ExecutionContext exe_ctx(exe_ctx_ref); 3200b57cec5SDimitry Andric StackFrame *frame = exe_ctx.GetFramePtr(); 3210b57cec5SDimitry Andric if (frame) { 3220b57cec5SDimitry Andric return m_variable_sp->IsInScope(frame); 3230b57cec5SDimitry Andric } else { 3240b57cec5SDimitry Andric // This ValueObject had a frame at one time, but now we can't locate it, 3250b57cec5SDimitry Andric // so return false since we probably aren't in scope. 3260b57cec5SDimitry Andric return false; 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric // We have a variable that wasn't tied to a frame, which means it is a global 3300b57cec5SDimitry Andric // and is always in scope. 3310b57cec5SDimitry Andric return true; 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric lldb::ModuleSP ValueObjectVariable::GetModule() { 3350b57cec5SDimitry Andric if (m_variable_sp) { 3360b57cec5SDimitry Andric SymbolContextScope *sc_scope = m_variable_sp->GetSymbolContextScope(); 3370b57cec5SDimitry Andric if (sc_scope) { 3380b57cec5SDimitry Andric return sc_scope->CalculateSymbolContextModule(); 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric return lldb::ModuleSP(); 3420b57cec5SDimitry Andric } 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric SymbolContextScope *ValueObjectVariable::GetSymbolContextScope() { 3450b57cec5SDimitry Andric if (m_variable_sp) 3460b57cec5SDimitry Andric return m_variable_sp->GetSymbolContextScope(); 3470b57cec5SDimitry Andric return nullptr; 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric bool ValueObjectVariable::GetDeclaration(Declaration &decl) { 3510b57cec5SDimitry Andric if (m_variable_sp) { 3520b57cec5SDimitry Andric decl = m_variable_sp->GetDeclaration(); 3530b57cec5SDimitry Andric return true; 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric return false; 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric const char *ValueObjectVariable::GetLocationAsCString() { 359fe6060f1SDimitry Andric if (m_resolved_value.GetContextType() == Value::ContextType::RegisterInfo) 3600b57cec5SDimitry Andric return GetLocationAsCStringImpl(m_resolved_value, m_data); 3610b57cec5SDimitry Andric else 3620b57cec5SDimitry Andric return ValueObject::GetLocationAsCString(); 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric bool ValueObjectVariable::SetValueFromCString(const char *value_str, 3660b57cec5SDimitry Andric Status &error) { 3670b57cec5SDimitry Andric if (!UpdateValueIfNeeded()) { 3680b57cec5SDimitry Andric error.SetErrorString("unable to update value before writing"); 3690b57cec5SDimitry Andric return false; 3700b57cec5SDimitry Andric } 3710b57cec5SDimitry Andric 372fe6060f1SDimitry Andric if (m_resolved_value.GetContextType() == Value::ContextType::RegisterInfo) { 3730b57cec5SDimitry Andric RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo(); 3740b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 3750b57cec5SDimitry Andric RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); 3760b57cec5SDimitry Andric RegisterValue reg_value; 3770b57cec5SDimitry Andric if (!reg_info || !reg_ctx) { 3780b57cec5SDimitry Andric error.SetErrorString("unable to retrieve register info"); 3790b57cec5SDimitry Andric return false; 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric error = reg_value.SetValueFromString(reg_info, llvm::StringRef(value_str)); 3820b57cec5SDimitry Andric if (error.Fail()) 3830b57cec5SDimitry Andric return false; 3840b57cec5SDimitry Andric if (reg_ctx->WriteRegister(reg_info, reg_value)) { 3850b57cec5SDimitry Andric SetNeedsUpdate(); 3860b57cec5SDimitry Andric return true; 3870b57cec5SDimitry Andric } else { 3880b57cec5SDimitry Andric error.SetErrorString("unable to write back to register"); 3890b57cec5SDimitry Andric return false; 3900b57cec5SDimitry Andric } 3910b57cec5SDimitry Andric } else 3920b57cec5SDimitry Andric return ValueObject::SetValueFromCString(value_str, error); 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric bool ValueObjectVariable::SetData(DataExtractor &data, Status &error) { 3960b57cec5SDimitry Andric if (!UpdateValueIfNeeded()) { 3970b57cec5SDimitry Andric error.SetErrorString("unable to update value before writing"); 3980b57cec5SDimitry Andric return false; 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric 401fe6060f1SDimitry Andric if (m_resolved_value.GetContextType() == Value::ContextType::RegisterInfo) { 4020b57cec5SDimitry Andric RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo(); 4030b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 4040b57cec5SDimitry Andric RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); 4050b57cec5SDimitry Andric RegisterValue reg_value; 4060b57cec5SDimitry Andric if (!reg_info || !reg_ctx) { 4070b57cec5SDimitry Andric error.SetErrorString("unable to retrieve register info"); 4080b57cec5SDimitry Andric return false; 4090b57cec5SDimitry Andric } 410bdd1243dSDimitry Andric error = reg_value.SetValueFromData(*reg_info, data, 0, true); 4110b57cec5SDimitry Andric if (error.Fail()) 4120b57cec5SDimitry Andric return false; 4130b57cec5SDimitry Andric if (reg_ctx->WriteRegister(reg_info, reg_value)) { 4140b57cec5SDimitry Andric SetNeedsUpdate(); 4150b57cec5SDimitry Andric return true; 4160b57cec5SDimitry Andric } else { 4170b57cec5SDimitry Andric error.SetErrorString("unable to write back to register"); 4180b57cec5SDimitry Andric return false; 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric } else 4210b57cec5SDimitry Andric return ValueObject::SetData(data, error); 4220b57cec5SDimitry Andric } 423