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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/Core/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 ValueObjectRegisterSet
41
42ValueObjectSP
43ValueObjectRegisterSet::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
77size_t ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) {
78  const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
79  if (reg_set) {
80    auto reg_count = reg_set->num_registers;
81    return reg_count <= max ? reg_count : max;
82  }
83  return 0;
84}
85
86std::optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
87
88bool ValueObjectRegisterSet::UpdateValue() {
89  m_error.Clear();
90  SetValueDidChange(false);
91  ExecutionContext exe_ctx(GetExecutionContextRef());
92  StackFrame *frame = exe_ctx.GetFramePtr();
93  if (frame == nullptr)
94    m_reg_ctx_sp.reset();
95  else {
96    m_reg_ctx_sp = frame->GetRegisterContext();
97    if (m_reg_ctx_sp) {
98      const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
99      if (reg_set == nullptr)
100        m_reg_ctx_sp.reset();
101      else if (m_reg_set != reg_set) {
102        SetValueDidChange(true);
103        m_name.SetCString(reg_set->name);
104      }
105    }
106  }
107  if (m_reg_ctx_sp) {
108    SetValueIsValid(true);
109  } else {
110    SetValueIsValid(false);
111    m_error.SetErrorToGenericError();
112    m_children.Clear();
113  }
114  return m_error.Success();
115}
116
117ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(
118    size_t idx, bool synthetic_array_member, int32_t synthetic_index) {
119  ValueObject *valobj = nullptr;
120  if (m_reg_ctx_sp && m_reg_set) {
121    const size_t num_children = GetNumChildren();
122    if (idx < num_children)
123      valobj = new ValueObjectRegister(
124          *this, m_reg_ctx_sp,
125          m_reg_ctx_sp->GetRegisterInfoAtIndex(m_reg_set->registers[idx]));
126  }
127  return valobj;
128}
129
130lldb::ValueObjectSP
131ValueObjectRegisterSet::GetChildMemberWithName(llvm::StringRef name,
132                                               bool can_create) {
133  ValueObject *valobj = nullptr;
134  if (m_reg_ctx_sp && m_reg_set) {
135    const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);
136    if (reg_info != nullptr)
137      valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info);
138  }
139  if (valobj)
140    return valobj->GetSP();
141  else
142    return ValueObjectSP();
143}
144
145size_t ValueObjectRegisterSet::GetIndexOfChildWithName(llvm::StringRef name) {
146  if (m_reg_ctx_sp && m_reg_set) {
147    const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name);
148    if (reg_info != nullptr)
149      return reg_info->kinds[eRegisterKindLLDB];
150  }
151  return UINT32_MAX;
152}
153
154#pragma mark -
155#pragma mark ValueObjectRegister
156
157void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {
158  if (reg_info) {
159    m_reg_info = *reg_info;
160    if (reg_info->name)
161      m_name.SetCString(reg_info->name);
162    else if (reg_info->alt_name)
163      m_name.SetCString(reg_info->alt_name);
164  }
165}
166
167ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
168                                         lldb::RegisterContextSP &reg_ctx_sp,
169                                         const RegisterInfo *reg_info)
170    : ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),
171      m_reg_value(), m_type_name(), m_compiler_type() {
172  assert(reg_ctx_sp.get());
173  ConstructObject(reg_info);
174}
175
176ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
177                                          lldb::RegisterContextSP &reg_ctx_sp,
178                                          const RegisterInfo *reg_info) {
179  auto manager_sp = ValueObjectManager::Create();
180  return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info))
181      ->GetSP();
182}
183
184ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
185                                         ValueObjectManager &manager,
186                                         lldb::RegisterContextSP &reg_ctx,
187                                         const RegisterInfo *reg_info)
188    : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(),
189      m_reg_value(), m_type_name(), m_compiler_type() {
190  assert(reg_ctx);
191  ConstructObject(reg_info);
192}
193
194ValueObjectRegister::~ValueObjectRegister() = default;
195
196CompilerType ValueObjectRegister::GetCompilerTypeImpl() {
197  if (!m_compiler_type.IsValid()) {
198    ExecutionContext exe_ctx(GetExecutionContextRef());
199    if (auto *target = exe_ctx.GetTargetPtr()) {
200      if (auto *exe_module = target->GetExecutableModulePointer()) {
201        auto type_system_or_err =
202            exe_module->GetTypeSystemForLanguage(eLanguageTypeC);
203        if (auto err = type_system_or_err.takeError()) {
204          LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err),
205                         "Unable to get CompilerType from TypeSystem: {0}");
206        } else {
207          if (auto ts = *type_system_or_err)
208            m_compiler_type = ts->GetBuiltinTypeForEncodingAndBitSize(
209                m_reg_info.encoding, m_reg_info.byte_size * 8);
210        }
211      }
212    }
213  }
214  return m_compiler_type;
215}
216
217ConstString ValueObjectRegister::GetTypeName() {
218  if (m_type_name.IsEmpty())
219    m_type_name = GetCompilerType().GetTypeName();
220  return m_type_name;
221}
222
223size_t ValueObjectRegister::CalculateNumChildren(uint32_t max) {
224  ExecutionContext exe_ctx(GetExecutionContextRef());
225  auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
226  return children_count <= max ? children_count : max;
227}
228
229std::optional<uint64_t> ValueObjectRegister::GetByteSize() {
230  return m_reg_info.byte_size;
231}
232
233bool ValueObjectRegister::UpdateValue() {
234  m_error.Clear();
235  ExecutionContext exe_ctx(GetExecutionContextRef());
236  StackFrame *frame = exe_ctx.GetFramePtr();
237  if (frame == nullptr) {
238    m_reg_ctx_sp.reset();
239    m_reg_value.Clear();
240  }
241
242  if (m_reg_ctx_sp) {
243    RegisterValue m_old_reg_value(m_reg_value);
244    if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) {
245      if (m_reg_value.GetData(m_data)) {
246        Process *process = exe_ctx.GetProcessPtr();
247        if (process)
248          m_data.SetAddressByteSize(process->GetAddressByteSize());
249        m_value.SetContext(Value::ContextType::RegisterInfo,
250                           (void *)&m_reg_info);
251        m_value.SetValueType(Value::ValueType::HostAddress);
252        m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
253        SetValueIsValid(true);
254        SetValueDidChange(!(m_old_reg_value == m_reg_value));
255        return true;
256      }
257    }
258  }
259
260  SetValueIsValid(false);
261  m_error.SetErrorToGenericError();
262  return false;
263}
264
265bool ValueObjectRegister::SetValueFromCString(const char *value_str,
266                                              Status &error) {
267  // The new value will be in the m_data.  Copy that into our register value.
268  error =
269      m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));
270  if (!error.Success())
271    return false;
272
273  if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
274    error.SetErrorString("unable to write back to register");
275    return false;
276  }
277
278  SetNeedsUpdate();
279  return true;
280}
281
282bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {
283  error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false);
284  if (!error.Success())
285    return false;
286
287  if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
288    error.SetErrorString("unable to write back to register");
289    return false;
290  }
291
292  SetNeedsUpdate();
293  return true;
294}
295
296bool ValueObjectRegister::ResolveValue(Scalar &scalar) {
297  if (UpdateValueIfNeeded(
298          false)) // make sure that you are up to date before returning anything
299    return m_reg_value.GetScalarValue(scalar);
300  return false;
301}
302
303void ValueObjectRegister::GetExpressionPath(Stream &s,
304                                            GetExpressionPathFormat epformat) {
305  s.Printf("$%s", m_reg_info.name);
306}
307