brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.9 KiB · 97aeaa8 Raw
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 &reg_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 &reg_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 &reg_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 &reg_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 &reg_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