Path: blob/main/contrib/llvm-project/lldb/source/Core/ValueObjectRegister.cpp
96333 views
//===-- ValueObjectRegister.cpp -------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Core/ValueObjectRegister.h"910#include "lldb/Core/Module.h"11#include "lldb/Core/Value.h"12#include "lldb/Symbol/CompilerType.h"13#include "lldb/Symbol/TypeSystem.h"14#include "lldb/Target/ExecutionContext.h"15#include "lldb/Target/Process.h"16#include "lldb/Target/RegisterContext.h"17#include "lldb/Target/StackFrame.h"18#include "lldb/Target/Target.h"19#include "lldb/Utility/DataExtractor.h"20#include "lldb/Utility/LLDBLog.h"21#include "lldb/Utility/Log.h"22#include "lldb/Utility/Scalar.h"23#include "lldb/Utility/Status.h"24#include "lldb/Utility/Stream.h"2526#include "llvm/ADT/StringRef.h"2728#include <cassert>29#include <memory>30#include <optional>3132namespace lldb_private {33class ExecutionContextScope;34}3536using namespace lldb;37using namespace lldb_private;3839#pragma mark ValueObjectRegisterSet4041ValueObjectSP42ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope,43lldb::RegisterContextSP ®_ctx_sp,44uint32_t set_idx) {45auto manager_sp = ValueObjectManager::Create();46return (new ValueObjectRegisterSet(exe_scope, *manager_sp, reg_ctx_sp,47set_idx))48->GetSP();49}5051ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,52ValueObjectManager &manager,53lldb::RegisterContextSP ®_ctx,54uint32_t reg_set_idx)55: ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx),56m_reg_set(nullptr), m_reg_set_idx(reg_set_idx) {57assert(reg_ctx);58m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);59if (m_reg_set) {60m_name.SetCString(m_reg_set->name);61}62}6364ValueObjectRegisterSet::~ValueObjectRegisterSet() = default;6566CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {67return CompilerType();68}6970ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); }7172ConstString ValueObjectRegisterSet::GetQualifiedTypeName() {73return ConstString();74}7576llvm::Expected<uint32_t>77ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) {78const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);79if (reg_set) {80auto reg_count = reg_set->num_registers;81return reg_count <= max ? reg_count : max;82}83return 0;84}8586std::optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }8788bool ValueObjectRegisterSet::UpdateValue() {89m_error.Clear();90SetValueDidChange(false);91ExecutionContext exe_ctx(GetExecutionContextRef());92StackFrame *frame = exe_ctx.GetFramePtr();93if (frame == nullptr)94m_reg_ctx_sp.reset();95else {96m_reg_ctx_sp = frame->GetRegisterContext();97if (m_reg_ctx_sp) {98const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);99if (reg_set == nullptr)100m_reg_ctx_sp.reset();101else if (m_reg_set != reg_set) {102SetValueDidChange(true);103m_name.SetCString(reg_set->name);104}105}106}107if (m_reg_ctx_sp) {108SetValueIsValid(true);109} else {110SetValueIsValid(false);111m_error.SetErrorToGenericError();112m_children.Clear();113}114return m_error.Success();115}116117ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(size_t idx) {118if (m_reg_ctx_sp && m_reg_set) {119return new ValueObjectRegister(120*this, m_reg_ctx_sp,121m_reg_ctx_sp->GetRegisterInfoAtIndex(m_reg_set->registers[idx]));122}123return nullptr;124}125126lldb::ValueObjectSP127ValueObjectRegisterSet::GetChildMemberWithName(llvm::StringRef name,128bool can_create) {129ValueObject *valobj = nullptr;130if (m_reg_ctx_sp && m_reg_set) {131const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);132if (reg_info != nullptr)133valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info);134}135if (valobj)136return valobj->GetSP();137else138return ValueObjectSP();139}140141size_t ValueObjectRegisterSet::GetIndexOfChildWithName(llvm::StringRef name) {142if (m_reg_ctx_sp && m_reg_set) {143const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);144if (reg_info != nullptr)145return reg_info->kinds[eRegisterKindLLDB];146}147return UINT32_MAX;148}149150#pragma mark -151#pragma mark ValueObjectRegister152153void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {154if (reg_info) {155m_reg_info = *reg_info;156if (reg_info->name)157m_name.SetCString(reg_info->name);158else if (reg_info->alt_name)159m_name.SetCString(reg_info->alt_name);160}161}162163ValueObjectRegister::ValueObjectRegister(ValueObject &parent,164lldb::RegisterContextSP ®_ctx_sp,165const RegisterInfo *reg_info)166: ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),167m_reg_value(), m_type_name(), m_compiler_type() {168assert(reg_ctx_sp.get());169ConstructObject(reg_info);170}171172ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,173lldb::RegisterContextSP ®_ctx_sp,174const RegisterInfo *reg_info) {175auto manager_sp = ValueObjectManager::Create();176return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info))177->GetSP();178}179180ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,181ValueObjectManager &manager,182lldb::RegisterContextSP ®_ctx,183const RegisterInfo *reg_info)184: ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(),185m_reg_value(), m_type_name(), m_compiler_type() {186assert(reg_ctx);187ConstructObject(reg_info);188}189190ValueObjectRegister::~ValueObjectRegister() = default;191192CompilerType ValueObjectRegister::GetCompilerTypeImpl() {193if (!m_compiler_type.IsValid()) {194ExecutionContext exe_ctx(GetExecutionContextRef());195if (auto *target = exe_ctx.GetTargetPtr()) {196if (auto *exe_module = target->GetExecutableModulePointer()) {197auto type_system_or_err =198exe_module->GetTypeSystemForLanguage(eLanguageTypeC);199if (auto err = type_system_or_err.takeError()) {200LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err),201"Unable to get CompilerType from TypeSystem: {0}");202} else {203if (auto ts = *type_system_or_err)204m_compiler_type = ts->GetBuiltinTypeForEncodingAndBitSize(205m_reg_info.encoding, m_reg_info.byte_size * 8);206}207}208}209}210return m_compiler_type;211}212213ConstString ValueObjectRegister::GetTypeName() {214if (m_type_name.IsEmpty())215m_type_name = GetCompilerType().GetTypeName();216return m_type_name;217}218219llvm::Expected<uint32_t>220ValueObjectRegister::CalculateNumChildren(uint32_t max) {221ExecutionContext exe_ctx(GetExecutionContextRef());222auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);223if (!children_count)224return children_count;225return *children_count <= max ? *children_count : max;226}227228std::optional<uint64_t> ValueObjectRegister::GetByteSize() {229return m_reg_info.byte_size;230}231232bool ValueObjectRegister::UpdateValue() {233m_error.Clear();234ExecutionContext exe_ctx(GetExecutionContextRef());235StackFrame *frame = exe_ctx.GetFramePtr();236if (frame == nullptr) {237m_reg_ctx_sp.reset();238m_reg_value.Clear();239}240241if (m_reg_ctx_sp) {242RegisterValue m_old_reg_value(m_reg_value);243if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) {244if (m_reg_value.GetData(m_data)) {245Process *process = exe_ctx.GetProcessPtr();246if (process)247m_data.SetAddressByteSize(process->GetAddressByteSize());248m_value.SetContext(Value::ContextType::RegisterInfo,249(void *)&m_reg_info);250m_value.SetValueType(Value::ValueType::HostAddress);251m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();252SetValueIsValid(true);253SetValueDidChange(!(m_old_reg_value == m_reg_value));254return true;255}256}257}258259SetValueIsValid(false);260m_error.SetErrorToGenericError();261return false;262}263264bool ValueObjectRegister::SetValueFromCString(const char *value_str,265Status &error) {266// The new value will be in the m_data. Copy that into our register value.267error =268m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));269if (!error.Success())270return false;271272if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {273error.SetErrorString("unable to write back to register");274return false;275}276277SetNeedsUpdate();278return true;279}280281bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {282error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false);283if (!error.Success())284return false;285286if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {287error.SetErrorString("unable to write back to register");288return false;289}290291SetNeedsUpdate();292return true;293}294295bool ValueObjectRegister::ResolveValue(Scalar &scalar) {296if (UpdateValueIfNeeded(297false)) // make sure that you are up to date before returning anything298return m_reg_value.GetScalarValue(scalar);299return false;300}301302void ValueObjectRegister::GetExpressionPath(Stream &s,303GetExpressionPathFormat epformat) {304s.Printf("$%s", m_reg_info.name);305}306307308