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 ®_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 ®_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 ®_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 ®_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 ®_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