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