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