1dda28197Spatrick //===-- ValueObjectRegister.cpp -------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "lldb/Core/ValueObjectRegister.h"
10061da546Spatrick
11061da546Spatrick #include "lldb/Core/Module.h"
12061da546Spatrick #include "lldb/Core/Value.h"
13061da546Spatrick #include "lldb/Symbol/CompilerType.h"
14061da546Spatrick #include "lldb/Symbol/TypeSystem.h"
15061da546Spatrick #include "lldb/Target/ExecutionContext.h"
16061da546Spatrick #include "lldb/Target/Process.h"
17061da546Spatrick #include "lldb/Target/RegisterContext.h"
18061da546Spatrick #include "lldb/Target/StackFrame.h"
19061da546Spatrick #include "lldb/Target/Target.h"
20061da546Spatrick #include "lldb/Utility/DataExtractor.h"
21*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
22061da546Spatrick #include "lldb/Utility/Log.h"
23061da546Spatrick #include "lldb/Utility/Scalar.h"
24061da546Spatrick #include "lldb/Utility/Status.h"
25061da546Spatrick #include "lldb/Utility/Stream.h"
26061da546Spatrick
27061da546Spatrick #include "llvm/ADT/StringRef.h"
28061da546Spatrick
29be691f3bSpatrick #include <cassert>
30061da546Spatrick #include <memory>
31*f6aab3d8Srobert #include <optional>
32061da546Spatrick
33061da546Spatrick namespace lldb_private {
34061da546Spatrick class ExecutionContextScope;
35061da546Spatrick }
36061da546Spatrick
37061da546Spatrick using namespace lldb;
38061da546Spatrick using namespace lldb_private;
39061da546Spatrick
40061da546Spatrick #pragma mark ValueObjectRegisterSet
41061da546Spatrick
42061da546Spatrick ValueObjectSP
Create(ExecutionContextScope * exe_scope,lldb::RegisterContextSP & reg_ctx_sp,uint32_t set_idx)43061da546Spatrick ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope,
44061da546Spatrick lldb::RegisterContextSP ®_ctx_sp,
45061da546Spatrick uint32_t set_idx) {
46dda28197Spatrick auto manager_sp = ValueObjectManager::Create();
47dda28197Spatrick return (new ValueObjectRegisterSet(exe_scope, *manager_sp, reg_ctx_sp,
48dda28197Spatrick set_idx))
49dda28197Spatrick ->GetSP();
50061da546Spatrick }
51061da546Spatrick
ValueObjectRegisterSet(ExecutionContextScope * exe_scope,ValueObjectManager & manager,lldb::RegisterContextSP & reg_ctx,uint32_t reg_set_idx)52061da546Spatrick ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
53dda28197Spatrick ValueObjectManager &manager,
54061da546Spatrick lldb::RegisterContextSP ®_ctx,
55061da546Spatrick uint32_t reg_set_idx)
56dda28197Spatrick : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx),
57dda28197Spatrick m_reg_set(nullptr), m_reg_set_idx(reg_set_idx) {
58061da546Spatrick assert(reg_ctx);
59061da546Spatrick m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);
60061da546Spatrick if (m_reg_set) {
61061da546Spatrick m_name.SetCString(m_reg_set->name);
62061da546Spatrick }
63061da546Spatrick }
64061da546Spatrick
65be691f3bSpatrick ValueObjectRegisterSet::~ValueObjectRegisterSet() = default;
66061da546Spatrick
GetCompilerTypeImpl()67061da546Spatrick CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {
68061da546Spatrick return CompilerType();
69061da546Spatrick }
70061da546Spatrick
GetTypeName()71061da546Spatrick ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); }
72061da546Spatrick
GetQualifiedTypeName()73061da546Spatrick ConstString ValueObjectRegisterSet::GetQualifiedTypeName() {
74061da546Spatrick return ConstString();
75061da546Spatrick }
76061da546Spatrick
CalculateNumChildren(uint32_t max)77061da546Spatrick size_t ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) {
78061da546Spatrick const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
79061da546Spatrick if (reg_set) {
80061da546Spatrick auto reg_count = reg_set->num_registers;
81061da546Spatrick return reg_count <= max ? reg_count : max;
82061da546Spatrick }
83061da546Spatrick return 0;
84061da546Spatrick }
85061da546Spatrick
GetByteSize()86*f6aab3d8Srobert std::optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
87061da546Spatrick
UpdateValue()88061da546Spatrick bool ValueObjectRegisterSet::UpdateValue() {
89061da546Spatrick m_error.Clear();
90061da546Spatrick SetValueDidChange(false);
91061da546Spatrick ExecutionContext exe_ctx(GetExecutionContextRef());
92061da546Spatrick StackFrame *frame = exe_ctx.GetFramePtr();
93061da546Spatrick if (frame == nullptr)
94061da546Spatrick m_reg_ctx_sp.reset();
95061da546Spatrick else {
96061da546Spatrick m_reg_ctx_sp = frame->GetRegisterContext();
97061da546Spatrick if (m_reg_ctx_sp) {
98061da546Spatrick const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
99061da546Spatrick if (reg_set == nullptr)
100061da546Spatrick m_reg_ctx_sp.reset();
101061da546Spatrick else if (m_reg_set != reg_set) {
102061da546Spatrick SetValueDidChange(true);
103061da546Spatrick m_name.SetCString(reg_set->name);
104061da546Spatrick }
105061da546Spatrick }
106061da546Spatrick }
107061da546Spatrick if (m_reg_ctx_sp) {
108061da546Spatrick SetValueIsValid(true);
109061da546Spatrick } else {
110061da546Spatrick SetValueIsValid(false);
111061da546Spatrick m_error.SetErrorToGenericError();
112061da546Spatrick m_children.Clear();
113061da546Spatrick }
114061da546Spatrick return m_error.Success();
115061da546Spatrick }
116061da546Spatrick
CreateChildAtIndex(size_t idx,bool synthetic_array_member,int32_t synthetic_index)117061da546Spatrick ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(
118061da546Spatrick size_t idx, bool synthetic_array_member, int32_t synthetic_index) {
119061da546Spatrick ValueObject *valobj = nullptr;
120061da546Spatrick if (m_reg_ctx_sp && m_reg_set) {
121061da546Spatrick const size_t num_children = GetNumChildren();
122061da546Spatrick if (idx < num_children)
123*f6aab3d8Srobert valobj = new ValueObjectRegister(
124*f6aab3d8Srobert *this, m_reg_ctx_sp,
125*f6aab3d8Srobert m_reg_ctx_sp->GetRegisterInfoAtIndex(m_reg_set->registers[idx]));
126061da546Spatrick }
127061da546Spatrick return valobj;
128061da546Spatrick }
129061da546Spatrick
130061da546Spatrick lldb::ValueObjectSP
GetChildMemberWithName(ConstString name,bool can_create)131061da546Spatrick ValueObjectRegisterSet::GetChildMemberWithName(ConstString name,
132061da546Spatrick bool can_create) {
133061da546Spatrick ValueObject *valobj = nullptr;
134061da546Spatrick if (m_reg_ctx_sp && m_reg_set) {
135061da546Spatrick const RegisterInfo *reg_info =
136dda28197Spatrick m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef());
137061da546Spatrick if (reg_info != nullptr)
138*f6aab3d8Srobert valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info);
139061da546Spatrick }
140061da546Spatrick if (valobj)
141061da546Spatrick return valobj->GetSP();
142061da546Spatrick else
143061da546Spatrick return ValueObjectSP();
144061da546Spatrick }
145061da546Spatrick
146061da546Spatrick size_t
GetIndexOfChildWithName(ConstString name)147061da546Spatrick ValueObjectRegisterSet::GetIndexOfChildWithName(ConstString name) {
148061da546Spatrick if (m_reg_ctx_sp && m_reg_set) {
149061da546Spatrick const RegisterInfo *reg_info =
150dda28197Spatrick m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef());
151061da546Spatrick if (reg_info != nullptr)
152061da546Spatrick return reg_info->kinds[eRegisterKindLLDB];
153061da546Spatrick }
154061da546Spatrick return UINT32_MAX;
155061da546Spatrick }
156061da546Spatrick
157061da546Spatrick #pragma mark -
158061da546Spatrick #pragma mark ValueObjectRegister
159061da546Spatrick
ConstructObject(const RegisterInfo * reg_info)160*f6aab3d8Srobert void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {
161061da546Spatrick if (reg_info) {
162061da546Spatrick m_reg_info = *reg_info;
163061da546Spatrick if (reg_info->name)
164061da546Spatrick m_name.SetCString(reg_info->name);
165061da546Spatrick else if (reg_info->alt_name)
166061da546Spatrick m_name.SetCString(reg_info->alt_name);
167061da546Spatrick }
168061da546Spatrick }
169061da546Spatrick
ValueObjectRegister(ValueObject & parent,lldb::RegisterContextSP & reg_ctx_sp,const RegisterInfo * reg_info)170061da546Spatrick ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
171061da546Spatrick lldb::RegisterContextSP ®_ctx_sp,
172*f6aab3d8Srobert const RegisterInfo *reg_info)
173061da546Spatrick : ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),
174061da546Spatrick m_reg_value(), m_type_name(), m_compiler_type() {
175061da546Spatrick assert(reg_ctx_sp.get());
176*f6aab3d8Srobert ConstructObject(reg_info);
177061da546Spatrick }
178061da546Spatrick
Create(ExecutionContextScope * exe_scope,lldb::RegisterContextSP & reg_ctx_sp,const RegisterInfo * reg_info)179061da546Spatrick ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
180061da546Spatrick lldb::RegisterContextSP ®_ctx_sp,
181*f6aab3d8Srobert const RegisterInfo *reg_info) {
182dda28197Spatrick auto manager_sp = ValueObjectManager::Create();
183*f6aab3d8Srobert return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info))
184dda28197Spatrick ->GetSP();
185061da546Spatrick }
186061da546Spatrick
ValueObjectRegister(ExecutionContextScope * exe_scope,ValueObjectManager & manager,lldb::RegisterContextSP & reg_ctx,const RegisterInfo * reg_info)187061da546Spatrick ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
188dda28197Spatrick ValueObjectManager &manager,
189061da546Spatrick lldb::RegisterContextSP ®_ctx,
190*f6aab3d8Srobert const RegisterInfo *reg_info)
191dda28197Spatrick : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(),
192061da546Spatrick m_reg_value(), m_type_name(), m_compiler_type() {
193061da546Spatrick assert(reg_ctx);
194*f6aab3d8Srobert ConstructObject(reg_info);
195061da546Spatrick }
196061da546Spatrick
197be691f3bSpatrick ValueObjectRegister::~ValueObjectRegister() = default;
198061da546Spatrick
GetCompilerTypeImpl()199061da546Spatrick CompilerType ValueObjectRegister::GetCompilerTypeImpl() {
200061da546Spatrick if (!m_compiler_type.IsValid()) {
201061da546Spatrick ExecutionContext exe_ctx(GetExecutionContextRef());
202061da546Spatrick if (auto *target = exe_ctx.GetTargetPtr()) {
203061da546Spatrick if (auto *exe_module = target->GetExecutableModulePointer()) {
204061da546Spatrick auto type_system_or_err =
205061da546Spatrick exe_module->GetTypeSystemForLanguage(eLanguageTypeC);
206061da546Spatrick if (auto err = type_system_or_err.takeError()) {
207*f6aab3d8Srobert LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err),
208*f6aab3d8Srobert "Unable to get CompilerType from TypeSystem");
209061da546Spatrick } else {
210*f6aab3d8Srobert if (auto ts = *type_system_or_err)
211*f6aab3d8Srobert m_compiler_type = ts->GetBuiltinTypeForEncodingAndBitSize(
212061da546Spatrick m_reg_info.encoding, m_reg_info.byte_size * 8);
213061da546Spatrick }
214061da546Spatrick }
215061da546Spatrick }
216061da546Spatrick }
217061da546Spatrick return m_compiler_type;
218061da546Spatrick }
219061da546Spatrick
GetTypeName()220061da546Spatrick ConstString ValueObjectRegister::GetTypeName() {
221061da546Spatrick if (m_type_name.IsEmpty())
222dda28197Spatrick m_type_name = GetCompilerType().GetTypeName();
223061da546Spatrick return m_type_name;
224061da546Spatrick }
225061da546Spatrick
CalculateNumChildren(uint32_t max)226061da546Spatrick size_t ValueObjectRegister::CalculateNumChildren(uint32_t max) {
227061da546Spatrick ExecutionContext exe_ctx(GetExecutionContextRef());
228061da546Spatrick auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
229061da546Spatrick return children_count <= max ? children_count : max;
230061da546Spatrick }
231061da546Spatrick
GetByteSize()232*f6aab3d8Srobert std::optional<uint64_t> ValueObjectRegister::GetByteSize() {
233be691f3bSpatrick return m_reg_info.byte_size;
234be691f3bSpatrick }
235061da546Spatrick
UpdateValue()236061da546Spatrick bool ValueObjectRegister::UpdateValue() {
237061da546Spatrick m_error.Clear();
238061da546Spatrick ExecutionContext exe_ctx(GetExecutionContextRef());
239061da546Spatrick StackFrame *frame = exe_ctx.GetFramePtr();
240061da546Spatrick if (frame == nullptr) {
241061da546Spatrick m_reg_ctx_sp.reset();
242061da546Spatrick m_reg_value.Clear();
243061da546Spatrick }
244061da546Spatrick
245061da546Spatrick if (m_reg_ctx_sp) {
246061da546Spatrick RegisterValue m_old_reg_value(m_reg_value);
247061da546Spatrick if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) {
248061da546Spatrick if (m_reg_value.GetData(m_data)) {
249061da546Spatrick Process *process = exe_ctx.GetProcessPtr();
250061da546Spatrick if (process)
251061da546Spatrick m_data.SetAddressByteSize(process->GetAddressByteSize());
252be691f3bSpatrick m_value.SetContext(Value::ContextType::RegisterInfo,
253061da546Spatrick (void *)&m_reg_info);
254be691f3bSpatrick m_value.SetValueType(Value::ValueType::HostAddress);
255061da546Spatrick m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
256061da546Spatrick SetValueIsValid(true);
257061da546Spatrick SetValueDidChange(!(m_old_reg_value == m_reg_value));
258061da546Spatrick return true;
259061da546Spatrick }
260061da546Spatrick }
261061da546Spatrick }
262061da546Spatrick
263061da546Spatrick SetValueIsValid(false);
264061da546Spatrick m_error.SetErrorToGenericError();
265061da546Spatrick return false;
266061da546Spatrick }
267061da546Spatrick
SetValueFromCString(const char * value_str,Status & error)268061da546Spatrick bool ValueObjectRegister::SetValueFromCString(const char *value_str,
269061da546Spatrick Status &error) {
270061da546Spatrick // The new value will be in the m_data. Copy that into our register value.
271061da546Spatrick error =
272061da546Spatrick m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));
273*f6aab3d8Srobert if (!error.Success())
274061da546Spatrick return false;
275*f6aab3d8Srobert
276*f6aab3d8Srobert if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
277*f6aab3d8Srobert error.SetErrorString("unable to write back to register");
278061da546Spatrick return false;
279061da546Spatrick }
280061da546Spatrick
281061da546Spatrick SetNeedsUpdate();
282061da546Spatrick return true;
283*f6aab3d8Srobert }
284*f6aab3d8Srobert
SetData(DataExtractor & data,Status & error)285*f6aab3d8Srobert bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {
286*f6aab3d8Srobert error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false);
287*f6aab3d8Srobert if (!error.Success())
288061da546Spatrick return false;
289*f6aab3d8Srobert
290*f6aab3d8Srobert if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
291*f6aab3d8Srobert error.SetErrorString("unable to write back to register");
292061da546Spatrick return false;
293061da546Spatrick }
294061da546Spatrick
295*f6aab3d8Srobert SetNeedsUpdate();
296*f6aab3d8Srobert return true;
297*f6aab3d8Srobert }
298*f6aab3d8Srobert
ResolveValue(Scalar & scalar)299061da546Spatrick bool ValueObjectRegister::ResolveValue(Scalar &scalar) {
300061da546Spatrick if (UpdateValueIfNeeded(
301061da546Spatrick false)) // make sure that you are up to date before returning anything
302061da546Spatrick return m_reg_value.GetScalarValue(scalar);
303061da546Spatrick return false;
304061da546Spatrick }
305061da546Spatrick
GetExpressionPath(Stream & s,GetExpressionPathFormat epformat)306061da546Spatrick void ValueObjectRegister::GetExpressionPath(Stream &s,
307061da546Spatrick GetExpressionPathFormat epformat) {
308061da546Spatrick s.Printf("$%s", m_reg_info.name);
309061da546Spatrick }
310