15ffd83dbSDimitry Andric //===-- ValueObjectRegister.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/ValueObjectRegister.h" 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "lldb/Core/Module.h" 120b57cec5SDimitry Andric #include "lldb/Core/Value.h" 130b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h" 140b57cec5SDimitry Andric #include "lldb/Symbol/TypeSystem.h" 150b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h" 160b57cec5SDimitry Andric #include "lldb/Target/Process.h" 170b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h" 180b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h" 190b57cec5SDimitry Andric #include "lldb/Target/Target.h" 200b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h" 2181ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 229dba64beSDimitry Andric #include "lldb/Utility/Log.h" 230b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h" 240b57cec5SDimitry Andric #include "lldb/Utility/Status.h" 250b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 280b57cec5SDimitry Andric 29fe6060f1SDimitry Andric #include <cassert> 300b57cec5SDimitry Andric #include <memory> 31bdd1243dSDimitry Andric #include <optional> 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric namespace lldb_private { 340b57cec5SDimitry Andric class ExecutionContextScope; 350b57cec5SDimitry Andric } 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric using namespace lldb; 380b57cec5SDimitry Andric using namespace lldb_private; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric #pragma mark ValueObjectRegisterSet 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric ValueObjectSP 430b57cec5SDimitry Andric ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope, 440b57cec5SDimitry Andric lldb::RegisterContextSP ®_ctx_sp, 450b57cec5SDimitry Andric uint32_t set_idx) { 465ffd83dbSDimitry Andric auto manager_sp = ValueObjectManager::Create(); 475ffd83dbSDimitry Andric return (new ValueObjectRegisterSet(exe_scope, *manager_sp, reg_ctx_sp, 485ffd83dbSDimitry Andric set_idx)) 495ffd83dbSDimitry Andric ->GetSP(); 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope, 535ffd83dbSDimitry Andric ValueObjectManager &manager, 540b57cec5SDimitry Andric lldb::RegisterContextSP ®_ctx, 550b57cec5SDimitry Andric uint32_t reg_set_idx) 565ffd83dbSDimitry Andric : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), 575ffd83dbSDimitry Andric m_reg_set(nullptr), m_reg_set_idx(reg_set_idx) { 580b57cec5SDimitry Andric assert(reg_ctx); 590b57cec5SDimitry Andric m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx); 600b57cec5SDimitry Andric if (m_reg_set) { 610b57cec5SDimitry Andric m_name.SetCString(m_reg_set->name); 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric 65fe6060f1SDimitry Andric ValueObjectRegisterSet::~ValueObjectRegisterSet() = default; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() { 680b57cec5SDimitry Andric return CompilerType(); 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); } 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric ConstString ValueObjectRegisterSet::GetQualifiedTypeName() { 740b57cec5SDimitry Andric return ConstString(); 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 77*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> 78*0fca6ea1SDimitry Andric ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) { 790b57cec5SDimitry Andric const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx); 800b57cec5SDimitry Andric if (reg_set) { 810b57cec5SDimitry Andric auto reg_count = reg_set->num_registers; 820b57cec5SDimitry Andric return reg_count <= max ? reg_count : max; 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric return 0; 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric 87bdd1243dSDimitry Andric std::optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric bool ValueObjectRegisterSet::UpdateValue() { 900b57cec5SDimitry Andric m_error.Clear(); 910b57cec5SDimitry Andric SetValueDidChange(false); 920b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 930b57cec5SDimitry Andric StackFrame *frame = exe_ctx.GetFramePtr(); 940b57cec5SDimitry Andric if (frame == nullptr) 950b57cec5SDimitry Andric m_reg_ctx_sp.reset(); 960b57cec5SDimitry Andric else { 970b57cec5SDimitry Andric m_reg_ctx_sp = frame->GetRegisterContext(); 980b57cec5SDimitry Andric if (m_reg_ctx_sp) { 990b57cec5SDimitry Andric const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx); 1000b57cec5SDimitry Andric if (reg_set == nullptr) 1010b57cec5SDimitry Andric m_reg_ctx_sp.reset(); 1020b57cec5SDimitry Andric else if (m_reg_set != reg_set) { 1030b57cec5SDimitry Andric SetValueDidChange(true); 1040b57cec5SDimitry Andric m_name.SetCString(reg_set->name); 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric if (m_reg_ctx_sp) { 1090b57cec5SDimitry Andric SetValueIsValid(true); 1100b57cec5SDimitry Andric } else { 1110b57cec5SDimitry Andric SetValueIsValid(false); 1120b57cec5SDimitry Andric m_error.SetErrorToGenericError(); 1130b57cec5SDimitry Andric m_children.Clear(); 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric return m_error.Success(); 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric 118*0fca6ea1SDimitry Andric ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(size_t idx) { 1190b57cec5SDimitry Andric if (m_reg_ctx_sp && m_reg_set) { 120*0fca6ea1SDimitry Andric return new ValueObjectRegister( 121349cc55cSDimitry Andric *this, m_reg_ctx_sp, 122349cc55cSDimitry Andric m_reg_ctx_sp->GetRegisterInfoAtIndex(m_reg_set->registers[idx])); 1230b57cec5SDimitry Andric } 124*0fca6ea1SDimitry Andric return nullptr; 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric lldb::ValueObjectSP 12806c3fb27SDimitry Andric ValueObjectRegisterSet::GetChildMemberWithName(llvm::StringRef name, 1290b57cec5SDimitry Andric bool can_create) { 1300b57cec5SDimitry Andric ValueObject *valobj = nullptr; 1310b57cec5SDimitry Andric if (m_reg_ctx_sp && m_reg_set) { 13206c3fb27SDimitry Andric const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name); 1330b57cec5SDimitry Andric if (reg_info != nullptr) 134349cc55cSDimitry Andric valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric if (valobj) 1370b57cec5SDimitry Andric return valobj->GetSP(); 1380b57cec5SDimitry Andric else 1390b57cec5SDimitry Andric return ValueObjectSP(); 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 14206c3fb27SDimitry Andric size_t ValueObjectRegisterSet::GetIndexOfChildWithName(llvm::StringRef name) { 1430b57cec5SDimitry Andric if (m_reg_ctx_sp && m_reg_set) { 14406c3fb27SDimitry Andric const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name); 1450b57cec5SDimitry Andric if (reg_info != nullptr) 1460b57cec5SDimitry Andric return reg_info->kinds[eRegisterKindLLDB]; 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric return UINT32_MAX; 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric #pragma mark - 1520b57cec5SDimitry Andric #pragma mark ValueObjectRegister 1530b57cec5SDimitry Andric 154349cc55cSDimitry Andric void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) { 1550b57cec5SDimitry Andric if (reg_info) { 1560b57cec5SDimitry Andric m_reg_info = *reg_info; 1570b57cec5SDimitry Andric if (reg_info->name) 1580b57cec5SDimitry Andric m_name.SetCString(reg_info->name); 1590b57cec5SDimitry Andric else if (reg_info->alt_name) 1600b57cec5SDimitry Andric m_name.SetCString(reg_info->alt_name); 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric ValueObjectRegister::ValueObjectRegister(ValueObject &parent, 1650b57cec5SDimitry Andric lldb::RegisterContextSP ®_ctx_sp, 166349cc55cSDimitry Andric const RegisterInfo *reg_info) 1670b57cec5SDimitry Andric : ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(), 1680b57cec5SDimitry Andric m_reg_value(), m_type_name(), m_compiler_type() { 1690b57cec5SDimitry Andric assert(reg_ctx_sp.get()); 170349cc55cSDimitry Andric ConstructObject(reg_info); 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope, 1740b57cec5SDimitry Andric lldb::RegisterContextSP ®_ctx_sp, 175349cc55cSDimitry Andric const RegisterInfo *reg_info) { 1765ffd83dbSDimitry Andric auto manager_sp = ValueObjectManager::Create(); 177349cc55cSDimitry Andric return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info)) 1785ffd83dbSDimitry Andric ->GetSP(); 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope, 1825ffd83dbSDimitry Andric ValueObjectManager &manager, 1830b57cec5SDimitry Andric lldb::RegisterContextSP ®_ctx, 184349cc55cSDimitry Andric const RegisterInfo *reg_info) 1855ffd83dbSDimitry Andric : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(), 1860b57cec5SDimitry Andric m_reg_value(), m_type_name(), m_compiler_type() { 1870b57cec5SDimitry Andric assert(reg_ctx); 188349cc55cSDimitry Andric ConstructObject(reg_info); 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 191fe6060f1SDimitry Andric ValueObjectRegister::~ValueObjectRegister() = default; 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric CompilerType ValueObjectRegister::GetCompilerTypeImpl() { 1940b57cec5SDimitry Andric if (!m_compiler_type.IsValid()) { 1950b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 1969dba64beSDimitry Andric if (auto *target = exe_ctx.GetTargetPtr()) { 1979dba64beSDimitry Andric if (auto *exe_module = target->GetExecutableModulePointer()) { 1989dba64beSDimitry Andric auto type_system_or_err = 1990b57cec5SDimitry Andric exe_module->GetTypeSystemForLanguage(eLanguageTypeC); 2009dba64beSDimitry Andric if (auto err = type_system_or_err.takeError()) { 20181ad6265SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err), 20206c3fb27SDimitry Andric "Unable to get CompilerType from TypeSystem: {0}"); 2039dba64beSDimitry Andric } else { 204bdd1243dSDimitry Andric if (auto ts = *type_system_or_err) 205bdd1243dSDimitry Andric m_compiler_type = ts->GetBuiltinTypeForEncodingAndBitSize( 2060b57cec5SDimitry Andric m_reg_info.encoding, m_reg_info.byte_size * 8); 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric } 2109dba64beSDimitry Andric } 2110b57cec5SDimitry Andric return m_compiler_type; 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric ConstString ValueObjectRegister::GetTypeName() { 2150b57cec5SDimitry Andric if (m_type_name.IsEmpty()) 2165ffd83dbSDimitry Andric m_type_name = GetCompilerType().GetTypeName(); 2170b57cec5SDimitry Andric return m_type_name; 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric 220*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> 221*0fca6ea1SDimitry Andric ValueObjectRegister::CalculateNumChildren(uint32_t max) { 2220b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 2230b57cec5SDimitry Andric auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx); 224*0fca6ea1SDimitry Andric if (!children_count) 225*0fca6ea1SDimitry Andric return children_count; 226*0fca6ea1SDimitry Andric return *children_count <= max ? *children_count : max; 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 229bdd1243dSDimitry Andric std::optional<uint64_t> ValueObjectRegister::GetByteSize() { 230e8d8bef9SDimitry Andric return m_reg_info.byte_size; 231e8d8bef9SDimitry Andric } 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric bool ValueObjectRegister::UpdateValue() { 2340b57cec5SDimitry Andric m_error.Clear(); 2350b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 2360b57cec5SDimitry Andric StackFrame *frame = exe_ctx.GetFramePtr(); 2370b57cec5SDimitry Andric if (frame == nullptr) { 2380b57cec5SDimitry Andric m_reg_ctx_sp.reset(); 2390b57cec5SDimitry Andric m_reg_value.Clear(); 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric if (m_reg_ctx_sp) { 2430b57cec5SDimitry Andric RegisterValue m_old_reg_value(m_reg_value); 2440b57cec5SDimitry Andric if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) { 2450b57cec5SDimitry Andric if (m_reg_value.GetData(m_data)) { 2460b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 2470b57cec5SDimitry Andric if (process) 2480b57cec5SDimitry Andric m_data.SetAddressByteSize(process->GetAddressByteSize()); 249fe6060f1SDimitry Andric m_value.SetContext(Value::ContextType::RegisterInfo, 2500b57cec5SDimitry Andric (void *)&m_reg_info); 251fe6060f1SDimitry Andric m_value.SetValueType(Value::ValueType::HostAddress); 2520b57cec5SDimitry Andric m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); 2530b57cec5SDimitry Andric SetValueIsValid(true); 2540b57cec5SDimitry Andric SetValueDidChange(!(m_old_reg_value == m_reg_value)); 2550b57cec5SDimitry Andric return true; 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric SetValueIsValid(false); 2610b57cec5SDimitry Andric m_error.SetErrorToGenericError(); 2620b57cec5SDimitry Andric return false; 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric bool ValueObjectRegister::SetValueFromCString(const char *value_str, 2660b57cec5SDimitry Andric Status &error) { 2670b57cec5SDimitry Andric // The new value will be in the m_data. Copy that into our register value. 2680b57cec5SDimitry Andric error = 2690b57cec5SDimitry Andric m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str)); 27081ad6265SDimitry Andric if (!error.Success()) 27181ad6265SDimitry Andric return false; 27281ad6265SDimitry Andric 27381ad6265SDimitry Andric if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) { 27481ad6265SDimitry Andric error.SetErrorString("unable to write back to register"); 27581ad6265SDimitry Andric return false; 27681ad6265SDimitry Andric } 27781ad6265SDimitry Andric 2780b57cec5SDimitry Andric SetNeedsUpdate(); 2790b57cec5SDimitry Andric return true; 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) { 283bdd1243dSDimitry Andric error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false); 28481ad6265SDimitry Andric if (!error.Success()) 28581ad6265SDimitry Andric return false; 28681ad6265SDimitry Andric 28781ad6265SDimitry Andric if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) { 28881ad6265SDimitry Andric error.SetErrorString("unable to write back to register"); 28981ad6265SDimitry Andric return false; 29081ad6265SDimitry Andric } 29181ad6265SDimitry Andric 2920b57cec5SDimitry Andric SetNeedsUpdate(); 2930b57cec5SDimitry Andric return true; 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric bool ValueObjectRegister::ResolveValue(Scalar &scalar) { 2970b57cec5SDimitry Andric if (UpdateValueIfNeeded( 2980b57cec5SDimitry Andric false)) // make sure that you are up to date before returning anything 2990b57cec5SDimitry Andric return m_reg_value.GetScalarValue(scalar); 3000b57cec5SDimitry Andric return false; 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric void ValueObjectRegister::GetExpressionPath(Stream &s, 3040b57cec5SDimitry Andric GetExpressionPathFormat epformat) { 3050b57cec5SDimitry Andric s.Printf("$%s", m_reg_info.name); 3060b57cec5SDimitry Andric } 307