309 lines · cpp
1//===-- ValueObjectRegister.cpp -------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/ValueObject/ValueObjectRegister.h"10 11#include "lldb/Core/Module.h"12#include "lldb/Core/Value.h"13#include "lldb/Symbol/CompilerType.h"14#include "lldb/Symbol/TypeSystem.h"15#include "lldb/Target/ExecutionContext.h"16#include "lldb/Target/Process.h"17#include "lldb/Target/RegisterContext.h"18#include "lldb/Target/StackFrame.h"19#include "lldb/Target/Target.h"20#include "lldb/Utility/DataExtractor.h"21#include "lldb/Utility/LLDBLog.h"22#include "lldb/Utility/Log.h"23#include "lldb/Utility/Scalar.h"24#include "lldb/Utility/Status.h"25#include "lldb/Utility/Stream.h"26 27#include "llvm/ADT/StringRef.h"28 29#include <cassert>30#include <memory>31#include <optional>32 33namespace lldb_private {34class ExecutionContextScope;35}36 37using namespace lldb;38using namespace lldb_private;39 40#pragma mark ValueObjectRegisterSet41 42ValueObjectSP43ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope,44 lldb::RegisterContextSP ®_ctx_sp,45 uint32_t set_idx) {46 auto manager_sp = ValueObjectManager::Create();47 return (new ValueObjectRegisterSet(exe_scope, *manager_sp, reg_ctx_sp,48 set_idx))49 ->GetSP();50}51 52ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,53 ValueObjectManager &manager,54 lldb::RegisterContextSP ®_ctx,55 uint32_t reg_set_idx)56 : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx),57 m_reg_set(nullptr), m_reg_set_idx(reg_set_idx) {58 assert(reg_ctx);59 m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);60 if (m_reg_set) {61 m_name.SetCString(m_reg_set->name);62 }63}64 65ValueObjectRegisterSet::~ValueObjectRegisterSet() = default;66 67CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {68 return CompilerType();69}70 71ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); }72 73ConstString ValueObjectRegisterSet::GetQualifiedTypeName() {74 return ConstString();75}76 77llvm::Expected<uint32_t>78ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) {79 const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);80 if (reg_set) {81 auto reg_count = reg_set->num_registers;82 return reg_count <= max ? reg_count : max;83 }84 return 0;85}86 87llvm::Expected<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }88 89bool ValueObjectRegisterSet::UpdateValue() {90 m_error.Clear();91 SetValueDidChange(false);92 ExecutionContext exe_ctx(GetExecutionContextRef());93 StackFrame *frame = exe_ctx.GetFramePtr();94 if (frame == nullptr)95 m_reg_ctx_sp.reset();96 else {97 m_reg_ctx_sp = frame->GetRegisterContext();98 if (m_reg_ctx_sp) {99 const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);100 if (reg_set == nullptr)101 m_reg_ctx_sp.reset();102 else if (m_reg_set != reg_set) {103 SetValueDidChange(true);104 m_name.SetCString(reg_set->name);105 }106 }107 }108 if (m_reg_ctx_sp) {109 SetValueIsValid(true);110 } else {111 SetValueIsValid(false);112 m_error = Status::FromErrorString("no register context");113 m_children.Clear();114 }115 return m_error.Success();116}117 118ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(size_t idx) {119 if (m_reg_ctx_sp && m_reg_set) {120 return new ValueObjectRegister(121 *this, m_reg_ctx_sp,122 m_reg_ctx_sp->GetRegisterInfoAtIndex(m_reg_set->registers[idx]));123 }124 return nullptr;125}126 127lldb::ValueObjectSP128ValueObjectRegisterSet::GetChildMemberWithName(llvm::StringRef name,129 bool can_create) {130 ValueObject *valobj = nullptr;131 if (m_reg_ctx_sp && m_reg_set) {132 const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);133 if (reg_info != nullptr)134 valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info);135 }136 if (valobj)137 return valobj->GetSP();138 else139 return ValueObjectSP();140}141 142llvm::Expected<size_t>143ValueObjectRegisterSet::GetIndexOfChildWithName(llvm::StringRef name) {144 if (m_reg_ctx_sp && m_reg_set) {145 const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);146 if (reg_info != nullptr)147 return reg_info->kinds[eRegisterKindLLDB];148 }149 return llvm::createStringError("Type has no child named '%s'",150 name.str().c_str());151}152 153#pragma mark -154#pragma mark ValueObjectRegister155 156void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {157 if (reg_info) {158 m_reg_info = *reg_info;159 if (reg_info->name)160 m_name.SetCString(reg_info->name);161 else if (reg_info->alt_name)162 m_name.SetCString(reg_info->alt_name);163 }164}165 166ValueObjectRegister::ValueObjectRegister(ValueObject &parent,167 lldb::RegisterContextSP ®_ctx_sp,168 const RegisterInfo *reg_info)169 : ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),170 m_reg_value(), m_type_name(), m_compiler_type() {171 assert(reg_ctx_sp.get());172 ConstructObject(reg_info);173}174 175ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,176 lldb::RegisterContextSP ®_ctx_sp,177 const RegisterInfo *reg_info) {178 auto manager_sp = ValueObjectManager::Create();179 return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info))180 ->GetSP();181}182 183ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,184 ValueObjectManager &manager,185 lldb::RegisterContextSP ®_ctx,186 const RegisterInfo *reg_info)187 : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(),188 m_reg_value(), m_type_name(), m_compiler_type() {189 assert(reg_ctx);190 ConstructObject(reg_info);191}192 193ValueObjectRegister::~ValueObjectRegister() = default;194 195CompilerType ValueObjectRegister::GetCompilerTypeImpl() {196 if (!m_compiler_type.IsValid()) {197 ExecutionContext exe_ctx(GetExecutionContextRef());198 if (auto *target = exe_ctx.GetTargetPtr()) {199 if (auto *exe_module = target->GetExecutableModulePointer()) {200 auto type_system_or_err =201 exe_module->GetTypeSystemForLanguage(eLanguageTypeC);202 if (auto err = type_system_or_err.takeError()) {203 LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err),204 "Unable to get CompilerType from TypeSystem: {0}");205 } else {206 if (auto ts = *type_system_or_err)207 m_compiler_type = ts->GetBuiltinTypeForEncodingAndBitSize(208 m_reg_info.encoding, m_reg_info.byte_size * 8);209 }210 }211 }212 }213 return m_compiler_type;214}215 216ConstString ValueObjectRegister::GetTypeName() {217 if (m_type_name.IsEmpty())218 m_type_name = GetCompilerType().GetTypeName();219 return m_type_name;220}221 222llvm::Expected<uint32_t>223ValueObjectRegister::CalculateNumChildren(uint32_t max) {224 ExecutionContext exe_ctx(GetExecutionContextRef());225 auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);226 if (!children_count)227 return children_count;228 return *children_count <= max ? *children_count : max;229}230 231llvm::Expected<uint64_t> ValueObjectRegister::GetByteSize() {232 return m_reg_info.byte_size;233}234 235bool ValueObjectRegister::UpdateValue() {236 m_error.Clear();237 ExecutionContext exe_ctx(GetExecutionContextRef());238 StackFrame *frame = exe_ctx.GetFramePtr();239 if (frame == nullptr) {240 m_reg_ctx_sp.reset();241 m_reg_value.Clear();242 }243 244 if (m_reg_ctx_sp) {245 RegisterValue m_old_reg_value(m_reg_value);246 if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) {247 if (m_reg_value.GetData(m_data)) {248 Process *process = exe_ctx.GetProcessPtr();249 if (process)250 m_data.SetAddressByteSize(process->GetAddressByteSize());251 m_value.SetContext(Value::ContextType::RegisterInfo,252 (void *)&m_reg_info);253 m_value.SetValueType(Value::ValueType::HostAddress);254 m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();255 SetValueIsValid(true);256 SetValueDidChange(!(m_old_reg_value == m_reg_value));257 return true;258 }259 }260 }261 262 SetValueIsValid(false);263 m_error = Status::FromErrorString("no register context");264 return false;265}266 267bool ValueObjectRegister::SetValueFromCString(const char *value_str,268 Status &error) {269 // The new value will be in the m_data. Copy that into our register value.270 error =271 m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));272 if (!error.Success())273 return false;274 275 if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {276 error = Status::FromErrorString("unable to write back to register");277 return false;278 }279 280 SetNeedsUpdate();281 return true;282}283 284bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {285 error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false);286 if (!error.Success())287 return false;288 289 if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {290 error = Status::FromErrorString("unable to write back to register");291 return false;292 }293 294 SetNeedsUpdate();295 return true;296}297 298bool ValueObjectRegister::ResolveValue(Scalar &scalar) {299 if (UpdateValueIfNeeded(300 false)) // make sure that you are up to date before returning anything301 return m_reg_value.GetScalarValue(scalar);302 return false;303}304 305void ValueObjectRegister::GetExpressionPath(Stream &s,306 GetExpressionPathFormat epformat) {307 s.Printf("$%s", m_reg_info.name);308}309