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 <assert.h> 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 ®_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 ®_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() {} 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(*this, m_reg_ctx_sp, 122 m_reg_set->registers[idx]); 123 } 124 return valobj; 125 } 126 127 lldb::ValueObjectSP 128 ValueObjectRegisterSet::GetChildMemberWithName(ConstString name, 129 bool can_create) { 130 ValueObject *valobj = nullptr; 131 if (m_reg_ctx_sp && m_reg_set) { 132 const RegisterInfo *reg_info = 133 m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef()); 134 if (reg_info != nullptr) 135 valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, 136 reg_info->kinds[eRegisterKindLLDB]); 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(uint32_t reg_num) { 159 const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoAtIndex(reg_num); 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 uint32_t reg_num) 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_num); 176 } 177 178 ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope, 179 lldb::RegisterContextSP ®_ctx_sp, 180 uint32_t reg_num) { 181 auto manager_sp = ValueObjectManager::Create(); 182 return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_num)) 183 ->GetSP(); 184 } 185 186 ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope, 187 ValueObjectManager &manager, 188 lldb::RegisterContextSP ®_ctx, 189 uint32_t reg_num) 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_num); 194 } 195 196 ValueObjectRegister::~ValueObjectRegister() {} 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( 207 lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TYPES), 208 std::move(err), "Unable to get CompilerType from TypeSystem"); 209 } else { 210 m_compiler_type = 211 type_system_or_err->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 llvm::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::eContextTypeRegisterInfo, 253 (void *)&m_reg_info); 254 m_value.SetValueType(Value::eValueTypeHostAddress); 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 if (m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) { 275 SetNeedsUpdate(); 276 return true; 277 } else 278 return false; 279 } else 280 return false; 281 } 282 283 bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) { 284 error = m_reg_value.SetValueFromData(&m_reg_info, data, 0, false); 285 if (error.Success()) { 286 if (m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) { 287 SetNeedsUpdate(); 288 return true; 289 } else 290 return false; 291 } else 292 return false; 293 } 294 295 bool ValueObjectRegister::ResolveValue(Scalar &scalar) { 296 if (UpdateValueIfNeeded( 297 false)) // make sure that you are up to date before returning anything 298 return m_reg_value.GetScalarValue(scalar); 299 return false; 300 } 301 302 void ValueObjectRegister::GetExpressionPath(Stream &s, 303 GetExpressionPathFormat epformat) { 304 s.Printf("$%s", m_reg_info.name); 305 } 306