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