#ifndef liblldb_ValueObject_h_
#define liblldb_ValueObject_h_
#include <map>
#include <vector>
#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/PriorityPointerPair.h"
#include "lldb/Utility/SharedCluster.h"
namespace lldb_private {
class ValueObject : public UserID
{
public:
enum GetExpressionPathFormat
{
eDereferencePointers = 1,
eHonorPointers
};
enum ValueObjectRepresentationStyle
{
eDisplayValue = 1,
eDisplaySummary,
eDisplayLanguageSpecific,
eDisplayLocation,
eDisplayChildrenCount,
};
enum ExpressionPathScanEndReason
{
eEndOfString = 1, eNoSuchChild, eEmptyRangeNotAllowed, eDotInsteadOfArrow, eArrowInsteadOfDot, eFragileIVarNotAllowed, eRangeOperatorNotAllowed, eRangeOperatorInvalid, eArrayRangeOperatorMet, eBitfieldRangeOperatorMet, eUnexpectedSymbol, eTakingAddressFailed, eDereferencingFailed, eRangeOperatorExpanded, eUnknown = 0xFFFF
};
enum ExpressionPathEndResultType
{
ePlain = 1, eBitfield, eBoundedRange, eUnboundedRange, eValueObjectList, eInvalid = 0xFFFF
};
enum ExpressionPathAftermath
{
eNothing = 1, eDereference, eTakeAddress };
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_ptr_depth;
uint32_t m_max_depth;
bool m_show_types;
bool m_show_location;
bool m_use_objc;
lldb::DynamicValueType m_use_dynamic;
lldb::SyntheticValueType m_use_synthetic;
bool m_scope_already_checked;
bool m_flat_output;
uint32_t m_omit_summary_depth;
bool m_ignore_cap;
DumpValueObjectOptions() :
m_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(lldb::eUseSyntheticFilter),
m_scope_already_checked(false),
m_flat_output(false),
m_omit_summary_depth(0),
m_ignore_cap(false)
{}
static const DumpValueObjectOptions
DefaultOptions()
{
static DumpValueObjectOptions g_default_options;
return g_default_options;
}
DumpValueObjectOptions&
SetPointerDepth(uint32_t depth = 0)
{
m_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&
SetUseDynamicType(lldb::DynamicValueType dyn = lldb::eNoDynamicValues)
{
m_use_dynamic = dyn;
return *this;
}
DumpValueObjectOptions&
SetUseSyntheticValue(lldb::SyntheticValueType syn = lldb::eUseSyntheticFilter)
{
m_use_synthetic = syn;
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(lldb::eNoSyntheticFilter);
SetOmitSummaryDepth(UINT32_MAX);
SetIgnoreCap(true);
}
else
{
SetUseSyntheticValue(lldb::eUseSyntheticFilter);
SetOmitSummaryDepth(0);
SetIgnoreCap(false);
}
return *this;
}
};
class EvaluationPoint
{
public:
EvaluationPoint ();
EvaluationPoint (ExecutionContextScope *exe_scope, bool use_selected = false);
EvaluationPoint (const EvaluationPoint &rhs);
~EvaluationPoint ();
ExecutionContextScope *
GetExecutionContextScope ();
lldb::TargetSP
GetTargetSP () const
{
return m_target_sp;
}
lldb::ProcessSP
GetProcessSP () const
{
return m_process_sp;
}
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 ()
{
m_mod_id.SetInvalid();
m_needs_update = false;
}
private:
bool
SyncWithProcessState ();
ExecutionContextScope *m_exe_scope; bool m_needs_update;
bool m_first_update;
lldb::TargetSP m_target_sp;
lldb::ProcessSP m_process_sp;
lldb::user_id_t m_thread_id;
StackID m_stack_id;
ProcessModID m_mod_id; };
const EvaluationPoint &
GetUpdatePoint () const
{
return m_update_point;
}
EvaluationPoint &
GetUpdatePoint ()
{
return m_update_point;
}
ExecutionContextScope *
GetExecutionContextScope ()
{
return m_update_point.GetExecutionContextScope();
}
void
SetNeedsUpdate ();
virtual ~ValueObject();
virtual size_t
GetByteSize() = 0;
virtual clang::ASTContext *
GetClangAST () = 0;
virtual lldb::clang_type_t
GetClangType () = 0;
virtual lldb::ValueType
GetValueType() const = 0;
virtual ConstString
GetTypeName() = 0;
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 = eDereferencePointers);
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 unsigned long long
GetValueAsUnsigned();
virtual bool
SetValueFromCString (const char *value_str);
virtual Module *
GetModule()
{
if (m_parent)
return m_parent->GetModule();
return NULL;
}
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 ();
const char *
GetObjectDescription ();
bool
GetPrintableRepresentation(Stream& s,
ValueObjectRepresentationStyle val_obj_display = eDisplaySummary,
lldb::Format custom_format = lldb::eFormatInvalid);
bool
DumpPrintableRepresentation(Stream& s,
ValueObjectRepresentationStyle val_obj_display = eDisplaySummary,
lldb::Format custom_format = lldb::eFormatInvalid);
bool
GetValueIsValid () const;
bool
GetValueDidChange ();
bool
UpdateValueIfNeeded (bool update_format = true);
bool
UpdateValueIfNeeded (lldb::DynamicValueType use_dynamic, bool update_format = true);
void
UpdateFormatsIfNeeded(lldb::DynamicValueType use_dynamic = lldb::eNoDynamicValues);
DataExtractor &
GetDataExtractor ();
lldb::ValueObjectSP
GetSP ()
{
return m_manager->GetSharedPointer(this);
}
protected:
void
AddSyntheticChild (const ConstString &key,
ValueObject *valobj);
public:
lldb::ValueObjectSP
GetSyntheticChild (const ConstString &key) const;
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
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);
lldb::ValueObjectSP
GetSyntheticValue (lldb::SyntheticValueType use_synthetic);
virtual bool
HasSyntheticValue();
virtual lldb::ValueObjectSP
CreateConstantValue (const ConstString &name);
virtual lldb::ValueObjectSP
Dereference (Error &error);
virtual lldb::ValueObjectSP
AddressOf (Error &error);
virtual lldb::ValueObjectSP
CastPointerType (const char *name,
ClangASTType &ast_type);
virtual lldb::ValueObjectSP
CastPointerType (const char *name,
lldb::TypeSP &type_sp);
virtual void
ValueUpdated ()
{
m_value_str.clear();
m_summary_str.clear();
m_object_desc_str.clear();
}
virtual bool
IsDynamic ()
{
return false;
}
static void
DumpValueObject (Stream &s,
ValueObject *valobj)
{
if (!valobj)
return;
ValueObject::DumpValueObject(s,
valobj,
DumpValueObjectOptions::DefaultOptions());
}
static void
DumpValueObject (Stream &s,
ValueObject *valobj,
const char *root_valobj_name)
{
if (!valobj)
return;
ValueObject::DumpValueObject(s,
valobj,
root_valobj_name,
DumpValueObjectOptions::DefaultOptions());
}
static void
DumpValueObject (Stream &s,
ValueObject *valobj,
const DumpValueObjectOptions& options)
{
if (!valobj)
return;
ValueObject::DumpValueObject(s,
valobj,
valobj->GetName().AsCString(),
options.m_ptr_depth,
0,
options.m_max_depth,
options.m_show_types,
options.m_show_location,
options.m_use_objc,
options.m_use_dynamic,
options.m_use_synthetic,
options.m_scope_already_checked,
options.m_flat_output,
options.m_omit_summary_depth,
options.m_ignore_cap);
}
static void
DumpValueObject (Stream &s,
ValueObject *valobj,
const char *root_valobj_name,
const DumpValueObjectOptions& options)
{
if (!valobj)
return;
ValueObject::DumpValueObject(s,
valobj,
root_valobj_name,
options.m_ptr_depth,
0,
options.m_max_depth,
options.m_show_types,
options.m_show_location,
options.m_use_objc,
options.m_use_dynamic,
options.m_use_synthetic,
options.m_scope_already_checked,
options.m_flat_output,
options.m_omit_summary_depth,
options.m_ignore_cap);
}
static void
DumpValueObject (Stream &s,
ValueObject *valobj,
const char *root_valobj_name,
uint32_t ptr_depth,
uint32_t curr_depth,
uint32_t max_depth,
bool show_types,
bool show_location,
bool use_objc,
lldb::DynamicValueType use_dynamic,
bool use_synthetic,
bool scope_already_checked,
bool flat_output,
uint32_t omit_summary_depth,
bool ignore_cap);
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);
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
SetIsExpressionResult(bool expr)
{
m_is_expression_result = expr;
}
bool
GetIsExpressionResult()
{
return m_is_expression_result;
}
void
SetFormat (lldb::Format format)
{
if (format != m_format)
m_value_str.clear();
m_format = format;
}
void
SetCustomSummaryFormat(lldb::SummaryFormatSP format)
{
m_forced_summary_format = format;
m_user_id_of_forced_summary = m_update_point.GetModID();
m_summary_str.clear();
}
lldb::SummaryFormatSP
GetCustomSummaryFormat()
{
return m_forced_summary_format;
}
void
ClearCustomSummaryFormat()
{
m_forced_summary_format.reset();
m_summary_str.clear();
}
bool
HasCustomSummaryFormat()
{
return (m_forced_summary_format.get());
}
lldb::SummaryFormatSP
GetSummaryFormat()
{
UpdateFormatsIfNeeded(m_last_format_mgr_dynamic);
if (HasCustomSummaryFormat())
return m_forced_summary_format;
return m_last_summary_format;
}
virtual ValueObject *
GetParent()
{
return m_parent;
}
virtual const ValueObject *
GetParent() const
{
return m_parent;
}
ValueObject *
GetNonBaseClassParent();
void
SetPointersPointToLoadAddrs (bool b)
{
m_pointers_point_to_load_addrs = b;
}
protected:
typedef ClusterManager<ValueObject> ValueObjectManager;
ValueObject * m_parent; EvaluationPoint m_update_point; ConstString m_name; DataExtractor m_data; Value m_value;
Error m_error; std::string m_value_str; std::string m_old_value_str; std::string m_location_str; std::string m_summary_str; std::string m_object_desc_str;
ValueObjectManager *m_manager;
std::vector<ValueObject *> m_children;
std::map<ConstString, ValueObject *> m_synthetic_children;
ValueObject *m_dynamic_value;
ValueObject *m_synthetic_value;
lldb::ValueObjectSP m_addr_of_valobj_sp; ValueObject *m_deref_valobj;
lldb::Format m_format;
uint32_t m_last_format_mgr_revision;
lldb::DynamicValueType m_last_format_mgr_dynamic;
lldb::SummaryFormatSP m_last_summary_format;
lldb::SummaryFormatSP m_forced_summary_format;
lldb::ValueFormatSP m_last_value_format;
lldb::SyntheticChildrenSP m_last_synthetic_filter;
ProcessModID m_user_id_of_forced_summary;
bool m_value_is_valid:1,
m_value_did_change:1,
m_children_count_valid:1,
m_old_value_valid:1,
m_pointers_point_to_load_addrs: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_expression_result:1;
uint32_t m_dump_printable_counter;
friend class ClangExpressionDeclMap; friend class ClangExpressionVariable; friend class Target;
ValueObject();
ValueObject (ExecutionContextScope *exe_scope);
ValueObject (ValueObject &parent);
ValueObjectManager *
GetManager()
{
return m_manager;
}
virtual bool
UpdateValue () = 0;
virtual void
CalculateDynamicValue (lldb::DynamicValueType use_dynamic);
virtual void
CalculateSyntheticValue (lldb::SyntheticValueType use_synthetic);
virtual ValueObject *
CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index);
virtual uint32_t
CalculateNumChildren() = 0;
void
SetNumChildren (uint32_t num_children);
void
SetValueDidChange (bool value_changed);
void
SetValueIsValid (bool valid);
void
ClearUserVisibleData();
public:
void
SetName (const ConstString &name);
lldb::addr_t
GetPointerValue (AddressType &address_type,
bool scalar_is_load_address);
lldb::addr_t
GetAddressOf (AddressType &address_type,
bool scalar_is_load_address);
private:
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);
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);
};
}
#endif // liblldb_ValueObject_h_