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 
32 namespace lldb_private {
33 class ExecutionContextScope;
34 }
35 
36 using namespace lldb;
37 using namespace lldb_private;
38 
39 #pragma mark ValueObjectRegisterSet
40 
41 ValueObjectSP
42 ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope,
43                                lldb::RegisterContextSP &reg_ctx_sp,
44                                uint32_t set_idx) {
45   auto manager_sp = ValueObjectManager::Create();
46   return (new ValueObjectRegisterSet(exe_scope, *manager_sp, reg_ctx_sp,
47                                      set_idx))
48       ->GetSP();
49 }
50 
51 ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
52                                                ValueObjectManager &manager,
53                                                lldb::RegisterContextSP &reg_ctx,
54                                                uint32_t reg_set_idx)
55     : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx),
56       m_reg_set(nullptr), m_reg_set_idx(reg_set_idx) {
57   assert(reg_ctx);
58   m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx);
59   if (m_reg_set) {
60     m_name.SetCString(m_reg_set->name);
61   }
62 }
63 
64 ValueObjectRegisterSet::~ValueObjectRegisterSet() = default;
65 
66 CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() {
67   return CompilerType();
68 }
69 
70 ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); }
71 
72 ConstString ValueObjectRegisterSet::GetQualifiedTypeName() {
73   return ConstString();
74 }
75 
76 size_t ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) {
77   const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
78   if (reg_set) {
79     auto reg_count = reg_set->num_registers;
80     return reg_count <= max ? reg_count : max;
81   }
82   return 0;
83 }
84 
85 llvm::Optional<uint64_t> ValueObjectRegisterSet::GetByteSize() { return 0; }
86 
87 bool ValueObjectRegisterSet::UpdateValue() {
88   m_error.Clear();
89   SetValueDidChange(false);
90   ExecutionContext exe_ctx(GetExecutionContextRef());
91   StackFrame *frame = exe_ctx.GetFramePtr();
92   if (frame == nullptr)
93     m_reg_ctx_sp.reset();
94   else {
95     m_reg_ctx_sp = frame->GetRegisterContext();
96     if (m_reg_ctx_sp) {
97       const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx);
98       if (reg_set == nullptr)
99         m_reg_ctx_sp.reset();
100       else if (m_reg_set != reg_set) {
101         SetValueDidChange(true);
102         m_name.SetCString(reg_set->name);
103       }
104     }
105   }
106   if (m_reg_ctx_sp) {
107     SetValueIsValid(true);
108   } else {
109     SetValueIsValid(false);
110     m_error.SetErrorToGenericError();
111     m_children.Clear();
112   }
113   return m_error.Success();
114 }
115 
116 ValueObject *ValueObjectRegisterSet::CreateChildAtIndex(
117     size_t idx, bool synthetic_array_member, int32_t synthetic_index) {
118   ValueObject *valobj = nullptr;
119   if (m_reg_ctx_sp && m_reg_set) {
120     const size_t num_children = GetNumChildren();
121     if (idx < num_children)
122       valobj = new ValueObjectRegister(
123           *this, m_reg_ctx_sp,
124           m_reg_ctx_sp->GetRegisterInfoAtIndex(m_reg_set->registers[idx]));
125   }
126   return valobj;
127 }
128 
129 lldb::ValueObjectSP
130 ValueObjectRegisterSet::GetChildMemberWithName(ConstString name,
131                                                bool can_create) {
132   ValueObject *valobj = nullptr;
133   if (m_reg_ctx_sp && m_reg_set) {
134     const RegisterInfo *reg_info =
135         m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef());
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 
145 size_t
146 ValueObjectRegisterSet::GetIndexOfChildWithName(ConstString name) {
147   if (m_reg_ctx_sp && m_reg_set) {
148     const RegisterInfo *reg_info =
149         m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef());
150     if (reg_info != nullptr)
151       return reg_info->kinds[eRegisterKindLLDB];
152   }
153   return UINT32_MAX;
154 }
155 
156 #pragma mark -
157 #pragma mark ValueObjectRegister
158 
159 void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) {
160   if (reg_info) {
161     m_reg_info = *reg_info;
162     if (reg_info->name)
163       m_name.SetCString(reg_info->name);
164     else if (reg_info->alt_name)
165       m_name.SetCString(reg_info->alt_name);
166   }
167 }
168 
169 ValueObjectRegister::ValueObjectRegister(ValueObject &parent,
170                                          lldb::RegisterContextSP &reg_ctx_sp,
171                                          const RegisterInfo *reg_info)
172     : ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(),
173       m_reg_value(), m_type_name(), m_compiler_type() {
174   assert(reg_ctx_sp.get());
175   ConstructObject(reg_info);
176 }
177 
178 ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope,
179                                           lldb::RegisterContextSP &reg_ctx_sp,
180                                           const RegisterInfo *reg_info) {
181   auto manager_sp = ValueObjectManager::Create();
182   return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info))
183       ->GetSP();
184 }
185 
186 ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope,
187                                          ValueObjectManager &manager,
188                                          lldb::RegisterContextSP &reg_ctx,
189                                          const RegisterInfo *reg_info)
190     : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(),
191       m_reg_value(), m_type_name(), m_compiler_type() {
192   assert(reg_ctx);
193   ConstructObject(reg_info);
194 }
195 
196 ValueObjectRegister::~ValueObjectRegister() = default;
197 
198 CompilerType ValueObjectRegister::GetCompilerTypeImpl() {
199   if (!m_compiler_type.IsValid()) {
200     ExecutionContext exe_ctx(GetExecutionContextRef());
201     if (auto *target = exe_ctx.GetTargetPtr()) {
202       if (auto *exe_module = target->GetExecutableModulePointer()) {
203         auto type_system_or_err =
204             exe_module->GetTypeSystemForLanguage(eLanguageTypeC);
205         if (auto err = type_system_or_err.takeError()) {
206           LLDB_LOG_ERROR(GetLog(LLDBLog::Types), std::move(err),
207                          "Unable to get CompilerType from TypeSystem");
208         } else {
209           m_compiler_type =
210               type_system_or_err->GetBuiltinTypeForEncodingAndBitSize(
211                   m_reg_info.encoding, m_reg_info.byte_size * 8);
212         }
213       }
214     }
215   }
216   return m_compiler_type;
217 }
218 
219 ConstString ValueObjectRegister::GetTypeName() {
220   if (m_type_name.IsEmpty())
221     m_type_name = GetCompilerType().GetTypeName();
222   return m_type_name;
223 }
224 
225 size_t ValueObjectRegister::CalculateNumChildren(uint32_t max) {
226   ExecutionContext exe_ctx(GetExecutionContextRef());
227   auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
228   return children_count <= max ? children_count : max;
229 }
230 
231 llvm::Optional<uint64_t> ValueObjectRegister::GetByteSize() {
232   return m_reg_info.byte_size;
233 }
234 
235 bool 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.SetErrorToGenericError();
264   return false;
265 }
266 
267 bool 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.SetErrorString("unable to write back to register");
277     return false;
278   }
279 
280   SetNeedsUpdate();
281   return true;
282 }
283 
284 bool 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.SetErrorString("unable to write back to register");
291     return false;
292   }
293 
294   SetNeedsUpdate();
295   return true;
296 }
297 
298 bool ValueObjectRegister::ResolveValue(Scalar &scalar) {
299   if (UpdateValueIfNeeded(
300           false)) // make sure that you are up to date before returning anything
301     return m_reg_value.GetScalarValue(scalar);
302   return false;
303 }
304 
305 void ValueObjectRegister::GetExpressionPath(Stream &s,
306                                             GetExpressionPathFormat epformat) {
307   s.Printf("$%s", m_reg_info.name);
308 }
309