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