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