//===-- ValueObjectRegister.cpp ---------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/Core/ValueObjectRegister.h" // C Includes // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/Core/Module.h" #include "lldb/Symbol/ClangASTType.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" using namespace lldb; using namespace lldb_private; #pragma mark ValueObjectRegisterContext ValueObjectRegisterContext::ValueObjectRegisterContext (ValueObject &parent, RegisterContextSP ®_ctx) : ValueObject (parent), m_reg_ctx_sp (reg_ctx) { assert (reg_ctx); m_name.SetCString("Registers"); SetValueIsValid (true); } ValueObjectRegisterContext::~ValueObjectRegisterContext() { } ClangASTType ValueObjectRegisterContext::GetClangTypeImpl () { return ClangASTType(); } ConstString ValueObjectRegisterContext::GetTypeName() { return ConstString(); } ConstString ValueObjectRegisterContext::GetQualifiedTypeName() { return ConstString(); } size_t ValueObjectRegisterContext::CalculateNumChildren() { return m_reg_ctx_sp->GetRegisterSetCount(); } uint64_t ValueObjectRegisterContext::GetByteSize() { return 0; } bool ValueObjectRegisterContext::UpdateValue () { m_error.Clear(); ExecutionContext exe_ctx(GetExecutionContextRef()); StackFrame *frame = exe_ctx.GetFramePtr(); if (frame) m_reg_ctx_sp = frame->GetRegisterContext(); else m_reg_ctx_sp.reset(); if (m_reg_ctx_sp.get() == NULL) { SetValueIsValid (false); m_error.SetErrorToGenericError(); } else SetValueIsValid (true); return m_error.Success(); } ValueObject * ValueObjectRegisterContext::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index) { ValueObject *new_valobj = NULL; const size_t num_children = GetNumChildren(); if (idx < num_children) { ExecutionContext exe_ctx(GetExecutionContextRef()); new_valobj = new ValueObjectRegisterSet(exe_ctx.GetBestExecutionContextScope(), m_reg_ctx_sp, idx); } return new_valobj; } #pragma mark - #pragma mark ValueObjectRegisterSet ValueObjectSP ValueObjectRegisterSet::Create (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, uint32_t set_idx) { return (new ValueObjectRegisterSet (exe_scope, reg_ctx_sp, set_idx))->GetSP(); } ValueObjectRegisterSet::ValueObjectRegisterSet (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx, uint32_t reg_set_idx) : ValueObject (exe_scope), m_reg_ctx_sp (reg_ctx), m_reg_set (NULL), m_reg_set_idx (reg_set_idx) { assert (reg_ctx); m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx); if (m_reg_set) { m_name.SetCString (m_reg_set->name); } } ValueObjectRegisterSet::~ValueObjectRegisterSet() { } ClangASTType ValueObjectRegisterSet::GetClangTypeImpl () { return ClangASTType(); } ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); } ConstString ValueObjectRegisterSet::GetQualifiedTypeName() { return ConstString(); } size_t ValueObjectRegisterSet::CalculateNumChildren() { const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx); if (reg_set) return reg_set->num_registers; return 0; } uint64_t ValueObjectRegisterSet::GetByteSize() { return 0; } bool ValueObjectRegisterSet::UpdateValue () { m_error.Clear(); SetValueDidChange (false); ExecutionContext exe_ctx(GetExecutionContextRef()); StackFrame *frame = exe_ctx.GetFramePtr(); if (frame == NULL) m_reg_ctx_sp.reset(); else { m_reg_ctx_sp = frame->GetRegisterContext (); if (m_reg_ctx_sp) { const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet (m_reg_set_idx); if (reg_set == NULL) m_reg_ctx_sp.reset(); else if (m_reg_set != reg_set) { SetValueDidChange (true); m_name.SetCString(reg_set->name); } } } if (m_reg_ctx_sp) { SetValueIsValid (true); } else { SetValueIsValid (false); m_error.SetErrorToGenericError (); m_children.Clear(); } return m_error.Success(); } ValueObject * ValueObjectRegisterSet::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index) { ValueObject *valobj = NULL; if (m_reg_ctx_sp && m_reg_set) { const size_t num_children = GetNumChildren(); if (idx < num_children) valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, m_reg_set->registers[idx]); } return valobj; } lldb::ValueObjectSP ValueObjectRegisterSet::GetChildMemberWithName (const ConstString &name, bool can_create) { ValueObject *valobj = NULL; if (m_reg_ctx_sp && m_reg_set) { const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName (name.AsCString()); if (reg_info != NULL) valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info->kinds[eRegisterKindLLDB]); } if (valobj) return valobj->GetSP(); else return ValueObjectSP(); } size_t ValueObjectRegisterSet::GetIndexOfChildWithName (const ConstString &name) { if (m_reg_ctx_sp && m_reg_set) { const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName (name.AsCString()); if (reg_info != NULL) return reg_info->kinds[eRegisterKindLLDB]; } return UINT32_MAX; } #pragma mark - #pragma mark ValueObjectRegister void ValueObjectRegister::ConstructObject (uint32_t reg_num) { const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoAtIndex (reg_num); if (reg_info) { m_reg_info = *reg_info; if (reg_info->name) m_name.SetCString(reg_info->name); else if (reg_info->alt_name) m_name.SetCString(reg_info->alt_name); } } ValueObjectRegister::ValueObjectRegister (ValueObject &parent, lldb::RegisterContextSP ®_ctx_sp, uint32_t reg_num) : ValueObject (parent), m_reg_ctx_sp (reg_ctx_sp), m_reg_info (), m_reg_value (), m_type_name (), m_clang_type () { assert (reg_ctx_sp.get()); ConstructObject(reg_num); } ValueObjectSP ValueObjectRegister::Create (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, uint32_t reg_num) { return (new ValueObjectRegister (exe_scope, reg_ctx_sp, reg_num))->GetSP(); } ValueObjectRegister::ValueObjectRegister (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx, uint32_t reg_num) : ValueObject (exe_scope), m_reg_ctx_sp (reg_ctx), m_reg_info (), m_reg_value (), m_type_name (), m_clang_type () { assert (reg_ctx); ConstructObject(reg_num); } ValueObjectRegister::~ValueObjectRegister() { } ClangASTType ValueObjectRegister::GetClangTypeImpl () { if (!m_clang_type.IsValid()) { ExecutionContext exe_ctx (GetExecutionContextRef()); Target *target = exe_ctx.GetTargetPtr(); if (target) { Module *exe_module = target->GetExecutableModulePointer(); if (exe_module) { m_clang_type = exe_module->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize (m_reg_info.encoding, m_reg_info.byte_size * 8); } } } return m_clang_type; } ConstString ValueObjectRegister::GetTypeName() { if (m_type_name.IsEmpty()) m_type_name = GetClangType().GetConstTypeName (); return m_type_name; } size_t ValueObjectRegister::CalculateNumChildren() { return GetClangType().GetNumChildren(true); } uint64_t ValueObjectRegister::GetByteSize() { return m_reg_info.byte_size; } bool ValueObjectRegister::UpdateValue () { m_error.Clear(); ExecutionContext exe_ctx(GetExecutionContextRef()); StackFrame *frame = exe_ctx.GetFramePtr(); if (frame == NULL) { m_reg_ctx_sp.reset(); m_reg_value.Clear(); } if (m_reg_ctx_sp) { if (m_reg_ctx_sp->ReadRegister (&m_reg_info, m_reg_value)) { if (m_reg_value.GetData (m_data)) { Process *process = exe_ctx.GetProcessPtr(); if (process) m_data.SetAddressByteSize(process->GetAddressByteSize()); m_value.SetContext(Value::eContextTypeRegisterInfo, (void *)&m_reg_info); m_value.SetValueType(Value::eValueTypeHostAddress); m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); SetValueIsValid (true); return true; } } } SetValueIsValid (false); m_error.SetErrorToGenericError (); return false; } bool ValueObjectRegister::SetValueFromCString (const char *value_str, Error& error) { // The new value will be in the m_data. Copy that into our register value. error = m_reg_value.SetValueFromCString (&m_reg_info, value_str); if (error.Success()) { if (m_reg_ctx_sp->WriteRegister (&m_reg_info, m_reg_value)) { SetNeedsUpdate(); return true; } else return false; } else return false; } bool ValueObjectRegister::SetData (DataExtractor &data, Error &error) { error = m_reg_value.SetValueFromData(&m_reg_info, data, 0, false); if (error.Success()) { if (m_reg_ctx_sp->WriteRegister (&m_reg_info, m_reg_value)) { SetNeedsUpdate(); return true; } else return false; } else return false; } bool ValueObjectRegister::ResolveValue (Scalar &scalar) { if (UpdateValueIfNeeded(false)) // make sure that you are up to date before returning anything return m_reg_value.GetScalarValue(scalar); return false; } void ValueObjectRegister::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat epformat) { s.Printf("$%s", m_reg_info.name); }