1//===-- ValueObjectRegister.cpp ---------------------------------*- C++ -*-===//
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/Log.h"
22#include "lldb/Utility/Scalar.h"
23#include "lldb/Utility/Status.h"
24#include "lldb/Utility/Stream.h"
25
26#include "llvm/ADT/StringRef.h"
27
28#include <assert.h>
29#include <memory>
30
31namespace lldb_private {
32class ExecutionContextScope;
33}
34
35using namespace lldb;
36using namespace lldb_private;
37
38#pragma mark ValueObjectRegisterContext
39
40ValueObjectRegisterContext::ValueObjectRegisterContext(
41    ValueObject &parent, RegisterContextSP &reg_ctx)
42    : ValueObject(parent), m_reg_ctx_sp(reg_ctx) {
43  assert(reg_ctx);
44  m_name.SetCString("Registers");
45  SetValueIsValid(true);
46}
47
48ValueObjectRegisterContext::~ValueObjectRegisterContext() {}
49
50CompilerType ValueObjectRegisterContext::GetCompilerTypeImpl() {
51  return CompilerType();
52}
53
54ConstString ValueObjectRegisterContext::GetTypeName() { return ConstString(); }
55
56ConstString ValueObjectRegisterContext::GetDisplayTypeName() {
57  return ConstString();
58}
59
60ConstString ValueObjectRegisterContext::GetQualifiedTypeName() {
61  return ConstString();
62}
63
64size_t ValueObjectRegisterContext::CalculateNumChildren(uint32_t max) {
65  auto reg_set_count = m_reg_ctx_sp->GetRegisterSetCount();
66  return reg_set_count <= max ? reg_set_count : max;
67}
68
69uint64_t ValueObjectRegisterContext::GetByteSize() { return 0; }
70
71bool ValueObjectRegisterContext::UpdateValue() {
72  m_error.Clear();
73  ExecutionContext exe_ctx(GetExecutionContextRef());
74  StackFrame *frame = exe_ctx.GetFramePtr();
75  if (frame)
76    m_reg_ctx_sp = frame->GetRegisterContext();
77  else
78    m_reg_ctx_sp.reset();
79
80  if (m_reg_ctx_sp.get() == nullptr) {
81    SetValueIsValid(false);
82    m_error.SetErrorToGenericError();
83  } else
84    SetValueIsValid(true);
85
86  return m_error.Success();
87}
88
89ValueObject *ValueObjectRegisterContext::CreateChildAtIndex(
90    size_t idx, bool synthetic_array_member, int32_t synthetic_index) {
91  ValueObject *new_valobj = nullptr;
92
93  const size_t num_children = GetNumChildren();
94  if (idx < num_children) {
95    ExecutionContext exe_ctx(GetExecutionContextRef());
96    new_valobj = new ValueObjectRegisterSet(
97        exe_ctx.GetBestExecutionContextScope(), m_reg_ctx_sp, idx);
98  }
99
100  return new_valobj;
101}
102
103#pragma mark -
104#pragma mark ValueObjectRegisterSet
105
106ValueObjectSP
107ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope,
108                               lldb::RegisterContextSP &reg_ctx_sp,
109                               uint32_t set_idx) {
110  return (new ValueObjectRegisterSet(exe_scope, reg_ctx_sp, set_idx))->GetSP();
111}
112
113ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
114                                               lldb::RegisterContextSP &reg_ctx,
115                                               uint32_t reg_set_idx)
116    : ValueObject(exe_scope), m_reg_ctx_sp(reg_ctx), m_reg_set(nullptr),
117      m_reg_set_idx(reg_set_idx) {
118  assert(reg_ctx);
119  m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);
120  if (m_reg_set) {
121    m_name.SetCString(m_reg_set->name);
122  }
123}
124
125ValueObjectRegisterSet::~ValueObjectRegisterSet() {}
126
127CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {
128  return CompilerType();
129}
130
131ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); }
132
133ConstString ValueObjectRegisterSet::GetQualifiedTypeName() {
134  return ConstString();
135}
136
137size_t ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) {
138  const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
139  if (reg_set) {
140    auto reg_count = reg_set->num_registers;
141    return reg_count <= max ? reg_count : max;
142  }
143  return 0;
144}
145
146uint64_t ValueObjectRegisterSet::GetByteSize() { return 0; }
147
148bool ValueObjectRegisterSet::UpdateValue() {
149  m_error.Clear();
150  SetValueDidChange(false);
151  ExecutionContext exe_ctx(GetExecutionContextRef());
152  StackFrame *frame = exe_ctx.GetFramePtr();
153  if (frame == nullptr)
154    m_reg_ctx_sp.reset();
155  else {
156    m_reg_ctx_sp = frame->GetRegisterContext();
157    if (m_reg_ctx_sp) {
158      const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
159      if (reg_set == nullptr)
160        m_reg_ctx_sp.reset();
161      else if (m_reg_set != reg_set) {
162        SetValueDidChange(true);
163        m_name.SetCString(reg_set->name);
164      }
165    }
166  }
167  if (m_reg_ctx_sp) {
168    SetValueIsValid(true);
169  } else {
170    SetValueIsValid(false);
171    m_error.SetErrorToGenericError();
172    m_children.Clear();
173  }
174  return m_error.Success();
175}
176
177ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(
178    size_t idx, bool synthetic_array_member, int32_t synthetic_index) {
179  ValueObject *valobj = nullptr;
180  if (m_reg_ctx_sp && m_reg_set) {
181    const size_t num_children = GetNumChildren();
182    if (idx < num_children)
183      valobj = new ValueObjectRegister(*this, m_reg_ctx_sp,
184                                       m_reg_set->registers[idx]);
185  }
186  return valobj;
187}
188
189lldb::ValueObjectSP
190ValueObjectRegisterSet::GetChildMemberWithName(ConstString name,
191                                               bool can_create) {
192  ValueObject *valobj = nullptr;
193  if (m_reg_ctx_sp && m_reg_set) {
194    const RegisterInfo *reg_info =
195        m_reg_ctx_sp->GetRegisterInfoByName(name.AsCString());
196    if (reg_info != nullptr)
197      valobj = new ValueObjectRegister(*this, m_reg_ctx_sp,
198                                       reg_info->kinds[eRegisterKindLLDB]);
199  }
200  if (valobj)
201    return valobj->GetSP();
202  else
203    return ValueObjectSP();
204}
205
206size_t
207ValueObjectRegisterSet::GetIndexOfChildWithName(ConstString name) {
208  if (m_reg_ctx_sp && m_reg_set) {
209    const RegisterInfo *reg_info =
210        m_reg_ctx_sp->GetRegisterInfoByName(name.AsCString());
211    if (reg_info != nullptr)
212      return reg_info->kinds[eRegisterKindLLDB];
213  }
214  return UINT32_MAX;
215}
216
217#pragma mark -
218#pragma mark ValueObjectRegister
219
220void ValueObjectRegister::ConstructObject(uint32_t reg_num) {
221  const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoAtIndex(reg_num);
222  if (reg_info) {
223    m_reg_info = *reg_info;
224    if (reg_info->name)
225      m_name.SetCString(reg_info->name);
226    else if (reg_info->alt_name)
227      m_name.SetCString(reg_info->alt_name);
228  }
229}
230
231ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
232                                         lldb::RegisterContextSP &reg_ctx_sp,
233                                         uint32_t reg_num)
234    : ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),
235      m_reg_value(), m_type_name(), m_compiler_type() {
236  assert(reg_ctx_sp.get());
237  ConstructObject(reg_num);
238}
239
240ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
241                                          lldb::RegisterContextSP &reg_ctx_sp,
242                                          uint32_t reg_num) {
243  return (new ValueObjectRegister(exe_scope, reg_ctx_sp, reg_num))->GetSP();
244}
245
246ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
247                                         lldb::RegisterContextSP &reg_ctx,
248                                         uint32_t reg_num)
249    : ValueObject(exe_scope), m_reg_ctx_sp(reg_ctx), m_reg_info(),
250      m_reg_value(), m_type_name(), m_compiler_type() {
251  assert(reg_ctx);
252  ConstructObject(reg_num);
253}
254
255ValueObjectRegister::~ValueObjectRegister() {}
256
257CompilerType ValueObjectRegister::GetCompilerTypeImpl() {
258  if (!m_compiler_type.IsValid()) {
259    ExecutionContext exe_ctx(GetExecutionContextRef());
260    if (auto *target = exe_ctx.GetTargetPtr()) {
261      if (auto *exe_module = target->GetExecutableModulePointer()) {
262        auto type_system_or_err =
263            exe_module->GetTypeSystemForLanguage(eLanguageTypeC);
264        if (auto err = type_system_or_err.takeError()) {
265          LLDB_LOG_ERROR(
266              lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TYPES),
267              std::move(err), "Unable to get CompilerType from TypeSystem");
268        } else {
269          m_compiler_type =
270              type_system_or_err->GetBuiltinTypeForEncodingAndBitSize(
271                  m_reg_info.encoding, m_reg_info.byte_size * 8);
272        }
273      }
274    }
275  }
276  return m_compiler_type;
277}
278
279ConstString ValueObjectRegister::GetTypeName() {
280  if (m_type_name.IsEmpty())
281    m_type_name = GetCompilerType().GetConstTypeName();
282  return m_type_name;
283}
284
285size_t ValueObjectRegister::CalculateNumChildren(uint32_t max) {
286  ExecutionContext exe_ctx(GetExecutionContextRef());
287  auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
288  return children_count <= max ? children_count : max;
289}
290
291uint64_t ValueObjectRegister::GetByteSize() { return m_reg_info.byte_size; }
292
293bool ValueObjectRegister::UpdateValue() {
294  m_error.Clear();
295  ExecutionContext exe_ctx(GetExecutionContextRef());
296  StackFrame *frame = exe_ctx.GetFramePtr();
297  if (frame == nullptr) {
298    m_reg_ctx_sp.reset();
299    m_reg_value.Clear();
300  }
301
302  if (m_reg_ctx_sp) {
303    RegisterValue m_old_reg_value(m_reg_value);
304    if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) {
305      if (m_reg_value.GetData(m_data)) {
306        Process *process = exe_ctx.GetProcessPtr();
307        if (process)
308          m_data.SetAddressByteSize(process->GetAddressByteSize());
309        m_value.SetContext(Value::eContextTypeRegisterInfo,
310                           (void *)&m_reg_info);
311        m_value.SetValueType(Value::eValueTypeHostAddress);
312        m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
313        SetValueIsValid(true);
314        SetValueDidChange(!(m_old_reg_value == m_reg_value));
315        return true;
316      }
317    }
318  }
319
320  SetValueIsValid(false);
321  m_error.SetErrorToGenericError();
322  return false;
323}
324
325bool ValueObjectRegister::SetValueFromCString(const char *value_str,
326                                              Status &error) {
327  // The new value will be in the m_data.  Copy that into our register value.
328  error =
329      m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));
330  if (error.Success()) {
331    if (m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
332      SetNeedsUpdate();
333      return true;
334    } else
335      return false;
336  } else
337    return false;
338}
339
340bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {
341  error = m_reg_value.SetValueFromData(&m_reg_info, data, 0, false);
342  if (error.Success()) {
343    if (m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
344      SetNeedsUpdate();
345      return true;
346    } else
347      return false;
348  } else
349    return false;
350}
351
352bool ValueObjectRegister::ResolveValue(Scalar &scalar) {
353  if (UpdateValueIfNeeded(
354          false)) // make sure that you are up to date before returning anything
355    return m_reg_value.GetScalarValue(scalar);
356  return false;
357}
358
359void ValueObjectRegister::GetExpressionPath(Stream &s,
360                                            bool qualify_cxx_base_classes,
361                                            GetExpressionPathFormat epformat) {
362  s.Printf("$%s", m_reg_info.name);
363}
364