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"
219dba64beSDimitry Andric #include "lldb/Utility/Log.h"
220b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h"
230b57cec5SDimitry Andric #include "lldb/Utility/Status.h"
240b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
270b57cec5SDimitry Andric
28*5f7ddb14SDimitry Andric #include <cassert>
290b57cec5SDimitry Andric #include <memory>
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric namespace lldb_private {
320b57cec5SDimitry Andric class ExecutionContextScope;
330b57cec5SDimitry Andric }
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric using namespace lldb;
360b57cec5SDimitry Andric using namespace lldb_private;
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric #pragma mark ValueObjectRegisterSet
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric ValueObjectSP
Create(ExecutionContextScope * exe_scope,lldb::RegisterContextSP & reg_ctx_sp,uint32_t set_idx)410b57cec5SDimitry Andric ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope,
420b57cec5SDimitry Andric lldb::RegisterContextSP ®_ctx_sp,
430b57cec5SDimitry Andric uint32_t set_idx) {
445ffd83dbSDimitry Andric auto manager_sp = ValueObjectManager::Create();
455ffd83dbSDimitry Andric return (new ValueObjectRegisterSet(exe_scope, *manager_sp, reg_ctx_sp,
465ffd83dbSDimitry Andric set_idx))
475ffd83dbSDimitry Andric ->GetSP();
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric
ValueObjectRegisterSet(ExecutionContextScope * exe_scope,ValueObjectManager & manager,lldb::RegisterContextSP & reg_ctx,uint32_t reg_set_idx)500b57cec5SDimitry Andric ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
515ffd83dbSDimitry Andric ValueObjectManager &manager,
520b57cec5SDimitry Andric lldb::RegisterContextSP ®_ctx,
530b57cec5SDimitry Andric uint32_t reg_set_idx)
545ffd83dbSDimitry Andric : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx),
555ffd83dbSDimitry Andric m_reg_set(nullptr), m_reg_set_idx(reg_set_idx) {
560b57cec5SDimitry Andric assert(reg_ctx);
570b57cec5SDimitry Andric m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);
580b57cec5SDimitry Andric if (m_reg_set) {
590b57cec5SDimitry Andric m_name.SetCString(m_reg_set->name);
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric
63*5f7ddb14SDimitry Andric ValueObjectRegisterSet::~ValueObjectRegisterSet() = default;
640b57cec5SDimitry Andric
GetCompilerTypeImpl()650b57cec5SDimitry Andric CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {
660b57cec5SDimitry Andric return CompilerType();
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric
GetTypeName()690b57cec5SDimitry Andric ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); }
700b57cec5SDimitry Andric
GetQualifiedTypeName()710b57cec5SDimitry Andric ConstString ValueObjectRegisterSet::GetQualifiedTypeName() {
720b57cec5SDimitry Andric return ConstString();
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric
CalculateNumChildren(uint32_t max)750b57cec5SDimitry Andric size_t ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) {
760b57cec5SDimitry Andric const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
770b57cec5SDimitry Andric if (reg_set) {
780b57cec5SDimitry Andric auto reg_count = reg_set->num_registers;
790b57cec5SDimitry Andric return reg_count <= max ? reg_count : max;
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric return 0;
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric
GetByteSize()84af732203SDimitry Andric llvm::Optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
850b57cec5SDimitry Andric
UpdateValue()860b57cec5SDimitry Andric bool ValueObjectRegisterSet::UpdateValue() {
870b57cec5SDimitry Andric m_error.Clear();
880b57cec5SDimitry Andric SetValueDidChange(false);
890b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef());
900b57cec5SDimitry Andric StackFrame *frame = exe_ctx.GetFramePtr();
910b57cec5SDimitry Andric if (frame == nullptr)
920b57cec5SDimitry Andric m_reg_ctx_sp.reset();
930b57cec5SDimitry Andric else {
940b57cec5SDimitry Andric m_reg_ctx_sp = frame->GetRegisterContext();
950b57cec5SDimitry Andric if (m_reg_ctx_sp) {
960b57cec5SDimitry Andric const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
970b57cec5SDimitry Andric if (reg_set == nullptr)
980b57cec5SDimitry Andric m_reg_ctx_sp.reset();
990b57cec5SDimitry Andric else if (m_reg_set != reg_set) {
1000b57cec5SDimitry Andric SetValueDidChange(true);
1010b57cec5SDimitry Andric m_name.SetCString(reg_set->name);
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric if (m_reg_ctx_sp) {
1060b57cec5SDimitry Andric SetValueIsValid(true);
1070b57cec5SDimitry Andric } else {
1080b57cec5SDimitry Andric SetValueIsValid(false);
1090b57cec5SDimitry Andric m_error.SetErrorToGenericError();
1100b57cec5SDimitry Andric m_children.Clear();
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric return m_error.Success();
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric
CreateChildAtIndex(size_t idx,bool synthetic_array_member,int32_t synthetic_index)1150b57cec5SDimitry Andric ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(
1160b57cec5SDimitry Andric size_t idx, bool synthetic_array_member, int32_t synthetic_index) {
1170b57cec5SDimitry Andric ValueObject *valobj = nullptr;
1180b57cec5SDimitry Andric if (m_reg_ctx_sp && m_reg_set) {
1190b57cec5SDimitry Andric const size_t num_children = GetNumChildren();
1200b57cec5SDimitry Andric if (idx < num_children)
1210b57cec5SDimitry Andric valobj = new ValueObjectRegister(*this, m_reg_ctx_sp,
1220b57cec5SDimitry Andric m_reg_set->registers[idx]);
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric return valobj;
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric lldb::ValueObjectSP
GetChildMemberWithName(ConstString name,bool can_create)1280b57cec5SDimitry Andric ValueObjectRegisterSet::GetChildMemberWithName(ConstString name,
1290b57cec5SDimitry Andric bool can_create) {
1300b57cec5SDimitry Andric ValueObject *valobj = nullptr;
1310b57cec5SDimitry Andric if (m_reg_ctx_sp && m_reg_set) {
1320b57cec5SDimitry Andric const RegisterInfo *reg_info =
1335ffd83dbSDimitry Andric m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef());
1340b57cec5SDimitry Andric if (reg_info != nullptr)
1350b57cec5SDimitry Andric valobj = new ValueObjectRegister(*this, m_reg_ctx_sp,
1360b57cec5SDimitry Andric reg_info->kinds[eRegisterKindLLDB]);
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric if (valobj)
1390b57cec5SDimitry Andric return valobj->GetSP();
1400b57cec5SDimitry Andric else
1410b57cec5SDimitry Andric return ValueObjectSP();
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andric size_t
GetIndexOfChildWithName(ConstString name)1450b57cec5SDimitry Andric ValueObjectRegisterSet::GetIndexOfChildWithName(ConstString name) {
1460b57cec5SDimitry Andric if (m_reg_ctx_sp && m_reg_set) {
1470b57cec5SDimitry Andric const RegisterInfo *reg_info =
1485ffd83dbSDimitry Andric m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef());
1490b57cec5SDimitry Andric if (reg_info != nullptr)
1500b57cec5SDimitry Andric return reg_info->kinds[eRegisterKindLLDB];
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric return UINT32_MAX;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric
1550b57cec5SDimitry Andric #pragma mark -
1560b57cec5SDimitry Andric #pragma mark ValueObjectRegister
1570b57cec5SDimitry Andric
ConstructObject(uint32_t reg_num)1580b57cec5SDimitry Andric void ValueObjectRegister::ConstructObject(uint32_t reg_num) {
1590b57cec5SDimitry Andric const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoAtIndex(reg_num);
1600b57cec5SDimitry Andric if (reg_info) {
1610b57cec5SDimitry Andric m_reg_info = *reg_info;
1620b57cec5SDimitry Andric if (reg_info->name)
1630b57cec5SDimitry Andric m_name.SetCString(reg_info->name);
1640b57cec5SDimitry Andric else if (reg_info->alt_name)
1650b57cec5SDimitry Andric m_name.SetCString(reg_info->alt_name);
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric
ValueObjectRegister(ValueObject & parent,lldb::RegisterContextSP & reg_ctx_sp,uint32_t reg_num)1690b57cec5SDimitry Andric ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
1700b57cec5SDimitry Andric lldb::RegisterContextSP ®_ctx_sp,
1710b57cec5SDimitry Andric uint32_t reg_num)
1720b57cec5SDimitry Andric : ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),
1730b57cec5SDimitry Andric m_reg_value(), m_type_name(), m_compiler_type() {
1740b57cec5SDimitry Andric assert(reg_ctx_sp.get());
1750b57cec5SDimitry Andric ConstructObject(reg_num);
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric
Create(ExecutionContextScope * exe_scope,lldb::RegisterContextSP & reg_ctx_sp,uint32_t reg_num)1780b57cec5SDimitry Andric ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
1790b57cec5SDimitry Andric lldb::RegisterContextSP ®_ctx_sp,
1800b57cec5SDimitry Andric uint32_t reg_num) {
1815ffd83dbSDimitry Andric auto manager_sp = ValueObjectManager::Create();
1825ffd83dbSDimitry Andric return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_num))
1835ffd83dbSDimitry Andric ->GetSP();
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric
ValueObjectRegister(ExecutionContextScope * exe_scope,ValueObjectManager & manager,lldb::RegisterContextSP & reg_ctx,uint32_t reg_num)1860b57cec5SDimitry Andric ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
1875ffd83dbSDimitry Andric ValueObjectManager &manager,
1880b57cec5SDimitry Andric lldb::RegisterContextSP ®_ctx,
1890b57cec5SDimitry Andric uint32_t reg_num)
1905ffd83dbSDimitry Andric : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(),
1910b57cec5SDimitry Andric m_reg_value(), m_type_name(), m_compiler_type() {
1920b57cec5SDimitry Andric assert(reg_ctx);
1930b57cec5SDimitry Andric ConstructObject(reg_num);
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric
196*5f7ddb14SDimitry Andric ValueObjectRegister::~ValueObjectRegister() = default;
1970b57cec5SDimitry Andric
GetCompilerTypeImpl()1980b57cec5SDimitry Andric CompilerType ValueObjectRegister::GetCompilerTypeImpl() {
1990b57cec5SDimitry Andric if (!m_compiler_type.IsValid()) {
2000b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef());
2019dba64beSDimitry Andric if (auto *target = exe_ctx.GetTargetPtr()) {
2029dba64beSDimitry Andric if (auto *exe_module = target->GetExecutableModulePointer()) {
2039dba64beSDimitry Andric auto type_system_or_err =
2040b57cec5SDimitry Andric exe_module->GetTypeSystemForLanguage(eLanguageTypeC);
2059dba64beSDimitry Andric if (auto err = type_system_or_err.takeError()) {
2069dba64beSDimitry Andric LLDB_LOG_ERROR(
2079dba64beSDimitry Andric lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TYPES),
2089dba64beSDimitry Andric std::move(err), "Unable to get CompilerType from TypeSystem");
2099dba64beSDimitry Andric } else {
2109dba64beSDimitry Andric m_compiler_type =
2119dba64beSDimitry Andric type_system_or_err->GetBuiltinTypeForEncodingAndBitSize(
2120b57cec5SDimitry Andric m_reg_info.encoding, m_reg_info.byte_size * 8);
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric }
2169dba64beSDimitry Andric }
2170b57cec5SDimitry Andric return m_compiler_type;
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric
GetTypeName()2200b57cec5SDimitry Andric ConstString ValueObjectRegister::GetTypeName() {
2210b57cec5SDimitry Andric if (m_type_name.IsEmpty())
2225ffd83dbSDimitry Andric m_type_name = GetCompilerType().GetTypeName();
2230b57cec5SDimitry Andric return m_type_name;
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric
CalculateNumChildren(uint32_t max)2260b57cec5SDimitry Andric size_t ValueObjectRegister::CalculateNumChildren(uint32_t max) {
2270b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef());
2280b57cec5SDimitry Andric auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
2290b57cec5SDimitry Andric return children_count <= max ? children_count : max;
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric
GetByteSize()232af732203SDimitry Andric llvm::Optional<uint64_t> ValueObjectRegister::GetByteSize() {
233af732203SDimitry Andric return m_reg_info.byte_size;
234af732203SDimitry Andric }
2350b57cec5SDimitry Andric
UpdateValue()2360b57cec5SDimitry Andric bool ValueObjectRegister::UpdateValue() {
2370b57cec5SDimitry Andric m_error.Clear();
2380b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef());
2390b57cec5SDimitry Andric StackFrame *frame = exe_ctx.GetFramePtr();
2400b57cec5SDimitry Andric if (frame == nullptr) {
2410b57cec5SDimitry Andric m_reg_ctx_sp.reset();
2420b57cec5SDimitry Andric m_reg_value.Clear();
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric
2450b57cec5SDimitry Andric if (m_reg_ctx_sp) {
2460b57cec5SDimitry Andric RegisterValue m_old_reg_value(m_reg_value);
2470b57cec5SDimitry Andric if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) {
2480b57cec5SDimitry Andric if (m_reg_value.GetData(m_data)) {
2490b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr();
2500b57cec5SDimitry Andric if (process)
2510b57cec5SDimitry Andric m_data.SetAddressByteSize(process->GetAddressByteSize());
252*5f7ddb14SDimitry Andric m_value.SetContext(Value::ContextType::RegisterInfo,
2530b57cec5SDimitry Andric (void *)&m_reg_info);
254*5f7ddb14SDimitry Andric m_value.SetValueType(Value::ValueType::HostAddress);
2550b57cec5SDimitry Andric m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
2560b57cec5SDimitry Andric SetValueIsValid(true);
2570b57cec5SDimitry Andric SetValueDidChange(!(m_old_reg_value == m_reg_value));
2580b57cec5SDimitry Andric return true;
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric }
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric SetValueIsValid(false);
2640b57cec5SDimitry Andric m_error.SetErrorToGenericError();
2650b57cec5SDimitry Andric return false;
2660b57cec5SDimitry Andric }
2670b57cec5SDimitry Andric
SetValueFromCString(const char * value_str,Status & error)2680b57cec5SDimitry Andric bool ValueObjectRegister::SetValueFromCString(const char *value_str,
2690b57cec5SDimitry Andric Status &error) {
2700b57cec5SDimitry Andric // The new value will be in the m_data. Copy that into our register value.
2710b57cec5SDimitry Andric error =
2720b57cec5SDimitry Andric m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));
2730b57cec5SDimitry Andric if (error.Success()) {
2740b57cec5SDimitry Andric if (m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
2750b57cec5SDimitry Andric SetNeedsUpdate();
2760b57cec5SDimitry Andric return true;
2770b57cec5SDimitry Andric } else
2780b57cec5SDimitry Andric return false;
2790b57cec5SDimitry Andric } else
2800b57cec5SDimitry Andric return false;
2810b57cec5SDimitry Andric }
2820b57cec5SDimitry Andric
SetData(DataExtractor & data,Status & error)2830b57cec5SDimitry Andric bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {
2840b57cec5SDimitry Andric error = m_reg_value.SetValueFromData(&m_reg_info, data, 0, false);
2850b57cec5SDimitry Andric if (error.Success()) {
2860b57cec5SDimitry Andric if (m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
2870b57cec5SDimitry Andric SetNeedsUpdate();
2880b57cec5SDimitry Andric return true;
2890b57cec5SDimitry Andric } else
2900b57cec5SDimitry Andric return false;
2910b57cec5SDimitry Andric } else
2920b57cec5SDimitry Andric return false;
2930b57cec5SDimitry Andric }
2940b57cec5SDimitry Andric
ResolveValue(Scalar & scalar)2950b57cec5SDimitry Andric bool ValueObjectRegister::ResolveValue(Scalar &scalar) {
2960b57cec5SDimitry Andric if (UpdateValueIfNeeded(
2970b57cec5SDimitry Andric false)) // make sure that you are up to date before returning anything
2980b57cec5SDimitry Andric return m_reg_value.GetScalarValue(scalar);
2990b57cec5SDimitry Andric return false;
3000b57cec5SDimitry Andric }
3010b57cec5SDimitry Andric
GetExpressionPath(Stream & s,GetExpressionPathFormat epformat)3020b57cec5SDimitry Andric void ValueObjectRegister::GetExpressionPath(Stream &s,
3030b57cec5SDimitry Andric GetExpressionPathFormat epformat) {
3040b57cec5SDimitry Andric s.Printf("$%s", m_reg_info.name);
3050b57cec5SDimitry Andric }
306