Path: blob/main/contrib/llvm-project/lldb/source/ValueObject/ValueObjectRegister.cpp
213764 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/ValueObject/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}8586llvm::Expected<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 = Status::FromErrorString("no register context");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}140141llvm::Expected<size_t>142ValueObjectRegisterSet::GetIndexOfChildWithName(llvm::StringRef name) {143if (m_reg_ctx_sp && m_reg_set) {144const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);145if (reg_info != nullptr)146return reg_info->kinds[eRegisterKindLLDB];147}148return llvm::createStringError("Type has no child named '%s'",149name.str().c_str());150}151152#pragma mark -153#pragma mark ValueObjectRegister154155void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {156if (reg_info) {157m_reg_info = *reg_info;158if (reg_info->name)159m_name.SetCString(reg_info->name);160else if (reg_info->alt_name)161m_name.SetCString(reg_info->alt_name);162}163}164165ValueObjectRegister::ValueObjectRegister(ValueObject &parent,166lldb::RegisterContextSP ®_ctx_sp,167const RegisterInfo *reg_info)168: ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),169m_reg_value(), m_type_name(), m_compiler_type() {170assert(reg_ctx_sp.get());171ConstructObject(reg_info);172}173174ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,175lldb::RegisterContextSP ®_ctx_sp,176const RegisterInfo *reg_info) {177auto manager_sp = ValueObjectManager::Create();178return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info))179->GetSP();180}181182ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,183ValueObjectManager &manager,184lldb::RegisterContextSP ®_ctx,185const RegisterInfo *reg_info)186: ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(),187m_reg_value(), m_type_name(), m_compiler_type() {188assert(reg_ctx);189ConstructObject(reg_info);190}191192ValueObjectRegister::~ValueObjectRegister() = default;193194CompilerType ValueObjectRegister::GetCompilerTypeImpl() {195if (!m_compiler_type.IsValid()) {196ExecutionContext exe_ctx(GetExecutionContextRef());197if (auto *target = exe_ctx.GetTargetPtr()) {198if (auto *exe_module = target->GetExecutableModulePointer()) {199auto type_system_or_err =200exe_module->GetTypeSystemForLanguage(eLanguageTypeC);201if (auto err = type_system_or_err.takeError()) {202LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err),203"Unable to get CompilerType from TypeSystem: {0}");204} else {205if (auto ts = *type_system_or_err)206m_compiler_type = ts->GetBuiltinTypeForEncodingAndBitSize(207m_reg_info.encoding, m_reg_info.byte_size * 8);208}209}210}211}212return m_compiler_type;213}214215ConstString ValueObjectRegister::GetTypeName() {216if (m_type_name.IsEmpty())217m_type_name = GetCompilerType().GetTypeName();218return m_type_name;219}220221llvm::Expected<uint32_t>222ValueObjectRegister::CalculateNumChildren(uint32_t max) {223ExecutionContext exe_ctx(GetExecutionContextRef());224auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);225if (!children_count)226return children_count;227return *children_count <= max ? *children_count : max;228}229230llvm::Expected<uint64_t> ValueObjectRegister::GetByteSize() {231return m_reg_info.byte_size;232}233234bool ValueObjectRegister::UpdateValue() {235m_error.Clear();236ExecutionContext exe_ctx(GetExecutionContextRef());237StackFrame *frame = exe_ctx.GetFramePtr();238if (frame == nullptr) {239m_reg_ctx_sp.reset();240m_reg_value.Clear();241}242243if (m_reg_ctx_sp) {244RegisterValue m_old_reg_value(m_reg_value);245if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) {246if (m_reg_value.GetData(m_data)) {247Process *process = exe_ctx.GetProcessPtr();248if (process)249m_data.SetAddressByteSize(process->GetAddressByteSize());250m_value.SetContext(Value::ContextType::RegisterInfo,251(void *)&m_reg_info);252m_value.SetValueType(Value::ValueType::HostAddress);253m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();254SetValueIsValid(true);255SetValueDidChange(!(m_old_reg_value == m_reg_value));256return true;257}258}259}260261SetValueIsValid(false);262m_error = Status::FromErrorString("no register context");263return false;264}265266bool ValueObjectRegister::SetValueFromCString(const char *value_str,267Status &error) {268// The new value will be in the m_data. Copy that into our register value.269error =270m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));271if (!error.Success())272return false;273274if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {275error = Status::FromErrorString("unable to write back to register");276return false;277}278279SetNeedsUpdate();280return true;281}282283bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {284error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false);285if (!error.Success())286return false;287288if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {289error = Status::FromErrorString("unable to write back to register");290return false;291}292293SetNeedsUpdate();294return true;295}296297bool ValueObjectRegister::ResolveValue(Scalar &scalar) {298if (UpdateValueIfNeeded(299false)) // make sure that you are up to date before returning anything300return m_reg_value.GetScalarValue(scalar);301return false;302}303304void ValueObjectRegister::GetExpressionPath(Stream &s,305GetExpressionPathFormat epformat) {306s.Printf("$%s", m_reg_info.name);307}308309310