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 
33 namespace lldb_private {
34 class ExecutionContextScope;
35 }
36 
37 using namespace lldb;
38 using namespace lldb_private;
39 
40 #pragma mark ValueObjectRegisterSet
41 
42 ValueObjectSP
43 ValueObjectRegisterSet::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 
52 ValueObjectRegisterSet::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 
65 ValueObjectRegisterSet::~ValueObjectRegisterSet() = default;
66 
67 CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {
68   return CompilerType();
69 }
70 
71 ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); }
72 
73 ConstString ValueObjectRegisterSet::GetQualifiedTypeName() {
74   return ConstString();
75 }
76 
77 size_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 
86 std::optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
87 
88 bool 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 
117 ValueObject *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 
130 lldb::ValueObjectSP
131 ValueObjectRegisterSet::GetChildMemberWithName(ConstString name,
132                                                bool can_create) {
133   ValueObject *valobj = nullptr;
134   if (m_reg_ctx_sp && m_reg_set) {
135     const RegisterInfo *reg_info =
136         m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef());
137     if (reg_info != nullptr)
138       valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info);
139   }
140   if (valobj)
141     return valobj->GetSP();
142   else
143     return ValueObjectSP();
144 }
145 
146 size_t
147 ValueObjectRegisterSet::GetIndexOfChildWithName(ConstString name) {
148   if (m_reg_ctx_sp && m_reg_set) {
149     const RegisterInfo *reg_info =
150         m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef());
151     if (reg_info != nullptr)
152       return reg_info->kinds[eRegisterKindLLDB];
153   }
154   return UINT32_MAX;
155 }
156 
157 #pragma mark -
158 #pragma mark ValueObjectRegister
159 
160 void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {
161   if (reg_info) {
162     m_reg_info = *reg_info;
163     if (reg_info->name)
164       m_name.SetCString(reg_info->name);
165     else if (reg_info->alt_name)
166       m_name.SetCString(reg_info->alt_name);
167   }
168 }
169 
170 ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
171                                          lldb::RegisterContextSP &reg_ctx_sp,
172                                          const RegisterInfo *reg_info)
173     : ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),
174       m_reg_value(), m_type_name(), m_compiler_type() {
175   assert(reg_ctx_sp.get());
176   ConstructObject(reg_info);
177 }
178 
179 ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
180                                           lldb::RegisterContextSP &reg_ctx_sp,
181                                           const RegisterInfo *reg_info) {
182   auto manager_sp = ValueObjectManager::Create();
183   return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info))
184       ->GetSP();
185 }
186 
187 ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
188                                          ValueObjectManager &manager,
189                                          lldb::RegisterContextSP &reg_ctx,
190                                          const RegisterInfo *reg_info)
191     : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(),
192       m_reg_value(), m_type_name(), m_compiler_type() {
193   assert(reg_ctx);
194   ConstructObject(reg_info);
195 }
196 
197 ValueObjectRegister::~ValueObjectRegister() = default;
198 
199 CompilerType ValueObjectRegister::GetCompilerTypeImpl() {
200   if (!m_compiler_type.IsValid()) {
201     ExecutionContext exe_ctx(GetExecutionContextRef());
202     if (auto *target = exe_ctx.GetTargetPtr()) {
203       if (auto *exe_module = target->GetExecutableModulePointer()) {
204         auto type_system_or_err =
205             exe_module->GetTypeSystemForLanguage(eLanguageTypeC);
206         if (auto err = type_system_or_err.takeError()) {
207           LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err),
208                          "Unable to get CompilerType from TypeSystem");
209         } else {
210           if (auto ts = *type_system_or_err)
211             m_compiler_type = ts->GetBuiltinTypeForEncodingAndBitSize(
212                 m_reg_info.encoding, m_reg_info.byte_size * 8);
213         }
214       }
215     }
216   }
217   return m_compiler_type;
218 }
219 
220 ConstString ValueObjectRegister::GetTypeName() {
221   if (m_type_name.IsEmpty())
222     m_type_name = GetCompilerType().GetTypeName();
223   return m_type_name;
224 }
225 
226 size_t ValueObjectRegister::CalculateNumChildren(uint32_t max) {
227   ExecutionContext exe_ctx(GetExecutionContextRef());
228   auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
229   return children_count <= max ? children_count : max;
230 }
231 
232 std::optional<uint64_t> ValueObjectRegister::GetByteSize() {
233   return m_reg_info.byte_size;
234 }
235 
236 bool ValueObjectRegister::UpdateValue() {
237   m_error.Clear();
238   ExecutionContext exe_ctx(GetExecutionContextRef());
239   StackFrame *frame = exe_ctx.GetFramePtr();
240   if (frame == nullptr) {
241     m_reg_ctx_sp.reset();
242     m_reg_value.Clear();
243   }
244 
245   if (m_reg_ctx_sp) {
246     RegisterValue m_old_reg_value(m_reg_value);
247     if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) {
248       if (m_reg_value.GetData(m_data)) {
249         Process *process = exe_ctx.GetProcessPtr();
250         if (process)
251           m_data.SetAddressByteSize(process->GetAddressByteSize());
252         m_value.SetContext(Value::ContextType::RegisterInfo,
253                            (void *)&m_reg_info);
254         m_value.SetValueType(Value::ValueType::HostAddress);
255         m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
256         SetValueIsValid(true);
257         SetValueDidChange(!(m_old_reg_value == m_reg_value));
258         return true;
259       }
260     }
261   }
262 
263   SetValueIsValid(false);
264   m_error.SetErrorToGenericError();
265   return false;
266 }
267 
268 bool ValueObjectRegister::SetValueFromCString(const char *value_str,
269                                               Status &error) {
270   // The new value will be in the m_data.  Copy that into our register value.
271   error =
272       m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));
273   if (!error.Success())
274     return false;
275 
276   if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
277     error.SetErrorString("unable to write back to register");
278     return false;
279   }
280 
281   SetNeedsUpdate();
282   return true;
283 }
284 
285 bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {
286   error = m_reg_value.SetValueFromData(m_reg_info, data, 0, false);
287   if (!error.Success())
288     return false;
289 
290   if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
291     error.SetErrorString("unable to write back to register");
292     return false;
293   }
294 
295   SetNeedsUpdate();
296   return true;
297 }
298 
299 bool ValueObjectRegister::ResolveValue(Scalar &scalar) {
300   if (UpdateValueIfNeeded(
301           false)) // make sure that you are up to date before returning anything
302     return m_reg_value.GetScalarValue(scalar);
303   return false;
304 }
305 
306 void ValueObjectRegister::GetExpressionPath(Stream &s,
307                                             GetExpressionPathFormat epformat) {
308   s.Printf("$%s", m_reg_info.name);
309 }
310