| //===-- ValueObject.h -------------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef liblldb_ValueObject_h_ |
| #define liblldb_ValueObject_h_ |
| |
| // C Includes |
| // C++ Includes |
| #include <map> |
| #include <vector> |
| // Other libraries and framework includes |
| // Project includes |
| |
| #include "lldb/lldb-private.h" |
| #include "lldb/Core/DataExtractor.h" |
| #include "lldb/Core/Error.h" |
| #include "lldb/Core/Flags.h" |
| #include "lldb/Core/ConstString.h" |
| #include "lldb/Core/UserID.h" |
| #include "lldb/Core/Value.h" |
| #include "lldb/Target/ExecutionContext.h" |
| #include "lldb/Target/ExecutionContextScope.h" |
| #include "lldb/Target/Process.h" |
| #include "lldb/Target/StackID.h" |
| #include "lldb/Utility/SharedCluster.h" |
| |
| namespace lldb_private { |
| |
| /// ValueObject: |
| /// |
| /// This abstract class provides an interface to a particular value, be it a register, a local or global variable, |
| /// that is evaluated in some particular scope. The ValueObject also has the capibility of being the "child" of |
| /// some other variable object, and in turn of having children. |
| /// If a ValueObject is a root variable object - having no parent - then it must be constructed with respect to some |
| /// particular ExecutionContextScope. If it is a child, it inherits the ExecutionContextScope from its parent. |
| /// The ValueObject will update itself if necessary before fetching its value, summary, object description, etc. |
| /// But it will always update itself in the ExecutionContextScope with which it was originally created. |
| |
| /// A brief note on life cycle management for ValueObjects. This is a little tricky because a ValueObject can contain |
| /// various other ValueObjects - the Dynamic Value, its children, the dereference value, etc. Any one of these can be |
| /// handed out as a shared pointer, but for that contained value object to be valid, the root object and potentially other |
| /// of the value objects need to stay around. |
| /// We solve this problem by handing out shared pointers to the Value Object and any of its dependents using a shared |
| /// ClusterManager. This treats each shared pointer handed out for the entire cluster as a reference to the whole |
| /// cluster. The whole cluster will stay around until the last reference is released. |
| /// |
| /// The ValueObject mostly handle this automatically, if a value object is made with a Parent ValueObject, then it adds |
| /// itself to the ClusterManager of the parent. |
| |
| /// It does mean that external to the ValueObjects we should only ever make available ValueObjectSP's, never ValueObjects |
| /// or pointers to them. So all the "Root level" ValueObject derived constructors should be private, and |
| /// should implement a Create function that new's up object and returns a Shared Pointer that it gets from the GetSP() method. |
| /// |
| /// However, if you are making an derived ValueObject that will be contained in a parent value object, you should just |
| /// hold onto a pointer to it internally, and by virtue of passing the parent ValueObject into its constructor, it will |
| /// be added to the ClusterManager for the parent. Then if you ever hand out a Shared Pointer to the contained ValueObject, |
| /// just do so by calling GetSP() on the contained object. |
| |
| class ValueObject : public UserID |
| { |
| public: |
| |
| enum GetExpressionPathFormat |
| { |
| eGetExpressionPathFormatDereferencePointers = 1, |
| eGetExpressionPathFormatHonorPointers |
| }; |
| |
| enum ValueObjectRepresentationStyle |
| { |
| eValueObjectRepresentationStyleValue = 1, |
| eValueObjectRepresentationStyleSummary, |
| eValueObjectRepresentationStyleLanguageSpecific, |
| eValueObjectRepresentationStyleLocation, |
| eValueObjectRepresentationStyleChildrenCount, |
| eValueObjectRepresentationStyleType |
| }; |
| |
| enum ExpressionPathScanEndReason |
| { |
| eExpressionPathScanEndReasonEndOfString = 1, // out of data to parse |
| eExpressionPathScanEndReasonNoSuchChild, // child element not found |
| eExpressionPathScanEndReasonEmptyRangeNotAllowed, // [] only allowed for arrays |
| eExpressionPathScanEndReasonDotInsteadOfArrow, // . used when -> should be used |
| eExpressionPathScanEndReasonArrowInsteadOfDot, // -> used when . should be used |
| eExpressionPathScanEndReasonFragileIVarNotAllowed, // ObjC ivar expansion not allowed |
| eExpressionPathScanEndReasonRangeOperatorNotAllowed, // [] not allowed by options |
| eExpressionPathScanEndReasonRangeOperatorInvalid, // [] not valid on objects other than scalars, pointers or arrays |
| eExpressionPathScanEndReasonArrayRangeOperatorMet, // [] is good for arrays, but I cannot parse it |
| eExpressionPathScanEndReasonBitfieldRangeOperatorMet, // [] is good for bitfields, but I cannot parse after it |
| eExpressionPathScanEndReasonUnexpectedSymbol, // something is malformed in the expression |
| eExpressionPathScanEndReasonTakingAddressFailed, // impossible to apply & operator |
| eExpressionPathScanEndReasonDereferencingFailed, // impossible to apply * operator |
| eExpressionPathScanEndReasonRangeOperatorExpanded, // [] was expanded into a VOList |
| eExpressionPathScanEndReasonSyntheticValueMissing, // getting the synthetic children failed |
| eExpressionPathScanEndReasonUnknown = 0xFFFF |
| }; |
| |
| enum ExpressionPathEndResultType |
| { |
| eExpressionPathEndResultTypePlain = 1, // anything but... |
| eExpressionPathEndResultTypeBitfield, // a bitfield |
| eExpressionPathEndResultTypeBoundedRange, // a range [low-high] |
| eExpressionPathEndResultTypeUnboundedRange, // a range [] |
| eExpressionPathEndResultTypeValueObjectList, // several items in a VOList |
| eExpressionPathEndResultTypeInvalid = 0xFFFF |
| }; |
| |
| enum ExpressionPathAftermath |
| { |
| eExpressionPathAftermathNothing = 1, // just return it |
| eExpressionPathAftermathDereference, // dereference the target |
| eExpressionPathAftermathTakeAddress // take target's address |
| }; |
| |
| enum ClearUserVisibleDataItems |
| { |
| eClearUserVisibleDataItemsNothing = 1u << 0, |
| eClearUserVisibleDataItemsValue = 1u << 1, |
| eClearUserVisibleDataItemsSummary = 1u << 2, |
| eClearUserVisibleDataItemsLocation = 1u << 3, |
| eClearUserVisibleDataItemsDescription = 1u << 4, |
| eClearUserVisibleDataItemsSyntheticChildren = 1u << 5, |
| eClearUserVisibleDataItemsAllStrings = eClearUserVisibleDataItemsValue | eClearUserVisibleDataItemsSummary | eClearUserVisibleDataItemsLocation | eClearUserVisibleDataItemsDescription, |
| eClearUserVisibleDataItemsAll = 0xFFFF |
| }; |
| |
| struct GetValueForExpressionPathOptions |
| { |
| bool m_check_dot_vs_arrow_syntax; |
| bool m_no_fragile_ivar; |
| bool m_allow_bitfields_syntax; |
| bool m_no_synthetic_children; |
| |
| GetValueForExpressionPathOptions(bool dot = false, |
| bool no_ivar = false, |
| bool bitfield = true, |
| bool no_synth = false) : |
| m_check_dot_vs_arrow_syntax(dot), |
| m_no_fragile_ivar(no_ivar), |
| m_allow_bitfields_syntax(bitfield), |
| m_no_synthetic_children(no_synth) |
| { |
| } |
| |
| GetValueForExpressionPathOptions& |
| DoCheckDotVsArrowSyntax() |
| { |
| m_check_dot_vs_arrow_syntax = true; |
| return *this; |
| } |
| |
| GetValueForExpressionPathOptions& |
| DontCheckDotVsArrowSyntax() |
| { |
| m_check_dot_vs_arrow_syntax = false; |
| return *this; |
| } |
| |
| GetValueForExpressionPathOptions& |
| DoAllowFragileIVar() |
| { |
| m_no_fragile_ivar = false; |
| return *this; |
| } |
| |
| GetValueForExpressionPathOptions& |
| DontAllowFragileIVar() |
| { |
| m_no_fragile_ivar = true; |
| return *this; |
| } |
| |
| GetValueForExpressionPathOptions& |
| DoAllowBitfieldSyntax() |
| { |
| m_allow_bitfields_syntax = true; |
| return *this; |
| } |
| |
| GetValueForExpressionPathOptions& |
| DontAllowBitfieldSyntax() |
| { |
| m_allow_bitfields_syntax = false; |
| return *this; |
| } |
| |
| GetValueForExpressionPathOptions& |
| DoAllowSyntheticChildren() |
| { |
| m_no_synthetic_children = false; |
| return *this; |
| } |
| |
| GetValueForExpressionPathOptions& |
| DontAllowSyntheticChildren() |
| { |
| m_no_synthetic_children = true; |
| return *this; |
| } |
| |
| static const GetValueForExpressionPathOptions |
| DefaultOptions() |
| { |
| static GetValueForExpressionPathOptions g_default_options; |
| |
| return g_default_options; |
| } |
| |
| }; |
| |
| struct DumpValueObjectOptions |
| { |
| uint32_t m_max_ptr_depth; |
| uint32_t m_max_depth; |
| bool m_show_types; |
| bool m_show_location; |
| bool m_use_objc; |
| lldb::DynamicValueType m_use_dynamic; |
| bool m_use_synthetic; |
| bool m_scope_already_checked; |
| bool m_flat_output; |
| uint32_t m_omit_summary_depth; |
| bool m_ignore_cap; |
| lldb::Format m_format; |
| lldb::TypeSummaryImplSP m_summary_sp; |
| std::string m_root_valobj_name; |
| |
| DumpValueObjectOptions() : |
| m_max_ptr_depth(0), |
| m_max_depth(UINT32_MAX), |
| m_show_types(false), |
| m_show_location(false), |
| m_use_objc(false), |
| m_use_dynamic(lldb::eNoDynamicValues), |
| m_use_synthetic(true), |
| m_scope_already_checked(false), |
| m_flat_output(false), |
| m_omit_summary_depth(0), |
| m_ignore_cap(false), |
| m_format (lldb::eFormatDefault), |
| m_summary_sp(), |
| m_root_valobj_name() |
| {} |
| |
| static const DumpValueObjectOptions |
| DefaultOptions() |
| { |
| static DumpValueObjectOptions g_default_options; |
| |
| return g_default_options; |
| } |
| |
| DumpValueObjectOptions (const DumpValueObjectOptions& rhs) : |
| m_max_ptr_depth(rhs.m_max_ptr_depth), |
| m_max_depth(rhs.m_max_depth), |
| m_show_types(rhs.m_show_types), |
| m_show_location(rhs.m_show_location), |
| m_use_objc(rhs.m_use_objc), |
| m_use_dynamic(rhs.m_use_dynamic), |
| m_use_synthetic(rhs.m_use_synthetic), |
| m_scope_already_checked(rhs.m_scope_already_checked), |
| m_flat_output(rhs.m_flat_output), |
| m_omit_summary_depth(rhs.m_omit_summary_depth), |
| m_ignore_cap(rhs.m_ignore_cap), |
| m_format(rhs.m_format), |
| m_summary_sp(rhs.m_summary_sp), |
| m_root_valobj_name(rhs.m_root_valobj_name) |
| {} |
| |
| DumpValueObjectOptions& |
| SetMaximumPointerDepth(uint32_t depth = 0) |
| { |
| m_max_ptr_depth = depth; |
| return *this; |
| } |
| |
| DumpValueObjectOptions& |
| SetMaximumDepth(uint32_t depth = 0) |
| { |
| m_max_depth = depth; |
| return *this; |
| } |
| |
| DumpValueObjectOptions& |
| SetShowTypes(bool show = false) |
| { |
| m_show_types = show; |
| return *this; |
| } |
| |
| DumpValueObjectOptions& |
| SetShowLocation(bool show = false) |
| { |
| m_show_location = show; |
| return *this; |
| } |
| |
| DumpValueObjectOptions& |
| SetUseObjectiveC(bool use = false) |
| { |
| m_use_objc = use; |
| return *this; |
| } |
| |
| DumpValueObjectOptions& |
| SetShowSummary(bool show = true) |
| { |
| if (show == false) |
| SetOmitSummaryDepth(UINT32_MAX); |
| else |
| SetOmitSummaryDepth(0); |
| return *this; |
| } |
| |
| DumpValueObjectOptions& |
| SetUseDynamicType(lldb::DynamicValueType dyn = lldb::eNoDynamicValues) |
| { |
| m_use_dynamic = dyn; |
| return *this; |
| } |
| |
| DumpValueObjectOptions& |
| SetUseSyntheticValue(bool use_synthetic = true) |
| { |
| m_use_synthetic = use_synthetic; |
| return *this; |
| } |
| |
| DumpValueObjectOptions& |
| SetScopeChecked(bool check = true) |
| { |
| m_scope_already_checked = check; |
| return *this; |
| } |
| |
| DumpValueObjectOptions& |
| SetFlatOutput(bool flat = false) |
| { |
| m_flat_output = flat; |
| return *this; |
| } |
| |
| DumpValueObjectOptions& |
| SetOmitSummaryDepth(uint32_t depth = 0) |
| { |
| m_omit_summary_depth = depth; |
| return *this; |
| } |
| |
| DumpValueObjectOptions& |
| SetIgnoreCap(bool ignore = false) |
| { |
| m_ignore_cap = ignore; |
| return *this; |
| } |
| |
| DumpValueObjectOptions& |
| SetRawDisplay(bool raw = false) |
| { |
| if (raw) |
| { |
| SetUseSyntheticValue(false); |
| SetOmitSummaryDepth(UINT32_MAX); |
| SetIgnoreCap(true); |
| } |
| else |
| { |
| SetUseSyntheticValue(true); |
| SetOmitSummaryDepth(0); |
| SetIgnoreCap(false); |
| } |
| return *this; |
| } |
| |
| DumpValueObjectOptions& |
| SetFormat (lldb::Format format = lldb::eFormatDefault) |
| { |
| m_format = format; |
| return *this; |
| } |
| |
| DumpValueObjectOptions& |
| SetSummary (lldb::TypeSummaryImplSP summary = lldb::TypeSummaryImplSP()) |
| { |
| m_summary_sp = summary; |
| return *this; |
| } |
| |
| DumpValueObjectOptions& |
| SetRootValueObjectName (const char* name = NULL) |
| { |
| if (name) |
| m_root_valobj_name.assign(name); |
| else |
| m_root_valobj_name.clear(); |
| return *this; |
| } |
| |
| }; |
| |
| class EvaluationPoint |
| { |
| public: |
| |
| EvaluationPoint (); |
| |
| EvaluationPoint (ExecutionContextScope *exe_scope, bool use_selected = false); |
| |
| EvaluationPoint (const EvaluationPoint &rhs); |
| |
| ~EvaluationPoint (); |
| |
| const ExecutionContextRef & |
| GetExecutionContextRef() const |
| { |
| return m_exe_ctx_ref; |
| } |
| |
| // Set the EvaluationPoint to the values in exe_scope, |
| // Return true if the Evaluation Point changed. |
| // Since the ExecutionContextScope is always going to be valid currently, |
| // the Updated Context will also always be valid. |
| |
| // bool |
| // SetContext (ExecutionContextScope *exe_scope); |
| |
| void |
| SetIsConstant () |
| { |
| SetUpdated(); |
| m_mod_id.SetInvalid(); |
| } |
| |
| bool |
| IsConstant () const |
| { |
| return !m_mod_id.IsValid(); |
| } |
| |
| ProcessModID |
| GetModID () const |
| { |
| return m_mod_id; |
| } |
| |
| void |
| SetUpdateID (ProcessModID new_id) |
| { |
| m_mod_id = new_id; |
| } |
| |
| bool |
| IsFirstEvaluation () const |
| { |
| return m_first_update; |
| } |
| |
| void |
| SetNeedsUpdate () |
| { |
| m_needs_update = true; |
| } |
| |
| void |
| SetUpdated (); |
| |
| bool |
| NeedsUpdating() |
| { |
| SyncWithProcessState(); |
| return m_needs_update; |
| } |
| |
| bool |
| IsValid () |
| { |
| if (!m_mod_id.IsValid()) |
| return false; |
| else if (SyncWithProcessState ()) |
| { |
| if (!m_mod_id.IsValid()) |
| return false; |
| } |
| return true; |
| } |
| |
| void |
| SetInvalid () |
| { |
| // Use the stop id to mark us as invalid, leave the thread id and the stack id around for logging and |
| // history purposes. |
| m_mod_id.SetInvalid(); |
| |
| // Can't update an invalid state. |
| m_needs_update = false; |
| |
| } |
| |
| private: |
| bool |
| SyncWithProcessState (); |
| |
| ProcessModID m_mod_id; // This is the stop id when this ValueObject was last evaluated. |
| ExecutionContextRef m_exe_ctx_ref; |
| bool m_needs_update; |
| bool m_first_update; |
| }; |
| |
| const EvaluationPoint & |
| GetUpdatePoint () const |
| { |
| return m_update_point; |
| } |
| |
| EvaluationPoint & |
| GetUpdatePoint () |
| { |
| return m_update_point; |
| } |
| |
| const ExecutionContextRef & |
| GetExecutionContextRef() const |
| { |
| return m_update_point.GetExecutionContextRef(); |
| } |
| |
| lldb::TargetSP |
| GetTargetSP() const |
| { |
| return m_update_point.GetExecutionContextRef().GetTargetSP(); |
| } |
| |
| lldb::ProcessSP |
| GetProcessSP() const |
| { |
| return m_update_point.GetExecutionContextRef().GetProcessSP(); |
| } |
| |
| lldb::ThreadSP |
| GetThreadSP() const |
| { |
| return m_update_point.GetExecutionContextRef().GetThreadSP(); |
| } |
| |
| lldb::StackFrameSP |
| GetFrameSP() const |
| { |
| return m_update_point.GetExecutionContextRef().GetFrameSP(); |
| } |
| |
| void |
| SetNeedsUpdate (); |
| |
| virtual ~ValueObject(); |
| |
| clang::ASTContext * |
| GetClangAST (); |
| |
| lldb::clang_type_t |
| GetClangType (); |
| |
| //------------------------------------------------------------------ |
| // Sublasses must implement the functions below. |
| //------------------------------------------------------------------ |
| virtual size_t |
| GetByteSize() = 0; |
| |
| virtual lldb::ValueType |
| GetValueType() const = 0; |
| |
| //------------------------------------------------------------------ |
| // Sublasses can implement the functions below. |
| //------------------------------------------------------------------ |
| virtual ConstString |
| GetTypeName(); |
| |
| virtual ConstString |
| GetQualifiedTypeName(); |
| |
| virtual lldb::LanguageType |
| GetObjectRuntimeLanguage(); |
| |
| virtual bool |
| IsPointerType (); |
| |
| virtual bool |
| IsArrayType (); |
| |
| virtual bool |
| IsScalarType (); |
| |
| virtual bool |
| IsPointerOrReferenceType (); |
| |
| virtual bool |
| IsPossibleCPlusPlusDynamicType (); |
| |
| virtual bool |
| IsPossibleDynamicType (); |
| |
| virtual bool |
| IsBaseClass () |
| { |
| return false; |
| } |
| |
| virtual bool |
| IsDereferenceOfParent () |
| { |
| return false; |
| } |
| |
| bool |
| IsIntegerType (bool &is_signed); |
| |
| virtual bool |
| GetBaseClassPath (Stream &s); |
| |
| virtual void |
| GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat = eGetExpressionPathFormatDereferencePointers); |
| |
| lldb::ValueObjectSP |
| GetValueForExpressionPath(const char* expression, |
| const char** first_unparsed = NULL, |
| ExpressionPathScanEndReason* reason_to_stop = NULL, |
| ExpressionPathEndResultType* final_value_type = NULL, |
| const GetValueForExpressionPathOptions& options = GetValueForExpressionPathOptions::DefaultOptions(), |
| ExpressionPathAftermath* final_task_on_target = NULL); |
| |
| int |
| GetValuesForExpressionPath(const char* expression, |
| lldb::ValueObjectListSP& list, |
| const char** first_unparsed = NULL, |
| ExpressionPathScanEndReason* reason_to_stop = NULL, |
| ExpressionPathEndResultType* final_value_type = NULL, |
| const GetValueForExpressionPathOptions& options = GetValueForExpressionPathOptions::DefaultOptions(), |
| ExpressionPathAftermath* final_task_on_target = NULL); |
| |
| virtual bool |
| IsInScope () |
| { |
| return true; |
| } |
| |
| virtual off_t |
| GetByteOffset() |
| { |
| return 0; |
| } |
| |
| virtual uint32_t |
| GetBitfieldBitSize() |
| { |
| return 0; |
| } |
| |
| virtual uint32_t |
| GetBitfieldBitOffset() |
| { |
| return 0; |
| } |
| |
| virtual bool |
| IsArrayItemForPointer() |
| { |
| return m_is_array_item_for_pointer; |
| } |
| |
| virtual bool |
| SetClangAST (clang::ASTContext *ast) |
| { |
| return false; |
| } |
| |
| virtual const char * |
| GetValueAsCString (); |
| |
| virtual bool |
| GetValueAsCString (lldb::Format format, |
| std::string& destination); |
| |
| virtual uint64_t |
| GetValueAsUnsigned (uint64_t fail_value); |
| |
| virtual bool |
| SetValueFromCString (const char *value_str); |
| |
| // Return the module associated with this value object in case the |
| // value is from an executable file and might have its data in |
| // sections of the file. This can be used for variables. |
| virtual lldb::ModuleSP |
| GetModule() |
| { |
| if (m_parent) |
| return m_parent->GetModule(); |
| return lldb::ModuleSP(); |
| } |
| |
| virtual bool |
| GetDeclaration (Declaration &decl); |
| |
| //------------------------------------------------------------------ |
| // The functions below should NOT be modified by sublasses |
| //------------------------------------------------------------------ |
| const Error & |
| GetError(); |
| |
| const ConstString & |
| GetName() const; |
| |
| virtual lldb::ValueObjectSP |
| GetChildAtIndex (uint32_t idx, bool can_create); |
| |
| virtual lldb::ValueObjectSP |
| GetChildMemberWithName (const ConstString &name, bool can_create); |
| |
| virtual uint32_t |
| GetIndexOfChildWithName (const ConstString &name); |
| |
| uint32_t |
| GetNumChildren (); |
| |
| const Value & |
| GetValue() const; |
| |
| Value & |
| GetValue(); |
| |
| virtual bool |
| ResolveValue (Scalar &scalar); |
| |
| const char * |
| GetLocationAsCString (); |
| |
| const char * |
| GetSummaryAsCString (); |
| |
| bool |
| GetSummaryAsCString (TypeSummaryImpl* summary_ptr, |
| std::string& destination); |
| |
| const char * |
| GetObjectDescription (); |
| |
| bool |
| HasSpecialPrintableRepresentation (ValueObjectRepresentationStyle val_obj_display, |
| lldb::Format custom_format); |
| |
| enum PrintableRepresentationSpecialCases |
| { |
| ePrintableRepresentationSpecialCasesDisable = 0, |
| ePrintableRepresentationSpecialCasesAllow = 1, |
| ePrintableRepresentationSpecialCasesOnly = 3 |
| }; |
| |
| bool |
| DumpPrintableRepresentation (Stream& s, |
| ValueObjectRepresentationStyle val_obj_display = eValueObjectRepresentationStyleSummary, |
| lldb::Format custom_format = lldb::eFormatInvalid, |
| PrintableRepresentationSpecialCases special = ePrintableRepresentationSpecialCasesAllow); |
| bool |
| GetValueIsValid () const; |
| |
| bool |
| GetValueDidChange (); |
| |
| bool |
| UpdateValueIfNeeded (bool update_format = true); |
| |
| bool |
| UpdateValueIfNeeded (lldb::DynamicValueType use_dynamic, bool update_format = true); |
| |
| bool |
| UpdateFormatsIfNeeded(lldb::DynamicValueType use_dynamic = lldb::eNoDynamicValues); |
| |
| lldb::ValueObjectSP |
| GetSP () |
| { |
| return m_manager->GetSharedPointer(this); |
| } |
| |
| void |
| SetName (const ConstString &name); |
| |
| virtual lldb::addr_t |
| GetAddressOf (bool scalar_is_load_address = true, |
| AddressType *address_type = NULL); |
| |
| lldb::addr_t |
| GetPointerValue (AddressType *address_type = NULL); |
| |
| lldb::ValueObjectSP |
| GetSyntheticChild (const ConstString &key) const; |
| |
| lldb::ValueObjectSP |
| GetSyntheticArrayMember (int32_t index, bool can_create); |
| |
| lldb::ValueObjectSP |
| GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create); |
| |
| lldb::ValueObjectSP |
| GetSyntheticArrayMemberFromArray (int32_t index, bool can_create); |
| |
| lldb::ValueObjectSP |
| GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_create); |
| |
| lldb::ValueObjectSP |
| GetSyntheticArrayRangeChild (uint32_t from, uint32_t to, bool can_create); |
| |
| lldb::ValueObjectSP |
| GetSyntheticExpressionPathChild(const char* expression, bool can_create); |
| |
| virtual lldb::ValueObjectSP |
| GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create); |
| |
| lldb::ValueObjectSP |
| GetDynamicValue (lldb::DynamicValueType valueType); |
| |
| virtual lldb::ValueObjectSP |
| GetStaticValue (); |
| |
| lldb::ValueObjectSP |
| GetSyntheticValue (bool use_synthetic = true); |
| |
| virtual bool |
| HasSyntheticValue(); |
| |
| virtual bool |
| IsSynthetic() { return false; } |
| |
| virtual lldb::ValueObjectSP |
| CreateConstantValue (const ConstString &name); |
| |
| virtual lldb::ValueObjectSP |
| Dereference (Error &error); |
| |
| virtual lldb::ValueObjectSP |
| AddressOf (Error &error); |
| |
| virtual lldb::addr_t |
| GetLiveAddress() |
| { |
| return LLDB_INVALID_ADDRESS; |
| } |
| |
| virtual void |
| SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS, |
| AddressType address_type = eAddressTypeLoad) |
| { |
| } |
| |
| virtual lldb::ValueObjectSP |
| Cast (const ClangASTType &clang_ast_type); |
| |
| virtual lldb::ValueObjectSP |
| CastPointerType (const char *name, |
| ClangASTType &ast_type); |
| |
| virtual lldb::ValueObjectSP |
| CastPointerType (const char *name, |
| lldb::TypeSP &type_sp); |
| |
| // The backing bits of this value object were updated, clear any |
| // descriptive string, so we know we have to refetch them |
| virtual void |
| ValueUpdated () |
| { |
| ClearUserVisibleData(eClearUserVisibleDataItemsValue | |
| eClearUserVisibleDataItemsSummary | |
| eClearUserVisibleDataItemsDescription); |
| } |
| |
| virtual bool |
| IsDynamic () |
| { |
| return false; |
| } |
| |
| virtual SymbolContextScope * |
| GetSymbolContextScope(); |
| |
| static void |
| DumpValueObject (Stream &s, |
| ValueObject *valobj); |
| static void |
| DumpValueObject (Stream &s, |
| ValueObject *valobj, |
| const DumpValueObjectOptions& options); |
| |
| static void |
| LogValueObject (Log *log, |
| ValueObject *valobj); |
| |
| static void |
| LogValueObject (Log *log, |
| ValueObject *valobj, |
| const DumpValueObjectOptions& options); |
| |
| |
| // returns true if this is a char* or a char[] |
| // if it is a char* and check_pointer is true, |
| // it also checks that the pointer is valid |
| bool |
| IsCStringContainer (bool check_pointer = false); |
| |
| void |
| ReadPointedString (Stream& s, |
| Error& error, |
| uint32_t max_length = 0, |
| bool honor_array = true, |
| lldb::Format item_format = lldb::eFormatCharArray); |
| |
| virtual size_t |
| GetPointeeData (DataExtractor& data, |
| uint32_t item_idx = 0, |
| uint32_t item_count = 1); |
| |
| virtual size_t |
| GetData (DataExtractor& data); |
| |
| bool |
| GetIsConstant () const |
| { |
| return m_update_point.IsConstant(); |
| } |
| |
| void |
| SetIsConstant () |
| { |
| m_update_point.SetIsConstant(); |
| } |
| |
| lldb::Format |
| GetFormat () const |
| { |
| if (m_parent && m_format == lldb::eFormatDefault) |
| return m_parent->GetFormat(); |
| return m_format; |
| } |
| |
| void |
| SetFormat (lldb::Format format) |
| { |
| if (format != m_format) |
| ClearUserVisibleData(eClearUserVisibleDataItemsValue); |
| m_format = format; |
| } |
| |
| lldb::TypeSummaryImplSP |
| GetSummaryFormat() |
| { |
| UpdateFormatsIfNeeded(m_last_format_mgr_dynamic); |
| return m_type_summary_sp; |
| } |
| |
| void |
| SetSummaryFormat(lldb::TypeSummaryImplSP format) |
| { |
| m_type_summary_sp = format; |
| ClearUserVisibleData(eClearUserVisibleDataItemsSummary); |
| } |
| |
| void |
| SetValueFormat(lldb::TypeFormatImplSP format) |
| { |
| m_type_format_sp = format; |
| ClearUserVisibleData(eClearUserVisibleDataItemsValue); |
| } |
| |
| lldb::TypeFormatImplSP |
| GetValueFormat() |
| { |
| UpdateFormatsIfNeeded(m_last_format_mgr_dynamic); |
| return m_type_format_sp; |
| } |
| |
| void |
| SetSyntheticChildren(const lldb::SyntheticChildrenSP &synth_sp) |
| { |
| if (synth_sp.get() == m_synthetic_children_sp.get()) |
| return; |
| ClearUserVisibleData(eClearUserVisibleDataItemsSyntheticChildren); |
| m_synthetic_children_sp = synth_sp; |
| } |
| |
| lldb::SyntheticChildrenSP |
| GetSyntheticChildren() |
| { |
| UpdateFormatsIfNeeded(m_last_format_mgr_dynamic); |
| return m_synthetic_children_sp; |
| } |
| |
| // Use GetParent for display purposes, but if you want to tell the parent to update itself |
| // then use m_parent. The ValueObjectDynamicValue's parent is not the correct parent for |
| // displaying, they are really siblings, so for display it needs to route through to its grandparent. |
| virtual ValueObject * |
| GetParent() |
| { |
| return m_parent; |
| } |
| |
| virtual const ValueObject * |
| GetParent() const |
| { |
| return m_parent; |
| } |
| |
| ValueObject * |
| GetNonBaseClassParent(); |
| |
| void |
| SetAddressTypeOfChildren(AddressType at) |
| { |
| m_address_type_of_ptr_or_ref_children = at; |
| } |
| |
| AddressType |
| GetAddressTypeOfChildren() |
| { |
| if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid) |
| { |
| if (m_parent) |
| return m_parent->GetAddressTypeOfChildren(); |
| } |
| return m_address_type_of_ptr_or_ref_children; |
| } |
| |
| protected: |
| typedef ClusterManager<ValueObject> ValueObjectManager; |
| |
| class ChildrenManager |
| { |
| public: |
| ChildrenManager() : |
| m_mutex(Mutex::eMutexTypeRecursive), |
| m_children(), |
| m_children_count(0) |
| {} |
| |
| bool |
| HasChildAtIndex (uint32_t idx) |
| { |
| Mutex::Locker(m_mutex); |
| ChildrenIterator iter = m_children.find(idx); |
| ChildrenIterator end = m_children.end(); |
| return (iter != end); |
| } |
| |
| ValueObject* |
| GetChildAtIndex (uint32_t idx) |
| { |
| Mutex::Locker(m_mutex); |
| ChildrenIterator iter = m_children.find(idx); |
| ChildrenIterator end = m_children.end(); |
| if (iter == end) |
| return NULL; |
| else |
| return iter->second; |
| } |
| |
| void |
| SetChildAtIndex (uint32_t idx, ValueObject* valobj) |
| { |
| ChildrenPair pair(idx,valobj); // we do not need to be mutex-protected to make a pair |
| Mutex::Locker(m_mutex); |
| m_children.insert(pair); |
| } |
| |
| void |
| SetChildrenCount (uint32_t count) |
| { |
| m_children_count = count; |
| } |
| |
| uint32_t |
| GetChildrenCount () |
| { |
| return m_children_count; |
| } |
| |
| void |
| Clear() |
| { |
| m_children_count = 0; |
| Mutex::Locker(m_mutex); |
| m_children.clear(); |
| } |
| |
| private: |
| typedef std::map<uint32_t, ValueObject*> ChildrenMap; |
| typedef ChildrenMap::iterator ChildrenIterator; |
| typedef ChildrenMap::value_type ChildrenPair; |
| Mutex m_mutex; |
| ChildrenMap m_children; |
| uint32_t m_children_count; |
| }; |
| |
| //------------------------------------------------------------------ |
| // Classes that inherit from ValueObject can see and modify these |
| //------------------------------------------------------------------ |
| ValueObject * m_parent; // The parent value object, or NULL if this has no parent |
| EvaluationPoint m_update_point; // Stores both the stop id and the full context at which this value was last |
| // updated. When we are asked to update the value object, we check whether |
| // the context & stop id are the same before updating. |
| ConstString m_name; // The name of this object |
| DataExtractor m_data; // A data extractor that can be used to extract the value. |
| Value m_value; |
| Error m_error; // An error object that can describe any errors that occur when updating values. |
| std::string m_value_str; // Cached value string that will get cleared if/when the value is updated. |
| std::string m_old_value_str;// Cached old value string from the last time the value was gotten |
| std::string m_location_str; // Cached location string that will get cleared if/when the value is updated. |
| std::string m_summary_str; // Cached summary string that will get cleared if/when the value is updated. |
| std::string m_object_desc_str; // Cached result of the "object printer". This differs from the summary |
| // in that the summary is consed up by us, the object_desc_string is builtin. |
| |
| ClangASTType m_override_type;// If the type of the value object should be overridden, the type to impose. |
| |
| ValueObjectManager *m_manager; // This object is managed by the root object (any ValueObject that gets created |
| // without a parent.) The manager gets passed through all the generations of |
| // dependent objects, and will keep the whole cluster of objects alive as long |
| // as a shared pointer to any of them has been handed out. Shared pointers to |
| // value objects must always be made with the GetSP method. |
| |
| ChildrenManager m_children; |
| std::map<ConstString, ValueObject *> m_synthetic_children; |
| |
| ValueObject* m_dynamic_value; |
| ValueObject* m_synthetic_value; |
| ValueObject* m_deref_valobj; |
| |
| lldb::ValueObjectSP m_addr_of_valobj_sp; // We have to hold onto a shared pointer to this one because it is created |
| // as an independent ValueObjectConstResult, which isn't managed by us. |
| |
| lldb::Format m_format; |
| uint32_t m_last_format_mgr_revision; |
| lldb::DynamicValueType m_last_format_mgr_dynamic; |
| lldb::TypeSummaryImplSP m_type_summary_sp; |
| lldb::TypeFormatImplSP m_type_format_sp; |
| lldb::SyntheticChildrenSP m_synthetic_children_sp; |
| ProcessModID m_user_id_of_forced_summary; |
| AddressType m_address_type_of_ptr_or_ref_children; |
| |
| bool m_value_is_valid:1, |
| m_value_did_change:1, |
| m_children_count_valid:1, |
| m_old_value_valid:1, |
| m_is_deref_of_parent:1, |
| m_is_array_item_for_pointer:1, |
| m_is_bitfield_for_scalar:1, |
| m_is_expression_path_child:1, |
| m_is_child_at_offset:1, |
| m_is_getting_summary:1, |
| m_did_calculate_complete_objc_class_type:1; |
| |
| friend class ClangExpressionDeclMap; // For GetValue |
| friend class ClangExpressionVariable; // For SetName |
| friend class Target; // For SetName |
| friend class ValueObjectConstResultImpl; |
| |
| //------------------------------------------------------------------ |
| // Constructors and Destructors |
| //------------------------------------------------------------------ |
| |
| // Use the no-argument constructor to make a constant variable object (with no ExecutionContextScope.) |
| |
| ValueObject(); |
| |
| // Use this constructor to create a "root variable object". The ValueObject will be locked to this context |
| // through-out its lifespan. |
| |
| ValueObject (ExecutionContextScope *exe_scope, |
| AddressType child_ptr_or_ref_addr_type = eAddressTypeLoad); |
| |
| // Use this constructor to create a ValueObject owned by another ValueObject. It will inherit the ExecutionContext |
| // of its parent. |
| |
| ValueObject (ValueObject &parent); |
| |
| ValueObjectManager * |
| GetManager() |
| { |
| return m_manager; |
| } |
| |
| virtual bool |
| UpdateValue () = 0; |
| |
| virtual void |
| CalculateDynamicValue (lldb::DynamicValueType use_dynamic); |
| |
| virtual void |
| CalculateSyntheticValue (bool use_synthetic = true); |
| |
| // Should only be called by ValueObject::GetChildAtIndex() |
| // Returns a ValueObject managed by this ValueObject's manager. |
| virtual ValueObject * |
| CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index); |
| |
| // Should only be called by ValueObject::GetNumChildren() |
| virtual uint32_t |
| CalculateNumChildren() = 0; |
| |
| void |
| SetNumChildren (uint32_t num_children); |
| |
| void |
| SetValueDidChange (bool value_changed); |
| |
| void |
| SetValueIsValid (bool valid); |
| |
| void |
| ClearUserVisibleData(uint32_t items = ValueObject::eClearUserVisibleDataItemsAllStrings); |
| |
| void |
| AddSyntheticChild (const ConstString &key, |
| ValueObject *valobj); |
| |
| DataExtractor & |
| GetDataExtractor (); |
| |
| //------------------------------------------------------------------ |
| // Sublasses must implement the functions below. |
| //------------------------------------------------------------------ |
| |
| virtual clang::ASTContext * |
| GetClangASTImpl () = 0; |
| |
| virtual lldb::clang_type_t |
| GetClangTypeImpl () = 0; |
| |
| private: |
| //------------------------------------------------------------------ |
| // For ValueObject only |
| //------------------------------------------------------------------ |
| |
| virtual ClangASTType |
| MaybeCalculateCompleteType (); |
| |
| lldb::ValueObjectSP |
| GetValueForExpressionPath_Impl(const char* expression_cstr, |
| const char** first_unparsed, |
| ExpressionPathScanEndReason* reason_to_stop, |
| ExpressionPathEndResultType* final_value_type, |
| const GetValueForExpressionPathOptions& options, |
| ExpressionPathAftermath* final_task_on_target); |
| |
| // this method will ONLY expand [] expressions into a VOList and return |
| // the number of elements it added to the VOList |
| // it will NOT loop through expanding the follow-up of the expression_cstr |
| // for all objects in the list |
| int |
| ExpandArraySliceExpression(const char* expression_cstr, |
| const char** first_unparsed, |
| lldb::ValueObjectSP root, |
| lldb::ValueObjectListSP& list, |
| ExpressionPathScanEndReason* reason_to_stop, |
| ExpressionPathEndResultType* final_value_type, |
| const GetValueForExpressionPathOptions& options, |
| ExpressionPathAftermath* final_task_on_target); |
| |
| |
| DISALLOW_COPY_AND_ASSIGN (ValueObject); |
| |
| }; |
| |
| } // namespace lldb_private |
| |
| #endif // liblldb_ValueObject_h_ |