| //===-- SBValue.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/API/SBValue.h" |
| #include "lldb/API/SBStream.h" |
| |
| #include "lldb/Breakpoint/Watchpoint.h" |
| #include "lldb/Core/DataExtractor.h" |
| #include "lldb/Core/Log.h" |
| #include "lldb/Core/Module.h" |
| #include "lldb/Core/Scalar.h" |
| #include "lldb/Core/Stream.h" |
| #include "lldb/Core/StreamFile.h" |
| #include "lldb/Core/Value.h" |
| #include "lldb/Core/ValueObject.h" |
| #include "lldb/Core/ValueObjectConstResult.h" |
| #include "lldb/Symbol/Block.h" |
| #include "lldb/Symbol/ObjectFile.h" |
| #include "lldb/Symbol/Variable.h" |
| #include "lldb/Symbol/VariableList.h" |
| #include "lldb/Target/ExecutionContext.h" |
| #include "lldb/Target/Process.h" |
| #include "lldb/Target/StackFrame.h" |
| #include "lldb/Target/Target.h" |
| #include "lldb/Target/Thread.h" |
| |
| #include "lldb/API/SBProcess.h" |
| #include "lldb/API/SBTarget.h" |
| #include "lldb/API/SBThread.h" |
| #include "lldb/API/SBFrame.h" |
| #include "lldb/API/SBDebugger.h" |
| |
| using namespace lldb; |
| using namespace lldb_private; |
| |
| SBValue::SBValue () : |
| m_opaque_sp () |
| { |
| } |
| |
| SBValue::SBValue (const lldb::ValueObjectSP &value_sp) : |
| m_opaque_sp (value_sp) |
| { |
| } |
| |
| SBValue::SBValue(const SBValue &rhs) : |
| m_opaque_sp (rhs.m_opaque_sp) |
| { |
| } |
| |
| SBValue & |
| SBValue::operator = (const SBValue &rhs) |
| { |
| if (this != &rhs) |
| m_opaque_sp = rhs.m_opaque_sp; |
| return *this; |
| } |
| |
| SBValue::~SBValue() |
| { |
| } |
| |
| bool |
| SBValue::IsValid () |
| { |
| // If this function ever changes to anything that does more than just |
| // check if the opaque shared pointer is non NULL, then we need to update |
| // all "if (m_opaque_sp)" code in this file. |
| return m_opaque_sp.get() != NULL; |
| } |
| |
| SBError |
| SBValue::GetError() |
| { |
| SBError sb_error; |
| |
| if (m_opaque_sp.get()) |
| sb_error.SetError(m_opaque_sp->GetError()); |
| |
| return sb_error; |
| } |
| |
| user_id_t |
| SBValue::GetID() |
| { |
| if (m_opaque_sp) |
| return m_opaque_sp->GetID(); |
| return LLDB_INVALID_UID; |
| } |
| |
| const char * |
| SBValue::GetName() |
| { |
| |
| const char *name = NULL; |
| if (m_opaque_sp) |
| name = m_opaque_sp->GetName().GetCString(); |
| |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (name) |
| log->Printf ("SBValue(%p)::GetName () => \"%s\"", m_opaque_sp.get(), name); |
| else |
| log->Printf ("SBValue(%p)::GetName () => NULL", m_opaque_sp.get()); |
| } |
| |
| return name; |
| } |
| |
| const char * |
| SBValue::GetTypeName () |
| { |
| const char *name = NULL; |
| if (m_opaque_sp) |
| name = m_opaque_sp->GetTypeName().GetCString(); |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (name) |
| log->Printf ("SBValue(%p)::GetTypeName () => \"%s\"", m_opaque_sp.get(), name); |
| else |
| log->Printf ("SBValue(%p)::GetTypeName () => NULL", m_opaque_sp.get()); |
| } |
| |
| return name; |
| } |
| |
| size_t |
| SBValue::GetByteSize () |
| { |
| size_t result = 0; |
| |
| if (m_opaque_sp) |
| result = m_opaque_sp->GetByteSize(); |
| |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::GetByteSize () => %zu", m_opaque_sp.get(), result); |
| |
| return result; |
| } |
| |
| bool |
| SBValue::IsInScope () |
| { |
| bool result = false; |
| |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| result = m_opaque_sp->IsInScope (); |
| } |
| } |
| |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::IsInScope () => %i", m_opaque_sp.get(), result); |
| |
| return result; |
| } |
| |
| const char * |
| SBValue::GetValue () |
| { |
| const char *cstr = NULL; |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| cstr = m_opaque_sp->GetValueAsCString (); |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (cstr) |
| log->Printf ("SBValue(%p)::GetValue => \"%s\"", m_opaque_sp.get(), cstr); |
| else |
| log->Printf ("SBValue(%p)::GetValue => NULL", m_opaque_sp.get()); |
| } |
| |
| return cstr; |
| } |
| |
| ValueType |
| SBValue::GetValueType () |
| { |
| ValueType result = eValueTypeInvalid; |
| if (m_opaque_sp) |
| result = m_opaque_sp->GetValueType(); |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| switch (result) |
| { |
| case eValueTypeInvalid: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeInvalid", m_opaque_sp.get()); break; |
| case eValueTypeVariableGlobal: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableGlobal", m_opaque_sp.get()); break; |
| case eValueTypeVariableStatic: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableStatic", m_opaque_sp.get()); break; |
| case eValueTypeVariableArgument:log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableArgument", m_opaque_sp.get()); break; |
| case eValueTypeVariableLocal: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableLocal", m_opaque_sp.get()); break; |
| case eValueTypeRegister: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeRegister", m_opaque_sp.get()); break; |
| case eValueTypeRegisterSet: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeRegisterSet", m_opaque_sp.get()); break; |
| case eValueTypeConstResult: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeConstResult", m_opaque_sp.get()); break; |
| default: log->Printf ("SBValue(%p)::GetValueType () => %i ???", m_opaque_sp.get(), result); break; |
| } |
| } |
| return result; |
| } |
| |
| const char * |
| SBValue::GetObjectDescription () |
| { |
| const char *cstr = NULL; |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| cstr = m_opaque_sp->GetObjectDescription (); |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (cstr) |
| log->Printf ("SBValue(%p)::GetObjectDescription => \"%s\"", m_opaque_sp.get(), cstr); |
| else |
| log->Printf ("SBValue(%p)::GetObjectDescription => NULL", m_opaque_sp.get()); |
| } |
| return cstr; |
| } |
| |
| SBType |
| SBValue::GetType() |
| { |
| SBType result; |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| result = SBType(ClangASTType (m_opaque_sp->GetClangAST(), m_opaque_sp->GetClangType())); |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (result.IsValid()) |
| log->Printf ("SBValue(%p)::GetType => %p", m_opaque_sp.get(), &result); |
| else |
| log->Printf ("SBValue(%p)::GetType => NULL", m_opaque_sp.get()); |
| } |
| return result; |
| } |
| |
| bool |
| SBValue::GetValueDidChange () |
| { |
| bool result = false; |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| result = m_opaque_sp->GetValueDidChange (); |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::GetValueDidChange => %i", m_opaque_sp.get(), result); |
| |
| return result; |
| } |
| |
| const char * |
| SBValue::GetSummary () |
| { |
| const char *cstr = NULL; |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| cstr = m_opaque_sp->GetSummaryAsCString(); |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (cstr) |
| log->Printf ("SBValue(%p)::GetSummary => \"%s\"", m_opaque_sp.get(), cstr); |
| else |
| log->Printf ("SBValue(%p)::GetSummary => NULL", m_opaque_sp.get()); |
| } |
| return cstr; |
| } |
| |
| const char * |
| SBValue::GetLocation () |
| { |
| const char *cstr = NULL; |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| cstr = m_opaque_sp->GetLocationAsCString(); |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (cstr) |
| log->Printf ("SBValue(%p)::GetSummary => \"%s\"", m_opaque_sp.get(), cstr); |
| else |
| log->Printf ("SBValue(%p)::GetSummary => NULL", m_opaque_sp.get()); |
| } |
| return cstr; |
| } |
| |
| bool |
| SBValue::SetValueFromCString (const char *value_str) |
| { |
| bool success = false; |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| success = m_opaque_sp->SetValueFromCString (value_str); |
| } |
| } |
| return success; |
| } |
| |
| lldb::SBValue |
| SBValue::CreateChildAtOffset (const char *name, uint32_t offset, SBType type) |
| { |
| lldb::SBValue result; |
| if (m_opaque_sp) |
| { |
| if (type.IsValid()) |
| { |
| result = SBValue(m_opaque_sp->GetSyntheticChildAtOffset(offset, type.m_opaque_sp->GetClangASTType(), true)); |
| result.m_opaque_sp->SetName(ConstString(name)); |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (result.IsValid()) |
| log->Printf ("SBValue(%p)::GetChildAtOffset => \"%s\"", m_opaque_sp.get(), result.m_opaque_sp->GetName().AsCString()); |
| else |
| log->Printf ("SBValue(%p)::GetChildAtOffset => NULL", m_opaque_sp.get()); |
| } |
| return result; |
| } |
| |
| lldb::SBValue |
| SBValue::Cast (SBType type) |
| { |
| return CreateChildAtOffset(m_opaque_sp->GetName().GetCString(), 0, type); |
| } |
| |
| lldb::SBValue |
| SBValue::CreateValueFromExpression (const char *name, const char* expression) |
| { |
| lldb::SBValue result; |
| if (m_opaque_sp) |
| { |
| ValueObjectSP result_valobj_sp; |
| m_opaque_sp->GetUpdatePoint().GetTargetSP()->EvaluateExpression (expression, |
| m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()->CalculateStackFrame(), |
| eExecutionPolicyOnlyWhenNeeded, |
| true, // unwind on error |
| true, // keep in memory |
| eNoDynamicValues, |
| result_valobj_sp); |
| result_valobj_sp->SetName(ConstString(name)); |
| result = SBValue(result_valobj_sp); |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (result.IsValid()) |
| log->Printf ("SBValue(%p)::GetChildFromExpression => \"%s\"", m_opaque_sp.get(), result.m_opaque_sp->GetName().AsCString()); |
| else |
| log->Printf ("SBValue(%p)::GetChildFromExpression => NULL", m_opaque_sp.get()); |
| } |
| return result; |
| } |
| |
| lldb::SBValue |
| SBValue::CreateValueFromAddress(const char* name, lldb::addr_t address, SBType type) |
| { |
| lldb::SBValue result; |
| if (m_opaque_sp) |
| { |
| |
| SBType real_type(type.GetPointerType()); |
| |
| lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&address,sizeof(lldb::addr_t))); |
| |
| ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create (m_opaque_sp->GetUpdatePoint().GetExecutionContextScope(), |
| real_type.m_opaque_sp->GetASTContext(), |
| real_type.m_opaque_sp->GetOpaqueQualType(), |
| ConstString(name), |
| buffer, |
| lldb::endian::InlHostByteOrder(), |
| GetTarget().GetProcess().GetAddressByteSize())); |
| |
| ValueObjectSP result_valobj_sp; |
| |
| ptr_result_valobj_sp->GetValue().SetValueType(Value::eValueTypeLoadAddress); |
| if (ptr_result_valobj_sp) |
| { |
| Error err; |
| result_valobj_sp = ptr_result_valobj_sp->Dereference(err); |
| if (result_valobj_sp) |
| result_valobj_sp->SetName(ConstString(name)); |
| } |
| result = SBValue(result_valobj_sp); |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (result.IsValid()) |
| log->Printf ("SBValue(%p)::GetChildFromAddress => \"%s\"", m_opaque_sp.get(), result.m_opaque_sp->GetName().AsCString()); |
| else |
| log->Printf ("SBValue(%p)::GetChildFromAddress => NULL", m_opaque_sp.get()); |
| } |
| return result; |
| } |
| |
| lldb::SBValue |
| SBValue::CreateValueFromData (const char* name, SBData data, SBType type) |
| { |
| SBValue result; |
| |
| AddressType addr_of_children_priv = eAddressTypeLoad; |
| |
| if (m_opaque_sp) |
| { |
| ValueObjectSP valobj_sp; |
| valobj_sp = ValueObjectConstResult::Create (m_opaque_sp->GetExecutionContextScope(), |
| type.m_opaque_sp->GetASTContext() , |
| type.m_opaque_sp->GetOpaqueQualType(), |
| ConstString(name), |
| *data.m_opaque_sp, |
| LLDB_INVALID_ADDRESS); |
| valobj_sp->SetAddressTypeOfChildren(addr_of_children_priv); |
| result = SBValue(valobj_sp); |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (result.IsValid()) |
| log->Printf ("SBValue(%p)::GetChildFromExpression => \"%s\"", m_opaque_sp.get(), result.m_opaque_sp->GetName().AsCString()); |
| else |
| log->Printf ("SBValue(%p)::GetChildFromExpression => NULL", m_opaque_sp.get()); |
| } |
| return result; |
| } |
| |
| SBValue |
| SBValue::GetChildAtIndex (uint32_t idx) |
| { |
| const bool can_create_synthetic = false; |
| lldb::DynamicValueType use_dynamic = eNoDynamicValues; |
| if (m_opaque_sp) |
| use_dynamic = m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetPreferDynamicValue(); |
| return GetChildAtIndex (idx, use_dynamic, can_create_synthetic); |
| } |
| |
| SBValue |
| SBValue::GetChildAtIndex (uint32_t idx, lldb::DynamicValueType use_dynamic, bool can_create_synthetic) |
| { |
| lldb::ValueObjectSP child_sp; |
| |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| const bool can_create = true; |
| child_sp = m_opaque_sp->GetChildAtIndex (idx, can_create); |
| if (can_create_synthetic && !child_sp) |
| { |
| if (m_opaque_sp->IsPointerType()) |
| { |
| child_sp = m_opaque_sp->GetSyntheticArrayMemberFromPointer(idx, can_create); |
| } |
| else if (m_opaque_sp->IsArrayType()) |
| { |
| child_sp = m_opaque_sp->GetSyntheticArrayMemberFromArray(idx, can_create); |
| } |
| } |
| |
| if (child_sp) |
| { |
| if (use_dynamic != lldb::eNoDynamicValues) |
| { |
| lldb::ValueObjectSP dynamic_sp(child_sp->GetDynamicValue (use_dynamic)); |
| if (dynamic_sp) |
| child_sp = dynamic_sp; |
| } |
| } |
| } |
| } |
| |
| SBValue sb_value (child_sp); |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::GetChildAtIndex (%u) => SBValue(%p)", m_opaque_sp.get(), idx, sb_value.get()); |
| |
| return sb_value; |
| } |
| |
| uint32_t |
| SBValue::GetIndexOfChildWithName (const char *name) |
| { |
| uint32_t idx = UINT32_MAX; |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| |
| idx = m_opaque_sp->GetIndexOfChildWithName (ConstString(name)); |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (idx == UINT32_MAX) |
| log->Printf ("SBValue(%p)::GetIndexOfChildWithName (name=\"%s\") => NOT FOUND", m_opaque_sp.get(), name); |
| else |
| log->Printf ("SBValue(%p)::GetIndexOfChildWithName (name=\"%s\") => %u", m_opaque_sp.get(), name, idx); |
| } |
| return idx; |
| } |
| |
| SBValue |
| SBValue::GetChildMemberWithName (const char *name) |
| { |
| if (m_opaque_sp) |
| { |
| lldb::DynamicValueType use_dynamic_value = m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetPreferDynamicValue(); |
| return GetChildMemberWithName (name, use_dynamic_value); |
| } |
| else |
| return GetChildMemberWithName (name, eNoDynamicValues); |
| } |
| |
| SBValue |
| SBValue::GetChildMemberWithName (const char *name, lldb::DynamicValueType use_dynamic_value) |
| { |
| lldb::ValueObjectSP child_sp; |
| const ConstString str_name (name); |
| |
| |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| child_sp = m_opaque_sp->GetChildMemberWithName (str_name, true); |
| if (use_dynamic_value != lldb::eNoDynamicValues) |
| { |
| if (child_sp) |
| { |
| lldb::ValueObjectSP dynamic_sp = child_sp->GetDynamicValue (use_dynamic_value); |
| if (dynamic_sp) |
| child_sp = dynamic_sp; |
| } |
| } |
| } |
| } |
| |
| SBValue sb_value (child_sp); |
| |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::GetChildMemberWithName (name=\"%s\") => SBValue(%p)", m_opaque_sp.get(), name, sb_value.get()); |
| |
| return sb_value; |
| } |
| |
| lldb::SBValue |
| SBValue::GetValueForExpressionPath(const char* expr_path) |
| { |
| lldb::ValueObjectSP child_sp; |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| // using default values for all the fancy options, just do it if you can |
| child_sp = m_opaque_sp->GetValueForExpressionPath(expr_path); |
| } |
| } |
| |
| SBValue sb_value (child_sp); |
| |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::GetValueForExpressionPath (expr_path=\"%s\") => SBValue(%p)", m_opaque_sp.get(), expr_path, sb_value.get()); |
| |
| return sb_value; |
| } |
| |
| int64_t |
| SBValue::GetValueAsSigned(SBError& error, int64_t fail_value) |
| { |
| error.Clear(); |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| Scalar scalar; |
| if (m_opaque_sp->ResolveValue (scalar)) |
| return scalar.GetRawBits64(fail_value); |
| else |
| error.SetErrorString("could not get value"); |
| } |
| else |
| error.SetErrorString("could not get target"); |
| } |
| error.SetErrorString("invalid SBValue"); |
| return fail_value; |
| } |
| |
| uint64_t |
| SBValue::GetValueAsUnsigned(SBError& error, uint64_t fail_value) |
| { |
| error.Clear(); |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| Scalar scalar; |
| if (m_opaque_sp->ResolveValue (scalar)) |
| return scalar.GetRawBits64(fail_value); |
| else |
| error.SetErrorString("could not get value"); |
| } |
| else |
| error.SetErrorString("could not get target"); |
| } |
| error.SetErrorString("invalid SBValue"); |
| return fail_value; |
| } |
| |
| int64_t |
| SBValue::GetValueAsSigned(int64_t fail_value) |
| { |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| Scalar scalar; |
| if (m_opaque_sp->ResolveValue (scalar)) |
| return scalar.GetRawBits64(fail_value); |
| } |
| } |
| return fail_value; |
| } |
| |
| uint64_t |
| SBValue::GetValueAsUnsigned(uint64_t fail_value) |
| { |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| Scalar scalar; |
| if (m_opaque_sp->ResolveValue (scalar)) |
| return scalar.GetRawBits64(fail_value); |
| } |
| } |
| return fail_value; |
| } |
| |
| uint32_t |
| SBValue::GetNumChildren () |
| { |
| uint32_t num_children = 0; |
| |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| |
| num_children = m_opaque_sp->GetNumChildren(); |
| } |
| } |
| |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::GetNumChildren () => %u", m_opaque_sp.get(), num_children); |
| |
| return num_children; |
| } |
| |
| |
| SBValue |
| SBValue::Dereference () |
| { |
| SBValue sb_value; |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| |
| Error error; |
| sb_value = m_opaque_sp->Dereference (error); |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::Dereference () => SBValue(%p)", m_opaque_sp.get(), sb_value.get()); |
| |
| return sb_value; |
| } |
| |
| bool |
| SBValue::TypeIsPointerType () |
| { |
| bool is_ptr_type = false; |
| |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| |
| is_ptr_type = m_opaque_sp->IsPointerType(); |
| } |
| } |
| |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::TypeIsPointerType () => %i", m_opaque_sp.get(), is_ptr_type); |
| |
| |
| return is_ptr_type; |
| } |
| |
| void * |
| SBValue::GetOpaqueType() |
| { |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); |
| |
| return m_opaque_sp->GetClangType(); |
| } |
| } |
| return NULL; |
| } |
| |
| lldb::SBTarget |
| SBValue::GetTarget() |
| { |
| SBTarget result; |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) |
| { |
| result = SBTarget(lldb::TargetSP(m_opaque_sp->GetUpdatePoint().GetTargetSP())); |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (result.get() == NULL) |
| log->Printf ("SBValue(%p)::GetTarget () => NULL", m_opaque_sp.get()); |
| else |
| log->Printf ("SBValue(%p)::GetTarget () => %p", m_opaque_sp.get(), result.get()); |
| } |
| return result; |
| } |
| |
| lldb::SBProcess |
| SBValue::GetProcess() |
| { |
| SBProcess result; |
| if (m_opaque_sp) |
| { |
| Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); |
| if (target) |
| { |
| result = SBProcess(lldb::ProcessSP(target->GetProcessSP())); |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (result.get() == NULL) |
| log->Printf ("SBValue(%p)::GetProcess () => NULL", m_opaque_sp.get()); |
| else |
| log->Printf ("SBValue(%p)::GetProcess () => %p", m_opaque_sp.get(), result.get()); |
| } |
| return result; |
| } |
| |
| lldb::SBThread |
| SBValue::GetThread() |
| { |
| SBThread result; |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()) |
| { |
| result = SBThread(m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()->CalculateThread()->GetSP()); |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (result.get() == NULL) |
| log->Printf ("SBValue(%p)::GetThread () => NULL", m_opaque_sp.get()); |
| else |
| log->Printf ("SBValue(%p)::GetThread () => %p", m_opaque_sp.get(), result.get()); |
| } |
| return result; |
| } |
| |
| lldb::SBFrame |
| SBValue::GetFrame() |
| { |
| SBFrame result; |
| if (m_opaque_sp) |
| { |
| if (m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()) |
| { |
| result.SetFrame (m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()->CalculateStackFrame()->GetSP()); |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| { |
| if (result.get() == NULL) |
| log->Printf ("SBValue(%p)::GetFrame () => NULL", m_opaque_sp.get()); |
| else |
| log->Printf ("SBValue(%p)::GetFrame () => %p", m_opaque_sp.get(), result.get()); |
| } |
| return result; |
| } |
| |
| |
| // Mimic shared pointer... |
| lldb_private::ValueObject * |
| SBValue::get() const |
| { |
| return m_opaque_sp.get(); |
| } |
| |
| lldb_private::ValueObject * |
| SBValue::operator->() const |
| { |
| return m_opaque_sp.get(); |
| } |
| |
| lldb::ValueObjectSP & |
| SBValue::operator*() |
| { |
| return m_opaque_sp; |
| } |
| |
| const lldb::ValueObjectSP & |
| SBValue::operator*() const |
| { |
| return m_opaque_sp; |
| } |
| |
| bool |
| SBValue::GetExpressionPath (SBStream &description) |
| { |
| if (m_opaque_sp) |
| { |
| m_opaque_sp->GetExpressionPath (description.ref(), false); |
| return true; |
| } |
| return false; |
| } |
| |
| bool |
| SBValue::GetExpressionPath (SBStream &description, bool qualify_cxx_base_classes) |
| { |
| if (m_opaque_sp) |
| { |
| m_opaque_sp->GetExpressionPath (description.ref(), qualify_cxx_base_classes); |
| return true; |
| } |
| return false; |
| } |
| |
| bool |
| SBValue::GetDescription (SBStream &description) |
| { |
| Stream &strm = description.ref(); |
| |
| if (m_opaque_sp) |
| { |
| ValueObject::DumpValueObject (strm, m_opaque_sp.get()); |
| } |
| else |
| strm.PutCString ("No value"); |
| |
| return true; |
| } |
| |
| lldb::Format |
| SBValue::GetFormat () |
| { |
| if (m_opaque_sp) |
| return m_opaque_sp->GetFormat(); |
| return eFormatDefault; |
| } |
| |
| void |
| SBValue::SetFormat (lldb::Format format) |
| { |
| if (m_opaque_sp) |
| m_opaque_sp->SetFormat(format); |
| } |
| |
| lldb::SBValue |
| SBValue::AddressOf() |
| { |
| SBValue sb_value; |
| if (m_opaque_sp) |
| { |
| Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); |
| if (target) |
| { |
| Mutex::Locker api_locker (target->GetAPIMutex()); |
| Error error; |
| sb_value = m_opaque_sp->AddressOf (error); |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::GetPointerToObject () => SBValue(%p)", m_opaque_sp.get(), sb_value.get()); |
| |
| return sb_value; |
| } |
| |
| lldb::addr_t |
| SBValue::GetLoadAddress() |
| { |
| lldb::addr_t value = LLDB_INVALID_ADDRESS; |
| if (m_opaque_sp) |
| { |
| Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); |
| if (target) |
| { |
| Mutex::Locker api_locker (target->GetAPIMutex()); |
| const bool scalar_is_load_address = true; |
| AddressType addr_type; |
| value = m_opaque_sp->GetAddressOf(scalar_is_load_address, &addr_type); |
| if (addr_type == eAddressTypeFile) |
| { |
| Module* module = m_opaque_sp->GetModule(); |
| if (!module) |
| value = LLDB_INVALID_ADDRESS; |
| else |
| { |
| Address addr; |
| module->ResolveFileAddress(value, addr); |
| value = addr.GetLoadAddress(m_opaque_sp->GetUpdatePoint().GetTargetSP().get()); |
| } |
| } |
| else if (addr_type == eAddressTypeHost || addr_type == eAddressTypeInvalid) |
| value = LLDB_INVALID_ADDRESS; |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::GetLoadAddress () => (%llu)", m_opaque_sp.get(), value); |
| |
| return value; |
| } |
| |
| lldb::SBAddress |
| SBValue::GetAddress() |
| { |
| Address addr; |
| if (m_opaque_sp) |
| { |
| Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); |
| if (target) |
| { |
| lldb::addr_t value = LLDB_INVALID_ADDRESS; |
| Mutex::Locker api_locker (target->GetAPIMutex()); |
| const bool scalar_is_load_address = true; |
| AddressType addr_type; |
| value = m_opaque_sp->GetAddressOf(scalar_is_load_address, &addr_type); |
| if (addr_type == eAddressTypeFile) |
| { |
| Module* module = m_opaque_sp->GetModule(); |
| if (module) |
| module->ResolveFileAddress(value, addr); |
| } |
| else if (addr_type == eAddressTypeLoad) |
| { |
| // no need to check the return value on this.. if it can actually do the resolve |
| // addr will be in the form (section,offset), otherwise it will simply be returned |
| // as (NULL, value) |
| addr.SetLoadAddress(value, target); |
| } |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::GetAddress () => (%s,%llu)", m_opaque_sp.get(), (addr.GetSection() ? addr.GetSection()->GetName().GetCString() : "NULL"), addr.GetOffset()); |
| return SBAddress(new Address(addr)); |
| } |
| |
| lldb::SBData |
| SBValue::GetPointeeData (uint32_t item_idx, |
| uint32_t item_count) |
| { |
| lldb::SBData sb_data; |
| if (m_opaque_sp) |
| { |
| Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); |
| if (target) |
| { |
| DataExtractorSP data_sp(new DataExtractor()); |
| Mutex::Locker api_locker (target->GetAPIMutex()); |
| m_opaque_sp->GetPointeeData(*data_sp, item_idx, item_count); |
| if (data_sp->GetByteSize() > 0) |
| *sb_data = data_sp; |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::GetPointeeData (%d, %d) => SBData(%p)", |
| m_opaque_sp.get(), |
| item_idx, |
| item_count, |
| sb_data.get()); |
| |
| return sb_data; |
| } |
| |
| lldb::SBData |
| SBValue::GetData () |
| { |
| lldb::SBData sb_data; |
| if (m_opaque_sp) |
| { |
| Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); |
| if (target) |
| { |
| DataExtractorSP data_sp(new DataExtractor()); |
| Mutex::Locker api_locker (target->GetAPIMutex()); |
| m_opaque_sp->GetData(*data_sp); |
| if (data_sp->GetByteSize() > 0) |
| *sb_data = data_sp; |
| } |
| } |
| LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::GetData () => SBData(%p)", |
| m_opaque_sp.get(), |
| sb_data.get()); |
| |
| return sb_data; |
| } |
| |
| lldb::SBWatchpoint |
| SBValue::Watch (bool resolve_location, bool read, bool write) |
| { |
| lldb::SBWatchpoint sb_watchpoint; |
| if (!m_opaque_sp) |
| return sb_watchpoint; |
| |
| Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); |
| if (target) |
| { |
| Mutex::Locker api_locker (target->GetAPIMutex()); |
| sb_watchpoint = WatchValue(read, write, false); |
| } |
| LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::Watch (resolve_location=%i, read=%i, write=%i) => wp(%p)", |
| m_opaque_sp.get(), resolve_location, read, write, sb_watchpoint.get()); |
| return sb_watchpoint; |
| } |
| |
| lldb::SBWatchpoint |
| SBValue::WatchPointee (bool resolve_location, bool read, bool write) |
| { |
| lldb::SBWatchpoint sb_watchpoint; |
| if (!m_opaque_sp) |
| return sb_watchpoint; |
| |
| Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); |
| if (target) |
| { |
| Mutex::Locker api_locker (target->GetAPIMutex()); |
| sb_watchpoint = WatchValue(read, write, true); |
| } |
| LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); |
| if (log) |
| log->Printf ("SBValue(%p)::WatchPointee (resolve_location=%i, read=%i, write=%i) => wp(%p)", |
| m_opaque_sp.get(), resolve_location, read, write, sb_watchpoint.get()); |
| return sb_watchpoint; |
| } |
| |
| // Helper function for SBValue::Watch() and SBValue::WatchPointee(). |
| SBWatchpoint |
| SBValue::WatchValue(bool read, bool write, bool watch_pointee) |
| { |
| SBWatchpoint sb_wp_empty; |
| |
| // If the SBValue is not valid, there's no point in even trying to watch it. |
| if (!IsValid() || !GetFrame().IsValid()) |
| return sb_wp_empty; |
| |
| // Read and Write cannot both be false. |
| if (!read && !write) |
| return sb_wp_empty; |
| |
| // If we are watching the pointee, check that the SBValue is a pointer type. |
| if (watch_pointee && !GetType().IsPointerType()) |
| return sb_wp_empty; |
| |
| addr_t addr; |
| size_t size; |
| if (watch_pointee) { |
| addr = GetValueAsUnsigned(LLDB_INVALID_ADDRESS); |
| size = GetType().GetPointeeType().GetByteSize(); |
| } else { |
| addr = GetLoadAddress(); |
| size = GetByteSize(); |
| } |
| |
| // Sanity check the address and the size before calling Target::CreateWatchpoint(). |
| if (addr == LLDB_INVALID_ADDRESS || size == 0) |
| return sb_wp_empty; |
| |
| uint32_t watch_type = (read ? LLDB_WATCH_TYPE_READ : 0) | |
| (write ? LLDB_WATCH_TYPE_WRITE : 0); |
| WatchpointSP wp_sp = GetFrame().m_opaque_sp->GetThread().GetProcess().GetTarget(). |
| CreateWatchpoint(addr, size, watch_type); |
| |
| if (wp_sp) { |
| // StackFrame::GetInScopeVariableList(true) to get file globals as well. |
| VariableListSP var_list_sp(GetFrame().m_opaque_sp->GetInScopeVariableList(true)); |
| VariableSP var_sp = var_list_sp->FindVariable(ConstString(GetName())); |
| if (var_sp && var_sp->GetDeclaration().GetFile()) { |
| StreamString ss; |
| // True to show fullpath for declaration file. |
| var_sp->GetDeclaration().DumpStopContext(&ss, true); |
| wp_sp->SetDeclInfo(ss.GetString()); |
| } |
| } |
| return wp_sp; |
| } |
| |